mirror of
https://github.com/kuhyx/screen-locker.git
synced 2026-11-10 22:27:12 +01:00
Real fixes: split over-long functions (lock-decision chain, manual sync, validation, phone verification, status), hoist a dead lazy import, context-manage Xvfb and temp dirs, add encodings, share the silent-failure argv loop. lock_grab_handoff read lock._recovery, which gatelock's LockWindow does not have (its public property is recovery); a contract test now checks every attribute the handoff reads against the real class. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WzxdWYdwRAtMg7ki6TKxuU
77 lines
2.5 KiB
Python
77 lines
2.5 KiB
Python
"""Split a Dart test file at top-level `group(` boundaries.
|
|
|
|
Each output file reuses the original's imports and its main() setup preamble
|
|
(everything between `void main() {` and the first top-level group), so every
|
|
part runs the same fixtures the original did.
|
|
|
|
Usage:
|
|
split_dart_test.py <file> <out1>:<firstGroupIdx> [<out2>:<idx> ...]
|
|
|
|
Indices are 0-based positions in the top-level group list; each output takes
|
|
groups[idx:next_idx]. The source file keeps groups[:first_idx].
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
import re
|
|
import sys
|
|
|
|
|
|
def top_level_groups(lines: list[str]) -> list[int]:
|
|
"""Return 0-based line indices of every top-level test boundary.
|
|
|
|
Screen tests are often a flat list of `testWidgets(` calls with no
|
|
`group(` at all, so both count as a split point.
|
|
"""
|
|
return [
|
|
i
|
|
for i, ln in enumerate(lines)
|
|
if re.match(r"^ (group|testWidgets|test)\(", ln)
|
|
]
|
|
|
|
|
|
def split(path: Path, specs: list[tuple[Path, int]]) -> None:
|
|
"""Write each spec's group range to its own file, trimming the source."""
|
|
lines = path.read_text(encoding="utf-8").splitlines(keepends=True)
|
|
groups = top_level_groups(lines)
|
|
main_idx = next(i for i, ln in enumerate(lines) if ln.startswith("void main("))
|
|
header = "".join(lines[:main_idx])
|
|
preamble = "".join(lines[main_idx + 1 : groups[0]])
|
|
|
|
# Fixtures and fake classes often sit AFTER main(). Every split file needs
|
|
# them too, or it fails to compile on a helper the original defined once.
|
|
main_end = next(
|
|
(i for i in range(len(lines) - 1, main_idx, -1) if lines[i].startswith("}")),
|
|
len(lines) - 1,
|
|
)
|
|
trailer = "".join(lines[main_end + 1 :])
|
|
|
|
ends = [i for _, i in specs[1:]] + [len(groups)]
|
|
for (out, start), end in zip(specs, ends, strict=True):
|
|
last = groups[end] if end < len(groups) else main_end
|
|
body = "".join(lines[groups[start] : last]).rstrip("\n")
|
|
out.write_text(
|
|
f"{header}void main() {{\n{preamble}{body}\n}}\n{trailer}", encoding="utf-8"
|
|
)
|
|
|
|
path.write_text(
|
|
"".join(lines[: groups[specs[0][1]]]).rstrip("\n") + "\n}\n" + trailer,
|
|
encoding="utf-8",
|
|
)
|
|
|
|
|
|
def main() -> int:
|
|
"""Parse argv and run the split."""
|
|
src = Path(sys.argv[1])
|
|
specs = []
|
|
for arg in sys.argv[2:]:
|
|
name, idx = arg.rsplit(":", 1)
|
|
specs.append((src.parent / name, int(idx)))
|
|
split(src, specs)
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|