Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions .ruff.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
Expand Down
2 changes: 1 addition & 1 deletion personal_python_ast_optimizer/futures.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down
36 changes: 20 additions & 16 deletions personal_python_ast_optimizer/parser/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -111,8 +111,8 @@ class TokenTypesConfig(_Config):
__slots__ = (
"skip_asserts",
"skip_dangling_expressions",
"skip_type_hints",
"skip_overload_functions",
"skip_type_hints",
)

def __init__(
Expand All @@ -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
Expand Down Expand Up @@ -190,26 +190,30 @@ 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__(
self,
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 (
Expand Down
18 changes: 9 additions & 9 deletions personal_python_ast_optimizer/parser/skipper.py
Original file line number Diff line number Diff line change
Expand Up @@ -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",
)
Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion personal_python_ast_optimizer/regex/replace.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion requirements_dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Empty file added tests/parser/__init__.py
Empty file.
2 changes: 1 addition & 1 deletion tests/parser/test_imports.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"),
Expand Down
2 changes: 1 addition & 1 deletion tests/parser/test_same_machine.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def get_cpu_count():


@pytest.mark.parametrize(
"assume_this_machine,before,after",
("assume_this_machine", "before", "after"),
[
(
True,
Expand Down
Empty file added tests/regex/__init__.py
Empty file.
2 changes: 1 addition & 1 deletion tests/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down