mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-11-06 01:53:56 -06:00
fix: pick a Python that can do HTTPS
This commit is contained in:
1 parent
4d46587693
commit
bcedd22a9e
7 files changed
+118
-13
No files matched your search
+1
-1
@@ -84,7 +84,7 @@
|
||||
param($candidate)
|
||||
if (-not $candidate) { return $false }
|
||||
$arguments = $candidate[1]
|
||||
& $candidate[0].Source @arguments -c "import sys; raise SystemExit(sys.version_info < (3, 8))" | Out-Null
|
||||
& $candidate[0].Source @arguments -c "import sys, ssl, unicodedata, zlib; raise SystemExit(sys.version_info < (3, 8))" 2>$null | Out-Null
|
||||
return ($LASTEXITCODE -eq 0)
|
||||
}
|
||||
$needPython = "Python 3.8 or newer is required. Install it with " +
|
||||
|
||||
+14
-2
@@ -121,14 +121,21 @@ if [ -z "$INSTALLER" ] || [ ! -f "$INSTALLER" ]; then
|
||||
INSTALLER="$TEMP_INSTALLER"
|
||||
fi
|
||||
|
||||
# A Python can be built without ssl, unicodedata or zlib, and the installer
|
||||
# needs all three: a python3 lacking ssl was chosen over a full python and
|
||||
# every download then failed as if the network were down.
|
||||
find_python() {
|
||||
PYTHON=""
|
||||
PYTHON_LACKING=""
|
||||
for command_name in python3 python; do
|
||||
if command -v "$command_name" >/dev/null 2>&1 \
|
||||
&& "$command_name" -c 'import sys; raise SystemExit(sys.version_info < (3, 8))' 2>/dev/null; then
|
||||
command -v "$command_name" >/dev/null 2>&1 || continue
|
||||
"$command_name" -c 'import sys; raise SystemExit(sys.version_info < (3, 8))' \
|
||||
2>/dev/null || continue
|
||||
if "$command_name" -c 'import ssl, unicodedata, zlib' 2>/dev/null; then
|
||||
PYTHON=$command_name
|
||||
return 0
|
||||
fi
|
||||
PYTHON_LACKING=${PYTHON_LACKING:-$command_name}
|
||||
done
|
||||
return 1
|
||||
}
|
||||
@@ -172,6 +179,11 @@ if ! find_python; then
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
if [ -z "$PYTHON" ] && [ -n "$PYTHON_LACKING" ]; then
|
||||
echo "Error: $PYTHON_LACKING is built without a module the installer needs" >&2
|
||||
echo " (ssl, unicodedata or zlib). Run it with a full Python 3.8 or newer." >&2
|
||||
exit 1
|
||||
fi
|
||||
if [ -z "$PYTHON" ]; then
|
||||
echo "Error: Python 3.8 or newer is required." >&2
|
||||
if [ -n "$install_command" ]; then
|
||||
|
||||
@@ -62,8 +62,8 @@
|
||||
{
|
||||
"dest": "roms/ports/retrobios/tui.txt",
|
||||
"repo_path": "ports/shared/tui.txt",
|
||||
"size": 35984,
|
||||
"sha256": "7291b11eef5b5c2df8d2befab10614a2d515bffdf96dc208529b5dee9e6df0f1",
|
||||
"size": 36434,
|
||||
"sha256": "fa05432a9a4325f3fd3220eec0548ad932dffc1888b93a08af2047cc78aa4d0c",
|
||||
"executable": false
|
||||
}
|
||||
]
|
||||
@@ -71,8 +71,8 @@
|
||||
"muos": {
|
||||
"archive": {
|
||||
"dest": "ARCHIVE/RetroBIOS.muxapp",
|
||||
"size": 1134145,
|
||||
"sha256": "9a837360311366ecb4a65c4c4eff5388319ff0ade4f6acad3709cd4e63249a59"
|
||||
"size": 1134595,
|
||||
"sha256": "72ef1c1054aaff03491127694455e27d25edcc5565ace9e490bb5623c2a62840"
|
||||
},
|
||||
"members": [
|
||||
{
|
||||
@@ -141,8 +141,8 @@
|
||||
{
|
||||
"name": "RetroBIOS/tui.txt",
|
||||
"repo_path": "ports/shared/tui.txt",
|
||||
"size": 35984,
|
||||
"sha256": "7291b11eef5b5c2df8d2befab10614a2d515bffdf96dc208529b5dee9e6df0f1",
|
||||
"size": 36434,
|
||||
"sha256": "fa05432a9a4325f3fd3220eec0548ad932dffc1888b93a08af2047cc78aa4d0c",
|
||||
"executable": false
|
||||
}
|
||||
]
|
||||
@@ -208,8 +208,8 @@
|
||||
{
|
||||
"dest": ".config/modules/retrobios/tui.txt",
|
||||
"repo_path": "ports/shared/tui.txt",
|
||||
"size": 35984,
|
||||
"sha256": "7291b11eef5b5c2df8d2befab10614a2d515bffdf96dc208529b5dee9e6df0f1",
|
||||
"size": 36434,
|
||||
"sha256": "fa05432a9a4325f3fd3220eec0548ad932dffc1888b93a08af2047cc78aa4d0c",
|
||||
"executable": false
|
||||
}
|
||||
]
|
||||
|
||||
@@ -43,7 +43,7 @@ rb_fetch_runtime() {
|
||||
fi
|
||||
PortMasterDialogInit "no-check"
|
||||
PortMasterDialog "messages_begin"
|
||||
PortMasterDialog "message" "This system's Python is older than 3.8. Downloading PortMaster's $RB_RUNTIME runtime."
|
||||
PortMasterDialog "message" "This system's Python is older than 3.8 or lacks a module install.py needs. Downloading PortMaster's $RB_RUNTIME runtime."
|
||||
answer=$(rb_answer "check_runtime" "$RB_RUNTIME.squashfs")
|
||||
PortMasterDialog "messages_end"
|
||||
PortMasterDialogExit
|
||||
|
||||
+11
-1
@@ -193,10 +193,17 @@ rb_open_log() {
|
||||
|
||||
# --- Python ---------------------------------------------------------------
|
||||
|
||||
rb_python_ok() {
|
||||
# The modules install.py needs that a Python can be built without: a python3
|
||||
# lacking ssl was chosen over PortMaster's runtime, and every download failed
|
||||
# as if the network were down.
|
||||
rb_python_new() {
|
||||
"$@" -c 'import sys; sys.exit(0 if sys.version_info >= (3, 8) else 1)' >/dev/null 2>&1
|
||||
}
|
||||
|
||||
rb_python_ok() {
|
||||
rb_python_new "$@" && "$@" -c 'import ssl, unicodedata, zlib' >/dev/null 2>&1
|
||||
}
|
||||
|
||||
# The OS python3 when it is 3.8 or newer, else PortMaster's python_3.11
|
||||
# runtime on aarch64, mounted as PortMaster's own Python ports do. A launcher
|
||||
# that can download the runtime defines rb_fetch_runtime. Sets
|
||||
@@ -252,6 +259,9 @@ rb_release_python() {
|
||||
rb_python_text() {
|
||||
local found
|
||||
found=$(python3 --version 2>&1 | awk '{print $2}')
|
||||
if command -v python3 >/dev/null 2>&1 && rb_python_new python3; then
|
||||
found="$found, built without a module install.py needs (ssl, unicodedata or zlib)"
|
||||
fi
|
||||
case "$RB_PYTHON_PROBLEM" in
|
||||
old) printf '%s\n' "Python 3.8 or newer is needed. This system has ${found:-none}, and PortMaster's Python runtime exists for aarch64 only, and this device is $(rb_arch). $RB_PC_ROUTE" ;;
|
||||
runtime_offline) printf '%s\n' "Python 3.8 or newer is needed. This system has ${found:-none}, and PortMaster's $RB_RUNTIME runtime needs a connection to download. $RB_PC_ROUTE" ;;
|
||||
|
||||
@@ -1080,6 +1080,44 @@ class ThePortMasterPort(unittest.TestCase):
|
||||
self.assertIn("--dest", screen)
|
||||
self.assertEqual(device.calls(), [])
|
||||
|
||||
def _python_without_ssl(self, device) -> None:
|
||||
"""A python3 3.8 or newer whose ssl import fails, as on a CFW image
|
||||
built without OpenSSL."""
|
||||
real = shutil.which("python3.8") or sys.executable
|
||||
shadow = device.root / "no-ssl"
|
||||
shadow.mkdir()
|
||||
(shadow / "ssl.py").write_text('raise ImportError("built without ssl")\n')
|
||||
device.tool("python3", f'#!/bin/sh\nPYTHONPATH="{shadow}" exec {real} "$@"\n')
|
||||
|
||||
def test_a_python_without_ssl_is_told_on_the_console(self):
|
||||
"""Only the version was probed: a python3 without ssl was chosen and
|
||||
every download failed as if the network were down."""
|
||||
device = self.device()
|
||||
self._python_without_ssl(device)
|
||||
device.tool("uname", "#!/bin/sh\necho armv7l\n")
|
||||
proc = device.run(["bash", self.script])
|
||||
self.assertEqual(proc.returncode, 1)
|
||||
screen = " ".join(device.screen.split())
|
||||
self.assertIn("built without a module install.py needs", screen)
|
||||
self.assertEqual(device.calls(), [])
|
||||
|
||||
def test_a_python_without_ssl_gives_way_to_the_runtime(self):
|
||||
device = self.device()
|
||||
self._python_without_ssl(device)
|
||||
real = shutil.which("python3.8") or sys.executable
|
||||
device.tool("uname", "#!/bin/sh\necho aarch64\n")
|
||||
device.tool("mount", '#!/bin/sh\nprintf "mount %s\\n" "$*" >> "$FAKE_STATE/tools.log"\n'
|
||||
'mkdir -p "$2/bin"\n'
|
||||
f'printf \'#!/bin/sh\\nunset PYTHONHOME\\nexec {real} "$@"\\n\' > "$2/bin/python3"\n'
|
||||
'chmod +x "$2/bin/python3"\n')
|
||||
device.tool("umount", FAKE_RECORDER)
|
||||
(self.control / "libs").mkdir()
|
||||
(self.control / "libs" / "python_3.11.squashfs").write_bytes(b"")
|
||||
proc = device.run(["bash", self.script])
|
||||
self.assertEqual(proc.returncode, 0, proc.stderr.decode())
|
||||
[call] = device.tui_calls()
|
||||
self.assertTrue(any(t.startswith("mount") for t in device.tools()))
|
||||
|
||||
def test_the_runtime_is_mounted_then_unmounted(self):
|
||||
"""ArkOS's Python 3.7: PortMaster's python_3.11 runtime, mounted for
|
||||
the run and unmounted after it."""
|
||||
|
||||
@@ -2575,6 +2575,51 @@ class NoPythonNamesThisSystemsCommand(unittest.TestCase):
|
||||
self.assertNotIn("apt", proc.stderr)
|
||||
|
||||
|
||||
class ABootstrapPythonCanDoHttps(unittest.TestCase):
|
||||
"""find_python checked the version only: a python3 built without ssl
|
||||
was chosen over a full python, and every download then failed."""
|
||||
|
||||
def _bin(self) -> tuple[Path, Path]:
|
||||
root = Path(_tempdir(self))
|
||||
fake_bin = root / "bin"
|
||||
fake_bin.mkdir()
|
||||
for tool in ("sed", "tr", "dirname", "cat", "awk", "uname"):
|
||||
found = shutil.which(tool)
|
||||
if found:
|
||||
(fake_bin / tool).symlink_to(found)
|
||||
shadow = root / "no-ssl"
|
||||
shadow.mkdir()
|
||||
(shadow / "ssl.py").write_text('raise ImportError("built without ssl")\n')
|
||||
(fake_bin / "python3").write_text(
|
||||
f'#!/bin/sh\nPYTHONPATH="{shadow}" exec {shlex.quote(sys.executable)} "$@"\n')
|
||||
(fake_bin / "python3").chmod(0o755)
|
||||
(root / "install.py").write_text("import ssl; print('installer ran')\n")
|
||||
shutil.copy(REPO_ROOT / "install.sh", root / "install.sh")
|
||||
return root, fake_bin
|
||||
|
||||
def _run(self, root: Path, fake_bin: Path) -> subprocess.CompletedProcess:
|
||||
return subprocess.run(
|
||||
["/bin/sh", str(root / "install.sh")], cwd=root,
|
||||
env={"PATH": str(fake_bin), "HOME": str(root)},
|
||||
capture_output=True, text=True, timeout=30, check=False,
|
||||
stdin=subprocess.DEVNULL, start_new_session=True,
|
||||
)
|
||||
|
||||
def test_a_full_python_is_preferred(self):
|
||||
root, fake_bin = self._bin()
|
||||
(fake_bin / "python").symlink_to(sys.executable)
|
||||
proc = self._run(root, fake_bin)
|
||||
self.assertEqual(proc.returncode, 0, proc.stderr)
|
||||
self.assertIn("installer ran", proc.stdout)
|
||||
|
||||
def test_the_missing_module_is_named(self):
|
||||
root, fake_bin = self._bin()
|
||||
proc = self._run(root, fake_bin)
|
||||
self.assertEqual(proc.returncode, 1)
|
||||
self.assertNotIn("installer ran", proc.stdout)
|
||||
self.assertIn("python3 is built without a module the installer needs", proc.stderr)
|
||||
|
||||
|
||||
@unittest.skipUnless(shutil.which("pwsh") and shutil.which("script"), "needs PowerShell and a terminal")
|
||||
class WindowsWithoutPythonIsOfferedWinget(unittest.TestCase):
|
||||
"""A Windows machine without Python was told to install it, open a new
|
||||
|
||||
Reference in new issue
Block a user