Skip to content

Commit

Permalink
Respect multi-segment submodule imports when resolving qualified names
Browse files Browse the repository at this point in the history
  • Loading branch information
charliermarsh committed Jan 3, 2024
1 parent 1ffc738 commit 2e1ed80
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 111 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -51,19 +51,14 @@ PYI058.py:21:13: PYI058 [*] Use `Iterator` as the return value for simple `__ite
= help: Convert the return annotation of your `__iter__` method to `Iterator`

Safe fix
1 |+from collections.abc import Iterator
1 2 | def scope():
2 3 | from collections.abc import Generator
3 4 |
--------------------------------------------------------------------------------
18 19 | import collections.abc
19 20 |
20 21 | class IteratorReturningSimpleGenerator3:
18 18 | import collections.abc
19 19 |
20 20 | class IteratorReturningSimpleGenerator3:
21 |- def __iter__(self) -> collections.abc.Generator:
22 |+ def __iter__(self) -> Iterator:
22 23 | ... # PYI058 (use `Iterator`)
23 24 |
24 25 |
21 |+ def __iter__(self) -> collections.abc.Iterator:
22 22 | ... # PYI058 (use `Iterator`)
23 23 |
24 24 |

PYI058.py:30:13: PYI058 [*] Use `Iterator` as the return value for simple `__iter__` methods
|
Expand All @@ -75,19 +70,14 @@ PYI058.py:30:13: PYI058 [*] Use `Iterator` as the return value for simple `__ite
= help: Convert the return annotation of your `__iter__` method to `Iterator`

Safe fix
1 |+from collections.abc import Iterator
1 2 | def scope():
2 3 | from collections.abc import Generator
3 4 |
--------------------------------------------------------------------------------
27 28 | from typing import Any
28 29 |
29 30 | class IteratorReturningSimpleGenerator4:
27 27 | from typing import Any
28 28 |
29 29 | class IteratorReturningSimpleGenerator4:
30 |- def __iter__(self, /) -> collections.abc.Generator[str, Any, None]:
31 |+ def __iter__(self, /) -> Iterator[str]:
31 32 | ... # PYI058 (use `Iterator`)
32 33 |
33 34 |
30 |+ def __iter__(self, /) -> collections.abc.Iterator[str]:
31 31 | ... # PYI058 (use `Iterator`)
32 32 |
33 33 |

PYI058.py:39:13: PYI058 [*] Use `Iterator` as the return value for simple `__iter__` methods
|
Expand All @@ -99,19 +89,14 @@ PYI058.py:39:13: PYI058 [*] Use `Iterator` as the return value for simple `__ite
= help: Convert the return annotation of your `__iter__` method to `Iterator`

Safe fix
1 |+from collections.abc import Iterator
1 2 | def scope():
2 3 | from collections.abc import Generator
3 4 |
--------------------------------------------------------------------------------
36 37 | import typing
37 38 |
38 39 | class IteratorReturningSimpleGenerator5:
36 36 | import typing
37 37 |
38 38 | class IteratorReturningSimpleGenerator5:
39 |- def __iter__(self, /) -> collections.abc.Generator[str, None, typing.Any]:
40 |+ def __iter__(self, /) -> Iterator[str]:
40 41 | ... # PYI058 (use `Iterator`)
41 42 |
42 43 |
39 |+ def __iter__(self, /) -> collections.abc.Iterator[str]:
40 40 | ... # PYI058 (use `Iterator`)
41 41 |
42 42 |

PYI058.py:47:13: PYI058 [*] Use `Iterator` as the return value for simple `__iter__` methods
|
Expand Down Expand Up @@ -167,18 +152,13 @@ PYI058.py:73:13: PYI058 [*] Use `AsyncIterator` as the return value for simple `
= help: Convert the return annotation of your `__aiter__` method to `AsyncIterator`

Safe fix
1 |+from collections.abc import AsyncIterator
1 2 | def scope():
2 3 | from collections.abc import Generator
3 4 |
--------------------------------------------------------------------------------
70 71 | import collections.abc
71 72 |
72 73 | class AsyncIteratorReturningSimpleAsyncGenerator3:
70 70 | import collections.abc
71 71 |
72 72 | class AsyncIteratorReturningSimpleAsyncGenerator3:
73 |- def __aiter__(self, /) -> collections.abc.AsyncGenerator[str, None]:
74 |+ def __aiter__(self, /) -> AsyncIterator[str]:
74 75 | ... # PYI058 (Use `AsyncIterator`)
75 76 |
76 77 |
73 |+ def __aiter__(self, /) -> collections.abc.AsyncIterator[str]:
74 74 | ... # PYI058 (Use `AsyncIterator`)
75 75 |
76 76 |


Original file line number Diff line number Diff line change
Expand Up @@ -54,19 +54,14 @@ PYI058.pyi:17:13: PYI058 [*] Use `Iterator` as the return value for simple `__it
= help: Convert the return annotation of your `__iter__` method to `Iterator`

Safe fix
1 |+from collections.abc import Iterator
1 2 | def scope():
2 3 | from collections.abc import Generator
3 4 |
--------------------------------------------------------------------------------
14 15 | import collections.abc
15 16 |
16 17 | class IteratorReturningSimpleGenerator3:
14 14 | import collections.abc
15 15 |
16 16 | class IteratorReturningSimpleGenerator3:
17 |- def __iter__(self) -> collections.abc.Generator: ... # PYI058 (use `Iterator`)
18 |+ def __iter__(self) -> Iterator: ... # PYI058 (use `Iterator`)
18 19 |
19 20 | def scope():
20 21 | import collections.abc
17 |+ def __iter__(self) -> collections.abc.Iterator: ... # PYI058 (use `Iterator`)
18 18 |
19 19 | def scope():
20 20 | import collections.abc

PYI058.pyi:24:13: PYI058 [*] Use `Iterator` as the return value for simple `__iter__` methods
|
Expand All @@ -79,19 +74,14 @@ PYI058.pyi:24:13: PYI058 [*] Use `Iterator` as the return value for simple `__it
= help: Convert the return annotation of your `__iter__` method to `Iterator`

Safe fix
1 |+from collections.abc import Iterator
1 2 | def scope():
2 3 | from collections.abc import Generator
3 4 |
--------------------------------------------------------------------------------
21 22 | from typing import Any
22 23 |
23 24 | class IteratorReturningSimpleGenerator4:
21 21 | from typing import Any
22 22 |
23 23 | class IteratorReturningSimpleGenerator4:
24 |- def __iter__(self, /) -> collections.abc.Generator[str, Any, None]: ... # PYI058 (use `Iterator`)
25 |+ def __iter__(self, /) -> Iterator[str]: ... # PYI058 (use `Iterator`)
25 26 |
26 27 | def scope():
27 28 | import collections.abc
24 |+ def __iter__(self, /) -> collections.abc.Iterator[str]: ... # PYI058 (use `Iterator`)
25 25 |
26 26 | def scope():
27 27 | import collections.abc

PYI058.pyi:31:13: PYI058 [*] Use `Iterator` as the return value for simple `__iter__` methods
|
Expand All @@ -104,19 +94,14 @@ PYI058.pyi:31:13: PYI058 [*] Use `Iterator` as the return value for simple `__it
= help: Convert the return annotation of your `__iter__` method to `Iterator`

Safe fix
1 |+from collections.abc import Iterator
1 2 | def scope():
2 3 | from collections.abc import Generator
3 4 |
--------------------------------------------------------------------------------
28 29 | import typing
29 30 |
30 31 | class IteratorReturningSimpleGenerator5:
28 28 | import typing
29 29 |
30 30 | class IteratorReturningSimpleGenerator5:
31 |- def __iter__(self, /) -> collections.abc.Generator[str, None, typing.Any]: ... # PYI058 (use `Iterator`)
32 |+ def __iter__(self, /) -> Iterator[str]: ... # PYI058 (use `Iterator`)
32 33 |
33 34 | def scope():
34 35 | from collections.abc import Generator
31 |+ def __iter__(self, /) -> collections.abc.Iterator[str]: ... # PYI058 (use `Iterator`)
32 32 |
33 33 | def scope():
34 34 | from collections.abc import Generator

PYI058.pyi:37:13: PYI058 [*] Use `Iterator` as the return value for simple `__iter__` methods
|
Expand Down Expand Up @@ -173,19 +158,14 @@ PYI058.pyi:49:13: PYI058 [*] Use `AsyncIterator` as the return value for simple
= help: Convert the return annotation of your `__aiter__` method to `AsyncIterator`

Safe fix
1 |+from collections.abc import AsyncIterator
1 2 | def scope():
2 3 | from collections.abc import Generator
3 4 |
--------------------------------------------------------------------------------
46 47 | import collections.abc
47 48 |
48 49 | class AsyncIteratorReturningSimpleAsyncGenerator3:
46 46 | import collections.abc
47 47 |
48 48 | class AsyncIteratorReturningSimpleAsyncGenerator3:
49 |- def __aiter__(self, /) -> collections.abc.AsyncGenerator[str, None]:
50 |+ def __aiter__(self, /) -> AsyncIterator[str]:
50 51 | ... # PYI058 (Use `AsyncIterator`)
51 52 |
52 53 | def scope():
49 |+ def __aiter__(self, /) -> collections.abc.AsyncIterator[str]:
50 50 | ... # PYI058 (Use `AsyncIterator`)
51 51 |
52 52 | def scope():

PYI058.pyi:56:13: PYI058 [*] Use `AsyncIterator` as the return value for simple `__aiter__` methods
|
Expand All @@ -198,18 +178,13 @@ PYI058.pyi:56:13: PYI058 [*] Use `AsyncIterator` as the return value for simple
= help: Convert the return annotation of your `__aiter__` method to `AsyncIterator`

Safe fix
1 |+from collections.abc import AsyncIterator
1 2 | def scope():
2 3 | from collections.abc import Generator
3 4 |
--------------------------------------------------------------------------------
53 54 | import collections.abc
54 55 |
55 56 | class AsyncIteratorReturningSimpleAsyncGenerator3:
53 53 | import collections.abc
54 54 |
55 55 | class AsyncIteratorReturningSimpleAsyncGenerator3:
56 |- def __aiter__(self, /) -> collections.abc.AsyncGenerator[str, None]: ... # PYI058 (Use `AsyncIterator`)
57 |+ def __aiter__(self, /) -> AsyncIterator[str]: ... # PYI058 (Use `AsyncIterator`)
57 58 |
58 59 | def scope():
59 60 | from typing import Iterator
56 |+ def __aiter__(self, /) -> collections.abc.AsyncIterator[str]: ... # PYI058 (Use `AsyncIterator`)
57 57 |
58 58 | def scope():
59 59 | from typing import Iterator


8 changes: 5 additions & 3 deletions crates/ruff_python_semantic/src/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -802,8 +802,10 @@ impl<'a> SemanticModel<'a> {
}
// Ex) Given `module="os"` and `object="name"`:
// `import os.path ` -> `os.name`
BindingKind::SubmoduleImport(SubmoduleImport { .. }) => {
if name == module {
// Ex) Given `module="os.path"` and `object="join"`:
// `import os.path ` -> `os.path.join`
BindingKind::SubmoduleImport(SubmoduleImport { call_path }) => {
if call_path.starts_with(&module_path) {
if let Some(source) = binding.source {
// Verify that `os` isn't bound in an inner scope.
if self
Expand All @@ -812,7 +814,7 @@ impl<'a> SemanticModel<'a> {
.all(|scope| !scope.has(name))
{
return Some(ImportedName {
name: format!("{name}.{member}"),
name: format!("{module}.{member}"),
source,
range: self.nodes[source].range(),
context: binding.context,
Expand Down

0 comments on commit 2e1ed80

Please sign in to comment.