python-discovery 1.3.2__tar.gz → 1.4.0__tar.gz

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.
Files changed (57) hide show
  1. {python_discovery-1.3.2 → python_discovery-1.4.0}/PKG-INFO +1 -1
  2. {python_discovery-1.3.2 → python_discovery-1.4.0}/docs/changelog.rst +9 -0
  3. {python_discovery-1.3.2 → python_discovery-1.4.0}/src/python_discovery/_py_info.py +9 -9
  4. {python_discovery-1.3.2 → python_discovery-1.4.0}/tests/py_info/test_py_info.py +23 -0
  5. {python_discovery-1.3.2 → python_discovery-1.4.0}/.github/FUNDING.yaml +0 -0
  6. {python_discovery-1.3.2 → python_discovery-1.4.0}/.github/SECURITY.md +0 -0
  7. {python_discovery-1.3.2 → python_discovery-1.4.0}/.github/dependabot.yaml +0 -0
  8. {python_discovery-1.3.2 → python_discovery-1.4.0}/.github/release.yaml +0 -0
  9. {python_discovery-1.3.2 → python_discovery-1.4.0}/.github/workflows/check.yaml +0 -0
  10. {python_discovery-1.3.2 → python_discovery-1.4.0}/.github/workflows/prepare-release.yaml +0 -0
  11. {python_discovery-1.3.2 → python_discovery-1.4.0}/.github/workflows/release.yaml +0 -0
  12. {python_discovery-1.3.2 → python_discovery-1.4.0}/.gitignore +0 -0
  13. {python_discovery-1.3.2 → python_discovery-1.4.0}/.pre-commit-config.yaml +0 -0
  14. {python_discovery-1.3.2 → python_discovery-1.4.0}/.readthedocs.yaml +0 -0
  15. {python_discovery-1.3.2 → python_discovery-1.4.0}/.readthedocs.yml +0 -0
  16. {python_discovery-1.3.2 → python_discovery-1.4.0}/CODE_OF_CONDUCT.md +0 -0
  17. {python_discovery-1.3.2 → python_discovery-1.4.0}/LICENSE +0 -0
  18. {python_discovery-1.3.2 → python_discovery-1.4.0}/README.md +0 -0
  19. {python_discovery-1.3.2 → python_discovery-1.4.0}/docs/_static/custom.css +0 -0
  20. {python_discovery-1.3.2 → python_discovery-1.4.0}/docs/_static/logo.svg +0 -0
  21. {python_discovery-1.3.2 → python_discovery-1.4.0}/docs/changelog/template.jinja2 +0 -0
  22. {python_discovery-1.3.2 → python_discovery-1.4.0}/docs/conf.py +0 -0
  23. {python_discovery-1.3.2 → python_discovery-1.4.0}/docs/explanation.rst +0 -0
  24. {python_discovery-1.3.2 → python_discovery-1.4.0}/docs/how-to/standalone-usage.rst +0 -0
  25. {python_discovery-1.3.2 → python_discovery-1.4.0}/docs/index.rst +0 -0
  26. {python_discovery-1.3.2 → python_discovery-1.4.0}/docs/reference/api.rst +0 -0
  27. {python_discovery-1.3.2 → python_discovery-1.4.0}/docs/reference/environment-variables.rst +0 -0
  28. {python_discovery-1.3.2 → python_discovery-1.4.0}/docs/tutorial/getting-started.rst +0 -0
  29. {python_discovery-1.3.2 → python_discovery-1.4.0}/pyproject.toml +0 -0
  30. {python_discovery-1.3.2 → python_discovery-1.4.0}/src/python_discovery/__init__.py +0 -0
  31. {python_discovery-1.3.2 → python_discovery-1.4.0}/src/python_discovery/_cache.py +0 -0
  32. {python_discovery-1.3.2 → python_discovery-1.4.0}/src/python_discovery/_cached_py_info.py +0 -0
  33. {python_discovery-1.3.2 → python_discovery-1.4.0}/src/python_discovery/_compat.py +0 -0
  34. {python_discovery-1.3.2 → python_discovery-1.4.0}/src/python_discovery/_discovery.py +0 -0
  35. {python_discovery-1.3.2 → python_discovery-1.4.0}/src/python_discovery/_py_spec.py +0 -0
  36. {python_discovery-1.3.2 → python_discovery-1.4.0}/src/python_discovery/_specifier.py +0 -0
  37. {python_discovery-1.3.2 → python_discovery-1.4.0}/src/python_discovery/_windows/__init__.py +0 -0
  38. {python_discovery-1.3.2 → python_discovery-1.4.0}/src/python_discovery/_windows/_pep514.py +0 -0
  39. {python_discovery-1.3.2 → python_discovery-1.4.0}/src/python_discovery/_windows/_propose.py +0 -0
  40. {python_discovery-1.3.2 → python_discovery-1.4.0}/src/python_discovery/py.typed +0 -0
  41. {python_discovery-1.3.2 → python_discovery-1.4.0}/tasks/release.py +0 -0
  42. {python_discovery-1.3.2 → python_discovery-1.4.0}/tests/conftest.py +0 -0
  43. {python_discovery-1.3.2 → python_discovery-1.4.0}/tests/py_info/test_py_info_exe_based_of.py +0 -0
  44. {python_discovery-1.3.2 → python_discovery-1.4.0}/tests/test_cache.py +0 -0
  45. {python_discovery-1.3.2 → python_discovery-1.4.0}/tests/test_cached_py_info.py +0 -0
  46. {python_discovery-1.3.2 → python_discovery-1.4.0}/tests/test_discovery.py +0 -0
  47. {python_discovery-1.3.2 → python_discovery-1.4.0}/tests/test_discovery_extra.py +0 -0
  48. {python_discovery-1.3.2 → python_discovery-1.4.0}/tests/test_iter_interpreters.py +0 -0
  49. {python_discovery-1.3.2 → python_discovery-1.4.0}/tests/test_py_info_extra.py +0 -0
  50. {python_discovery-1.3.2 → python_discovery-1.4.0}/tests/test_py_spec.py +0 -0
  51. {python_discovery-1.3.2 → python_discovery-1.4.0}/tests/test_py_spec_extra.py +0 -0
  52. {python_discovery-1.3.2 → python_discovery-1.4.0}/tests/test_specifier.py +0 -0
  53. {python_discovery-1.3.2 → python_discovery-1.4.0}/tests/windows/conftest.py +0 -0
  54. {python_discovery-1.3.2 → python_discovery-1.4.0}/tests/windows/test_windows.py +0 -0
  55. {python_discovery-1.3.2 → python_discovery-1.4.0}/tests/windows/test_windows_pep514.py +0 -0
  56. {python_discovery-1.3.2 → python_discovery-1.4.0}/tests/windows/winreg_mock_values.py +0 -0
  57. {python_discovery-1.3.2 → python_discovery-1.4.0}/tox.toml +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-discovery
3
- Version: 1.3.2
3
+ Version: 1.4.0
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
@@ -6,6 +6,15 @@
6
6
 
7
7
  .. towncrier release notes start
8
8
 
9
+ ********************
10
+ v1.4.0 (2026-05-28)
11
+ ********************
12
+
13
+ Features - 1.4.0
14
+ ================
15
+ - Add ``debug_build`` attribute to :class:`PythonInfo` exposing whether the interpreter is a debug build
16
+ (``Py_DEBUG``) - by :user:`gaborbernat`. (:issue:`80`)
17
+
9
18
  ********************
10
19
  v1.3.2 (2026-05-27)
11
20
  ********************
@@ -12,6 +12,7 @@ import sys
12
12
  import sysconfig
13
13
  import warnings
14
14
  from collections import OrderedDict
15
+ from itertools import product
15
16
  from string import digits
16
17
  from typing import TYPE_CHECKING, ClassVar, Final, NamedTuple
17
18
 
@@ -73,6 +74,7 @@ class PythonInfo: # noqa: PLR0904
73
74
  self.version = sys.version
74
75
  self.os = os.name
75
76
  self.free_threaded = sysconfig.get_config_var("Py_GIL_DISABLED") == 1
77
+ self.debug_build = bool(sysconfig.get_config_var("Py_DEBUG"))
76
78
 
77
79
  def _init_prefixes(self) -> None:
78
80
  def abs_path(value: str | None) -> str | None:
@@ -404,10 +406,11 @@ class PythonInfo: # noqa: PLR0904
404
406
  @property
405
407
  def spec(self) -> str:
406
408
  """A specification string identifying this interpreter (e.g. ``CPython3.13.2-64-arm64``)."""
407
- return "{}{}{}-{}-{}".format(
409
+ return "{}{}{}{}-{}-{}".format(
408
410
  self.implementation,
409
411
  ".".join(str(i) for i in self.version_info),
410
412
  "t" if self.free_threaded else "",
413
+ "d" if self.debug_build else "",
411
414
  self.architecture,
412
415
  self.machine,
413
416
  )
@@ -731,17 +734,14 @@ class PythonInfo: # noqa: PLR0904
731
734
 
732
735
  def _find_possible_exe_names(self) -> list[str]:
733
736
  name_candidate = OrderedDict()
737
+ mods = ["", "t"] if self.free_threaded else [""]
738
+ debug_suffixes = ["_d", ""] if self.debug_build else [""]
739
+ archs = [f"-{self.architecture}", ""]
734
740
  for name in self._possible_base():
735
741
  for at in (3, 2, 1, 0):
736
742
  version = ".".join(str(i) for i in self.version_info[:at])
737
- mods = [""]
738
- if self.free_threaded:
739
- mods.append("t")
740
- for mod in mods:
741
- for arch in [f"-{self.architecture}", ""]:
742
- for ext in EXTENSIONS:
743
- candidate = f"{name}{version}{mod}{arch}{ext}"
744
- name_candidate[candidate] = None
743
+ for mod, debug, arch, ext in product(mods, debug_suffixes, archs, EXTENSIONS):
744
+ name_candidate[f"{name}{version}{mod}{debug}{arch}{ext}"] = None
745
745
  return list(name_candidate.keys())
746
746
 
747
747
  def _possible_base(self) -> Generator[str, None, None]:
@@ -40,6 +40,7 @@ def test_current_as_json() -> None:
40
40
  "serial": serial,
41
41
  }
42
42
  assert parsed["free_threaded"] is free_threaded
43
+ assert parsed["debug_build"] is bool(sysconfig.get_config_var("Py_DEBUG"))
43
44
 
44
45
 
45
46
  def test_bad_exe_py_info_raise(tmp_path: Path, session_cache: DiskCache) -> None:
@@ -418,6 +419,28 @@ def test_py_info_satisfies_machine_cross_os_normalization(platform: str, spec_ma
418
419
  assert info.satisfies(spec, impl_must_match=True) is True
419
420
 
420
421
 
422
+ @pytest.mark.parametrize("debug", [True, False], ids=["debug", "release"])
423
+ def test_py_info_debug_build_in_spec(*, debug: bool) -> None:
424
+ info = copy.deepcopy(CURRENT)
425
+ info.debug_build = debug
426
+ assert ("d-" in info.spec) is debug
427
+
428
+
429
+ @pytest.mark.parametrize("debug", [True, False], ids=["debug", "release"])
430
+ def test_py_info_debug_build_exe_names(*, debug: bool) -> None:
431
+ info = copy.deepcopy(CURRENT)
432
+ info.debug_build = debug
433
+ names = info._find_possible_exe_names()
434
+ assert any("_d" in n for n in names) is debug
435
+
436
+
437
+ def test_py_info_debug_build_json_round_trip() -> None:
438
+ info = copy.deepcopy(CURRENT)
439
+ info.debug_build = True
440
+ restored = PythonInfo.from_json(info.to_json())
441
+ assert restored.debug_build is True
442
+
443
+
421
444
  def test_py_info_to_dict_includes_sysconfig_platform() -> None:
422
445
  data = CURRENT.to_dict()
423
446
  assert "sysconfig_platform" in data