Skip to main content

simple library based on python +3.8 to use Dataclass-syntaxfor interacting with Data

Project description

DataModel

DataModel is a simple library based on python +3.8 to use Dataclass-syntax for interacting with Data, using the same syntax of Dataclass, users can write Python Objects and work with Data in the same way (like ORM's), is a reimplementation of python Dataclasses supporting true inheritance (without decorators), true composition and other good features.

The key features are:

  • Easy to use: No more using decorators, concerns abour re-ordering attributes or common problems with using dataclasses with inheritance.
  • Extensibility: Can use other dataclasses, Data objects or primitives as data-types.
  • Fast: DataModel is a replacement 100% full compatible with dataclasses, without any overhead.

Requirements

Python 3.8+

Installation

$ pip install python-datamodel
---> 100%
Successfully installed datamodel

Quickstart

from datamodel import Field, BaseModel
from dataclasses import dataclass, fields, is_dataclass


# This pure Dataclass:
@dataclass
class Point:
    x: int = Field(default=0, min=0, max=10)
    y: int = Field(default=0, min=0, max=10)

point = Point(x=10, y=10)
print(point)
print(fields(point))
print('IS a Dataclass?: ', is_dataclass(point))

# Can be represented by BaseModel
class newPoint(BaseModel):
    x: int = Field(default=0, min=0, max=10)
    y: int = Field(default=0, min=0, max=10)

    def get_coordinate(self):
        return (self.x, self.y)

point = newPoint(x=10, y=10)
print(point)
print(fields(point))
print('IS a Dataclass?: ', is_dataclass(point))
print(point.get_coordinate())

Supported types

DataModel support recursive transformation of fields, so you can easily work with nested dataclasses or complex types.

DataModel supports automatic conversion of:

  • datetime objects. datetime objects are encoded to str exactly like orjson conversion, any str typed as datetime is decoded to datetime. The same behavior is used to decoding time, date and timedelta objects.

  • UUID objects. They are encoded as str (JSON string) and decoded back to uuid.UUID objects.

  • Decimal objects. They are also encoded as float and decoded back to Decimal.

Also, "custom" encoders are supported.

import uuid
from typing import (
    List,
    Optional,
    Union
)
from dataclasses import dataclass, field
from datamodel import BaseModel, Field

@dataclass
class Point:
    x: int = Field(default=0, min=0, max=10)
    y: int = Field(default=0, min=0, max=10)

class coordinate(BaseModel, intSum):
    latitude: float
    longitude: float

    def get_location(self) -> tuple:
        return (self.latitude, self.longitude)

def auto_uid():
    return uuid.uuid4()

def default_rect():
    return [0,0,0,0]

def valid_zipcode(field, value):
    return value > 1000

class Address(BaseModel):
    id: uuid.UUID = field(default_factory=auto_uid)
    street: str = Field(required=True)
    zipcode: int = Field(required=False, default=1010, validator=valid_zipcode)
    location: Optional[coordinate]
    box: List[Optional[Point]]
    rect: List[int] = Field(factory=default_rect)


addr = Address(street="Calle Mayor", location=(18.1, 22.1), zipcode=3021, box=[(2, 10), (4, 8)], rect=[1, 2, 3, 4])
print('IS a Dataclass?: ', is_dataclass(addr))

print(addr.location.get_location())
# returns
Address(id=UUID('24b34dd5-8d35-4cfd-8916-7876b28cdae3'), street='Calle Mayor', zipcode=3021, location=coordinate(latitude=18.1, longitude=22.1), box=[Point(x=2, y=10), Point(x=4, y=8)], rect=[1, 2, 3, 4])
  • Fast and convenience conversion from-to JSON (using orjson):
import orjson

b = addr.json()
print(b)
{"id":"24b34dd5-8d35-4cfd-8916-7876b28cdae3","street":"Calle Mayor","zipcode":3021,"location":{"latitude":18.1,"longitude":22.1}, "box":[{"x":2,"y":10},{"x":4,"y":8}],"rect":[1,2,3,4]}
# and re-imported from json
new_addr = Address.from_json(b) # load directly from json string
# or using a dictionary decoded by orjson
data = orjson.loads(b)
new_addr = Address(**data)

Inheritance

python-datamodel supports inheritance of classes.

import uuid
from typing import Union, List
from dataclasses import dataclass, field
from datamodel import BaseModel, Column, Field


def auto_uid():
    return uuid.uuid4()

class User(BaseModel):
    id: uuid.UUID = field(default_factory=auto_uid)
    name: str
    first_name: str
    last_name: str


@dataclass
class Address:
    street: str
    city: str
    state: str
    zipcode: str
    country: Optional[str] = 'US'

    def __str__(self) -> str:
        """Provides pretty response of address"""
        lines = [self.street]
        lines.append(f"{self.city}, {self.zipcode} {self.state}")
        lines.append(f"{self.country}")
        return "\n".join(lines)

class Employee(User):
    """
    Base Employee.
    """
    role: str
    address: Address # composition of a dataclass inside of DataModel is possible.

# Supporting multiple inheritance and composition
# Wage Policies
class MonthlySalary(BaseModel):
    salary: Union[float, int]

    def calculate_payroll(self) -> Union[float, int]:
        return self.salary

class HourlySalary(BaseModel):
    salary: Union[float, int] = Field(default=0)
    hours_worked: Union[float, int] = Field(default=0)

    def calculate_payroll(self) -> Union[float, int]:
        return (self.hours_worked * self.salary)

# employee types
class Secretary(Employee, MonthlySalary):
    """Secretary.

    Person with montly salary policy and no commissions.
    """
    role: str = 'Secretary'

class FactoryWorker(Employee, HourlySalary):
    """
    FactoryWorker is an employee with hourly salary policy and no commissions.
    """
    role: str = 'Factory Worker'

class PayrollSystem:
    def calculate_payroll(self, employees: List[dataclass]) -> None:
        print('=== Calculating Payroll === ')
        for employee in employees:
            print(f"Payroll for employee {employee.id} - {employee.name}")
            print(f"- {employee.role} Amount: {employee.calculate_payroll()}")
            if employee.address:
                print('- Sent to:')
                print(employee.address)
            print("")

jane = Secretary(name='Jane Doe', first_name='Jane', last_name='Doe', salary=1500)
bob = FactoryWorker(name='Bob Doyle', first_name='Bob', last_name='Doyle', salary=15, hours_worked=40)
mitch = FactoryWorker(name='Mitch Brian', first_name='Mitch', last_name='Brian', salary=20, hours_worked=35)

payroll = PayrollSystem()
payroll.calculate_payroll([jane, bob, mitch])

A sample of output:

```console
=== Calculating Payroll ===
Payroll for employee 745a2623-d4d2-4da6-bf0a-1fa691bafd33 - Jane Doe
- Secretary Amount: 1500
- Sent to:
Rodeo Drive, Rd
Los Angeles, 31050 CA
US

Contributing

First of all, thank you for being interested in contributing to this library. I really appreciate you taking the time to work on this project.

  • If you're just interested in getting into the code, a good place to start are issues tagged as bugs.
  • If introducing a new feature, especially one that modifies the public API, consider submitting an issue for discussion before a PR. Please also take a look at existing issues / PRs to see what you're proposing has already been covered before / exists.
  • I like to follow the commit conventions documented here

License

This project is licensed under the terms of the BSD v3. license.

Project details


Release history Release notifications | RSS feed

This version

0.7.4

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

python_datamodel-0.7.4-pp310-pypy310_pp73-win_amd64.whl (835.1 kB view details)

Uploaded PyPy Windows x86-64

python_datamodel-0.7.4-pp39-pypy39_pp73-win_amd64.whl (834.8 kB view details)

Uploaded PyPy Windows x86-64

python_datamodel-0.7.4-cp313-cp313-win_amd64.whl (876.7 kB view details)

Uploaded CPython 3.13 Windows x86-64

python_datamodel-0.7.4-cp312-cp312-win_amd64.whl (879.0 kB view details)

Uploaded CPython 3.12 Windows x86-64

python_datamodel-0.7.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.4 MB view details)

Uploaded CPython 3.12 manylinux: glibc 2.17+ x86-64

python_datamodel-0.7.4-cp311-cp311-win_amd64.whl (884.1 kB view details)

Uploaded CPython 3.11 Windows x86-64

python_datamodel-0.7.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.3 MB view details)

Uploaded CPython 3.11 manylinux: glibc 2.17+ x86-64

python_datamodel-0.7.4-cp310-cp310-win_amd64.whl (882.3 kB view details)

Uploaded CPython 3.10 Windows x86-64

python_datamodel-0.7.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.2 MB view details)

Uploaded CPython 3.10 manylinux: glibc 2.17+ x86-64

python_datamodel-0.7.4-cp39-cp39-win_amd64.whl (883.8 kB view details)

Uploaded CPython 3.9 Windows x86-64

python_datamodel-0.7.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.2 MB view details)

Uploaded CPython 3.9 manylinux: glibc 2.17+ x86-64

File details

Details for the file python_datamodel-0.7.4-pp310-pypy310_pp73-win_amd64.whl.

File metadata

File hashes

Hashes for python_datamodel-0.7.4-pp310-pypy310_pp73-win_amd64.whl
Algorithm Hash digest
SHA256 8c33b6908c0f3b6f7082b2b717558842c610a5213d1b9c4059c84e8407d23a6c
MD5 cc729d3fa55df2f84ffa61a6a6899c5e
BLAKE2b-256 e3f01ac2a1d0157797be5716985cae1f55d66a95dafcfde0eba8394bfa294a70

See more details on using hashes here.

File details

Details for the file python_datamodel-0.7.4-pp39-pypy39_pp73-win_amd64.whl.

File metadata

File hashes

Hashes for python_datamodel-0.7.4-pp39-pypy39_pp73-win_amd64.whl
Algorithm Hash digest
SHA256 7e5dd17e2da1f0b78970263a04f4e35dc57436f59e2dc48c5822a52a59111456
MD5 2811bc8eb166a127134b74627e1ea44f
BLAKE2b-256 5ab05763a80cd244959742aa22381ab9f9aaaa1b74c9984328344bd698b95b3f

See more details on using hashes here.

File details

Details for the file python_datamodel-0.7.4-cp313-cp313-win_amd64.whl.

File metadata

File hashes

Hashes for python_datamodel-0.7.4-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 2cb7c7c4d848928399dd2a70e9eaad476d80ad9119d87da506eb748e7b239dc1
MD5 bf9e89777814a34e41bc74a0ae112ac1
BLAKE2b-256 175c538c6de4aa9dfb1f5e568c0ae6284a44532f452e3acec05b91d23aad3733

See more details on using hashes here.

File details

Details for the file python_datamodel-0.7.4-cp312-cp312-win_amd64.whl.

File metadata

File hashes

Hashes for python_datamodel-0.7.4-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 c4edb2e42969eee1b3e19e6b456f5f40c9834d1a20c097e0f085c776ce0f2045
MD5 7b77632f3f8c22c6820caf0f16d78d9d
BLAKE2b-256 44bdbeb0bc17f6365f194e52f8523dda5b9ff5f433fe696dfd66ecf78f6aa2ad

See more details on using hashes here.

File details

Details for the file python_datamodel-0.7.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for python_datamodel-0.7.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 94dcfb4df15a1ace809d90379d93303636b41d4b7837c6d77af671d7e7faf6a7
MD5 1592f617b154645c8aa43e5928d2a06c
BLAKE2b-256 8c56b316ef869083cbccaffc6f72b8129b97dae36b58ee3967978e464c3bff33

See more details on using hashes here.

File details

Details for the file python_datamodel-0.7.4-cp311-cp311-win_amd64.whl.

File metadata

File hashes

Hashes for python_datamodel-0.7.4-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 527dc13473bc31d62b0044bea7d75c726d479b8a2b2c8a8ea4663b276c693874
MD5 15e93d63be837e2bd349395660ed99de
BLAKE2b-256 4c592c60b5499f80bbfcf1153e72487c975ae0b8fa9fd9472b8f35fae89db4aa

See more details on using hashes here.

File details

Details for the file python_datamodel-0.7.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for python_datamodel-0.7.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 fbf17d515be4435c6649670420894ebe9b52afac859073db233730914adda273
MD5 0ad428dfabd558f429a604ce205f12c4
BLAKE2b-256 9072df16144ef3a7acdc8f933a6c1e33a8bf03f4a3f0dd7aff63e835f407947a

See more details on using hashes here.

File details

Details for the file python_datamodel-0.7.4-cp310-cp310-win_amd64.whl.

File metadata

File hashes

Hashes for python_datamodel-0.7.4-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 10fcde9380f28fab34c501977c463181a4cc88c5e023c4ac25450577e81d6611
MD5 df0db6aa87479b8a080a63bdf0a6823e
BLAKE2b-256 dc720d478e1c8981d8bf21e13329c1790a199f9b67f7e2ebbac8cd5fa1c0ee28

See more details on using hashes here.

File details

Details for the file python_datamodel-0.7.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for python_datamodel-0.7.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 9fae2a6123f69849f38ef0a05ed86f91b007e849451fd84de09313c0b5916e0f
MD5 13ab01a782088252b62c79c8c0a5d96c
BLAKE2b-256 a7664f6fda79f7d7fc1ee66251ac900ba88797097d0eaf27392f7c79b2c99c5a

See more details on using hashes here.

File details

Details for the file python_datamodel-0.7.4-cp39-cp39-win_amd64.whl.

File metadata

File hashes

Hashes for python_datamodel-0.7.4-cp39-cp39-win_amd64.whl
Algorithm Hash digest
SHA256 81da515a81d12d2da9f6bc9e229680e76bf2965fea9a4e1af501580428330e7b
MD5 132305d743b3a3b6c414ab08645b9db4
BLAKE2b-256 2622490555220734ed76f03cc8aced1e9cdc17a7d22cb3550cfcc994be5bdb95

See more details on using hashes here.

File details

Details for the file python_datamodel-0.7.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for python_datamodel-0.7.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 d7ab593fa8faa5460a1b23a0f7d12ffbd4fbe3967db1145adaeb8119fdae8f66
MD5 1030e2e5638a906a6757c35fd37bafcd
BLAKE2b-256 76244c7895e4a512417b18fce5236b8dc0aa422d189a57753fb3df6f21bd0cd4

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