Last active
January 31, 2022 20:42
-
-
Save caiquecp/7167907f4bdcfdc83b671f1df209f8d5 to your computer and use it in GitHub Desktop.
A very simple (and uncompleted) dependency injection decorator for Python.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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