Examples#

Every example below lives in examples/ in the repository and is a runnable script (python examples/<name>.py). This page embeds them directly so they can never drift out of sync with what actually runs.

@Data#

"""Runnable example: @Data on a plain class and on a stacked @dataclass."""

from dataclasses import dataclass

from inito import Data


@Data
class User:
    name: str
    age: int = 0


@Data(frozen=True)
@dataclass
class Point:
    x: int
    y: int


def main() -> None:
    user = User("Ada", age=30)
    print(user)
    print(user.get_name(), user.get_age())
    user.set_age(31)
    print(user)
    print(User("Ada", 31) == user)

    origin = Point(0, 0)
    print(origin)
    print(hash(origin) == hash(Point(0, 0)))


if __name__ == "__main__":
    main()

@Getter#

"""Runnable example: @Getter on its own, without @Data's other capabilities."""

from inito import Getter


@Getter
class User:
    name: str
    age: int = 0


def main() -> None:
    user = User()
    user.name = "Ada"
    user.age = 30
    print(user.get_name(), user.get_age())


if __name__ == "__main__":
    main()

@Setter#

"""Runnable example: @Setter on its own, without @Data's other capabilities."""

from inito import Setter


@Setter
class User:
    name: str
    age: int = 0


def main() -> None:
    user = User()
    user.set_name("Ada")
    user.set_age(30)
    print(user.name, user.age)


if __name__ == "__main__":
    main()

@NoArgsConstructor#

"""Runnable example: @NoArgsConstructor requires every field to have a default."""

from inito import NoArgsConstructor


@NoArgsConstructor
class Config:
    debug: bool = False
    retries: int = 3


def main() -> None:
    config = Config()
    print(config.debug, config.retries)


if __name__ == "__main__":
    main()

@AllArgsConstructor#

"""Runnable example: @AllArgsConstructor generates a constructor only."""

from inito import AllArgsConstructor


@AllArgsConstructor
class Point:
    x: int
    y: int


def main() -> None:
    point = Point(1, 2)
    print(point.x, point.y)


if __name__ == "__main__":
    main()

@RequiredArgsConstructor#

"""Runnable example: @RequiredArgsConstructor only requires fields without defaults."""

from inito import RequiredArgsConstructor


@RequiredArgsConstructor
class User:
    name: str
    age: int = 0


def main() -> None:
    user = User("Ada")
    print(user.name, user.age)


if __name__ == "__main__":
    main()

@Builder / builder#

The three patterns below mirror the original project spec exactly (modulo a uuid import-casing typo fixed in the source).

"""Runnable example: the three @builder patterns from the original spec.

Note: the spec's examples used `from UUID import uuid4` (wrong casing,
`uuid` is lowercase) and annotated fields with `uuid4` itself (a function,
not a type). Both are fixed here to valid Python; inito does not validate
annotations against runtime values, so the patterns below are otherwise
verbatim.
"""

from dataclasses import dataclass
from uuid import UUID, uuid4

from inito import builder

# Example 1: bare @builder on a plain class.


@builder
class Request:
    request_id: UUID
    prompt: str
    temperature: float
    top_p: int


# Example 2: @builder stacked on @dataclass.


@builder
@dataclass
class DataclassRequest:
    request_id: UUID
    prompt: str
    temperature: float
    top_p: int


# Example 3: @builder(to_builder=True) stacked on @dataclass.


@builder(to_builder=True)
@dataclass
class ToBuilderRequest:
    request_id: UUID
    prompt: str
    temperature: float
    top_p: int


def main() -> None:
    request = (
        Request.builder().request_id(uuid4()).prompt("hello").temperature(0.7).top_p(1).build()
    )
    print(request.prompt, request.temperature, request.top_p)

    dataclass_request = (
        DataclassRequest.builder()
        .request_id(uuid4())
        .prompt("hi")
        .temperature(0.5)
        .top_p(1)
        .build()
    )
    print(dataclass_request)

    original = ToBuilderRequest(uuid4(), "original", 0.9, 1)
    revised = original.to_builder().prompt("revised").build()
    print(original.prompt, revised.prompt)


if __name__ == "__main__":
    main()

@ToString#

"""Runnable example: @ToString paired with @Builder for a readable repr."""

from inito import ToString, builder


@builder
@ToString
class Point:
    x: int
    y: int


def main() -> None:
    point = Point.builder().x(1).y(2).build()
    print(point)


if __name__ == "__main__":
    main()

@EqualsAndHashCode#

"""Runnable example: @EqualsAndHashCode on its own, without @Data's other capabilities."""

from inito import EqualsAndHashCode


@EqualsAndHashCode
class Point:
    x: int
    y: int


def main() -> None:
    a, b = Point(), Point()
    a.x, a.y = 1, 2
    b.x, b.y = 1, 2
    print(a == b, hash(a) == hash(b))


if __name__ == "__main__":
    main()

@Value#

"""Runnable example: @Value, a genuinely immutable data class with no setters."""

from dataclasses import FrozenInstanceError

from inito import Value


@Value
class Point:
    x: int
    y: int


def main() -> None:
    point = Point(1, 2)
    print(point)
    print(point.get_x(), point.get_y())
    print(point == Point(1, 2))
    print(not hasattr(point, "set_x"))

    try:
        point.x = 5  # no @dataclass(frozen=True) stacking needed - @Value enforces this itself
    except FrozenInstanceError as error:
        print(f"blocked: {error}")


if __name__ == "__main__":
    main()

Dependency injection#

"""Runnable example: @Service/@Singleton/@Inject and Container-based dependency injection."""

from inito import Inject, Service, Singleton, default_container


@Singleton
class Repo:
    def __init__(self) -> None:
        self.ages = {"Ada": 30}


@Service
class UserService:
    def __init__(self, repo: Repo, retries: int = 3) -> None:
        self.repo = repo
        self.retries = retries

    def age_of(self, name: str) -> int:
        return self.repo.ages[name]


@Inject
def main(service: UserService) -> None:
    print(service.age_of("Ada"))
    print(service.retries)
    print(default_container.get(UserService) is service)

    # @Service never mutates the class - it's still an ordinary, directly
    # constructible Python class, with no DI-specific overhead.
    plain = UserService(Repo(), retries=5)
    print(plain.retries)


if __name__ == "__main__":
    main()