# InjectQ
[](https://pypi.org/project/injectq/)
[](https://pypi.org/project/injectq/)
[](https://github.com/Iamsdt/injectq/blob/main/LICENSE)
[](#)
InjectQ is a modern, lightweight Python dependency injection library focused on clarity, type-safety, and seamless framework integration.
## Documentation
Full documentation is hosted at https://iamsdt.github.io/injectq/ and the repository `docs/` contains the source.
## Key features
- Simplicity-first dict-like API for quick starts
- Flexible decorator- and type-based injection (`@inject`, `Inject[T]`)
- Type-friendly: designed to work with static type checkers
- Built-in integrations for frameworks (FastAPI, Taskiq) as optional extras
- Factory and async factory support
- Scope management and testing utilities
## Quick Start (recommended pattern)
Prefer the exported global `InjectQ.get_instance()` container in examples and application code. It uses the active context container when present, otherwise falls back to a global singleton.
```python
from injectq import InjectQ, inject, singleton
container = InjectQ.get_instance()
# Basic value binding
container[str] = "Hello, World!"
@singleton
class UserService:
def __init__(self, message: str):
self.message = message
def greet(self) -> str:
return f"Service says: {self.message}"
@inject
def main(service: UserService) -> None:
print(service.greet())
if __name__ == "__main__":
main() # Prints: Service says: Hello, World!
```
Notes:
- Use `container[...]` for simple bindings and values.
- Use `@inject` and `Inject[T]` for function/class injection.
## Enhanced Features
### Nullable Dependencies
InjectQ supports binding `None` values for optional dependencies using the `allow_none` parameter:
```python
from injectq import InjectQ
container = InjectQ()
# Optional service - can be None
class EmailService:
def send_email(self, to: str, message: str) -> str:
return f"Email sent to {to}: {message}"
class NotificationService:
def __init__(self, email_service: EmailService | None = None):
self.email_service = email_service
def notify(self, message: str) -> str:
if self.email_service:
return self.email_service.send_email("user", message)
return f"Basic notification: {message}"
# Bind None for optional dependency
container.bind(EmailService, None, allow_none=True)
container.bind(NotificationService, NotificationService)
service = container.get(NotificationService)
print(service.notify("Hello")) # Prints: Basic notification: Hello
```
### Abstract Class Validation
InjectQ automatically prevents binding abstract classes and raises a `BindingError` during binding (not at resolution time):
```python
from abc import ABC, abstractmethod
from injectq import InjectQ
from injectq.utils.exceptions import BindingError
class PaymentProcessor(ABC): # Abstract class
@abstractmethod
def process_payment(self, amount: float) -> str:
pass
class CreditCardProcessor(PaymentProcessor): # Concrete implementation
def process_payment(self, amount: float) -> str:
return f"Processing ${amount} via credit card"
container = InjectQ()
# This will raise BindingError immediately
try:
container.bind(PaymentProcessor, PaymentProcessor) # Error!
except BindingError:
print("Cannot bind abstract class")
# This works fine
container.bind(PaymentProcessor, CreditCardProcessor) # OK
```
See `examples/enhanced_features_demo.py` for a complete demonstration.
## Installation
Install from PyPI:
```bash
pip install injectq
```
Optional framework integrations (install only what you need):
```bash
pip install injectq[fastapi] # FastAPI integration (optional)
pip install injectq[taskiq] # Taskiq integration (optional)
```
## Where to look next
- `docs/getting-started/installation.md` — installation and verification
- `docs/injection-patterns/dict-interface.md` — dict-like API
- `docs/injection-patterns/inject-decorator.md` — `@inject` usage
- `docs/integrations/` — integration guides for FastAPI and Taskiq
## License
MIT — see the `LICENSE` file.
## Run tests with coverage
Activate the project's virtualenv and run pytest (coverage threshold is configured to 73%):
```bash
source .venv/bin/activate
python -m pytest
```
Coverage reports are written to `htmlcov/` and `coverage.xml`.
Raw data
{
"_id": null,
"home_page": null,
"name": "injectq",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.10",
"maintainer_email": null,
"keywords": "container, dependency-injection, di, inversion-of-control, ioc",
"author": "InjectQ Contributors",
"author_email": null,
"download_url": "https://files.pythonhosted.org/packages/29/fa/8d324712876d3361bbb6a21b8dfa77a077ac2047b5bdadd7b1a08983054f/injectq-0.3.1.tar.gz",
"platform": null,
"description": "# InjectQ\n[](https://pypi.org/project/injectq/)\n[](https://pypi.org/project/injectq/)\n[](https://github.com/Iamsdt/injectq/blob/main/LICENSE)\n[](#)\n\n\nInjectQ is a modern, lightweight Python dependency injection library focused on clarity, type-safety, and seamless framework integration.\n\n## Documentation\nFull documentation is hosted at https://iamsdt.github.io/injectq/ and the repository `docs/` contains the source.\n\n## Key features\n\n- Simplicity-first dict-like API for quick starts\n- Flexible decorator- and type-based injection (`@inject`, `Inject[T]`)\n- Type-friendly: designed to work with static type checkers\n- Built-in integrations for frameworks (FastAPI, Taskiq) as optional extras\n- Factory and async factory support\n- Scope management and testing utilities\n\n## Quick Start (recommended pattern)\n\nPrefer the exported global `InjectQ.get_instance()` container in examples and application code. It uses the active context container when present, otherwise falls back to a global singleton.\n\n```python\nfrom injectq import InjectQ, inject, singleton\n\ncontainer = InjectQ.get_instance()\n\n# Basic value binding\ncontainer[str] = \"Hello, World!\"\n\n@singleton\nclass UserService:\n def __init__(self, message: str):\n self.message = message\n\n def greet(self) -> str:\n return f\"Service says: {self.message}\"\n\n@inject\ndef main(service: UserService) -> None:\n print(service.greet())\n\nif __name__ == \"__main__\":\n main() # Prints: Service says: Hello, World!\n```\n\nNotes:\n- Use `container[...]` for simple bindings and values.\n- Use `@inject` and `Inject[T]` for function/class injection.\n\n## Enhanced Features\n\n### Nullable Dependencies\n\nInjectQ supports binding `None` values for optional dependencies using the `allow_none` parameter:\n\n```python\nfrom injectq import InjectQ\n\ncontainer = InjectQ()\n\n# Optional service - can be None\nclass EmailService:\n def send_email(self, to: str, message: str) -> str:\n return f\"Email sent to {to}: {message}\"\n\nclass NotificationService:\n def __init__(self, email_service: EmailService | None = None):\n self.email_service = email_service\n \n def notify(self, message: str) -> str:\n if self.email_service:\n return self.email_service.send_email(\"user\", message)\n return f\"Basic notification: {message}\"\n\n# Bind None for optional dependency\ncontainer.bind(EmailService, None, allow_none=True)\ncontainer.bind(NotificationService, NotificationService)\n\nservice = container.get(NotificationService)\nprint(service.notify(\"Hello\")) # Prints: Basic notification: Hello\n```\n\n### Abstract Class Validation\n\nInjectQ automatically prevents binding abstract classes and raises a `BindingError` during binding (not at resolution time):\n\n```python\nfrom abc import ABC, abstractmethod\nfrom injectq import InjectQ\nfrom injectq.utils.exceptions import BindingError\n\nclass PaymentProcessor(ABC): # Abstract class\n @abstractmethod\n def process_payment(self, amount: float) -> str:\n pass\n\nclass CreditCardProcessor(PaymentProcessor): # Concrete implementation\n def process_payment(self, amount: float) -> str:\n return f\"Processing ${amount} via credit card\"\n\ncontainer = InjectQ()\n\n# This will raise BindingError immediately\ntry:\n container.bind(PaymentProcessor, PaymentProcessor) # Error!\nexcept BindingError:\n print(\"Cannot bind abstract class\")\n\n# This works fine\ncontainer.bind(PaymentProcessor, CreditCardProcessor) # OK\n```\n\nSee `examples/enhanced_features_demo.py` for a complete demonstration.\n\n## Installation\n\nInstall from PyPI:\n\n```bash\npip install injectq\n```\n\nOptional framework integrations (install only what you need):\n\n```bash\npip install injectq[fastapi] # FastAPI integration (optional)\npip install injectq[taskiq] # Taskiq integration (optional)\n```\n\n## Where to look next\n\n- `docs/getting-started/installation.md` \u2014 installation and verification\n- `docs/injection-patterns/dict-interface.md` \u2014 dict-like API\n- `docs/injection-patterns/inject-decorator.md` \u2014 `@inject` usage\n- `docs/integrations/` \u2014 integration guides for FastAPI and Taskiq\n\n## License\n\nMIT \u2014 see the `LICENSE` file.\n\n## Run tests with coverage\n\nActivate the project's virtualenv and run pytest (coverage threshold is configured to 73%):\n\n```bash\nsource .venv/bin/activate\npython -m pytest\n```\n\nCoverage reports are written to `htmlcov/` and `coverage.xml`.",
"bugtrack_url": null,
"license": null,
"summary": "Modern Python dependency injection library combining simplicity, power, and performance",
"version": "0.3.1",
"project_urls": {
"Documentation": "https://github.com/Iamsdt/injectq",
"Homepage": "https://github.com/Iamsdt/injectq",
"Issues": "https://github.com/Iamsdt/injectq/issues",
"Repository": "https://github.com/Iamsdt/injectq"
},
"split_keywords": [
"container",
" dependency-injection",
" di",
" inversion-of-control",
" ioc"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "bdb61a5e2d5c04e9405b94bb0d982530a6246d2515242b38bbfbfe3ccdc29c96",
"md5": "3171451d77b8181a8e677107cdeaabe8",
"sha256": "e53d8ccfbe0da928e27da6794738b11c3fdff95135f3191ba9ae062d23176699"
},
"downloads": -1,
"filename": "injectq-0.3.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "3171451d77b8181a8e677107cdeaabe8",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.10",
"size": 64501,
"upload_time": "2025-09-08T05:37:43",
"upload_time_iso_8601": "2025-09-08T05:37:43.347101Z",
"url": "https://files.pythonhosted.org/packages/bd/b6/1a5e2d5c04e9405b94bb0d982530a6246d2515242b38bbfbfe3ccdc29c96/injectq-0.3.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "29fa8d324712876d3361bbb6a21b8dfa77a077ac2047b5bdadd7b1a08983054f",
"md5": "cc32981b4f312350d5fd002d3dbfedca",
"sha256": "2cef919b5636ee99ded2d11035b3ca6e86a2fb3dd47ac7c7eb163c663bb516c8"
},
"downloads": -1,
"filename": "injectq-0.3.1.tar.gz",
"has_sig": false,
"md5_digest": "cc32981b4f312350d5fd002d3dbfedca",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.10",
"size": 464740,
"upload_time": "2025-09-08T05:37:47",
"upload_time_iso_8601": "2025-09-08T05:37:47.289369Z",
"url": "https://files.pythonhosted.org/packages/29/fa/8d324712876d3361bbb6a21b8dfa77a077ac2047b5bdadd7b1a08983054f/injectq-0.3.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-09-08 05:37:47",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "Iamsdt",
"github_project": "injectq",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"lcname": "injectq"
}