summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Baty <damien.baty@polyconseil.fr>2020-07-05 23:06:04 +0200
committerPierre Sassoulas <pierre.sassoulas@gmail.com>2020-08-18 09:12:33 +0200
commit9bc9bdf533213ba967b5199aa9f3246f08f8999c (patch)
treeed2ae7b060b5af1f051af393c7a6f1e9f4c500e7
parent707fc4603b9d505bda68cf6adf9805882b99d73c (diff)
downloadpylint-git-9bc9bdf533213ba967b5199aa9f3246f08f8999c.tar.gz
Support both isort 4 and isort 5
The API of isort 5 (released on 2020-07-04) is completely different. We must still support isort 4 because isort 5 dropped the compatibility with Python 3.5, which pylint still supports. Note about the `known-standard-library` option: it has been included in pylint for years. Until now, it was mapped with the option of the same name in isort. However, isort 5 has changed the meaning of this option (see https://timothycrosley.github.io/isort/docs/upgrade_guides/5.0.0/#known_standard_library). Most users of pylint want the meaning of the new `extra-standard-library` option. To avoid a breaking change in pylint, the `known-standard-library` pylint option is now mapped to `known-standard-library` in isort 4, and `extra-standard-library` in isort 5. Users that really want the _new_ meaning of `known-standard-library` in isort 4 must disable the `wrong-import-order` check in pylint and run isort manually, outside of pylint. Fix #3722.
-rw-r--r--ChangeLog4
-rw-r--r--doc/whatsnew/2.6.rst4
-rw-r--r--man/pylint.12
-rw-r--r--pylint/__pkginfo__.py2
-rw-r--r--pylint/checkers/imports.py11
-rw-r--r--pylint/utils/__init__.py2
-rw-r--r--pylint/utils/utils.py35
-rw-r--r--tests/functional/w/wrong_import_order.txt6
-rw-r--r--tests/test_functional.py5
-rw-r--r--tox.ini4
10 files changed, 61 insertions, 14 deletions
diff --git a/ChangeLog b/ChangeLog
index 197255275..6c509fa06 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -47,6 +47,10 @@ Release date: TBA
* Add `raise-missing-from` check for exceptions that should have a cause.
+* Support both isort 4 and isort 5. If you have pinned isort 4 in your projet requirements, nothing changes. If you use isort 5, though, note that the `known-standard-library` option is not interpreted the same in isort 4 and isort 5 (see the migration guide in isort documentation for further details). For compatibility's sake for most pylint users, the `known-standard-library` option in pylint now maps to `extra-standard-library` in isort 5. If you really want what `known-standard-library` now means in isort 5, you must disable the `wrong-import-order` check in pylint and run isort manually with a proper isort configuration file.
+
+ Close #3722
+
What's New in Pylint 2.5.4?
===========================
diff --git a/doc/whatsnew/2.6.rst b/doc/whatsnew/2.6.rst
index 4da6f6122..e954199e7 100644
--- a/doc/whatsnew/2.6.rst
+++ b/doc/whatsnew/2.6.rst
@@ -27,3 +27,7 @@ Other Changes
* `mixed-indentation` has been removed, it is no longer useful since TabError is included directly in python3
* Fix superfluous-parens false-positive for the walrus operator
+
+* Add support for both isort 4 and isort 5. If you have pinned isort 4 in your projet requirements, nothing changes. If you use isort 5, though, note that the `known-standard-library` option is not interpreted the same in isort 4 and isort 5 (see `the migration guide in isort documentation`_ for further details). For compatibility's sake for most pylint users, the `known-standard-library` option in pylint now maps to `extra-standard-library` in isort 5. If you really want what `known-standard-library` now means in isort 5, you must disable the `wrong-import-order` check in pylint and run isort manually with a proper isort configuration file.
+
+.. _the migration guide in isort documentation: https://timothycrosley.github.io/isort/docs/upgrade_guides/5.0.0/#known_standard_library
diff --git a/man/pylint.1 b/man/pylint.1
index 7e0e4e94c..b08a0be78 100644
--- a/man/pylint.1
+++ b/man/pylint.1
@@ -209,7 +209,7 @@ Create a graph of external dependencies in the given file (report RP0402 must no
.IP "--int-import-graph=<file.dot>"
Create a graph of internal dependencies in the given file (report RP0402 must not be disabled). [default: none]
.IP "--known-standard-library=<modules>"
-Force import order to recognize a module as part of the standard compatibility libraries. [default: none]
+Force import order to recognize a module as part of the standard compatibility libraries.
.IP "--known-third-party=<modules>"
Force import order to recognize a module as part of a third party library. [default: enchant]
.IP "--allow-any-import-level=<modules>"
diff --git a/pylint/__pkginfo__.py b/pylint/__pkginfo__.py
index f6660504f..fc3d79ebd 100644
--- a/pylint/__pkginfo__.py
+++ b/pylint/__pkginfo__.py
@@ -38,7 +38,7 @@ if dev_version is not None:
install_requires = [
"astroid>=2.4.0,<=2.5",
- "isort>=4.2.5,<5",
+ "isort>=4.2.5,<6",
"mccabe>=0.6,<0.7",
"toml>=0.7.1",
]
diff --git a/pylint/checkers/imports.py b/pylint/checkers/imports.py
index 713e56412..032c855c2 100644
--- a/pylint/checkers/imports.py
+++ b/pylint/checkers/imports.py
@@ -46,7 +46,6 @@ import sys
from distutils import sysconfig
import astroid
-import isort
from astroid import modutils
from astroid.decorators import cached
@@ -60,7 +59,7 @@ from pylint.exceptions import EmptyReportError
from pylint.graph import DotBackend, get_cycles
from pylint.interfaces import IAstroidChecker
from pylint.reporters.ureports.nodes import Paragraph, VerbatimText
-from pylint.utils import get_global_option
+from pylint.utils import IsortDriver, get_global_option
def _qualified_names(modname):
@@ -709,11 +708,7 @@ class ImportsChecker(BaseChecker):
third_party_not_ignored = []
first_party_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,
- )
+ isort_driver = IsortDriver(self.config)
for node, modname in self._imports_stack:
if modname.startswith("."):
package = "." + modname.split(".")[1]
@@ -723,7 +718,7 @@ class ImportsChecker(BaseChecker):
ignore_for_import_order = not self.linter.is_message_enabled(
"wrong-import-order", node.fromlineno
)
- import_category = isort_obj.place_module(package)
+ import_category = isort_driver.place_module(package)
node_and_package_import = (node, package)
if import_category in ("FUTURE", "STDLIB"):
std_imports.append(node_and_package_import)
diff --git a/pylint/utils/__init__.py b/pylint/utils/__init__.py
index beef10d15..e03938387 100644
--- a/pylint/utils/__init__.py
+++ b/pylint/utils/__init__.py
@@ -46,6 +46,8 @@ main pylint class
from pylint.utils.ast_walker import ASTWalker
from pylint.utils.file_state import FileState
from pylint.utils.utils import (
+ HAS_ISORT_5,
+ IsortDriver,
_basename_in_blacklist_re,
_check_csv,
_format_option_value,
diff --git a/pylint/utils/utils.py b/pylint/utils/utils.py
index 21dd8d251..d7f1bf052 100644
--- a/pylint/utils/utils.py
+++ b/pylint/utils/utils.py
@@ -1,6 +1,15 @@
# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
# For details: https://github.com/PyCQA/pylint/blob/master/COPYING
+try:
+ import isort.api
+
+ HAS_ISORT_5 = True
+except ImportError: # isort < 5
+ import isort
+
+ HAS_ISORT_5 = False
+
import codecs
import os
import re
@@ -398,3 +407,29 @@ def _ini_format(stream, options):
# remove trailing ',' from last element of the list
value = value[:-1]
print("%s=%s" % (optname, value), file=stream)
+
+
+class IsortDriver:
+ """A wrapper around isort API that changed between versions 4 and 5."""
+
+ def __init__(self, config):
+ if HAS_ISORT_5:
+ self.isort5_config = isort.api.Config(
+ # There is not typo here. EXTRA_standard_library is
+ # what most users want. The option has been named
+ # KNOWN_standard_library for ages in pylint and we
+ # don't want to break compatibility.
+ extra_standard_library=config.known_standard_library,
+ known_third_party=config.known_third_party,
+ )
+ else:
+ self.isort4_obj = isort.SortImports( # pylint: disable=no-member
+ file_contents="",
+ known_standard_library=config.known_standard_library,
+ known_third_party=config.known_third_party,
+ )
+
+ def place_module(self, package):
+ if HAS_ISORT_5:
+ return isort.api.place_module(package, self.isort5_config)
+ return self.isort4_obj.place_module(package)
diff --git a/tests/functional/w/wrong_import_order.txt b/tests/functional/w/wrong_import_order.txt
index 13b601eb5..46fe2b65e 100644
--- a/tests/functional/w/wrong_import_order.txt
+++ b/tests/functional/w/wrong_import_order.txt
@@ -1,6 +1,6 @@
wrong-import-order:12::standard import "import os.path" should be placed before "import six"
wrong-import-order:14::standard import "import sys" should be placed before "import six"
wrong-import-order:15::standard import "import datetime" should be placed before "import six"
-wrong-import-order:18::first party import "import totally_missing" should be placed before "from .package import Class"
-wrong-import-order:20::third party import "import astroid" should be placed before "import unused_import"
-wrong-import-order:24::third party import "from six.moves.urllib.parse import quote" should be placed before "import unused_import"
+wrong-import-order:18::third party import "import totally_missing" should be placed before "from .package import Class"
+wrong-import-order:20::third party import "import astroid" should be placed before "from .package import Class"
+wrong-import-order:24::third party import "from six.moves.urllib.parse import quote" should be placed before "from .package import Class"
diff --git a/tests/test_functional.py b/tests/test_functional.py
index e7eacf4a6..f31221772 100644
--- a/tests/test_functional.py
+++ b/tests/test_functional.py
@@ -28,6 +28,7 @@ import sys
import pytest
from pylint import testutils
+from pylint.utils import HAS_ISORT_5
class test_dialect(csv.excel):
@@ -77,6 +78,10 @@ def get_tests():
continue
for filename in filenames:
if filename != "__init__.py" and filename.endswith(".py"):
+ # isort 5 has slightly different rules as isort 4. Testing
+ # both would be hard: test with isort 5 only.
+ if filename == "wrong_import_order.py" and not HAS_ISORT_5:
+ continue
suite.append(testutils.FunctionalTestFile(dirpath, filename))
return suite
diff --git a/tox.ini b/tox.ini
index b44a200e3..31b8091ea 100644
--- a/tox.ini
+++ b/tox.ini
@@ -37,7 +37,7 @@ commands =
basepython = python3
deps =
black==19.10b0
- isort==4.3.21
+ isort==5.4.2
commands =
black --check . --exclude="tests/functional/|tests/input|tests/extensions/data|tests/regrtest_data/|tests/data/|venv|astroid|.tox"
isort -rc . --check-only
@@ -58,6 +58,8 @@ deps =
coverage<5.0
isort
mccabe
+ # isort 5 is not compatible with Python 3.5
+ py35: isort>=4.2.5,<5
pytest
pytest-xdist
pytest-benchmark