added parsers and parser composer for clean handling of storage blobs in the context of interpreting downloaded blobs

This commit is contained in:
Matthias Bisping 2022-06-03 16:13:15 +02:00
parent ea2d3223fb
commit 6e5af4092e
9 changed files with 135 additions and 0 deletions

View File

View File

@ -0,0 +1,14 @@
import abc
class ParsingError(Exception):
pass
class BlobParser(abc.ABC):
@abc.abstractmethod
def parse(self, blob: bytes):
pass
def __call__(self, blob: bytes):
return self.parse(blob)

View File

@ -0,0 +1,52 @@
from funcy import rcompose
from pyinfra.parser.blob_parser import ParsingError
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 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.parse(item)
class EitherParserComposer:
def __init__(self, *parsers):
self.parser = rcompose(*map(EitherParserWrapper, parsers))
def parse(self, item):
return self.parser(item).item
def __call__(self, item):
return self.parse(item)

View File

View File

@ -0,0 +1,7 @@
from pyinfra.parser.blob_parser import BlobParser
class IdentityBlobParser(BlobParser):
def parse(self, data: bytes):
return data

View File

@ -0,0 +1,19 @@
import json
from pyinfra.parser.blob_parser import BlobParser, ParsingError
from pyinfra.server.packing import string_to_bytes
class JsonBlobParser(BlobParser):
def parse(self, data: bytes):
try:
data = data.decode()
data = json.loads(data)
except (UnicodeDecodeError, json.JSONDecodeError, AttributeError) as err:
raise ParsingError from err
if "data" in data:
data["data"] = string_to_bytes(data["data"])
return data

View File

@ -0,0 +1,9 @@
from pyinfra.parser.blob_parser import BlobParser, ParsingError
class StringBlobParser(BlobParser):
def parse(self, data: bytes):
try:
return data.decode()
except Exception as err:
raise ParsingError from err

0
test/parser/__init__.py Normal file
View File

View File

@ -0,0 +1,34 @@
import json
from pyinfra.parser.parser_composer import EitherParserComposer
from pyinfra.parser.parsers.identity import IdentityBlobParser
from pyinfra.parser.parsers.json import JsonBlobParser
from pyinfra.parser.parsers.string import StringBlobParser
def test_json_parser():
d = {"a": 1}
assert JsonBlobParser()(json.dumps(d).encode()) == d
def test_string_parser():
a = "a"
assert StringBlobParser()(a.encode()) == a
def test_identity_parser():
a = "a"
assert IdentityBlobParser()(a.encode()) == a.encode()
def test_either_parser_composer():
parser = EitherParserComposer(JsonBlobParser(), StringBlobParser(), IdentityBlobParser())
d = {"a": 1}
assert parser(json.dumps(d).encode()) == d
a = "a"
assert parser(a.encode()) == a
a = 1
assert parser(a) == a