Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Respect multi-segment submodule imports when resolving qualified names #9382

Merged
merged 1 commit into from
Jan 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading