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
22 changes: 18 additions & 4 deletions scripts/find_and_fix_pep798.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@
The rewritten source uses Python 3.15+ syntax, so fixed files need 3.15+.

Usage:
scripts/find_and_fix_pep798.py [--fix] PATH [PATH ...]
scripts/find_and_fix_pep798.py [--fix] [PATH ...]

If no path is provided, the current working directory is searched.

Without ``--fix`` the script only reports and exits with status 1 if any
opportunities were found.
Expand Down Expand Up @@ -126,7 +128,7 @@

def _segment(source: str, offsets: _Offsets, node: ast.expr, parens: tuple) -> str:
start = offsets.offset(node.lineno, node.col_offset)
end = offsets.offset(node.end_lineno, node.end_col_offset)

Check failure on line 131 in scripts/find_and_fix_pep798.py

View workflow job for this annotation

GitHub Actions / ty

ty (invalid-argument-type)

scripts/find_and_fix_pep798.py:131:43: invalid-argument-type: Argument to bound method `_Offsets.offset` is incorrect: Expected `int`, found `int | None` info: element `None` of union `int | None` is not assignable to `int` scripts/find_and_fix_pep798.py:124:9: info: Method defined here scripts/find_and_fix_pep798.py:124:33: Parameter declared here

Check failure on line 131 in scripts/find_and_fix_pep798.py

View workflow job for this annotation

GitHub Actions / ty

ty (invalid-argument-type)

scripts/find_and_fix_pep798.py:131:26: invalid-argument-type: Argument to bound method `_Offsets.offset` is incorrect: Expected `int`, found `int | None` info: element `None` of union `int | None` is not assignable to `int` scripts/find_and_fix_pep798.py:124:9: info: Method defined here scripts/find_and_fix_pep798.py:124:22: Parameter declared here
text = source[start:end]
return f"({text})" if isinstance(node, parens) else text

Expand Down Expand Up @@ -213,14 +215,26 @@
def iter_python_files(paths: Iterable[Path]) -> Iterator[Path]:
for path in paths:
if path.is_dir():
yield from sorted(path.rglob("*.py"))
else:
yield from sorted(
candidate
for candidate in path.rglob("*.py")
if not any(part.startswith(".") for part in candidate.parent.parts)
)
elif path.suffix == ".py" and not any(
part.startswith(".") for part in path.parent.parts
):
yield path


def main(argv: list[str] | None = None) -> int:
parser = argparse.ArgumentParser(description=__doc__.split("\n\n")[0])
parser.add_argument("paths", nargs="+", type=Path, help="files or directories")
parser.add_argument(
"paths",
nargs="*",
type=Path,
default=[Path.cwd()],
help="Python files or directories (defaults to the current directory)",
)
parser.add_argument("--fix", action="store_true", help="rewrite files in place")
args = parser.parse_args(argv)

Expand Down
19 changes: 17 additions & 2 deletions tests/test_find_and_fix_pep798.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,13 +97,16 @@ def test_multiline_comprehension() -> None:

def test_iter_python_files(tmp_path: Path) -> None:
(tmp_path / "sub").mkdir()
(tmp_path / ".hidden").mkdir()
first = tmp_path / "a.py"
second = tmp_path / "sub" / "b.py"
other = tmp_path / "c.txt"
for path in (first, second, other):
hidden = tmp_path / ".hidden" / "hidden.py"
for path in (first, second, other, hidden):
path.write_text("")
assert list(iter_python_files([tmp_path])) == [first, second]
assert list(iter_python_files([other])) == [other]
assert list(iter_python_files([other])) == []
assert list(iter_python_files([hidden])) == []


def test_main_reports_without_fixing(
Expand Down Expand Up @@ -137,6 +140,18 @@ def test_main_clean_file_returns_zero(
assert "0 PEP 798 opportunities found" in capsys.readouterr().out


def test_main_defaults_to_current_directory(
tmp_path: Path, monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]
) -> None:
path = tmp_path / "mod.py"
path.write_text("a = [y for x in xs for y in x]\n")
monkeypatch.chdir(tmp_path)
assert main([]) == 1
output = capsys.readouterr().out
assert f"{path}:1:" in output
assert "1 PEP 798 opportunity found" in output


def test_main_skips_syntax_errors(
tmp_path: Path, capsys: pytest.CaptureFixture[str]
) -> None:
Expand Down
Loading