Skip to main content

bagof-magic

Classes that build themselves from your type hints.

Write your fields as annotations. Magic generates __init__, __repr__, __eq__, and everything else.

from bagof.magic import Magic

class Point(Magic, frozen=True):
    x: float
    y: float
>>> Point(1.0, 2.0)
Point(x=1.0, y=2.0)
>>> Point(1.0, 2.0) == Point(1.0, 2.0)
True
>>> Point(1.0, 2.0).x = 3.0
Traceback (most recent call last):
AttributeError: Cannot set frozen field 'x'

If you prefer a decorator:

=== "Base class"

```python
from bagof.magic import Magic

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

=== "Decorator"

```python
from bagof.magic import magic

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

What sets it apart

  • Settings are class keyword arguments, and subclasses inherit them. Set frozen=True on a base once; every subclass keeps it, and can override just the settings it needs to change. See Settings.
  • Per-field behaviour lives in the annotation, not in a field() call: tags: Factory[list], token: NoRepr[str] = "". See Field annotations.
  • Conversion and validation come from the type hint, opt in per class or per field. Config("localhost", "9000") becomes port=9000 because the hint says int. See Conversion and validation.
  • A class can build one of its own subclasses, chosen from the arguments it's called with. See Building the right subclass.
  • A field can accept several input names, and expose forwarding properties under other names. See Input aliases and forwarding properties.
  • Also included: dict-like instances, replace/asdict/astuple, mutable defaults that aren't shared, hooks around construction, generic classes, and docstrings generated from the fields. See Extras.

How it compares

Close to attrs in spirit, with pydantic's habit of doing real work from your type hints, and inheritance where the others use decorators.

dataclasses attrs pydantic magic
settings inherited by subclasses no no yes yes
per-field behaviour in the annotation no no partly yes
conversion from the type hint no partly yes yes
validation from the type hint no partly yes yes
dict-like instances no no partly yes
no methods added unless asked yes yes no yes

There is a fuller side-by-side in the comparison page.

Settings

class Thing(Magic, frozen=True, kw_only=True, slots=True):
    ...
Setting Default What it does
init True generate __init__
repr True generate __repr__
eq True generate __eq__
order False generate the comparisons
hash None generate __hash__; decides for itself by default
unsafe_hash False generate one even when the class is mutable
frozen False refuse assignment after construction
match_args False support structural pattern matching
kw_only False every field must be passed by name
positional_only False every field must be passed by position
slots False use __slots__, and drop __dict__
weakref_slot False allow weak references under slots
convert False convert every field from its type
validate False check every field against its type
convert_defaults True convert a value that came from a default, too
validate_defaults True check a value that came from a default, too
unresolved_hints "warn" what to do when a type hint still names something undefined the first time a field needs it; or "raise", or "ignore"
factory False build every missing default from its type
mutable_default "factory" give each instance its own copy of x: list = []; or "raise", or "allow"
alias default public name input names; True includes enabled property names, False keeps underscores
property False forwarding attributes; True or "readonly" exposes the public name, "all" every input alias
mapping False behave like a dictionary; a subclass inherits the methods and cannot turn them off
override False apply this class's settings to inherited fields too
polymorphic False build one of this class's subclasses, chosen from the arguments; or "strict", which refuses to build this class when none of them matches
pin_discriminant "pin" what a subclass does with the field it matches on; or "classvar", or "keep"
reverse False list a subclass's own fields before inherited ones
doc True add the field table to the class docstring

Most of them also accept a string instead of True, which binds the generated method under that name. This is useful when you want to call the generated method from your own.

See Settings for how they're inherited and how to override them.

Install

pip install git+https://github.com/bagofseeds/bagof-magic.git

Python 3.8 and later.

Status

Early. The API is settling, and things may still move. Issues and ideas are welcome at bagofseeds/bagof-magic.

Metadata

Release files for bagof-magic 0.2.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for bagof-magic 0.2.1
File Size Uploaded
bagof_magic-0.2.1.tar.gz 167.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for bagof-magic 0.2.1
File Interpreter ABI Platform
bagof_magic-0.2.1-py3-none-any.whl Python 3 none any Details

Total release size: 267.1 kB

Release files / bagof_magic-0.2.1.tar.gz

Download URL bagof_magic-0.2.1.tar.gz
Size 167.5 kB
Tags Source
SHA-256 checksum
How to use checksums
13cda551293afbf6b02169e80a9f677becd4d83b4667695a0465477856801545
BLAKE2b-256 checksum
How to use checksums
abd87ce9f94e6b7aa3ee82fb69622f5027fba61a35d391869a3ca0c71de3c189
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / bagof_magic-0.2.1-py3-none-any.whl

Download URL bagof_magic-0.2.1-py3-none-any.whl
Size 99.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b3d5f7f0615dbd9e462f615b4dbacb48523871e97b248e9bd5e5633b69057fe1
BLAKE2b-256 checksum
How to use checksums
7eb4025d70e382287264cd79c8e4fb0cae545b7b94d27d6f3fef0fdac832b8be
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14
Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page