Repository Validate / repository-checks (push) Successful in 21s
Co-authored-by: AI Tester <ai-tester@git.p2prod.ru>
93 lines
3.5 KiB
Python
93 lines
3.5 KiB
Python
"""Keep README.md synchronized with the delivered CLI contract.
|
|
|
|
The documentation is part of the product: the calling agent relies on the
|
|
parameter list, the status vocabulary and the exit codes stated in README.md.
|
|
These checks fail when the implementation moves on and the documentation is
|
|
left describing something the tool no longer does.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
|
|
from tools.envelope import STATUS_EXIT_CODES
|
|
from tools.errors import ACCEPTED_FORMATS
|
|
from tools.example import build_parser
|
|
from tools.sources import default_registry
|
|
|
|
README = Path(__file__).resolve().parent.parent / "README.md"
|
|
|
|
|
|
def readme_text() -> str:
|
|
assert README.is_file(), "README.md is missing"
|
|
text = README.read_text(encoding="utf-8")
|
|
assert text.strip(), "README.md is empty"
|
|
return text
|
|
|
|
|
|
def long_options() -> list[str]:
|
|
"""Return every ``--long`` option the real parser accepts."""
|
|
|
|
options: list[str] = []
|
|
for action in build_parser()._actions:
|
|
for option in action.option_strings:
|
|
if option.startswith("--"):
|
|
options.append(option)
|
|
return sorted(set(options))
|
|
|
|
|
|
def test_readme_documents_every_cli_parameter() -> None:
|
|
text = readme_text()
|
|
options = long_options()
|
|
assert {"--topic", "--width", "--height", "--format", "--source", "--count",
|
|
"--download", "--output-dir", "--resize", "--dry-run"} <= set(options)
|
|
missing = [option for option in options if option == "--help" and option not in text]
|
|
missing += [
|
|
option
|
|
for option in options
|
|
if option != "--help" and f"`{option}" not in text
|
|
]
|
|
assert not missing, f"README.md does not document parameters: {missing}"
|
|
# The positional request document and both invocation styles are documented.
|
|
assert "REQUEST.json" in text
|
|
assert "python -m tools.example examples/input.json" in text
|
|
# Format vocabulary in the README matches the accepted formats.
|
|
for image_format in ACCEPTED_FORMATS:
|
|
assert image_format in text
|
|
|
|
|
|
def test_readme_status_table_matches_exit_codes() -> None:
|
|
text = readme_text()
|
|
for status, exit_code in STATUS_EXIT_CODES.items():
|
|
assert f"| `{status}` | {exit_code} |" in text, (
|
|
f"README.md status table disagrees for {status!r} -> {exit_code}"
|
|
)
|
|
|
|
|
|
def test_readme_documents_response_schema_and_sources() -> None:
|
|
text = readme_text()
|
|
for key in ('"status"', '"source"', '"request"', '"items"', '"error"'):
|
|
assert key in text, f"README.md does not document response key {key}"
|
|
for source_id in default_registry().available_sources():
|
|
assert source_id in text, f"README.md does not document source {source_id!r}"
|
|
assert "SourceAdapter" in text and "SourceRegistry" in text
|
|
assert "API key" in text
|
|
|
|
|
|
def test_readme_documents_product_decisions() -> None:
|
|
text = readme_text()
|
|
# --download without --output-dir is an invalid request.
|
|
assert "--download" in text and "without `--output-dir` is an invalid request" in text
|
|
# Partial saves have their own status.
|
|
assert "partial_download" in text
|
|
assert "invalid_request" in text
|
|
# Native process only: no Docker or container packaging.
|
|
assert "Docker" in text and "container" in text
|
|
|
|
|
|
def test_readme_documents_the_real_test_entrypoint() -> None:
|
|
text = readme_text()
|
|
assert "\npytest\n" in text, "README.md must document the real pytest entrypoint"
|
|
assert "python -m compileall tools tests" in text
|
|
assert "python -m tools.example --help" in text
|