Skip to content

Commit 106fb48

Browse files
committed
refactor: extract CLI argv normalization
1 parent 130bd0d commit 106fb48

3 files changed

Lines changed: 146 additions & 61 deletions

File tree

tests/test_cli_config.py

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
from __future__ import annotations
2+
3+
import pytest
4+
5+
from typetreeflow import cli
6+
from typetreeflow.cli_config import _normalize_command_argv as config_normalize_argv
7+
8+
9+
def test_cli_normalize_command_argv_compatibility_export():
10+
assert cli._normalize_command_argv is config_normalize_argv
11+
12+
13+
def test_normalize_command_aliases_preserves_existing_rewrites():
14+
assert config_normalize_argv(["doctor", "--strict"]) == (
15+
["--doctor", "--doctor-strict"],
16+
False,
17+
False,
18+
)
19+
assert config_normalize_argv(["status", "--outdir", "out"]) == (
20+
["--status", "--outdir", "out"],
21+
False,
22+
False,
23+
)
24+
assert config_normalize_argv(["next-step", "--json"]) == (
25+
["--next-step", "--json"],
26+
False,
27+
False,
28+
)
29+
assert config_normalize_argv(["package-results", "--include", "reports"]) == (
30+
["--package-results", "--include", "reports"],
31+
False,
32+
True,
33+
)
34+
35+
36+
def test_normalize_verify_genus_aliases_policy_and_biosample_entrez():
37+
assert config_normalize_argv(
38+
[
39+
"verify-genus",
40+
"Fusobacterium",
41+
"--policy",
42+
"balanced",
43+
"--enable-biosample-entrez",
44+
]
45+
) == (
46+
[
47+
"--acquire-genus",
48+
"Fusobacterium",
49+
"--dry-run",
50+
"--selection-policy",
51+
"balanced",
52+
"--enrich-biosample",
53+
"--enable-biosample-entrez",
54+
],
55+
True,
56+
False,
57+
)
58+
59+
60+
def test_parse_args_handles_doctor_version_and_common_flags(tmp_path):
61+
doctor_config = cli.parse_args(["doctor", "--strict", "--outdir", str(tmp_path)])
62+
assert doctor_config.doctor is True
63+
assert doctor_config.doctor_strict is True
64+
65+
with pytest.raises(SystemExit) as excinfo:
66+
cli.parse_args(["--version"])
67+
assert excinfo.value.code == 0
68+
69+
config = cli.parse_args(
70+
[
71+
"verify-genus",
72+
"Aliivibrio",
73+
"--policy=balanced",
74+
"--outdir",
75+
str(tmp_path / "verify"),
76+
]
77+
)
78+
assert config.verify_genus is True
79+
assert config.acquire_genus == "Aliivibrio"
80+
assert config.dry_run is True
81+
assert config.selection_policy == "balanced"

typetreeflow/cli.py

Lines changed: 2 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,9 @@
1616
write_completion_summary,
1717
)
1818
from typetreeflow.completion_gaps import generate_completion_gap_reports
19-
from typetreeflow.config import AppConfig, ensure_real_action_allowed
19+
from typetreeflow.cli_config import _normalize_command_argv
2020
from typetreeflow.cli_parser import build_parser
21+
from typetreeflow.config import AppConfig, ensure_real_action_allowed
2122
from typetreeflow.delivery import package_results
2223
from typetreeflow.diagnostics import (
2324
build_doctor_report,
@@ -316,66 +317,6 @@ def parse_args(argv: list[str] | None = None) -> AppConfig:
316317
)
317318

318319

319-
def _normalize_command_argv(
320-
argv: list[str] | None,
321-
) -> tuple[list[str] | None, bool, bool]:
322-
raw_argv = list(sys.argv[1:] if argv is None else argv)
323-
if raw_argv and raw_argv[0] == "doctor":
324-
normalized = ["--doctor"]
325-
for item in raw_argv[1:]:
326-
if item == "--strict":
327-
normalized.append("--doctor-strict")
328-
else:
329-
normalized.append(item)
330-
return normalized, False, False
331-
if raw_argv and raw_argv[0] == "status":
332-
return ["--status", *raw_argv[1:]], False, False
333-
if raw_argv and raw_argv[0] == "next-step":
334-
return ["--next-step", *raw_argv[1:]], False, False
335-
if raw_argv and raw_argv[0] == "package-results":
336-
return ["--package-results", *raw_argv[1:]], False, True
337-
if raw_argv and raw_argv[0] == "verify-release-genus":
338-
if len(raw_argv) >= 2 and raw_argv[1] in {"-h", "--help"}:
339-
return ["--help"], False, False
340-
if len(raw_argv) < 2 or raw_argv[1].startswith("-"):
341-
raise ValueError("verify-release-genus requires a GENUS argument.")
342-
return ["--verify-release-genus", raw_argv[1], *raw_argv[2:]], False, False
343-
if not raw_argv or raw_argv[0] != "verify-genus":
344-
return argv, False, False
345-
if len(raw_argv) >= 2 and raw_argv[1] in {"-h", "--help"}:
346-
return ["--help"], False, False
347-
if len(raw_argv) < 2 or raw_argv[1].startswith("-"):
348-
raise ValueError("verify-genus requires a GENUS argument.")
349-
350-
genus = raw_argv[1]
351-
normalized = ["--acquire-genus", genus, "--dry-run"]
352-
remaining = raw_argv[2:]
353-
index = 0
354-
while index < len(remaining):
355-
item = remaining[index]
356-
if item == "--policy":
357-
normalized.append("--selection-policy")
358-
if index + 1 >= len(remaining):
359-
raise ValueError(
360-
"--policy requires one of: strict, balanced, review-only, "
361-
"representative."
362-
)
363-
normalized.append(remaining[index + 1])
364-
index += 2
365-
continue
366-
if item.startswith("--policy="):
367-
normalized.append("--selection-policy=" + item.split("=", 1)[1])
368-
index += 1
369-
continue
370-
if item == "--enable-biosample-entrez":
371-
normalized.extend(["--enrich-biosample", item])
372-
index += 1
373-
continue
374-
normalized.append(item)
375-
index += 1
376-
return normalized, True, False
377-
378-
379320
def _env_value(name: str) -> str | None:
380321
value = os.environ.get(name)
381322
if value is None:

typetreeflow/cli_config.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
from __future__ import annotations
2+
3+
import sys
4+
5+
6+
def _normalize_command_argv(
7+
argv: list[str] | None,
8+
) -> tuple[list[str] | None, bool, bool]:
9+
raw_argv = list(sys.argv[1:] if argv is None else argv)
10+
if raw_argv and raw_argv[0] == "doctor":
11+
normalized = ["--doctor"]
12+
for item in raw_argv[1:]:
13+
if item == "--strict":
14+
normalized.append("--doctor-strict")
15+
else:
16+
normalized.append(item)
17+
return normalized, False, False
18+
if raw_argv and raw_argv[0] == "status":
19+
return ["--status", *raw_argv[1:]], False, False
20+
if raw_argv and raw_argv[0] == "next-step":
21+
return ["--next-step", *raw_argv[1:]], False, False
22+
if raw_argv and raw_argv[0] == "package-results":
23+
return ["--package-results", *raw_argv[1:]], False, True
24+
if raw_argv and raw_argv[0] == "verify-release-genus":
25+
if len(raw_argv) >= 2 and raw_argv[1] in {"-h", "--help"}:
26+
return ["--help"], False, False
27+
if len(raw_argv) < 2 or raw_argv[1].startswith("-"):
28+
raise ValueError("verify-release-genus requires a GENUS argument.")
29+
return ["--verify-release-genus", raw_argv[1], *raw_argv[2:]], False, False
30+
if not raw_argv or raw_argv[0] != "verify-genus":
31+
return argv, False, False
32+
if len(raw_argv) >= 2 and raw_argv[1] in {"-h", "--help"}:
33+
return ["--help"], False, False
34+
if len(raw_argv) < 2 or raw_argv[1].startswith("-"):
35+
raise ValueError("verify-genus requires a GENUS argument.")
36+
37+
genus = raw_argv[1]
38+
normalized = ["--acquire-genus", genus, "--dry-run"]
39+
remaining = raw_argv[2:]
40+
index = 0
41+
while index < len(remaining):
42+
item = remaining[index]
43+
if item == "--policy":
44+
normalized.append("--selection-policy")
45+
if index + 1 >= len(remaining):
46+
raise ValueError(
47+
"--policy requires one of: strict, balanced, review-only, "
48+
"representative."
49+
)
50+
normalized.append(remaining[index + 1])
51+
index += 2
52+
continue
53+
if item.startswith("--policy="):
54+
normalized.append("--selection-policy=" + item.split("=", 1)[1])
55+
index += 1
56+
continue
57+
if item == "--enable-biosample-entrez":
58+
normalized.extend(["--enrich-biosample", item])
59+
index += 1
60+
continue
61+
normalized.append(item)
62+
index += 1
63+
return normalized, True, False

0 commit comments

Comments
 (0)