Migration guide#
From dataclasses#
inito composes with dataclasses rather than replacing it — @Data
(and every other decorator) is dataclass-aware: stack it on top of an
existing @dataclass and it reuses the dataclass’s own field
metadata/defaults rather than re-deriving them.
from dataclasses import dataclass
from inito import Getter
@Getter
@dataclass
class Point:
x: int
y: int
Reach for inito over plain dataclasses when you want:
Accessors (
get_x()/set_x(value)) —dataclasseshas none.A fluent builder (
@Builder) —dataclasseshas none.Picking capabilities individually (
@Getteralone,@ToStringalone, …) rather than the all-or-nothing@dataclass(init=, repr=, eq=, ...)flag surface.
Stick with plain dataclasses if you don’t need any of the above — it’s
in the standard library, and (per Performance) construction
performance is within noise of inito.
To stack an inito constructor-generating decorator with
@dataclass(frozen=True), put the @dataclass(frozen=True) innermost
(@Data / @dataclass(frozen=True) / class); the reverse order isn’t
supported. For an immutable class, prefer @Value or @Data(frozen=True),
which need no stacking. See Troubleshooting for
details, and if you hit FrozenInstanceError from a setter afterward
(expected: setters still respect frozen semantics, only construction is
exempted).
From attrs#
attrs and inito overlap the most: both eliminate boilerplate, both
generate real methods once at class-creation time, both have zero required
runtime overhead. The differences:
attrsclasses are slotted by default (attrs.define), which gives a smaller per-instance memory footprint (see Performance) —initodoesn’t generate slotted classes today.attrshas one flexible@define/@attrs.sentry point with many flags;initofavors many small, Lombok-named decorators (@Getter,@ToString, …) you compose explicitly.attrshas mature mypy and pyright plugin support for every generated attribute;initoships an equivalent mypy plugin covering all of it, plus adataclass_transform-based.pyistub that gets@Data/@AllArgsConstructor’s constructors correctly typed under pyright too — butget_x/set_xand@Builder’s fluent chain remain a pyright-only gap (see Troubleshooting).
If you’re coming from Java/Lombok and want that naming/mental model
directly in Python, inito will feel more familiar. If per-instance memory
or IDE type-checking of generated members matters most, attrs is the more
mature choice today.
From Pydantic#
Pydantic is a validation/parsing library first — it’s built for validating
untrusted input (e.g. JSON from an API request) against a schema, with
coercion, custom validators, and serialization built in. inito does none
of that: it has no notion of “validate this value,” no serialization
format support, and no runtime type checking of assigned values.
Use inito for plain internal data-carrier classes where you control
construction and just want less boilerplate. Use Pydantic when you’re
parsing/validating external input. The two aren’t mutually exclusive - it’s
reasonable to use Pydantic at your API boundary and plain inito-decorated
classes internally.