Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

cargo

Package Overview
Dependencies
Maintainers
1
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

cargo

Dependency injection library for Python.

  • 0.3
  • PyPI
  • Socket score

Maintainers
1

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

FAQs


Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc