From 03d6d9819fec7b68ebd26ecaaadda218a9f7d2d0 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Thu, 20 Feb 2025 09:51:35 +0100 Subject: [PATCH] Ruff rules B017, B028, and E203 --- isort/api.py | 15 ++++++++++----- isort/main.py | 19 ++++++++++++------- isort/parse.py | 6 ++++-- isort/settings.py | 25 ++++++++++++++++++------- isort/setuptools_commands.py | 2 +- pyproject.toml | 9 --------- tests/unit/test_io.py | 7 ++++--- tests/unit/test_isort.py | 5 ++--- 8 files changed, 51 insertions(+), 37 deletions(-) diff --git a/isort/api.py b/isort/api.py index bcfcc3bdb..f58dff9ac 100644 --- a/isort/api.py +++ b/isort/api.py @@ -199,7 +199,8 @@ def sort_stream( raise ExistingSyntaxErrors(content_source) if config.verbose: warn( - f"{content_source} Python AST errors found but ignored due to Cython extension" + f"{content_source} Python AST errors found but ignored due to Cython extension", + stacklevel=2, ) input_stream = StringIO(file_content) @@ -227,7 +228,8 @@ def sort_stream( raise IntroducedSyntaxErrors(content_source) if config.verbose: warn( - f"{content_source} Python AST errors found but ignored due to Cython extension" + f"{content_source} Python AST errors found but ignored due to Cython extension", + stacklevel=2, ) if _internal_output != output_stream: output_stream.write(_internal_output.read()) @@ -494,9 +496,12 @@ def sort_file( source_file.stream.close() except ExistingSyntaxErrors: - warn(f"{actual_file_path} unable to sort due to existing syntax errors") + warn(f"{actual_file_path} unable to sort due to existing syntax errors", stacklevel=2) except IntroducedSyntaxErrors: # pragma: no cover - warn(f"{actual_file_path} unable to sort as isort introduces new syntax errors") + warn( + f"{actual_file_path} unable to sort as isort introduces new syntax errors", + stacklevel=2, + ) return changed @@ -599,7 +604,7 @@ def find_imports_in_file( **config_kwargs, ) except OSError as error: - warn(f"Unable to parse file {filename} due to {error}") + warn(f"Unable to parse file {filename} due to {error}", stacklevel=2) def find_imports_in_paths( diff --git a/isort/main.py b/isort/main.py index 614bbd497..5a6447d38 100644 --- a/isort/main.py +++ b/isort/main.py @@ -102,11 +102,11 @@ def sort_imports( skipped = True return SortAttempt(incorrectly_sorted, skipped, True) except (OSError, ValueError) as error: - warn(f"Unable to parse file {file_name} due to {error}") + warn(f"Unable to parse file {file_name} due to {error}", stacklevel=2) return None except UnsupportedEncoding: if config.verbose: - warn(f"Encoding not supported for {file_name}") + warn(f"Encoding not supported for {file_name}", stacklevel=2) return SortAttempt(incorrectly_sorted, skipped, False) except ISortError as error: _print_hard_fail(config, message=str(error)) @@ -1079,7 +1079,7 @@ def main(argv: Optional[Sequence[str]] = None, stdin: Optional[TextIOWrapper] = venv = arguments["virtual_env"] arguments["virtual_env"] = os.path.abspath(venv) if not os.path.isdir(arguments["virtual_env"]): - warn(f"virtual_env dir does not exist: {arguments['virtual_env']}") + warn(f"virtual_env dir does not exist: {arguments['virtual_env']}", stacklevel=2) file_names = arguments.pop("files", []) if not file_names and not show_config: @@ -1260,7 +1260,9 @@ def main(argv: Optional[Sequence[str]] = None, stdin: Optional[TextIOWrapper] = if num_broken and not config.quiet: if config.verbose: for was_broken in broken: - warn(f"{was_broken} was broken path, make sure it exists correctly") + warn( + f"{was_broken} was broken path, make sure it exists correctly", stacklevel=2 + ) print(f"Broken {num_broken} paths") if num_broken > 0 and is_no_attempt: @@ -1272,16 +1274,19 @@ def main(argv: Optional[Sequence[str]] = None, stdin: Optional[TextIOWrapper] = if remapped_deprecated_args: warn( "W0502: The following deprecated single dash CLI flags were used and translated: " - f"{', '.join(remapped_deprecated_args)}!" + f"{', '.join(remapped_deprecated_args)}!", + stacklevel=2, ) if deprecated_flags: warn( "W0501: The following deprecated CLI flags were used and ignored: " - f"{', '.join(deprecated_flags)}!" + f"{', '.join(deprecated_flags)}!", + stacklevel=2, ) warn( "W0500: Please see the 5.0.0 Upgrade guide: " - "https://pycqa.github.io/isort/docs/upgrade_guides/5.0.0.html" + "https://pycqa.github.io/isort/docs/upgrade_guides/5.0.0.html", + stacklevel=2, ) if wrong_sorted_files: diff --git a/isort/parse.py b/isort/parse.py index 2ae01e0f7..e1b205768 100644 --- a/isort/parse.py +++ b/isort/parse.py @@ -451,7 +451,8 @@ def file_contents(contents: str, config: Config = DEFAULT_CONFIG) -> ParsedConte if placed_module == "": warn( f"could not place module {import_from} of line {line} --" - " Do you need to define a default section?" + " Do you need to define a default section?", + stacklevel=2, ) if placed_module and placed_module not in imports: @@ -569,7 +570,8 @@ def file_contents(contents: str, config: Config = DEFAULT_CONFIG) -> ParsedConte if placed_module == "": warn( f"could not place module {module} of line {line} --" - " Do you need to define a default section?" + " Do you need to define a default section?", + stacklevel=2, ) imports.setdefault("", {"straight": OrderedDict(), "from": OrderedDict()}) diff --git a/isort/settings.py b/isort/settings.py index b35792d8e..b8281a41a 100644 --- a/isort/settings.py +++ b/isort/settings.py @@ -339,7 +339,8 @@ def __init__( "was found inside. This can happen when [settings] is used as the config " "header instead of [isort]. " "See: https://pycqa.github.io/isort/docs/configuration/config_files" - "#custom-config-files for more information." + "#custom-config-files for more information.", + stacklevel=2, ) elif settings_path: if not os.path.exists(settings_path): @@ -407,7 +408,8 @@ def __init__( f"Default to {section_name} if unsure." "\n\n" "See: https://pycqa.github.io/isort/" - "#custom-sections-and-ordering." + "#custom-sections-and-ordering.", + stacklevel=2, ) else: combined_config[section_name] = frozenset(value) @@ -419,7 +421,8 @@ def __init__( " included in `sections` config option:" f" {combined_config.get('sections', SECTION_DEFAULTS)}.\n\n" "See: https://pycqa.github.io/isort/" - "#custom-sections-and-ordering." + "#custom-sections-and-ordering.", + stacklevel=2, ) if key.startswith(IMPORT_HEADING_PREFIX): import_headings[key[len(IMPORT_HEADING_PREFIX) :].lower()] = str(value) @@ -442,7 +445,8 @@ def __init__( warn( f"`sections` setting includes {section}, but no known_{section.lower()} " "is defined. " - f"The following known_SECTION config options are defined: {config_keys}." + f"The following known_SECTION config options are defined: {config_keys}.", + stacklevel=2, ) if "directory" not in combined_config: @@ -495,7 +499,8 @@ def __init__( "W0503: Deprecated config options were used: " f"{', '.join(deprecated_options_used)}." "Please see the 5.0.0 upgrade guide: " - "https://pycqa.github.io/isort/docs/upgrade_guides/5.0.0.html" + "https://pycqa.github.io/isort/docs/upgrade_guides/5.0.0.html", + stacklevel=2, ) if known_other: @@ -777,7 +782,10 @@ def _find_config(path: str) -> Tuple[str, Dict[str, Any]]: potential_config_file, CONFIG_SECTIONS[config_file_name] ) except Exception: - warn(f"Failed to pull configuration information from {potential_config_file}") + warn( + f"Failed to pull configuration information from {potential_config_file}", + stacklevel=2, + ) config_data = {} if config_data: return (current_directory, config_data) @@ -814,7 +822,10 @@ def find_all_configs(path: str) -> Trie: potential_config_file, CONFIG_SECTIONS[config_file_name] ) except Exception: - warn(f"Failed to pull configuration information from {potential_config_file}") + warn( + f"Failed to pull configuration information from {potential_config_file}", + stacklevel=2, + ) config_data = {} if config_data: diff --git a/isort/setuptools_commands.py b/isort/setuptools_commands.py index 8cca60f76..123c9f4cf 100644 --- a/isort/setuptools_commands.py +++ b/isort/setuptools_commands.py @@ -57,6 +57,6 @@ def run(self) -> None: if not api.check_file(python_file, **arguments): wrong_sorted_files = True # pragma: no cover except OSError as error: # pragma: no cover - warn(f"Unable to parse file {python_file} due to {error}") + warn(f"Unable to parse file {python_file} due to {error}", stacklevel=2) if wrong_sorted_files: sys.exit(1) # pragma: no cover diff --git a/pyproject.toml b/pyproject.toml index 8efaf4e17..3af28496b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -145,12 +145,6 @@ dev = [ [tool.flake8] max-line-length = 100 -# Ignore non PEP 8 compliant rules as suggested by black -# E203: https://github.com/psf/black/blob/3fab5ade71bccf80ae0a5af76729099869adea56/docs/the_black_code_style/current_style.md#slices -extend-ignore = [ - "B017", - "E203", -] exclude = "_vendored" per-file-ignores = [ "tests/unit/example_crlf_file.py:F401", @@ -190,10 +184,7 @@ lint.select = [ "W", ] lint.ignore = [ - "B017", - "B028", "B904", - "E203", "E501", "PERF203", "RUF100", diff --git a/tests/unit/test_io.py b/tests/unit/test_io.py index a4479c860..c41ce4ecd 100644 --- a/tests/unit/test_io.py +++ b/tests/unit/test_io.py @@ -4,6 +4,7 @@ import pytest from isort import io +from isort.exceptions import UnsupportedEncoding class TestFile: @@ -15,7 +16,7 @@ def test_read(self, tmpdir): """ test_file = tmpdir.join("file.py") test_file.write(test_file_content) - with pytest.raises(Exception): + with pytest.raises(UnicodeDecodeError): with io.File.read(str(test_file)) as file_handler: file_handler.stream.read() @@ -27,7 +28,7 @@ def test_from_content(self, tmpdir): assert file_obj.extension == "py" def test_open(self, tmpdir): - with pytest.raises(Exception): + with pytest.raises(FileNotFoundError): io.File._open("THISCANTBEAREALFILEὩὩὩὩὩὩὩὩὩὩὩὩ.ὩὩὩὩὩ") def raise_arbitrary_exception(*args, **kwargs): @@ -39,5 +40,5 @@ def raise_arbitrary_exception(*args, **kwargs): # correctly responds to error determining encoding with patch("tokenize.detect_encoding", raise_arbitrary_exception): - with pytest.raises(Exception): + with pytest.raises(UnsupportedEncoding): io.File._open(str(test_file)) diff --git a/tests/unit/test_isort.py b/tests/unit/test_isort.py index 5f75ece21..09bedbb0b 100644 --- a/tests/unit/test_isort.py +++ b/tests/unit/test_isort.py @@ -4337,9 +4337,8 @@ def test_settings_path_skip_issue_909(tmpdir) -> None: test_run_directory = os.getcwd() os.chdir(str(base_dir)) - with pytest.raises( - Exception - ): # without the settings path provided: the command should not skip & identify errors + with pytest.raises(subprocess.CalledProcessError): + # without the settings path provided: the command should not skip & identify errors subprocess.run(["isort", ".", "--check-only"], check=True) result = subprocess.run( ["isort", ".", "--check-only", "--settings-path=conf/.isort.cfg"],