defmodule Dds do @moduledoc """ The dds toolchain, bundled. This module is a LOCATOR AND RUNNER, nothing more — the instruments are the bundled Python (the same bytes as the tagged toolchain repo), and all semantics live there. Runtime resolution: 1. **Pythonx** (a hard dep — embedded CPython, hermetic): `mix deps.get` is the ONLY prerequisite. Pythonx provisions a standalone interpreter and the tree-sitter wheels itself (pinned below), in-process, no system Python, no PATH. The mechanical witness and evidence replay work out of the box. 2. Fallback, only when the host app already initialized pythonx with its own interpreter AND that interpreter lacks our deps: `uv` on PATH (same hermetic properties via subprocess), then `python3` (stdlib legs, honest degradation), then a clear error. """ @pythonx_project """ [project] name = "dds-runner" version = "0.0.0" requires-python = ">=3.10" dependencies = ["tree-sitter", "tree-sitter-elixir"] """ @tree_deps ["tree-sitter", "tree-sitter-elixir"] @doc "Run the bundled CLI with `args`; exits the VM with its exit code on failure." def run(args) when is_list(args) do cli = Path.join(:code.priv_dir(:dds), "toolchain/cli.py") status = case run_pythonx(cli, args) do {:ok, s} -> s :fallback -> run_path_tiers(cli, args) end if status != 0, do: exit({:shutdown, status}) :ok end defp run_pythonx(cli, args) do # embedded CPython: pythonx downloads/caches a standalone build and # the pinned deps; the toolchain runs in-process. SystemExit is the # CLI's normal exit path — catch it and surface the code. {:ok, _} = Application.ensure_all_started(:pythonx) usable? = try do Pythonx.uv_init(@pythonx_project) true rescue _ -> # already initialized by the host app: usable only if ITS # interpreter can serve the tree-sitter legs {probe, _} = Pythonx.eval( "import importlib.util as u; bool(u.find_spec('tree_sitter'))", %{} ) Pythonx.decode(probe) == true end if not usable? do IO.warn( "pythonx was already initialized by the host app and its " <> "interpreter lacks tree-sitter — falling back to uv/python3 on PATH" ) throw(:fallback) end {result, _globals} = Pythonx.eval( """ import runpy, sys sys.argv = ["dds", *[a.decode() for a in args]] _code = 0 try: runpy.run_path(cli.decode(), run_name="__main__") except SystemExit as e: _code = int(e.code or 0) _code """, %{"args" => args, "cli" => cli} ) {:ok, result |> Pythonx.decode() |> trunc()} catch :fallback -> :fallback end defp run_path_tiers(cli, args) do cond do uv = System.find_executable("uv") -> run_cmd(uv, uv_args(cli, args)) py = System.find_executable("python3") -> run_cmd(py, [cli | args]) true -> raise_no_runtime() end end defp uv_args(cli, args) do ["run", "--quiet"] ++ Enum.flat_map(@tree_deps, &["--with", &1]) ++ ["--", cli | args] end defp run_cmd(cmd, argv) do {_, status} = System.cmd(cmd, argv, into: IO.stream(:stdio, :line), stderr_to_stdout: true) status end defp raise_no_runtime do raise """ dds could not get a runtime: pythonx is unusable here (host-app interpreter without tree-sitter) and neither uv nor python3 is on PATH. Install uv (https://docs.astral.sh/uv/) or python3 >= 3.9. """ end end