mrshannon / dataclass-builder Goto Github PK
View Code? Open in Web Editor NEWCreate instances of dataclasses with the builder pattern.
License: MIT License
Create instances of dataclasses with the builder pattern.
License: MIT License
When using types from the typing module such as Sequence
the dataclass_builder
factory method fails building the class docstring for the generated class.
The following example
from typing import Sequence
from dataclasses import dataclass
from dataclass_builder import dataclass_builder
@dataclass
class ComplexTypes:
sequence: Sequence[int]
ComplexTypes = dataclass_builder(ComplexTypes)
will throw an AttributeError
because typing.Sequence
does not have a __name__
attribute.
Traceback (most recent call last):
File "test.py", line 12, in <module>
ComplexTypes = dataclass_builder(ComplexTypes)
File ".../dataclass_builder/factory.py", line 372, in dataclass_builder
for name, field in settable_fields.items()])
File ".../dataclass_builder/factory.py", line 372, in <listcomp>
for name, field in settable_fields.items()])
File "/usr/lib/python3.7/typing.py", line 699, in __getattr__
raise AttributeError(attr)
AttributeError: __name__
Mypy, and other type checkers issue an error when accessing the fields of a DataclassBuilder
because they are dynamically assigned.
from dataclasses import dataclass
from dataclass_builder import DataclassBuilder
@dataclass
class Point:
x: float
y: float
w: float = 1.0
point_builder = DataclassBuilder(Point, x=2.0, y=4.0)
print(point_builder.x)
Now if you run mypy
on this you get
$ mypy getattr_bug.py
getattr_bug.py:11: error: "DataclassBuilder" has no attribute "x"
Child classes of DataclassBuilder
throw an AttributeError
on initialization.
from dataclasses import dataclass
from dataclass_builder import DataclassBuilder
@dataclass
class Something:
pass
class ExtendedBuilder(DataclassBuilder):
pass
Now if you construct an instance of the child class you get:
>>> ExtendedBuilder(Something)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File ".../dataclass-builder/dataclass_builder/__init__.py", line 190, in __init__
self.__dataclass = dataclass
File ".../dataclass-builder/dataclass_builder/__init__.py", line 218, in __setattr__
elif item not in self.__settable_fields:
AttributeError: 'ExtendedBuilder' object has no attribute '_DataclassBuilder__settable_fields'
Really liking this package and I was hoping to pick your brain on how to possibly use it to standardize basic modifications to dataclass properties during construction. This is particularly tricky in frozen
dataclasses since there isn't a clear way to modify a property in the __post_init__
method of the dataclass but putting this type of logic in a builder object seems more correct anyway โ eliminating logic from the dataclass as much as possible.
A quick example would be needing to sort a list-type property without requiring that everyone building an instance of my dataclass sort it because it is an implementation detail.
@dataclass(frozen=True)
class SomeCollection:
things: Tuple[str]
def get_some_things():
return sorted(self.things)
Right now I am sorting the list on its way out in any getter type methods โ the getter methods are doing more than just returning the sorted list but I wanted to keep the example short. It would be nice if part of the build()
process would allow me to sort the list before passing it to the dataclass so my dataclass can simply require a sorted list without imposing that step everywhere a dataclass instance is created.
Is this already easily possible with your package? Would I create an extended DataclassBuilder class with a custom _build
or setter method? Do I modify the builder class created by things like PointBuilder = dataclass_builder(Point)
?
Because REQUIRED, OPTIONAL, and MISSING are intended to be sentinal objects they should still be comparable after a copy.deepcopy the same way None is.
from copy import deepcopy
from dataclass_builder import REQUIRED, OPTIONAL, MISSING
>>>None is None
True
>>>deepcopy(None) is None
True
>>>REQUIRED is REQUIRED
True
>>>deepcopy(REQUIRED) is REQUIRED
False
>>>REQUIRED is REQUIRED
True
>>>REQUIRED is deepcopy(REQUIRED)
True
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.