ducktools-pythonfinder 0.4.7__tar.gz → 0.5.1__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.
- {ducktools_pythonfinder-0.4.7/src/ducktools_pythonfinder.egg-info → ducktools_pythonfinder-0.5.1}/PKG-INFO +16 -5
- {ducktools_pythonfinder-0.4.7 → ducktools_pythonfinder-0.5.1}/README.md +15 -4
- {ducktools_pythonfinder-0.4.7 → ducktools_pythonfinder-0.5.1}/pyproject.toml +3 -0
- ducktools_pythonfinder-0.5.1/src/ducktools/pythonfinder/_version.py +2 -0
- {ducktools_pythonfinder-0.4.7 → ducktools_pythonfinder-0.5.1}/src/ducktools/pythonfinder/linux/__init__.py +6 -2
- {ducktools_pythonfinder-0.4.7 → ducktools_pythonfinder-0.5.1}/src/ducktools/pythonfinder/shared.py +60 -1
- {ducktools_pythonfinder-0.4.7 → ducktools_pythonfinder-0.5.1}/src/ducktools/pythonfinder/win32/__init__.py +6 -2
- {ducktools_pythonfinder-0.4.7 → ducktools_pythonfinder-0.5.1/src/ducktools_pythonfinder.egg-info}/PKG-INFO +16 -5
- {ducktools_pythonfinder-0.4.7 → ducktools_pythonfinder-0.5.1}/src/ducktools_pythonfinder.egg-info/SOURCES.txt +1 -0
- ducktools_pythonfinder-0.5.1/src/ducktools_pythonfinder.egg-info/entry_points.txt +2 -0
- ducktools_pythonfinder-0.4.7/src/ducktools/pythonfinder/_version.py +0 -2
- {ducktools_pythonfinder-0.4.7 → ducktools_pythonfinder-0.5.1}/.gitignore +0 -0
- {ducktools_pythonfinder-0.4.7 → ducktools_pythonfinder-0.5.1}/LICENSE +0 -0
- {ducktools_pythonfinder-0.4.7 → ducktools_pythonfinder-0.5.1}/MANIFEST.in +0 -0
- {ducktools_pythonfinder-0.4.7 → ducktools_pythonfinder-0.5.1}/scripts/build_zipapp.py +0 -0
- {ducktools_pythonfinder-0.4.7 → ducktools_pythonfinder-0.5.1}/scripts/detail_this_python.py +0 -0
- {ducktools_pythonfinder-0.4.7 → ducktools_pythonfinder-0.5.1}/scripts/print_python_versions.py +0 -0
- {ducktools_pythonfinder-0.4.7 → ducktools_pythonfinder-0.5.1}/setup.cfg +0 -0
- {ducktools_pythonfinder-0.4.7 → ducktools_pythonfinder-0.5.1}/src/ducktools/pythonfinder/__init__.py +0 -0
- {ducktools_pythonfinder-0.4.7 → ducktools_pythonfinder-0.5.1}/src/ducktools/pythonfinder/__main__.py +0 -0
- {ducktools_pythonfinder-0.4.7 → ducktools_pythonfinder-0.5.1}/src/ducktools/pythonfinder/darwin/__init__.py +0 -0
- {ducktools_pythonfinder-0.4.7 → ducktools_pythonfinder-0.5.1}/src/ducktools/pythonfinder/details_script.py +0 -0
- {ducktools_pythonfinder-0.4.7 → ducktools_pythonfinder-0.5.1}/src/ducktools/pythonfinder/linux/pyenv_search.py +0 -0
- {ducktools_pythonfinder-0.4.7 → ducktools_pythonfinder-0.5.1}/src/ducktools/pythonfinder/pythonorg_search.py +0 -0
- {ducktools_pythonfinder-0.4.7 → ducktools_pythonfinder-0.5.1}/src/ducktools/pythonfinder/win32/pyenv_search.py +0 -0
- {ducktools_pythonfinder-0.4.7 → ducktools_pythonfinder-0.5.1}/src/ducktools/pythonfinder/win32/registry_search.py +0 -0
- {ducktools_pythonfinder-0.4.7 → ducktools_pythonfinder-0.5.1}/src/ducktools_pythonfinder.egg-info/dependency_links.txt +0 -0
- {ducktools_pythonfinder-0.4.7 → ducktools_pythonfinder-0.5.1}/src/ducktools_pythonfinder.egg-info/requires.txt +0 -0
- {ducktools_pythonfinder-0.4.7 → ducktools_pythonfinder-0.5.1}/src/ducktools_pythonfinder.egg-info/top_level.txt +0 -0
- {ducktools_pythonfinder-0.4.7 → ducktools_pythonfinder-0.5.1}/tests/conftest.py +0 -0
- {ducktools_pythonfinder-0.4.7 → ducktools_pythonfinder-0.5.1}/tests/sources/python_versions.txt +0 -0
- {ducktools_pythonfinder-0.4.7 → ducktools_pythonfinder-0.5.1}/tests/sources/release.json +0 -0
- {ducktools_pythonfinder-0.4.7 → ducktools_pythonfinder-0.5.1}/tests/sources/release_file.json +0 -0
- {ducktools_pythonfinder-0.4.7 → ducktools_pythonfinder-0.5.1}/tests/test_details_script.py +0 -0
- {ducktools_pythonfinder-0.4.7 → ducktools_pythonfinder-0.5.1}/tests/test_foldersearch.py +0 -0
- {ducktools_pythonfinder-0.4.7 → ducktools_pythonfinder-0.5.1}/tests/test_orgsearch.py +0 -0
- {ducktools_pythonfinder-0.4.7 → ducktools_pythonfinder-0.5.1}/tests/test_pyenv.py +0 -0
- {ducktools_pythonfinder-0.4.7 → ducktools_pythonfinder-0.5.1}/tests/test_shared.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: ducktools-pythonfinder
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5.1
|
|
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
|
|
@@ -33,6 +33,11 @@ for Windows and MacOS or sources for Linux (as python.org does not provide linux
|
|
|
33
33
|
|
|
34
34
|
Requires Python >= 3.8 (but will discover older Python installs)
|
|
35
35
|
|
|
36
|
+
[Download the zipapp here](https://github.com/DavidCEllis/ducktools-pythonfinder/releases/latest/download/pythonfinder.pyz)
|
|
37
|
+
|
|
38
|
+
It is also available as a library on PyPI that can be installed with pip:
|
|
39
|
+
`python -m pip install ducktools-pythonfinder`
|
|
40
|
+
|
|
36
41
|
## Command Line Usage ##
|
|
37
42
|
|
|
38
43
|
`ducktools-pythonfinder` can be used as a module or as a bundled zipapp (as `pythonfinder.pyz`).
|
|
@@ -77,13 +82,19 @@ The module provides two main functions for searching for local python installs:
|
|
|
77
82
|
* `get_python_installs` is a generator that will yield each python version it discovers
|
|
78
83
|
* `list_python_installs` will take the python versions discovered by `get_python_installs`
|
|
79
84
|
and return a sorted list from newest to oldest python version discovered.
|
|
85
|
+
* For the purposes of sorting, prerelease versions are considered older than any released
|
|
86
|
+
version.
|
|
80
87
|
|
|
81
88
|
On Windows these methods will search the registry for PEP514 recorded python installs
|
|
82
|
-
before checking for any `pyenv-win` installs that have not been registered.
|
|
89
|
+
before checking for any `pyenv-win` installs that have not been registered. Finally, if
|
|
90
|
+
`uv` is available it will try to find Python installs managed by `uv`.
|
|
91
|
+
|
|
92
|
+
On Linux and MacOS this will search for `pyenv` installs first,
|
|
93
|
+
if `uv` is available it will then try to find `uv` managed python installs.
|
|
94
|
+
Finally it will search `PATH` for any other `python*` binaries that might be available.
|
|
83
95
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
to run a small script to identify the version.
|
|
96
|
+
If a python install is found twice (for instance a pyenv install in the windows registry)
|
|
97
|
+
it will only be returned the first time it is found.
|
|
87
98
|
|
|
88
99
|
The python installs will be returned as instances of `PythonInstall` which will
|
|
89
100
|
contain version info and executable path along with some other useful metadata.
|
|
@@ -5,6 +5,11 @@ for Windows and MacOS or sources for Linux (as python.org does not provide linux
|
|
|
5
5
|
|
|
6
6
|
Requires Python >= 3.8 (but will discover older Python installs)
|
|
7
7
|
|
|
8
|
+
[Download the zipapp here](https://github.com/DavidCEllis/ducktools-pythonfinder/releases/latest/download/pythonfinder.pyz)
|
|
9
|
+
|
|
10
|
+
It is also available as a library on PyPI that can be installed with pip:
|
|
11
|
+
`python -m pip install ducktools-pythonfinder`
|
|
12
|
+
|
|
8
13
|
## Command Line Usage ##
|
|
9
14
|
|
|
10
15
|
`ducktools-pythonfinder` can be used as a module or as a bundled zipapp (as `pythonfinder.pyz`).
|
|
@@ -49,13 +54,19 @@ The module provides two main functions for searching for local python installs:
|
|
|
49
54
|
* `get_python_installs` is a generator that will yield each python version it discovers
|
|
50
55
|
* `list_python_installs` will take the python versions discovered by `get_python_installs`
|
|
51
56
|
and return a sorted list from newest to oldest python version discovered.
|
|
57
|
+
* For the purposes of sorting, prerelease versions are considered older than any released
|
|
58
|
+
version.
|
|
52
59
|
|
|
53
60
|
On Windows these methods will search the registry for PEP514 recorded python installs
|
|
54
|
-
before checking for any `pyenv-win` installs that have not been registered.
|
|
61
|
+
before checking for any `pyenv-win` installs that have not been registered. Finally, if
|
|
62
|
+
`uv` is available it will try to find Python installs managed by `uv`.
|
|
63
|
+
|
|
64
|
+
On Linux and MacOS this will search for `pyenv` installs first,
|
|
65
|
+
if `uv` is available it will then try to find `uv` managed python installs.
|
|
66
|
+
Finally it will search `PATH` for any other `python*` binaries that might be available.
|
|
55
67
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
to run a small script to identify the version.
|
|
68
|
+
If a python install is found twice (for instance a pyenv install in the windows registry)
|
|
69
|
+
it will only be returned the first time it is found.
|
|
59
70
|
|
|
60
71
|
The python installs will be returned as instances of `PythonInstall` which will
|
|
61
72
|
contain version info and executable path along with some other useful metadata.
|
|
@@ -39,6 +39,9 @@ dynamic = ['version']
|
|
|
39
39
|
[project.optional-dependencies]
|
|
40
40
|
testing = ["pytest", "pytest-cov", "pyfakefs"]
|
|
41
41
|
|
|
42
|
+
[project.scripts]
|
|
43
|
+
"ducktools-pythonfinder" = "ducktools.pythonfinder.__main__:main"
|
|
44
|
+
|
|
42
45
|
[tool.setuptools.packages.find]
|
|
43
46
|
where = ["src"]
|
|
44
47
|
|
|
@@ -27,7 +27,7 @@ import os.path
|
|
|
27
27
|
import itertools
|
|
28
28
|
from _collections_abc import Iterator
|
|
29
29
|
|
|
30
|
-
from ..shared import PythonInstall, get_folder_pythons
|
|
30
|
+
from ..shared import PythonInstall, get_folder_pythons, get_uv_pythons
|
|
31
31
|
from .pyenv_search import get_pyenv_pythons
|
|
32
32
|
|
|
33
33
|
|
|
@@ -57,7 +57,11 @@ def get_path_pythons() -> Iterator[PythonInstall]:
|
|
|
57
57
|
def get_python_installs():
|
|
58
58
|
listed_pythons = set()
|
|
59
59
|
|
|
60
|
-
for py in itertools.chain(
|
|
60
|
+
for py in itertools.chain(
|
|
61
|
+
get_pyenv_pythons(),
|
|
62
|
+
get_uv_pythons(),
|
|
63
|
+
get_path_pythons(),
|
|
64
|
+
):
|
|
61
65
|
if py.executable not in listed_pythons:
|
|
62
66
|
yield py
|
|
63
67
|
listed_pythons.add(py.executable)
|
{ducktools_pythonfinder-0.4.7 → ducktools_pythonfinder-0.5.1}/src/ducktools/pythonfinder/shared.py
RENAMED
|
@@ -26,6 +26,8 @@ import sys
|
|
|
26
26
|
import os
|
|
27
27
|
import os.path
|
|
28
28
|
|
|
29
|
+
from _collections_abc import Iterator
|
|
30
|
+
|
|
29
31
|
from ducktools.classbuilder import slotclass, Field, SlotFields
|
|
30
32
|
from ducktools.lazyimporter import LazyImporter, ModuleImport, FromImport
|
|
31
33
|
|
|
@@ -229,7 +231,8 @@ def get_install_details(executable: str) -> PythonInstall | None:
|
|
|
229
231
|
|
|
230
232
|
|
|
231
233
|
def get_folder_pythons(
|
|
232
|
-
base_folder: str | os.PathLike,
|
|
234
|
+
base_folder: str | os.PathLike,
|
|
235
|
+
basenames: tuple[str] = ("python", "pypy")
|
|
233
236
|
):
|
|
234
237
|
regexes = [_python_exe_regex(name) for name in basenames]
|
|
235
238
|
|
|
@@ -243,3 +246,59 @@ def get_folder_pythons(
|
|
|
243
246
|
install = get_install_details(file_path.path)
|
|
244
247
|
if install:
|
|
245
248
|
yield install
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
# UV Specific finder
|
|
252
|
+
def _get_uv_python_path() -> str | None:
|
|
253
|
+
try:
|
|
254
|
+
uv_python_find = _laz.subprocess.run(
|
|
255
|
+
["uv", "python", "dir"],
|
|
256
|
+
check=True,
|
|
257
|
+
text=True,
|
|
258
|
+
capture_output=True
|
|
259
|
+
)
|
|
260
|
+
except _laz.subprocess.CalledProcessError:
|
|
261
|
+
uv_python_dir = None
|
|
262
|
+
else:
|
|
263
|
+
# remove newline
|
|
264
|
+
uv_python_dir = uv_python_find.stdout.strip()
|
|
265
|
+
|
|
266
|
+
return uv_python_dir
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
def _implementation_from_uv_dir(direntry: os.DirEntry) -> PythonInstall | None:
|
|
270
|
+
python_exe = "python.exe" if sys.platform == "win32" else "bin/python"
|
|
271
|
+
python_path = os.path.join(direntry, python_exe)
|
|
272
|
+
|
|
273
|
+
install: PythonInstall | None = None
|
|
274
|
+
|
|
275
|
+
if os.path.exists(python_path):
|
|
276
|
+
try:
|
|
277
|
+
implementation, version, platform, arch, _ = direntry.name.split("-")
|
|
278
|
+
except ValueError:
|
|
279
|
+
# Directory name format has changed
|
|
280
|
+
# Slow backup - ask python itself
|
|
281
|
+
install = get_install_details(python_path)
|
|
282
|
+
else:
|
|
283
|
+
if implementation == "cpython":
|
|
284
|
+
install = PythonInstall.from_str(
|
|
285
|
+
version=version,
|
|
286
|
+
executable=python_path,
|
|
287
|
+
architecture="32bit" if arch in {"i686", "armv7"} else "64bit",
|
|
288
|
+
implementation=implementation,
|
|
289
|
+
)
|
|
290
|
+
else:
|
|
291
|
+
# Get additional alternate implementation details
|
|
292
|
+
install = get_install_details(python_path)
|
|
293
|
+
|
|
294
|
+
return install
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
def get_uv_pythons() -> Iterator[PythonInstall]:
|
|
298
|
+
# This takes some shortcuts over the regular pythonfinder
|
|
299
|
+
# As the UV folders give the python version and the implementation
|
|
300
|
+
if uv_python_path := _get_uv_python_path():
|
|
301
|
+
with os.scandir(uv_python_path) as fld:
|
|
302
|
+
for f in fld:
|
|
303
|
+
if f.is_dir() and (install := _implementation_from_uv_dir(f)):
|
|
304
|
+
yield install
|
|
@@ -25,14 +25,18 @@ from __future__ import annotations
|
|
|
25
25
|
from _collections_abc import Iterator
|
|
26
26
|
import itertools
|
|
27
27
|
|
|
28
|
-
from ..shared import PythonInstall
|
|
28
|
+
from ..shared import PythonInstall, get_uv_pythons
|
|
29
29
|
from .pyenv_search import get_pyenv_pythons
|
|
30
30
|
from .registry_search import get_registered_pythons
|
|
31
31
|
|
|
32
32
|
|
|
33
33
|
def get_python_installs() -> Iterator[PythonInstall]:
|
|
34
34
|
listed_installs = set()
|
|
35
|
-
for py in itertools.chain(
|
|
35
|
+
for py in itertools.chain(
|
|
36
|
+
get_registered_pythons(),
|
|
37
|
+
get_pyenv_pythons(),
|
|
38
|
+
get_uv_pythons(),
|
|
39
|
+
):
|
|
36
40
|
if py.executable not in listed_installs:
|
|
37
41
|
yield py
|
|
38
42
|
listed_installs.add(py.executable)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: ducktools-pythonfinder
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5.1
|
|
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
|
|
@@ -33,6 +33,11 @@ for Windows and MacOS or sources for Linux (as python.org does not provide linux
|
|
|
33
33
|
|
|
34
34
|
Requires Python >= 3.8 (but will discover older Python installs)
|
|
35
35
|
|
|
36
|
+
[Download the zipapp here](https://github.com/DavidCEllis/ducktools-pythonfinder/releases/latest/download/pythonfinder.pyz)
|
|
37
|
+
|
|
38
|
+
It is also available as a library on PyPI that can be installed with pip:
|
|
39
|
+
`python -m pip install ducktools-pythonfinder`
|
|
40
|
+
|
|
36
41
|
## Command Line Usage ##
|
|
37
42
|
|
|
38
43
|
`ducktools-pythonfinder` can be used as a module or as a bundled zipapp (as `pythonfinder.pyz`).
|
|
@@ -77,13 +82,19 @@ The module provides two main functions for searching for local python installs:
|
|
|
77
82
|
* `get_python_installs` is a generator that will yield each python version it discovers
|
|
78
83
|
* `list_python_installs` will take the python versions discovered by `get_python_installs`
|
|
79
84
|
and return a sorted list from newest to oldest python version discovered.
|
|
85
|
+
* For the purposes of sorting, prerelease versions are considered older than any released
|
|
86
|
+
version.
|
|
80
87
|
|
|
81
88
|
On Windows these methods will search the registry for PEP514 recorded python installs
|
|
82
|
-
before checking for any `pyenv-win` installs that have not been registered.
|
|
89
|
+
before checking for any `pyenv-win` installs that have not been registered. Finally, if
|
|
90
|
+
`uv` is available it will try to find Python installs managed by `uv`.
|
|
91
|
+
|
|
92
|
+
On Linux and MacOS this will search for `pyenv` installs first,
|
|
93
|
+
if `uv` is available it will then try to find `uv` managed python installs.
|
|
94
|
+
Finally it will search `PATH` for any other `python*` binaries that might be available.
|
|
83
95
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
to run a small script to identify the version.
|
|
96
|
+
If a python install is found twice (for instance a pyenv install in the windows registry)
|
|
97
|
+
it will only be returned the first time it is found.
|
|
87
98
|
|
|
88
99
|
The python installs will be returned as instances of `PythonInstall` which will
|
|
89
100
|
contain version info and executable path along with some other useful metadata.
|
|
@@ -21,6 +21,7 @@ src/ducktools/pythonfinder/win32/registry_search.py
|
|
|
21
21
|
src/ducktools_pythonfinder.egg-info/PKG-INFO
|
|
22
22
|
src/ducktools_pythonfinder.egg-info/SOURCES.txt
|
|
23
23
|
src/ducktools_pythonfinder.egg-info/dependency_links.txt
|
|
24
|
+
src/ducktools_pythonfinder.egg-info/entry_points.txt
|
|
24
25
|
src/ducktools_pythonfinder.egg-info/requires.txt
|
|
25
26
|
src/ducktools_pythonfinder.egg-info/top_level.txt
|
|
26
27
|
tests/conftest.py
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ducktools_pythonfinder-0.4.7 → ducktools_pythonfinder-0.5.1}/scripts/print_python_versions.py
RENAMED
|
File without changes
|
|
File without changes
|
{ducktools_pythonfinder-0.4.7 → ducktools_pythonfinder-0.5.1}/src/ducktools/pythonfinder/__init__.py
RENAMED
|
File without changes
|
{ducktools_pythonfinder-0.4.7 → ducktools_pythonfinder-0.5.1}/src/ducktools/pythonfinder/__main__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ducktools_pythonfinder-0.4.7 → ducktools_pythonfinder-0.5.1}/tests/sources/python_versions.txt
RENAMED
|
File without changes
|
|
File without changes
|
{ducktools_pythonfinder-0.4.7 → ducktools_pythonfinder-0.5.1}/tests/sources/release_file.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|