python-discovery 1.4.1__py3-none-any.whl → 1.4.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -225,21 +225,28 @@ class PythonInfo: # noqa: PLR0904
225
225
  # Try fallback for POSIX virtual environments
226
226
  return self._try_posix_fallback_executable(base_executable) # pragma: >=3.11 cover
227
227
 
228
- def _resolve_executable_symlink(self, path: str) -> str:
228
+ def _resolve_executable_symlink(self, path: str, *, framework: bool | None = None) -> str:
229
229
  """
230
230
  Resolve symlinks of the executable itself, but never of its parent directories.
231
231
 
232
232
  Mirrors CPython's ``getpath.realpath`` (and ``venv`` in python/cpython#115237): an executable-only symlink
233
233
  resolves to the real interpreter so its home can be located, while a fully symlinked interpreter tree is
234
- kept as-is.
234
+ kept as-is. Like ``getpath``, resolution stops as soon as the stdlib landmark is reachable from the current
235
+ directory - an alias such as Debian's ``/usr/bin/python3`` is a usable home and stays untouched.
235
236
  """
236
237
  result = os.path.abspath(path)
237
238
  if self.os != "posix": # CPython only does this where HAVE_READLINK
238
239
  return result
240
+ if framework is None:
241
+ framework = bool(sysconfig.get_config_var("PYTHONFRAMEWORK"))
242
+ if framework: # macOS framework builds self-locate via dyld from the real binary; e.g. for Homebrew
243
+ return result # resolving would pin the versioned Cellar path into the recorded home
239
244
  real_path = os.path.realpath(result)
240
245
  if not os.path.exists(real_path): # symlink loop or broken symlink
241
246
  return result
242
247
  while os.path.islink(result):
248
+ if self._stdlib_landmark_exists(os.path.dirname(result)):
249
+ return result
243
250
  link = os.readlink(result)
244
251
  candidate = link if os.path.isabs(link) else os.path.normpath(os.path.join(os.path.dirname(result), link))
245
252
  # normpath through a symlinked directory may point at a different file - stop resolving there
@@ -248,6 +255,13 @@ class PythonInfo: # noqa: PLR0904
248
255
  result = candidate
249
256
  return result
250
257
 
258
+ @staticmethod
259
+ def _stdlib_landmark_exists(dir_path: str) -> bool:
260
+ lib_name = os.path.basename(os.path.dirname(os.__file__))
261
+ return any(
262
+ os.path.exists(os.path.join(dir_path, os.pardir, lib, lib_name, "os.py")) for lib in ("lib", "lib64")
263
+ )
264
+
251
265
  def _try_posix_fallback_executable(self, base_executable: str) -> str | None:
252
266
  """Find a versioned Python binary as fallback for POSIX virtual environments."""
253
267
  major, minor = self.version_info.major, self.version_info.minor
@@ -415,7 +429,7 @@ class PythonInfo: # noqa: PLR0904
415
429
 
416
430
  @property
417
431
  def machine(self) -> str:
418
- """Return the instruction set architecture (ISA) derived from :func:`sysconfig.get_platform`."""
432
+ """The instruction set architecture (ISA) derived from :func:`sysconfig.get_platform`."""
419
433
  plat = self.sysconfig_platform
420
434
  if plat is None:
421
435
  return "unknown"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-discovery
3
- Version: 1.4.1
3
+ Version: 1.4.3
4
4
  Summary: Python interpreter discovery
5
5
  Project-URL: Changelog, https://github.com/tox-dev/python-discovery/releases
6
6
  Project-URL: Documentation, https://python-discovery.readthedocs.io
@@ -3,14 +3,14 @@ python_discovery/_cache.py,sha256=bG4fD-h2pdPmb4v9BldbXmJ5Tlt1boiH1Qrz8kp9Dds,50
3
3
  python_discovery/_cached_py_info.py,sha256=1AFEoc_-OaCi1PXmaFz9Iy_bEuqOhJdFSDFHljzD-EE,8540
4
4
  python_discovery/_compat.py,sha256=iqxGuhK9rPaiui80G1H1KrweoMJ16gyLYEmUrSXrp5c,709
5
5
  python_discovery/_discovery.py,sha256=cdo6xlktNMEwsQn2R8pn4T1VDE4LD2EJPUyCT7vlHnM,16830
6
- python_discovery/_py_info.py,sha256=Pd-rZhulxTWCoEa2SaEH2MLm8oeNzjWzpgAFmZ5oIic,35723
6
+ python_discovery/_py_info.py,sha256=7e4Ei810L2uS-JuqNdiCHvgyb-R4gj_5VrtN3yNtIAg,36647
7
7
  python_discovery/_py_spec.py,sha256=Kky0LXi8BU_ojfMdvvRhtDk6I4WPjovwXOu6E2QYHTo,10421
8
8
  python_discovery/_specifier.py,sha256=PTh6suNTC0hMnFSxFYF_vggdciFLnwxoh1YflSbgCXA,10368
9
9
  python_discovery/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
10
  python_discovery/_windows/__init__.py,sha256=qthcyGh36b3WkeSbZ4ECRRYLbCOCaQu5X_DRZ98tXfk,315
11
11
  python_discovery/_windows/_pep514.py,sha256=zXxje07QIXfrCB3eYbZHOBgXcvAQQpZ-ZWun3_zrapA,7688
12
12
  python_discovery/_windows/_propose.py,sha256=iMJf6l0TU4SvuV8UsCHHINAe9L5dUT949xyeyMVdong,1565
13
- python_discovery-1.4.1.dist-info/METADATA,sha256=g-gwW8yAGaOFpbnCZoxY4fTQ3KBrGzYYadpCvbZjRcc,5592
14
- python_discovery-1.4.1.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
15
- python_discovery-1.4.1.dist-info/licenses/LICENSE,sha256=kOJeH68qSq6o2V7o5_VziwUqGswMnFgGgQH5Mahr1Yg,1023
16
- python_discovery-1.4.1.dist-info/RECORD,,
13
+ python_discovery-1.4.3.dist-info/METADATA,sha256=_9Cm3smElV4lgueLcYMDdHjFzo66tjO1tqH-K6KwkG0,5592
14
+ python_discovery-1.4.3.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
15
+ python_discovery-1.4.3.dist-info/licenses/LICENSE,sha256=kOJeH68qSq6o2V7o5_VziwUqGswMnFgGgQH5Mahr1Yg,1023
16
+ python_discovery-1.4.3.dist-info/RECORD,,