Skip to content

assert isinstance check for a non-subtype confuses mypy #2776

Closed
@axch

Description

@axch

Consider a coding pattern where one chooses (for some reason) to type a function as accepting a broad argument type, but in the body to assert isinstance a narrower type, like this:

class A(object): pass

class B(A): pass

def foo(x):
    # type: (A) -> None
    reveal_type(x)
    assert isinstance(x, B)
    reveal_type(x)

Mypy recognizes the assert and narrows the type of x for the second reveal_type, as expected:

$ mypy --python-version 2.7 mypytest.py
mypytest.py:7: error: Revealed type is 'mypytest.A'
mypytest.py:9: error: Revealed type is 'mypytest.B'

But, suppose one makes a mistake, and either uses the wrong class, or forgets to inherit from A, like this:

class A(object): pass

class C(object): pass

def bar(x):
    # type: (A) -> None
    reveal_type(x)
    assert isinstance(x, C)
    reveal_type(x)

Now, mypy appears to just ignore the assert and the second reveal_type:

$ mypy --python-version 2.7 mypytest2.py
mypytest2.py:7: error: Revealed type is 'mypytest2.A'

I recognize that multiple inheritance in Python means that mypy would need intersection types in order to type x precisely in the second example, but I am very surprised that it just completely ignores the reveal_type.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions