Skip to content

bagof.magic

A Magic acts like a python dataclass, except that it operates via inheritance, rather than via a decorator (although the @magic decorator can be used if preferred).

The options typically specified in the @dataclass decorator are instead specified as class keyword arguments, and are inherited (or overloaded) by subclasses.

class Point(Magic, frozen=True):
    x: float
    y: float

# --- or ---

@magic(frozen=True)
class Point:
    x: float
    y: float

Most options supported by dataclasses are supported, but there are some differences. Additional options are also implemented:

Parameters:

Name Type Description Default
init bool | str

Generate __init__ method

True
repr bool | str

Generate __repr__ method

True
eq bool | str

Generate __eq__ method

True
order bool | str

Generate __lt__ method

False
unsafe_hash bool

Always generate __hash__ method

False
frozen bool

Disable __setattr__ and __delattr__

False
match_args bool | str

Generate __match_args__ for pattern matching

False
kw_only bool

Make all fields keyword-only by default

False
slots bool

Generate __slots__ and remove __dict__

False
weakref_slot bool

Generate a weakref slot in __slots__

False
factory bool

Use field type as factory if none is provided

False
convert bool

Use field type as converter if none is provided

False
validate bool

Use field type as validator if none is provided

False

Examples:

It also differs from a standard dataclass in that field-specific options are assigned via annotations, rather than via a field function:

# - Default factories
#   instead of x: list = field(factory=list)
x: Factory[list, list_factory]
x: Annotated[list, Factory(list_factory)]

#   if no factory is provided, it will use the type as the default factory
x: Factory[list] -> x: Annotated[list, Factory(list)]

# - Include in the init method
#   instead of x: int = field(init=True)
x: Init[int]
x: Annotated[int, Init()]
x: Annotated[int, Init(True)]
x: NoInit[int]
x: Annotated[int, NoInit()]
x: Annotated[int, Init(False)]

# - Keyword-only arguments
#   instead of x: int = field(kw_only=True)
x: KwOnly[int]
x: Annotated[int, KwOnly()]
x: Annotated[int, KwOnly(True)]
x: NotKwOnly[int]
x: Annotated[int, NotKwOnly()]
x: Annotated[int, KwOnly(False)]

It supports additional features such as automatic conversion of field values via annotations:

x: ConvertTo[int, partial(int, base=16)]
x: Annotated[int, ConvertTo(partial(int, base=16))]

# if no converter is provided, it will use the type as the default converter
x: ConvertTo[int] -> x: Annotated[int, ConvertTo(int)]

Frozen or unfrozen fields:

x: Frozen[int]
x: Annotated[int, Frozen()]
x: Annotated[int, Frozen(True)]
x: NotFrozen[int]
x: Annotated[int, NotFrozen()]
x: Annotated[int, Frozen(False)]

Classes

HIDE_IF_NONE

HIDE_IF_NONE(key: str | None = None)

Bases: SHOW_ATTR

Sentinel for Field.repr / Field.key: include the field in the generated __repr__ / dict-like interface only when its value is not None at runtime, instead of unconditionally.

class C(Magic):
    x: Annotated[Optional[int], Field(repr=HIDE_IF_NONE)]

repr(C(None))  # "C()"
repr(C(5))     # "C(x=5)"

Magic

Base class for data structures.

Examples:

class Point(Magic, frozen=True):
    x: float
    y: float

Parameters:

Name Type Description Default
init bool | str

Generate __init__ method.

True
repr bool | str

Generate __repr__ method.

True
eq bool | str

Generate __eq__ method.

True
order bool | str

Generate __lt__ method.

False
hash bool | str

Generate __hash__ method. If None, decide automatically.

None
unsafe_hash bool

Always generate __hash__ method.

False
frozen bool

Disable __setattr__ and __delattr__.

False
match_args bool | str

Generate __match_args__ for pattern matching.

False
kw_only bool

Make all fields keyword-only by default.

False
positional_only bool

Make all fields positional-only by default.

False
slots bool

Generate __slots__ and remove __dict__.

False
weakref_slot bool

Generate a weakref slot in __slots__.

False
factory bool

Use field type as factory if none is provided.

False
convert bool

Use field type as converter if none is provided.

False
validate bool

Use field type as validator if none is provided.

False
mapping bool

Implement the Mapping protocol.

False
reverse bool

Use the reverse MRO order to determine field order. This only affects the relative order of the fields of one class with respect to the fields of its base classes.

False
doc bool | str

Add field documentation to class docstring.

True

Functions:

magic

magic(**kwargs) -> Callable[[type], type]
magic(cls: type, **kwargs) -> type

Decorator for defining a Magic class. See Magic for parameters and examples.