diff options
author | Timothy Crosley <timothy.crosley@gmail.com> | 2020-07-14 22:16:40 -0700 |
---|---|---|
committer | Timothy Crosley <timothy.crosley@gmail.com> | 2020-07-14 22:16:40 -0700 |
commit | 36d4cc056570bc83b0c457491dbca5e4c4f45ea3 (patch) | |
tree | edd1a4297635bbeadb3d795cfd215f0c7ae6b740 | |
parent | 413f8a0f8c1cba07b2a174fdd03c8bf279198d3b (diff) | |
download | isort-36d4cc056570bc83b0c457491dbca5e4c4f45ea3.tar.gz |
- Implemented experimental support for floating all imports to the top of a file (issue #1228)
-rw-r--r-- | CHANGELOG.md | 1 | ||||
-rw-r--r-- | docs/configuration/options.md | 26 | ||||
-rw-r--r-- | isort/api.py | 30 | ||||
-rw-r--r-- | isort/main.py | 11 | ||||
-rw-r--r-- | isort/settings.py | 1 | ||||
-rw-r--r-- | tests/test_ticketed_features.py | 117 |
6 files changed, 172 insertions, 14 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 21f1b725..6ce6172d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ NOTE: isort follows the [semver](https://semver.org/) versioning standard. ### 5.1.0 July TBD, 2020 - isort now throws an exception if an invalid settings path is given (issue #1174). - Implemented support for automatic redundant alias removal (issue #1281). + - Implemented experimental support for floating all imports to the top of a file (issue #1228) - Fixed #1178: support for semicolons in decorators. - Fixed #1315: Extra newline before comment with -n + --fss. - Fixed #1192: `-k` or `--keep-direct-and-as-imports` option has been deprecated as it is now always on. diff --git a/docs/configuration/options.md b/docs/configuration/options.md index 86ad6da4..fecc8347 100644 --- a/docs/configuration/options.md +++ b/docs/configuration/options.md @@ -468,18 +468,6 @@ Ensures that if a star import is present, nothing else is imported from that nam - --cs - --combine-star -## Keep Direct And As Imports - -Turns off default behavior that removes direct imports when as imports exist. - -**Type:** Bool -**Default:** `True` -**Python & Config File Name:** keep_direct_and_as_imports -**CLI Flags:** - -- -k -- --keep-direct-and-as - ## Include Trailing Comma Includes a trailing comma on multi line imports that include parentheses. @@ -762,6 +750,17 @@ Tells isort to remove redundant aliases from imports, such as `import os as os`. - --remove-redundant-aliases +## Float To Top + +Causes all non indented imports to float to the top of the file having its imports sorted. *NOTE*: This is a **beta** feature. It currently doesn't work with cimports and is gauranteed to run much slower and use much more memory than the default. Still it can be a great shortcut for collecting imports every once in a while when you put them in the middle of a file. + +**Type:** Bool +**Default:** `False` +**Python & Config File Name:** float_to_top +**CLI Flags:** + +- --float-to-top + ## Check Checks the file for unsorted / unformatted imports and prints them to the command line without modifying the file. @@ -923,4 +922,5 @@ See isort's determined config, as well as sources of config options. **Python & Config File Name:** **Not Supported** **CLI Flags:** -- --apply +- -k +- --keep-direct-and-as diff --git a/isort/api.py b/isort/api.py index 3aa25dc0..6f7230ed 100644 --- a/isort/api.py +++ b/isort/api.py @@ -386,6 +386,36 @@ def _sort_imports( cimports: bool = False made_changes: bool = False + if config.float_to_top: + new_input = "" + current = "" + isort_off = False + for line in chain(input_stream, (None,)): + if isort_off and line is not None: + if line == "# isort: on\n": + isort_off = False + new_input += line + elif line in ("# isort: split\n", "# isort: off\n", None): + if line == "# isort: off\n": + isort_off = True + if current: + parsed = parse.file_contents(current, config=config) + extra_space = "" + while current[-1] == "\n": + extra_space += "\n" + current = current[:-1] + extra_space = extra_space.replace("\n", "", 1) + new_input += output.sorted_imports( + parsed, config, extension, import_type="import" + ) + new_input += extra_space + current = "" + new_input += line or "" + else: + current += line or "" + + input_stream = StringIO(new_input) + for index, line in enumerate(chain(input_stream, (None,))): if line is None: if index == 0 and not config.force_adds: diff --git a/isort/main.py b/isort/main.py index 589db60f..48da508a 100644 --- a/isort/main.py +++ b/isort/main.py @@ -588,7 +588,16 @@ def _build_arg_parser() -> argparse.ArgumentParser: " aliases to signify intent and change behaviour." ), ) - + parser.add_argument( + "--float-to-top", + dest="float_to_top", + action="store_true", + help="Causes all non indented imports to float to the top of the file having its imports " + "sorted. *NOTE*: This is a **beta** feature. It currently doesn't work with cimports and " + "is gauranteed to run much slower and use much more memory than the default. Still it " + "can be a great shortcut for collecting imports every once in a while when you put them " + "in the middle of a file.", + ) # deprecated options parser.add_argument( "--recursive", diff --git a/isort/settings.py b/isort/settings.py index 437cca59..68f32a66 100644 --- a/isort/settings.py +++ b/isort/settings.py @@ -166,6 +166,7 @@ class _Config: src_paths: FrozenSet[Path] = frozenset() old_finders: bool = False remove_redundant_aliases: bool = False + float_to_top: bool = False def __post_init__(self): py_version = self.py_version diff --git a/tests/test_ticketed_features.py b/tests/test_ticketed_features.py index 2709a769..4e958781 100644 --- a/tests/test_ticketed_features.py +++ b/tests/test_ticketed_features.py @@ -32,3 +32,120 @@ def test_isort_automatically_removes_duplicate_aliases_issue_1193(): ) assert isort.check_code("import os as os\n", show_diff=True) assert isort.code("import os as os", remove_redundant_aliases=True) == "import os\n" + + +def test_isort_enables_floating_imports_to_top_of_module_issue_1228(): + """Test to ensure isort will allow floating all non-indented imports to the top of a file. + See: https://github.com/timothycrosley/isort/issues/1228. + """ + assert ( + isort.code( + """ +import os + + +def my_function_1(): + pass + +import sys + +def my_function_2(): + pass +""", + float_to_top=True, + ) + == """ +import os +import sys + + +def my_function_1(): + pass + + +def my_function_2(): + pass +""" + ) + + assert ( + isort.code( + """ +import os + + +def my_function_1(): + pass + +# isort: split +import sys + +def my_function_2(): + pass +""", + float_to_top=True, + ) + == """ +import os + + +def my_function_1(): + pass + +# isort: split +import sys + + +def my_function_2(): + pass +""" + ) + + +assert ( + isort.code( + """ +import os + + +def my_function_1(): + pass + +# isort: off +import b +import a +def y(): + pass + +# isort: on +import b + +def my_function_2(): + pass + +import a +""", + float_to_top=True, + ) + == """ +import os + + +def my_function_1(): + pass + +# isort: off +import b +import a +def y(): + pass + +# isort: on +import a +import b + + +def my_function_2(): + pass +""" +) |