uv/scripts/scenarios/update.py
Zanie Blue 0d5252580c
Improve scenario update script (#759)
Following #757, improves the script for generating scenario test cases
with:

- A requirements file
- Support for downloading packse scenarios from GitHub dynamically
- Running rustfmt on the generated test file
- Updating snapshots / running tests
2024-01-03 20:13:11 -06:00

143 lines
3.7 KiB
Python
Executable file

#!/usr/bin/env python3
#
# Generates and updates snapshot test cases from packse scenarios.
#
# Usage:
#
# $ scripts/scenarios/update.py
#
# Requirements:
#
# Requires `packse` and `chevron-blue`.
#
# $ pip install -r scripts/scenarios/requirements.txt
#
# Also supports a local, editable requirement on `packse`.
#
# Uses `git`, `rustfmt`, and `cargo insta test` requirements from the project.
import json
import shutil
import subprocess
import sys
from pathlib import Path
TOOL_ROOT = Path(__file__).parent
TEMPLATE = TOOL_ROOT / "template.mustache"
PACKSE = TOOL_ROOT / "packse-scenarios"
REQUIREMENTS = TOOL_ROOT / "requirements.txt"
PROJECT_ROOT = TOOL_ROOT.parent.parent
TARGET = PROJECT_ROOT / "crates" / "puffin-cli" / "tests" / "pip_install_scenarios.rs"
try:
import packse
except ImportError:
print(
f"missing requirement `packse`: install the requirements at {REQUIREMENTS.relative_to(PROJECT_ROOT)}",
file=sys.stderr,
)
exit(1)
try:
import chevron_blue
except ImportError:
print(
f"missing requirement `chevron-blue`: install the requirements at {REQUIREMENTS.relative_to(PROJECT_ROOT)}",
file=sys.stderr,
)
exit(1)
if packse.__development_base_path__.name != "packse":
# Not a local editable installation, download latest scenarios
if PACKSE.exists():
shutil.rmtree(PACKSE)
print("Downloading scenarios from packse repository...", file=sys.stderr)
# Perform a sparse checkout where we only grab the `scenarios` folder
subprocess.check_call(
[
"git",
"clone",
"-n",
"--depth=1",
"--filter=tree:0",
"https://github.com/zanieb/packse",
str(PACKSE),
],
cwd=TOOL_ROOT,
stdout=subprocess.DEVNULL,
stderr=subprocess.STDOUT,
)
subprocess.check_call(
["git", "sparse-checkout", "set", "--no-cone", "scenarios"],
cwd=PACKSE,
stdout=subprocess.DEVNULL,
stderr=subprocess.STDOUT,
)
subprocess.check_call(
["git", "checkout"],
cwd=PACKSE,
stdout=subprocess.DEVNULL,
stderr=subprocess.STDOUT,
)
scenarios_path = str(PACKSE / "scenarios")
else:
print("Using local packse scenarios...", file=sys.stderr)
scenarios_path = str(packse.__development_base_path__ / "scenarios")
print("Loading scenario metadata...", file=sys.stderr)
data = json.loads(
subprocess.check_output(
[
"packse",
"inspect",
scenarios_path,
],
)
)
# Add a generated note
data["generated_by"] = f"Generated by `{' '.join(sys.argv)}`"
# Add normalized names for tests
for scenario in data["scenarios"]:
scenario["normalized_name"] = scenario["name"].replace("-", "_")
# Drop the example scenario
for index, scenario in enumerate(data["scenarios"]):
if scenario["name"] == "example":
data["scenarios"].pop(index)
# Render the template
print("Rendering template...", file=sys.stderr)
output = chevron_blue.render(template=TEMPLATE.read_text(), data=data, no_escape=True)
# Update the test file
print(f"Updating test file at `{TARGET.relative_to(PROJECT_ROOT)}`...", file=sys.stderr)
with open(TARGET, "wt") as target_file:
target_file.write(output)
# Format
print("Formatting test file...", file=sys.stderr)
subprocess.check_call(["rustfmt", str(TARGET)])
# Update snapshots
print("Updating snapshots...\n", file=sys.stderr)
subprocess.call(
[
"cargo",
"insta",
"test",
"--accept",
"--test",
TARGET.with_suffix("").name,
"--features",
"pypi,python",
],
cwd=PROJECT_ROOT,
)
print("\nDone!", file=sys.stderr)