From 5f85319d97ee5caf5026d11eb4e5facd1a470ff4 Mon Sep 17 00:00:00 2001 From: John Sirois Date: Wed, 19 Feb 2025 19:11:31 -0800 Subject: [PATCH] Fix Windows test skips and daemon launches. More work towards #2658. --- pex/docs/server.py | 5 ++--- pex/subprocess.py | 17 ++++++++++++++++- testing/devpi.py | 5 ++--- tests/integration/test_sh_boot.py | 8 ++++++++ tests/integration/test_shebang_length_limit.py | 2 +- 5 files changed, 29 insertions(+), 8 deletions(-) diff --git a/pex/docs/server.py b/pex/docs/server.py index 842f8e513..698257494 100644 --- a/pex/docs/server.py +++ b/pex/docs/server.py @@ -14,7 +14,7 @@ from pex.cache.dirs import CacheDir from pex.common import safe_open from pex.os import kill -from pex.subprocess import subprocess_daemon_kwargs +from pex.subprocess import launch_python_daemon from pex.typing import TYPE_CHECKING from pex.version import __version__ @@ -163,14 +163,13 @@ def launch( # ephemeral port chosen. env.update(PYTHONUNBUFFERED="1") with safe_open(log, "w") as fp: - process = subprocess.Popen( + process = launch_python_daemon( args=[sys.executable, "-m", http_server_module, str(port)], env=env, cwd=document_root, bufsize=1, stdout=fp.fileno(), stderr=subprocess.STDOUT, - **subprocess_daemon_kwargs() ) pidfile = Pidfile.record(server_log=log, pid=process.pid, timeout=timeout) diff --git a/pex/subprocess.py b/pex/subprocess.py index 52a9ebeba..061241504 100644 --- a/pex/subprocess.py +++ b/pex/subprocess.py @@ -11,7 +11,7 @@ from pex.typing import TYPE_CHECKING if TYPE_CHECKING: - from typing import Any, Dict + from typing import Any, Dict, List def subprocess_daemon_kwargs(): @@ -33,3 +33,18 @@ def subprocess_daemon_kwargs(): # The os.setsid function is not available on Windows. "preexec_fn": os.setsid # type: ignore[attr-defined] } + + +def launch_python_daemon( + args, # type: List[str] + **kwargs # type: Any +): + # type: (...) -> subprocess.Popen + if WINDOWS: + python, _ = os.path.splitext(os.path.basename(args[0])) + if python == "python": + pythonw = os.path.join(os.path.dirname(args[0]), "pythonw.exe") + if os.path.exists(pythonw): + args[0] = pythonw + kwargs.update(subprocess_daemon_kwargs()) + return subprocess.Popen(args=args, **kwargs) diff --git a/testing/devpi.py b/testing/devpi.py index d9827945d..0c09fd632 100644 --- a/testing/devpi.py +++ b/testing/devpi.py @@ -17,7 +17,7 @@ from pex.common import safe_open, safe_rmtree from pex.interpreter import PythonInterpreter from pex.interpreter_constraints import InterpreterConstraint -from pex.subprocess import subprocess_daemon_kwargs +from pex.subprocess import launch_python_daemon from pex.typing import TYPE_CHECKING, cast from pex.venv.virtualenv import InvalidVirtualenvError, Virtualenv from testing import PEX_TEST_DEV_ROOT @@ -197,7 +197,7 @@ def launch( log = os.path.join(DEVPI_DIR, "log.txt") with safe_open(log, "w") as fp: - process = subprocess.Popen( + process = launch_python_daemon( args=devpi_server.launch_args( "--host", host, @@ -211,7 +211,6 @@ def launch( cwd=DEVPI_DIR, stdout=fp.fileno(), stderr=subprocess.STDOUT, - **subprocess_daemon_kwargs() ) pidfile = Pidfile.record(log=log, pid=process.pid, timeout=timeout) diff --git a/tests/integration/test_sh_boot.py b/tests/integration/test_sh_boot.py index 340a6a319..d7185d9ad 100644 --- a/tests/integration/test_sh_boot.py +++ b/tests/integration/test_sh_boot.py @@ -12,6 +12,7 @@ from pex.common import safe_open from pex.layout import Layout +from pex.os import WINDOWS from pex.typing import TYPE_CHECKING from testing import all_pythons, make_env, run_pex_command from testing.pytest.tmp import Tempdir @@ -20,6 +21,13 @@ from typing import Any, Iterable, Iterator, List, Text, Tuple +if WINDOWS: + pytest.skip( + "The --sh-boot shebang launch trick only works on systems with shebang support.", + allow_module_level=True, + ) + + @pytest.mark.parametrize( ["execution_mode_args"], [ diff --git a/tests/integration/test_shebang_length_limit.py b/tests/integration/test_shebang_length_limit.py index 90548d19e..c3986b2f3 100644 --- a/tests/integration/test_shebang_length_limit.py +++ b/tests/integration/test_shebang_length_limit.py @@ -53,7 +53,7 @@ def find_max_length( # Pytest fails to cleanup tmp dirs used probing file_path_length_limit and this squashes a very # large ream of warnings. if WINDOWS: - pytestmark = pytest.mark.skip("The current process of probing limits can break Windows.") + pytest.skip("The current process of probing limits can break Windows.", allow_module_level=True) else: pytestmark = pytest.mark.filterwarnings( "ignore:\\(rm_rf\\) error removing.*:pytest.PytestWarning"