This is an automated email from the ASF dual-hosted git repository.
sbp pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tooling-releases-client.git
The following commit(s) were added to refs/heads/main by this push:
new 24bb671 Add transcript testing
24bb671 is described below
commit 24bb671f3358e68fd2ddb48068fc7e57a87986ca
Author: Sean B. Palmer <[email protected]>
AuthorDate: Thu Jul 10 15:28:35 2025 +0100
Add transcript testing
---
pyproject.toml | 4 ++--
src/atrclient/client.py | 29 +++++++++++++++++++++++++----
tests/cli_version.t | 2 ++
tests/test_all.py | 37 +++++++++++++++++++++++++++++++++++++
uv.lock | 4 ++--
5 files changed, 68 insertions(+), 8 deletions(-)
diff --git a/pyproject.toml b/pyproject.toml
index 1c45dc6..2826c92 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -11,7 +11,7 @@ build-backend = "hatchling.build"
[project]
name = "apache-trusted-releases"
-version = "0.20250710.1345"
+version = "0.20250710.1426"
description = "ATR CLI and Python API"
readme = "README.md"
requires-python = ">=3.13"
@@ -48,4 +48,4 @@ atr = "atrclient.client:main"
packages = ["src/atrclient"]
[tool.uv]
-exclude-newer = "2025-07-10T13:45:00Z"
+exclude-newer = "2025-07-10T14:26:00Z"
diff --git a/src/atrclient/client.py b/src/atrclient/client.py
index 6f67f7e..3a0b88f 100755
--- a/src/atrclient/client.py
+++ b/src/atrclient/client.py
@@ -197,6 +197,17 @@ def app_dev_stamp() -> None:
)
LOGGER.info("Updated version." if version_updated else "Did not update
version.")
+ path = pathlib.Path("tests/cli_version.t")
+ if not path.exists():
+ LOGGER.warning("tests/cli_version.t not found.")
+ return
+ text_v1 = path.read_text(encoding="utf-8")
+ text_v2 = re.sub(r"0\.\d{8}\.\d{4}", v, text_v1)
+ version_updated = not (text_v1 == text_v2)
+ if version_updated:
+ path.write_text(text_v2, "utf-8")
+ LOGGER.info("Updated tests/cli_version.t.")
+
@APP.command(name="docs", help="Show comprehensive CLI documentation in
Markdown.")
def app_docs() -> None:
@@ -683,6 +694,18 @@ def documentation_to_markdown(
return markdown
+def initialise() -> None:
+ # We do this because pytest_console_scripts.ScriptRunner invokes main
multiple times
+ APP.version = VERSION
+ signal.signal(signal.SIGPIPE, signal.SIG_DFL)
+ logging.basicConfig(level=logging.INFO, format="%(message)s")
+ subcommands_register(APP)
+
+
+def initialised() -> bool:
+ return APP.version == VERSION
+
+
def iso_to_human(ts: str) -> str:
dt = datetime.datetime.fromisoformat(ts.rstrip("Z"))
if dt.tzinfo is None:
@@ -691,10 +714,8 @@ def iso_to_human(ts: str) -> str:
def main() -> None:
- signal.signal(signal.SIGPIPE, signal.SIG_DFL)
- logging.basicConfig(level=logging.INFO, format="%(message)s")
- subcommands_register(APP)
- APP.version = VERSION
+ if not initialised():
+ initialise()
# if "PYTEST_CURRENT_TEST" in os.environ:
# # "Cyclopts application invoked without tokens"
# pass
diff --git a/tests/cli_version.t b/tests/cli_version.t
new file mode 100644
index 0000000..2fb95e8
--- /dev/null
+++ b/tests/cli_version.t
@@ -0,0 +1,2 @@
+$ atr --version
+0.20250710.1426
diff --git a/tests/test_all.py b/tests/test_all.py
index 16119f3..83bcaad 100755
--- a/tests/test_all.py
+++ b/tests/test_all.py
@@ -18,6 +18,7 @@
# TODO: Use transcript style script testing
from __future__ import annotations
+import shlex
import atrclient.client as client
import pathlib
@@ -28,6 +29,12 @@ import pytest
import pytest_console_scripts
+def decorator_transcript_file_paths() -> list[pathlib.Path]:
+ parent = pathlib.Path(__file__).parent
+ paths = list(parent.glob("*.t"))
+ return paths
+
+
def test_app_checks_status_non_draft_phase(
capsys: pytest.CaptureFixture[str], fixture_config_env: pathlib.Path
) -> None:
@@ -182,6 +189,36 @@ def test_cli_version(script_runner:
pytest_console_scripts.ScriptRunner) -> None
assert result.stderr == ""
[email protected](
+ "transcript_path", decorator_transcript_file_paths(), ids=lambda p: p.name
+)
+def test_cli_transcripts(
+ transcript_path: pathlib.Path, script_runner:
pytest_console_scripts.ScriptRunner
+) -> None:
+ with open(transcript_path, "r", encoding="utf-8") as f:
+ actual_stdout = []
+ for line in f:
+ line = line.rstrip("\n")
+ if line.startswith("$ ") or line.startswith("! "):
+ expected_code = 0 if line.startswith("$ ") else 1
+ command = line[2:]
+ if not command.startswith("atr"):
+ pytest.fail(f"Command does not start with 'atr':
{command}")
+ return
+ result = script_runner.run(shlex.split(command))
+ assert result.returncode == expected_code
+ actual_stdout[:] = result.stdout.splitlines()
+ elif actual_stdout:
+ actual_stdout_line = actual_stdout.pop(0)
+ if actual_stdout_line != line:
+ pytest.fail(f"Expected {line!r} but got
{actual_stdout_line!r}")
+ return
+ elif line:
+ pytest.fail(f"Unexpected line: {line!r}")
+ return
+ assert not actual_stdout
+
+
def test_config_set_get_roundtrip() -> None:
config: dict[str, Any] = {}
client.config_set(config, ["abc", "pqr"], 123)
diff --git a/uv.lock b/uv.lock
index bbb5e38..5e59bf5 100644
--- a/uv.lock
+++ b/uv.lock
@@ -2,7 +2,7 @@ version = 1
requires-python = ">=3.13"
[options]
-exclude-newer = "2025-07-10T13:45:00Z"
+exclude-newer = "2025-07-10T14:26:00Z"
[[package]]
name = "aiohappyeyeballs"
@@ -74,7 +74,7 @@ wheels = [
[[package]]
name = "apache-trusted-releases"
-version = "0.20250710.1345"
+version = "0.20250710.1426"
source = { editable = "." }
dependencies = [
{ name = "aiohttp" },
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]