Skip to main content
https://img.shields.io/pypi/v/compynent.svg https://img.shields.io/travis/caioaao/compynent.svg Documentation Status

An easy way to define a dependency graph between parts of your application and manage their life-cycle using the built-in context managers.

Compynent is a micro library for dependency injection and managing state in an application.

Install

Recommended install is using pip:

$ pip install compynent

Quick start

“Components” in your application are just context managers. All of them receive their dependencies in their init, and they will be initialized by the time the context is “entered”.

For example, let’s define two components A, and B, and A depends on B.

from contextlib import contextmanager
@contextmanager
def component_a(b):
    print('entered A')
    yield b
    print('exiting A')
@contextmanager
def component_b():
    print('entered B')
    yield 35
    print('exiting B')

Now, let’s define our system config and use it inside a context:

from compynent import System
system = System({'a': (component_a, ['b']),
                 'b': (component_b, [])})
with system.start() as ctx:
    print('A: %d' % ctx['a'])
    print('B: %d' % ctx['b'])

When we run the code block above, we get:

entered B
entered A
A: 35
B: 35
exiting A
exiting B

But why?

Dependency Injection is a good idea for many reasons. I suggest reading about it and learning for yourself (trust me, it’s worth it).

Now, why not use one of the many dependency injection libraries out there? My second suggestion is to start a Python REPL and run import this (or read about the zen of python). This library is focused on the second and third lines:

  • Explicit is better than implicit

  • Simple is better than complex

All the libraries fall short in one or two of these rules. Some will depend on incantations to automatically find where to inject code, while others provide a complex API for defining all sorts of dependencies, bindings, providers, containers, etc. This library doesn’t do that. It provides a way to define that component A depends on component B and that’s it. Everything else is up to the user. No singletons, factories, etc., for the sole reason that it’s not needed in Python.

Another reason is state management. One important feature of dependency injection is being able to share state between different parts of your code while maintaining the parts decoupled. This means the dependency graph is important to define the order in which the application parts must be initialized. But, if you want an application that is actually easily testable, you also want the cleanup to be done properly in the reverse order of initialization. Most libraries out there assume your program will run forever or that you will handle releasing resources manually after it’s done. Well, Python solves that pretty well already with context managers, so why not take advantage of that?

Dependency Injection Libraries

Python community came up with other great libraries. If this one is not for you, make sure to check the others out:

Credits

This package was created with Cookiecutter and the audreyr/cookiecutter-pypackage project template.

It was inspired by the Component library for Clojure, written by Stuart Sierra. I hope this project carries some of that simplicity with it.

Metadata

Release files for compynent 1.0.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for compynent 1.0.1
File Size Uploaded Provenance Actions
compynent-1.0.1.tar.gz 11.0 kB Without provenance Details for compynent-1.0.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for compynent 1.0.1
File Interpreter ABI Platform Actions
compynent-1.0.1-py2.py3-none-any.whl Python 3, Python 2 none any Details for compynent-1.0.1-py2.py3-none-any.whl

Total release size: 16.0 kB

Release files / compynent-1.0.1.tar.gz

Download URL compynent-1.0.1.tar.gz
Size 11.0 kB
Tags Source
SHA-256 checksum
How to use checksums
6d26d0cd48afda49c3ac7d18518b7ec6576e1881fc888a63d78df592ee3f6269
BLAKE2b-256 checksum
How to use checksums
894ed0d39ddde7125d998817d87a0933f9eec4f187520c4eeb1920ec53720634
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/3.2.0 pkginfo/1.6.1 requests/2.25.0 setuptools/49.2.1 requests-toolbelt/0.9.1 tqdm/4.52.0 CPython/3.9.0

Release files / compynent-1.0.1-py2.py3-none-any.whl

Download URL compynent-1.0.1-py2.py3-none-any.whl
Size 4.9 kB
Tags Python 2 Python 3
SHA-256 checksum
How to use checksums
c4863e960ef0bceda569256a387d4aeaec175515d389e31c8671abc58ab89dc0
BLAKE2b-256 checksum
How to use checksums
ad83b1eccfdd058f93c20103a6ea0edf81b996b00f52eb6ec55839d7996ca38e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/3.2.0 pkginfo/1.6.1 requests/2.25.0 setuptools/49.2.1 requests-toolbelt/0.9.1 tqdm/4.52.0 CPython/3.9.0

Security for compynent 1.0.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page