Skip to content

Instantly share code, notes, and snippets.

@caiquecp
Last active January 31, 2022 20:42
Show Gist options
  • Save caiquecp/7167907f4bdcfdc83b671f1df209f8d5 to your computer and use it in GitHub Desktop.
Save caiquecp/7167907f4bdcfdc83b671f1df209f8d5 to your computer and use it in GitHub Desktop.
A very simple (and uncompleted) dependency injection decorator for Python.
import functools
from inspect import signature, Parameter
# Dict to store our dependencies
__dependencies__ = {}
def register_dependency(dependency: object) -> None:
# Get the class name to use it as an id in our dependencies dict
cls_name = dependency.__class__.__name__
# Register it, which is basically store the instance (of the dependency) with its class name as id
__dependencies__[cls_name] = dependency
# A very simple decorator to inject dependencies
def inject(func):
@functools.wraps(func)
def wrapper_decorator(*args, **kwargs):
# We get the func signature (inspect lib) so we can get the func parameters metadata
func_sig = signature(func)
# For each parameter we verify if it's type (needs typing) matchs any of our dependencies
for param in func_sig.parameters.values():
if param.annotation.__name__ in __dependencies__.keys():
# For now we support only keywords compatible parameters (I'll edit it soon)
if param.kind in [Parameter.POSITIONAL_OR_KEYWORD, Parameter.KEYWORD_ONLY]:
# If found we update kwargs dict with the dependency
kwargs[param.name] = __dependencies__[param.annotation.__name__]
return func(*args, **kwargs)
return wrapper_decorator
# A simple class to print text that we'll use as a dependency
class Printer:
def print_text(self, text: str):
print(f'PRINTER: {text.upper()}')
# We instanciate the Printer and register it as a dependency
printer = Printer()
register_dependency(printer)
# So for our example we have a func called writes that receive a text and needs a printer
# to print it. The printer will be inject with out inject function.
# Obs.: it's a very simple code only to represent a case where an action has a dependency
@inject
def writes(text: str, printer: Printer) -> None:
printer.print_text(text)
# Last but not least we call the writes function only giving a text (the printer dependency
# will be provided by the inject decorator)
writes('oi')
# >> PRINTER: OI
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment