Pytyp Package

Pytyp can encode from Python classes to dicts. It can also decode dicts back into Python classes.

Although they are designed to work together, each of these processes has different requirements. If you only want to move data in one direction you only need to comply with the requirements for that process.

Routines that use the encoding and decoding describe here to inter-operate with JSON and YAML are available in the sub-packages pytyp.json and pytyp.yaml. The documentation in this section and pytyp.types focusses on the underlying implementation.

Encoding

pytyp.DEFAULT_RAW = (<class 'str'>, <class 'int'>, <class 'float'>, <class 'bool'>)

Types that are not explicitly encoded, but instead passed through as raw values.

pytyp.encode(obj, raw=(<class 'str'>, <class 'int'>, <class 'float'>, <class 'bool'>), recurse=True, check_circular=True, strict=True)[source]

Encode a Python class as a dictionary. This function can also encode lists, tuples and dictionaries containing classes, and nested classes.

Parameters:
  • obj – The object to be encoded.
  • raw – Types that are not explicitly encoded, but passed through as raw values (by default, DEFAULT_RAW).
  • recurse – Recursively encode values? encode is designed to be used with other encodes; sometimes these expect only a single value to be encoded (recurse=False).
  • check_circular – If True, an error is rased for circular references (if disabled the encoding may loop indefinitely).
  • strict – If True, fail when constructor parameters with default values have no corresponding attribute.

To encode data, pytyp looks at the constructor arguments. For each argument it assumes that the class has an attribute or property that provides a value.

So, for example, this class can be encoded:

>>> class EncExample():
...     def __init__(self, a, b=None):
...         self.a = a
...         self.b = b
...
>>> encode(EncExample(1, 2))
{'a': 1, 'b': 2}

but this class cannot:

>>> class BadEncExample():
...     def __init__(self, q):
...         self.z = q
...
>>> encode(BadEncExample(1))
Traceback (most recent call last):
  ...
AttributeError: 'BadEncExample' object has no attribute 'q'

If you do not want your objects to be mutable you can expose the same information through read-only properties:

>>> class ReadOnly():
...     def __init__(self, value):
...         self._value = value
...     @property
...     def value(self):
...         return self._value
...
>>> encode(ReadOnly(1))
{'value': 1}

Decoding

pytyp.decode(spec, value)[source]

Decode a dictionary of data as a Python class. This function can also decode lists, tuples and dictionaries of values, and nested values.

Parameters:
  • spec – The class (more generally, the type specification - see below) to create.
  • value – The data to decode.

To decode data, pytyp looks at the type specification and constructs the class by calling the constructor. The specification can contain lists, tuples and dictionaries, but must have the same form as the input.

For example, here decode() is called with a type specification for a list of DecExample() instances:

>>> class DecExample():
...     def __init__(self, a):
...         self.a = a
...     def __repr__(self):
...         return '<DecExample({0})>'.format(self.a)
...
>>> decode([DecExample], [{'a': 1}, {'a': 2}])
[<DecExample(1)>, <DecExample(2)>]

To handle nested types the constructor of the container class must have a type declaration (another type specification):

>>> class Container():
...     def __init__(self, ex:DecExample):
...         self.ex = ex
...     def __repr__(self):
...         return '<Container({0})>'.format(self.ex)
...
>>> decode(Container, {'ex': {'a': 1}})
<Container(<DecExample(1)>)>

Note the type declaration in the constructor above. Without that declaration pytyp will incorrectly interpret the data:

>>> class BadContainer():
...     def __init__(self, ex):
...         self.ex = ex
...     def __repr__(self):
...         return '<BadContainer({0})>'.format(self.ex)
...
>>> decode(BadContainer, {'ex': {'a': 1}})
<BadContainer({'a': 1})>

In type specifications, lists must be of a single type, but tuples and dicts have a specific type for each member:

>>> decode((Container, DecExample), ({'ex': {'a': 1}}, {'a': 2}))
(<Container(<DecExample(1)>)>, <DecExample(2)>)

A value of None can be matched by an optional type:

>>> decode((Opt(Container), DecExample), (None, {'a': 2}))
(None, <DecExample(2)>)

Table Of Contents

Previous topic

Welcome to Pytyp’s documentation!

Next topic

Pytyp.json Module

This Page