-
-
Notifications
You must be signed in to change notification settings - Fork 3k
Stricter handling of submodules as attributes #20179
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
Conversation
This comment has been minimized.
This comment has been minimized.
|
Random check: primer installs The stubs have empty |
|
(should we clean up type dependencies in mypy-primer?..) |
|
A few other entries:
Testcase for a ( |
|
@sterliakov Thanks for the analysis! I think both |
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice! That was correct, and you won't have to untangle the beartype metaprogramming...
|
Oh, but then something like this fails on the second run Because ancestors are not treated as a dependency, so they may not be loaded. Not sure what to do here, we can't really make ancestors dependencies because this will create a lot of extra "import cycles". So maybe we will need to accept few false positives for the sake of consistency between cold an warm runs. |
Yes, you can make a PR to github.com/hauntsaninja/mypy-primer to fix this. |
Or maybe we can load the ancestors if they are fresh. Need some time to figure out if this will always be correct. |
|
Ough.
If the ancestor module is fresh, you should be able to add it as a dependency "for free", right? And if it's stale, it should already be analyzed as another target, so it will be in the modules map anyway. Am I missing something? |
Unfortunately, this doesn't work. For example, in test case I posted, if I touch The real problem is the difference between how we handle import foo.bar.bazvs from foo.bar import bazAlthough runtime effect on So the only robust solution is to handle After thinking more about this, it is quite natural to rely on the fact that after So my conclusion is that we can declare the runtime behaviour of |
This comment has been minimized.
This comment has been minimized.
| return sym | ||
|
|
||
| def is_visible_import(self, base_id: str, id: str) -> bool: | ||
| if base_id not in self.transitive_submodule_imports: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about adding a fast path, where we first check if the target is in the direct import dependencies of the current module? For example, if current module has import foo.bar, then foo.bar will be a direct dep. Now we can immediately see that foo.bar will be visible due to it being in import_map, without having to do the recursive search?
|
Diff from mypy_primer, showing the effect of this PR on open source code: beartype (https://github.com/beartype/beartype)
+ beartype/_data/typing/datatyping.py:671: error: Name "beartype._check.forward.reference.fwdrefabc.BeartypeForwardRefABC" is not defined [name-defined]
+ beartype/_check/forward/reference/fwdrefmeta.py:61: error: Unused "type: ignore" comment [unused-ignore]
+ beartype/_check/forward/reference/fwdrefmeta.py:270: error: Unused "type: ignore" comment [unused-ignore]
+ beartype/_check/forward/reference/fwdrefmeta.py:298: error: Unused "type: ignore" comment [unused-ignore]
+ beartype/_check/forward/reference/fwdrefmeta.py:327: error: Unused "type: ignore" comment [unused-ignore]
+ beartype/_check/forward/reference/fwdrefmeta.py:380: error: Unused "type: ignore" comment [unused-ignore]
+ beartype/_check/forward/reference/fwdrefabc.py:218: error: Unused "type: ignore" comment [unused-ignore]
+ beartype/_check/forward/reference/fwdrefmake.py:91: error: Unused "type: ignore" comment [unused-ignore]
CPython (Argument Clinic) (https://github.com/python/cpython)
+ Tools/clinic/libclinic/clanguage.py:67: error: Module has no attribute "cpp" [attr-defined]
zulip (https://github.com/zulip/zulip)
+ zilencer/migrations/0026_auditlog_models_extra_data_json.py:17: error: Module has no attribute "serializers" [attr-defined]
+ zilencer/migrations/0026_auditlog_models_extra_data_json.py:24: error: Module has no attribute "serializers" [attr-defined]
+ zerver/migrations/0452_realmauditlog_extra_data_json.py:17: error: Module has no attribute "serializers" [attr-defined]
cki-lib (https://gitlab.com/cki-project/cki-lib)
- cki_lib/s3bucket.py:76: error: Incompatible types in assignment (expression has type "ParseResult", variable has type "str") [assignment]
+ cki_lib/s3bucket.py:76: error: Module has no attribute "parse" [attr-defined]
mitmproxy (https://github.com/mitmproxy/mitmproxy)
+ mitmproxy/certs.py:98: error: Name "OpenSSL.crypto.X509" is not defined [name-defined]
+ mitmproxy/certs.py:102: error: Name "OpenSSL.crypto.X509" is not defined [name-defined]
+ mitmproxy/certs.py:103: error: Module has no attribute "crypto" [attr-defined]
ibis (https://github.com/ibis-project/ibis)
+ ibis/backends/snowflake/tests/conftest.py:212: error: Module has no attribute "snowflake" [attr-defined]
pandera (https://github.com/pandera-dev/pandera)
+ pandera/engines/type_aliases.py:10: error: Module has no attribute "dtypes" [attr-defined]
+ pandera/engines/type_aliases.py:11: error: Name "pd.core.dtypes.base.ExtensionDtype" is not defined [name-defined]
+ pandera/api/pandas/types.py:18: error: Name "pd.core.dtypes.base.ExtensionDtype" is not defined [name-defined]
+ pandera/typing/pandas.py:106: error: Name "pd.core.dtypes.base.ExtensionDtype" is not defined [name-defined]
- pandera/api/pandas/components.py:23: error: Incompatible default for argument "dtype" (default has type "None", argument has type "str | type | DataType | ExtensionDtype | dtype[Any]") [assignment]
- pandera/api/pandas/components.py:23: note: PEP 484 prohibits implicit Optional. Accordingly, mypy has changed its default to no_implicit_optional=True
- pandera/api/pandas/components.py:23: note: Use https://github.com/hauntsaninja/no_implicit_optional to automatically upgrade your codebase
- pandera/api/pandas/components.py:365: error: Argument "dtype" to "Column" has incompatible type "DataType | None"; expected "str | type | DataType | ExtensionDtype | dtype[Any]" [arg-type]
+ tests/pandas/test_typing.py:320: error: Name "pd.core.dtypes.base.ExtensionDtype" is not defined [name-defined]
+ tests/pandas/test_typing.py:482: error: Name "pd.core.dtypes.base.ExtensionDtype" is not defined [name-defined]
+ tests/pandas/test_schema_components.py:663: error: Unused "type: ignore" comment [unused-ignore]
- tests/pandas/test_multithreaded.py:11: error: Type argument "floating[_32Bit]" of "Series" must be a subtype of "bool | int | str | float | Bool | <30 more items>" [type-var]
- tests/pandas/test_model.py:193: error: Type argument "list[int]" of "Series" must be a subtype of "bool | int | str | float | Bool | <30 more items>" [type-var]
+ tests/pandas/test_model.py:178: error: Unused "type: ignore" comment [unused-ignore]
scipy-stubs (https://github.com/scipy/scipy-stubs)
+ tests/misc/test_subpackage_export.pyi:7: error: Module has no attribute "misc" [attr-defined]
+ tests/misc/test_subpackage_empty.pyi:17: error: Module has no attribute "common" [attr-defined]
+ tests/misc/test_subpackage_empty.pyi:18: error: Module has no attribute "doccer" [attr-defined]
|
Fixes #20174
The idea is quite straightforward: we only allow
foo.barwithout explicit re-export iffoo.barwas imported in any transitive dependency (and not in some unrelated module). Note: onlyimport foo.bartakes effect, effect of usingfrom foo.bar import ...is not propagated for two reasons: