68 lines
1.5 KiB
Python
68 lines
1.5 KiB
Python
import logging
|
|
|
|
from funcy import rcompose
|
|
|
|
from pyinfra.parser.blob_parser import ParsingError
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class Either:
|
|
def __init__(self, item):
|
|
self.item = item
|
|
|
|
def bind(self):
|
|
return self.item
|
|
|
|
|
|
class Left(Either):
|
|
pass
|
|
|
|
|
|
class Right(Either):
|
|
pass
|
|
|
|
|
|
class EitherParserWrapper:
|
|
def __init__(self, parser):
|
|
self.parser = parser
|
|
|
|
def __log(self, result):
|
|
if isinstance(result, Right):
|
|
logger.debug(f"{self.parser.__class__.__name__} succeeded or forwarded on {result.bind()}")
|
|
else:
|
|
logger.debug(f"{self.parser.__class__.__name__} failed on {result.bind()}")
|
|
return result
|
|
|
|
def parse(self, item: Either):
|
|
if isinstance(item, Left):
|
|
|
|
try:
|
|
return Right(self.parser(item.bind()))
|
|
except ParsingError:
|
|
return item
|
|
|
|
elif isinstance(item, Right):
|
|
return item
|
|
|
|
else:
|
|
return self.parse(Left(item))
|
|
|
|
def __call__(self, item):
|
|
return self.__log(self.parse(item))
|
|
|
|
|
|
class EitherParserComposer:
|
|
def __init__(self, *parsers):
|
|
self.parser = rcompose(*map(EitherParserWrapper, parsers))
|
|
|
|
def parse(self, item):
|
|
result = self.parser(item)
|
|
if isinstance(result, Right):
|
|
return result.bind()
|
|
else:
|
|
raise ParsingError("All parsers failed.")
|
|
|
|
def __call__(self, item):
|
|
return self.parse(item)
|