Add helpers module
This commit is contained in:
parent
a6b8d7f2d3
commit
8f2e0f5db9
11
setup.py
Normal file
11
setup.py
Normal file
@ -0,0 +1,11 @@
|
||||
from setuptools import setup, find_packages
|
||||
|
||||
setup(
|
||||
name="spqr.kieran",
|
||||
version="0.0.1",
|
||||
author="Maks Snegov",
|
||||
author_email="snegov@spqr.link",
|
||||
description="Helpers for SPQR projects",
|
||||
packages=find_packages(),
|
||||
python_requires=">=3.8",
|
||||
)
|
||||
6
spqr/kieran/__init__.py
Normal file
6
spqr/kieran/__init__.py
Normal file
@ -0,0 +1,6 @@
|
||||
from .helpers import (
|
||||
nested_dataclass,
|
||||
ExtraDataclass,
|
||||
singleton,
|
||||
ConstEnum
|
||||
)
|
||||
95
spqr/kieran/helpers.py
Normal file
95
spqr/kieran/helpers.py
Normal file
@ -0,0 +1,95 @@
|
||||
from dataclasses import dataclass, is_dataclass, fields, asdict
|
||||
from enum import Enum
|
||||
from typing import Sequence
|
||||
|
||||
|
||||
def nested_dataclass(*args, **kwargs):
|
||||
def wrapper(cls):
|
||||
cls = dataclass(cls, **kwargs)
|
||||
original_init = cls.__init__
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
for name, value in kwargs.items():
|
||||
field_type = cls.__annotations__.get(name, None)
|
||||
if is_dataclass(field_type) and isinstance(value, dict):
|
||||
new_obj = field_type(**value)
|
||||
kwargs[name] = new_obj
|
||||
original_init(self, *args, **kwargs)
|
||||
|
||||
cls.__init__ = __init__
|
||||
return cls
|
||||
|
||||
return wrapper(args[0]) if args else wrapper
|
||||
|
||||
|
||||
@dataclass
|
||||
class ExtraDataclass:
|
||||
@classmethod
|
||||
def from_dict(cls, data: dict):
|
||||
""" Create dataclass from dict ignoring extra arguments. """
|
||||
cl_fields = set([f.name for f in fields(cls)])
|
||||
filtered_data = dict()
|
||||
for k, v in data.items():
|
||||
if k in cl_fields:
|
||||
filtered_data[k] = v
|
||||
return cls(**filtered_data)
|
||||
|
||||
@classmethod
|
||||
def from_list(cls, ent_list: Sequence[dict]) -> list:
|
||||
""" Create list of dataclass instances from list of dicts. """
|
||||
return [cls.from_dict(ent) for ent in ent_list]
|
||||
|
||||
def to_dict(self) -> dict:
|
||||
""" Returns dict with not None values """
|
||||
return asdict(
|
||||
self, dict_factory=lambda d: {k: v for k, v in d if v is not None}
|
||||
)
|
||||
|
||||
|
||||
def singleton(class_):
|
||||
instances = {}
|
||||
|
||||
def get_instance(*args, **kwargs):
|
||||
if class_ not in instances:
|
||||
instances[class_] = class_(*args, **kwargs)
|
||||
return instances[class_]
|
||||
|
||||
return get_instance
|
||||
|
||||
|
||||
class ConstEnum(str, Enum):
|
||||
"""
|
||||
Class is used for gathering string constants in one place.
|
||||
Attribute values are generated from attribute names.
|
||||
All attributes values will be considered as strings.
|
||||
Class name is omitted from attribute value.
|
||||
|
||||
>>> Booze = ConstEnum("Booze", "Whiskey Beer Vodka")
|
||||
>>> Booze.Beer
|
||||
Beer
|
||||
>>> print(Booze.Beer)
|
||||
Beer
|
||||
>>> type(Booze.Vodka)
|
||||
<enum 'Booze'>
|
||||
>>> repr(Booze.Whiskey)
|
||||
'Whiskey'
|
||||
|
||||
Also could be used with usual class creation:
|
||||
>>> from enum import auto
|
||||
>>> class NotBooze(ConstEnum):
|
||||
>>> Juice = auto()
|
||||
>>> Tea = auto()
|
||||
>>> Coffee = auto()
|
||||
|
||||
>>> repr(NotBooze.Tea)
|
||||
'Tea'
|
||||
"""
|
||||
|
||||
def _generate_next_value_(name, start, count, last_values):
|
||||
return name
|
||||
|
||||
def __repr__(self):
|
||||
return self.name
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
Loading…
Reference in New Issue
Block a user