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

Uploaded PyPy Windows x86-64

python_datamodel-0.6.24-pp39-pypy39_pp73-win_amd64.whl (831.4 kB view details)

Uploaded PyPy Windows x86-64

python_datamodel-0.6.24-cp312-cp312-win_amd64.whl (876.1 kB view details)

Uploaded CPython 3.12 Windows x86-64

python_datamodel-0.6.24-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.6.24-cp311-cp311-win_amd64.whl (882.0 kB view details)

Uploaded CPython 3.11 Windows x86-64

python_datamodel-0.6.24-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.6.24-cp310-cp310-win_amd64.whl (880.4 kB view details)

Uploaded CPython 3.10 Windows x86-64

python_datamodel-0.6.24-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.6.24-cp39-cp39-win_amd64.whl (882.0 kB view details)

Uploaded CPython 3.9 Windows x86-64

python_datamodel-0.6.24-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.6.24-pp310-pypy310_pp73-win_amd64.whl.

File metadata

File hashes

Hashes for python_datamodel-0.6.24-pp310-pypy310_pp73-win_amd64.whl
Algorithm Hash digest
SHA256 540fae363d5efb1c033bd2c7582e732c806ead09943795eba1234ab4c7c49dda
MD5 9afe742e6c7997fe48ea4e858cef99bd
BLAKE2b-256 fd294d8bc449dbe38b4f43574b596a82e172ed5f53bd54305d5fcca4ee1230df

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for python_datamodel-0.6.24-pp39-pypy39_pp73-win_amd64.whl
Algorithm Hash digest
SHA256 c6e0c9443a4c1b576918efb65c657bed8f6f07eb6d2424f5c1170853327a427d
MD5 0f1722a8811b75c063497a52c5b157e0
BLAKE2b-256 b979f3efcea886603194c0e2a69e57187a89a95bf7d92cfb823cc139ba388f01

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for python_datamodel-0.6.24-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 1c367dc9f9043039d8c8e67315ad6cb4a94ae6118e1e2deeb1796a3db2c2d810
MD5 89afdf370598b77fe6e3f5c21c9eb35d
BLAKE2b-256 26b3fbdff6c61326a9eba4d975d153a8c790d5682d2db580842f6073a0d43738

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for python_datamodel-0.6.24-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 149747c543ac0d3c925c58de73b8570cbd35026190bed149a6622c955c6a5a35
MD5 272e5a0c5cf18ac1dfa619e408380f3f
BLAKE2b-256 3b123955f31b40d57d33cc21bd9bb99fe4506c84ee01113be1291c572548ab4e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for python_datamodel-0.6.24-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 084c3643bb2393eba07ff0dd76b6735bdfca68d57a63df9d2495fae018490143
MD5 3bc5693f2ba98f7247edc084a1601f0d
BLAKE2b-256 7aa57dd1943055679c6501bea4d05e1dc4994a6ca1e31a8f2430283660f33482

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for python_datamodel-0.6.24-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 09fbe7f34ab3b0672831ad08c830c6ab423c25987cb515f13ac934e86a58ccec
MD5 8c20f05e8762f6765a4a434ee9b6bb68
BLAKE2b-256 1434ef82c6c51727bcd728e4b5d06e21c24105a41c9f20e85616bba9bd414ba6

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for python_datamodel-0.6.24-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 9ed396c69ce37b0b7bd4ad131d7de9d58fde94d674c3fc3f33250e521507817b
MD5 d39923d4ae424e18d3bc8f2af64a8775
BLAKE2b-256 15ef2d397637ff6faafe818ec9a8c77e8fa9940c0eab5477a1461573d0172c60

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for python_datamodel-0.6.24-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 970a4a23b7d6e36f0ef228d1c6a97e6de162ea6d514d723d52e62ace7c2d344f
MD5 7772c59e927a60fcc91dbcd83d78b739
BLAKE2b-256 b77586684046e997729fc5a1f279764539b66b9223072df1c4a57177739b4ce8

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for python_datamodel-0.6.24-cp39-cp39-win_amd64.whl
Algorithm Hash digest
SHA256 5d4ce86d549690f94ea3b6534c954a5821559b7d0a273b7099b4c1ef10b82d45
MD5 f98eccdb43847621053d66ceb0dd3910
BLAKE2b-256 1c6edfdac7176137b63f32e1de3e309c484ff15985ca3acb0de3f9c163d52f47

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for python_datamodel-0.6.24-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 cd9f64de3d2fb5112ad85861a2d20c448bed4015115b7e297d601e47d9f79bf9
MD5 5fab062658ae1fa2b0f6da2bda5cf91d
BLAKE2b-256 9207c78196af7b7bcbb0b78fa1f5d0ad2d4203ff3345dd67dbd607092ca09e49

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