Open
Description
Hi, I really like this package and am using it in production. I was tying to mess around with decorators because I want to add side effects to a function, adding a secret_number
in the example. I was expecting decorated_function_1
to work but it didn't and I can't wrap my head around it. Is this an expected behavior? Could injection be supported like in my_decorator_1
?
I also added few examples of things I tried and only decorated_function_4
actually works.
from functools import wraps
from dependency_injector import containers, providers
from dependency_injector.wiring import Provide, inject
class Container(containers.DeclarativeContainer):
config = providers.Configuration()
@inject
def my_decorator_1(func, secret_number: int = Provide[Container.config.secret_number]):
@wraps(func)
def wrapper(*args, **kwargs):
result = func(*args, **kwargs)
return result + secret_number
return wrapper
@inject
def my_decorator_2(secret_number: int = Provide[Container.config.secret_number]):
def inner_decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
result = func(*args, **kwargs)
return result + secret_number
return wrapper
return inner_decorator
def my_decorator_3():
@inject
def inner_decorator(func, secret_number: int = Provide[Container.config.secret_number]):
@wraps(func)
def wrapper(*args, **kwargs):
result = func(*args, **kwargs)
return result + secret_number
return wrapper
return inner_decorator
def my_decorator_4(func):
@wraps(func)
def wrapper(*args, **kwargs):
result = func(*args, **kwargs)
secret_number = kwargs['secret_number']
return result + secret_number
return wrapper
@my_decorator_1
def decorated_function_1():
return 42
@inject
@my_decorator_1
def decorated_function_1a():
return 42
@my_decorator_2()
def decorated_function_2():
return 42
@my_decorator_3()
def decorated_function_3():
return 42
@inject
@my_decorator_3()
def decorated_function_3a():
return 42
@inject
@my_decorator_4
def decorated_function_4(secret_number: int = Provide[Container.config.secret_number]):
return 42
@my_decorator_4
@inject
def decorated_function_4a(secret_number: int = Provide[Container.config.secret_number]):
return 42
def main():
test_funcs = [
decorated_function_1,
decorated_function_1a,
decorated_function_2,
decorated_function_3,
decorated_function_3a,
decorated_function_4,
decorated_function_4a,
]
for test_f in test_funcs:
try:
result = test_f()
print(f"Function {test_f} returned {result}")
except Exception as exc:
print(f"Function {test_f} raised {exc.__class__.__name__} '{exc}'")
if __name__ == '__main__':
import sys
container = Container()
container.init_resources()
container.config.secret_number.from_env("SECRET_INT", 24)
container.wire(modules=[sys.modules[__name__]])
main()
The output is:
Function <function decorated_function_1 at 0x7f93d8a4d310> raised TypeError 'unsupported operand type(s) for +: 'int' and 'Provide''
Function <function decorated_function_1a at 0x7f93d8a4d4c0> raised TypeError 'unsupported operand type(s) for +: 'int' and 'Provide''
Function <function decorated_function_2 at 0x7f93d8a4d670> raised TypeError 'unsupported operand type(s) for +: 'int' and 'Provide''
Function <function decorated_function_3 at 0x7f93d8a4d820> raised TypeError 'unsupported operand type(s) for +: 'int' and 'Provide''
Function <function decorated_function_3a at 0x7f93d8a4daf0> raised TypeError 'unsupported operand type(s) for +: 'int' and 'Provide''
Function <function decorated_function_4 at 0x7f93d8a4dca0> returned 66
Function <function decorated_function_4a at 0x7f93d8a4de50> raised KeyError ''secret_number''