diff --git a/bears/python/PyImportSortBear.py b/bears/python/PyImportSortBear.py index 158543a371..6903996a34 100644 --- a/bears/python/PyImportSortBear.py +++ b/bears/python/PyImportSortBear.py @@ -4,21 +4,42 @@ from coalib.bears.LocalBear import LocalBear from coalib.results.Diff import Diff from coalib.results.Result import Result +from coalib.settings.Setting import typed_list class PyImportSortBear(LocalBear): LANGUAGES = ("Python",) - def run(self, - filename, - file, + def run(self, filename, file, + use_parentheses_in_import: bool=True, + force_alphabetical_sort_in_import: bool=False, + force_sort_within_import_sections: bool=True, + from_first_in_import: bool=False, + include_trailing_comma_in_import: bool=False, + combine_star_imports: bool=True, + combine_as_imports: bool=True, + lines_after_imports: int=-1, + order_imports_by_type: bool=False, + balanced_wrapping_in_imports: bool=False, + import_heading_localfolder: str="", + import_heading_firstparty: str="", + import_heading_thirdparty: str="", + import_heading_stdlib: str="", + import_heading_future: str="", + default_import_section: str="FIRSTPARTY", + force_grid_wrap_imports: bool=False, + force_single_line_imports: bool=True, + sort_imports_by_length: bool=False, use_spaces: bool=True, tab_width: int=SpacingHelper.DEFAULT_TAB_WIDTH, + forced_separate_imports: typed_list(str)=(), + isort_multi_line_output: int=4, + known_first_party_imports: typed_list(str)=(), + known_third_party_imports: typed_list(str)=(), + known_standard_library_imports: typed_list(str)=None, max_line_length: int=80, - use_parentheses_in_import: bool=True, - sort_imports_by_length: bool=False, - isort_multi_line_output: int=4): + imports_forced_to_top: typed_list(str)=()): """ Handle imports for python using the utility ``isort``. It can sort the imports, segregate it into various sections, and also add comments @@ -27,28 +48,129 @@ def run(self, You can read more about ``isort`` at . + :param use_parentheses_in_import: + True if parenthesis are to be used in import statements. + :param force_alphabetical_sort_in_import: + If set, forces all imports to be sorted as a single section, + instead of within other groups (such as straight vs from). + :param force_sort_within_import_sections: + If set, imports will be sorted within there section independent + to the import_type. + :param from_first_in_import: + If set, imports using "from" will be displayed above normal + (straight) imports. + :param include_trailing_comma_in_import: + If set, will automatically add a trailing comma to the end of + "from" imports. Example: ``from abc import (a, b, c,)`` + :param combine_star_imports: + If set to true - ensures that if a star import is present, + nothing else is imported from that namespace. + :param combine_as_imports: + If set to true - isort will combine as imports on the same line + within for import statements. + :param lines_after_imports: + Forces a certain number of lines after the imports and before the + first line of functional code. By default this is set to -1 which + uses 2 lines if the first line of code is a class or function and + 1 line if it's anything else. + :param order_imports_by_type: + If set to true - isort will create separate sections within "from" + imports for CONSTANTS, Classes, and modules/functions. + :param balanced_wrapping_in_imports: + If set to true - for each multi-line import statement isort will + dynamically change the import length to the one that produces + the most balanced grid, while staying below the maximum import + length defined. + :param import_heading_localfolder: + A comment to consistently place directly above imports that + start with '.'. + :param import_heading_firstparty: + A comment to consistently place directly above imports from + the current project. + :param import_heading_thirdparty: + A comment to consistently place directly above thirdparty imports. + :param import_heading_stdlib: + A comment to consistently place directly above imports from + the standard library. + :param import_heading_future: + A comment to consistently place directly above future imports. + :param default_import_section: + The default section to place imports in, if their section can + not be automatically determined. + :param force_grid_wrap_imports: + Force "from" imports to be grid wrapped regardless of line length. + :param force_single_line_imports: + If set to true - instead of wrapping multi-line from style imports, + each import will be forced to display on its own line. + :param sort_imports_by_length: + Set to true to sort imports by length instead of alphabetically. :param use_spaces: True if spaces are to be used instead of tabs. :param tab_width: Number of spaces per indent level. + :param forced_separate_imports: + A list of modules that you want to appear in their own separate + section. + :param isort_multi_line_output: + An integer that represents how you want imports to be displayed + by ``isort`` if they're long enough to span multiple lines. + This value is passed to isort as the ``multi_line_output`` setting. + Possible values are (0-grid, 1-vertical, 2-hanging, 3-vert-hanging, + 4-vert-grid, 5-vert-grid-grouped) + A full definition of all possible modes can be found at + . + :param known_first_party_imports: + A list of imports that will be forced to display within the + standard library category of imports. + :param known_third_party_imports: + A list of imports that will be forced to display within the + third party category of imports. + :param known_standard_library_imports: + A list of imports that will be forced to display within the + first party category of imports. + :param import_wrap_length: + An integer that represents the longest line-length you want when + wrapping. If not set will default to line_length. + :param imports_forced_to_top: + Forces a list of imports to the top of their respective section. + This works well for handling the unfortunate cases of import + dependencies that occur in many projects. :param max_line_length: Maximum number of characters for a line. - :param use_parentheses_in_import: - True if parenthesis are to be used in import statements. - :param sort_imports_by_length: - Set to true to sort imports by length instead of alphabetically. - :param isort_multi_line_output: - The type of formatting to be used by isort when indenting imports. - This value if passed to isort as the `multi_line_output` setting. """ - indent = "Tab" if use_spaces == False else tab_width - new_file = tuple(SortImports( - file_contents=''.join(file), - line_length=max_line_length, - indent=indent, - multi_line_output=isort_multi_line_output, + isort_settings = dict( use_parentheses=use_parentheses_in_import, - length_sort=sort_imports_by_length).output.splitlines(True)) + force_alphabetical_sort=force_alphabetical_sort_in_import, + force_sort_within_sections=force_sort_within_import_sections, + from_first=from_first_in_import, + include_trailing_comma=include_trailing_comma_in_import, + combine_star=combine_star_imports, + lines_after_imports=lines_after_imports, + order_by_type=order_imports_by_type, + balanced_wrapping=balanced_wrapping_in_imports, + import_heading_localfolder=import_heading_localfolder, + import_heading_firstparty=import_heading_firstparty, + import_heading_thirdparty=import_heading_thirdparty, + import_heading_stdlib=import_heading_stdlib, + import_heading_future=import_heading_future, + default_section=default_import_section, + force_grid_wrap=force_grid_wrap_imports, + force_single_line=force_single_line_imports, + length_sort=sort_imports_by_length, + indent="Tab" if use_spaces == False else tab_width, + forced_separate=forced_separate_imports, + multi_line_output=isort_multi_line_output, + known_first_party=known_first_party_imports, + line_length=max_line_length, + force_to_top=imports_forced_to_top) + + if known_standard_library_imports is not None: + isort_settings["known_standard_library"] = ( + known_standard_library_imports) + + sort_imports = SortImports(file_contents=''.join(file), + **isort_settings) + new_file = tuple(sort_imports.output.splitlines(True)) if new_file != tuple(file): diff = Diff.from_string_arrays(file, new_file) diff --git a/tests/python/PyImportSortBearTest.py b/tests/python/PyImportSortBearTest.py index 0ffeec67f4..a44b7eab86 100644 --- a/tests/python/PyImportSortBearTest.py +++ b/tests/python/PyImportSortBearTest.py @@ -6,3 +6,18 @@ ("import os\n", "import sys\n")), (["import sys\n", "import os\n"], ("import sys\n", "import os\n"))) + +PyImportSortBearConfigsTest = verify_local_bear( + PyImportSortBear, + (("from os import read\n", "from sys import *\n"),), + (("from os import read\n", "from os import *\n"),), + settings={"combine_star_imports": True}) + +PyImportSortBearIgnoredConfigsTest = verify_local_bear( + PyImportSortBear, + (("import xyz\n", "\n", "import abc\n"), + ("from xyz import *\n", "\n", "import abc\n")), + (("import xyz\n", "import abc\n"), + ("import abc\n", "import xyz\n")), + settings={"known_standard_library_imports": "xyz", + "known_first_party_imports": "abc"})