#!/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)