Source code for dolor.types.optional

import inspect

from .type import Type
from .util import prepare_types

[docs]class Optional(Type): elem_type = None exists = None
[docs] @classmethod def is_prefixed_by_type(cls): return isinstance(cls.exists, type) and issubclass(cls.exists, Type)
[docs] @classmethod def has_function(cls): return inspect.isfunction(cls.exists)
[docs] @classmethod def is_at_end(cls): return cls.exists is None
@classmethod def _default(cls, *, ctx=None): if cls.has_function() and cls.exists(ctx.instance): return cls.elem_type.default(ctx=ctx) return None @classmethod def _unpack(cls, buf, *, ctx=None): if cls.has_function(): if cls.exists(ctx.instance): return cls.elem_type.unpack(buf, ctx=ctx) elif cls.is_prefixed_by_type() and cls.exists.unpack(buf, ctx=ctx): return cls.elem_type.unpack(buf, ctx=ctx) elif cls.is_at_end(): try: return cls.elem_type.unpack(buf, ctx=ctx) except: return None return None @classmethod def _pack(cls, value, *, ctx=None): if cls.has_function(): if cls.exists(ctx.instance): return cls.elem_type.pack(value, ctx=ctx) return b"" elif cls.is_prefixed_by_type(): if value is not None: return cls.exists.pack(True, ctx=ctx) + cls.elem_type.pack(value, ctx=ctx) return cls.exists.pack(False, ctx=ctx) elif cls.is_at_end(): if value is not None: return cls.elem_type.pack(value, ctx=ctx) return b"" return b"" @classmethod @prepare_types def _call(cls, elem_type: Type, exists=None): if isinstance(exists, str): attr = exists exists = lambda x: getattr(x, attr) return cls.make_type(f"{cls.__name__}{elem_type.__name__}", elem_type = elem_type, exists = exists, )