zerial package¶
Module contents¶
-
class
zerial.Sequence(item_type, restructure_factory=<class 'list'>, destructure_factory=<class 'list'>, apparent_type=NOTHING)[source]¶ Bases:
zerial._base.Ztype,typing.GenericMetadata type for a sequence of items.
Handles any version of N number of items of type T. Works for sets, tuples, lists, and anything else that follows that interface.
Attribute item_type: The type of the object contained in this sequence. Note that this can itself be another complex object or another Ztype, so these data types can be arbitrarily nested. Attribute restructure_factory: The callable that will convert a stored sequence into a live data type. Basically, the function that can rebuild your data into the collection type you want. Attribute destructure_factory: The callable that will convert a live sequence into storage data. Normally this will always be list, unless your serialization format supports other sequence types. Attribute apparent_type: To be deprecated
-
class
zerial.Mapping(key_type: Type[K], val_type: Type[V], restructure_factory=<class 'dict'>, destructure_factory=<class 'dict'>, extract_pairs=operator.methodcaller('items'), apparent_type=typing.MutableMapping)[source]¶ Bases:
zerial._base.Ztype,typing.GenericZtype wrapper for a simple mapping/dict
Since many serialization formats require that keys for mappings be strings, we require that the key_type be convertible to-and-from string. This limits us to pretty primitive types, like int and str.
Attribute key_type: The type of the keys of the mapping. Currently only supports types that can do a straight-forward one-to-one convertion to and from
str.Attribute val_type: The type of the values of the mapping. Can be any type that will can be serialized, including other
Ztypeobjects, allowing arbirarily complex value types.Attribute restructure_factory: The container type that will be used to rebuild your data type upon being restructured. It will be called with an iterable of key-value pairs. The default is dict, but if you want, say, a
collections.defaultdictto come out with a default function ofint, you could give this:@zerial.record @attr.s class MyRecord: my_field = attr.ib( type=typing.Mapping[str, int], metadata=zerial.data(zerial.Mapping( str, int, partial(defaultdict, int) )), )
This will result in
my_fieldbeing restructured ready for you to do all the fundefaultdictstuff you’ve always wanted to do likemy_record.my_field[arbitrary_key] += 1, becausezerialensures that it gets restructured that way.Attribute destructure_factory: The container type that will be used to take apart your data to destructure it. Can be useful if your mapping is ordered, in which case you’d want to save it as a
listto preserve the order even in a serialized dict. This feature is unstable and may be replaced by something more sophisticated in the future.Attribute extract_pairs: Function to extract item pairs from the object created by
destructure_factory. By default, this calls.items()on the object it receives, but if you were to destructure into alist, you’ll need to passNonehere (which is converted to the identity functionlambda x: x) since a list of pairs is already, well, a list of pairs. This feature is unstable and may be replaced by something better in the future.
-
class
zerial.Variant(type_records, default=<object object>, name: str = NOTHING, enum: enum.Enum = NOTHING)[source]¶ Bases:
zerial._base.ZtypeVariant that allows multiple types to occupy the same attribute slot.
This is an implementation of a sum type (called enums or variants, depending on the source) for serialization. It allows multiple types to be saved in the same slot, and deserialized intelligently into the correct type. It accomplishes this by storing a name corresponding to the type along with the type information.
Attribute _type_records: Iterable of types, or a mapping of names to types. The types should be concrete types, in the sense that they can instantiate a real object of their class from provided data. They are treated as invariant. If you have multiple subclasses of a type, they must all be specified here. The Varianthas to be able to store the type in the destructured data and consistently map it to the desired runtime type in the restuctured model, so it needs a full accounting of which types are available to it at definition time. If passed a mapping, the keys are taken as the type names. If passed a plain iterable, the type names are taken from the__name__attribute of the class. Collisions are invalid, so if you have two types with the same__name__, use a mapping to give them unique names in this context.Attribute default: Default type to use if no type information is found in the destructured data. This permits previously non-variant field to become variants without invalidating previously saved data. -
NO_DEFAULT= <object object>¶
-
apparent_type¶ Special type indicating an unconstrained type.
- Any is compatible with every type.
- Any assumed to have all methods.
- All values assumed to be instances of Any.
Note that all the above statements are true from the point of view of static type checkers. At runtime, Any should not be used with instance or class checks.
-
destruct(inst, ztr)[source]¶ Unstructure inst into a mapping.
The Ztructurer doing the destructuring is passed for its options and to permit further recursive descent if necessary.
Works with the Ztructurer to take apart more complex types.
-
name¶
-
restruct(data, ztr)[source]¶ Structure the mapping into the appropriate type.
The Ztructurer doing the rebuilding is passed for its options and to permit recursive rebuilding if needed.
Works with Ztructurer to rebuild more complext types.
-
types¶
-
-
class
zerial.Serializer(to_outer: Callable[T, U], to_inner: Callable[U, T])[source]¶ Bases:
zerial._base.Ztype,typing.GenericWhen you just need a serializer that goes forward and back.
Attribute to_outer: Function that destructures the data. Attribute to_inner: Function that restructures the data. If the other metadata types fail, or there are obvious standard string representations of your data type (like in dates), you can just use a
Serializerto take care of it for you:import datetime @zerial.record @attr.s class ImportantDate: name = attr.ib(type=str) date = attr.ib( type=datetime.date, metadata=zerial.data(zerial.Serializer( lambda d: d.isoformat(), lambda s: datetime.datetime.strptime(s, '%Y-%m-%d').date(), )), )
It doesn’t necessarily have to be a string either. If your mapping variant is too complex for
Mapping, then you could use this class as a last resort for defining a method of destructuring it.
-
class
zerial.Ztructurer(dict_factory=<class 'dict'>, metachar: str = '%', permitted_passthrus: tuple = (<class 'bool'>, <class 'int'>, <class 'float'>, <class 'str'>), is_serializable_field=operator.attrgetter('init'), encoders=NOTHING, can_structure=<function has>)[source]¶ Bases:
object
-
zerial.Zapping¶ alias of
zerial._data.Mapping
-
zerial.Zariant¶ alias of
zerial._data.Variant
-
zerial.Zequence¶ alias of
zerial._data.Sequence
-
zerial.Zerializer¶ alias of
zerial._data.Serializer