gdnative_python/tests/python_binary/SConscript

121 lines
3.5 KiB
Python

import os
import re
import shutil
import tempfile
import subprocess
from pathlib import Path
from SCons.Errors import UserError
from contextlib import contextmanager
Import("env")
if env["platform"].startswith("windows"):
PYTHON_RELATIVE_PATH = "python.exe"
python = f"{env['DIST_PLATFORM']}/{PYTHON_RELATIVE_PATH}"
scripts = f"{env['DIST_PLATFORM']}/Scripts"
else:
PYTHON_RELATIVE_PATH = "bin/python3"
python = f"{env['DIST_PLATFORM']}/{PYTHON_RELATIVE_PATH}"
scripts = f"{env['DIST_PLATFORM']}/bin"
def run_cmd(cmd):
if isinstance(cmd, str):
cmd = cmd.split()
try:
return subprocess.run(cmd, check=True, capture_output=True)
except subprocess.CalledProcessError as exc:
print(f"Error !!! Non-zero return code: {exc.returncode}")
print(f"command: {cmd}")
print(f"stdout: {exc.stdout.decode()}")
print(f"stderr: {exc.stderr.decode()}")
raise UserError(f"Test has failed (returncode: {exc.returncode})") from exc
@contextmanager
def run_cmd_and_handle_errors(cmd):
out = run_cmd(cmd)
try:
yield out
except Exception as exc:
print(f"Error !!! {str(exc)}")
print(f"command: {cmd}")
print(f"stdout: {out.stdout.decode()}")
print(f"stderr: {out.stderr.decode()}")
raise UserError(f"Test has failed ({str(exc)})") from exc
def test_factory(target, cmd):
if callable(cmd):
fn = cmd
else:
def fn(target, source, env):
run_cmd(cmd)
fn.__name__ = f"test_{target}"
env.Command([target], [], fn, strfunction=lambda target, source, env: f"Test: {target[0]}")
env.Depends(target, env["DIST_ROOT"])
env.AlwaysBuild(target)
return target
test_factory("run_python", f"{python} --version")
test_factory(
"import_pandemonium_module",
[
python,
"-c",
"""
try:
import pandemonium
except ImportError as exc:
assert "Cannot initialize pandemonium module given Godot GDNative API not available." in str(exc)
""",
],
)
def test_ensurepip_and_run_pip(target, source, env):
# ensurepip does modification, so copy dist first
with tempfile.TemporaryDirectory() as tmpdirname:
pythonscript_path = f"{tmpdirname}/pythonscript"
shutil.copytree(str(env["DIST_PLATFORM"].abspath), pythonscript_path, symlinks=True)
python = f"{pythonscript_path}/{PYTHON_RELATIVE_PATH}"
run_cmd(f"{python} -m ensurepip")
with run_cmd_and_handle_errors(
f"{python} -m pip --disable-pip-version-check --version"
) as out:
# Check pip site-packages location
stdout = out.stdout.decode().strip()
regex = r"^pip\s+[0-9.]+\s+from\s+(.*)\s+\(python\s+[0-9.+]+\)$"
match = re.match(regex, stdout)
if match:
site_packages_path = Path(match.group(1))
dist_platform_path = Path(pythonscript_path)
try:
site_packages_path.relative_to(dist_platform_path)
except ValueError as exc:
raise AssertionError(
f"pip site-packages is not located inside dist folder `{env['DIST_PLATFORM']}`"
) from exc
else:
raise AssertionError(f"stdout doesn't match regex `{regex}`")
run_cmd(
f"{python} -m pip install requests"
) # Basically the most downloaded packages on pypi
run_cmd([python, "-c", "import requests"])
test_factory("ensurepip_and_run_pip", test_ensurepip_and_run_pip)