Skip to content

Quick Start

A working example in under 50 lines. Copy, paste, run.

from spryx_di import ApplicationContext, ClassProvider, Module, ModuleBoundaryError


# --- Ports (interfaces) ---

class UserReader:
    def get(self, user_id: str) -> str:
        raise NotImplementedError

class UserRepository:
    def save(self, user_id: str) -> None:
        raise NotImplementedError


# --- Implementations ---

class PgUserReader(UserReader):
    def __init__(self, repo: UserRepository) -> None:
        self._repo = repo

    def get(self, user_id: str) -> str:
        return f"user:{user_id}"

class PgUserRepository(UserRepository):
    def save(self, user_id: str) -> None:
        print(f"saved {user_id}")


# --- Modules ---

identity_module = Module(
    name="identity",
    providers=[
        ClassProvider(provide=UserRepository, use_class=PgUserRepository),
        ClassProvider(provide=UserReader, use_class=PgUserReader),
    ],
    exports=[UserReader],  # UserRepository stays private
)


class OrderHandler:
    def __init__(self, reader: UserReader) -> None:
        self._reader = reader

    def handle(self) -> str:
        return self._reader.get("u1")

orders_module = Module(
    name="orders",
    providers=[],
    imports=[identity_module],
)


# --- Compose ---

ctx = ApplicationContext(modules=[identity_module, orders_module])

handler = ctx.resolve(OrderHandler)
print(handler.handle())  # "user:u1"

# Boundary enforcement
try:
    ctx.resolve_within(orders_module, UserRepository)
except ModuleBoundaryError as e:
    print(e)
    # Cannot resolve 'UserRepository' in module 'orders'.
    #   'UserRepository' is a provider of 'identity' but is not exported.