A lightweight, type-safe dependency injection library for Python.
- Type-safe dependency injection with full Python type hints support
- Zero runtime dependencies - just pure Python
- Monadic interface for composition and transformation
- Pythonic generator-based syntax for requesting dependencies
- Flexible context creation with multiple builder patterns
Requires Python 3.9+
pip install monadic-contextOr with Poetry:
poetry add monadic-contextfrommonadic_contextimportrequires, useimportmonadic_contextascontext# Define tags for your dependenciesport_tag=context.Tag[int]("port")
host_tag=context.Tag[str]("host")
# Function that requires dependencies from context@requiresdefbuild_url():
port=yieldfromuse(port_tag)
host=yieldfromuse(host_tag)
returnf"http://{host}:{port}"# Create a context with required dependenciesctx=context.from_dict({port_tag: 8080, host_tag: "localhost"})
# Run the function with the contexturl=ctx.run(build_url())
print(url) # Output: http://localhost:8080The library offers multiple ways to create contexts:
# Single dependencyctx1=context.of(port_tag)(8080)
# Joining contextsctx2=ctx1.join(context.of(host_tag)("localhost"))
# From pairs (more efficient for multiple dependencies)ctx3=context.from_pairs(
(port_tag, 8080),
(host_tag, "localhost"),
)
# From dictionaryctx4=context.from_dict({port_tag: 8080, host_tag: "localhost"})The library supports standard monadic operations:
# Map over a context-requiring functionhome_url=context.pipe(build_url(), context.map(lambdaurl: f"{url}/home"))
result=ctx.run(home_url)
print(result) # Output: http://localhost:8080/homeFor functions that take a service as first argument:
importsocketdb_conn_tag=context.Tag[socket.SocketType]("db_conn")
@context.with_service(db_conn_tag)defconfigure_server(db_conn: socket.SocketType, timeout=30):
# Use db_conn to configure serverreturn {"connection": db_conn, "timeout": timeout}- Testability: Easy to mock dependencies for testing
- Composability: Combine and transform context-aware functions
- Type Safety: Full type checking with mypy/pyright
- Separation of Concerns: Clean separation between business logic and dependency resolution
- No Runtime Reflection: Unlike some DI frameworks, no runtime reflection or complex containers
- No Mypy Plugins: No need to reconfigure your programming environment
MIT