Code generators for immutable structured data, including algebraic data types, and functions to destructure them.
Project description
Code generators for immutable structured data, including algebraic data types, and functions to destructure them. Structured Data provides three public modules: structured_data.enum, structured_data.match, and structured_data.data.
The enum module provides a class decorator and annotation type for converting a class into an algebraic data type; the name is taken from its use in Rust.
The match module provides a Pattern class that can be used to build match structures, and a ValueMatcher class that wraps a value, and attempts to apply match structures to it. If the match succeeds, the bindings can be extracted and used. It includes some special support for enum subclasses.
The match architecture allows you tell pull values out of a nested structure:
structure = (match.pat.a, match.pat.b @ (match.pat.c, match.pat.d), 5)
my_value = (('abc', 'xyz'), ('def', 'ghi'), 5)
value_matcher = match.ValueMatcher(my_value)
if value_matcher.match(structure):
# The format of the matches is not final.
print(value_matcher.matches['a']) # ('abc', 'xyz')
print(value_matcher.matches['b']) # ('def', 'ghi')
print(value_matcher.matches['c']) # 'def'
print(value_matcher.matches['d']) # 'ghi'
The @ operator allows binding both the outside and the inside of a structure. The contents of the matches attribute will change once there’s been some real-world usage.
The enum decorator exists to create classes that do not necessarily have a single fixed format, but do have a fixed set of possible formats. This lowers the maintenance burden of writing functions that operate on values of an enum class, because the full list of cases to handle is directly in the class definition.
Here are implementations of common algebraic data types in other languages:
@enum.enum
class Maybe(typing.Generic[T]):
Just: enum.Ctor[T]
Nothing: enum.Ctor
@enum.enum
class Either(typing.Generic[E, R]):
Left: enum.Ctor[E]
Right: enum.Ctor[R]
The data module provides classes based on these examples.
Free software: MIT license
Should I Use This?
Until there’s a major version out, probably not.
There are several alternatives in the standard library that may be better suited to particular use-cases:
The namedtuple factory creates tuple classes with a single structure; the typing.NamedTuple class offers the ability to include type information. The interface is slightly awkward, and the values expose their tuple-nature easily.
The enum module provides base classes to create finite enumerations. Unlike NamedTuple, the ability to convert values into an underlying type must be opted into in the class definition.
The dataclasses module provides a class decorator that converts a class into one with a single structure, similar to a namedtuple, but with more customization: instances are mutable by default, and it’s possible to generate implementations of common protocols.
The Structured Data enum decorator is inspired by the design of dataclasses. (A previous attempt used metaclasses inspired by the enum module, and was a nightmare.) Unlike enum, it doesn’t require all instances to be defined up front; instead each class defines constructors using a sequence of types, which ultimately determines the number of arguments the constructor takes. Unlike namedtuple and dataclasses, it allows instances to have multiple shapes with their own type signatures. Unlike using regular classes, the set of shapes is specified up front.
If you want multiple shapes, and don’t want to specify them ahead of time, your best bet is probably a normal tree of classes, where the leaf classes are dataclasses.
Installation
pip install structured-data
Documentation
Development
To run the all tests run:
tox
Changelog
Unreleased
Added
Simpler way to create match bindings.
Dependency on the astor library.
First attempt at populating the annotations and signature of the generated constructors.
data module containing some generic algebraic data types.
Attempts at monad implementations for data classes.
Changed
Broke the package into many smaller modules.
Switched many attributes to use a WeakKeyDictionary instead.
Moved prewritten methods into a class to avoid defining reserved methods at the module level.
When assigning equality methods is disabled for a decorated class, the default behavior is now object semantics, rather than failing comparison and hashing with a TypeError.
The prewritten comparison methods no longer return NotImplemented.
Removed
Ctor metaclass.
0.2.1 (2018-07-13)
Fixed
Removed an incorrect classifier. This code cannot run on pypy.
0.2.0 (2018-07-13)
Added
Explicit __bool__ implementation, to consider all constructor instances as truthy, unless defined otherwise.
Python 3.7 support.
Changed
Marked the enum constructor base class as private. (EnumConstructor -> _EnumConstructor)
Switched scope of test coverage to supported versions. (Python 3.7)
Removed
Support for Python 3.6 and earlier.
Incidental functionality required by supported Python 3.6 versions. (Hooks to enable restricted subclassing.)
0.1.0 (2018-06-10)
First release on PyPI.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Hashes for structured_data-0.3.0-py2.py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 5c53ad532abad33fb65419a97217be6514429b81d4966f4a17b39a0ffaf4dfe9 |
|
MD5 | aeec2e2c8415cc534030eb4d39e688ce |
|
BLAKE2b-256 | 63ec89647e5fa8694a25988aad8bc7523ff1587edd028abfc34ec8d3ae65c93f |