Commit 6e7391cb authored by Rolf van Kleef's avatar Rolf van Kleef
Browse files

Feature completeness

parent 5ec2e899
Loading
Loading
Loading
Loading

LICENSE.txt

0 → 100644
+501 −0

File added.

Preview size limit exceeded, changes collapsed.

+35 −10
Original line number Original line Diff line number Diff line
from typing import Optional
from typing import Optional, Union


from typeguard import check_type
from typeguard import check_type


@@ -86,7 +86,7 @@ class Deserializable(metaclass=BaseMeta):
        return fields
        return fields




def deserialize(t, d, try_all=False):
def get_deserialization_class(t, d, try_all=False):
    for sc in t.__subclasses__():
    for sc in t.__subclasses__():
        if hasattr(sc, '_discriminators'):
        if hasattr(sc, '_discriminators'):
            for discriminator in sc._discriminators:
            for discriminator in sc._discriminators:
@@ -94,17 +94,42 @@ def deserialize(t, d, try_all=False):
                    break
                    break
            else:
            else:
                try:
                try:
                    return deserialize(sc, d)
                    return get_deserialization_class(sc, t, try_all)
                except TypeError as e:
                except TypeError as e:
                    if not try_all:
                    if not try_all:
                        raise e
                        raise e
    return t


    if hasattr(t, '_abstract') and t._abstract:
        raise TypeError('Cannot deserialize into {}: is abstract.'.format(t.__name__))


    instance = t()
def deserialize(rule: Rule, data, try_all=False, key=None):
    for k, rule in t.get_attrs().items():
    # In case of primitive types, attempt to assign.
        v = rule.validate(k, d[k] if k in d else None)
    try:
        return rule.validate(key, data)
    except TypeError:
        pass

    if type(rule.type) is type(Union):
        for arg in rule.type.__args__:
            try:
                return deserialize(Rule(arg), data, try_all, key)
            except TypeError:
                pass
        raise TypeError('{} did not match any of {}.'.format(type(data), rule.type.__args__))

    if issubclass(rule.type, Deserializable):
        if not isinstance(data, dict):
            raise TypeError('Cannot deserialize non-dict into class.')

        cls = get_deserialization_class(rule.type, data, try_all)

        if hasattr(cls, '_abstract') and cls._abstract:
            raise TypeError('Cannot deserialize into {}: is abstract.'.format(cls.__name__))

        instance = cls()
        for k, r in cls.get_attrs().items():
            v = deserialize(r, data[k] if k in data else r.default, try_all, key=k)
            setattr(instance, k, v)
            setattr(instance, k, v)


        return instance
        return instance

    raise TypeError('Unable to find a deserialization candidate for {} in {}.'.format(data, rule))
 No newline at end of file
+26 −8
Original line number Original line Diff line number Diff line
from time import sleep
from time import sleep
from typing import Optional
from typing import Optional


from serializer_utils.deserializer import Deserializable
from serializer_utils.deserializer import Deserializable, Rule
from serializer_utils.annotations import abstract, discriminate
from serializer_utils.annotations import abstract, discriminate




@@ -32,16 +32,34 @@ class RefundLine(ReceiptLine):
        return 'RefundLine(super={})'.format(super(RefundLine, self).__repr__())
        return 'RefundLine(super={})'.format(super(RefundLine, self).__repr__())





class Test(Deserializable):
    tf: Optional[ReceiptLine]

    def __repr__(self):
        return 'Test(tf={})'.format(self.tf.__repr__())


if __name__ == '__main__':
if __name__ == '__main__':
    import sys
    import sys
    import traceback
    import traceback


    from serializer_utils.deserializer import deserialize
    from serializer_utils.deserializer import deserialize


    def print_result(function, *args, **kwargs):
        try:
        try:
        print(deserialize(ReceiptLine, {'type': 'transaction', 'name': 'asdf', 'article_id': 5, 'amount': 5}))
            print(function(*args, **kwargs))
        print(deserialize(ReceiptLine, {'type': 'refund', 'name': 'asdf', 'pk': 5}))
        except:
        print(deserialize(ReceiptLine, {'type': 'other', 'name': 'asdf'}))
    except TypeError as err:
            sleep(0.05)
            sleep(0.05)
            print(traceback.format_exc(), file=sys.stderr)
            print(traceback.format_exc(), file=sys.stderr)

    fns = [
        [Rule(ReceiptLine), {'type': 'transaction', 'name': 'asdf', 'article_id': 5, 'amount': 5}],
        [Rule(ReceiptLine), {'type': 'refund', 'name': 'asdf', 'pk': 5}],
        [Rule(ReceiptLine), {'type': 'other', 'name': 'asdf'}],
        [Rule(ReceiptLine), {'type': 'transaction'}],
        [Rule(ReceiptLine), {'type': 'transaction', 'name': 'asdf', 'pk': 'no'}],
        [Rule(Test), {'tf': {'type': 'refund', 'name': 'asdf', 'pk': 5}}]
    ]

    [print_result(deserialize, *entry) for entry in fns]