dataclass_builder.wrapper module

Create instances of dataclasses.dataclass() with the builder pattern.

This module uses a generic wrapper that becomes specialized at initialization into a builder instance that can build a given dataclass.

Examples

Using a builder instance is the fastest way to get started with the dataclass-builder package.

from dataclasses import dataclass
from dataclass_builder import (DataclassBuilder, build, fields,
                               REQUIRED, OPTIONAL)

@dataclass
class Point:
    x: float
    y: float
    w: float = 1.0

Now we can build a point.

>>> builder = DataclassBuilder(Point)
>>> builder.x = 5.8
>>> builder.y = 8.1
>>> builder.w = 2.0
>>> build(builder)
Point(x=5.8, y=8.1, w=2.0)

Field values can also be provided in the constructor.

>>> builder = DataclassBuilder(Point, x=5.8, w=100)
>>> builder.y = 8.1
>>> build(builder)
Point(x=5.8, y=8.1, w=100)

Note

Positional arguments are not allowed, except for the dataclass itself.

Fields with default values in the dataclass are optional in the builder.

>>> builder = DataclassBuilder(Point)
>>> builder.x = 5.8
>>> builder.y = 8.1
>>> build(builder)
Point(x=5.8, y=8.1, w=1.0)

Fields that don’t have default values in the dataclass are not optional.

>>> builder = DataclassBuilder(Point)
>>> builder.y = 8.1
>>> build(builder)
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 = DataclassBuilder(Point)
>>> builder.x
REQUIRED
>>> builder.w
OPTIONAL

The fields() function 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(fields(builder).keys())
['x', 'y', 'w']
>>> [f.type.__name__ for f in fields(builder).values()]
['float', 'float', 'float']

A subset of the fields can be also be retrieved, for instance, to only get required fields:

>>> list(fields(builder, optional=False).keys())
['x', 'y']

or only the optional fields.

>>> list(fields(builder, required=False).keys())
['w']
class dataclass_builder.wrapper.DataclassBuilder(dataclass: Any, **kwargs: Any)[source]

Bases: object

Wrap a dataclass with an object implementing the builder pattern.

This class, via wrapping, allows dataclasses to be constructed with the builder pattern. Once an instance is constructed simply assign to it’s attributes, which are identical to the dataclass it was constructed with. When done use the dataclass_builder.utility.build() function to attempt to build the underlying dataclass.

Warning

Because this class overrides attribute assignment when extending it care must be taken to only use private or “dunder” attributes and methods.

Parameters
  • dataclass – The dataclass_that should be built by the builder instance

  • **kwargs – Optionally initialize fields during initialization of the builder. These can be changed later and will raise UndefinedFieldError if they are not part of the dataclass’s __init__ method.

Raises
__setattr__(item: str, value: Any) → None[source]

Set a field value, or an object attribute if it is private.

Note

This will pass through all attributes beginning with an underscore. If this is a valid field of the dataclass it will still be built correctly but UndefinedFieldError will not be thrown for attributes beginning with an underscore.

If you need the exception to be thrown then set the field in the constructor.

Parameters
  • item – Name of the dataclass field or private/”dunder” attribute to set.

  • value – Value to assign to the dataclass field or private/”dunder” attribute.

Raises

dataclass_builder.exceptions.UndefinedFieldError – If item is not initialisable in the underlying dataclass. If item is private (begins with an underscore) or is a “dunder” then this exception will not be raised.

__repr__() → str[source]

Print a representation of the builder.

from dataclasses import dataclass
from dataclass_builder import DataclassBuilder, build, fields

@dataclass
class Point:
    x: float
    y: float
    w: float = 1.0
>>> DataclassBuilder(Point, x=4.0, w=2.0)
DataclassBuilder(Point, x=4.0, w=2.0)
Returns

String representation that can be used to construct this builder instance.