ducktools-pythonfinder 0.5.1__tar.gz → 0.5.3__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 (38) hide show
  1. {ducktools_pythonfinder-0.5.1/src/ducktools_pythonfinder.egg-info → ducktools_pythonfinder-0.5.3}/PKG-INFO +1 -1
  2. ducktools_pythonfinder-0.5.3/src/ducktools/pythonfinder/_version.py +2 -0
  3. {ducktools_pythonfinder-0.5.1 → ducktools_pythonfinder-0.5.3}/src/ducktools/pythonfinder/linux/__init__.py +17 -8
  4. {ducktools_pythonfinder-0.5.1 → ducktools_pythonfinder-0.5.3}/src/ducktools/pythonfinder/pythonorg_search.py +29 -1
  5. {ducktools_pythonfinder-0.5.1 → ducktools_pythonfinder-0.5.3}/src/ducktools/pythonfinder/shared.py +2 -2
  6. {ducktools_pythonfinder-0.5.1 → ducktools_pythonfinder-0.5.3/src/ducktools_pythonfinder.egg-info}/PKG-INFO +1 -1
  7. {ducktools_pythonfinder-0.5.1 → ducktools_pythonfinder-0.5.3}/tests/test_orgsearch.py +18 -0
  8. ducktools_pythonfinder-0.5.1/src/ducktools/pythonfinder/_version.py +0 -2
  9. {ducktools_pythonfinder-0.5.1 → ducktools_pythonfinder-0.5.3}/.gitignore +0 -0
  10. {ducktools_pythonfinder-0.5.1 → ducktools_pythonfinder-0.5.3}/LICENSE +0 -0
  11. {ducktools_pythonfinder-0.5.1 → ducktools_pythonfinder-0.5.3}/MANIFEST.in +0 -0
  12. {ducktools_pythonfinder-0.5.1 → ducktools_pythonfinder-0.5.3}/README.md +0 -0
  13. {ducktools_pythonfinder-0.5.1 → ducktools_pythonfinder-0.5.3}/pyproject.toml +0 -0
  14. {ducktools_pythonfinder-0.5.1 → ducktools_pythonfinder-0.5.3}/scripts/build_zipapp.py +0 -0
  15. {ducktools_pythonfinder-0.5.1 → ducktools_pythonfinder-0.5.3}/scripts/detail_this_python.py +0 -0
  16. {ducktools_pythonfinder-0.5.1 → ducktools_pythonfinder-0.5.3}/scripts/print_python_versions.py +0 -0
  17. {ducktools_pythonfinder-0.5.1 → ducktools_pythonfinder-0.5.3}/setup.cfg +0 -0
  18. {ducktools_pythonfinder-0.5.1 → ducktools_pythonfinder-0.5.3}/src/ducktools/pythonfinder/__init__.py +0 -0
  19. {ducktools_pythonfinder-0.5.1 → ducktools_pythonfinder-0.5.3}/src/ducktools/pythonfinder/__main__.py +0 -0
  20. {ducktools_pythonfinder-0.5.1 → ducktools_pythonfinder-0.5.3}/src/ducktools/pythonfinder/darwin/__init__.py +0 -0
  21. {ducktools_pythonfinder-0.5.1 → ducktools_pythonfinder-0.5.3}/src/ducktools/pythonfinder/details_script.py +0 -0
  22. {ducktools_pythonfinder-0.5.1 → ducktools_pythonfinder-0.5.3}/src/ducktools/pythonfinder/linux/pyenv_search.py +0 -0
  23. {ducktools_pythonfinder-0.5.1 → ducktools_pythonfinder-0.5.3}/src/ducktools/pythonfinder/win32/__init__.py +0 -0
  24. {ducktools_pythonfinder-0.5.1 → ducktools_pythonfinder-0.5.3}/src/ducktools/pythonfinder/win32/pyenv_search.py +0 -0
  25. {ducktools_pythonfinder-0.5.1 → ducktools_pythonfinder-0.5.3}/src/ducktools/pythonfinder/win32/registry_search.py +0 -0
  26. {ducktools_pythonfinder-0.5.1 → ducktools_pythonfinder-0.5.3}/src/ducktools_pythonfinder.egg-info/SOURCES.txt +0 -0
  27. {ducktools_pythonfinder-0.5.1 → ducktools_pythonfinder-0.5.3}/src/ducktools_pythonfinder.egg-info/dependency_links.txt +0 -0
  28. {ducktools_pythonfinder-0.5.1 → ducktools_pythonfinder-0.5.3}/src/ducktools_pythonfinder.egg-info/entry_points.txt +0 -0
  29. {ducktools_pythonfinder-0.5.1 → ducktools_pythonfinder-0.5.3}/src/ducktools_pythonfinder.egg-info/requires.txt +0 -0
  30. {ducktools_pythonfinder-0.5.1 → ducktools_pythonfinder-0.5.3}/src/ducktools_pythonfinder.egg-info/top_level.txt +0 -0
  31. {ducktools_pythonfinder-0.5.1 → ducktools_pythonfinder-0.5.3}/tests/conftest.py +0 -0
  32. {ducktools_pythonfinder-0.5.1 → ducktools_pythonfinder-0.5.3}/tests/sources/python_versions.txt +0 -0
  33. {ducktools_pythonfinder-0.5.1 → ducktools_pythonfinder-0.5.3}/tests/sources/release.json +0 -0
  34. {ducktools_pythonfinder-0.5.1 → ducktools_pythonfinder-0.5.3}/tests/sources/release_file.json +0 -0
  35. {ducktools_pythonfinder-0.5.1 → ducktools_pythonfinder-0.5.3}/tests/test_details_script.py +0 -0
  36. {ducktools_pythonfinder-0.5.1 → ducktools_pythonfinder-0.5.3}/tests/test_foldersearch.py +0 -0
  37. {ducktools_pythonfinder-0.5.1 → ducktools_pythonfinder-0.5.3}/tests/test_pyenv.py +0 -0
  38. {ducktools_pythonfinder-0.5.1 → ducktools_pythonfinder-0.5.3}/tests/test_shared.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ducktools-pythonfinder
3
- Version: 0.5.1
3
+ Version: 0.5.3
4
4
  Summary: Cross platform tool to find available python installations
5
5
  Author: David C Ellis
6
6
  Project-URL: Homepage, https://github.com/davidcellis/ducktools-pythonfinder
@@ -0,0 +1,2 @@
1
+ __version__ = "0.5.3"
2
+ __version_tuple__ = (0, 5, 3)
@@ -27,22 +27,31 @@ import os.path
27
27
  import itertools
28
28
  from _collections_abc import Iterator
29
29
 
30
- from ..shared import PythonInstall, get_folder_pythons, get_uv_pythons
30
+ from ..shared import PythonInstall, get_folder_pythons, get_uv_pythons, get_uv_python_path
31
31
  from .pyenv_search import get_pyenv_pythons
32
32
 
33
33
 
34
- PATH_FOLDERS = os.environ.get("PATH").split(":")
35
- _PYENV_ROOT = os.environ.get("PYENV_ROOT")
36
-
37
-
38
34
  def get_path_pythons() -> Iterator[PythonInstall]:
39
35
  exe_names = set()
40
36
 
41
- for fld in PATH_FOLDERS:
37
+ path_folders = os.environ.get("PATH").split(":")
38
+ pyenv_root = os.environ.get("PYENV_ROOT")
39
+ uv_root = get_uv_python_path()
40
+
41
+ excluded_folders = [pyenv_root, uv_root]
42
+
43
+ for fld in path_folders:
42
44
  # Don't retrieve pyenv installs
43
- if _PYENV_ROOT and fld.startswith(_PYENV_ROOT):
45
+ skip_folder = False
46
+ for exclude in excluded_folders:
47
+ if exclude and fld.startswith(exclude):
48
+ skip_folder = True
49
+ break
50
+
51
+ if skip_folder:
44
52
  continue
45
- elif not os.path.exists(fld):
53
+
54
+ if not os.path.exists(fld):
46
55
  continue
47
56
 
48
57
  for install in get_folder_pythons(fld):
@@ -322,7 +322,7 @@ class PythonOrgSearch(Prefab):
322
322
 
323
323
  return latest_binaries
324
324
 
325
- def latest_binary_match(self, specifier: SpecifierSet, prereleases=False) -> PythonDownload:
325
+ def latest_binary_match(self, specifier: SpecifierSet, prereleases=False) -> PythonDownload | None:
326
326
  """
327
327
  Get the latest binary (source on linux) download that matches a given specifier set
328
328
 
@@ -335,3 +335,31 @@ class PythonOrgSearch(Prefab):
335
335
  for download in self.matching_downloads(specifier, prereleases):
336
336
  if download.url.endswith(tag):
337
337
  return download
338
+
339
+ def latest_python_download(self, prereleases=False) -> PythonDownload | None:
340
+ """
341
+ Get the absolute latest python release.
342
+ :param prereleases: Include prereleases
343
+ :return: PythonDownload object or None
344
+ """
345
+ tags = get_download_tags(system=self.system, machine=self.machine)
346
+
347
+ release = None
348
+ for r in self.releases:
349
+ if not prereleases and r.pre_release:
350
+ continue
351
+ release = r
352
+ break
353
+
354
+ if release:
355
+ for release_file in self.release_files:
356
+ if release_file.release == release.resource_uri:
357
+ for tag in tags:
358
+ if release_file.url.endswith(tag):
359
+ download = PythonDownload(
360
+ name=release.name,
361
+ version=release.version_str,
362
+ url=release_file.url,
363
+ md5_sum=release_file.md5_sum,
364
+ )
365
+ return download
@@ -249,7 +249,7 @@ def get_folder_pythons(
249
249
 
250
250
 
251
251
  # UV Specific finder
252
- def _get_uv_python_path() -> str | None:
252
+ def get_uv_python_path() -> str | None:
253
253
  try:
254
254
  uv_python_find = _laz.subprocess.run(
255
255
  ["uv", "python", "dir"],
@@ -297,7 +297,7 @@ def _implementation_from_uv_dir(direntry: os.DirEntry) -> PythonInstall | None:
297
297
  def get_uv_pythons() -> Iterator[PythonInstall]:
298
298
  # This takes some shortcuts over the regular pythonfinder
299
299
  # As the UV folders give the python version and the implementation
300
- if uv_python_path := _get_uv_python_path():
300
+ if uv_python_path := get_uv_python_path():
301
301
  with os.scandir(uv_python_path) as fld:
302
302
  for f in fld:
303
303
  if f.is_dir() and (install := _implementation_from_uv_dir(f)):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ducktools-pythonfinder
3
- Version: 0.5.1
3
+ Version: 0.5.3
4
4
  Summary: Cross platform tool to find available python installations
5
5
  Author: David C Ellis
6
6
  Project-URL: Homepage, https://github.com/davidcellis/ducktools-pythonfinder
@@ -121,6 +121,12 @@ class TestWindows:
121
121
  assert match.version == "3.13.0rc1"
122
122
  assert match.is_prerelease is True
123
123
 
124
+ def test_latest_download(self, searcher):
125
+ s = searcher(self.system, self.machine)
126
+ download = s.latest_python_download()
127
+ assert download.version == "3.12.5"
128
+ assert download.url.endswith("3.12.5-amd64.exe")
129
+
124
130
 
125
131
  class TestMacOS:
126
132
  system = "Darwin"
@@ -168,6 +174,12 @@ class TestMacOS:
168
174
  for v in all_bins:
169
175
  assert any(v.url.endswith(tag) for tag in tags)
170
176
 
177
+ def test_latest_download(self, searcher):
178
+ s = searcher(self.system, self.machine)
179
+ download = s.latest_python_download()
180
+ assert download.version == "3.12.5"
181
+ assert download.url.endswith("3.12.5-macos11.pkg")
182
+
171
183
 
172
184
  class TestLinux:
173
185
  system = "Linux"
@@ -214,3 +226,9 @@ class TestLinux:
214
226
 
215
227
  for v in all_bins:
216
228
  assert any(v.url.endswith(tag) for tag in tags)
229
+
230
+ def test_latest_download(self, searcher):
231
+ s = searcher(self.system, self.machine)
232
+ download = s.latest_python_download()
233
+ assert download.version == "3.12.5"
234
+ assert download.url.endswith("3.12.5.tgz")
@@ -1,2 +0,0 @@
1
- __version__ = "0.5.1"
2
- __version_tuple__ = (0, 5, 1)