Punq
An unintrusive library for dependency injection in modern Python. Inspired by Funq, Punq is a dependency injection library you can understand.
- No global state
- No decorators
- No weird syntax applied to arguments
- Supports type checking with strict modes of
mypy,pyright, andpyrefly - Small and simple code base with 100% test coverage and developer-friendly comments.
Installation
Punq is available on the cheese shop
pip install punq
Documentation is available on GitHub pages.
Quick Start
Punq avoids global state, so you must explicitly create a container in the entrypoint of your application:
import punq
container = punq.Container()
Once you have a container, you can register your application's dependencies. In the simplest case, we can register any arbitrary object with some key:
container.register("connection_string", instance="postgresql://...")
We can then request that object back from the container:
conn_str = container.resolve("connection_string")
Usually, though, we want to register some object that implements a useful service.:
class ConfigReader:
def get_config(self) -> dict[str, str]:
pass
class EnvironmentConfigReader(ConfigReader):
def get_config(self) -> dict[str, str]:
return {
"logging": {
"level": os.env.get("LOGGING_LEVEL", "debug"),
},
"greeting": os.env.get("GREETING", "Hello world"),
}
container.register(ConfigReader, EnvironmentConfigReader)
Now we can resolve the ConfigReader service, and receive a concrete implementation:
config = container.resolve(ConfigReader).get_config()
If our application's dependencies have their own dependencies, Punq will inject those, too:
class Greeter:
def greet(self) -> None:
pass
class ConsoleGreeter(Greeter):
def __init__(self, config_reader: ConfigReader) -> None:
self.config = config_reader.get_config()
def greet(self) -> None:
print(self.config['greeting'])
container.register(Greeter, ConsoleGreeter)
container.resolve(Greeter).greet()
If you just want to resolve an object without having any base class, that's okay:
class Greeter:
def __init__(self, config_reader: ConfigReader) -> None:
self.config = config_reader.get_config()
def greet(self) -> None:
print(self.config['greeting'])
container.register(Greeter)
container.resolve(Greeter).greet()
And if you need to have a singleton object for some reason, we can tell punq to register a specific instance of an object:
class FileWritingGreeter:
def __init__(self, path: str, greeting: str) -> None:
self.path = path
self.message = greeting
self.file = open(self.path, 'w')
def greet(self) -> None:
self.file.write(self.message)
one_true_greeter = FileWritingGreeter("/tmp/greetings", "Hello world")
container.register(Greeter, instance=one_true_greeter)
You might not know all of your arguments at registration time, but you can provide them later:
container.register(Greeter, FileWritingGreeter)
greeter = container.resolve(Greeter, path="/tmp/foo", greeting="Hello world")
Conversely, you might want to provide arguments at registration time, without adding them to the container:
container.register(Greeter, FileWritingGreeter, path="/tmp/foo", greeting="Hello world")
Fuller documentation is available on GitHub pages
GitHub workflows, nox configuration, and linting gratefully stolen from CookieCutter UV
Release files for punq 0.9.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| punq-0.9.0.tar.gz | 17.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| punq-0.9.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 27.5 kB
Release files / punq-0.9.0.tar.gz
| Download URL | punq-0.9.0.tar.gz |
|---|---|
| Size | 17.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
85aab7455fac47ce1b099fcb7ea2d8e9f562014672e9d7d46e4cc8e60e19685d
|
|
BLAKE2b-256 checksum How to use checksums |
0d3815118e8542ada95a49f63648b90bdfdd1115bbc2ed8caf3f0582d509dcc9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.14
|
Release files / punq-0.9.0-py3-none-any.whl
| Download URL | punq-0.9.0-py3-none-any.whl |
|---|---|
| Size | 9.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c8a3cc778776982cab170853c09a8712d98daae77bdd6516740c1360d41dc28c
|
|
BLAKE2b-256 checksum How to use checksums |
4fe3f668dbcfd7f2fda95b850989640417e692a346bda688415801063dcf2504
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.14
|