blob: 1f8fe6eecc843b9199d55c401cef1e3dc5851180 [file] [log] [blame] [edit]
#!/usr/bin/env -S uv run --script
#
# /// script
# requires-python = ">=3.11"
# dependencies = ["mypy-primer"]
#
# [tool.uv.sources]
# mypy-primer = { git = "https://github.com/hauntsaninja/mypy_primer" }
# ///
"""Clone a mypy-primer project and set up a virtualenv with its dependencies installed.
Usage: uv run scripts/setup_primer_project.py <project-name> [directory]
"""
from __future__ import annotations
import argparse
import shlex
import subprocess
import sys
from pathlib import Path
from typing import NoReturn
from mypy_primer.model import Project
from mypy_primer.projects import get_projects
def find_project(name: str) -> Project:
projects = get_projects()
for p in projects:
if p.name == name:
return p
_project_not_found(name, projects)
def _project_not_found(name: str, projects: list[Project]) -> NoReturn:
print(f"error: project {name!r} not found", file=sys.stderr)
print("available projects:", file=sys.stderr)
for p in sorted(projects, key=lambda p: p.name):
print(f" {p.name}", file=sys.stderr)
sys.exit(1)
def main() -> None:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("project", help="Name of a mypy-primer project")
parser.add_argument(
"directory",
nargs="?",
help="Directory to clone into (default: project name)",
)
args = parser.parse_args()
project = find_project(args.project)
target_dir = Path(args.directory or project.name).resolve()
# Clone (shallow if no pinned revision, same as primer)
clone_cmd = [
"git",
"clone",
"--recurse-submodules",
project.location,
str(target_dir),
]
if not project.revision:
clone_cmd += ["--depth", "1"]
print(f"Cloning {project.location} into {target_dir}...")
subprocess.run(clone_cmd, check=True)
if project.revision:
print(f"Checking out revision {project.revision}...")
subprocess.run(
["git", "checkout", project.revision], cwd=target_dir, check=True
)
# Create venv (matching primer's Venv.make_venv())
venv_dir = target_dir / ".venv"
print(f"Creating virtualenv at {venv_dir}...")
subprocess.run(
["uv", "venv", str(venv_dir), "--python", sys.executable, "--seed", "--clear"],
check=True,
)
venv_python = venv_dir / "bin" / "python"
install_base = f"uv pip install --python {shlex.quote(str(venv_python))}"
# Run custom install command if the project defines one (matching primer's setup())
if project.install_cmd:
install_cmd = project.install_cmd.format(install=install_base)
print(f"Running install command: {install_cmd}")
subprocess.run(shlex.split(install_cmd), cwd=target_dir, check=True)
# Install listed dependencies (matching primer's setup())
if project.deps:
deps_cmd_parts = shlex.split(install_base) + project.deps
print(f"Installing dependencies: {', '.join(project.deps)}")
subprocess.run(deps_cmd_parts, cwd=target_dir, check=True)
print(f"\nDone! Project set up at {target_dir}")
print(f"Activate the venv with: source {venv_dir}/bin/activate")
if __name__ == "__main__":
main()