Metadata-Version: 2.1
Name: middle
Version: 0.2.1
Summary: Flexible, extensible Python data structures for general usage
Home-page: https://github.com/vltr/middle
Author: Richard Kuesters
Author-email: rkuesters@gmail.com
License: MIT license
Keywords: attrs,object,primitives,serialization,models,hooks,customizable,utilities
Platform: UNKNOWN
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: Unix
Classifier: Operating System :: POSIX
Classifier: Operating System :: Microsoft :: Windows
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Topic :: Utilities
Requires-Dist: attrs (>=17.4.0)
Requires-Dist: pytz (>=2018)
Requires-Dist: python-dateutil (>=2.6.0)

==========
``middle``
==========



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!

Quick peak
----------

.. 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
====

- Alias options (keys) to populate classes;
- Read-only and write-only fields;
- Better error handling (almost everywhere);
- Create a benchmark suite against other solutions;
- Some formatters are still missing;
- Possibility to "cast" an instance to another instance where the original object is a subclass of it;

Done
----

- If possible, fine grain the converters, so a ``str`` input value of ``{}`` doesn't end up as ``str({})``;
- Get ``date`` and ``datetime`` converters to be customizable, instead of an ``if isinstance`` statement;
- Implement more validators and a registerable for more metadata options;
- Implement a better "type dispatcher" based on more complex rules (other than ``type(field.type)`` delivered by ``functools.singledispatch``) because the ``typing`` module has changed **a bit** between Python 3.6 and 3.7;
- Support more types (``typing.Tuple``, ``decimal.Decimal``);
- Get 100% (or closer) in code coverage;
- Lots of documentation;
- Python 3.5 support;

Future discussions
------------------

- In Python 3.7, a neat feature was added: ``dataclasses``. I know it sounds really awesome to not depend on a 3rd-party library - such as ``attrs``, but the latest provides a lot of functionalities that can't be found on Python 3.7 ``dataclasses`` (for now), so I'll leave this open for further discussion.

Documentation
=============

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

Inspirations and thanks
=======================

Some libs that inspired the creation of ``middle``:

- `attrs <http://www.attrs.org/en/stable/>`_: how such a simple library can be such flexible, extendable and fast?
- `cattrs <https://github.com/Tinche/cattrs>`_: for its speed on creating ``attrs`` instances from ``dict`` and to instances again;
- `pydantic <https://pydantic-docs.helpmanual.io/>`_: for such pythonic and beautiful approach on creating classes using ``typing`` hints;
- `mashmallow <https://marshmallow.readthedocs.io/en/latest/>`_: it is one of the most feature rich modelling APIs I've seen;
- `apistar <https://docs.apistar.com/>`_: it's almost magical!
- `Sanic <http://sanic.readthedocs.io/en/latest/>`_: "*Gotta go fast!*"
- `ionelmc/cookiecutter-pylibrary <https://github.com/ionelmc/cookiecutter-pylibrary>`_: The most complete (or interesting) ``cookiecutter`` template I found so far (make sure to `read this <https://blog.ionelmc.ro/2014/05/25/python-packaging/>`_ article too);

License
=======

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


Changelog
=========

v0.2.1 on 2018-07-26
--------------------

* Quick fix related to the change log and MANIFEST.in files

v0.2.0 on 2018-07-26
--------------------

* Released (part) of the documentation
* Got 99% coverage (finally combined)
* Python 3.5 support added

v0.1.1 on 2018-07-02
--------------------

* Add proper unit testing and support for Python 3.6 and 3.7
* Made the API a bit more flexible
* Code format and check done with `black <https://github.com/ambv/black>`_

v0.1.0 on 2018-06-21
--------------------

* First release on PyPI.


