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

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

Uploaded PyPy Windows x86-64

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

Uploaded PyPy Windows x86-64

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

Uploaded CPython 3.13 Windows x86-64

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

Uploaded CPython 3.12 Windows x86-64

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

Uploaded CPython 3.11 Windows x86-64

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

Uploaded CPython 3.10 Windows x86-64

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

Uploaded CPython 3.9 Windows x86-64

python_datamodel-0.7.2-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.2-pp310-pypy310_pp73-win_amd64.whl.

File metadata

File hashes

Hashes for python_datamodel-0.7.2-pp310-pypy310_pp73-win_amd64.whl
Algorithm Hash digest
SHA256 22b244fdccf3809b7ecab79a9c8f707b708d96b4b1f4bfcdfa680ff17fa8b11c
MD5 7e4da43676bdd7220e769326d2dfb2b3
BLAKE2b-256 781011bacbced4c4467e1c7b01cc0787db6a37996f54962a936de3d03ac74667

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for python_datamodel-0.7.2-pp39-pypy39_pp73-win_amd64.whl
Algorithm Hash digest
SHA256 f582bc88036efbd67160c1fadbb8845f6cc4889e3b2379c663d0e21db2d4a6c8
MD5 21c2c67de5c5ca5ff9115cff47f7ca39
BLAKE2b-256 f55aeda0300ccaa802dc417c6ce59a210c20fb793fd453afeb189633ea9d1a40

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for python_datamodel-0.7.2-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 d190502fea2a574d1683bb68b3f25016cd9610e23e038f94aa34d8be0f75e779
MD5 74389fe9065f059d4e5392d6b5012fad
BLAKE2b-256 2ab6231a5ba9b6351e01f0249b2ef0a1edd0ce7e08080980dc87ee8b77496a72

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for python_datamodel-0.7.2-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 b311165b47893895c5db82a52ad83d1ad0ac2eb05e47a4dad80e7b75e5d8b4df
MD5 b6eae7d38fb9de1c82a67c1eca69dfc2
BLAKE2b-256 b4bbc9867d27fbded76c99b6700844dbf9c03513c57872feda5f02a8a04b3e62

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for python_datamodel-0.7.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 bb2aff3e0a8dc7debde1c80d38e232ee7fd308ddc0ad3bb80f7a2020fce9f111
MD5 2396385793d3efe07cb1225afdc1aa4f
BLAKE2b-256 5e6b4909ae79c446c6c32befdf426368c9bc96e2b33d993b1748c6f1b7e9b335

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for python_datamodel-0.7.2-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 03c0c77cc0fe353aec64d4ab5c492c110f0149d90a4f5a09ab4cdfdf755d640a
MD5 62357fefa1d9904024065ecd0a9451ee
BLAKE2b-256 384d6c43393fed48ed439823f355035b6e6a2b8629dd29db2b3b87698116fbd4

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for python_datamodel-0.7.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 3c66164fa7d44535d55b62e7ad84a75852f3b61dc021f576ba824afc99ef334e
MD5 5edf583146d8f6fdfadb0f2c41774269
BLAKE2b-256 24cb0f4a4b73ca17ebdc37b63403b2dad9ff84dc89671cc2cf01c25c28c8e164

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for python_datamodel-0.7.2-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 fdd7806e04e6e9e6a70054c12c4c4baccf0c6280673b3034351928db92913469
MD5 5e405980f2d22820e2b9e05074070f5e
BLAKE2b-256 75035ff6d51d7eb8420ba4ca203d9c366e2c3d4283a89051cea7384590e6991e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for python_datamodel-0.7.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 fdb4a1bb1c98aac512aeda08a366600590b288086c30f7c62934063e5d68e89f
MD5 69414a7f0fdea547f2b20e8cba39a283
BLAKE2b-256 89e4637ca49df5c3bb911e6239cbf3c4fe9901da24ebc5fe8ed211174220715d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for python_datamodel-0.7.2-cp39-cp39-win_amd64.whl
Algorithm Hash digest
SHA256 ef08b816a1571ff4c6e8720c81db2312e797840aa392ae7a3ae9298584f7fb1c
MD5 1811d0d2a3e5e1f9e35e9763922b1a54
BLAKE2b-256 21bd6b32ddea1f8fb5677368b877518e788f37107eeb68c0c1ddff5d2b7ae1e1

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for python_datamodel-0.7.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 901aa800e9c508d8008728015667df6b43c5df683ce8e2a9bc02dbff9663f2e9
MD5 4885ded78628d2a96b6fccdaa3f17ae6
BLAKE2b-256 89d94863fe495c8032211ae01db5b3d7c852eb8b4b53d4f81a5e18d4448e52fe

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