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.3

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.3-pp310-pypy310_pp73-win_amd64.whl (835.0 kB view details)

Uploaded PyPy Windows x86-64

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

Uploaded PyPy Windows x86-64

python_datamodel-0.7.3-cp313-cp313-win_amd64.whl (876.6 kB view details)

Uploaded CPython 3.13 Windows x86-64

python_datamodel-0.7.3-cp312-cp312-win_amd64.whl (878.9 kB view details)

Uploaded CPython 3.12 Windows x86-64

python_datamodel-0.7.3-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.3-cp311-cp311-win_amd64.whl (884.0 kB view details)

Uploaded CPython 3.11 Windows x86-64

python_datamodel-0.7.3-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.3-cp310-cp310-win_amd64.whl (882.2 kB view details)

Uploaded CPython 3.10 Windows x86-64

python_datamodel-0.7.3-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.3-cp39-cp39-win_amd64.whl (883.8 kB view details)

Uploaded CPython 3.9 Windows x86-64

python_datamodel-0.7.3-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.3-pp310-pypy310_pp73-win_amd64.whl.

File metadata

File hashes

Hashes for python_datamodel-0.7.3-pp310-pypy310_pp73-win_amd64.whl
Algorithm Hash digest
SHA256 684048386275e5c1d74aebe546f347b8f21a0ac30cb7a0ee37eeef3916d90065
MD5 7ef63a52d452d4675195c18f14ddc47a
BLAKE2b-256 89411406df526ce61a80b90d48a5f54be5dad5055af6a685998b7b5ae84b2653

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for python_datamodel-0.7.3-pp39-pypy39_pp73-win_amd64.whl
Algorithm Hash digest
SHA256 1289736c47420005a31067bef4ccea5841ee037417c8ba44fe35fd703abb4950
MD5 f0961c7f0e626f93ed5e6e6f4847938a
BLAKE2b-256 9bf225df345e85a1e62c4a06b007e25762c36f31a9f0646f455eb1735723f9e7

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for python_datamodel-0.7.3-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 56125c9db4b2625cf2e3ed3b4acb63c0383af8829556c2627b5a077dbe3b8c0b
MD5 4f4413a0bdad6b1c03ba262dcd5d8e00
BLAKE2b-256 59a0d68065f5ceb6c57d0141efaaa1838402a42cbda18e19cfec5f68aaa41031

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for python_datamodel-0.7.3-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 aa1ce7b34426f75b97b985cb6f4e5c025bbeb459e9cc671f4eec7833f82b9d52
MD5 761aa052695cee3100d8e6337e809b37
BLAKE2b-256 15fdb7b5a08cef8fe1816910e49311c5ee569f23e77303396666f105a4b93fc7

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for python_datamodel-0.7.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 f465c0b41f26b70176b79d8e710f5043cdc413611fbd86764f7334a53d988755
MD5 75d9145a1b8dd3af478a6ea673ae50ce
BLAKE2b-256 9f97718daf032df8aa539aba1f067c0a715a2d8f0905d291ed3e258891583626

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for python_datamodel-0.7.3-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 84cb50b994536ced2b6daa7313374529b64b45c14cc8cfb9356abbd3c6194575
MD5 c3290f8f0bde45f9433e9bb800859e91
BLAKE2b-256 2179046b36a461994fae9faf94a5e89349e85ec91bad87ed2fda1edfe830e4c8

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for python_datamodel-0.7.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 7b8f389a83d2105300785fa451164438fcb30d52b4653e2d2b54f07466d4aeb4
MD5 cdae36f268ea32b244c821dbc6b69fa3
BLAKE2b-256 612ac0cdb3ae2d0329d492680d9bf22c8e2ed1d38fcfb08eea820d2fe5d02466

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for python_datamodel-0.7.3-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 b9c5ebc160ac0772e3fe286e686df8d3c9a5316a055f97b89363ed02b4c78d66
MD5 c96ad087fbe713525de50cf3ac930a85
BLAKE2b-256 2113a8766a2a3689e75b755251189e9d07075c61c5fbe60763535f42aee6a3cd

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for python_datamodel-0.7.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 c241c63274a3c97d7af00efd8114f83918547613a4da845ab3b1af8797fb82e1
MD5 213bde36f0dd1f0ca438dd5094bbd70f
BLAKE2b-256 35772ddf68086a407b3fddf565945f13d2bc5ad7d826d4bffa3b968b61f17860

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for python_datamodel-0.7.3-cp39-cp39-win_amd64.whl
Algorithm Hash digest
SHA256 8f2d5f45e80b5f2876c59e0e58ba42892bd3c626a4064571915e359974323c63
MD5 eb050fb0dfd92ce6e085e8d81601c278
BLAKE2b-256 ff110a469acee846089d0c7e23c5c6dd271a09032765d1128ddc9c32511d33b2

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for python_datamodel-0.7.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 2b726713dbe63b68bcfaf38146ca11ef8d145c1125d908bfc107d5d231680947
MD5 e488ed266f72d003d981ded3da281cc3
BLAKE2b-256 fd62d6308327266996ae0c1b28e48f91b992804d426ee9b455f7205945ab96cf

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