From 9e0620833d014a0c8d34b6bf8c908e01b3ac7e70 Mon Sep 17 00:00:00 2001 From: Laura M?dioni Date: Wed, 2 Dec 2015 09:58:20 +0100 Subject: Allow statements in if or try blocks containing imports. Closes issue #714 --- ChangeLog | 4 ++++ pylint/checkers/imports.py | 21 ++++++++++++++++++--- pylint/test/functional/wrong_import_position.py | 16 ++++++++++++++-- pylint/test/functional/wrong_import_position.txt | 6 +++--- 4 files changed, 39 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index c9410a9..f8129cc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -16,6 +16,10 @@ ChangeLog for Pylint * Don't emit super-on-old-class on classes with unknown bases. Closes issue #721. + * Allow statements in `if` or `try` blocks containing imports. + + Closes issue #714. + * Added a new warning, 'unsupported-assignment-operation', which is emitted when item assignment is tried on an object which doesn't have this ability. Closes issue #591. diff --git a/pylint/checkers/imports.py b/pylint/checkers/imports.py index 2fdcc85..2d37461 100644 --- a/pylint/checkers/imports.py +++ b/pylint/checkers/imports.py @@ -381,9 +381,24 @@ given file (report RP0402 must not be disabled)'} = visit_ifexp = visit_comprehension = visit_if def visit_functiondef(self, node): - # if it is the first non import instruction of the module, record it - if not self._first_non_import_node: - self._first_non_import_node = node + # If it is the first non import instruction of the module, record it. + if self._first_non_import_node: + return + + # Check if the node belongs to an `If` or a `Try` block. If they + # contain imports, skip recording this node. + if not isinstance(node.parent.scope(), astroid.Module): + return + + root = node + while not isinstance(root.parent, astroid.Module): + root = root.parent + + if isinstance(root, (astroid.If, astroid.TryFinally, astroid.TryExcept)): + if any(root.nodes_of_class((astroid.Import, astroid.ImportFrom))): + return + + self._first_non_import_node = node visit_classdef = visit_for = visit_while = visit_functiondef diff --git a/pylint/test/functional/wrong_import_position.py b/pylint/test/functional/wrong_import_position.py index 1547ff2..269d757 100644 --- a/pylint/test/functional/wrong_import_position.py +++ b/pylint/test/functional/wrong_import_position.py @@ -1,13 +1,25 @@ """Checks import order rule""" # pylint: disable=unused-import,relative-import,ungrouped-imports,wrong-import-order,using-constant-test -# pylint: disable=import-error +# pylint: disable=import-error, too-few-public-methods, missing-docstring import os.path + if True: from astroid import are_exclusive try: import sys except ImportError: - import datetime + class Myclass(object): + """docstring""" + +if sys.version_info[0] == 3: + from collections import OrderedDict +else: + class OrderedDict(object): + """Nothing to see here.""" + def some_func(self): + pass + +import six CONSTANT = True diff --git a/pylint/test/functional/wrong_import_position.txt b/pylint/test/functional/wrong_import_position.txt index 2f417e4..5cde17d 100644 --- a/pylint/test/functional/wrong_import_position.txt +++ b/pylint/test/functional/wrong_import_position.txt @@ -1,3 +1,3 @@ -wrong-import-position:14::Import "import datetime" should be placed at the top of the module -wrong-import-position:20::Import "import scipy" should be placed at the top of the module -wrong-import-position:21::Import "import astroid" should be placed at the top of the module +wrong-import-position:26::Import "import datetime" should be placed at the top of the module +wrong-import-position:32::Import "import scipy" should be placed at the top of the module +wrong-import-position:33::Import "import astroid" should be placed at the top of the module -- cgit v1.2.1