Module xtelligent_serial.data_structs

Expand source code
from .struct_descriptor import describe_struct_family, DescriptorInterface
from .struct_registry import register_struct_family

__all__ = [
    'describe_struct_family',
    'register_struct_family',
    'DescriptorInterface',
]

Sub-modules

xtelligent_serial.data_structs.struct_descriptor
xtelligent_serial.data_structs.struct_registry

Functions

def describe_struct_family(name, is_instance: , get_fields: ) ‑> DescriptorInterface
Expand source code
def describe_struct_family(name, is_instance: is_instance_callback, get_fields: get_fields_callback) -> DescriptorInterface:
    return DescriptorInterface2(name, is_instance, get_fields)
def register_struct_family(descriptor: DescriptorInterface) ‑> FamilyRegistry
Expand source code
def register_struct_family(descriptor: DescriptorInterface) -> FamilyRegistry:

    def ds_struct(t: Type, raw_data: Mapping):
        type_fields = {f.name:f for f in descriptor.get_fields(t)}
        def pick_type(field: Field, value: Any) -> Type:
            return field.type or type(value)
        names_to_type = {k:pick_type(f, raw_data.get(k)) for k, f in type_fields.items()}
        kwargs = {k: deserialize(names_to_type[k], v) for k, v in raw_data.items() if k in type_fields}
        return t(**kwargs)

    def register_specific_type(t: Type):
        f = dispatcher.get(t)
        if f:
            return f
        def ds(raw_data: Mapping): # pylint: disable=invalid-name
            return ds_struct(t, raw_data)
        dispatcher[t] = ds
        return ds

    class StructProxy(ABC):
        @classmethod
        def __subclasshook__(cls, subclass):
            if descriptor.is_instance(subclass):
                register_specific_type(subclass)
                return True
            return False

    def ds_hook(raw_data, **kwargs): # check kwargs for type and dispatch accordingly.
        t = kwargs.get('type')
        if not t:
            raise ValueError('No type argument supplied')
        f = dispatcher.get(t)
        if not f:
            raise NotImplementedError(f'No serializer for type {t}')
        return f(raw_data)

    # Duplicate registrations cause ambiguous dispatch exceptions.
    if descriptor.name in registries:
        return registries[descriptor.name]

    register_deserializer(StructProxy, ds_hook)
    class Registry:
        @classmethod
        def has(cls, t: Type) -> bool:
            return issubclass(t, StructProxy) and t in dispatcher
    registries[descriptor.name] = Registry
    return Registry

Classes

class DescriptorInterface

Describes a family of classes/structs such as dataclass or attrs.

Expand source code
class DescriptorInterface:
    '''Describes a family of classes/structs such as dataclass or attrs.'''
    @property
    def name(self) -> str:
        '''Name of the family/API (dataclass, attrs)'''
        raise NotImplementedError()

    def is_instance(self, target: Any) -> bool:
        '''Returns True if an instance is from that family. Note that the API
        may not leverage inheritance for membership.'''
        raise NotImplementedError()

    def get_fields(self, t: Type) -> Iterable[Field]:
        '''Returns the fields of a type in the family/API. The result is an Iterable
        of dataclasses.Field instances.'''
        raise NotImplementedError()

Instance variables

var name : str

Name of the family/API (dataclass, attrs)

Expand source code
@property
def name(self) -> str:
    '''Name of the family/API (dataclass, attrs)'''
    raise NotImplementedError()

Methods

def get_fields(self, t: Type) ‑> Iterable[dataclasses.Field]

Returns the fields of a type in the family/API. The result is an Iterable of dataclasses.Field instances.

Expand source code
def get_fields(self, t: Type) -> Iterable[Field]:
    '''Returns the fields of a type in the family/API. The result is an Iterable
    of dataclasses.Field instances.'''
    raise NotImplementedError()
def is_instance(self, target: Any) ‑> bool

Returns True if an instance is from that family. Note that the API may not leverage inheritance for membership.

Expand source code
def is_instance(self, target: Any) -> bool:
    '''Returns True if an instance is from that family. Note that the API
    may not leverage inheritance for membership.'''
    raise NotImplementedError()