0 purchases
relatedwithoutfuture 0.7.4
This fork sacrifices support for Python 2.7 in favorof Python 3.12
Related is a Python library for creating nested object models
that can be serialized to and de-serialized from
nested python dictionaries.
When paired with other libraries (e.g. PyYAML),
Related object models can be used to convert to and from
nested data formats (e.g. JSON, YAML).
Example use cases for related object models include:
Configuration file reading and writing
REST API message response generation and request processing
Object-Document Mapping for a document store (e.g. MongoDB, elasticsearch)
Data import parsing or export generation
Requirements
Python 3.5+
Installation
Install using pip...
pip install related
First Example
import related
@related.immutable
class Person(object):
first_name = related.StringField()
last_name = related.StringField()
@related.immutable
class RoleModels(object):
scientists = related.SetField(Person)
people = [Person(first_name="Grace", last_name="Hopper"),
Person(first_name="Katherine", last_name="Johnson"),
Person(first_name="Katherine", last_name="Johnson")]
print(related.to_yaml(RoleModels(scientists=people)))
Yields:
scientists:
- first_name: Grace
last_name: Hopper
- first_name: Katherine
last_name: Johnson
Second Example
The below example is based off of this Docker Compose example.
It shows how a YAML file can be loaded into an object model, tested, and
then generated back into a string that matches the original YAML.
version: '2'
services:
web:
build: .
ports:
- 5000:5000
volumes:
- .:/code
redis:
image: redis
Below is the related object model that represents the above configuration.
Notice how the name-based mapping of services (i.e. web, redis) are
represented by the model.
import related
@related.immutable
class Service(object):
name = related.StringField()
image = related.StringField(required=False)
build = related.StringField(required=False)
ports = related.SequenceField(str, required=False)
volumes = related.SequenceField(str, required=False)
command = related.StringField(required=False)
@related.immutable
class Compose(object):
version = related.StringField(required=False, default=None)
services = related.MappingField(Service, "name", required=False)
The above yaml can then be loaded by using one of the convenience
method and then round-tripped back to yaml to check that the format
has been maintained. The related module uses OrderedDict objects
in order to maintain sort order by default.
from os.path import join, dirname
from model import Compose
from related import to_yaml, from_yaml, to_model
YML_FILE = join(dirname(__file__), "docker-compose.yml")
def test_compose_from_yml():
original_yaml = open(YML_FILE).read().strip()
yml_dict = from_yaml(original_yaml)
compose = to_model(Compose, yml_dict)
assert compose.version == '2'
assert compose.services['web'].ports == ["5000:5000"]
assert compose.services['redis'].image == "redis"
generated_yaml = to_yaml(compose,
suppress_empty_values=True,
suppress_map_key_values=True).strip()
assert original_yaml == generated_yaml
More Examples
More examples can be found by reviewing the tests/ folder of this project.
Below are links and descriptions of the tests provided so far.
Example
description
Example 00
First example above that shows how SetFields work.
Example 01
Second example above that demonstrates YAML (de)serialization.
Example 02
Compose v3 with long-form ports and singledispatch to_dict
Example 03
A single class (Company) with a bunch of value fields.
Example 04
A multi-class object model with Enum class value field.
Example 05
Handling of renaming of attributes including Python keywords.
Example 06
Basic JSON (de)serialization with TimeField, DateTimeField and DecimalField.
Example 07
Function decorator that converts inputs to obj and outputs to dict
Example 08
Handle self-referencing and out-of-order references using strings.
Documentation
Below is a quick version of documentation until more time can be dedicated.
Overview
The attrs library is the underlying engine for related.
As explained in this article by Glyph,
attrs cleanly and cleverly
eliminates a lot of the boilerplate
required when creating Python classes
without using inheritance.
Some core functionality provided by attrs:
Generated initializer method
(__init__)
Generated comparison methods
(__eq__, __ne__, __lt__, __le__, __gt__, __ge__ )
Human-readable representation method
(__repr__)
Attribute converter and validator framework
The related project is an opinionated layer
built on top of the attrs library
that provides the following:
Value fields that handle both validation and conversion
to and from basic data types like
str, float, and bool.
Nested fields that support relationships such as
Child, Sequences, Mappings, and Sets of objects.
to_dict function that converts nested object graphs
to python dictionaries.
Made customizable (without resorting to monkey-patching)
by the singledispatch library.
to_model function that instantiated classes
used by the de-serialization process going from
python dictionaries to the related model.
Conversion helper functions
(to_yaml, from_yaml, to_json, from_json)
for easily going between
related models and data formats.
@mutable and @immutable for decorating classes
as related models without the need for inheritance increasing
maintainability and flexibility.
Class Decorators
decorator
description
@mutable
Activate a related class that instantiates changeable objects.
@immutable
Activate a related class that instantiates unchangeable objects.
See the decorators.py file to view the source code until proper
documentation is generated.
Field Types
field type
description
BooleanField
bool value field.
ChildField
Child object of a specified type cls.
DateField
date field formatted using formatter.
DateTimeField
datetime field formatted using formatter.
TimeField
time field formatted using formatter.
FloatField
float value field.
IntegerField
int value field.
MappingField(cls,key)
Dictionary of objects of type cls index by key field values.
RegexField(regex)
str value field that is validated by re.match(regex).
SequenceField(cls)
List of objects all of specified type cls.
SetField
Set of objects all of a specified type cls.
StringField
str value field.
URLField
ParseResult object.
UUIDField
UUID object, will create uuid4 by default if not specified.
Adding your own field types is fairly straightforward
due to the power of the underlying attrs project.
See the fields.py file to see how the above are constructed.
Functions
function
description
from_json(s,cls)
Convert a JSON string or stream into specified class.
from_yaml(s,cls)
Convert a YAML string or stream into specified class.
is_related(obj)
Returns True if object is @mutable or @immutable.
to_dict(obj)
Singledispatch function for converting to a dict.
to_json(obj)
Convert object to a (pretty) JSON string via to_dict.
to_model(cls,value)
Convert a value to a cls instance.
to_yaml(obj)
Convert object to a YAML string via to_dict.
See the functions.py file to view the source code until proper
documentation is generated.
Credits/Prior Art
The related project has been heavily influenced by the following
projects that might be worth looking at if related doesn't meet your needs.
attrs - The engine that powers related functionality.
Django ORM - Object-relational mapping for Django that inspired related's design.
cattrs - Alternative take for handling nested-objects using attrs.
addict and box - Python dictionary wrappers that do not require a model.
Jackson - Java-based technology for serializing and de-serializing objects.
License
The MIT License (MIT)
Copyright (c) 2017 Ian Maurer, Genomoncology LLC
0.7.1 (2018-10-13)
Add URL to related pypi page [#28]
Make singledispatch an optional dependency for < python 3.4. Thanks [GhostofGoes].
URLField bug [#20]
Deprecation warnings fixed for python 3.7 [#27]
0.6.2 (2018-02-12)
Contribution [GabrielDav]: TimeField and DateTimeField fields.
0.6.1 (2018-01-31)
Strict Mode [Issue #8] throws an exception when receiving an undefined key.
0.3 (2017-06-23)
New type: ImmutableDict
Add function on TypedMapping
Bug fixes in from_yaml and from_json functions.
0.2 (2017-06-05)
Allow None by default in Typed Collections.
0.1 (2017-05-24)
Initial release.
For personal and professional use. You cannot resell or redistribute these repositories in their original state.
There are no reviews.