Many values trigger warning even when you accept SupportsInt #2136

Open
sametmax opened this Issue Sep 15, 2016 · 3 comments

Projects

None yet

3 participants

@sametmax

When linting this program with mypy:


from typing import SupportsInt

class Bar:

    def __int__(self):
        return 1

def foo(a: SupportsInt):
    return int(a)

foo('1')
foo(True)
foo(1)
foo(1.1)
foo(Bar())

I got the following errors:

test.py:12: error: Argument 1 to "foo" has incompatible type "str"; expected "SupportsInt"
test.py:16: error: Argument 1 to "foo" has incompatible type "Bar"; expected "SupportsInt"

I was expecting that anything accepted but int() would be accepted by something hinting for SupportsInt. Is my expectation wrong or is this a bug?

If my expectations are wrong, how would I create the same signature as int()?

@Michael0x2a
Collaborator

To fix foo(Bar()) not being accepted, you need to change Bar so it extends SupportInt -- do class Bar(SupportsInt): ....

(The reason why mypy needs you to extend SupportsInt instead of just automatically detecting that any class with an __int__ method matches the SupportsInt interface is because mypy doesn't yet support structural typing -- see python/typing#11 for details)

That said, it seems like str doesn't actually have an __int__ method, so it's seems correct to me that it doesn't extend SupportsInt.

You can find the type signature for int on the repo for typeshed. For Python 3, it's:

class int(SupportsInt, SupportsFloat, SupportsAbs[int]):
    def __init__(self, x: Union[SupportsInt, str, bytes] = ..., base: int = ...) -> None: ...
@sametmax

The code I want to hint, I don't have access to the class I'm accepting, so I can't make it subclass anything.

Is mypy planning to support structural typing in the future ?

@gvanrossum
Member

Structural typing is on the road map, but we don't have a specific plan or timeline yet.

I wonder if it would be simple for mypy to hard-code some structural typing for the standard typing.SupportsXxx classes. In some places it uses structural checks, e.g. in for and with statements anything that has __iter__ or __enter__/__exit__ respectively is accepted, so it's possible to do with enough willpower.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment