Metadata-Version: 2.4
Name: exit-stack-container
Version: 0.1.2
Summary: Async lifecycle management with declarative dependency injection
Project-URL: Repository, https://github.com/qqqoid/exit-stack-container
Project-URL: Issues, https://github.com/qqqoid/exit-stack-container/issues
Author-email: "Salavat D. Samigoullin" <qqq@oid.su>
License: MIT
License-File: LICENSE
Keywords: async,asyncio,dependency-injection,di-container,lifecycle
Classifier: Development Status :: 3 - Alpha
Classifier: Framework :: AsyncIO
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.13
Requires-Dist: msgspec-settings>=0.1.0
Requires-Dist: msgspec>=0.20.0
Provides-Extra: dev
Requires-Dist: ipykernel>=6.29.5; extra == 'dev'
Requires-Dist: ipython>=8.18.0; extra == 'dev'
Requires-Dist: ipywidgets>=8.1.0; extra == 'dev'
Description-Content-Type: text/markdown

# exit-stack-container

Async lifecycle management with declarative dependency injection for Python 3.13+.

Automatically initialize and cleanup application resources (database connections, caches, clients) when your app starts and stops using async context manager pattern.

## Installation

```bash
pip install exit-stack-container
```

## Quick Start

```python
from msgspec import Struct
from msgspec_settings import BaseSettings

from exit_stack_container import AsyncExitStackContainer, BaseResources, Dependency, on_exit


class Database:
    def __init__(self, host: str, port: int):
        print(f"Database connected to {host}:{port}")

    def close(self):
        print("Database connection closed")


@on_exit(lambda db: db.close)
def create_database(*, host: str, port: int) -> Database:
    return Database(host=host, port=port)


class DatabaseSettings(Struct, frozen=True):
    host: str = "localhost"
    port: int = 5432

class AppSettings(BaseSettings):
    database: DatabaseSettings

class AppResources(BaseResources[AppSettings]):
    database: Database

class AppContainer(AsyncExitStackContainer[AppSettings, AppResources]):
    _settings: AppSettings = AppSettings()

    database: Dependency = Dependency(
        create_database,
        host=_settings.database.host,
        port=_settings.database.port,
    )


# Use with async context manager - automatic init and cleanup
async def main():
    async with AppContainer() as resources:
        # resources.database is ready to use
        # cleanup happens automatically on exit
        pass
```

## Features

- **Declarative DI** — Define dependencies with type-safe descriptors
- **Async lifecycle** — Automatic resource initialization and cleanup via async context manager
- **Topological sorting** — Dependencies resolved in correct order automatically
- **Circular detection** — Prevents circular dependency issues at runtime
- **Single active context** — Container cannot be re-entered before exiting

## License

MIT
