kink icon indicating copy to clipboard operation
kink copied to clipboard

[mypy] Missing positional argument "x" in call to "C"

Open dosisod opened this issue 3 years ago • 6 comments

I am getting mypy errors when using the inject decorator on classes:

# file.py

from kink import di, inject

di["x"] = 42

@inject
class C:
    def __init__(self, x: int) -> None:
        print(x)


c = C()

Running mypy with:

$ mypy file.py
file.py:13: error: Missing positional argument "x" in call to "C"
Found 1 error in 1 file (checked 1 source file)

Version info:

$ pip freeze
kink==0.6.2
mypy==0.910
mypy-extensions==0.4.3
toml==0.10.2
typing-extensions==3.10.0.2

$ python --version
Python 3.9.7

The only workaround I can see is this:

class C:
    def __init__(self, x: int = di["x"]) -> None:

Which means the inject decorator isn't needed.

dosisod avatar Oct 21 '21 04:10 dosisod

hi @dosisod, what is the usecase for initialisation C directly?

I would recommend getting it from di instead, like in the example below:

c = di[C]

The reason for that is container is quite capable of instantiating complex dependencies with nested structures and by using automated initialisation you possibly cannot make any mistake.

Valid reason to instantiate dependencies manually is testing, but in this scenario you should pass all the required dependencies whether they are mocked dependencies or not and probably you shouldn't use DI in that scenario or at least you should mock it.

dkraczkowski avatar Oct 22 '21 11:10 dkraczkowski

I did not know that services that where injected got added to the di object. The issue now is that c will be type Any, and I will need to cast it:

from kink import di, inject

di["x"] = 42

@inject
class C:
    def __init__(self, x: int) -> None:
        print(x)

c = di[C]
reveal_type(c)

c2: C = di[C]
reveal_type(c2)
$ mypy file.py
file.py:11: note: Revealed type is "Any"
file.py:14: note: Revealed type is "file.C"

dosisod avatar Oct 23 '21 01:10 dosisod

@dosisod There are two possible solutions for now:

  • add mypy plugin that adds kink support (and I would really appreciate help on that)
  • second is obviously not perfect and you have already provided it.

The way how we use this library is mostly in controllers and dependencies are injected as function's arguments and those have type annotations so mypy handles those gracefully. Our controllers are either executed by framework code or lambda layer in AWS, so again this is outside our project code.

I assume creating a mypy plugin to fix this issue shouldn't be a big deal, but at the moment I have couple other priorities so I would appreciate support on this. Eventually you can give it a time and I believe in next couple weeks I might sort it out.

dkraczkowski avatar Oct 25 '21 21:10 dkraczkowski

First of all, thanks for the awesome library!

I've tried writing a plugin for mypy which will modify signatures of functions decorated with @inject, but there is a problem: it's not possible to differentiate which specific arguments are going to be injected and which are going to be provided by the caller.

I've outlined several possible solutions here: https://github.com/kodemore/kink/issues/30#issuecomment-1272353187. Please let me know you thoughts!

and3rson avatar Oct 08 '22 16:10 and3rson

This issue is now very much related to #36

skewty avatar Aug 16 '23 21:08 skewty

@skewty I have just seen the issue. I think I will need to spend some time with mypy plugin system, once I get a bit of my life back ^^. I will keep you in the loop.

dkraczkowski avatar Aug 31 '23 06:08 dkraczkowski