Skip to main content

Soupape

Soupape is a dependency injection and inversion of control library in pure Python. It allows you to manage the dependencies of your services in your application in a clean and efficient way. Soupape is a standalone library that does not rely on any framework and can be used in any Python project.

Synchronous and asynchronous applications get the same API: SyncInjector and AsyncInjector register, resolve and dispose services the same way.

Installation

$ pip install soupape  # or use your preferred package manager

Soupape requires Python 3.13 or later.

Quick start

Write your services as plain classes. The dependencies are declared as type hints in the constructor, and the injector will resolve them automatically.

from typing import Any

from my_app.models import User


class HttpService:
    async def get(self, url: str) -> dict[str, Any]: ...


class UserService:
    async def get_user(self, user_id: int) -> User: ...


class AuthService:
    def __init__(self, http: HttpService, user_service: UserService) -> None:
        self.http = http
        self.user_service = user_service

    async def authenticate(self, token: str) -> User: ...

Register them in a ServiceCollection, then resolve them from an injector.

from soupape import AsyncInjector, ServiceCollection

from my_app.services import AuthService, HttpService, UserService


def define_services() -> ServiceCollection:
    services = ServiceCollection()
    services.add_singleton(HttpService)
    services.add_scoped(UserService)
    services.add_scoped(AuthService)
    return services


async def main() -> None:
    async with AsyncInjector(define_services()) as injector:
        async with injector.get_scoped_injector() as scoped_injector:
            auth_service = await scoped_injector.require(AuthService)
            token = ...  # obtain token from somewhere
            user = await auth_service.authenticate(token)

HttpService is a singleton: a single instance shared for the lifetime of the main injector. UserService and AuthService are scoped: a new instance per scoped injector, disposed of when that injection session closes. The same registrations run on a SyncInjector, as long as no service requires asynchronous initialization.

What Soupape does

  • Service lifetimes — singleton, scoped and transient. Each service can define its own lifetime, the nested injectors will manage their instances accordingly.
  • Injection sessions — scoped injectors, nested or not. Scoped services will be created once per session, and disposed of when the session they belong to closes. Child sessions will inherit the parent session's scoped services.
  • Initialization and teardown — services can implement the sync or async context manager protocol, or declare @post_init hooks. The injector will enter them as it builds them, and exit them in reverse order, the dependents before their dependencies.
  • Resolver functions — register a function instead of a class, synchronous, asynchronous, or a generator that cleans up on teardown. Its return type hint is the registration.
  • Function calls — injector.call(func) will inject the parameters of any function and call it. Some parameters can be given as positional_args or named_args, the injector will resolve the others.
  • Per-call fallbacks — require and call accept a list of fallback resolvers. They will serve the parameters no registered service matches, by name or by anything else the resolution context knows about.
  • Custom and annotated resolvers — soupape.extension is the extension surface. A ServiceResolver will take over a whole type, an Annotated marker with a __resolve__ method will build a single parameter.
  • Collection and context injection — a list[T] or a dict[str, T] parameter will receive every registered service assignable to T. The injector itself, the resolution context and the caller context can be injected the same way.
  • Generic services — generic services are registered and resolved by specialization. Repository[User] and Repository[Order] are two different services.
  • Registration helpers — the @injectable decorators will register your services from a cache. depends_on declares a service that must be resolved first, typically one that registers other services.
  • Errors — every failure raises a SoupapeError with its own error code. Unknown services, missing type hints, captive dependencies and circular dependencies are all detected before any instance is created.

Soupape is fully typed and checked in Pyright's strict mode.

License

Soupape is released under the MIT license, see LICENSE.txt.

Metadata

Release files for soupape 0.10.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for soupape 0.10.0
File Size Uploaded
soupape-0.10.0.tar.gz 18.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for soupape 0.10.0
File Interpreter ABI Platform
soupape-0.10.0-py3-none-any.whl Python 3 none any Details

Total release size: 49.8 kB

Release files / soupape-0.10.0.tar.gz

Download URL soupape-0.10.0.tar.gz
Size 18.3 kB
Tags Source
SHA-256 checksum
How to use checksums
66677491a78858e5ea4e5d32345b279e5774b3e0f24ef4472b76a38a66bd47d9
BLAKE2b-256 checksum
How to use checksums
50c75a54ddfcc91f832874378fec3c82295439db74bd16153f5a89a302c1b83c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.13 {"installer":{"name":"uv","version":"0.12.13","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / soupape-0.10.0-py3-none-any.whl

Download URL soupape-0.10.0-py3-none-any.whl
Size 31.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f2c2e366d80978681df9e1a729ca3ac5fc5521e3766948ba94d859826888bbd2
BLAKE2b-256 checksum
How to use checksums
48548d918d8de372c3378478b1ad19f0275d24cf879062dc84cd0b1c4674a25d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.13 {"installer":{"name":"uv","version":"0.12.13","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

This release

0.10.0 This release

2 release files

0.9.0

2 release files

0.8.0

2 release files

0.7.0

2 release files

0.6.3

2 release files

0.6.2

2 release files

0.6.1

2 release files

0.6.0

2 release files

0.5.0

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page