Allow statements in if or try blocks containing imports.

Closes issue #714

authorLaura Médioni <laura.medioni@logilab.fr>
changeset083425ea56b0
branchdefault
phasepublic
hiddenno
parent revision#83afd8d7a075 Move the construction of generated_members into open.
child revision#6fbe83cee30d Merged in jakirkham/pylint/issue_538_pt2 (pull request #315)
files modified by this revision
ChangeLog
pylint/checkers/imports.py
pylint/test/functional/wrong_import_position.py
pylint/test/functional/wrong_import_position.txt
# HG changeset patch
# User Laura Médioni <laura.medioni@logilab.fr>
# Date 1449046700 -3600
# Wed Dec 02 09:58:20 2015 +0100
# Node ID 083425ea56b0f1cce1af00630d9b1e4714d43f0d
# Parent 83afd8d7a075ef7efb3930e79b4ffd645dae803f
Allow statements in if or try blocks containing imports.

Closes issue #714

diff --git a/ChangeLog b/ChangeLog
@@ -14,10 +14,14 @@
1       .qname() method after the inference.
2 
3      * Don't emit super-on-old-class on classes with unknown bases.
4        Closes issue #721.
5 
6 +    * Allow statements in `if` or `try` blocks containing imports.
7 +
8 +      Closes issue #714. 
9 +
10      * Added a new warning, 'unsupported-assignment-operation', which is
11        emitted when item assignment is tried on an object which doesn't
12        have this ability. Closes issue #591.
13 
14      * Added a new warning, 'unsupported-delete-operation', which is
diff --git a/pylint/checkers/imports.py b/pylint/checkers/imports.py
@@ -379,13 +379,28 @@
15 
16      visit_tryfinally = visit_tryexcept = visit_assignattr = visit_assign \
17              = visit_ifexp = visit_comprehension = visit_if
18 
19      def visit_functiondef(self, node):
20 -        # if it is the first non import instruction of the module, record it
21 -        if not self._first_non_import_node:
22 -            self._first_non_import_node = node
23 +        # If it is the first non import instruction of the module, record it.
24 +        if self._first_non_import_node:
25 +            return
26 +
27 +        # Check if the node belongs to an `If` or a `Try` block. If they
28 +        # contain imports, skip recording this node.
29 +        if not isinstance(node.parent.scope(), astroid.Module):
30 +            return
31 +
32 +        root = node
33 +        while not isinstance(root.parent, astroid.Module):
34 +            root = root.parent
35 +
36 +        if isinstance(root, (astroid.If, astroid.TryFinally, astroid.TryExcept)):
37 +            if any(root.nodes_of_class((astroid.Import, astroid.ImportFrom))):
38 +                return
39 +
40 +        self._first_non_import_node = node
41 
42      visit_classdef = visit_for = visit_while = visit_functiondef
43 
44      def _check_misplaced_future(self, node):
45          basename = node.modname
diff --git a/pylint/test/functional/wrong_import_position.py b/pylint/test/functional/wrong_import_position.py
@@ -1,15 +1,27 @@
46  """Checks import order rule"""
47  # pylint: disable=unused-import,relative-import,ungrouped-imports,wrong-import-order,using-constant-test
48 -# pylint: disable=import-error
49 +# pylint: disable=import-error, too-few-public-methods, missing-docstring
50  import os.path
51 +
52  if True:
53      from astroid import are_exclusive
54  try:
55      import sys
56  except ImportError:
57 -    import datetime
58 +    class Myclass(object):
59 +        """docstring"""
60 +
61 +if sys.version_info[0] == 3:
62 +    from collections import OrderedDict
63 +else:
64 +    class OrderedDict(object):
65 +        """Nothing to see here."""
66 +        def some_func(self):
67 +            pass
68 +
69 +import six
70 
71  CONSTANT = True
72 
73  import datetime  # [wrong-import-position]
74 
diff --git a/pylint/test/functional/wrong_import_position.txt b/pylint/test/functional/wrong_import_position.txt
@@ -1,3 +1,3 @@
75 -wrong-import-position:14::Import "import datetime" should be placed at the top of the module
76 -wrong-import-position:20::Import "import scipy" should be placed at the top of the module
77 -wrong-import-position:21::Import "import astroid" should be placed at the top of the module
78 +wrong-import-position:26::Import "import datetime" should be placed at the top of the module
79 +wrong-import-position:32::Import "import scipy" should be placed at the top of the module
80 +wrong-import-position:33::Import "import astroid" should be placed at the top of the module