Quick Start - InjectQ Documentation
Author: InjectQ Contributors
Description: Modern Python dependency injection library

Skip to content

# Quick Start

Get up and running with InjectQ in minutes! This guide will walk you through the basic concepts and APIs.

## 🎯 Hello World Example

Let's start with a simple example:

    from injectq import InjectQ, inject

    # 1. Create a container
    container = InjectQ.get_instance()

    # 2. Bind a simple value
    container[str] = "Hello, InjectQ!"

    # 3. Use dependency injection
    @inject
    def greet(message: str) -> str:
        return f"Message: {message}"

    # 4. Call the function
    result = greet()
    print(result)  # Output: Message: Hello, InjectQ!

## 🏗️ Building Your First Application

Let's create a more realistic example with classes and dependencies:

    from injectq import InjectQ, inject, singleton

    # 1. Define your services
    @singleton
    class Database:
        def __init__(self, connection_string: str):
            self.connection_string = connection_string
            print(f"Connected to: {connection_string}")

        def query(self, sql: str) -> str:
            return f"Executed: {sql}"

    class UserService:
        def __init__(self, db: Database):
            self.db = db

        def get_user_count(self) -> int:
            result = self.db.query("SELECT COUNT(*) FROM users")
            return 42  # Mock result

    # 2. Set up the container
    container = InjectQ.get_instance()

    # Bind configuration
    container[str] = "postgresql://localhost:5432/myapp"

    # Bind services (classes are automatically resolved)
    container.bind(Database, Database)
    container.bind(UserService, UserService)

    # 3. Use dependency injection
    @inject
    def show_user_stats(service: UserService) -> None:
        count = service.get_user_count()
        print(f"Total users: {count}")

    # 4. Run the application
    if __name__ == "__main__":
        show_user_stats()

## 🔄 Different Injection Patterns

InjectQ supports multiple ways to inject dependencies:

### Method 1: @inject Decorator (Recommended)

    @inject
    def process_data(service: UserService, config: str) -> None:
        # All parameters automatically injected
        pass

    # Call without arguments
    process_data()

### Method 2: Dict-like Interface

    container = InjectQ.get_instance()
    container["api_key"] = "your-secret-key"
    container[UserService] = UserService()

    # Access directly
    api_key = container["api_key"]
    service = container[UserService]

### Method 3: Manual Resolution

    container = InjectQ.get_instance()

    # Get services when needed
    service = container.get(UserService)
    config = container.get(str)

## 🎭 Understanding Scopes

Control how long your services live:

    from injectq import singleton, transient

    @singleton  # One instance for entire app
    class DatabaseConnection:
        def __init__(self):
            self.id = id(self)
            print(f"Database created: {self.id}")

    @transient  # New instance every time
    class RequestHandler:
        def __init__(self, db: DatabaseConnection):
            self.db = db
            self.id = id(self)
            print(f"Handler created: {self.id}")

    container = InjectQ.get_instance()
    container.bind(DatabaseConnection, DatabaseConnection)
    container.bind(RequestHandler, RequestHandler)

    # Test singleton behavior
    db1 = container.get(DatabaseConnection)
    db2 = container.get(DatabaseConnection)
    print(f"Same database? {db1 is db2}")  # True

    # Test transient behavior
    handler1 = container.get(RequestHandler)
    handler2 = container.get(RequestHandler)
    print(f"Different handlers? {handler1 is not handler2}")  # True
    print(f"Same database in handlers? {handler1.db is handler2.db}")  # True

## 📦 Using Modules

Organize your dependencies with modules:

    from injectq import Module, provider

    class ConfigModule(Module):
        def configure(self, binder):
            binder.bind_instance("database_url", "postgresql://localhost/db")
            binder.bind_instance("api_key", "secret-key")

    class ServiceModule(Module):
        @provider
        def provide_database(self, url: str) -> Database:
            return Database(url)

        @provider
        def provide_user_service(self, db: Database) -> UserService:
            return UserService(db)

    # Create container with modules
    container = InjectQ([ConfigModule(), ServiceModule()])

    # Services are automatically available
    @inject
    def main(service: UserService):
        print("Application started!")

    main()

## 🧪 Testing with InjectQ

InjectQ makes testing easy:

    from injectq.testing import override_dependency

    def test_user_service():
        # Override dependencies for testing
        mock_db = MockDatabase()

        with override_dependency(Database, mock_db):
            service = container.get(UserService)
            # service now uses mock_db
            result = service.get_user_count()
            assert result == 0  # Mocked result

    # Or use test containers
    from injectq.testing import test_container

    def test_with_isolated_container():
        with test_container() as test_cont:
            test_cont.bind(Database, MockDatabase)
            service = test_cont.get(UserService)
            # Test in isolation

## 🚀 What's Next?

Now that you understand the basics:

1. Explore Core Concepts: Learn about dependency injection patterns
2. Master Scopes: Understand service lifetimes
3. Use Modules: Organize complex applications
4. Framework Integration: Integrate with FastAPI, Taskiq, etc.
5. Check Examples: See more practical examples

## 💡 Pro Tips

- Use `@inject` for automatic dependency injection
- Use `@singleton` for services that should be shared
- Use `@transient` for services that need fresh instances
- Use modules to organize related dependencies
- Use `override_dependency` for testing

Happy coding with InjectQ! 🎉