reagento / adaptix Goto Github PK
View Code? Open in Web Editor NEWAn extremely flexible and configurable data model conversion library.
Home Page: https://adaptix.readthedocs.io
License: Apache License 2.0
An extremely flexible and configurable data model conversion library.
Home Page: https://adaptix.readthedocs.io
License: Apache License 2.0
from dataclasses import dataclass
from dataclass_factory import Factory
from datetime import datetime
@dataclass()
class Traffic:
time: datetime
rx: int
tx: int
if __name__ == '__main__':
dict_traff = {
'time': datetime(2019, 12, 1, 1, 20, 13),
'rx': 10,
'tx': 15
}
factory = Factory()
traff: Traffic = factory.load(dict_traff, Traffic)
print(factory.dump(traff))
Ошибка:
Traceback (most recent call last):
File "E:/NMS/NMSProgect/modules/traffic.py", line 24, in <module>
traff: Traffic = factory.load(dict_traff, Traffic)
File "E:\NMS\lib\site-packages\dataclass_factory\factory.py", line 94, in load
return self.parser(class_)(data)
File "E:\NMS\lib\site-packages\dataclass_factory\parsers.py", line 139, in dataclass_parser
for field, name, parser in field_info
File "E:\NMS\lib\site-packages\dataclass_factory\parsers.py", line 140, in <dictcomp>
if name in data
File "E:\NMS\lib\site-packages\dataclass_factory\parsers.py", line 186, in class_parser
k: parser(data.get(k)) for k, parser in parsers.items() if k in data
File "E:\NMS\lib\site-packages\dataclass_factory\parsers.py", line 186, in <dictcomp>
k: parser(data.get(k)) for k, parser in parsers.items() if k in data
TypeError: argument of type 'datetime.datetime' is not iterable
node.js возвращает поля с спецсимволами "foo-bar$1"
былобы удобно обьявить поле value_1 а получать значения из value-1
There is no Schema parametr, which do not change fields namestyle to one concrete, like bool ignore_namestyle
аналогичная функциональность в Pydantic
model_a.py
from pydantic import BaseModel
class ModelA(BaseModel):
field: int
model_b.py
from __future__ import annotations
from typing import TYPE_CHECKING
from pydantic import BaseModel
if TYPE_CHECKING:
from model_a import ModelA
class ModelB(BaseModel):
field: int
a: ModelA
main.py
from model_b import ModelB
print(ModelB.__fields__)
-> {'field': ModelField(name='field', type=int, required=True), 'a': ModelField(name='a', type=ForwardRef('ModelA'), required=PydanticUndefined)}
по type=ForwardRef
и в этом месте неизвестно что именно из себя представляет ModelA
для ModelB
потому что его нет в скоупе модуля model_b
.
для этого есть ModelB.update_forward_refs()
вызываем из main.py
только прямой вызов ModelB.update_forward_refs()
ничего не сделает - NameError: name 'ModelA' is not defined
, потому что в модуле где находится класс все еще нет такого имени
делаем следующее - ModelB.update_forward_refs(ModelA=ModelA)
и далее снова смотрим поля:
{'field': ModelField(name='field', type=int, required=True), 'a': ModelField(name='a', type=ModelA, required=True)}
ModelA
теперь имеет реальный тип а не референс
What will happen if some of the fields are in one style and some in another? How does it work in practice? I would like to see more examples in Readme.nd
import dataclass_factory
from dataclasses import dataclass
@dataclass
class Problem:
name: str
eventid: int
urls: list
data = {
'name': 'TestProblem',
'eventid': 1,
'urls': []
}
factory = dataclass_factory.Factory()
problem: Problem = factory.load(data, Problem)
print(problem)
Traceback (most recent call last):
File "C:/Users/themida/Documents/project/test.py", line 19, in <module>
problem: Problem = factory.load(data, Problem)
File "C:\Users\themida\Documents\project\venv\lib\site-packages\dataclass_factory\factory.py", line 118, in load
return self.parser(class_)(data)
File "C:\Users\themida\Documents\project\venv\lib\site-packages\dataclass_factory\factory.py", line 77, in parser
return self._parser_with_stack(class_, StackedFactory(self))
File "C:\Users\themida\Documents\project\venv\lib\site-packages\dataclass_factory\factory.py", line 93, in _parser_with_stack
schema.parser = create_parser(stacked_factory, schema, self.debug_path, class_)
File "C:\Users\themida\Documents\project\venv\lib\site-packages\dataclass_factory\parsers.py", line 256, in create_parser
parser = create_parser_impl(factory, schema, debug_path, cls)
File "C:\Users\themida\Documents\project\venv\lib\site-packages\dataclass_factory\parsers.py", line 340, in create_parser_impl
parsers = {
File "C:\Users\themida\Documents\project\venv\lib\site-packages\dataclass_factory\parsers.py", line 341, in <dictcomp>
field.name: factory.parser(resolved_hints[field.name])
File "C:\Users\themida\Documents\project\venv\lib\site-packages\dataclass_factory\factory.py", line 29, in parser
return self.factory._parser_with_stack(class_, self)
File "C:\Users\themida\Documents\project\venv\lib\site-packages\dataclass_factory\factory.py", line 93, in _parser_with_stack
schema.parser = create_parser(stacked_factory, schema, self.debug_path, class_)
File "C:\Users\themida\Documents\project\venv\lib\site-packages\dataclass_factory\parsers.py", line 256, in create_parser
parser = create_parser_impl(factory, schema, debug_path, cls)
File "C:\Users\themida\Documents\project\venv\lib\site-packages\dataclass_factory\parsers.py", line 316, in create_parser_impl
if args_unspecified(cls):
File "C:\Users\themida\Documents\project\venv\lib\site-packages\dataclass_factory\type_detection.py", line 119, in args_unspecified
(not cls.__args__ and cls.__parameters__) or
AttributeError: type object 'list' has no attribute '__args__'
I have a dataclass which str item default is "a" and int item default is 2.
But in data dict, their value is None.
When I call factory.load(data, DataClass), I want to leave the None type as it is, don't change it.
Or I don't want to get an exception when type .
Any solution?
Thanks
When serialising skip None values if it is also set as default
We need new field in Schema and change logic of dataclass serializer.
Skipping None for all Optionals is not safe, as object cannot be created from such a dict.
Skipping other defaults is not safe enough, but can be separatly implemented
Setting this feature for each field should be done separately
How can I deserialize a recursive structure?
I have seen #17 but I am getting errors trying to deserialize the following:
@dataclass(frozen=True)
class JsonSport:
sport_id: int
sport_name: str
sport_description: Optional[str]
sports: Optional[List["JsonSport"]]
The error is
dataclass_factory.exceptions.InvalidFieldError: Invalid data at path [sports]: No suitable parsers in union found for
[{'sportId': 63, 'sportName': 'Idrettsskoler', 'sportDescription': 'Idrett generelt...`
It is very difficult to understand what going wrong during parsing
mypy_extensions
and typing
) from normal Dict.__total__
@dataclass
class List:
data: int
next: Optional[List]
This should be parsed as well
Make JSONEncoder compatible version of factory
https://docs.python.org/3/library/json.html#json.JSONEncoder
Example with https://github.com/Tishka17/dataclass_factory#structure-flattening full of magic
Could you explain how this works? So far, all this is not obvious. What kind of magic zero..?
Add to schema "impl" attribute which provides real type of interface.
So factory.load(data, Interface)
will be equal to factory.load(data, impl)
Also must be applyed to fields with Interface
type
Tuple type; Tuple[X, Y] is the type of a tuple of two items with the first item of type X and the second of type Y.
Example: Tuple[T1, T2] is a tuple of two elements corresponding to type variables T1 and T2. Tuple[int, float, str] is a tuple of an int, a float and a string.
To specify a variable-length tuple of homogeneous type, use literal ellipsis, e.g. Tuple[int, ...]. A plain Tuple is equivalent to Tuple[Any, ...], and in turn to tuple.
see feature/schema_serial
Trying to deserialize a nullable Dict[T, U] results in get_dict_parser being called anyway and raising an AttributeError due to the target dict being None.
Testing with Python 3.7 and dataclass_factory 2.4.1 the following code will raise:
from typing import Optional, Dict, Any
from dataclass_factory import Factory
@dataclass
class Test:
x: Optional[Dict[str, Any]]
f = Factory()
f.load({"x": None}, Test)
The root issue seems to be that Optional is not being detected correctly as it is indistinguishable from Union[T, NoneType], which ends up in get_dict_parser raising due to the order of the type arguments.
Пример:
T = TypeVar('T')
@dataclass
class Foo(Generic[T]):
value: T
Должен парситься Foo[int]
Он не детектится как датакласс, надо работать с Origin
Custom parser can be provided in Schema.
It is ok to parse data in dict before passing to custom parser or provide a way to call use factory inside custo mparser.
Допустим есть классы с наследованием
@dataclass
class A:
a: int
@dataclass
class B(A):
b: int
Сейчас, если мы хотим сделать предобработку поля a, мы должны сделать две схемы: для класс A и для класса B и в обеих определить pre_parse.
Необходимо продумать как это делать более удобно
We can parse class if it has init with annotations. Probably it is ok to serialize it as well. All schema features must be included
@dataclass
class A:
x: str
y: str
schema_num = Schema[A](
name_mapping={
"x": (1, "a", "b"),
}
)
class Test1(TestCase):
def test_load_num(self):
factory = Factory(
schemas={
A: schema_num
}
)
data = {
"a": [None, {"b": "hello"}],
"y": "world"
}
expected = A("hello", "world")
self.assertEqual(expected, factory.load(data, A))
Ошибка:
======================================================================
ERROR: test_load_num (test_path.Test1)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/tishka17/src/dataclass_factory/tests/test_path.py", line 39, in test_load_num
self.assertEqual(expected, factory.load(data, A))
File "/home/tishka17/src/dataclass_factory/dataclass_factory/factory.py", line 94, in load
return self.parser(class_)(data)
File "/home/tishka17/src/dataclass_factory/dataclass_factory/parsers.py", line 139, in dataclass_parser
for field, name, parser in field_info
TypeError: __init__() missing 1 required positional argument: 'x'
class JsonFactory:
...
def dump(self, data, type):
return json.dumps(self.real_factory.dump(data, type))
def load(self, data, type):
return self.real_facory.load(json.loads(data), type)
Idea: check class __init__
method args
https://github.com/Tishka17/dataclass_factory#schemas
from dataclass_factory import Schema
skipped in example
Нужно поднять версию Programming Language так как с 3.7 добавлены датаклассы
https://www.python.org/dev/peps/pep-0557/
typing
in python 3.8 and typing_extensions
https://github.com/Tishka17/dataclass_factory#polymorphic-parsing
Missing import dataclass
In werkzeug MultiDict allows to use getlist
to get multiple values for single name in form data.
This could be useful for filing dataclass List field
Create instruction or provide builin mechanism for creating polymorphics parsers.
Store all extra input fields, which absent in dataclass, separately in field with name from schema.rest
, if provided.
Also unpack rest
when serialising
Do serialization to primitives, that can be stored in extrernal structured format (e.g. json) and than parsed
>>> class A(Enum):
... a=1
... b="s"
...
>>> Factory().dump(A.a)
<A.a: 1>
Hi! Thanks for the awesome project.
It looks like you have covered almost all of your source code with type annotations, but currently it is not shipped to the final user.
I suggest to fix this situation. Here's how:
py.typed
file in the root of the dataclass_factory
folder, it is required for PEP561 to work. Example: https://github.com/dry-python/returns/blob/master/returns/py.typeddef load(self, data: Any, class_: Type[T]) -> T:
(do not forget about Generic
base class)mypy
to check these annotationsThis feature would improve developer experience and make this project even more awesome!
Did not see custom validation of fields except types. For example here https://marshmallow.readthedocs.io/en/stable/quickstart.html#validation . For example, expect a certain length or a certain value from a list of valid. Also multiple validation of one field, for example a password field
Do you think to write the example in the docs with many parameter (like marshmallow), i.e. list comprehesion or as an alternative with a new dataclass and List[Item]?
A lot of parameters, which description we have at docs, have no practical examples, which can helps to understand it better. Could you write more examples in the documentation?
dataclass <-> dataclass
dataclass <-> protobuf
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.