From b76157ee3b80b07b2816376b8d362a99ed3cbc31 Mon Sep 17 00:00:00 2001 From: Ofek Lev Date: Mon, 22 Jan 2024 13:49:57 -0500 Subject: [PATCH 1/2] Resolve symbolic links for environment metadata --- src/virtualenv/discovery/py_info.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/virtualenv/discovery/py_info.py b/src/virtualenv/discovery/py_info.py index da1619faf..7f3f0999f 100644 --- a/src/virtualenv/discovery/py_info.py +++ b/src/virtualenv/discovery/py_info.py @@ -32,8 +32,9 @@ class PythonInfo: # noqa: PLR0904 """Contains information for a Python interpreter.""" def __init__(self) -> None: # noqa: PLR0915 - def abs_path(v): - return None if v is None else os.path.abspath(v) # unroll relative elements from path (e.g. ..) + def real_path(v): + # unroll relative elements from path (e.g. ..) and ensure symbolic links are resolved + return None if v is None else os.path.realpath(v) # qualifies the python self.platform = sys.platform @@ -53,16 +54,16 @@ def abs_path(v): self.os = os.name # information about the prefix - determines python home - self.prefix = abs_path(getattr(sys, "prefix", None)) # prefix we think - self.base_prefix = abs_path(getattr(sys, "base_prefix", None)) # venv - self.real_prefix = abs_path(getattr(sys, "real_prefix", None)) # old virtualenv + self.prefix = real_path(getattr(sys, "prefix", None)) # prefix we think + self.base_prefix = real_path(getattr(sys, "base_prefix", None)) # venv + self.real_prefix = real_path(getattr(sys, "real_prefix", None)) # old virtualenv # information about the exec prefix - dynamic stdlib modules - self.base_exec_prefix = abs_path(getattr(sys, "base_exec_prefix", None)) - self.exec_prefix = abs_path(getattr(sys, "exec_prefix", None)) + self.base_exec_prefix = real_path(getattr(sys, "base_exec_prefix", None)) + self.exec_prefix = real_path(getattr(sys, "exec_prefix", None)) - self.executable = abs_path(sys.executable) # the executable we were invoked via - self.original_executable = abs_path(self.executable) # the executable as known by the interpreter + self.executable = real_path(sys.executable) # the executable we were invoked via + self.original_executable = real_path(self.executable) # the executable as known by the interpreter self.system_executable = self._fast_get_system_executable() # the executable we are based of (if available) try: From afd73d28ec128f5308259732b16a7a25d6909b39 Mon Sep 17 00:00:00 2001 From: Ofek Lev Date: Mon, 22 Jan 2024 17:08:09 -0500 Subject: [PATCH 2/2] less invasive strategy --- src/virtualenv/create/pyenv_cfg.py | 4 +++- src/virtualenv/discovery/py_info.py | 19 +++++++++---------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/virtualenv/create/pyenv_cfg.py b/src/virtualenv/create/pyenv_cfg.py index 03ebfbbda..04883dea2 100644 --- a/src/virtualenv/create/pyenv_cfg.py +++ b/src/virtualenv/create/pyenv_cfg.py @@ -1,6 +1,7 @@ from __future__ import annotations import logging +import os from collections import OrderedDict @@ -32,7 +33,8 @@ def write(self): logging.debug("write %s", self.path) text = "" for key, value in self.content.items(): - line = f"{key} = {value}" + normalized_value = os.path.realpath(value) if value and os.path.exists(value) else value + line = f"{key} = {normalized_value}" logging.debug("\t%s", line) text += line text += "\n" diff --git a/src/virtualenv/discovery/py_info.py b/src/virtualenv/discovery/py_info.py index 7f3f0999f..da1619faf 100644 --- a/src/virtualenv/discovery/py_info.py +++ b/src/virtualenv/discovery/py_info.py @@ -32,9 +32,8 @@ class PythonInfo: # noqa: PLR0904 """Contains information for a Python interpreter.""" def __init__(self) -> None: # noqa: PLR0915 - def real_path(v): - # unroll relative elements from path (e.g. ..) and ensure symbolic links are resolved - return None if v is None else os.path.realpath(v) + def abs_path(v): + return None if v is None else os.path.abspath(v) # unroll relative elements from path (e.g. ..) # qualifies the python self.platform = sys.platform @@ -54,16 +53,16 @@ def real_path(v): self.os = os.name # information about the prefix - determines python home - self.prefix = real_path(getattr(sys, "prefix", None)) # prefix we think - self.base_prefix = real_path(getattr(sys, "base_prefix", None)) # venv - self.real_prefix = real_path(getattr(sys, "real_prefix", None)) # old virtualenv + self.prefix = abs_path(getattr(sys, "prefix", None)) # prefix we think + self.base_prefix = abs_path(getattr(sys, "base_prefix", None)) # venv + self.real_prefix = abs_path(getattr(sys, "real_prefix", None)) # old virtualenv # information about the exec prefix - dynamic stdlib modules - self.base_exec_prefix = real_path(getattr(sys, "base_exec_prefix", None)) - self.exec_prefix = real_path(getattr(sys, "exec_prefix", None)) + self.base_exec_prefix = abs_path(getattr(sys, "base_exec_prefix", None)) + self.exec_prefix = abs_path(getattr(sys, "exec_prefix", None)) - self.executable = real_path(sys.executable) # the executable we were invoked via - self.original_executable = real_path(self.executable) # the executable as known by the interpreter + self.executable = abs_path(sys.executable) # the executable we were invoked via + self.original_executable = abs_path(self.executable) # the executable as known by the interpreter self.system_executable = self._fast_get_system_executable() # the executable we are based of (if available) try: