diff --git a/isort/core.py b/isort/core.py index 472d914d..bff28458 100644 --- a/isort/core.py +++ b/isort/core.py @@ -12,9 +12,9 @@ from .settings import FILE_SKIP_COMMENTS CIMPORT_IDENTIFIERS = ("cimport ", "cimport*", "from.cimport") -IMPORT_START_IDENTIFIERS = ("from ", "from.import", "import ", "import*") + CIMPORT_IDENTIFIERS +IMPORT_START_IDENTIFIERS = ("from ", "from.import", "import ", "import*", *CIMPORT_IDENTIFIERS) DOCSTRING_INDICATORS = ('"""', "'''") -COMMENT_INDICATORS = DOCSTRING_INDICATORS + ("'", '"', "#") +COMMENT_INDICATORS = (*DOCSTRING_INDICATORS, "'", '"', "#") CODE_SORT_COMMENTS = ( "# isort: list", "# isort: dict", @@ -180,11 +180,11 @@ def process( add_imports = [ import_to_add for import_to_add in add_imports - if not import_to_add == import_not_to_add + if import_to_add != import_not_to_add ] if ( - (index == 0 or (index in (1, 2) and not contains_imports)) + (index == 0 or (index in {1, 2} and not contains_imports)) and stripped_line.startswith("#") and stripped_line not in config.section_comments and stripped_line not in CODE_SORT_COMMENTS @@ -199,11 +199,9 @@ def process( first_comment_index_end = index - 1 was_in_quote = bool(in_quote) - if (not stripped_line.startswith("#") or in_quote) and '"' in line or "'" in line: + if ((not stripped_line.startswith("#") or in_quote) and '"' in line) or "'" in line: char_index = 0 - if first_comment_index_start == -1 and ( - line.startswith('"') or line.startswith("'") - ): + if first_comment_index_start == -1 and line.startswith(('"', "'")): first_comment_index_start = index while char_index < len(line): if line[char_index] == "\\": @@ -287,9 +285,8 @@ def process( indent = line[: -len(line.lstrip())] elif not (stripped_line or contains_imports): not_imports = True - elif ( - not stripped_line - or stripped_line.startswith("#") + elif not stripped_line or ( + stripped_line.startswith("#") and (not indent or indent + line.lstrip() == line) and not config.treat_all_comments_as_code and stripped_line not in config.treat_comments_as_code @@ -477,7 +474,7 @@ def process( output_stream.write(new_line) stripped_line = new_line.strip().split("#")[0] - if stripped_line.startswith("raise") or stripped_line.startswith("yield"): + if stripped_line.startswith(("raise", "yield")): while stripped_line.endswith("\\"): new_line = input_stream.readline() if not new_line: diff --git a/isort/deprecated/finders.py b/isort/deprecated/finders.py index 75f53964..cf21f4e2 100644 --- a/isort/deprecated/finders.py +++ b/isort/deprecated/finders.py @@ -236,10 +236,9 @@ def _load_mapping() -> Optional[Dict[str, str]]: def _load_names(self) -> List[str]: """Return list of thirdparty modules from requirements""" - names = [] + names: List[str] = [] for path in self._get_files(): - for name in self._get_names(path): - names.append(self._normalize_name(name)) + names.extend(self._normalize_name(name) for name in self._get_names(path)) return names @staticmethod @@ -298,7 +297,7 @@ def _get_files_from_dir(self, path: str) -> Iterator[str]: @classmethod @lru_cache(maxsize=16) def _get_files_from_dir_cached(cls, path: str) -> List[str]: - results = [] + results: List[str] = [] for fname in os.listdir(path): if "requirements" not in fname: @@ -308,9 +307,11 @@ def _get_files_from_dir_cached(cls, path: str) -> List[str]: # *requirements*/*.{txt,in} if os.path.isdir(full_path): for subfile_name in os.listdir(full_path): - for ext in cls.exts: - if subfile_name.endswith(ext): - results.append(os.path.join(full_path, subfile_name)) + results.extend( + os.path.join(full_path, subfile_name) + for ext in cls.ext # type: ignore[attr-defined] + if subfile_name.endswith(ext) + ) continue # *requirements*.{txt,in} @@ -329,13 +330,11 @@ def _get_names(self, path: str) -> Iterator[str]: @classmethod @lru_cache(maxsize=16) def _get_names_cached(cls, path: str) -> List[str]: - result = [] + result: List[str] = [] with chdir(os.path.dirname(path)): requirements = parse_requirements(Path(path)) - for req in requirements.values(): - if req.name: - result.append(req.name) + result.extend(req.name for req in requirements.values() if req.name) return result diff --git a/isort/identify.py b/isort/identify.py index b1964b41..da9eb822 100644 --- a/isort/identify.py +++ b/isort/identify.py @@ -61,7 +61,7 @@ def imports( continue stripped_line = raw_line.strip().split("#")[0] - if stripped_line.startswith("raise") or stripped_line.startswith("yield"): + if stripped_line.startswith(("raise", "yield")): if stripped_line == "yield": while not stripped_line or stripped_line == "yield": try: diff --git a/isort/literal.py b/isort/literal.py index 1f57a3d7..39ef3493 100644 --- a/isort/literal.py +++ b/isort/literal.py @@ -96,7 +96,7 @@ def _list(value: List[Any], printer: ISortPrettyPrinter) -> str: @register_type("unique-list", list) def _unique_list(value: List[Any], printer: ISortPrettyPrinter) -> str: - return printer.pformat(list(sorted(set(value)))) + return printer.pformat(sorted(set(value))) @register_type("set", set) diff --git a/isort/main.py b/isort/main.py index 8d9e48de..614bbd49 100644 --- a/isort/main.py +++ b/isort/main.py @@ -876,7 +876,7 @@ def _build_arg_parser() -> argparse.ArgumentParser: "--python-version", action="store", dest="py_version", - choices=tuple(VALID_PY_TARGETS) + ("auto",), + choices=(*tuple(VALID_PY_TARGETS), "auto"), help="Tells isort to set the known standard library based on the specified Python " "version. Default is to assume any Python 3 version could be the target, and use a union " "of all stdlib modules across versions. If auto is specified, the version of the " diff --git a/isort/output.py b/isort/output.py index ade4ad29..195f418e 100644 --- a/isort/output.py +++ b/isort/output.py @@ -41,7 +41,7 @@ def sorted_imports( parsed.imports[section].get("straight", {}) ) parsed.imports["no_sections"]["from"].update(parsed.imports[section].get("from", {})) - sections = base_sections + ("no_sections",) + sections = (*base_sections, "no_sections") output: List[str] = [] seen_headings: Set[str] = set() @@ -338,7 +338,7 @@ def _with_from_imports( ) if comment: single_import_line += ( - f"{comments and ';' or config.comment_prefix} " f"{comment}" + f"{(comments and ';') or config.comment_prefix} " f"{comment}" ) if from_import in as_imports: if ( @@ -467,7 +467,7 @@ def _with_from_imports( comment_prefix=config.comment_prefix, ) single_import_line += ( - f"{use_comments and ';' or config.comment_prefix} " f"{comment}" + f"{(use_comments and ';') or config.comment_prefix} " f"{comment}" ) output.append(wrap.line(single_import_line, parsed.line_separator, config)) @@ -662,7 +662,7 @@ def _ensure_newline_before_comment(output: List[str]) -> List[str]: def is_comment(line: Optional[str]) -> bool: return line.startswith("#") if line else False - for line, prev_line in zip(output, [None] + output): # type: ignore + for line, prev_line in zip(output, [None, *output]): if is_comment(line) and prev_line != "" and not is_comment(prev_line): new_output.append("") new_output.append(line) @@ -672,5 +672,5 @@ def is_comment(line: Optional[str]) -> bool: def _with_star_comments(parsed: parse.ParsedContent, module: str, comments: List[str]) -> List[str]: star_comment = parsed.categorized_comments["nested"].get(module, {}).pop("*", None) if star_comment: - return comments + [star_comment] + return [*comments, star_comment] return comments diff --git a/isort/parse.py b/isort/parse.py index c7641a02..2ae01e0f 100644 --- a/isort/parse.py +++ b/isort/parse.py @@ -493,7 +493,7 @@ def file_contents(contents: str, config: Config = DEFAULT_CONFIG) -> ParsedConte and "isort:imports-" not in last and "isort: imports-" not in last and not config.treat_all_comments_as_code - and not last.strip() in config.treat_comments_as_code + and last.strip() not in config.treat_comments_as_code ): categorized_comments["above"]["from"].setdefault(import_from, []).insert( 0, out_lines.pop(-1) @@ -545,7 +545,7 @@ def file_contents(contents: str, config: Config = DEFAULT_CONFIG) -> ParsedConte and "isort:imports-" not in last and "isort: imports-" not in last and not config.treat_all_comments_as_code - and not last.strip() in config.treat_comments_as_code + and last.strip() not in config.treat_comments_as_code ): categorized_comments["above"]["straight"].setdefault(module, []).insert( 0, out_lines.pop(-1) diff --git a/isort/place.py b/isort/place.py index b3a25366..52ddc122 100644 --- a/isort/place.py +++ b/isort/place.py @@ -71,7 +71,7 @@ def _src_path( src_paths = config.src_paths root_module_name, *nested_module = name.split(".", 1) - new_prefix = prefix + (root_module_name,) + new_prefix = (*prefix, root_module_name) namespace = ".".join(new_prefix) for src_path in src_paths: diff --git a/isort/settings.py b/isort/settings.py index 0abc43a8..5ee47f58 100644 --- a/isort/settings.py +++ b/isort/settings.py @@ -437,7 +437,7 @@ def __init__( if section in SECTION_DEFAULTS: continue - if not section.lower() in known_other: + if section.lower() not in known_other: config_keys = ", ".join(known_other.keys()) warn( f"`sections` setting includes {section}, but no known_{section.lower()} " @@ -852,15 +852,12 @@ def _get_config_data(file_path: str, sections: Tuple[str, ...]) -> Dict[str, Any for section in sections: if section.startswith("*.{") and section.endswith("}"): extension = section[len("*.{") : -1] - for config_key in config.keys(): + for config_key in config: if ( config_key.startswith("*.{") and config_key.endswith("}") and extension - in map( - lambda text: text.strip(), - config_key[len("*.{") : -1].split(","), # noqa - ) + in (text.strip() for text in config_key[len("*.{") : -1].split(",")) ): settings.update(config.items(config_key)) @@ -877,10 +874,10 @@ def _get_config_data(file_path: str, sections: Tuple[str, ...]) -> Dict[str, Any indent_size = settings.pop("tab_width", "").strip() if indent_style == "space": - settings["indent"] = " " * (indent_size and int(indent_size) or 4) + settings["indent"] = " " * ((indent_size and int(indent_size)) or 4) elif indent_style == "tab": - settings["indent"] = "\t" * (indent_size and int(indent_size) or 1) + settings["indent"] = "\t" * ((indent_size and int(indent_size)) or 1) max_line_length = settings.pop("max_line_length", "").strip() if max_line_length and (max_line_length == "off" or max_line_length.isdigit()): @@ -890,7 +887,7 @@ def _get_config_data(file_path: str, sections: Tuple[str, ...]) -> Dict[str, Any settings = { key: value for key, value in settings.items() - if key in _DEFAULT_SETTINGS.keys() or key.startswith(KNOWN_PREFIX) + if key in _DEFAULT_SETTINGS or key.startswith(KNOWN_PREFIX) } for key, value in settings.items(): diff --git a/isort/sorting.py b/isort/sorting.py index bd1df18d..f4504f07 100644 --- a/isort/sorting.py +++ b/isort/sorting.py @@ -51,7 +51,7 @@ def module_key( or str(section_name).lower() in config.length_sort_sections ) _length_sort_maybe = (str(len(module_name)) + ":" + module_name) if length_sort else module_name - return f"{module_name in config.force_to_top and 'A' or 'B'}{prefix}{_length_sort_maybe}" + return f"{(module_name in config.force_to_top and 'A') or 'B'}{prefix}{_length_sort_maybe}" def section_key(line: str, config: Config) -> str: @@ -90,7 +90,7 @@ def section_key(line: str, config: Config) -> str: module_name = module_name.lower() if not config.order_by_type: names = names.lower() - line = " import ".join([module_name, names]) + line = f"{module_name} import {names}" elif not config.case_sensitive: line = line.lower() elif not config.order_by_type: diff --git a/isort/wrap_modes.py b/isort/wrap_modes.py index e7909ea2..3ae47152 100644 --- a/isort/wrap_modes.py +++ b/isort/wrap_modes.py @@ -333,7 +333,7 @@ def hanging_indent_with_parentheses(**interface: Any) -> str: while interface["imports"]: next_import = interface["imports"].pop(0) if ( - not interface["line_separator"] in interface["statement"] + interface["line_separator"] not in interface["statement"] and "#" in interface["statement"] ): # pragma: no cover # TODO: fix, this is because of test run inconsistency. line, comments = interface["statement"].split("#", 1) diff --git a/scripts/build_profile_docs.py b/scripts/build_profile_docs.py index 08916fb7..9a8a892f 100755 --- a/scripts/build_profile_docs.py +++ b/scripts/build_profile_docs.py @@ -20,7 +20,7 @@ def format_profile(profile_name: str, profile: Dict[str, Any]) -> str: - options = "\n".join(f" - **{name}**: `{repr(value)}`" for name, value in profile.items()) + options = "\n".join(f" - **{name}**: `{value!r}`" for name, value in profile.items()) return f""" #{profile_name} diff --git a/tests/integration/test_hypothesmith.py b/tests/integration/test_hypothesmith.py index 28517513..8dc2acb8 100644 --- a/tests/integration/test_hypothesmith.py +++ b/tests/integration/test_hypothesmith.py @@ -63,7 +63,7 @@ def configs(**force_strategies: st.SearchStrategy) -> st.SearchStrategy: "default_section": st.sampled_from(sorted(isort.settings.KNOWN_SECTION_MAPPING)), "force_grid_wrap": st.integers(0, 20), "profile": st.sampled_from(sorted(isort.settings.profiles)), - "py_version": st.sampled_from(("auto",) + isort.settings.VALID_PY_TARGETS), + "py_version": st.sampled_from(("auto", *isort.settings.VALID_PY_TARGETS)), } kwargs = {**inferred_kwargs, **specific, **force_strategies} return st.fixed_dictionaries({}, optional=kwargs).map(_as_config) diff --git a/tests/integration/test_setting_combinations.py b/tests/integration/test_setting_combinations.py index bace3dea..aae1b354 100644 --- a/tests/integration/test_setting_combinations.py +++ b/tests/integration/test_setting_combinations.py @@ -58,7 +58,7 @@ def configs() -> st.SearchStrategy: "force_grid_wrap": st.integers(0, 20), "profile": st.sampled_from(sorted(isort.settings.profiles)), "sort_order": st.sampled_from(sorted(("native", "natural", "natural_plus"))), - "py_version": st.sampled_from(("auto",) + isort.settings.VALID_PY_TARGETS), + "py_version": st.sampled_from(("auto", *isort.settings.VALID_PY_TARGETS)), } kwargs = {**inferred_kwargs, **specific} return st.fixed_dictionaries({}, optional=kwargs).map(_as_config) diff --git a/tests/unit/test_deprecated_finders.py b/tests/unit/test_deprecated_finders.py index 5b9111dd..fd709382 100644 --- a/tests/unit/test_deprecated_finders.py +++ b/tests/unit/test_deprecated_finders.py @@ -21,7 +21,7 @@ def __init__(self, *args, **kwargs): with patch( "isort.deprecated.finders.FindersManager._default_finders_classes", - FindersManager._default_finders_classes + (ExceptionOnInit,), # type: ignore + (*FindersManager._default_finders_classes, ExceptionOnInit), ): assert FindersManager(settings.Config(verbose=True)) diff --git a/tests/unit/test_hooks.py b/tests/unit/test_hooks.py index 29685f50..efa129d0 100644 --- a/tests/unit/test_hooks.py +++ b/tests/unit/test_hooks.py @@ -66,7 +66,7 @@ def test_git_hook(src_dir): "isort.hooks.get_lines", MagicMock(return_value=[os.path.join(src_dir, "main.py")]) ) as run_mock: - class FakeProcessResponse(object): + class FakeProcessResponse: stdout = b"# isort: skip-file\nimport b\nimport a\n" with patch("subprocess.run", MagicMock(return_value=FakeProcessResponse())) as run_mock: diff --git a/tests/unit/test_main.py b/tests/unit/test_main.py index 82204c31..89770939 100644 --- a/tests/unit/test_main.py +++ b/tests/unit/test_main.py @@ -177,7 +177,7 @@ def test_main(capsys, tmpdir): assert main.QUICK_GUIDE in out # Unless the config is requested, in which case it will be returned alone as JSON - main.main(base_args + ["--show-config"]) + main.main([*base_args, "--show-config"]) out, error = capsys.readouterr() returned_config = json.loads(out) assert returned_config @@ -207,9 +207,12 @@ def test_main(capsys, tmpdir): ) config_args = ["--settings-path", str(config_file)] main.main( - config_args - + ["--virtual-env", "/random-root-folder-that-cant-exist-right?"] - + ["--show-config"] + [ + *config_args, + "--virtual-env", + "/random-root-folder-that-cant-exist-right?", + "--show-config", + ] ) out, error = capsys.readouterr() assert json.loads(out)["profile"] == "hug" @@ -223,7 +226,7 @@ def test_main(capsys, tmpdir): """ ) ) - main.main(config_args + ["-"], stdin=input_content) + main.main([*config_args, "-"], stdin=input_content) out, error = capsys.readouterr() assert ( out @@ -244,7 +247,7 @@ def test_main(capsys, tmpdir): """ ) ) - main.main(config_args + ["-", "--diff"], stdin=input_content) + main.main([*config_args, "-", "--diff"], stdin=input_content) out, error = capsys.readouterr() assert not error assert "+" in out @@ -264,7 +267,7 @@ def test_main(capsys, tmpdir): ) with pytest.raises(SystemExit): - main.main(config_args + ["-", "--check-only"], stdin=input_content_check) + main.main([*config_args, "-", "--check-only"], stdin=input_content_check) out, error = capsys.readouterr() assert error == "ERROR: Imports are incorrectly sorted and/or formatted.\n" @@ -1289,11 +1292,11 @@ def test_multiple_configs(capsys, tmpdir): main.main([str(tmpdir), "--resolve-all-configs", "--cr", str(tmpdir), "--verbose"]) out, _ = capsys.readouterr() - assert f"{str(setup_cfg_file)} used for file {str(file1)}" in out - assert f"{str(pyproject_toml_file)} used for file {str(file2)}" in out - assert f"{str(isort_cfg_file)} used for file {str(file3)}" in out - assert f"default used for file {str(file4)}" in out - assert f"default used for file {str(file5)}" in out + assert f"{setup_cfg_file} used for file {file1}" in out + assert f"{pyproject_toml_file} used for file {file2}" in out + assert f"{isort_cfg_file} used for file {file3}" in out + assert f"default used for file {file4}" in out + assert f"default used for file {file5}" in out assert ( file1.read() @@ -1350,7 +1353,7 @@ def test_multiple_configs(capsys, tmpdir): _, err = capsys.readouterr() - assert f"{str(file6)} Imports are incorrectly sorted and/or formatted" in err + assert f"{file6} Imports are incorrectly sorted and/or formatted" in err def test_multiple_src_paths(tmpdir, capsys):