summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimothy Edmund Crosley <timothy.crosley@gmail.com>2019-02-15 19:30:10 -0800
committerGitHub <noreply@github.com>2019-02-15 19:30:10 -0800
commitd075644528d171d63dd8789ab1fa21a5ab7da685 (patch)
tree1a9b4097657b5c8e245bad990726bf29c791d937
parent8d3e0653117431e062d64d5f3c9ab3022d061f3e (diff)
parent9582a8e3d06080f8c227e31fc12eb7f1d9fb5b82 (diff)
downloadisort-d075644528d171d63dd8789ab1fa21a5ab7da685.tar.gz
Merge branch 'develop' into test-coverage-improvements
-rw-r--r--isort/main.py5
-rw-r--r--isort/settings.py16
-rw-r--r--test_isort.py19
3 files changed, 37 insertions, 3 deletions
diff --git a/isort/main.py b/isort/main.py
index b95a2999..a584c226 100644
--- a/isort/main.py
+++ b/isort/main.py
@@ -284,11 +284,16 @@ def parse_args(argv=None):
help='Tells isort to ignore whitespace differences when --check-only is being used.')
parser.add_argument('-y', '--apply', dest='apply', action='store_true',
help='Tells isort to apply changes recursively without asking')
+ parser.add_argument('--unsafe', dest='unsafe', action='store_true',
+ help='Tells isort to look for files in standard library directories, etc. '
+ 'where it may not be safe to operate in')
parser.add_argument('files', nargs='*', help='One or more Python source files that need their imports sorted.')
arguments = {key: value for key, value in vars(parser.parse_args(argv)).items() if value}
if 'dont_order_by_type' in arguments:
arguments['order_by_type'] = False
+ if arguments.pop('unsafe', False):
+ arguments['safety_excludes'] = False
return arguments
diff --git a/isort/settings.py b/isort/settings.py
index 79ae6c4c..cb047158 100644
--- a/isort/settings.py
+++ b/isort/settings.py
@@ -27,6 +27,7 @@ from __future__ import absolute_import, division, print_function, unicode_litera
import fnmatch
import io
import os
+import re
import posixpath
import sys
import warnings
@@ -48,6 +49,10 @@ except ImportError:
MAX_CONFIG_SEARCH_DEPTH = 25 # The number of parent directories isort will look for a config file within
DEFAULT_SECTIONS = ('FUTURE', 'STDLIB', 'THIRDPARTY', 'FIRSTPARTY', 'LOCALFOLDER')
+safety_exclude_re = re.compile(
+ r"/(\.eggs|\.git|\.hg|\.mypy_cache|\.nox|\.tox|\.venv|_build|buck-out|build|dist|lib/python[0-9].[0-9]+)/"
+)
+
WrapModes = ('GRID', 'VERTICAL', 'HANGING_INDENT', 'VERTICAL_HANGING_INDENT', 'VERTICAL_GRID', 'VERTICAL_GRID_GROUPED',
'VERTICAL_GRID_GROUPED_NO_COMMA', 'NOQA')
WrapModes = namedtuple('WrapModes', WrapModes)(*range(len(WrapModes)))
@@ -145,7 +150,9 @@ default = {'force_to_top': [],
'show_diff': False,
'ignore_whitespace': False,
'no_lines_before': [],
- 'no_inline_sort': False}
+ 'no_inline_sort': False,
+ 'safety_excludes': True,
+ }
@lru_cache()
@@ -292,8 +299,13 @@ def _get_config_data(file_path, sections):
def should_skip(filename, config, path='/'):
"""Returns True if the file should be skipped based on the passed in settings."""
+ normalized_path = posixpath.join(path.replace('\\', '/'), filename)
+
+ if config['safety_excludes'] and safety_exclude_re.search(normalized_path):
+ return True
+
for skip_path in config['skip']:
- if posixpath.abspath(posixpath.join(path.replace('\\', '/'), filename)) == posixpath.abspath(skip_path.replace('\\', '/')):
+ if posixpath.abspath(normalized_path) == posixpath.abspath(skip_path.replace('\\', '/')):
return True
position = os.path.split(filename)
diff --git a/test_isort.py b/test_isort.py
index 302abfc9..c0ddff7f 100644
--- a/test_isort.py
+++ b/test_isort.py
@@ -25,11 +25,12 @@ from __future__ import absolute_import, division, print_function, unicode_litera
from tempfile import NamedTemporaryFile
import io
+import os
import sys
import pytest
-from isort import finders
+from isort import finders, main, settings
from isort.isort import SortImports
from isort.utils import exists_case_sensitive
from isort.main import is_python_file
@@ -2623,3 +2624,19 @@ def test_command_line(tmpdir, capfd, multiprocess):
# it informs us about fixing the files:
assert str(tmpdir.join("file1.py")) in out
assert str(tmpdir.join("file2.py")) in out
+
+
+@pytest.mark.parametrize('enabled', (False, True))
+def test_safety_excludes(tmpdir, enabled):
+ tmpdir.join("victim.py").write("# ...")
+ tmpdir.mkdir(".tox").join("verysafe.py").write("# ...")
+ tmpdir.mkdir("lib").mkdir("python3.7").join("importantsystemlibrary.py").write("# ...")
+ config = dict(settings.default.copy(), safety_excludes=enabled)
+ skipped = []
+ file_names = set(os.path.relpath(f, str(tmpdir)) for f in main.iter_source_code([str(tmpdir)], config, skipped))
+ if enabled:
+ assert file_names == {'victim.py'}
+ assert len(skipped) == 2
+ else:
+ assert file_names == {'.tox/verysafe.py', 'lib/python3.7/importantsystemlibrary.py', 'victim.py'}
+ assert not skipped