Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Justfile
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,7 @@ hook:

unhook:
uv run pre-commit uninstall

docs:
uv pip install -r docs/requirements.txt
uv run mkdocs serve
2 changes: 1 addition & 1 deletion docs/css/code.css
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* Round the corners of code blocks */
.md-typeset .highlight code {
border-radius: 6px !important;
border-radius: 10px !important;
}

@media (max-width: 600px) {
Expand Down
3 changes: 3 additions & 0 deletions docs/dev/contributing.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,6 @@ Run all checks by command `just lint`

## Running tests
Run all tests by command `just tests`

## Building and running the documentation
Host the documentation locally by running `just docs`
113 changes: 35 additions & 78 deletions docs/index.md
Original file line number Diff line number Diff line change
@@ -1,106 +1,63 @@
# Quickstart
## Install
```bash
pip install that-depends
```
# That Depends

## Describe resources and classes:
```python
import dataclasses
import logging
import typing
Welcome to the `that-depends` documentation!

`that-depends` is a python dependency injection framework which, among other things,
supports the following:

logger = logging.getLogger(__name__)
- Async and sync dependency resolution
- Scopes and granular context management
- Dependency injection anywhere
- Fully typed and tested
- Compatibility with popular frameworks like `FastAPI` and `LiteStar`
- Python 3.10+ support

---

# singleton provider with finalization
def create_sync_resource() -> typing.Iterator[str]:
logger.debug("Resource initiated")
try:
yield "sync resource"
finally:
logger.debug("Resource destructed")
## Installation

```bash
pip install that-depends
```

---

## Quickstart

# same, but async
async def create_async_resource() -> typing.AsyncIterator[str]:
### Define a creator
```python
async def create_async_resource():
logger.debug("Async resource initiated")
try:
yield "async resource"
finally:
logger.debug("Async resource destructed")


@dataclasses.dataclass(kw_only=True, slots=True)
class DependentFactory:
sync_resource: str
async_resource: str
```

## Describe IoC-container
### Setup Dependency Injection Container with Providers
```python
from that_depends import BaseContainer, providers


class DIContainer(BaseContainer):
sync_resource = providers.Resource(create_sync_resource)
async_resource = providers.Resource(create_async_resource)

simple_factory = providers.Factory(SimpleFactory, dep1="text", dep2=123)
dependent_factory = providers.Factory(
sync_resource=sync_resource,
async_resource=async_resource,
)
class Container(BaseContainer):
provider = providers.Resource(create_async_resource)
```

## Resolve dependencies in your code
```python
# async resolving by default:
await DIContainer.simple_factory()

# sync resolving is also allowed if there is no uninitialized async resources in dependencies
DIContainer.simple_factory.sync_resolve()
See the [containers documentation](introduction/ioc-container.md) for more information on defining the container.

# otherwise you can initialize resources beforehand one by one or in one call:
await DIContainer.init_resources()
```

## Resolve dependencies not described in container
For a list of providers and their usage, see the [providers section](providers/collections.md).
### Resolve dependencies in your code
```python
@dataclasses.dataclass(kw_only=True, slots=True)
class FreeFactory:
dependent_factory: DependentFactory
sync_resource: str

# this way container will try to find providers by names and resolve them to build FreeFactory instance
free_factory_instance = await DIContainer.resolve(FreeFactory)
await Container.provider()
```

## Inject providers in function arguments
### Inject providers in function arguments
```python
import datetime

from that_depends import inject, Provide

from tests import container


@inject
async def some_coroutine(
simple_factory: container.SimpleFactory = Provide[container.DIContainer.simple_factory],
dependent_factory: container.DependentFactory = Provide[container.DIContainer.dependent_factory],
default_zero: int = 0,
) -> None:
assert simple_factory.dep1
assert isinstance(dependent_factory.async_resource, datetime.datetime)
assert default_zero == 0
async def some_foo(value: str = Provide[Container.provider]):
return value

@inject
def some_function(
simple_factory: container.SimpleFactory = Provide[container.DIContainer.simple_factory],
default_zero: int = 0,
) -> None:
assert simple_factory.dep1
assert default_zero == 0
await some_foo() # "async resource"
```

See the [injection documentation](introduction/injection.md) for more information.
Loading