Flexible, extensible Python data structures for general usage
Project description
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
Useful links
Inspirations and thanks
Some libs that inspired the creation of middle:
attrs: how such a simple library can be such flexible, extendable and fast?
cattrs: for its speed on creating attrs instances from dict and to instances again;
pydantic: for such pythonic and beautiful approach on creating classes using typing hints;
mashmallow: it is one of the most feature rich modelling APIs I’ve seen;
apistar: it’s almost magical!
Sanic: “Gotta go fast!”
ionelmc/cookiecutter-pylibrary: The most complete (or interesting) cookiecutter template I found so far (make sure to read this article too);
License
middle is a free software distributed under the MIT license.
Changelog
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.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file middle-0.2.4.tar.gz
.
File metadata
- Download URL: middle-0.2.4.tar.gz
- Upload date:
- Size: 61.0 kB
- Tags: Source
- Uploaded using 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
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 95c3971b7bf7fe8c98e112be098b38e519a572cfa18870811388c2daa3c62a89 |
|
MD5 | 79814741ec0b0a6dd1bd9052d603145e |
|
BLAKE2b-256 | 0a811021ea18bbb00f76e24a0681dbdfa05f3f28ed0ac65fdc3724263a84456b |
File details
Details for the file middle-0.2.4-py3-none-any.whl
.
File metadata
- Download URL: middle-0.2.4-py3-none-any.whl
- Upload date:
- Size: 20.0 kB
- Tags: Python 3
- Uploaded using 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
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | d5d2d0b62ce8f33d29c1a8bc193754019b401e9395f323e6afc00f69e4215564 |
|
MD5 | c64753af3a80e3ecaba28bc462922872 |
|
BLAKE2b-256 | 8e70856c72196dd8c22850fc0bb0ca31e9c10d3467bca0a6fe67bff3a0c0ce0e |