Welcome to Pinjected, a powerful dependency injection and dependency resolver library for Python inspired by pinject.
- Python 3.10 or higher
- Basic understanding of Python decorators and functions
pip install pinjectedDependency injection is a design pattern where objects receive their dependencies from an external source rather than creating them internally. This makes code more:
- Flexible: Easy to change implementations
- Testable: Simple to mock dependencies
- Maintainable: Clear separation of concerns
- @instance: Decorator that marks a function as a dependency provider
- design(): Creates a design with dependencies (both value-based and function-based)
- Design: Configuration registry that manages dependencies
- to_graph(): Creates an object graph that resolves dependencies
Please refer to Coding Guidelines for development standards and best practices.
This project uses uv for dependency management.
# Install uv if you haven't already curl -LsSf https://astral.sh/uv/install.sh | sh # Or install with pip pip install uv # Install dependencies uv pip syncfrompinjectedimportdesign, instance# Define a simple configuration@instancedefdatabase_config(): return{"host": "localhost", "port": 5432, "name": "mydb" } @instancedefdatabase_connection(database_config): # Dependencies are automatically injectedreturnf"Connected to {database_config['name']} at {database_config['host']}:{database_config['port']}"# Create a design with our configurationsdi=design( db_config=database_config, connection=database_connection ) # Use the dependency injectiongraph=di.to_graph() connection=graph['connection'] print(connection) # "Connected to mydb at localhost:5432"frompinjectedimportdesign# Base configurationbase_config=design( api_url="https://api.example.com", timeout=30 ) # Development overridesdev_config=base_config+design( api_url="http://localhost:8000" ) # Production overridesprod_config=base_config+design( timeout=60 )frompinjectedimportinstance, design@instancedefapi_client(api_url, timeout): returnf"Client configured with {api_url} (timeout: {timeout}s)"@instancedefservice(api_client): returnf"Service using {api_client}"# Create and use the servicedi=dev_config+design( client=api_client, service=service ) graph=di.to_graph() my_service=graph['service']# Override dependencies for testingtest_config=design( api_url="mock://test", timeout=1 ) test_design=test_config+design( client=api_client, service=service )For more detailed documentation and advanced features, see:
The documentation is organized into two directories:
/docs: User documentation for using the pinjected library
/dev_docs: Developer documentation for contributors
Pinjected makes it easy to compose multiple Python objects to create a final object. It automatically creates dependencies and composes them, providing a clean and modular approach to dependency management. To learn more about the motivation behind Pinjected and its key concepts, check out the Introduction. Design
- VSCode plugin is available at pinjected-runner
The Design section covers the core concept of Pinjected. It explains how to define a collection of objects and their dependencies using the Design class. You'll learn about binding instances, providers, and classes to create a dependency graph.
Pinjected provides two decorators, @instance and @injected, to define provider functions. The Decorators section explains the differences between these decorators and how to use them effectively in your code.
In the Injected section, you'll learn about the Injected class, which represents a variable that requires injection. This section covers how to create Injected instances, compose them, and use them as providers in your dependency graph.
Pinjected supports running Injected instances from the command line and integrating with IDEs like IntelliJ IDEA. The Running section provides details on how to use the CLI and set up IDE integration for a smooth development experience.
Pinjected offers support for asynchronous programming, allowing you to use async functions as providers. The Async Support section explains how to define and use async providers, as well as how to compose async Injected instances.
The Resolver section dives into the object graph and resolver concepts in Pinjected. You'll learn how the resolver manages the lifecycle of injected variables and how to use it to retrieve instances from the dependency graph.
For additional information, refer to the Miscellaneous section, which covers topics like performance considerations, comparisons with other DI libraries, and troubleshooting.
The Appendix contains supplementary information, such as a comparison with pinject and other relevant details.
Stay up to date with the latest changes and releases by checking the Updates section, which includes a changelog and release information.
The Migration Guides section provides step-by-step instructions for transitioning from deprecated APIs to newer ones. Currently featuring a comprehensive guide for migrating from instances(), providers(), and classes() to the new unified design() function.
We hope you find Pinjected helpful in your projects! If you have any questions or feedback, please don't hesitate to reach out.
This repository is organized as a monorepo with the following packages:
- pinjected: Core dependency injection framework (root package)
- pinjected-openai: OpenAI API bindings for pinjected (in packages/openai_support)
- pinjected-anthropic: Anthropic API bindings for pinjected (in packages/anthropic)
- pinjected-wandb: Weights & Biases integration for pinjected (in packages/wandb_util)
- pinjected-error-reports: Error reporting utilities for pinjected (in packages/error_reports)
- pinjected-reviewer: Code review tools for pinjected (in packages/reviewer)
- pinjected-rate-limit: Rate limiting utilities for API calls (in packages/rate_limit)
- pinjected-niji-voice: Niji Voice integration for pinjected (in packages/niji_voice)
- injected-utils: Utility functions for pinjected packages (in packages/injected_utils)
The pinjected linter requires system dependencies for Rust compilation. These are automatically installed when you run make sync, but you can also install them manually:
sudo apt-get update sudo apt-get install -y pkg-config libssl-devsudo yum install -y pkg-config openssl-develbrew install pkg-config opensslIf you encounter linter compilation errors, try running:
make install-system-depsTo install all packages for development:
# Install uv if you haven't already curl -LsSf https://astral.sh/uv/install.sh | sh # Set up the workspace make sync make setup-allRun tests for all packages:
make testBuild individual packages:
make publish # Build and publish pinjected make publish-openai # Build and publish pinjected-openai# And other packages similarly