Skip to content

Commit 8f93cdc

Browse files
author
s
committed
Parse placeholder Wiki commands
1 parent 096569a commit 8f93cdc

2 files changed

Lines changed: 78 additions & 14 deletions

File tree

ci/run_wiki_acceptance.py

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -382,8 +382,21 @@ def _grammar_arguments(command: DocumentedCommand) -> list[str]:
382382
"[MODULE]": "example",
383383
"<module-name>": "example",
384384
}
385-
arguments = [values.get(value, value) for value in command.argv[1:]]
386-
return [value for value in arguments if value != "[options]"]
385+
arguments: list[str] = []
386+
for value in command.argv[1:]:
387+
if value == "[options]":
388+
continue
389+
if PLACEHOLDER.search(value):
390+
replacement = values.get(value)
391+
if replacement is None:
392+
raise ValueError(
393+
f"{command.source}:{command.line}: unsupported documented "
394+
f"placeholder: {value}"
395+
)
396+
arguments.append(replacement)
397+
else:
398+
arguments.append(value)
399+
return arguments
387400

388401

389402
def audit_commands(
@@ -404,13 +417,11 @@ def audit_commands(
404417
raise ValueError(
405418
f"{command.source}:{command.line}: classified record lacks gate or reason"
406419
)
407-
if (
408-
command.classification == "placeholder"
409-
or not command.argv
410-
or command.argv[0] != "sn-module-gen"
411-
):
420+
if not command.argv or command.argv[0] != "sn-module-gen":
412421
continue
413422
parse_arguments(_grammar_arguments(command))
423+
if command.classification == "placeholder":
424+
continue
414425
if command.execution_gate == "documentation-smoke":
415426
subprocess.run(
416427
(generator_command, *command.argv[1:]),

tests/test_release_qualification.py

Lines changed: 60 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
import pytest
1010

11+
import ci.run_wiki_acceptance as wiki_acceptance
1112
from supernote_module_generator import __version__
1213
from ci.materialize_readme_examples import materialize, read_examples
1314
from ci.run_wiki_acceptance import (
@@ -24,6 +25,7 @@
2425
from supernote_module_generator.arguments import parse_arguments
2526
from supernote_module_generator.feature_generator import FeatureConfig, stage_feature
2627
from supernote_module_generator.feature_model import StarterFamily
28+
from supernote_module_generator.errors import ConfigurationError
2729
from supernote_module_generator.helptext import COMMAND_HELP
2830

2931

@@ -379,12 +381,8 @@ def test_every_readme_and_wiki_command_output_record_is_source_classified(
379381
if record.classification in {"explanatory_output", "placeholder"}
380382
)
381383
for record in records:
382-
if (
383-
record.argv
384-
and record.argv[0] == "sn-module-gen"
385-
and record.classification != "placeholder"
386-
):
387-
parse_arguments(list(record.argv[1:]))
384+
if record.argv and record.argv[0] == "sn-module-gen":
385+
parse_arguments(wiki_acceptance._grammar_arguments(record))
388386

389387
by_source_and_text = {(record.source, record.text): record for record in records}
390388
expected = {
@@ -428,6 +426,7 @@ def test_every_readme_and_wiki_command_output_record_is_source_classified(
428426

429427
def test_pinned_wiki_audit_inventories_commands_and_explanatory_output(
430428
tmp_path: Path,
429+
monkeypatch: pytest.MonkeyPatch,
431430
) -> None:
432431
bundle = ROOT / "ci/fixtures/supernote-module-generator-wiki.bundle"
433432
wiki = tmp_path / "wiki"
@@ -452,7 +451,15 @@ def test_pinned_wiki_audit_inventories_commands_and_explanatory_output(
452451
encoding="utf-8",
453452
)
454453
generator.chmod(0o755)
455-
audit_commands(wiki, ROOT / "README.md", str(generator), output)
454+
parsed_arguments: list[tuple[str, ...]] = []
455+
original_parse_arguments = wiki_acceptance.parse_arguments
456+
457+
def tracked_parse_arguments(arguments: list[str]):
458+
parsed_arguments.append(tuple(arguments))
459+
return original_parse_arguments(arguments)
460+
461+
monkeypatch.setattr(wiki_acceptance, "parse_arguments", tracked_parse_arguments)
462+
audited_records = audit_commands(wiki, ROOT / "README.md", str(generator), output)
456463
manifest = json.loads(output.read_text(encoding="utf-8"))
457464
assert manifest["schema_version"] == "1.1"
458465
assert manifest["record_count"] == len(manifest["records"])
@@ -464,6 +471,27 @@ def test_pinned_wiki_audit_inventories_commands_and_explanatory_output(
464471
record["classification"] == "explanatory_output"
465472
for record in manifest["records"]
466473
)
474+
placeholders = [
475+
record
476+
for record in audited_records
477+
if record.classification == "placeholder"
478+
and record.argv[:1] == ("sn-module-gen",)
479+
]
480+
assert {(record.source, record.text) for record in placeholders} == {
481+
(
482+
"Error-Handling.md",
483+
"sn-module-gen validate <module-name> --build --verbose",
484+
),
485+
("Using-the-CLI.md", "sn-module-gen add [PACKAGE] [options]"),
486+
("Using-the-CLI.md", "sn-module-gen update [FEATURE] [options]"),
487+
("Using-the-CLI.md", "sn-module-gen validate [FEATURE] [options]"),
488+
("Using-the-CLI.md", "sn-module-gen validate --all [options]"),
489+
("Using-the-CLI.md", "sn-module-gen remove [FEATURE] [options]"),
490+
("Using-the-CLI.md", "sn-module-gen remove --all [options]"),
491+
}
492+
assert {
493+
tuple(wiki_acceptance._grammar_arguments(record)) for record in placeholders
494+
} <= set(parsed_arguments)
467495

468496

469497
def test_pinned_wiki_doctor_adb_claim_matches_source_and_installed_help(
@@ -574,6 +602,31 @@ def test_wiki_acceptance_commands_are_bounded_and_source_backed(tmp_path: Path)
574602
with pytest.raises(ValueError, match="unclassified bash fenced command"):
575603
scan_documented_commands([page])
576604

605+
wiki = tmp_path / "invalid-wiki"
606+
wiki.mkdir()
607+
readme = tmp_path / "empty-readme.md"
608+
readme.write_text("# Readme\n", encoding="utf-8")
609+
invalid = wiki / "Invalid.md"
610+
invalid.write_text(
611+
"# Invalid placeholder command\n\n"
612+
"```bash\n"
613+
"sn-module-gen validate <module-name> --definitely-invalid\n"
614+
"```\n",
615+
encoding="utf-8",
616+
)
617+
with pytest.raises(ConfigurationError, match='unknown option "--definitely-invalid"'):
618+
audit_commands(wiki, readme, "unused-generator", tmp_path / "invalid.json")
619+
620+
invalid.write_text(
621+
"# Unsupported placeholder\n\n"
622+
"```bash\n"
623+
"sn-module-gen validate <unknown-module>\n"
624+
"```\n",
625+
encoding="utf-8",
626+
)
627+
with pytest.raises(ValueError, match="unsupported documented placeholder"):
628+
audit_commands(wiki, readme, "unused-generator", tmp_path / "invalid.json")
629+
577630

578631
def test_template_launch_contract_and_fake_device_harness(tmp_path: Path) -> None:
579632
template = tmp_path / "template"

0 commit comments

Comments
 (0)