summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xpy-nuitka-build80
1 files changed, 80 insertions, 0 deletions
diff --git a/py-nuitka-build b/py-nuitka-build
new file mode 100755
index 0000000..3b14427
--- /dev/null
+++ b/py-nuitka-build
@@ -0,0 +1,80 @@
+#!/usr/bin/env bash
+#
+# Nuitka Build Helper Script
+#
+# Compiles Python scripts into standalone executables using Nuitka with
+# dependency management via uv.
+
+set -euo pipefail
+
+_parse_dependecies() {
+ cat <<EOF | python3 - "$1"
+import platform
+import re
+import sys
+import tomllib
+
+REGEX = r"(?m)^# /// (?P<type>[a-zA-Z0-9-]+)$\s(?P<content>(^#(| .*)$\s)+)^# ///$"
+
+
+def read(script: str) -> dict | None:
+ name = "script"
+ matches = list(filter(lambda m: m.group("type") == name, re.finditer(REGEX, script)))
+ if len(matches) > 1:
+ raise ValueError(f"Multiple {name} blocks found")
+ elif len(matches) == 1:
+ content = "".join(
+ line[2:] if line.startswith("# ") else line[1:]
+ for line in matches[0].group("content").splitlines(keepends=True)
+ )
+ return tomllib.loads(content)
+ else:
+ return {}
+
+
+with open(sys.argv[1], "r") as fd:
+ script = fd.read()
+ metadata = read(script)
+ python_version = metadata.get("requires-python", platform.python_version())
+ dependencies = metadata.get("dependencies", [])
+ print(python_version)
+ if dependencies:
+ print("\n".join(dependencies))
+EOF
+}
+
+main() {
+
+ if [[ $# -ne 1 ]]; then
+ echo "Usage: $0 <python_script.py>" >&2
+ exit 1
+ fi
+
+ local script="$1"
+
+ if [[ ! -f "$script" ]]; then
+ echo "Error: Script '$script' not found" >&2
+ exit 2
+ fi
+
+ {
+ local python_version
+ local -a dependencies=()
+ IFS= read -r python_version
+ readarray -t dependencies
+
+ local cmd=(uv run)
+ cmd+=(--python "$python_version")
+ for dependency in "${dependencies[@]}"; do
+ cmd+=(--with "$dependency")
+ done
+
+ cmd+=(--with 'Nuitka[onefile]')
+ cmd+=(python -m nuitka --standalone --onefile "$script")
+
+ "${cmd[@]}"
+ } < <(_parse_dependecies "$script")
+
+}
+
+main "$@"