kodemore / kink

Dependency injection container made for Python
MIT License
397 stars 25 forks source link

Potential issue where constructor is not defined #4

Closed danballance closed 3 years ago

danballance commented 3 years ago

I'm not sure if this is an issue with my syntax/configuration or if it might be a small bug.

I am getting an error when I try to inject an implementation that does not define an __init__ method:

kink.errors.execution_error.ExecutionError: Cannot execute function without required parameters. Did you forget to bind the following parameters: `args`, `kwargs`?

It doesn't seem to be a big issue because after experimenting a bit, it seems that simply defining an init method that does nothing seems to make the error go away, such as:

def __init__(self):
    pass

I've created a test case that demonstrates the problem as I see it:

from typing import Protocol

from kink import di
from kink import inject

class ExampleProtocol(Protocol):
    def run(self, a: int, b: int) -> int:
        ...

@inject(alias=ExampleProtocol)
class ImplementationNoConstructor(ExampleProtocol):
    def run(self, a: int, b: int) -> int:
        return a + b

@inject(alias=ExampleProtocol)
class ImplementationWithConstructor(ExampleProtocol):
    def __init__(self):
        pass

    def run(self, a: int, b: int) -> int:
        return a * b

@inject
class CompositionExample:
    def __init__(self, example: ExampleProtocol):
        self._example: ExampleProtocol = example

    def use_it(self, a: int, b: int) -> int:
        return self._example.run(a=a, b=b)

def test_that_auto_wiring_works_with_constructor():
    """
    This one works - I think because ImplementationWithConstructor.__init__ is defined
    """
    di[ExampleProtocol] = ImplementationWithConstructor()
    composition_example = CompositionExample()
    assert composition_example.use_it(a=2, b=3) == 6

def test_that_auto_wiring_works_without_constructor():
    """
    This one doesn't work - I think because there's no __init__ defined on ImplementationNoConstructor
    """
    di[ExampleProtocol] = ImplementationNoConstructor()
    composition_example = CompositionExample()
    assert composition_example.use_it(a=2, b=3) == 5
dkraczkowski commented 3 years ago

@danballance Thank you for rising the issue, I will take care of it immediately.