Skip to content

Commit 1e05190

Browse files
committed
import-outside-toplevel is emitted for ImportFrom nodes as well.
Close #3175
1 parent 3f86141 commit 1e05190

16 files changed

+31
-28
lines changed

ChangeLog

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ Release date: TBA
1818
Close #3148
1919

2020

21+
* ``import-outside-toplevel`` is emitted for ``ImportFrom`` nodes as well.
22+
23+
Close #3175
24+
2125
What's New in Pylint 2.4.2?
2226
===========================
2327

pylint/__init__.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,35 +9,35 @@
99

1010
import sys
1111

12-
from .__pkginfo__ import version as __version__
12+
from pylint.__pkginfo__ import version as __version__
13+
from pylint.checkers.similar import Run as SimilarRun
14+
from pylint.epylint import Run as EpylintRun
15+
from pylint.lint import Run as PylintRun
16+
from pylint.pyreverse.main import Run as PyreverseRun
1317

1418

1519
def run_pylint():
1620
"""run pylint"""
17-
from pylint.lint import Run
1821

1922
try:
20-
Run(sys.argv[1:])
23+
PylintRun(sys.argv[1:])
2124
except KeyboardInterrupt:
2225
sys.exit(1)
2326

2427

2528
def run_epylint():
2629
"""run pylint"""
27-
from pylint.epylint import Run
2830

29-
Run()
31+
EpylintRun()
3032

3133

3234
def run_pyreverse():
3335
"""run pyreverse"""
34-
from pylint.pyreverse.main import Run
3536

36-
Run(sys.argv[1:])
37+
PyreverseRun(sys.argv[1:])
3738

3839

3940
def run_symilar():
4041
"""run symilar"""
41-
from pylint.checkers.similar import Run
4242

43-
Run(sys.argv[1:])
43+
SimilarRun(sys.argv[1:])

pylint/checkers/imports.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,7 @@ def visit_importfrom(self, node):
520520
self._check_wildcard_imports(node, imported_module)
521521
self._check_same_line_imports(node)
522522
self._check_reimport(node, basename=basename, level=node.level)
523+
self._check_toplevel(node)
523524

524525
if isinstance(node.parent, astroid.Module):
525526
# Allow imports nested

pylint/checkers/similar.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
import sys
2121
from collections import defaultdict
22+
from getopt import getopt
2223
from itertools import groupby
2324

2425
import astroid
@@ -412,7 +413,6 @@ def Run(argv=None):
412413
"""standalone command line access point"""
413414
if argv is None:
414415
argv = sys.argv[1:]
415-
from getopt import getopt
416416

417417
s_opts = "hdi"
418418
l_opts = (

pylint/lint.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@
7373
from astroid.__pkginfo__ import version as astroid_version
7474
from astroid.builder import AstroidBuilder
7575

76-
from pylint import checkers, config, exceptions, interfaces, reporters
76+
from pylint import __pkginfo__, checkers, config, exceptions, interfaces, reporters
7777
from pylint.__pkginfo__ import version
7878
from pylint.constants import MAIN_CHECKER_NAME, MSG_TYPES, OPTION_RGX
7979
from pylint.message import Message, MessageDefinitionStore, MessagesHandlerMixIn
@@ -1761,8 +1761,6 @@ def cb_generate_config(self, *args, **kwargs):
17611761

17621762
def cb_generate_manpage(self, *args, **kwargs):
17631763
"""optik callback for sample config file generation"""
1764-
from pylint import __pkginfo__
1765-
17661764
self.linter.generate_manpage(__pkginfo__)
17671765
sys.exit(0)
17681766

pylint/reporters/__init__.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
"""utilities methods and classes for reporters"""
2020

2121

22+
from pylint import utils
2223
from pylint.reporters.base_reporter import BaseReporter
2324
from pylint.reporters.collecting_reporter import CollectingReporter
2425
from pylint.reporters.json_reporter import JSONReporter
@@ -27,8 +28,6 @@
2728

2829
def initialize(linter):
2930
"""initialize linter with reporters in this package """
30-
from pylint import utils
31-
3231
utils.register_plugins(linter, __path__[0])
3332

3433

tests/functional/b/bad_reversed_sequence.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
""" Checks that reversed() receive proper argument """
22
# pylint: disable=missing-docstring, useless-object-inheritance
33
# pylint: disable=too-few-public-methods,no-self-use,no-absolute-import
4-
from collections import deque
4+
from collections import deque, OrderedDict
5+
from enum import IntEnum
56

6-
__revision__ = 0
77

88
class GoodReversed(object):
99
""" Implements __reversed__ """
@@ -61,8 +61,6 @@ def test(path):
6161

6262
def test_dict_ancestor_and_reversed():
6363
"""Don't emit for subclasses of dict, with __reversed__ implemented."""
64-
from collections import OrderedDict
65-
6664
class Child(dict):
6765
def __reversed__(self):
6866
return reversed(range(10))
@@ -73,8 +71,6 @@ def __reversed__(self):
7371

7472
def test_dont_emit_for_reversing_enums():
7573
"""Don't emit when reversing enum classes"""
76-
from enum import IntEnum
77-
7874
class Color(IntEnum):
7975
RED = 1
8076
GREEN = 2

tests/functional/b/bugfix_local_scope_metaclass_1177.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# pylint: disable=missing-docstring,too-few-public-methods,import-error
2-
from UNINFERABLE import ImportedMetaclass
2+
from UNINFERABLE import ImportedMetaclass, ImportedMetaclass2
33

44

55
class Meta(type):
@@ -48,8 +48,6 @@ class ClassImp2(metaclass=ImportedMetaclass):
4848

4949

5050
def imported_and_nested_scope2():
51-
from UNINFERABLE import ImportedMetaclass2
52-
5351
class ClassImp3(metaclass=ImportedMetaclass2):
5452
pass
5553

tests/functional/c/consider_using_enumerate.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ def good():
4949
for index in range(len(iterable)):
5050
yield other_obj[index]
5151

52+
# pylint: disable=import-outside-toplevel
5253
from unknown import unknown
5354
for index in range(unknown(iterable)):
5455
yield iterable[index]

tests/functional/import_outside_toplevel.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,7 @@ def j(self):
3232
def k(flag):
3333
if flag:
3434
import tabnanny # [import-outside-toplevel]
35+
36+
37+
def j():
38+
from collections import defaultdict # [import-outside-toplevel]

tests/functional/import_outside_toplevel.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ import-outside-toplevel:22:i:Import outside toplevel (random, socket)
55
import-outside-toplevel:26:C:Import outside toplevel (tokenize)
66
import-outside-toplevel:29:C.j:Import outside toplevel (turtle)
77
import-outside-toplevel:34:k:Import outside toplevel (tabnanny)
8+
import-outside-toplevel:38:j:Import outside toplevel (collections)

tests/functional/r/redefined_outer_name_type_checking.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
class Cls:
99
def func(self, stuff: defaultdict):
1010
# This import makes the definition work.
11+
# pylint: disable=import-outside-toplevel
1112
from collections import defaultdict
1213

1314
obj = defaultdict()

tests/functional/s/string_formatting.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ def issue338():
134134
trying to infer EmptyNodes (resulted after mocking the
135135
members of namedtuples).
136136
"""
137-
from collections import namedtuple
137+
from collections import namedtuple # pylint: disable=import-outside-toplevel
138138

139139
class Crash(namedtuple("C", "foo bar")):
140140
""" Looking for attributes in __str__ will crash,

tests/functional/s/string_formatting_py3.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,5 @@ def issue_957_bad2():
1717

1818

1919
def issue_957_uninferable():
20-
from butchery import meat
20+
from butchery import meat # pylint: disable=import-outside-toplevel
2121
print('%s%s%s' % ('eggs', *meat))

tests/functional/u/unbalanced_tuple_unpacking.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from __future__ import absolute_import
33
from functional.u.unpacking import unpack
44

5-
# pylint: disable=using-constant-test, useless-object-inheritance
5+
# pylint: disable=using-constant-test, useless-object-inheritance,import-outside-toplevel
66

77
def do_stuff():
88
"""This is not right."""

tests/input/func_w0401_disabled_in_func.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"""Test disabling of cyclic import check inside a function
22
"""
3-
# pylint: disable=no-absolute-import
3+
# pylint: disable=no-absolute-import,import-outside-toplevel
44
from __future__ import print_function
55

66

0 commit comments

Comments
 (0)