diff --git a/.ruff.toml b/.ruff.toml index c063169..3c4172f 100644 --- a/.ruff.toml +++ b/.ruff.toml @@ -4,11 +4,21 @@ indent-width = 4 target-version = "py312" [lint] -select = ["C4", "E", "FURB", "F", "I", "PERF", "PL", "Q", "RET", "SIM", "TRY", "UP", "W", "YTT"] +select = ["B", "C", "C4", "E", "FURB", "F", "I", "PERF", "PL", "Q", "RET", "RUF", "SIM", "TRY", "UP", "W", "YTT"] +# COM812: Trailing Comma (Only covers single line trailing commas, seems out of place) # D: Doc style +# EM: Error messages +# FBT: Boolean Trap (Slower) +# PTH: Use Pathlib (Wants slower API used) # TRY003: Avoid specifying long messages outside the exception class (Slower and less clear) -ignore = ["D", "TRY003"] +ignore = ["COM812", "D", "EM", "FBT", "PTH", "TRY003"] + +[lint.extend-per-file-ignores] + +# ANN201: Missing return type +# PT011: Pytest raises +"tests/*" = ["ANN201", "PT011", "S101"] [lint.isort] known-third-party = ["nuitka"] diff --git a/personal_python_ast_optimizer/futures.py b/personal_python_ast_optimizer/futures.py index 5794524..f59a6e8 100644 --- a/personal_python_ast_optimizer/futures.py +++ b/personal_python_ast_optimizer/futures.py @@ -1,5 +1,5 @@ class Futures: - __slots__ = ("name", "mandatory_version") + __slots__ = ("mandatory_version", "name") def __init__(self, name: str, mandatory_version: tuple[int, int]) -> None: self.name: str = name diff --git a/personal_python_ast_optimizer/parser/config.py b/personal_python_ast_optimizer/parser/config.py index a6c8185..24a7235 100644 --- a/personal_python_ast_optimizer/parser/config.py +++ b/personal_python_ast_optimizer/parser/config.py @@ -56,13 +56,13 @@ def has_code_to_skip(self) -> bool: class TokensConfig(_Config): __slots__ = ( "_no_warn", - "from_imports_to_skip", - "functions_to_skip", - "variables_to_skip", "classes_to_skip", - "dict_keys_to_skip", "decorators_to_skip", + "dict_keys_to_skip", + "from_imports_to_skip", + "functions_to_skip", "module_imports_to_skip", + "variables_to_skip", ) def __init__( # noqa: PLR0913 @@ -111,8 +111,8 @@ class TokenTypesConfig(_Config): __slots__ = ( "skip_asserts", "skip_dangling_expressions", - "skip_type_hints", "skip_overload_functions", + "skip_type_hints", ) def __init__( @@ -131,15 +131,15 @@ def __init__( class OptimizationsConfig(_Config): __slots__ = ( - "vars_to_fold", + "assume_this_machine", + "collection_concat_to_unpack", "enums_to_fold", + "fold_constants", "functions_safe_to_exclude_in_test_expr", "remove_typing_cast", "remove_unused_imports", - "collection_concat_to_unpack", - "fold_constants", - "assume_this_machine", "simplify_named_tuples", + "vars_to_fold", ) def __init__( # noqa: PLR0913 @@ -190,10 +190,10 @@ def _format_enums_to_fold_as_dict( class SkipConfig(_Config): __slots__ = ( "module_name", + "optimizations_config", "target_python_version", "token_types_config", "tokens_config", - "optimizations_config", ) def __init__( @@ -201,15 +201,19 @@ def __init__( module_name: str, *, target_python_version: tuple[int, int] | None = None, - tokens_config: TokensConfig = TokensConfig(), - token_types_config: TokenTypesConfig = TokenTypesConfig(), - optimizations_config: OptimizationsConfig = OptimizationsConfig(), + tokens_config: TokensConfig | None = None, + token_types_config: TokenTypesConfig | None = None, + optimizations_config: OptimizationsConfig | None = None, ) -> None: self.module_name: str = module_name self.target_python_version: tuple[int, int] | None = target_python_version - self.tokens_config: TokensConfig = tokens_config - self.token_types_config: TokenTypesConfig = token_types_config - self.optimizations_config: OptimizationsConfig = optimizations_config + self.tokens_config: TokensConfig = tokens_config or TokensConfig() + self.token_types_config: TokenTypesConfig = ( + token_types_config or TokenTypesConfig() + ) + self.optimizations_config: OptimizationsConfig = ( + optimizations_config or OptimizationsConfig() + ) def has_code_to_skip(self) -> bool: return ( diff --git a/personal_python_ast_optimizer/parser/skipper.py b/personal_python_ast_optimizer/parser/skipper.py index 8b32c21..0313857 100644 --- a/personal_python_ast_optimizer/parser/skipper.py +++ b/personal_python_ast_optimizer/parser/skipper.py @@ -42,8 +42,8 @@ class AstNodeSkipper(ast.NodeTransformer): "_node_context_skippable_futures", "_simplified_named_tuple", "module_name", - "target_python_version", "optimizations_config", + "target_python_version", "token_types_config", "tokens_config", ) @@ -665,11 +665,10 @@ def visit_BinOp(self, node: ast.BinOp) -> ast.AST: if ( isinstance(parsed_node.left, ast.Tuple) and isinstance(parsed_node.right, ast.Tuple) - or ( - isinstance(parsed_node.left, ast.List) - and isinstance(parsed_node.right, ast.List) - ) - ): # noqa: E721 + ) or ( + isinstance(parsed_node.left, ast.List) + and isinstance(parsed_node.right, ast.List) + ): parsed_node.left.elts += parsed_node.right.elts elif isinstance(parsed_node.left, (ast.Tuple, ast.List)): parsed_node.left.elts.append(ast.Starred(parsed_node.right)) @@ -748,18 +747,19 @@ def _should_skip_function_assign(self, node: ast.Assign | ast.AnnAssign) -> bool and get_node_name(node.value.func) in self.tokens_config.functions_to_skip ) - def _warn_unused_skips(self): + def _warn_unused_skips(self) -> None: for ( token_type, not_found_tokens, ) in self.tokens_config.get_missing_tokens_iter(): warnings.warn( f"{self.module_name}: requested to skip {token_type} " - f"{not_found_tokens} but was not found" + f"{not_found_tokens} but was not found", + stacklevel=2, ) @staticmethod - def _ast_constants_operation( # noqa: PLR0912 + def _ast_constants_operation( # noqa: C901, PLR0912 left: ast.Constant, right: ast.Constant, operation: ast.operator | ast.cmpop, diff --git a/personal_python_ast_optimizer/regex/replace.py b/personal_python_ast_optimizer/regex/replace.py index 322d49a..132c10d 100644 --- a/personal_python_ast_optimizer/regex/replace.py +++ b/personal_python_ast_optimizer/regex/replace.py @@ -5,7 +5,7 @@ class RegexReplacement: """Represents arguments to a regex replacement call like re.sub""" - __slots__ = ("pattern", "replacement", "flags", "count") + __slots__ = ("count", "flags", "pattern", "replacement") def __init__( self, pattern: str, replacement: str = "", flags: int = 0, count: int = 1 diff --git a/requirements_dev.txt b/requirements_dev.txt index f9ce042..d6505d5 100644 --- a/requirements_dev.txt +++ b/requirements_dev.txt @@ -2,4 +2,4 @@ codespell==2.4.1 mypy==1.19.1 pytest==9.0.2 pytest-cov==7.0.0 -ruff==0.14.13 +ruff==0.14.14 diff --git a/tests/parser/__init__.py b/tests/parser/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/parser/test_imports.py b/tests/parser/test_imports.py index e80cae4..2c1f4d7 100644 --- a/tests/parser/test_imports.py +++ b/tests/parser/test_imports.py @@ -20,7 +20,7 @@ @pytest.mark.parametrize( - "version,skip_type_hints,after", + ("version", "skip_type_hints", "after"), [ (None, TypeHintsToSkip.NONE, _futures_imports_inline), ((3, 7), TypeHintsToSkip.NONE, "from __future__ import annotations"), diff --git a/tests/parser/test_same_machine.py b/tests/parser/test_same_machine.py index 75bc974..67a96ca 100644 --- a/tests/parser/test_same_machine.py +++ b/tests/parser/test_same_machine.py @@ -20,7 +20,7 @@ def get_cpu_count(): @pytest.mark.parametrize( - "assume_this_machine,before,after", + ("assume_this_machine", "before", "after"), [ ( True, diff --git a/tests/regex/__init__.py b/tests/regex/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/utils.py b/tests/utils.py index 86a7fd5..faf77e7 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -12,7 +12,7 @@ class BeforeAndAfter: """Input and output after minifying it""" - __slots__ = ("before", "after") + __slots__ = ("after", "before") def __init__(self, before: str, after: str) -> None: self.before: str = before