dataclass_builder.factory module¶
Create dataclasses.dataclass()
builders for specific dataclasses.
This module uses a factory to build builder classes that build a specific dataclass. These builder classes implement the builder pattern and allow constructing dataclasses over a period of time instead of all at once.
Examples¶
Using specialized builders allows for better documentation than the
DataclassBuilder
wrapper and allows for type checking because
annotations are dynamically generated.
from dataclasses import dataclass
from dataclass_builder import (dataclass_builder, build, fields,
REQUIRED, OPTIONAL)
@dataclass
class Point:
x: float
y: float
w: float = 1.0
PointBuilder = dataclass_builder(Point)
Now we can build a point.
>>> builder = PointBuilder()
>>> builder.x = 5.8
>>> builder.y = 8.1
>>> builder.w = 2.0
>>> build(builder)
Point(x=5.8, y=8.1, w=2.0)
As long as the dataclass the builder was constructed for does not have a build field then a build method will be generated as well.
>>> builder.build()
Point(x=5.8, y=8.1, w=2.0)
Field values can also be provided in the constructor.
>>> builder = PointBuilder(x=5.8, w=100)
>>> builder.y = 8.1
>>> builder.build()
Point(x=5.8, y=8.1, w=100)
Note
Positional arguments are not allowed.
Fields with default values in the dataclass are optional in the builder.
>>> builder = PointBuilder()
>>> builder.x = 5.8
>>> builder.y = 8.1
>>> builder.build()
Point(x=5.8, y=8.1, w=1.0)
Fields that don’t have default values in the dataclass are not optional.
>>> builder = PointBuilder()
>>> builder.y = 8.1
>>> builder.build()
Traceback (most recent call last):
...
MissingFieldError: field 'x' of dataclass 'Point' is not optional
Fields not defined in the dataclass cannot be set in the builder.
>>> builder.z = 3.0
Traceback (most recent call last):
...
UndefinedFieldError: dataclass 'Point' does not define field 'z'
Note
No exception will be raised for fields beginning with an underscore as they are reserved for use by subclasses.
Accessing a field of the builder before it is set gives either the REQUIRED or OPTIONAL constant
>>> builder = PointBuilder()
>>> builder.x
REQUIRED
>>> builder.w
OPTIONAL
The fields method can be used to retrieve a dictionary of settable fields for
the builder. This is a mapping of field names to dataclasses.Field
objects from which extra data can be retrieved such as the type of the data
stored in the field.
>>> list(builder.fields().keys())
['x', 'y', 'w']
>>> [f.type.__name__ for f in builder.fields().values()]
['float', 'float', 'float']
A subset of the fields can be also be retrieved, for instance, to only get required fields:
>>> list(builder.fields(optional=False).keys())
['x', 'y']
or only the optional fields.
>>> list(builder.fields(required=False).keys())
['w']
Note
If the underlying dataclass has a field named fields this method will
not be generated and instead the fields()
function should be used
instead.
-
dataclass_builder.factory.
dataclass_builder
(dataclass: Type[Any], *, name: Optional[str] = None) → Type[Any][source]¶ Create a new builder class specialized to a given dataclass.
- Parameters
dataclass – The
dataclasses.dataclass()
to create the builder for.name – Override the name of the builder, by default it will be ‘<dataclass>Builder’ where <dataclass> is replaced by the name of the dataclass.
- Return object
A new dataclass builder class that is specialized to the given dataclass. If the given
dataclasses.dataclass()
does not contain the fields build or fields these will be exposed as public methods with the same signature as thedataclass_builder.utility.build()
anddataclass_builder.utility.fields()
functions respectively.- Raises
TypeError – If dataclass is not a
dataclasses.dataclass()
. This is decided viadataclasses.is_dataclass()
.