|
| 1 | +# action.py |
| 2 | +import os |
| 3 | +from pathlib import Path |
| 4 | +from .utils import info, die, run, require_tool, warn |
| 5 | +from .env import ( |
| 6 | + DEFAULT_PY_SPEC, |
| 7 | + DEFAULT_VENV, |
| 8 | + resolve_python, |
| 9 | + is_free_threaded, |
| 10 | + configure_uv_env, |
| 11 | +) |
| 12 | + |
| 13 | +REPO_ROOT = ( |
| 14 | + Path(os.getenv("CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY")) |
| 15 | + or Path(__file__).parent.parent.parent |
| 16 | +) |
| 17 | + |
| 18 | +if not REPO_ROOT.exists(): |
| 19 | + raise SystemExit(f"REPO_ROOT does not exist: {REPO_ROOT}") |
| 20 | +elif not str(REPO_ROOT).split("/")[-1] == "radiate": |
| 21 | + raise SystemExit(f"REPO_ROOT does not look like the radiate repo: {REPO_ROOT}") |
| 22 | + |
| 23 | +PY_DIR = REPO_ROOT / "py-radiate" |
| 24 | +PY_TESTS_DIR = PY_DIR / "tests" |
| 25 | +PY_EXAMPLES_DIR = PY_DIR / "examples" |
| 26 | + |
| 27 | + |
| 28 | +def do_clean() -> None: |
| 29 | + info("cleaning build artifacts") |
| 30 | + try: |
| 31 | + import shutil |
| 32 | + |
| 33 | + venv = PY_DIR / ".venv" |
| 34 | + examples_venv = PY_EXAMPLES_DIR / ".venv" |
| 35 | + if venv.exists(): |
| 36 | + shutil.rmtree(venv) |
| 37 | + if examples_venv.exists(): |
| 38 | + shutil.rmtree(examples_venv) |
| 39 | + |
| 40 | + # remove any .so files under radiate/ |
| 41 | + for so_file in (PY_DIR / "radiate").glob("*.so"): |
| 42 | + try: |
| 43 | + os.remove(so_file) |
| 44 | + except Exception as e: |
| 45 | + warn(f"failed to remove {so_file}: {e}") |
| 46 | + |
| 47 | + except Exception as e: |
| 48 | + die(f"failed to clean: {e}") |
| 49 | + |
| 50 | + |
| 51 | +def do_dev(py_spec: str, extra_args: list[str]) -> None: |
| 52 | + py_bin = resolve_python(py_spec) |
| 53 | + venv_dir = Path(DEFAULT_VENV) |
| 54 | + configure_uv_env(py_bin, venv_dir) |
| 55 | + |
| 56 | + # choose features by mode |
| 57 | + # feats = ["--features", "gil"] |
| 58 | + # if is_free_threaded(py_bin): |
| 59 | + # feats = ["--no-default-features", "--features", "nogil"] |
| 60 | + |
| 61 | + require_tool("uvx") |
| 62 | + cmd = [ |
| 63 | + "uvx", |
| 64 | + "--python", |
| 65 | + py_bin, |
| 66 | + "maturin", |
| 67 | + "develop", |
| 68 | + "--release", |
| 69 | + # *feats, |
| 70 | + # *extra_args, |
| 71 | + ] |
| 72 | + run(cmd, cwd=PY_DIR) |
| 73 | + |
| 74 | + |
| 75 | +def do_wheel(py_spec: str, extra_args: list[str]) -> None: |
| 76 | + py_bin = resolve_python(py_spec) |
| 77 | + venv_dir = Path(DEFAULT_VENV) |
| 78 | + configure_uv_env(py_bin, venv_dir) |
| 79 | + |
| 80 | + feats = ["--features", "gil"] |
| 81 | + if is_free_threaded(py_bin): |
| 82 | + feats = ["--no-default-features", "--features", "nogil"] |
| 83 | + |
| 84 | + require_tool("uvx") |
| 85 | + cmd = [ |
| 86 | + "uvx", |
| 87 | + "--python", |
| 88 | + py_bin, |
| 89 | + "maturin", |
| 90 | + "build", |
| 91 | + "--release", |
| 92 | + *feats, |
| 93 | + *extra_args, |
| 94 | + ] |
| 95 | + run(cmd, cwd=PY_DIR) |
| 96 | + |
| 97 | + |
| 98 | +def do_test(extra_args: list[str]) -> None: |
| 99 | + require_tool("uv") |
| 100 | + cmd = ["uv", "run", "pytest", "--benchmark-disable", *extra_args] |
| 101 | + run(cmd, cwd=PY_DIR) |
| 102 | + |
| 103 | + |
| 104 | +def resolve_example_py(arg: str) -> Path: |
| 105 | + p = Path(arg) |
| 106 | + if p.is_absolute(): |
| 107 | + return p |
| 108 | + # allow bare names like "image.py" or "image" |
| 109 | + if "/" in arg or "\\" in arg: |
| 110 | + return ( |
| 111 | + (PY_DIR / "examples" / arg).with_suffix(".py") |
| 112 | + if not arg.endswith(".py") |
| 113 | + else (PY_DIR / "examples" / arg) |
| 114 | + ) |
| 115 | + return PY_DIR / "examples" / (arg if arg.endswith(".py") else f"{arg}.py") |
| 116 | + |
| 117 | + |
| 118 | +def do_example(example: str, extra_args: list[str]) -> None: |
| 119 | + target = resolve_example_py(example) |
| 120 | + if not target.exists(): |
| 121 | + die(f"Python example not found: {target}") |
| 122 | + require_tool("uv") |
| 123 | + run(["uv", "sync", "--group", "dev"], cwd=PY_DIR) |
| 124 | + rel = target.relative_to(PY_DIR) |
| 125 | + run(["uv", "run", str(rel), *extra_args], cwd=PY_DIR) |
| 126 | + |
| 127 | + |
| 128 | +def cmd_dev(py, rest): |
| 129 | + os.chdir(PY_DIR) |
| 130 | + print(f"[dev] python={py}, rest={rest}") |
| 131 | + do_clean() |
| 132 | + do_dev(py or DEFAULT_PY_SPEC, rest) |
| 133 | + |
| 134 | + |
| 135 | +def cmd_wheel(py, rest): |
| 136 | + os.chdir(PY_DIR) |
| 137 | + print(f"[wheel] python={py}, rest={rest}") |
| 138 | + do_clean() |
| 139 | + do_wheel(py or DEFAULT_PY_SPEC, rest) |
| 140 | + |
| 141 | + |
| 142 | +def cmd_test(rest): |
| 143 | + os.chdir(PY_TESTS_DIR) |
| 144 | + print(f"[test] rest={rest}") |
| 145 | + do_test(rest) |
| 146 | + |
| 147 | + |
| 148 | +def cmd_ex(name, rest): |
| 149 | + print(f"[ex] name={name}, rest={rest}") |
| 150 | + do_example(name, rest) |
| 151 | + |
| 152 | + |
| 153 | +def cmd_clean(rest): |
| 154 | + os.chdir(PY_DIR) |
| 155 | + print(f"[clean] rest={rest}") |
| 156 | + do_clean() |
0 commit comments