Skip to content

Commit

Permalink
Fix #1949: zipapp virtual environment creation fails if zipapp path i…
Browse files Browse the repository at this point in the history
…s symlinked (#2722)

Co-authored-by: HandSonic <3>
  • Loading branch information
HandSonic committed May 11, 2024
1 parent 3be84af commit 0a3816e
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 2 deletions.
1 change: 1 addition & 0 deletions docs/changelog/1949.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
``virtualenv.pyz`` no longer fails when zipapp path contains a symlink - by :user:`HandSonic` and :user:`petamas`.
8 changes: 6 additions & 2 deletions src/virtualenv/util/zipapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,12 @@ def extract(full_path, dest):


def _get_path_within_zip(full_path):
full_path = os.path.abspath(str(full_path))
sub_file = full_path[len(ROOT) + 1 :]
full_path = os.path.realpath(os.path.abspath(str(full_path)))
prefix = f"{ROOT}{os.sep}"
if not full_path.startswith(prefix):
msg = f"full_path={full_path} should start with prefix={prefix}."
raise RuntimeError(msg)
sub_file = full_path[len(prefix) :]
if IS_WIN:
# paths are always UNIX separators, even on Windows, though __file__ still follows platform default
sub_file = sub_file.replace(os.sep, "/")
Expand Down
19 changes: 19 additions & 0 deletions tests/integration/test_zipapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from flaky import flaky

from virtualenv.discovery.py_info import PythonInfo
from virtualenv.info import fs_supports_symlink
from virtualenv.run import cli_run

HERE = Path(__file__).parent
Expand Down Expand Up @@ -83,6 +84,24 @@ def _run(*args):
return _run


@pytest.fixture()
def call_zipapp_symlink(zipapp, tmp_path, zipapp_test_env, temp_app_data): # noqa: ARG001
def _run(*args):
symlinked = zipapp.parent / "symlinked_virtualenv.pyz"
symlinked.symlink_to(str(zipapp))
cmd = [str(zipapp_test_env), str(symlinked), "-vv", str(tmp_path / "env"), *list(args)]
subprocess.check_call(cmd)

return _run


@pytest.mark.skipif(not fs_supports_symlink(), reason="symlink not supported")
def test_zipapp_in_symlink(capsys, call_zipapp_symlink):
call_zipapp_symlink("--reset-app-data")
_out, err = capsys.readouterr()
assert not err


@flaky(max_runs=2, min_passes=1)
def test_zipapp_help(call_zipapp, capsys):
call_zipapp("-h")
Expand Down

0 comments on commit 0a3816e

Please sign in to comment.