Skip to content

Commit

Permalink
import-outside-toplevel is emitted for ImportFrom nodes as well.
Browse files Browse the repository at this point in the history
Close #3175
  • Loading branch information
PCManticore committed Oct 9, 2019
1 parent e0ab5b9 commit d3eda2e
Show file tree
Hide file tree
Showing 16 changed files with 31 additions and 28 deletions.
4 changes: 4 additions & 0 deletions ChangeLog
Expand Up @@ -12,6 +12,10 @@ Release date: TBA
Close #3148


* ``import-outside-toplevel`` is emitted for ``ImportFrom`` nodes as well.

Close #3175

What's New in Pylint 2.4.2?
===========================

Expand Down
18 changes: 9 additions & 9 deletions pylint/__init__.py
Expand Up @@ -9,35 +9,35 @@

import sys

from .__pkginfo__ import version as __version__
from pylint.__pkginfo__ import version as __version__
from pylint.checkers.similar import Run as SimilarRun
from pylint.epylint import Run as EpylintRun
from pylint.lint import Run as PylintRun
from pylint.pyreverse.main import Run as PyreverseRun


def run_pylint():
"""run pylint"""
from pylint.lint import Run

try:
Run(sys.argv[1:])
PylintRun(sys.argv[1:])
except KeyboardInterrupt:
sys.exit(1)


def run_epylint():
"""run pylint"""
from pylint.epylint import Run

Run()
EpylintRun()


def run_pyreverse():
"""run pyreverse"""
from pylint.pyreverse.main import Run

Run(sys.argv[1:])
PyreverseRun(sys.argv[1:])


def run_symilar():
"""run symilar"""
from pylint.checkers.similar import Run

Run(sys.argv[1:])
SimilarRun(sys.argv[1:])
1 change: 1 addition & 0 deletions pylint/checkers/imports.py
Expand Up @@ -520,6 +520,7 @@ def visit_importfrom(self, node):
self._check_wildcard_imports(node, imported_module)
self._check_same_line_imports(node)
self._check_reimport(node, basename=basename, level=node.level)
self._check_toplevel(node)

if isinstance(node.parent, astroid.Module):
# Allow imports nested
Expand Down
2 changes: 1 addition & 1 deletion pylint/checkers/similar.py
Expand Up @@ -19,6 +19,7 @@

import sys
from collections import defaultdict
from getopt import getopt
from itertools import groupby

import astroid
Expand Down Expand Up @@ -412,7 +413,6 @@ def Run(argv=None):
"""standalone command line access point"""
if argv is None:
argv = sys.argv[1:]
from getopt import getopt

s_opts = "hdi"
l_opts = (
Expand Down
4 changes: 1 addition & 3 deletions pylint/lint.py
Expand Up @@ -73,7 +73,7 @@
from astroid.__pkginfo__ import version as astroid_version
from astroid.builder import AstroidBuilder

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

def cb_generate_manpage(self, *args, **kwargs):
"""optik callback for sample config file generation"""
from pylint import __pkginfo__

self.linter.generate_manpage(__pkginfo__)
sys.exit(0)

Expand Down
3 changes: 1 addition & 2 deletions pylint/reporters/__init__.py
Expand Up @@ -19,6 +19,7 @@
"""utilities methods and classes for reporters"""


from pylint import utils
from pylint.reporters.base_reporter import BaseReporter
from pylint.reporters.collecting_reporter import CollectingReporter
from pylint.reporters.json_reporter import JSONReporter
Expand All @@ -27,8 +28,6 @@

def initialize(linter):
"""initialize linter with reporters in this package """
from pylint import utils

utils.register_plugins(linter, __path__[0])


Expand Down
8 changes: 2 additions & 6 deletions tests/functional/b/bad_reversed_sequence.py
@@ -1,9 +1,9 @@
""" Checks that reversed() receive proper argument """
# pylint: disable=missing-docstring, useless-object-inheritance
# pylint: disable=too-few-public-methods,no-self-use,no-absolute-import
from collections import deque
from collections import deque, OrderedDict
from enum import IntEnum

__revision__ = 0

class GoodReversed(object):
""" Implements __reversed__ """
Expand Down Expand Up @@ -61,8 +61,6 @@ def test(path):

def test_dict_ancestor_and_reversed():
"""Don't emit for subclasses of dict, with __reversed__ implemented."""
from collections import OrderedDict

class Child(dict):
def __reversed__(self):
return reversed(range(10))
Expand All @@ -73,8 +71,6 @@ def __reversed__(self):

def test_dont_emit_for_reversing_enums():
"""Don't emit when reversing enum classes"""
from enum import IntEnum

class Color(IntEnum):
RED = 1
GREEN = 2
Expand Down
4 changes: 1 addition & 3 deletions tests/functional/b/bugfix_local_scope_metaclass_1177.py
@@ -1,5 +1,5 @@
# pylint: disable=missing-docstring,too-few-public-methods,import-error
from UNINFERABLE import ImportedMetaclass
from UNINFERABLE import ImportedMetaclass, ImportedMetaclass2


class Meta(type):
Expand Down Expand Up @@ -48,8 +48,6 @@ class ClassImp2(metaclass=ImportedMetaclass):


def imported_and_nested_scope2():
from UNINFERABLE import ImportedMetaclass2

class ClassImp3(metaclass=ImportedMetaclass2):
pass

Expand Down
1 change: 1 addition & 0 deletions tests/functional/c/consider_using_enumerate.py
Expand Up @@ -49,6 +49,7 @@ def good():
for index in range(len(iterable)):
yield other_obj[index]

# pylint: disable=import-outside-toplevel
from unknown import unknown
for index in range(unknown(iterable)):
yield iterable[index]
Expand Down
4 changes: 4 additions & 0 deletions tests/functional/import_outside_toplevel.py
Expand Up @@ -32,3 +32,7 @@ def j(self):
def k(flag):
if flag:
import tabnanny # [import-outside-toplevel]


def j():
from collections import defaultdict # [import-outside-toplevel]
1 change: 1 addition & 0 deletions tests/functional/import_outside_toplevel.txt
Expand Up @@ -5,3 +5,4 @@ import-outside-toplevel:22:i:Import outside toplevel (random, socket)
import-outside-toplevel:26:C:Import outside toplevel (tokenize)
import-outside-toplevel:29:C.j:Import outside toplevel (turtle)
import-outside-toplevel:34:k:Import outside toplevel (tabnanny)
import-outside-toplevel:38:j:Import outside toplevel (collections)
1 change: 1 addition & 0 deletions tests/functional/r/redefined_outer_name_type_checking.py
Expand Up @@ -8,6 +8,7 @@
class Cls:
def func(self, stuff: defaultdict):
# This import makes the definition work.
# pylint: disable=import-outside-toplevel
from collections import defaultdict

obj = defaultdict()
Expand Down
2 changes: 1 addition & 1 deletion tests/functional/s/string_formatting.py
Expand Up @@ -134,7 +134,7 @@ def issue338():
trying to infer EmptyNodes (resulted after mocking the
members of namedtuples).
"""
from collections import namedtuple
from collections import namedtuple # pylint: disable=import-outside-toplevel

class Crash(namedtuple("C", "foo bar")):
""" Looking for attributes in __str__ will crash,
Expand Down
2 changes: 1 addition & 1 deletion tests/functional/s/string_formatting_py3.py
Expand Up @@ -17,5 +17,5 @@ def issue_957_bad2():


def issue_957_uninferable():
from butchery import meat
from butchery import meat # pylint: disable=import-outside-toplevel
print('%s%s%s' % ('eggs', *meat))
2 changes: 1 addition & 1 deletion tests/functional/u/unbalanced_tuple_unpacking.py
Expand Up @@ -2,7 +2,7 @@
from __future__ import absolute_import
from functional.u.unpacking import unpack

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

def do_stuff():
"""This is not right."""
Expand Down
2 changes: 1 addition & 1 deletion tests/input/func_w0401_disabled_in_func.py
@@ -1,6 +1,6 @@
"""Test disabling of cyclic import check inside a function
"""
# pylint: disable=no-absolute-import
# pylint: disable=no-absolute-import,import-outside-toplevel
from __future__ import print_function


Expand Down

0 comments on commit d3eda2e

Please sign in to comment.