Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ What's New in Pylint 2.0?

Release date: tba

* Disabling 'wrong-import-order', 'wrong-import-position', or
'ungrouped-imports' for a single line now prevents that line from
triggering violations on subsequent lines.

Close #1336

* Added a new error, 'used-prior-global-declaration', which is emitted when a name
is used prior a global declaration in a function. This causes a SyntaxError in
Python 3.6
Expand Down
24 changes: 16 additions & 8 deletions pylint/checkers/imports.py
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,8 @@ def leave_module(self, node):
met = set()
current_package = None
for import_node, import_name in std_imports + ext_imports + loc_imports:
if not self.linter.is_message_enabled('ungrouped-imports', import_node.fromlineno):
continue
package, _, _ = import_name.partition('.')
if current_package and current_package != package and package in met:
self.add_message('ungrouped-imports', node=import_node,
Expand All @@ -436,6 +438,8 @@ def leave_module(self, node):
self._first_non_import_node = None

def compute_first_non_import_node(self, node):
if not self.linter.is_message_enabled('wrong-import-position', node.fromlineno):
return
# if the node does not contain an import instruction, and if it is the
# first node of the module, keep a track of it (all the import positions
# of the module will be compared to the position of this first
Expand Down Expand Up @@ -466,6 +470,8 @@ def compute_first_non_import_node(self, node):
compute_first_non_import_node

def visit_functiondef(self, node):
if not self.linter.is_message_enabled('wrong-import-position', node.fromlineno):
return
# If it is the first non import instruction of the module, record it.
if self._first_non_import_node:
return
Expand Down Expand Up @@ -552,8 +558,8 @@ def _check_imports_order(self, _module_node):
extern_imports = []
local_imports = []
std_imports = []
extern_not_nested = []
local_not_nested = []
extern_not_ignored = []
local_not_ignored = []
isort_obj = isort.SortImports(
file_contents='', known_third_party=self.config.known_third_party,
known_standard_library=self.config.known_standard_library,
Expand All @@ -564,10 +570,12 @@ def _check_imports_order(self, _module_node):
else:
package = modname.split('.')[0]
nested = not isinstance(node.parent, astroid.Module)
ignore_for_import_order = not self.linter.is_message_enabled('wrong-import-order',
node.fromlineno)
import_category = isort_obj.place_module(package)
if import_category in ('FUTURE', 'STDLIB'):
std_imports.append((node, package))
wrong_import = extern_not_nested or local_not_nested
wrong_import = extern_not_ignored or local_not_ignored
if self._is_fallback_import(node, wrong_import):
continue
if wrong_import and not nested:
Expand All @@ -576,17 +584,17 @@ def _check_imports_order(self, _module_node):
'"%s"' % wrong_import[0][0].as_string()))
elif import_category in ('FIRSTPARTY', 'THIRDPARTY'):
extern_imports.append((node, package))
if not nested:
extern_not_nested.append((node, package))
wrong_import = local_not_nested
if not nested and not ignore_for_import_order:
extern_not_ignored.append((node, package))
wrong_import = local_not_ignored
if wrong_import and not nested:
self.add_message('wrong-import-order', node=node,
args=('external import "%s"' % node.as_string(),
'"%s"' % wrong_import[0][0].as_string()))
elif import_category == 'LOCALFOLDER':
local_imports.append((node, package))
if not nested:
local_not_nested.append((node, package))
if not nested and not ignore_for_import_order:
local_not_ignored.append((node, package))
return std_imports, extern_imports, local_imports

def _get_imported_module(self, importnode, modname):
Expand Down
10 changes: 10 additions & 0 deletions pylint/test/functional/disable_ungrouped_imports.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
"""Checks that disabling 'ungrouped-imports' on an import prevents subsequent
imports from being considered ungrouped in respect to it."""
# pylint: disable=unused-import,relative-import,wrong-import-position,wrong-import-order,using-constant-test
# pylint: disable=import-error
import os
import logging.config # pylint: disable=ungrouped-imports
import os.path
import logging
from os.path import join # [ungrouped-imports]
import logging.handlers # [ungrouped-imports]
2 changes: 2 additions & 0 deletions pylint/test/functional/disable_ungrouped_imports.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ungrouped-imports:9::Imports from package os are not grouped
ungrouped-imports:10::Imports from package logging are not grouped
11 changes: 11 additions & 0 deletions pylint/test/functional/disable_wrong_import_order.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
"""Checks that disabling 'wrong-import-order' on an import prevents subsequent
imports from being considered out-of-order in respect to it but does not prevent
it from being considered for 'ungrouped-imports'."""
# pylint: disable=unused-import,import-error,no-name-in-module

from first_party.foo import bar # pylint: disable=wrong-import-order
import logging
import os.path
import sys
from astroid import are_exclusive
import first_party # [ungrouped-imports]
1 change: 1 addition & 0 deletions pylint/test/functional/disable_wrong_import_order.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ungrouped-imports:11::Imports from package first_party are not grouped
7 changes: 7 additions & 0 deletions pylint/test/functional/disable_wrong_import_position.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
"""Checks that disabling 'wrong-import-position' on a statement prevents it from
invalidating subsequent imports."""
# pylint: disable=unused-import

CONSTANT = True # pylint: disable=wrong-import-position

import sys