Package: cargo
CargoCargo is a dependency injection library for Python.Cargo issimple to use,typed,flexible,extensibleandeasy to debug.Getting startedStep 1: Install cargoWith pip:$pipinstallcargoWith pipenv:$pipenvinstallcargoWith poetry:$poetryaddcargoStep 2: Use cargoexamples/intro.py:importcargo# 1. Define your componentsclassA:def__str__(self):return"A"classB:def__init__(self,a:A):self.a=a# 2. Create a cargo containercontainer=cargo.containers.Standard()# 3. Register your componentscontainer[A]=Acontainer[B]=B# 4. Use cargo to initialize your componentsb=container[B]# 5. Use your componentsprint(b.a)FeaturesAll the examples are located in theexamplesdirectory.Cargo is typedCargo uses the argument types to inject the dependencies; not their
names.examples/hello_dependencies.py:importcargoclassA:passclassB:passclassHello:def__init__(self,foo:A,bar:B):print(f"Hello{foo}and{bar}")container=cargo.containers.Standard()container[A]=Acontainer[B]=Bcontainer[Hello]=Hello# Prints: Hello <__main__.A object at 0x7f863b0fd450> and <__main__.B object at 0x7f863b09b810>container[Hello]Cargo is flexibleFunctions and methods can be used as factories; and objects as values.examples/factory_and_value.py:...DatabaseURL=typing.NewType("DatabaseURL",str)defdatabase_client_factory(db_url:DatabaseURL)->DatabaseClient:ifdb_url.startswith("mysql://"):returnMysqlClient(db_url)ifdb_url.startswith("postgres://"):returnPostgresClient(db_url)raiseException(f"Invalid database url:{db_url}")container=cargo.containers.Standard()# Registers a factorycontainer[DatabaseClient]=database_client_factory# Registers a valuecontainer[DatabaseURL]="mysql://user:password@host:3306/db"db_client=container[DatabaseClient]print(db_client)# Prints: <__main__.MysqlClient object at 0x7f681975b390>Cargo is extensibleCargo composes middlewares to create containers. TheStandardcontainer is just a stack of
opiniated middlewares. You can create your own types of containers
with themiddlewaresyou want, or even create
your own middlewares.examples/my_container.py:importcargoclassLoggerMiddleware(cargo.types.Middleware):defexecute(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}")returndependency_valuemiddleware_factories=[LoggerMiddleware,cargo.middlewares.CircularDependencyCircuitBreaker,cargo.middlewares.Singleton,]container=cargo.containers.create(middleware_factories)classA:passclassB:def__init__(self,a:A):passcontainer[A]=Acontainer[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 debugDependency not foundCargo raises aDependencyNotFoundexception
with the missing dependency type when a dependency is not found.examples/dependency_not_found.py:...classA:def__init__(self,b:B):passclassB:passcontainer=cargo.containers.Standard()container[A]=A# Note: B has not been registered# Raises cargo.exceptions.DependencyNotFound: <class '__main__.B'>container[A]Circular dependencyCargo raises aCircularDependencyexception
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]=Acontainer[B]=Bcontainer[C]=Ccontainer[D]=D# Raises cargo.exceptions.CircularDependency:#   [<class '__main__.B'>, <class '__main__.C'>, <class '__main__.D'>, <class '__main__.B'>]container[A]ContributorsMathieu LaroseLicenseCargo is licensed under the terms of theMIT license.Websitehttps://github.com/larose/cargo