Skip to main content

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!

Sneak peek

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

>>> 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!

>>> 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 to your own classes!

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;

  • 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 (with the exception of Windows platforms, see warning for Windows developers below);

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.

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. If Guido doesn’t care, why should I (or you) ?

Documentation

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

v0.2.2 on 2018-10-28

  • Added the possibility for models to have methods, functions, properties and etc.

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

v0.1.0 on 2018-06-21

  • First release on PyPI.

Release files for middle 0.2.4

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for middle 0.2.4
File Size Uploaded
middle-0.2.4.tar.gz 61.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for middle 0.2.4
File Interpreter ABI Platform
middle-0.2.4-py3-none-any.whl Python 3 none any Details

Total release size: 81.0 kB

Release files / middle-0.2.4.tar.gz

Download URL middle-0.2.4.tar.gz
Size 61.0 kB
Tags Source
SHA-256 checksum
How to use checksums
95c3971b7bf7fe8c98e112be098b38e519a572cfa18870811388c2daa3c62a89
BLAKE2b-256 checksum
How to use checksums
0a811021ea18bbb00f76e24a0681dbdfa05f3f28ed0ac65fdc3724263a84456b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/1.13.0 pkginfo/1.5.0.1 requests/2.22.0 setuptools/40.8.0 requests-toolbelt/0.9.1 tqdm/4.32.1 CPython/3.7.3

Release files / middle-0.2.4-py3-none-any.whl

Download URL middle-0.2.4-py3-none-any.whl
Size 20.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d5d2d0b62ce8f33d29c1a8bc193754019b401e9395f323e6afc00f69e4215564
BLAKE2b-256 checksum
How to use checksums
8e70856c72196dd8c22850fc0bb0ca31e9c10d3467bca0a6fe67bff3a0c0ce0e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/1.13.0 pkginfo/1.5.0.1 requests/2.22.0 setuptools/40.8.0 requests-toolbelt/0.9.1 tqdm/4.32.1 CPython/3.7.3

Release history Release notifications | RSS feed

This release

0.2.4 This release

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.1

1 release file

0.1.0

1 release file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page