Skip to main content

Dependency injection library for Python.

Project description

Cargo

Cargo is a dependency injection library for Python.

Cargo is simple to use, typed, flexible, extensible and easy to debug.

Getting started

Step 1: Install cargo

With pip:

$ pip install cargo

With pipenv:

$ pipenv install cargo

With poetry:

$ poetry add cargo

Step 2: Use cargo

examples/intro.py:

import cargo

# 1. Define your components


class A:
    def __str__(self):
        return "A"


class B:
    def __init__(self, a: A):
        self.a = a


# 2. Create a cargo container

container = cargo.containers.Standard()


# 3. Register your components

container[A] = A
container[B] = B


# 4. Use cargo to initialize your components

b = container[B]


# 5. Use your components

print(b.a)

Features

All the examples are located in the examples directory.

Cargo is typed

Cargo uses the argument types to inject the dependencies; not their names.

examples/hello_dependencies.py:

import cargo


class A:
    pass


class B:
    pass


class Hello:
    def __init__(self, foo: A, bar: B):
        print(f"Hello {foo} and {bar}")


container = cargo.containers.Standard()

container[A] = A
container[B] = B
container[Hello] = Hello

# Prints: Hello <__main__.A object at 0x7f863b0fd450> and <__main__.B object at 0x7f863b09b810>
container[Hello]

Cargo is flexible

Functions and methods can be used as factories; and objects as values.

examples/factory_and_value.py:

...

DatabaseURL = typing.NewType("DatabaseURL", str)

def database_client_factory(db_url: DatabaseURL) -> DatabaseClient:
    if db_url.startswith("mysql://"):
        return MysqlClient(db_url)

    if db_url.startswith("postgres://"):
        return PostgresClient(db_url)

    raise Exception(f"Invalid database url: {db_url}")


container = cargo.containers.Standard()

# Registers a factory
container[DatabaseClient] = database_client_factory

# Registers a value
container[DatabaseURL] = "mysql://user:password@host:3306/db"

db_client = container[DatabaseClient]

print(db_client)  # Prints: <__main__.MysqlClient object at 0x7f681975b390>

Cargo is extensible

Cargo composes middlewares to create containers. The Standard container is just a stack of opiniated middlewares. You can create your own types of containers with the middlewares you want, or even create your own middlewares.

examples/my_container.py:

import cargo


class LoggerMiddleware(cargo.types.Middleware):
    def execute(
        self,
        dependency_type: cargo.types.DependencyType,
        next_middleware: cargo.types.NextMiddleware,
    ):
        print(f"Start resolving {dependency_type}")
        dependency_value = next_middleware()
        print(f"End resolving {dependency_type}")
        return dependency_value


middleware_factories = [
    LoggerMiddleware,
    cargo.middlewares.CircularDependencyCircuitBreaker,
    cargo.middlewares.Singleton,
]
container = cargo.containers.create(middleware_factories)


class A:
    pass


class B:
    def __init__(self, a: A):
        pass


container[A] = A
container[B] = B

# Prints:
# Start resolving <class '__main__.B'>
# Start resolving <class '__main__.A'>
# End resolving <class '__main__.A'>
# End resolving <class '__main__.B'>
container[B]

Cargo is easy to debug

Dependency not found

Cargo raises a DependencyNotFound exception with the missing dependency type when a dependency is not found.

examples/dependency_not_found.py:

...

class A:
    def __init__(self, b: B):
        pass


class B:
    pass


container = cargo.containers.Standard()
container[A] = A
# Note: B has not been registered

# Raises cargo.exceptions.DependencyNotFound: <class '__main__.B'>
container[A]

Circular dependency

Cargo raises a CircularDependency exception with the dependency cycle when a circular dependency is detected.

examples/circular_dependency.py:

...

# Dependencies:
#   - A depends on B
#   - B depends on C
#   - C depends on D
#   - D depends on B
#
# Circular dependency cycle is: B -> C -> D -> B

...

container = cargo.containers.Standard()
container[A] = A
container[B] = B
container[C] = C
container[D] = D

# Raises cargo.exceptions.CircularDependency:
#   [<class '__main__.B'>, <class '__main__.C'>, <class '__main__.D'>, <class '__main__.B'>]
container[A]

Contributors

License

Cargo is licensed under the terms of the MIT license.

Website

https://github.com/larose/cargo

Project details


Release history Release notifications | RSS feed

This version

0.3

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cargo-0.3.tar.gz (7.4 kB view details)

Uploaded Source

Built Distribution

cargo-0.3-py3-none-any.whl (7.2 kB view details)

Uploaded Python 3

File details

Details for the file cargo-0.3.tar.gz.

File metadata

  • Download URL: cargo-0.3.tar.gz
  • Upload date:
  • Size: 7.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.0.5 CPython/3.7.6 Linux/5.0.0-1035-azure

File hashes

Hashes for cargo-0.3.tar.gz
Algorithm Hash digest
SHA256 38534a877b2df38f3ab6c2767e673351888dfeb062ce6f2a715b3dce6ca1f8fe
MD5 a425c2da5089f33e3ec36d609ffd7218
BLAKE2b-256 8dacd3ac29288dde6e7358af4340c736334ac5fe99d601df3ab4805cf31ae59c

See more details on using hashes here.

File details

Details for the file cargo-0.3-py3-none-any.whl.

File metadata

  • Download URL: cargo-0.3-py3-none-any.whl
  • Upload date:
  • Size: 7.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.0.5 CPython/3.7.6 Linux/5.0.0-1035-azure

File hashes

Hashes for cargo-0.3-py3-none-any.whl
Algorithm Hash digest
SHA256 eb41caddbdfab94d5ce72c363fb1109ff74e55d3381ba545a62ca25763cd8adb
MD5 3ef2bcccde0cd9415733749cbaa07183
BLAKE2b-256 3690555fbe2dc0936090d8a512b33a0186ea0b1d465c881c2aa3f59eb90d2c19

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page