Skip to main content

Know your object is a attribute type checker

Project description

                       ▄▄          ▄▄                      
▀████▀ ▀███▀          ▄██          ██                 ██   
  ██   ▄█▀             ██                             ██   
  ██ ▄█▀      ▄██▀██▄  ██▄████▄  ▀███  ▄▄█▀██ ▄██▀████████ 
  █████▄     ██▀   ▀██ ██    ▀██   ██ ▄█▀   ███▀  ██  ██   
  ██  ███    ██     ██ ██     ██   ██ ██▀▀▀▀▀▀█       ██   
  ██   ▀██▄  ██▄   ▄██ ██▄   ▄██   ██ ██▄    ▄█▄    ▄ ██   
▄████▄   ███▄ ▀█████▀  █▀█████▀    ██  ▀█████▀█████▀  ▀████
                                ██ ██                      
                                ▀███                       By CenturyBoys
                                
Know your object is a __init__ type validator for class and dataclass

Usage

Kobject can be use inside default class declaration and with dataclasses. Kobject uses the __init__ signature to check types.

Default classes

from kobject import Kobject

class StubClass(Kobject):
    a_int: int
    a_bool: bool
    
    def __init__(
        self,
        a_int: int,
        a_bool: bool
    ):
        self.a_int = a_int
        self.a_bool = a_bool
        self.__post_init__()

instance = StubClass(a_int=1, a_bool=True)

Notice that in the default class declaration you need to call self.__post_init__() at the end of the __init__ declaration.

Dataclass

from dataclasses import dataclass
from kobject import Kobject

@dataclass
class StubClass(Kobject):
    a_int: int
    a_bool: bool

instance = StubClass(a_int=1, a_bool=True)

By default, dataclass calls self.__post_init__() at the end of the __init__ declaration doc.

Exception

Kobject raises TypeError with all validation errors, that means it checks all your object's attributes before raising the TypeError. Types like List and Tuple will have all their elements checked.

from dataclasses import dataclass
from kobject import Kobject
from typing import List, Tuple

@dataclass
class StubClass(Kobject):
    a_list_int: List[int]
    a_tuple_bool: Tuple[bool]

instance = StubClass(a_list_int=[1, "", 2, ""], a_tuple_bool=["", True])
Traceback (most recent call last):
...
TypeError: Class 'StubClass' type error:
 Wrong type for a_list_int: typing.List[int] != '<class 'list'>'
 Wrong type for a_tuple_bool: typing.Tuple[bool] != '<class 'list'>'

You can use lazy validation to improve performance, the code will stop in the first found error for this use

from kobject import Kobject

Kobject.set_lazy_type_check(status=True)

Default value

Kobject supports default values and will check them before any validation, that means if you declare a a_bool: bool = None it will not raise an error.

from dataclasses import dataclass
from kobject import Kobject

class StubClass(Kobject):
    a_bool: bool = None

    def __init__(self, a_bool: bool = 10):
        self.a_bool = a_bool
        self.__post_init__()

@dataclass
class StubDataClass(Kobject):
    a_bool: bool = 10

Custom exception

By default, Kobject raise a TypeError but you can override this exception using set_validation_custom_exception for type validation or set_content_check_custom_exception for field check on from JSON operation.

from dataclasses import dataclass
from kobject import Kobject


class CustomException(Exception):
    pass


Kobject.set_validation_custom_exception(CustomException)
#Kobject.set_content_check_custom_exception(CustomException)

@dataclass
class StubClass(Kobject):
    a__int: int


instance = StubClass(a__int="")
Traceback (most recent call last):
...
CustomException: Class 'StubClass' type error:
 Wrong type for a__int: <class 'int'> != '<class 'str'>'

ToJSON

Kobject has his own implementation to parse class instance to a JSON representation.

from dataclasses import dataclass
from typing import List, Tuple

from kobject import Kobject
    
@dataclass
class BaseC(Kobject):
    a_int: int
    a_str: str
    a_list_of_int: List[int]
    a_tuple_of_bool: Tuple[bool]
    
instance = BaseC(
    a_int=1,
    a_str="lala",
    a_list_of_int=[1, 2, 3],
    a_tuple_of_bool=(True,)
)

json_bytes = instance.to_json()

print(json_bytes)
b'{"a_int": 1, "a_str": "lala", "a_list_of_int": [1, 2, 3], "a_tuple_of_bool": [true]}'

For complex values ToJSON expose set_encoder_resolver to handler it.

Notest, Before encoding the object to JSON bytes, it will be represented by self.dict(). Some objects, such as datetime.datetime, can be useful in dictionary structures but are not JSON serializable. In such cases, you can use the on_dict: bool parameter in the Kobject.set_encoder_resolver() method to encode only when JSON bytes are required, not in its dictionary representation.

from dataclasses import dataclass
from datetime import datetime
from typing import List
from uuid import UUID

from kobject import Kobject


@dataclass
class BaseA(Kobject):
    a_datetime: datetime


@dataclass
class BaseB:
    a_uuid: UUID


@dataclass
class BaseC(Kobject):
    a_base_a: BaseA
    a_base_b: BaseB
    a_list_of_base_a: List[BaseA]

Kobject.set_encoder_resolver(datetime, lambda value: str(value), False)
Kobject.set_encoder_resolver(BaseB, lambda value: {"a_uuid": str(value.a_uuid)})

instance = BaseC(
    a_base_a=BaseA(a_datetime=datetime.fromisoformat("2023-02-01 17:38:45.389426")),
    a_base_b=BaseB(a_uuid=UUID("1d9cf695-c917-49ce-854b-4063f0cda2e7")),
    a_list_of_base_a=[BaseA(a_datetime=datetime.fromisoformat("2023-02-01 17:38:45.389426"))]
)

dict_repr = instance.dict()

isinstance(dict_repr["a_base_a"]["a_datetime"], datetime)

json_bytes = instance.to_json()

print(json_bytes)
b'{"a_base_a": {"a_datetime": "2023-02-01 17:38:45.389426"}, "a_base_b": {"a_uuid": "1d9cf695-c917-49ce-854b-4063f0cda2e7"}, "a_list_of_base_a": [{"a_datetime": "2023-02-01 17:38:45.389426"}]}'

FromJSON

Kobject has his own implementation to parse JSON to a class instance.

from dataclasses import dataclass
from typing import List, Tuple

from kobject import Kobject


@dataclass
class BaseC(Kobject):
    a_int: int
    a_str: str
    a_list_of_int: List[int]
    a_tuple_of_bool: Tuple[bool]

payload = (
    b'{"a_int": 1,"a_str": "lala","a_list_of_int": [1,2,3],'
    b'"a_tuple_of_bool": [true]}'
)
instance = BaseC.from_json(payload=payload)

print(instance)
BaseC(a_int=1, a_str='lala', a_list_of_int=[1, 2, 3], a_tuple_of_bool=(True,))

For complex values FromJSON expose set_decoder_resolver to handler it.

from datetime import datetime
from dataclasses import dataclass
from typing import List
from uuid import UUID

from kobject import Kobject


@dataclass
class BaseA(Kobject):
    a_datetime: datetime


@dataclass
class BaseB:
    a_uuid: UUID


@dataclass
class BaseC(Kobject):
    a_base_a: BaseA
    a_base_b: BaseB
    a_list_of_base_a: List[BaseA]

Kobject.set_decoder_resolver(
    datetime,
    lambda attr_type, value: datetime.fromisoformat(value)
    if isinstance(value, str)
    else value,
)
Kobject.set_decoder_resolver(
    BaseB,
    lambda attr_type, value: attr_type(a_uuid=UUID(value["a_uuid"]))
    if isinstance(value, dict)
    else value,
)
payload = (
    b'{"a_base_a": {"a_datetime": "2023-02-01 17:38:45.389426"},"a_base_b": {"a_'
    b'uuid":"1d9cf695-c917-49ce-854b-4063f0cda2e7"}, "a_lis'
    b't_of_base_a": [{"a_datetime": "2023-02-01 17:38:45.389426"}]}'
)
instance = BaseC.from_json(payload=payload)

print(instance)
BaseC(a_base_a=BaseA(a_datetime=datetime.datetime(2023, 2, 1, 17, 38, 45, 389426)), a_base_b=BaseB(a_uuid=UUID('1d9cf695-c917-49ce-854b-4063f0cda2e7')), a_list_of_base_a=[BaseA(a_datetime=datetime.datetime(2023, 2, 1, 17, 38, 45, 389426))])

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

kobject-0.6.2.tar.gz (10.5 kB view details)

Uploaded Source

Built Distribution

kobject-0.6.2-py3-none-any.whl (11.6 kB view details)

Uploaded Python 3

File details

Details for the file kobject-0.6.2.tar.gz.

File metadata

  • Download URL: kobject-0.6.2.tar.gz
  • Upload date:
  • Size: 10.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.1.2 CPython/3.13.3 Linux/6.1.0-37-amd64

File hashes

Hashes for kobject-0.6.2.tar.gz
Algorithm Hash digest
SHA256 b115f7c67faf4ffe620e648b9a4fb2b007a430d1bfcb212a6733d56b503ea5fe
MD5 73f73ea7901fe0ea6db792df754af832
BLAKE2b-256 51964163e60d8c963e256c3201dc6316633c26532c8a1b58a6f78f11ad4ebcd2

See more details on using hashes here.

File details

Details for the file kobject-0.6.2-py3-none-any.whl.

File metadata

  • Download URL: kobject-0.6.2-py3-none-any.whl
  • Upload date:
  • Size: 11.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.1.2 CPython/3.13.3 Linux/6.1.0-37-amd64

File hashes

Hashes for kobject-0.6.2-py3-none-any.whl
Algorithm Hash digest
SHA256 4d15a7194d5174ceefa88ee396ac1367107ac03d849805ef72b5067b328c0674
MD5 cb5e6448173a5a56fdcf0c24e77a927b
BLAKE2b-256 466613f988bc80b6ab7b818f011107451bc290e8223bf05945e345d01473b84f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page