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)) — dataclasses has none.

  • A fluent builder (@Builder) — dataclasses has none.

  • Picking capabilities individually (@Getter alone, @ToString alone, …) 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:

  • attrs classes are slotted by default (attrs.define), which gives a smaller per-instance memory footprint (see Performance) — inito doesn’t generate slotted classes today.

  • attrs has one flexible @define/@attrs.s entry point with many flags; inito favors many small, Lombok-named decorators (@Getter, @ToString, …) you compose explicitly.

  • attrs has mature mypy and pyright plugin support for every generated attribute; inito ships an equivalent mypy plugin covering all of it, plus a dataclass_transform-based .pyi stub that gets @Data/@AllArgsConstructor’s constructors correctly typed under pyright too — but get_x/set_x and @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.