Skip to content

Commit

Permalink
Update docs
Browse files Browse the repository at this point in the history
  • Loading branch information
maldoinc committed Aug 24, 2024
1 parent 6329d43 commit dde3868
Show file tree
Hide file tree
Showing 7 changed files with 41 additions and 31 deletions.
1 change: 1 addition & 0 deletions docs/mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ nav:
- Demo application: demo_app.md
- Versioning: versioning.md
- Integrations:
- Integrations: integrations/index.md
- Django: integrations/django.md
- FastAPI: integrations/fastapi.md
- Flask: integrations/flask.md
Expand Down
14 changes: 4 additions & 10 deletions docs/pages/configuration.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
Wireup configuration can be injected through annotations or programmatically using factory functions.
You can mix and match the two as necessary, but for consistency, it's best to stick to one approach for a given project.
You can also mix and match the two as necessary.

## @ Annotations

This declarative approach uses configuration metadata provided by decorators and annotations to define services and dependencies between them.
It allows you to declare the final state and let the container handle the rest, rather than imperatively coding object creation and dependency injection.
It allows you to declare the final state and let the container handle the rest.

This generally results in less boilerplate code compared to a programmatic approach and is how many popular frameworks operate.

Expand All @@ -23,7 +23,6 @@ Factories can request dependencies as usual and may use annotations for configur

## @ Annotation-based configuration
In addition to service objects, the container also holds configuration, called parameters.
Adding configuration is done by using `container.params`.

!!! warning
**Parameters represent application configuration**.
Expand All @@ -38,7 +37,7 @@ Adding configuration is done by using `container.params`.
To inject a parameter by name, annotate the type with `Inject(param="param_name")`.

```python
@service
@container.autowire
def target(cache_dir: Annotated[str, Inject(param="cache_dir")]) -> None:
...
```
Expand Down Expand Up @@ -80,6 +79,7 @@ Examples use [pydantic-settings](https://docs.pydantic.dev/latest/concepts/pydan
from pydantic_settings import BaseSettings
from pydantic import Field, PostgresDsn


class Settings(BaseSettings):
gh_api_key: str = Field(alias="gh_api_key")
pg_dsn: PostgresDsn = Field(alias="pg_dsn")
Expand Down Expand Up @@ -108,12 +108,6 @@ To wire everything together we can use a few factories.
```python title="factories.py"
from wireup import service, container

# Since settings has no parameters it can also be
# registered directly as the constructor can be the factory.
container.register(Settings)


# If it needs additional configuration then it is also possible to use a regular factory.
@service
def settings_factory() -> Settings:
return Settings(...)
Expand Down
38 changes: 22 additions & 16 deletions docs/pages/getting_started.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,26 +50,32 @@ The first step is to initialize the container on application startup.
```

=== "🏭 Programmatic"
```python title="main.py" hl_lines="15 19"
from pydantic import Field
Register application settings as a service.

```python title="services/config.py"
from pydantic_settings import BaseSettings
from wireup import container, initialize_container
from wireup import service

from myapp.services import factories

@service
class Settings(BaseSettings):
redis_url: str = Field(alias="APP_REDIS_URL")
weather_api_key: str = Field(alias="APP_WEATHER_API_KEY")
```

In the application's entrypoint initialize wireup.

```python title="main.py" hl_lines="15 19"
from pydantic import Field
from wireup import container, initialize_container

from myapp import services

def create_app():
app = ...
# Expose configuration as a service in the container.
container.register(Settings)
# ⬇️ Start the container: Register and initialize services.
# service_modules is a list of top-level modules containing registrations.
initialize_container(container, service_modules=[factories])
initialize_container(container, service_modules=[services])

return app
```
Expand Down Expand Up @@ -150,14 +156,13 @@ Next, we add a weather service that will perform requests against a remote serve
from wireup import service

@service #(1)!
@dataclass
@dataclass # TIP: Use alongside dataclasses to simplify init code.
class WeatherService:
api_key: Annotated[str, Inject(param="weather_api_key")]
kv_store: KeyValueStore

async def get_forecast(self, lat: float, lon: float) -> WeatherForecast:
# implementation omitted for brevity
pass
raise NotImplementedError
```

1. * Injection is supported for regular classes as well as dataclasses.
Expand All @@ -174,8 +179,7 @@ Next, we add a weather service that will perform requests against a remote serve
kv: KeyValueStore

async def get_forecast(self, lat: float, lon: float) -> WeatherForecast:
# implementation omitted for brevity
pass
raise NotImplementedError
```

```python title="services/factories.py" hl_lines="3 4"
Expand Down Expand Up @@ -209,11 +213,13 @@ This concludes the "Getting Started" walkthrough, covering the most common depen

!!! info "Good to know"
* The `@container.autowire` decorator is not needed for services.
* Wireup can perform injection on both sync and async functions.
* When using the [FastAPI](integrations/fastapi.md), or [Flask](integrations/flask.md) integrations,
decorating views with `@container.autowire` is no longer required.
* Wireup can perform injection on both sync and async targets.

## Next Steps

Use Wireup with the provided framework integrations
While Wireup is framework-agnostic, usage can be further simplified in following frameworks:

- [Django](integrations/django.md)
- [FastAPI](integrations/fastapi.md)
Expand Down
2 changes: 1 addition & 1 deletion docs/pages/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ Performant, concise, and easy-to-use dependency injection container for Python 3

## Framework integrations

Simplified integration with the following frameworks.
Simplified use with the following frameworks.

- [x] [Django](integrations/django.md)
- [x] [FastAPI](integrations/fastapi.md)
Expand Down
7 changes: 7 additions & 0 deletions docs/pages/integrations/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Integrations

Wireup is framework-agnostic and can be used in any project, but it also provides integrations for the following frameworks:

- [x] [Django](django.md)
- [x] [FastAPI](fastapi.md)
- [x] [Flask](flask.md)
2 changes: 1 addition & 1 deletion docs/pages/interfaces.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ def target(
## Default implementation

If there are many implementations associated with a given interface, you may want to associate one of them as the
"default" implementation.
default implementation.

To accomplish that, omit the qualifier when registering the implementation.

Expand Down
8 changes: 5 additions & 3 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,13 @@

## ⚡ Key Features
* Inject services and configuration.
* Support for interfaces and abstract classes.
* Interfaces and abstract classes.
* Factory pattern.
* Singleton and transient dependencies.
* Framework-agnostic.
* Simplified integration with [Django](https://maldoinc.github.io/wireup/latest/integrations/django/),
* Apply the container anywhere as a decorator
* Service Locator
* Simplified use with [Django](https://maldoinc.github.io/wireup/latest/integrations/django/),
[Flask](https://maldoinc.github.io/wireup/latest/integrations/flask/), and
[FastAPI](https://maldoinc.github.io/wireup/latest/integrations/fastapi/).

Expand Down Expand Up @@ -69,7 +71,7 @@ class KeyValueStore:


@service
@dataclass
@dataclass # Can be used alongside dataclasses to simplify init boilerplate.
class WeatherService:
# Inject the value of the parameter to this field. ⬇️
api_key: Annotated[str, Inject(param="weather_api_key")]
Expand Down

0 comments on commit dde3868

Please sign in to comment.