fix(codex): drop Python 3.11 requirement, auto-install python3
- tomllib fallback: try tomllib (3.11+) -> tomli -> minimal parser - Works with Python 3.8+ (Ubuntu 20.04, Debian 11, etc.) - Auto-install python3 if not found (like Gemini/Qwen scripts) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -21,7 +21,56 @@ import shutil
|
|||||||
import platform
|
import platform
|
||||||
import subprocess
|
import subprocess
|
||||||
import argparse
|
import argparse
|
||||||
import tomllib
|
try:
|
||||||
|
import tomllib
|
||||||
|
except ModuleNotFoundError:
|
||||||
|
try:
|
||||||
|
import tomli as tomllib
|
||||||
|
except ModuleNotFoundError:
|
||||||
|
# Minimal TOML reader for Python < 3.11
|
||||||
|
import re as _re
|
||||||
|
class _T:
|
||||||
|
@staticmethod
|
||||||
|
def load(f):
|
||||||
|
raw = f.read()
|
||||||
|
return _T._parse(raw.decode("utf-8") if isinstance(raw, bytes) else raw)
|
||||||
|
@staticmethod
|
||||||
|
def loads(s):
|
||||||
|
return _T._parse(s)
|
||||||
|
@staticmethod
|
||||||
|
def _parse(text):
|
||||||
|
result, cur = {}, None
|
||||||
|
for line in text.split("\n"):
|
||||||
|
line = line.strip()
|
||||||
|
if not line or line.startswith("#"):
|
||||||
|
continue
|
||||||
|
m = _re.match(r'^\[([^\]]+)\]$', line)
|
||||||
|
if m:
|
||||||
|
keys = [k.strip() for k in m.group(1).split(".")]
|
||||||
|
cur = result
|
||||||
|
for k in keys:
|
||||||
|
cur = cur.setdefault(k, {})
|
||||||
|
continue
|
||||||
|
m = _re.match(r'^([^=]+?)\s*=\s*(.+)$', line)
|
||||||
|
if m and cur is not None:
|
||||||
|
k, v = m.group(1).strip(), m.group(2).strip()
|
||||||
|
if v.startswith('"') and v.endswith('"'): v = v[1:-1]
|
||||||
|
elif v == "true": v = True
|
||||||
|
elif v == "false": v = False
|
||||||
|
elif _re.match(r'^-?\d+$', v): v = int(v)
|
||||||
|
elif v.startswith("[") and v.endswith("]"):
|
||||||
|
inner = v[1:-1].strip()
|
||||||
|
v = [x.strip().strip('"') for x in inner.split(",")] if inner else []
|
||||||
|
cur[k] = v
|
||||||
|
elif m:
|
||||||
|
k, v = m.group(1).strip(), m.group(2).strip()
|
||||||
|
if v.startswith('"') and v.endswith('"'): v = v[1:-1]
|
||||||
|
elif v == "true": v = True
|
||||||
|
elif v == "false": v = False
|
||||||
|
elif _re.match(r'^-?\d+$', v): v = int(v)
|
||||||
|
result[k] = v
|
||||||
|
return result
|
||||||
|
tomllib = _T()
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
|
|||||||
@@ -37,21 +37,34 @@ echo -e "${NC}"
|
|||||||
|
|
||||||
# ---- Check prerequisites ----
|
# ---- Check prerequisites ----
|
||||||
|
|
||||||
for cmd in python3 curl tar; do
|
install_pkg() {
|
||||||
|
if command -v apt-get >/dev/null 2>&1; then
|
||||||
|
apt-get update -qq && apt-get install -y -qq "$@"
|
||||||
|
elif command -v dnf >/dev/null 2>&1; then
|
||||||
|
dnf install -y -q "$@"
|
||||||
|
elif command -v yum >/dev/null 2>&1; then
|
||||||
|
yum install -y -q "$@"
|
||||||
|
elif command -v brew >/dev/null 2>&1; then
|
||||||
|
brew install "$@"
|
||||||
|
else
|
||||||
|
err "No package manager found. Install $* manually."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
if ! command -v python3 &>/dev/null; then
|
||||||
|
info "python3 not found, installing..."
|
||||||
|
install_pkg python3
|
||||||
|
fi
|
||||||
|
|
||||||
|
for cmd in curl tar; do
|
||||||
if ! command -v "$cmd" &>/dev/null; then
|
if ! command -v "$cmd" &>/dev/null; then
|
||||||
err "$cmd is required but not found"
|
err "$cmd is required but not found"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
PY_VER=$(python3 -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')")
|
log "Python3 $(python3 --version | awk '{print $2}')"
|
||||||
PY_MAJOR=$(echo "$PY_VER" | cut -d. -f1)
|
|
||||||
PY_MINOR=$(echo "$PY_VER" | cut -d. -f2)
|
|
||||||
if [ "$PY_MAJOR" -lt 3 ] || ([ "$PY_MAJOR" -eq 3 ] && [ "$PY_MINOR" -lt 11 ]); then
|
|
||||||
err "Python 3.11+ required (found $PY_VER)"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
log "Python3 $PY_VER"
|
|
||||||
|
|
||||||
# ---- Step 1: Install Codex binary from GitHub ----
|
# ---- Step 1: Install Codex binary from GitHub ----
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,42 @@ checks config.toml values and environment variables.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import tomllib
|
try:
|
||||||
|
import tomllib
|
||||||
|
except ModuleNotFoundError:
|
||||||
|
try:
|
||||||
|
import tomli as tomllib
|
||||||
|
except ModuleNotFoundError:
|
||||||
|
import re as _re
|
||||||
|
class _T:
|
||||||
|
@staticmethod
|
||||||
|
def load(f):
|
||||||
|
raw = f.read()
|
||||||
|
return _T._parse(raw.decode("utf-8") if isinstance(raw, bytes) else raw)
|
||||||
|
@staticmethod
|
||||||
|
def _parse(text):
|
||||||
|
result, cur = {}, None
|
||||||
|
for line in text.split("\n"):
|
||||||
|
line = line.strip()
|
||||||
|
if not line or line.startswith("#"):
|
||||||
|
continue
|
||||||
|
m = _re.match(r'^\[([^\]]+)\]$', line)
|
||||||
|
if m:
|
||||||
|
keys = [k.strip() for k in m.group(1).split(".")]
|
||||||
|
cur = result
|
||||||
|
for k in keys:
|
||||||
|
cur = cur.setdefault(k, {})
|
||||||
|
continue
|
||||||
|
m = _re.match(r'^([^=]+?)\s*=\s*(.+)$', line)
|
||||||
|
if m:
|
||||||
|
k, v = m.group(1).strip(), m.group(2).strip()
|
||||||
|
if v.startswith('"') and v.endswith('"'): v = v[1:-1]
|
||||||
|
elif v == "true": v = True
|
||||||
|
elif v == "false": v = False
|
||||||
|
elif _re.match(r'^-?\d+$', v): v = int(v)
|
||||||
|
(cur if cur is not None else result)[k] = v
|
||||||
|
return result
|
||||||
|
tomllib = _T()
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import Callable, Optional
|
from typing import Callable, Optional
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user