related-li 0.7.0

Creator: railscoderz

Last updated:

Add to Cart

Description:

relatedli 0.7.0

<img src='./.images/logo.png' width='140' align="left" /><a href='https://codecov.io/github/genomoncology/related/'><img src='https://codecov.io/github/genomoncology/related/branch/master/graph/badge.svg' align="right" /></a><a href='https://travis-ci.org/genomoncology/related'><img src='https://img.shields.io/travis/genomoncology/related.svg' align="right" /></a><a href='https://pypi.python.org/pypi/related'><img src='https://img.shields.io/pypi/v/related.svg' align="right" /></a><br/><br/>`Related` is a Python library for creating nested object modelsthat can be serialized to and de-serialized fromnested python dictionaries.When paired with other libraries (e.g. [PyYAML]),`Related` object models can be used to convert to and fromnested 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<br/>![flow-image]<br/># Requirements* Python (2.7, 3.5, 3.6)# InstallationInstall using `pip`... pip install related# First Example```pythonimport related@related.immutableclass Person(object): first_name = related.StringField() last_name = related.StringField()@related.immutableclass 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:```yamlscientists:- first_name: Grace last_name: Hopper- first_name: Katherine last_name: Johnson```# Second ExampleThe below example is based off of this [Docker Compose example].It shows how a YAML file can be loaded into an object model, tested, andthen generated back into a string that matches the original YAML.```yamlversion: '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) arerepresented by the model.```pythonimport related@related.immutableclass 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.immutableclass 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 conveniencemethod and then round-tripped back to yaml to check that the formathas been maintained. The `related` module uses `OrderedDict` objectsin order to maintain sort order by default.```pythonfrom os.path import join, dirnamefrom model import Composefrom related import to_yaml, from_yaml, to_modelYML_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 ExamplesMore 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. |# DocumentationBelow is a quick version of documentation until more time can be dedicated.## OverviewThe [attrs] library is the underlying engine for `related`.As explained in [this article by Glyph],`attrs` cleanly and cleverlyeliminates a lot of the boilerplaterequired when creating Python classeswithout 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 frameworkThe `related` project is an opinionated layerbuilt on top of the `attrs` librarythat 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 properdocumentation 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 straightforwarddue 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 properdocumentation is generated.# Credits/Prior ArtThe `related` project has been heavily influenced by the followingprojects 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.# LicenseThe MIT License (MIT)Copyright (c) 2017 [Ian Maurer], [Genomoncology LLC][flow-image]: ./.images/flow.png[decorators.py]: ./src/related/decorators.py[fields.py]: ./src/related/fields.py[functions.py]: ./src/related/functions.py[attrs]: http://attrs.readthedocs.io/en/stable/[this article by Glyph]: https://glyph.twistedmatrix.com/2016/08/attrs.html[Genomoncology LLC]: http://genomoncology.com[Ian Maurer]: https://github.com/imaurer[singledispatch library]: https://pypi.python.org/pypi/singledispatch[monkey-patching]: http://stackoverflow.com/questions/5626193/what-is-a-monkey-patch[Django ORM]: https://docs.djangoproject.com/en/1.11/topics/db/models/[UUID]: https://docs.python.org/3/library/uuid.html#uuid.UUID[uuid4]: https://docs.python.org/3/library/uuid.html#uuid.uuid4[ParseResult]: https://docs.python.org/2/library/urlparse.html#urlparse.ParseResult[cattrs]: http://cattrs.readthedocs.io/en/latest/readme.html[addict]: https://github.com/mewwts/addict[box]: https://pypi.python.org/pypi/python-box[Jackson]: https://github.com/FasterXML/jackson[Docker Compose example]: https://docs.docker.com/compose/gettingstarted/#step-3-define-services-in-a-compose-file[PyYAML]: https://pypi.python.org/pypi/PyYAML[tests/]: ./tests/[Example 00]: ./tests/ex00_sets_hashes[Example 01]: ./tests/ex01_compose_v2[Example 02]: ./tests/ex02_compose_v3.2[Example 03]: ./tests/ex03_company[Example 04]: ./tests/ex04_contact[Example 05]: ./tests/ex05_field_names[Example 06]: ./tests/ex06_json[Example 07]: ./tests/ex07_serializer[Example 08]: ./tests/ex08_self_reference0.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.

License

For personal and professional use. You cannot resell or redistribute these repositories in their original state.

Customer Reviews

There are no reviews.