summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimothy Edmund Crosley <timothy.crosley@gmail.com>2019-02-16 18:17:36 -0800
committerGitHub <noreply@github.com>2019-02-16 18:17:36 -0800
commit880f6798ee1bb5ed81779217ce45f221f0e50c06 (patch)
tree13f358f45b7753f98568ca7a83521676978303e8
parentbf67c678c13f5052623a968764263e934551db62 (diff)
parent537712f40c1b1b6d49be08444c2cae50157db5ca (diff)
downloadisort-880f6798ee1bb5ed81779217ce45f221f0e50c06.tar.gz
Merge pull request #775 from mattbennett/nondeterministic-forced-separate
Maintain order when loading iterable values from config files
-rw-r--r--isort/settings.py7
-rw-r--r--isort/utils.py23
-rw-r--r--test_isort.py25
3 files changed, 52 insertions, 3 deletions
diff --git a/isort/settings.py b/isort/settings.py
index cb047158..8d6be959 100644
--- a/isort/settings.py
+++ b/isort/settings.py
@@ -35,6 +35,7 @@ from collections import namedtuple
from distutils.util import strtobool
from .pie_slice import lru_cache
+from .utils import difference, union
try:
import configparser
@@ -217,11 +218,11 @@ def _update_with_config_file(file_path, sections, computed_settings):
else:
existing_data = set(computed_settings.get(access_key, default.get(access_key)))
if key.startswith('not_'):
- computed_settings[access_key] = list(existing_data.difference(_as_list(value)))
+ computed_settings[access_key] = difference(existing_data, _as_list(value))
elif key.startswith('known_'):
- computed_settings[access_key] = list(existing_data.union(_abspaths(cwd, _as_list(value))))
+ computed_settings[access_key] = union(existing_data, _abspaths(cwd, _as_list(value)))
else:
- computed_settings[access_key] = list(existing_data.union(_as_list(value)))
+ computed_settings[access_key] = union(existing_data, _as_list(value))
elif existing_value_type == bool:
# Only some configuration formats support native boolean values.
if not isinstance(value, bool):
diff --git a/isort/utils.py b/isort/utils.py
index 9206c88e..ce4e588e 100644
--- a/isort/utils.py
+++ b/isort/utils.py
@@ -28,3 +28,26 @@ def chdir(path):
yield
finally:
os.chdir(curdir)
+
+
+def union(a, b):
+ """ Return a list of items that are in `a` or `b`
+ """
+ u = []
+ for item in a:
+ if item not in u:
+ u.append(item)
+ for item in b:
+ if item not in u:
+ u.append(item)
+ return u
+
+
+def difference(a, b):
+ """ Return a list of items from `a` that are not in `b`.
+ """
+ d = []
+ for item in a:
+ if item not in b:
+ d.append(item)
+ return d
diff --git a/test_isort.py b/test_isort.py
index ca826a5a..34d19569 100644
--- a/test_isort.py
+++ b/test_isort.py
@@ -2565,6 +2565,31 @@ def test_requirements_finder(tmpdir):
req_file.remove()
+def test_forced_separate_is_deterministic_issue_774(tmpdir):
+
+ config_file = tmpdir.join('setup.cfg')
+ config_file.write(
+ "[isort]\n"
+ "forced_separate:\n"
+ " separate1\n"
+ " separate2\n"
+ " separate3\n"
+ " separate4\n"
+ )
+
+ test_input = ('import time\n'
+ '\n'
+ 'from separate1 import foo\n'
+ '\n'
+ 'from separate2 import bar\n'
+ '\n'
+ 'from separate3 import baz\n'
+ '\n'
+ 'from separate4 import quux\n')
+
+ assert SortImports(file_contents=test_input, settings_path=config_file.strpath).output == test_input
+
+
PIPFILE = """
[[source]]
url = "https://pypi.org/simple"