vltr / middle

Flexible, extensible Python data structures for general usage
https://middle.readthedocs.io/en/latest/
MIT License
10 stars 1 forks source link
attrs customizable hooks models object primitives serialization utilities

========== middle

.. start-badges

.. image:: https://img.shields.io/pypi/status/middle.svg :alt: PyPI - Status :target: https://pypi.org/project/middle/

.. image:: https://img.shields.io/pypi/v/middle.svg :alt: PyPI Package latest release :target: https://pypi.org/project/middle/

.. image:: https://img.shields.io/pypi/pyversions/middle.svg :alt: Supported versions :target: https://pypi.org/project/middle/

.. image:: https://travis-ci.org/vltr/middle.svg?branch=master :alt: Travis-CI Build Status :target: https://travis-ci.org/vltr/middle

.. image:: https://ci.appveyor.com/api/projects/status/github/vltr/middle?branch=master&svg=true :alt: AppVeyor Build Status :target: https://ci.appveyor.com/project/vltr/middle

.. image:: https://readthedocs.org/projects/middle/badge/?style=flat :target: https://readthedocs.org/projects/middle :alt: Documentation Status

.. image:: https://codecov.io/github/vltr/middle/coverage.svg?branch=master :alt: Coverage Status :target: https://codecov.io/github/vltr/middle

.. image:: https://api.codacy.com/project/badge/Grade/10c6ef32dfbe497087d57c9d86c02c80 :alt: Codacy Grade :target: https://www.codacy.com/app/vltr/middle?utm_source=github.com&utm_medium=referral&utm_content=vltr/middle&utm_campaign=Badge_Grade

.. image:: https://pyup.io/repos/github/vltr/middle/shield.svg :target: https://pyup.io/account/repos/github/vltr/middle/ :alt: Packages status

.. end-badges

Flexible, extensible Python data structures for general usage. Get data in and out, reliably, without boilerplate and with speed!

middle stands on the shoulders of attrs and aims to be as simple as possible to get data from complex objects to Python primitives and vice-versa, with validators, converters, a lot of sugar and other utilities! middle can be used with your preferred web framework, background job application, configuration parser and more!

Sneak peek

The most simple example of middle and some of its features (using Python 3.6+ syntax):

.. code-block:: pycon

>>> import typing
>>> import middle

>>> class Address(middle.Model):
...     street_name: str
...     number: typing.Optional[int]
...     city: str

>>> class Person(middle.Model):
...     name: str
...     age: int
...     address: typing.Dict[str, Address]

>>> data = {
...     "name": "John Doe",
...     "age": 42,
...     "address": {
...         "home": {
...             "street_name": "Foo St",
...             "number": None,
...             "city": "Python Park"
...         },
...         "work": {
...             "street_name": "Bar Blvd",
...             "number": "1337",
...             "city": "Park City"
...         }
...     }
... }

>>> person = Person(data)

>>> person
Person(name='John Doe', age=42, address={'home': Address(street_name='Foo St', number=None, city='Python Park'), 'work': Address(street_name='Bar Blvd', number=1337, city='Park City')})

>>> middle.asdict(person)
{'name': 'John Doe', 'age': 42, 'address': {'home': {'street_name': 'Foo St', 'number': None, 'city': 'Python Park'}, 'work': {'street_name': 'Bar Blvd', 'number': 1337, 'city': 'Park City'}}}

Wanted a more complex example, with Python 3.5 compatible syntax? For sure!

.. code-block:: pycon

>>> from typing import Dict, List
>>> import middle

>>> class Game(middle.Model):
...     name: str = middle.field()
...     score: float = middle.field(minimum=0, maximum=10)
...     resolution_tested: str = middle.field(pattern="^\d+x\d+$")
...     genre: List[str] = middle.field(unique_items=True)
...     rating: Dict[str, float] = middle.field(max_properties=5)

>>> data = {
...     "name": "Cities: Skylines",
...     "score": 9.0,
...     "resolution_tested": "1920x1200",
...     "genre": ["Simulators", "City Building"],
...     "rating": {
...         "IGN": 8.5,
...         "Gamespot": 8.0,
...         "Steam": 4.5
...     }
... }

>>> game = Game(**data)

>>> game
Game(name='Cities: Skylines', score=9.0, resolution_tested='1920x1200', genre=['Simulators', 'City Building'], rating={'IGN': 8.5, 'Gamespot': 8.0, 'Steam': 4.5})

>>> middle.asdict(game)
{'name': 'Cities: Skylines', 'score': 9.0, 'resolution_tested': '1920x1200', 'genre': ['Simulators', 'City Building'], 'rating': {'IGN': 8.5, 'Gamespot': 8.0, 'Steam': 4.5}}

middle is flexible enough to understand Enum, nested models and a large variety of types declared on the typing module out of the box. Also, you can extend it <https://middle.readthedocs.io/en/latest/extending.html>_ to your own classes!

.. warning::

**IMPORTANT**: ``middle`` is in **very early stages** of development. There are some requirements (like ``python-dateutil``) that would not be required in future releases; as there's a lot of functionalities that needs to be implemented and some known misbehaviors to be addressed, not to mention it needs a lot of testing before moving to any other status rather than **alpha**.

TODO

Done

Future discussions

Warning for Windows developers

If you're using Windows and Python 3.5, I think middle would not work well for you. CI in AppVeyor was disabled for Python 3.5 because of this issue <https://github.com/python/typing/issues/523>_. If Guido doesn't care, why should I (or you) ?

Documentation

https://middle.readthedocs.io/en/latest/

Useful links

Inspirations and thanks

Some libs that inspired the creation of middle:

License

middle is a free software distributed under the MIT <https://choosealicense.com/licenses/mit/>_ license.