Implement pylint import-outside-toplevel rule (C0415)#5180
Implement pylint import-outside-toplevel rule (C0415)#5180charliermarsh merged 1 commit intoastral-sh:mainfrom
Conversation
PR Check ResultsEcosystemℹ️ ecosystem check detected linter changes. (+10 -0 violations, +0 -0 fixes in 41 projects) rotki/rotki (+10 -0 violations, +0 -0 fixes)
ruff check --no-cache --exit-zero
+ rotkehlchen/assets/resolver.py:127:9: PLC0415 `import` should be at the top-level of a file + rotkehlchen/assets/resolver.py:128:9: PLC0415 `import` should be at the top-level of a file + rotkehlchen/assets/resolver.py:158:9: PLC0415 `import` should be at the top-level of a file + rotkehlchen/assets/resolver.py:159:9: PLC0415 `import` should be at the top-level of a file + rotkehlchen/assets/resolver.py:70:9: PLC0415 `import` should be at the top-level of a file + rotkehlchen/assets/resolver.py:71:9: PLC0415 `import` should be at the top-level of a file + rotkehlchen/assets/resolver.py:96:9: PLC0415 `import` should be at the top-level of a file + rotkehlchen/assets/resolver.py:97:9: PLC0415 `import` should be at the top-level of a file + rotkehlchen/tests/conftest.py:133:9: PLC0415 `import` should be at the top-level of a file + tools/pyinstaller_hooks/pre_find_module_path/hook-distutils.py:40:5: PLC0415 `import` should be at the top-level of a file Changes by rule (1 rules affected)
|
|
|
||
| /// C0415 | ||
| pub(crate) fn import_outside_top_level(checker: &mut Checker, stmt: &Stmt) { | ||
| if !checker.semantic().at_top_level() && !checker.semantic().in_type_checking_block() { |
There was a problem hiding this comment.
As far as I can tell, Pylint only flags this for imports outside of the module scope:
if True:
import sys # Pylint doesn't flag this.
def foo():
import sys # It does flag this!I think this should perhaps be !checker.scope().kind.is_module()?
|
@charliermarsh I've gone with your suggestion of just checking the semantic scope kind. I had misinterpreted one of the tests from pylint and it does look like they considered nested conditionals to be at the top-level (and that's why pylint needs no special handling for type-checking). I've also updated the documentation for this check as I don't think PEP8 completely offers a rationale for this rule. The pylint PR for this rule also doesn't provide a lot of explanation, so I've done my best to offer a more complete rationale for this check, but I'd welcome suggestions. |
|
For the record, this is why ChatGPT thinks we should place our imports at the top-level of a module:
|
|
The autofix for this could be #1251 |
33c5da3 to
8f891cf
Compare
Summary
Implements pylint C0415 (import-outside-toplevel) — imports should be at the top level of a file.
The great debate I had on this implementation is whether "top-level" is one word or two (
toplevelortop_level). I opted for 2 because that seemed to be how it is used in the codebase but the rule string itself uses one-word "toplevel." 🤷 I'd be happy to change it as desired.I suppose this could be auto-fixed by moving the import to the top-level, but it seems likely that the author's intent was to actually import this dynamically, so I view the main point of this rule is to force some sort of explanation, and auto-fixing might be annoying.
For reference, this is what "pylint" reports:
ruff would now report:
Contributes to #970.
Test Plan
Snapshot test.