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
4 changes: 2 additions & 2 deletions .github/release.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
changelog:
exclude:
authors:
- dependabot
- pre-commit-ci
- dependabot[bot]
- pre-commit-ci[bot]
1 change: 1 addition & 0 deletions docs/changelog/2975.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix backwards incompatible changes to ``PythonInfo`` - by :user:`gaborbernat`.
39 changes: 17 additions & 22 deletions src/virtualenv/discovery/py_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ def _get_path_extensions():


EXTENSIONS = _get_path_extensions()
_CONF_VAR_RE = re.compile(r"\{\w+\}")
_CONF_VAR_RE = re.compile(r"\{\w+}")


class PythonInfo:
class PythonInfo: # noqa: PLR0904
"""Contains information for a Python interpreter."""

def __init__(self) -> None: # noqa: PLR0915
Expand Down Expand Up @@ -135,6 +135,7 @@ def abs_path(v):
self.system_stdlib = self.sysconfig_path("stdlib", confs)
self.system_stdlib_platform = self.sysconfig_path("platstdlib", confs)
self.max_size = getattr(sys, "maxsize", getattr(sys, "maxint", None))
self._creators = None

@staticmethod
def _get_tcl_tk_libs():
Expand Down Expand Up @@ -310,6 +311,13 @@ def sysconfig_path(self, key, config_var=None, sep=os.sep):
config_var = base
return pattern.format(**config_var).replace("/", sep)

def creators(self, refresh=False): # noqa: FBT002
if self._creators is None or refresh is True:
from virtualenv.run.plugin.creators import CreatorSelector # noqa: PLC0415

self._creators = CreatorSelector.for_interpreter(self)
return self._creators

@property
def system_include(self):
path = self.sysconfig_path(
Expand Down Expand Up @@ -423,7 +431,7 @@ def satisfies(self, spec, impl_must_match): # noqa: C901, PLR0911
_current = None

@classmethod
def current(cls, app_data, cache):
def current(cls, app_data=None, cache=None):
"""
This locates the current host interpreter information. This might be different than what we run into in case
the host python has been upgraded from underneath us.
Expand All @@ -439,7 +447,7 @@ def current(cls, app_data, cache):
return cls._current

@classmethod
def current_system(cls, app_data, cache) -> PythonInfo:
def current_system(cls, app_data=None, cache=None) -> PythonInfo:
"""
This locates the current host interpreter information. This might be different than what we run into in case
the host python has been upgraded from underneath us.
Expand Down Expand Up @@ -467,8 +475,8 @@ def _to_dict(self):
def from_exe( # noqa: PLR0913
cls,
exe,
app_data,
cache,
app_data=None,
cache=None,
raise_on_error=True, # noqa: FBT002
ignore_cache=False, # noqa: FBT002
resolve_to_host=True, # noqa: FBT002
Expand All @@ -480,13 +488,7 @@ def from_exe( # noqa: PLR0913

env = os.environ if env is None else env
proposed = from_exe_cache(
cls,
app_data,
exe,
env=env,
raise_on_error=raise_on_error,
ignore_cache=ignore_cache,
cache=cache,
cls, app_data, exe, env=env, raise_on_error=raise_on_error, ignore_cache=ignore_cache, cache=cache
)

if isinstance(proposed, PythonInfo) and resolve_to_host:
Expand Down Expand Up @@ -538,7 +540,7 @@ def _resolve_to_system(cls, app_data, target, cache):

_cache_exe_discovery = {} # noqa: RUF012

def discover_exe(self, app_data, cache, prefix, exact=True, env=None): # noqa: FBT002
def discover_exe(self, app_data, prefix, exact=True, env=None, cache=None): # noqa: FBT002
key = prefix, exact
if key in self._cache_exe_discovery and prefix:
LOGGER.debug("discover exe from cache %s - exact %s: %r", prefix, exact, self._cache_exe_discovery[key])
Expand Down Expand Up @@ -568,14 +570,7 @@ def _check_exe(self, app_data, cache, folder, name, exact, discovered, env): #
exe_path = os.path.join(folder, name)
if not os.path.exists(exe_path):
return None
info = self.from_exe(
exe_path,
app_data,
cache,
resolve_to_host=False,
raise_on_error=False,
env=env,
)
info = self.from_exe(exe_path, app_data, cache, resolve_to_host=False, raise_on_error=False, env=env)
if info is None: # ignore if for some reason we can't query
return None
for item in ["implementation", "architecture", "version_info"]:
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/create/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def venv(tmp_path_factory, session_app_data, current_info):
# sadly creating a virtual environment does not tell us where the executable lives in general case
# so discover using some heuristic
cache = FileCache(session_app_data.py_info, session_app_data.py_info_clear)
return current_info.discover_exe(session_app_data, cache, prefix=str(dest)).original_executable
return current_info.discover_exe(session_app_data, prefix=str(dest), cache=cache).original_executable


PYTHON = {
Expand Down
6 changes: 3 additions & 3 deletions tests/unit/discovery/py_info/test_py_info_exe_based_of.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
def test_discover_empty_folder(tmp_path):
app_data, cache = MockAppData(), MockCache()
with pytest.raises(RuntimeError):
CURRENT.discover_exe(app_data, cache, prefix=str(tmp_path))
CURRENT.discover_exe(app_data, prefix=str(tmp_path), cache=cache)


BASE = (CURRENT.install_path("scripts"), ".")
Expand All @@ -43,7 +43,7 @@ def test_discover_ok(tmp_path, suffix, impl, version, arch, into, caplog): # no
if pyvenv.exists():
(folder / pyvenv.name).write_text(pyvenv.read_text(encoding="utf-8"), encoding="utf-8")
inside_folder = str(tmp_path)
base = CURRENT.discover_exe(app_data, cache, inside_folder)
base = CURRENT.discover_exe(app_data, inside_folder, cache=cache)
found = base.executable
dest_str = str(dest)
if not fs_is_case_sensitive():
Expand All @@ -56,4 +56,4 @@ def test_discover_ok(tmp_path, suffix, impl, version, arch, into, caplog): # no
dest.rename(dest.parent / (dest.name + "-1"))
CURRENT._cache_exe_discovery.clear() # noqa: SLF001
with pytest.raises(RuntimeError):
CURRENT.discover_exe(app_data, cache, inside_folder)
CURRENT.discover_exe(app_data, inside_folder, cache=cache)
Loading