Skip to main content

Object tree serialization library for python

Project description

ctor

ctor is an object tree construction and deconstruction library for python>=3.7. It provides non-invasive way of constructing and deconstructing objects based on type annotations.

PyPI - Python Version

Installation:

pip install ctor

Features

  • 0 dependencies
  • Your classes are yours! Library does not mess with your code.
    • No subclassing / metaclassing
    • No special class-level field annotations
    • Library does no replace/generate __init__ and/or other methods
  • Works with dataclasses, attrs, PyDantic and even pure-python classes.
  • Extendable if needed
  • Supports Union, Literal, Annotated, forward references, cyclic-types ...
  • PyCharm and other IDEs highlight constructor arguments natively without plugins
  • Supports Python 3.7+

Example with python dataclasses

from dataclasses import dataclass  # standard python


@dataclass
class MyClass:
  name: str
  value: int

# some_other_file.py
#   note that this import might be in a different file 
#   so that your code remains untouched by serialization logic  
import ctor

# Dumping
my_object = MyClass(name='hello', value=42)
data = ctor.dump(my_object)
print(data)  # {'name': 'hello', 'value': 42}

# Loading
data = {'name': 'World', 'value': -42}
restored_object = ctor.load(MyClass, data)
print(restored_object)  # MyClass(name='world', value=-42)

Nested objects with dataclasses

from dataclasses import dataclass  # standard python
from typing import List


@dataclass
class TreeNode:
  name: str
  children: List['TreeNode']  # Note: forward reference making class cyclic


graph = TreeNode(name="root", children=[
  TreeNode(name="A", children=[]),
  TreeNode(name="B", children=[
    TreeNode(name="x", children=[]),
    TreeNode(name="y", children=[]),
  ]),
  TreeNode(name="C", children=[]),
])

# Note: Even in this complex scenario, classes and data are still untouched by the library code.
import ctor

graph_data = ctor.dump(graph)
print(
  graph_data)  # {'name': 'root', 'children': [{'name': 'A', 'children': []}, {'name': 'B', 'children': [{'name': 'x', 'children': []}, {'name': 'y', 'children': []}]}, {'name': 'C', 'children': []}]}

Bare classes

class User:
  def __init__(self, uid: int, email: str, name: str):
    self.uid = uid
    self.email = email
    self.name = name


class Post:
  def __init__(self, title: str, content: str, author: User):
    self.title = title
    self.content = content
    self.author = author


import ctor  # Import placed here just to highlight that your business-level code still does not require serialization library

data = {
  'content': 'Fields can go in any order also',
  'author': {
    'uid': 123,
    'email': 'john@doe.org',
    'name': 'John Doe'
  },
  'title': 'Unbelievable'
}
post = ctor.load(Post, data)  # post is a normal python object here
print(post.author.name)  # post.user is a User

Note that this is not just Post(**data) because you need to construct User object first. This works with objects of any depth.

Implementation described lower in the README.

Rationale

  • Serialization logic should not be coupled with business logic
  • Business logic should not depend on 3rd party libraries

Implementation

ctor heavily relies on typing annotations and utilizes lots of features from python typing module.

To obtain object schema ctor looks at the signature of the callable you want to construct/deconstruct. Classes are callable, so ctor looks at __init__ method to find information about attributes and annotations, trying to specify a converter for each of the arguments.

About python 3.6 or less

typing became more or less stable only after python 3.7 (including). API for types in 3.6 differs significantly from 3.7 onward.

It is hard to maintain two different APIs that's why I decided to stick to the newer one. However, if you feel brave enough and really need that 3.6 support you can open a PullRequest and contact me if you have any questions.

Running tests

  • To test against current python version: pytest
  • To tests all python versions: tox --parallel

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

ctor-0.3.3.tar.gz (15.8 kB view details)

Uploaded Source

Built Distribution

ctor-0.3.3-py3-none-any.whl (14.7 kB view details)

Uploaded Python 3

File details

Details for the file ctor-0.3.3.tar.gz.

File metadata

  • Download URL: ctor-0.3.3.tar.gz
  • Upload date:
  • Size: 15.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.7.1 importlib_metadata/4.9.0 pkginfo/1.8.2 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.9.0

File hashes

Hashes for ctor-0.3.3.tar.gz
Algorithm Hash digest
SHA256 544ae17a4b487e1b1feeab46369113b3ee234c4d40071054339cda06b94ae3bb
MD5 c7ef9df1a14371e80fa4d8a319510c46
BLAKE2b-256 ea89e132aedf10b3083728b187602fe5f47d1ca1bc976b20827da62edfdd4470

See more details on using hashes here.

File details

Details for the file ctor-0.3.3-py3-none-any.whl.

File metadata

  • Download URL: ctor-0.3.3-py3-none-any.whl
  • Upload date:
  • Size: 14.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.7.1 importlib_metadata/4.9.0 pkginfo/1.8.2 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.9.0

File hashes

Hashes for ctor-0.3.3-py3-none-any.whl
Algorithm Hash digest
SHA256 c06416129119ce1bdeec62599e99116a2673c036764e1c8a15cc3ede63f8eef5
MD5 af21fc856f0ff33e146c123fa765a865
BLAKE2b-256 a77b47a5512f3f5e6daa5ff8d623a61800663934f9d5f9e9d09bddf8bd8c9105

See more details on using hashes here.

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