from functools import wraps from pathlib import Path import os import subprocess import sys from byteb4rb1e.testing.pytest import get_current_test def run_in_subprocess_once(): """ A decorator that reruns th test in a subprocess if not already inside one. Requires pytest to be installed and test to be run by pytest. For what? Anything that can't be done in a thread-safe manner, e.g. modifying PYTHON_PATH """ def decorator(test_func): @wraps(test_func) def wrapper(*args, **kwargs): if os.environ.get("XPYTEST_INSIDE_SUBPROCESS") == "1": return test_func(*args, **kwargs) suite_path, case_name = get_current_test() cmd = [ sys.executable, "-m", "pytest", f"{suite_path}::{case_name}", ] result = subprocess.run( cmd, env={**os.environ, "XPYTEST_INSIDE_SUBPROCESS": "1"}, capture_output=True, text=True, ) if result.returncode != 0: print(' '.join(cmd)) print("==== Subprocess stdout ====") print(result.stdout) print("==== Subprocess stderr ====") print(result.stderr) raise AssertionError(f"Subprocess test failed with exit code {result.returncode}") return wrapper return decorator