mypy-zope icon indicating copy to clipboard operation
mypy-zope copied to clipboard

Retuning an instance of the class being defined which provides an interface is not handled

Open wsanchez opened this issue 5 years ago • 6 comments

In https://github.com/twisted/klein/pull/471, I'm running into the following error in CI:

src/klein/_dihttp.py:62:16: error: Incompatible return value type (got "RequestURL", expected "IDependencyInjector")  [return-value]
            return cls()

The code in question is:

@provider(IRequiredParameter, IDependencyInjector)
class RequestURL:
    """
    Require a hyperlink L{DecodedURL} object from a L{Requirer}.

    @since: Klein NEXT
    """

    @classmethod
    def registerInjector(
        cls,
        injectionComponents: Componentized,
        parameterName: str,
        requestLifecycle: IRequestLifecycle,
    ) -> IDependencyInjector:
        return cls()

…

So here, we return a RequestURL, which is declared as a provider of IDependencyInjector, so I think the above error is incorrect.

I'm guessing this is due to the fact that the definition of RequestURL isn't complete yet?

wsanchez avatar Mar 16 '21 17:03 wsanchez

I think the actual issue is that @provider isn't handled, unlike @implementer.

wsanchez avatar Mar 16 '21 18:03 wsanchez

Yes, mypy-zope doesn't know anything about @provider. That said, I think your declaration is not quite correct? If instance of RequestURL implements IDependencyInjector, as registerInjector suggests, shouldn't RequestURL be declared with @implementer instead?

kedder avatar Mar 16 '21 21:03 kedder

Heh… I had to ask @glyph about this also. @implementer says that instances of the class will provide the interface. @provider says that the class itself does so. (Note that the methods are all class methods.)

wsanchez avatar Mar 16 '21 22:03 wsanchez

Super happy to be getting real typing via mypy-zope, by the way. It's great. And thanks for the quick replies to these tickets.

wsanchez avatar Mar 16 '21 22:03 wsanchez

Heh… I had to ask @glyph about this also. @implementer says that instances of the class will provide the interface. @provider says that the class itself does so. (Note that the methods are all class methods.)

Right, but registerInjector returns an instance of RequestURL. So, in order for registerInjector return type to be correct, an instance of RequestURL must provide the IDependencyInjector . However, it does not provide that interface. Only the class itself does, according to @provider declaration.

So, even though @provider is currently not supported by mypy-zope, I suspect the type hint on registerInjector is not entirely correct. I'd say registerInjector has to return cls, not cls(). Or, alterntively, RequestURL must implement IDependencyInjector, not provide it.

kedder avatar Mar 16 '21 22:03 kedder

Super happy to be getting real typing via mypy-zope, by the way. It's great. And thanks for the quick replies to these tickets.

Thanks! I'm glad mypy exists and it was possible to marry zope with it. Interfaces become so much more meaningful with it! :)

kedder avatar Mar 16 '21 23:03 kedder