-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
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
Better story for import redefinitions #13969
Conversation
This changes our importing logic to be more consistent and to treat import statements more like assignments. Fixes python#13803 The primary motivation for this is when typing modules as protocols, as in the linked issue. But it turns out we already allowed redefinition with from imports, so this just seems like a nice consistency win. We move shared logic from visit_import_all and visit_import_from (via process_imported_symbol) into add_imported_symbol. We then reuse it in visit_import. To simplify stuff, we inline the code from add_module_symbol into visit_import. Then we copy over logic from add_symbol, because MypyFile is not a SymbolTableNode, but this isn't the worst thing ever. Finally, we now need to check non-from import statements like assignments, which was a thing we weren't doing earlier.
[stale] | ||
[out2] | ||
tmp/b.py:4: error: Name "a" already defined on line 3 | ||
[stale b] |
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.
Not fully sure what's going on with this particular test case, maybe we should delete it since the behaviour now looks pretty similar to ignore. Alternatively, could add some new special case logic in checker.py to disallow assignments via import x
to things typed Any (although I don't really like the idea of doing that).
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.
We can keep this test case, though it's not super interesting. The changes to the test case look reasonable to me. There's no particular reason to generate an error here.
This comment has been minimized.
This comment has been minimized.
Okay, primer looks pretty good. The one change is some type ignores go from error code no-redef to assignment. I think this is okay — it's more consistent with what would happen with "from" 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.
This looks more consistent that the pretty ad-hoc rules we had for imports previously. Left some ideas about additional test cases. If you don't think they are useful, this is ready to merge.
[stale] | ||
[out2] | ||
tmp/b.py:4: error: Name "a" already defined on line 3 | ||
[stale b] |
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.
We can keep this test case, though it's not super interesting. The changes to the test case look reasonable to me. There's no particular reason to generate an error here.
def f(self) -> str: ... | ||
|
||
cond: bool | ||
t: P |
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 something like c: Type[Cls]
and then conditionally importing two different classes? Also, f: Callable[[int], str]
and then importing functions, perhaps. Or maybe these are covered by existing test cases?
Diff from mypy_primer, showing the effect of this PR on open source code: psycopg (https://github.com/psycopg/psycopg)
+ psycopg/psycopg/pq/__init__.py:89: error: Unused "type: ignore" comment
+ psycopg/psycopg/pq/__init__.py:89: error: Incompatible import of "module" (imported name has type Module, local name has type "object") [assignment]
+ psycopg/psycopg/pq/__init__.py:89: note: Error code "assignment" not covered by "type: ignore" comment
+ tests/test_copy.py:312: error: Unused "type: ignore" comment
+ tests/test_copy.py:312: error: Incompatible import of "BaseDumper" (imported name has type "Type[StrBinaryDumper]", local name has type "Type[StrDumper]") [assignment]
+ tests/test_copy.py:312: note: Error code "assignment" not covered by "type: ignore" comment
+ tests/test_copy_async.py:305: error: Unused "type: ignore" comment
+ tests/test_copy_async.py:305: error: Incompatible import of "BaseDumper" (imported name has type "Type[StrBinaryDumper]", local name has type "Type[StrDumper]") [assignment]
+ tests/test_copy_async.py:305: note: Error code "assignment" not covered by "type: ignore" comment
cwltool (https://github.com/common-workflow-language/cwltool)
+ cwltool/utils.py:252: error: Unused "type: ignore" comment
+ cwltool/utils.py:254: error: Unused "type: ignore" comment
werkzeug (https://github.com/pallets/werkzeug)
+ src/werkzeug/utils.py:267: error: Unused "type: ignore" comment
dragonchain (https://github.com/dragonchain/dragonchain)
+ dragonchain/transaction_processor/transaction_processor.py:45:9: error: Name "processor" already defined (by an import) [no-redef]
+ dragonchain/transaction_processor/transaction_processor.py:47:9: error: Name "processor" already defined (by an import) [no-redef]
+ dragonchain/transaction_processor/transaction_processor.py:49:9: error: Name "processor" already defined (by an import) [no-redef]
+ dragonchain/transaction_processor/transaction_processor.py:52:9: error: Name "processor" already defined (by an import) [no-redef]
+ dragonchain/transaction_processor/transaction_processor.py:54:9: error: Module has no attribute "setup" [attr-defined]
pandas (https://github.com/pandas-dev/pandas)
+ pandas/core/frame.py:2695: error: Unused "type: ignore" comment
+ pandas/core/frame.py:2695: error: Incompatible import of "statawriter" (imported name has type "Type[StataWriter117]", local name has type "Type[StataWriter]") [assignment]
+ pandas/core/frame.py:2695: note: Error code "assignment" not covered by "type: ignore" comment
+ pandas/core/frame.py:2700: error: Unused "type: ignore" comment
+ pandas/core/frame.py:2700: error: Incompatible import of "statawriter" (imported name has type "Type[StataWriterUTF8]", local name has type "Type[StataWriter]") [assignment]
+ pandas/core/frame.py:2700: note: Error code "assignment" not covered by "type: ignore" comment
pytest (https://github.com/pytest-dev/pytest)
- testing/_py/test_local.py:1156: error: Name "isimportable" already defined (possibly by an import) [no-redef]
jinja (https://github.com/pallets/jinja)
+ src/jinja2/utils.py:185: error: Unused "type: ignore" comment
aiohttp (https://github.com/aio-libs/aiohttp)
+ aiohttp/client_reqrep.py:75: error: Unused "type: ignore" comment
|
fix mypy fail caused by python/mypy#13969
…lc into fix_localhost_platform_matching * 'fix_localhost_platform_matching' of github.com:wxtim/cylc: Fix a bug preventing `cylc vip --workflow-name=foo` from working. (cylc#5349) fix no rose vars in cylc view (cylc#5367) Cylc lint fixes (cylc#5363) data store: support unsatisfied ext_trigger fix mypy fail caused by python/mypy#13969
This changes our importing logic to be more consistent and to treat import statements more like assignments.
Fixes #13803, fixes #13914, fixes half of #12965, probably fixes #12574
The primary motivation for this is when typing modules as protocols, as in #13803. But it turns out we already allowed redefinition with "from" imports, so this also seems like a nice consistency win.
We move shared logic from visit_import_all and visit_import_from (via process_imported_symbol) into add_imported_symbol. We then reuse it in visit_import.
To simplify stuff, we inline the code from add_module_symbol into visit_import. Then we copy over logic from add_symbol, because MypyFile is not a SymbolTableNode, but this isn't the worst thing ever.
Finally, we now need to check non-from import statements like assignments, which was a thing we weren't doing earlier.