Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Release Notes

## 2.91.5

This release fixes Pex PEX scie behavior to match Pex.

* Make ephemeral exec, venv repl and scie compatible (#3129)

## 2.91.4

This release brings 2 performance fixes from @tobni:
Expand Down
5 changes: 5 additions & 0 deletions pex/bin/pex.py
Original file line number Diff line number Diff line change
Expand Up @@ -1289,6 +1289,11 @@ def main(args=None):

try:
with global_environment(options) as env:
# These are set if we're running from within a Pex PEX scie and already installed.
# We clear them to allow recursive use of Pex / PEX.
env.pop("__PEX_EXE__", None)
env.pop("__PEX_ENTRY_POINT__", None)

try:
resolver_configuration = resolver_options.configure(
options,
Expand Down
7 changes: 3 additions & 4 deletions pex/pex_boot.py
Original file line number Diff line number Diff line change
Expand Up @@ -229,12 +229,11 @@ def boot(
if os.path.isfile(pex_exe):
sys.argv[0] = pex_exe

overridden_entry_point = os.environ.get("__PEX_ENTRY_POINT__", None)
overridden_pex = os.environ.get("__PEX_EXE__", None)
sys.path[0] = os.path.abspath(sys.path[0])
sys.path.insert(
0, os.path.abspath(os.path.join(overridden_entry_point or entry_point, bootstrap_dir))
)
sys.path.insert(0, os.path.abspath(os.path.join(overridden_pex or entry_point, bootstrap_dir)))

overridden_entry_point = os.environ.get("__PEX_ENTRY_POINT__", None)
if overridden_entry_point and overridden_entry_point != entry_point:
# This PEX has already been installed out of band; so we short-circuit to execute the
# pre-installed PEX.
Expand Down
2 changes: 1 addition & 1 deletion pex/version.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright 2015 Pex project contributors.
# Licensed under the Apache License, Version 2.0 (see LICENSE).

__version__ = "2.91.4"
__version__ = "2.91.5"
2 changes: 1 addition & 1 deletion tests/integration/cli/commands/test_lock_subset.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ def test_lock_subset_miss(lock):
# type: (str) -> None

_, original_locked_reqs = index(lock)
requests_version = original_locked_reqs[ProjectName("requests")].pin.version
requests_version = original_locked_reqs[ProjectName("requests")].pin.version.raw
run_pex3(
"lock", "subset", "--lock", lock, "requests!={version}".format(version=requests_version)
).assert_failure(
Expand Down
68 changes: 68 additions & 0 deletions tests/integration/scie/test_scie_ephemeral_run.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Copyright 2026 Pex project contributors.
# Licensed under the Apache License, Version 2.0 (see LICENSE).

from __future__ import absolute_import

import subprocess
import sys

import pytest

from pex.typing import TYPE_CHECKING
from testing import IS_PYPY, make_env, run_pex_command
from testing.pytest_utils.tmp import Tempdir
from testing.scie import skip_if_no_provider

if TYPE_CHECKING:
from typing import List


@pytest.mark.parametrize(
"execution_mode_args",
[
pytest.param([], id="ZIPAPP"),
pytest.param(["--venv"], id="VENV"),
],
)
@skip_if_no_provider
def test_scie_ephemeral_run(
tmpdir, # type: Tempdir
pex_wheel, # type: str
execution_mode_args, # type: List[str]
):
# type: (...) -> None

pex_scie = tmpdir.join("pex")
run_pex_command(
args=[pex_wheel, "-c", "pex", "-o", pex_scie, "--scie", "eager"] + execution_mode_args
).assert_success()

ic = "{impl}=={major}.{minor}.*".format(
impl="PyPy" if IS_PYPY else "CPython", major=sys.version_info[0], minor=sys.version_info[1]
)

# Verify the scie can perform an ephemeral run with `-- -c`.
output = subprocess.check_output(
args=[
pex_scie,
"--interpreter-constraint",
ic,
"--",
"-c",
"import sys; print(sys.executable)",
],
env=make_env(PATH=None),
)
assert output.decode("utf-8").strip()

# Verify the scie can drop into a REPL via ephemeral run.
process = subprocess.Popen(
args=[pex_scie, "--interpreter-constraint", ic, "--"],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
env=make_env(PATH=None),
)
stdout, stderr = process.communicate(input=b"import sys; print(sys.executable)\nquit()\n")
assert process.returncode == 0, stderr.decode("utf-8")
assert b">>>" in stdout or b">>>" in stderr
Loading