Skip to main content

Typed, declarative data structures

Project description

Build Status PyPI version

This package provides immutable data classes for Python2.7 and Python 3.5+

Synopsis

You declare a class by listing its fields, and the type of each field

>>> from tdds import Field, Record, seq_of

>>> class Track(Record):
...     title = str
...     total_seconds = int
...
...     @property
...     def duration_str(self):
...         return '%d:%02d' % (self.total_seconds / 60, self.total_seconds % 60)

>>> class Album(Record):
...     artist = str
...     title = str
...     year = Field(int, check=lambda value: 1900 < value < 2050)
...     tracks = seq_of(Track)

You instantiate it and access its fields normally

>>> album = Album(
...     artist='Wah-wah',
...     title='Gyroscope',
...     year=2000,
...     tracks=[
...         Track(title="Elevon", total_seconds=209),
...         Track(title="Gear", total_seconds=514),
...         Track(title="Stringer", total_seconds=413),
...         ],
...     )

>>> album.title
'Gyroscope'

>>> album.tracks[0].duration_str
'3:29'

Record objects are immutable, hashable and comparable.

>>> album.artist = 'Schwah-schwah'
Traceback (most recent call last):
  ...
tdds.basics.RecordsAreImmutable: Album objects are immutable

>>> Track(title='Hull', total_seconds=7) == Track(title='Hull', total_seconds=7)
True

>>> Track(title='Hull', total_seconds=7) == Track(title='Hold', total_seconds=8)
False

The constructor checks the type of each of the given values, and refuses to proceed if the types aren't as declared

>>> Track(title='Fireworks', total_seconds='9')
Traceback (most recent call last):
  ...
tdds.basics.FieldTypeError: Track.total_seconds should be of type int, not str ('9')

There are functions to convert to and from Plain Old Data Structures, i.e. just lists and dicts. This is useful e.g. for JSON serialisation.

>>> pods = album.record_pods()

>>> print(json.dumps(pods, indent=4, sort_keys=True))
{
    "artist": "Wah-wah",
    "title": "Gyroscope",
    "tracks": [
        {
            "title": "Elevon",
            "total_seconds": 209
        },
        {
            "title": "Gear",
            "total_seconds": 514
        },
        {
            "title": "Stringer",
            "total_seconds": 413
        }
    ],
    "year": 2000
}

>>> Album.from_pods(album.record_pods()) == album
True

Records are also picklable

>>> pickle.loads(pickle.dumps(album)) == album
True

The library offers many more features such as automatic type coercion, custom validation functions, enum fields, typed collections, and more. See the tests directory for a specification of sorts.

See also

This project is similar in spirit to these other fine libraries:

but this one is mine.

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

tdds-1.0.tar.gz (35.7 kB view hashes)

Uploaded Source

Built Distribution

tdds-1.0-py3-none-any.whl (45.8 kB view hashes)

Uploaded Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page