Handle dotted alias imports to check for implicit imports (#4685)

This commit is contained in:
Dhruv Manilawala 2023-05-28 09:28:03 +05:30 committed by GitHub
parent 9f16ae354e
commit 79b35fc3cc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 114 additions and 2 deletions

View File

@ -55,3 +55,50 @@ def f():
def test(value: A):
return pkg.B()
def f():
# In un-strict mode, this shouldn't rase an error, since `pkg.bar` is used at runtime.
import pkg
import pkg.bar as B
def test(value: pkg.A):
return B()
def f():
# In un-strict mode, this shouldn't rase an error, since `pkg.foo.bar` is used at runtime.
import pkg.foo as F
import pkg.foo.bar as B
def test(value: F.Foo):
return B()
def f():
# In un-strict mode, this shouldn't rase an error, since `pkg.foo.bar` is used at runtime.
import pkg
import pkg.foo.bar as B
def test(value: pkg.A):
return B()
def f():
# In un-strict mode, this _should_ rase an error, since `pkgfoo.bar` is used at runtime.
# Note that `pkg` is a prefix of `pkgfoo` which are both different modules. This is
# testing the implementation.
import pkg
import pkgfoo.bar as B
def test(value: pkg.A):
return B()
def f():
# In un-strict mode, this shouldn't raise an error, since `pkg.bar` is used at runtime.
import pkg.bar as B
import pkg.foo as F
def test(value: F.Foo):
return B.Bar()

View File

@ -186,8 +186,18 @@ fn is_implicit_import(this: &Binding, that: &Binding) -> bool {
| BindingKind::SubmoduleImportation(SubmoduleImportation {
name: that_name, ..
}) => {
// Submodule importation with an alias (`import pkg.A as B`)
// are represented as `Importation`.
match (this_name.find('.'), that_name.find('.')) {
// Ex) `pkg.A` vs. `pkg.B`
this_name == that_name
(Some(i), Some(j)) => this_name[..i] == that_name[..j],
// Ex) `pkg.A` vs. `pkg`
(Some(i), None) => this_name[..i] == **that_name,
// Ex) `pkg` vs. `pkg.B`
(None, Some(j)) => **this_name == that_name[..j],
// Ex) `pkg` vs. `pkg`
(None, None) => this_name == that_name,
}
}
_ => false,
},

View File

@ -31,4 +31,50 @@ strict.py:54:25: TCH002 Move third-party import `pkg.bar.A` into a type-checking
58 | def test(value: A):
|
strict.py:62:12: TCH002 Move third-party import `pkg` into a type-checking block
|
62 | def f():
63 | # In un-strict mode, this shouldn't rase an error, since `pkg.bar` is used at runtime.
64 | import pkg
| ^^^ TCH002
65 | import pkg.bar as B
|
strict.py:71:12: TCH002 Move third-party import `pkg.foo` into a type-checking block
|
71 | def f():
72 | # In un-strict mode, this shouldn't rase an error, since `pkg.foo.bar` is used at runtime.
73 | import pkg.foo as F
| ^^^^^^^^^^^^ TCH002
74 | import pkg.foo.bar as B
|
strict.py:80:12: TCH002 Move third-party import `pkg` into a type-checking block
|
80 | def f():
81 | # In un-strict mode, this shouldn't rase an error, since `pkg.foo.bar` is used at runtime.
82 | import pkg
| ^^^ TCH002
83 | import pkg.foo.bar as B
|
strict.py:91:12: TCH002 Move third-party import `pkg` into a type-checking block
|
91 | # Note that `pkg` is a prefix of `pkgfoo` which are both different modules. This is
92 | # testing the implementation.
93 | import pkg
| ^^^ TCH002
94 | import pkgfoo.bar as B
|
strict.py:101:12: TCH002 Move third-party import `pkg.foo` into a type-checking block
|
101 | # In un-strict mode, this shouldn't raise an error, since `pkg.bar` is used at runtime.
102 | import pkg.bar as B
103 | import pkg.foo as F
| ^^^^^^^^^^^^ TCH002
104 |
105 | def test(value: F.Foo):
|

View File

@ -11,4 +11,13 @@ strict.py:54:25: TCH002 Move third-party import `pkg.bar.A` into a type-checking
58 | def test(value: A):
|
strict.py:91:12: TCH002 Move third-party import `pkg` into a type-checking block
|
91 | # Note that `pkg` is a prefix of `pkgfoo` which are both different modules. This is
92 | # testing the implementation.
93 | import pkg
| ^^^ TCH002
94 | import pkgfoo.bar as B
|