Name | aiogram-dependency JSON |
Version |
1.0.3
JSON |
| download |
home_page | None |
Summary | A FastAPI-style dependency injection system for aiogram Telegram bots. This library brings clean, type-safe dependency injection to your aiogram handlers, making your code more modular, testable, and maintainable. |
upload_time | 2025-08-01 11:43:36 |
maintainer | None |
docs_url | None |
author | Vladyslav Chaliuk |
requires_python | >=3.11 |
license | None |
keywords |
|
VCS |
|
bugtrack_url |
|
requirements |
No requirements were recorded.
|
Travis-CI |
No Travis.
|
coveralls test coverage |
No coveralls.
|
# Aiogram Dependency Injection
A FastAPI-style dependency injection system for aiogram Telegram bots. This library brings clean, type-safe dependency injection to your aiogram handlers, making your code more modular, testable, and maintainable.
[](https://pepy.tech/projects/aiogram-dependency)
## Features
- ๐ **FastAPI-style syntax** - Familiar `Depends()` decorator
- ๐ **Multiple dependency scopes** - Singleton, Request, and Transient
- ๐๏ธ **Nested dependencies** - Dependencies can depend on other dependencies
- โก **Async support** - Both sync and async dependency functions
- ๐ก๏ธ **Circular dependency detection** - Prevents infinite loops
- ๐งช **Type-safe** - Full type hints support
- ๐พ **Smart caching** - Efficient resource management
## Installation
```bash
pip install aiogram-dependency
```
Or install from source:
```bash
git clone https://github.com/AstralMortem/aiogram-dependency
cd aiogram-dependency
pip install -e .
```
## Quick Start
```python
import asyncio
from aiogram import Bot, Dispatcher, F
from aiogram.types import Message
from aiogram_dependency import Depends, setup_dependency, Scope
# Define your dependencies
class DatabaseConnection:
def __init__(self, connection_string: str):
self.connection_string = connection_string
async def query(self, sql: str):
# Your database logic here
return f"Result for: {sql}"
class UserService:
def __init__(self, db: DatabaseConnection):
self.db = db
async def get_user_profile(self, user_id: int):
return await self.db.query(f"SELECT * FROM users WHERE id = {user_id}")
# Dependency factories
async def get_database() -> DatabaseConnection:
return DatabaseConnection("postgresql://localhost/mydb")
async def get_user_service(
db: DatabaseConnection = Depends(get_database, scope=Scope.SINGLETON)
) -> UserService:
return UserService(db)
# Handler with dependency injection
async def profile_handler(
message: Message,
user_service: UserService = Depends(get_user_service)
):
if not message.from_user:
await message.answer("User not found")
return
profile = await user_service.get_user_profile(message.from_user.id)
await message.answer(f"Your profile: {profile}")
# Setup bot (ORDER MATER!)
async def main():
bot = Bot(token="YOUR_BOT_TOKEN")
dp = Dispatcher()
# Register handlers
dp.message.register(profile_handler, F.text == "/profile")
# Register dependency injection
setup_dependency(dp)
await dp.start_polling(bot)
if __name__ == "__main__":
asyncio.run(main())
```
## Dependency Scopes
### Singleton
Created once and shared across all requests globally.
```python
async def get_database() -> DatabaseConnection:
return DatabaseConnection("connection_string")
async def handler(
message: Message,
db: DatabaseConnection = Depends(get_database, scope=Scope.SINGLETON)
):
# Same database instance for all users
pass
```
### Request (Default)
Created once per user/chat and cached for subsequent calls in the same context.
```python
async def get_user_service() -> UserService:
return UserService()
async def handler(
message: Message,
service: UserService = Depends(get_user_service, scope=Scope.REQUEST)
):
# Same service instance for this user, different for other users
pass
```
### Transient
Created fresh every time it's requested.
```python
async def get_timestamp() -> float:
return time.time()
async def handler(
message: Message,
timestamp: float = Depends(get_timestamp, scope=Scope.TRANSIENT)
):
# New timestamp every time
pass
```
## Advanced Usage
### Annotated
You can use Annotated type to make it more readable.
```python
from typing import Annotated
from aiogram_dependency import Depends
from aiogram import Dispatcher,filters,types
async def get_database() -> DatabaseConnection:
return DatabaseConnection("postgresql://localhost/db")
DatabaseDep = Annotated[DatabaseConnection, Depends(get_database)]
async def get_user(db: DatabaseDep):
return db.execute('SQL')
UserDep = Annotated[dict, Depends(get_user)]
dp = Dispatcher()
@dp.message(filters.CommandStart())
async def start(message:types.Message, user: UserDep):
return await message.answer(user['username'])
```
### Nested Dependencies
Dependencies can depend on other dependencies:
```python
async def get_database() -> DatabaseConnection:
return DatabaseConnection("postgresql://localhost/db")
async def get_user_repository(
db: DatabaseConnection = Depends(get_database)
) -> UserRepository:
return UserRepository(db)
async def get_user_service(
user_repo: UserRepository = Depends(get_user_repository),
notification_service: NotificationService = Depends(get_notification_service)
) -> UserService:
return UserService(user_repo, notification_service)
```
### Using Event Data in Dependencies
Dependencies can access the current event and handler data:
```python
async def get_current_user(event: Message) -> Optional[User]:
return event.from_user
async def get_user_permissions(
event: Message,
data: dict,
current_user: User = Depends(get_current_user)
) -> List[str]:
# Access event, data, and other dependencies
if current_user and current_user.id in data.get('admins', []):
return ['admin', 'user']
return ['user']
async def admin_handler(
message: Message,
permissions: List[str] = Depends(get_user_permissions)
):
if 'admin' not in permissions:
await message.answer("Access denied")
return
await message.answer("Welcome, admin!")
```
### Custom Registry and Resolver
For advanced use cases, you can customize the dependency system:
```python
from aiogram_dependency.registry import DependencyRegistry
from aiogram_dependency.resolver import DependencyResolver
from aiogram_dependency.middleware import DependencyMiddleware
from aiogram_dependency import Scope
# Create custom registry
registry = DependencyRegistry()
db_dep = Depends(get_database, scope=Scope.SINGLETON)
# Pre-populate with some dependencies
registry.set_dependency(
db_dep,
DatabaseConnection("custom://connection"),
"global"
)
# Use custom middleware
middleware = DependencyMiddleware(registry)
dp.message.middleware(middleware)
```
## Testing
The library is fully testable. Here's an example:
Run the full test suite:
```bash
# Install test dependencies
pip install pytest pytest-asyncio
# Run tests
pytest tests/ -v
# Run with coverage
pytest tests/ --cov=aiogram_dependency --cov-report=html
```
## License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
## Related Projects
- [aiogram](https://github.com/aiogram/aiogram) - Modern and fully asynchronous framework for Telegram Bot API
- [FastAPI](https://github.com/tiangolo/fastapi) - Modern, fast web framework for building APIs with Python
Raw data
{
"_id": null,
"home_page": null,
"name": "aiogram-dependency",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.11",
"maintainer_email": null,
"keywords": null,
"author": "Vladyslav Chaliuk",
"author_email": "chaliukvladyslav@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/fb/b7/930dd4d7e3cfd8049c3c55b511552801f019c291ca63ab7ac0ada5a743fc/aiogram_dependency-1.0.3.tar.gz",
"platform": null,
"description": "# Aiogram Dependency Injection\n\nA FastAPI-style dependency injection system for aiogram Telegram bots. This library brings clean, type-safe dependency injection to your aiogram handlers, making your code more modular, testable, and maintainable.\n\n[](https://pepy.tech/projects/aiogram-dependency)\n## Features\n\n- \ud83d\ude80 **FastAPI-style syntax** - Familiar `Depends()` decorator\n- \ud83d\udd04 **Multiple dependency scopes** - Singleton, Request, and Transient\n- \ud83c\udfd7\ufe0f **Nested dependencies** - Dependencies can depend on other dependencies\n- \u26a1 **Async support** - Both sync and async dependency functions\n- \ud83d\udee1\ufe0f **Circular dependency detection** - Prevents infinite loops\n- \ud83e\uddea **Type-safe** - Full type hints support\n- \ud83d\udcbe **Smart caching** - Efficient resource management\n\n## Installation\n\n```bash\npip install aiogram-dependency\n```\n\nOr install from source:\n\n```bash\ngit clone https://github.com/AstralMortem/aiogram-dependency\ncd aiogram-dependency\npip install -e .\n```\n\n## Quick Start\n\n```python\nimport asyncio\nfrom aiogram import Bot, Dispatcher, F\nfrom aiogram.types import Message\n\nfrom aiogram_dependency import Depends, setup_dependency, Scope\n\n# Define your dependencies\nclass DatabaseConnection:\n def __init__(self, connection_string: str):\n self.connection_string = connection_string\n \n async def query(self, sql: str):\n # Your database logic here\n return f\"Result for: {sql}\"\n\nclass UserService:\n def __init__(self, db: DatabaseConnection):\n self.db = db\n \n async def get_user_profile(self, user_id: int):\n return await self.db.query(f\"SELECT * FROM users WHERE id = {user_id}\")\n\n# Dependency factories\nasync def get_database() -> DatabaseConnection:\n return DatabaseConnection(\"postgresql://localhost/mydb\")\n\nasync def get_user_service(\n db: DatabaseConnection = Depends(get_database, scope=Scope.SINGLETON)\n) -> UserService:\n return UserService(db)\n\n# Handler with dependency injection\nasync def profile_handler(\n message: Message,\n user_service: UserService = Depends(get_user_service)\n):\n if not message.from_user:\n await message.answer(\"User not found\")\n return\n \n profile = await user_service.get_user_profile(message.from_user.id)\n await message.answer(f\"Your profile: {profile}\")\n\n# Setup bot (ORDER MATER!)\nasync def main():\n bot = Bot(token=\"YOUR_BOT_TOKEN\")\n dp = Dispatcher()\n \n # Register handlers\n dp.message.register(profile_handler, F.text == \"/profile\")\n\n # Register dependency injection \n setup_dependency(dp)\n \n await dp.start_polling(bot)\n\nif __name__ == \"__main__\":\n asyncio.run(main())\n```\n\n## Dependency Scopes\n\n### Singleton\nCreated once and shared across all requests globally.\n\n```python\nasync def get_database() -> DatabaseConnection:\n return DatabaseConnection(\"connection_string\")\n\nasync def handler(\n message: Message,\n db: DatabaseConnection = Depends(get_database, scope=Scope.SINGLETON)\n):\n # Same database instance for all users\n pass\n```\n\n### Request (Default)\nCreated once per user/chat and cached for subsequent calls in the same context.\n\n```python\nasync def get_user_service() -> UserService:\n return UserService()\n\nasync def handler(\n message: Message,\n service: UserService = Depends(get_user_service, scope=Scope.REQUEST)\n):\n # Same service instance for this user, different for other users\n pass\n```\n\n### Transient\nCreated fresh every time it's requested.\n\n```python\nasync def get_timestamp() -> float:\n return time.time()\n\nasync def handler(\n message: Message,\n timestamp: float = Depends(get_timestamp, scope=Scope.TRANSIENT)\n):\n # New timestamp every time\n pass\n```\n\n## Advanced Usage\n\n### Annotated\n\nYou can use Annotated type to make it more readable.\n```python\nfrom typing import Annotated\nfrom aiogram_dependency import Depends\nfrom aiogram import Dispatcher,filters,types\n\nasync def get_database() -> DatabaseConnection:\n return DatabaseConnection(\"postgresql://localhost/db\")\n\nDatabaseDep = Annotated[DatabaseConnection, Depends(get_database)]\n\nasync def get_user(db: DatabaseDep):\n return db.execute('SQL')\n\nUserDep = Annotated[dict, Depends(get_user)]\n\ndp = Dispatcher()\n\n@dp.message(filters.CommandStart())\nasync def start(message:types.Message, user: UserDep):\n return await message.answer(user['username'])\n\n\n```\n\n\n### Nested Dependencies\n\nDependencies can depend on other dependencies:\n\n```python\nasync def get_database() -> DatabaseConnection:\n return DatabaseConnection(\"postgresql://localhost/db\")\n\nasync def get_user_repository(\n db: DatabaseConnection = Depends(get_database)\n) -> UserRepository:\n return UserRepository(db)\n\nasync def get_user_service(\n user_repo: UserRepository = Depends(get_user_repository),\n notification_service: NotificationService = Depends(get_notification_service)\n) -> UserService:\n return UserService(user_repo, notification_service)\n```\n\n### Using Event Data in Dependencies\n\nDependencies can access the current event and handler data:\n\n```python\nasync def get_current_user(event: Message) -> Optional[User]:\n return event.from_user\n\nasync def get_user_permissions(\n event: Message,\n data: dict,\n current_user: User = Depends(get_current_user)\n) -> List[str]:\n # Access event, data, and other dependencies\n if current_user and current_user.id in data.get('admins', []):\n return ['admin', 'user']\n return ['user']\n\nasync def admin_handler(\n message: Message,\n permissions: List[str] = Depends(get_user_permissions)\n):\n if 'admin' not in permissions:\n await message.answer(\"Access denied\")\n return\n \n await message.answer(\"Welcome, admin!\")\n```\n\n### Custom Registry and Resolver\n\nFor advanced use cases, you can customize the dependency system:\n\n```python\nfrom aiogram_dependency.registry import DependencyRegistry\nfrom aiogram_dependency.resolver import DependencyResolver\nfrom aiogram_dependency.middleware import DependencyMiddleware\nfrom aiogram_dependency import Scope\n\n# Create custom registry\nregistry = DependencyRegistry()\n\ndb_dep = Depends(get_database, scope=Scope.SINGLETON)\n\n# Pre-populate with some dependencies\nregistry.set_dependency(\n db_dep,\n DatabaseConnection(\"custom://connection\"),\n \"global\"\n)\n\n# Use custom middleware\nmiddleware = DependencyMiddleware(registry)\ndp.message.middleware(middleware)\n```\n\n## Testing\n\nThe library is fully testable. Here's an example:\n\n\nRun the full test suite:\n\n```bash\n# Install test dependencies\npip install pytest pytest-asyncio\n\n# Run tests\npytest tests/ -v\n\n# Run with coverage\npytest tests/ --cov=aiogram_dependency --cov-report=html\n```\n\n\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\n\n\n## Related Projects\n\n- [aiogram](https://github.com/aiogram/aiogram) - Modern and fully asynchronous framework for Telegram Bot API\n- [FastAPI](https://github.com/tiangolo/fastapi) - Modern, fast web framework for building APIs with Python\n\n",
"bugtrack_url": null,
"license": null,
"summary": "A FastAPI-style dependency injection system for aiogram Telegram bots. This library brings clean, type-safe dependency injection to your aiogram handlers, making your code more modular, testable, and maintainable.",
"version": "1.0.3",
"project_urls": null,
"split_keywords": [],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "8f48f093065397f83293855a78baac5deb5ea8278a86afd7fd708c98c902bfbc",
"md5": "c5c3d19c6930259724dddbe97287e524",
"sha256": "3ed8567aec9b4ef81b0e8166a7746ab1ecf6f90943be061af46937c99d26df7f"
},
"downloads": -1,
"filename": "aiogram_dependency-1.0.3-py3-none-any.whl",
"has_sig": false,
"md5_digest": "c5c3d19c6930259724dddbe97287e524",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.11",
"size": 9164,
"upload_time": "2025-08-01T11:43:35",
"upload_time_iso_8601": "2025-08-01T11:43:35.433358Z",
"url": "https://files.pythonhosted.org/packages/8f/48/f093065397f83293855a78baac5deb5ea8278a86afd7fd708c98c902bfbc/aiogram_dependency-1.0.3-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "fbb7930dd4d7e3cfd8049c3c55b511552801f019c291ca63ab7ac0ada5a743fc",
"md5": "133c316659c4315a5618349f6be21f45",
"sha256": "92aa5a9dff946bd25d4876a219675c220ae15393ec697a6f5214fe8e51c31bc2"
},
"downloads": -1,
"filename": "aiogram_dependency-1.0.3.tar.gz",
"has_sig": false,
"md5_digest": "133c316659c4315a5618349f6be21f45",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.11",
"size": 6644,
"upload_time": "2025-08-01T11:43:36",
"upload_time_iso_8601": "2025-08-01T11:43:36.999270Z",
"url": "https://files.pythonhosted.org/packages/fb/b7/930dd4d7e3cfd8049c3c55b511552801f019c291ca63ab7ac0ada5a743fc/aiogram_dependency-1.0.3.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-08-01 11:43:36",
"github": false,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"lcname": "aiogram-dependency"
}