ruff/crates/ty_python_semantic/resources/mdtest/import/conflicts.md
2025-05-03 19:49:15 +02:00

1.4 KiB

Conflicting attributes and submodules

Via import

import a.b

reveal_type(a.b)  # revealed: <module 'a.b'>

a/__init__.py:

b: int = 42

a/b.py:

Via from/import

from a import b

reveal_type(b)  # revealed: int

a/__init__.py:

b: int = 42

a/b.py:

Via both

import a.b
from a import b

reveal_type(b)  # revealed: <module 'a.b'>
reveal_type(a.b)  # revealed: <module 'a.b'>

a/__init__.py:

b: int = 42

a/b.py:

Via both (backwards)

In this test, we infer a different type for b than the runtime behavior of the Python interpreter. The interpreter will not load the submodule a.b during the from a import b statement, since a contains a non-module attribute named b. (See the definition of a from...import statement for details.) However, because our import tracking is flow-insensitive, we will see that a.b is imported somewhere in the file, and therefore assume that the from...import statement sees the submodule as the value of b instead of the integer.

from a import b
import a.b

# Python would say `int` for `b`
reveal_type(b)  # revealed: <module 'a.b'>
reveal_type(a.b)  # revealed: <module 'a.b'>

a/__init__.py:

b: int = 42

a/b.py: