iisi-app-core
iisi-app-core is a small Python library for two things:
- bootstrapping ports-and-adapters applications with decorators, autoload, and
punq - lightweight role-based authorization with an explicit
Principal
Requirements
- Python
>=3.14,<4
Installation
pip install iisi-app-core
Bootstrap Quickstart
1. Mark ports and implementations
from dataclasses import dataclass
from iisi_app_core import (
ContainerBuilder,
application,
driven_adapter,
driven_port,
driving_adapter,
driving_port,
)
@driven_port
class UserRepository:
def get(self, user_id: str) -> dict[str, str]:
raise NotImplementedError
@driven_adapter(port=UserRepository)
class DynamoUserRepository(UserRepository):
def get(self, user_id: str) -> dict[str, str]:
return {"id": user_id, "name": "Ada"}
@driving_port
class GetUserProfilePort:
def get_user_profile(self, user_id: str) -> dict[str, str]:
raise NotImplementedError
@dataclass(frozen=True, slots=True)
@application(port=GetUserProfilePort)
class GetUserProfile(GetUserProfilePort):
repo: UserRepository
def get_user_profile(self, user_id: str) -> dict[str, str]:
return self.repo.get(user_id)
@dataclass(frozen=True, slots=True)
@driving_adapter
class GetUserProfileHandler:
app: GetUserProfilePort
def handle(self, user_id: str) -> dict[str, str]:
return self.app.get_user_profile(user_id)
ContainerBuilder.build() validates the boundaries:
- driving adapters may depend only on
@driving_portports - applications may depend only on
@driven_portports - depending on a decorated implementation directly raises
PortsAndAdaptersViolationError
2. Autoload modules
import app.users
from iisi_app_core import autoload
modules = autoload(app.users)
autoload(...) expects an imported package object and recursively imports all Python modules under it, excluding __init__.py.
3. Build the container
from iisi_app_core import ComponentRegistry, ContainerBuilder
registry = ComponentRegistry.from_modules(modules)
container = ContainerBuilder(registry).build()
handler = container.resolve(GetUserProfileHandler)
result = handler.handle("123")
Both the declared port and the concrete implementation are registered in punq.
4. Optional FastAPI + Mangum bootstrap
Install the framework extra when you want a web bootstrap path:
pip install "iisi-app-core[fastapi]"
from typing import Annotated
import app.users
from fastapi import APIRouter, FastAPI
from iisi_app_core.integrations.fastapi import FastApiMangumBuilder, from_container
def create_app(ctx) -> FastAPI:
from app.users.ports import GetUserProfilePort
router = APIRouter()
@router.get("/users/{user_id}")
def get_user_profile(
user_id: str,
use_case: Annotated[GetUserProfilePort, from_container(GetUserProfilePort)],
) -> dict[str, str]:
return use_case.get_user_profile(user_id)
app = FastAPI()
app.include_router(router)
return app
built = (
FastApiMangumBuilder()
.autoload(app.users)
.app(create_app)
.enable_mangum(lifespan="off")
.build()
)
app = built.app
handler = built.handler
FastApiMangumBuilder reuses the existing autoload(...) and ContainerBuilder.build() logic, then exposes the built container, registry, and modules through app.state.
Standalone Authz
authz is explicit and does not use request-local global state.
from iisi_app_core import Principal, Role, require_role
@require_role(Role.READER)
def view_profile(*, principal: Principal, user_id: str) -> str:
return f"{principal.name}:{user_id}"
principal = Principal.of(name="alice", role=Role.READER, tenant_id="tenant")
result = view_profile(principal=principal, user_id="123")
If your callable does not receive principal= directly, provide principal_getter=...:
from iisi_app_core import Role, require_role
@require_role(Role.ADMIN, principal_getter=lambda args, kwargs: args[0].principal)
def run(command) -> str:
return "ok"
Available authz helpers:
Principal,Roleauthorize,ensure_at_least,at_least,has_rolerequire_roleDomainValidationError,ForbiddenError
Public API
Top-level exports are intentionally small:
- bootstrap:
autoload,ModuleAutoloadError, decorators, metadata types,ComponentRegistry,ContainerBuilder - authz:
Principal,Role,require_role, helper functions,DomainValidationError,ForbiddenError
Everything else from earlier versions is out of scope for this library.
Metadata
Release files for iisi-app-core 0.2.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| iisi_app_core-0.2.2.tar.gz | 17.0 kB | Without provenance | Details for iisi_app_core-0.2.2.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| iisi_app_core-0.2.2-py3-none-any.whl | Python 3 | none | any | Details for iisi_app_core-0.2.2-py3-none-any.whl |
Total release size: 30.3 kB
Release files / iisi_app_core-0.2.2.tar.gz
| Download URL | iisi_app_core-0.2.2.tar.gz |
|---|---|
| Size | 17.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ea27e9adac796b29198871ccec694e2d9eac32a606e603ec61ac73984bd47837
|
|
BLAKE2b-256 checksum How to use checksums |
6ab3b7c6d7bcddea9d0bb1a7a67a6664cb291335ee15e6edb01189f891b0fefa
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.0
|
Release files / iisi_app_core-0.2.2-py3-none-any.whl
| Download URL | iisi_app_core-0.2.2-py3-none-any.whl |
|---|---|
| Size | 13.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
0912dcf3c6937a523290b683b3b77f9d6e795d1de66558feede651e2bf9dca90
|
|
BLAKE2b-256 checksum How to use checksums |
903312518f1a1c20ca09056beb9ac99bddeed0d7fea8f9917ad5be16363aeaac
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.0
|
Security for iisi-app-core 0.2.2
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.