mirror of
https://github.com/langchain-ai/markdown-exec.git
synced 2026-07-01 18:25:52 -04:00
204 lines
6.7 KiB
Python
Executable File
204 lines
6.7 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""Management commands."""
|
|
|
|
import os
|
|
import shutil
|
|
import subprocess
|
|
import sys
|
|
from contextlib import contextmanager
|
|
from pathlib import Path
|
|
from typing import Any, Iterator
|
|
|
|
PYTHON_VERSIONS = os.getenv("PYTHON_VERSIONS", "3.8 3.9 3.10 3.11 3.12 3.13").split()
|
|
|
|
exe = ""
|
|
prefix = ""
|
|
|
|
|
|
def shell(cmd: str) -> None:
|
|
"""Run a shell command."""
|
|
subprocess.run(cmd, shell=True, check=True) # noqa: S602
|
|
|
|
|
|
@contextmanager
|
|
def environ(**kwargs: str) -> Iterator[None]:
|
|
"""Temporarily set environment variables."""
|
|
original = dict(os.environ)
|
|
os.environ.update(kwargs)
|
|
try:
|
|
yield
|
|
finally:
|
|
os.environ.clear()
|
|
os.environ.update(original)
|
|
|
|
|
|
def uv_install() -> None:
|
|
"""Install dependencies using uv."""
|
|
uv_opts = ""
|
|
if "UV_RESOLUTION" in os.environ:
|
|
uv_opts = f"--resolution={os.getenv('UV_RESOLUTION')}"
|
|
cmd = f"uv pip compile {uv_opts} --all-extras pyproject.toml devdeps.txt | uv pip install -r -"
|
|
shell(cmd)
|
|
if "CI" not in os.environ:
|
|
shell("uv pip install --no-deps -e .")
|
|
else:
|
|
shell("uv pip install --no-deps .")
|
|
|
|
|
|
def setup() -> None:
|
|
"""Setup the project."""
|
|
if not shutil.which("uv"):
|
|
raise ValueError("make: setup: uv must be installed, see https://github.com/astral-sh/uv")
|
|
|
|
print("Installing dependencies (default environment)") # noqa: T201
|
|
default_venv = Path(".venv")
|
|
if not default_venv.exists():
|
|
shell("uv venv --python python")
|
|
uv_install()
|
|
|
|
if PYTHON_VERSIONS:
|
|
for version in PYTHON_VERSIONS:
|
|
print(f"\nInstalling dependencies (python{version})") # noqa: T201
|
|
venv_path = Path(f".venvs/{version}")
|
|
if not venv_path.exists():
|
|
shell(f"uv venv --python {version} {venv_path}")
|
|
with environ(VIRTUAL_ENV=str(venv_path.resolve())):
|
|
uv_install()
|
|
|
|
|
|
def activate(path: str) -> None:
|
|
"""Activate a virtual environment."""
|
|
global exe, prefix # noqa: PLW0603
|
|
|
|
if (bin := Path(path, "bin")).exists():
|
|
activate_script = bin / "activate_this.py"
|
|
elif (scripts := Path(path, "Scripts")).exists():
|
|
activate_script = scripts / "activate_this.py"
|
|
exe = ".exe"
|
|
prefix = f"{path}/Scripts/"
|
|
else:
|
|
raise ValueError(f"make: activate: Cannot find activation script in {path}")
|
|
|
|
if not activate_script.exists():
|
|
raise ValueError(f"make: activate: Cannot find activation script in {path}")
|
|
|
|
exec(activate_script.read_text(), {"__file__": str(activate_script)}) # noqa: S102
|
|
|
|
|
|
def run(version: str, cmd: str, *args: str, **kwargs: Any) -> None:
|
|
"""Run a command in a virtual environment."""
|
|
kwargs = {"check": True, **kwargs}
|
|
if version == "default":
|
|
activate(".venv")
|
|
subprocess.run([f"{prefix}{cmd}{exe}", *args], **kwargs) # noqa: S603, PLW1510
|
|
else:
|
|
activate(f".venvs/{version}")
|
|
os.environ["MULTIRUN"] = "1"
|
|
subprocess.run([f"{prefix}{cmd}{exe}", *args], **kwargs) # noqa: S603, PLW1510
|
|
|
|
|
|
def multirun(cmd: str, *args: str, **kwargs: Any) -> None:
|
|
"""Run a command for all configured Python versions."""
|
|
if PYTHON_VERSIONS:
|
|
for version in PYTHON_VERSIONS:
|
|
run(version, cmd, *args, **kwargs)
|
|
else:
|
|
run("default", cmd, *args, **kwargs)
|
|
|
|
|
|
def allrun(cmd: str, *args: str, **kwargs: Any) -> None:
|
|
"""Run a command in all virtual environments."""
|
|
run("default", cmd, *args, **kwargs)
|
|
if PYTHON_VERSIONS:
|
|
multirun(cmd, *args, **kwargs)
|
|
|
|
|
|
def clean() -> None:
|
|
"""Delete build artifacts and cache files."""
|
|
paths_to_clean = ["build", "dist", "htmlcov", "site", ".coverage*", ".pdm-build"]
|
|
for path in paths_to_clean:
|
|
shell(f"rm -rf {path}")
|
|
|
|
cache_dirs = [".cache", ".pytest_cache", ".mypy_cache", ".ruff_cache", "__pycache__"]
|
|
for dirpath in Path(".").rglob("*"):
|
|
if any(dirpath.match(pattern) for pattern in cache_dirs) and not (dirpath.match(".venv") or dirpath.match(".venvs")):
|
|
shutil.rmtree(path, ignore_errors=True)
|
|
|
|
|
|
def vscode() -> None:
|
|
"""Configure VSCode to work on this project."""
|
|
Path(".vscode").mkdir(parents=True, exist_ok=True)
|
|
shell("cp -v config/vscode/* .vscode")
|
|
|
|
|
|
def main() -> int:
|
|
"""Main entry point."""
|
|
args = list(sys.argv[1:])
|
|
if not args or args[0] == "help":
|
|
if len(args) > 1:
|
|
run("default", "duty", "--help", args[1])
|
|
else:
|
|
print("Available commands") # noqa: T201
|
|
print(" help Print this help. Add task name to print help.") # noqa: T201
|
|
print(" setup Setup all virtual environments (install dependencies).") # noqa: T201
|
|
print(" run Run a command in the default virtual environment.") # noqa: T201
|
|
print(" multirun Run a command for all configured Python versions.") # noqa: T201
|
|
print(" allrun Run a command in all virtual environments.") # noqa: T201
|
|
print(" 3.x Run a command in the virtual environment for Python 3.x.") # noqa: T201
|
|
print(" clean Delete build artifacts and cache files.") # noqa: T201
|
|
print(" vscode Configure VSCode to work on this project.") # noqa: T201
|
|
try:
|
|
run("default", "python", "-V", capture_output=True)
|
|
except (subprocess.CalledProcessError, ValueError):
|
|
pass
|
|
else:
|
|
print("\nAvailable tasks") # noqa: T201
|
|
run("default", "duty", "--list")
|
|
return 0
|
|
|
|
while args:
|
|
cmd = args.pop(0)
|
|
|
|
if cmd == "run":
|
|
run("default", *args)
|
|
return 0
|
|
|
|
if cmd == "multirun":
|
|
multirun(*args)
|
|
return 0
|
|
|
|
if cmd == "allrun":
|
|
allrun(*args)
|
|
return 0
|
|
|
|
if cmd.startswith("3."):
|
|
run(cmd, *args)
|
|
return 0
|
|
|
|
opts = []
|
|
while args and (args[0].startswith("-") or "=" in args[0]):
|
|
opts.append(args.pop(0))
|
|
|
|
if cmd == "clean":
|
|
clean()
|
|
elif cmd == "setup":
|
|
setup()
|
|
elif cmd == "vscode":
|
|
vscode()
|
|
elif cmd == "check":
|
|
multirun("duty", "check-quality", "check-types", "check-docs")
|
|
run("default", "duty", "check-api")
|
|
elif cmd in {"check-quality", "check-docs", "check-types", "test"}:
|
|
multirun("duty", cmd, *opts)
|
|
else:
|
|
run("default", "duty", cmd, *opts)
|
|
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
try:
|
|
sys.exit(main())
|
|
except Exception: # noqa: BLE001
|
|
sys.exit(1)
|