ducktools-pythonfinder 0.5.4__tar.gz → 0.5.5__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.5.4/src/ducktools_pythonfinder.egg-info → ducktools_pythonfinder-0.5.5}/PKG-INFO +1 -1
- {ducktools_pythonfinder-0.5.4 → ducktools_pythonfinder-0.5.5}/src/ducktools/pythonfinder/__main__.py +39 -17
- ducktools_pythonfinder-0.5.5/src/ducktools/pythonfinder/_version.py +2 -0
- {ducktools_pythonfinder-0.5.4 → ducktools_pythonfinder-0.5.5}/src/ducktools/pythonfinder/details_script.py +40 -1
- {ducktools_pythonfinder-0.5.4 → ducktools_pythonfinder-0.5.5}/src/ducktools/pythonfinder/shared.py +20 -4
- {ducktools_pythonfinder-0.5.4 → ducktools_pythonfinder-0.5.5/src/ducktools_pythonfinder.egg-info}/PKG-INFO +1 -1
- ducktools_pythonfinder-0.5.4/src/ducktools/pythonfinder/_version.py +0 -2
- {ducktools_pythonfinder-0.5.4 → ducktools_pythonfinder-0.5.5}/.gitignore +0 -0
- {ducktools_pythonfinder-0.5.4 → ducktools_pythonfinder-0.5.5}/LICENSE +0 -0
- {ducktools_pythonfinder-0.5.4 → ducktools_pythonfinder-0.5.5}/MANIFEST.in +0 -0
- {ducktools_pythonfinder-0.5.4 → ducktools_pythonfinder-0.5.5}/README.md +0 -0
- {ducktools_pythonfinder-0.5.4 → ducktools_pythonfinder-0.5.5}/pyproject.toml +0 -0
- {ducktools_pythonfinder-0.5.4 → ducktools_pythonfinder-0.5.5}/scripts/build_zipapp.py +0 -0
- {ducktools_pythonfinder-0.5.4 → ducktools_pythonfinder-0.5.5}/scripts/detail_this_python.py +0 -0
- {ducktools_pythonfinder-0.5.4 → ducktools_pythonfinder-0.5.5}/scripts/print_python_versions.py +0 -0
- {ducktools_pythonfinder-0.5.4 → ducktools_pythonfinder-0.5.5}/setup.cfg +0 -0
- {ducktools_pythonfinder-0.5.4 → ducktools_pythonfinder-0.5.5}/src/ducktools/pythonfinder/__init__.py +0 -0
- {ducktools_pythonfinder-0.5.4 → ducktools_pythonfinder-0.5.5}/src/ducktools/pythonfinder/darwin/__init__.py +0 -0
- {ducktools_pythonfinder-0.5.4 → ducktools_pythonfinder-0.5.5}/src/ducktools/pythonfinder/linux/__init__.py +0 -0
- {ducktools_pythonfinder-0.5.4 → ducktools_pythonfinder-0.5.5}/src/ducktools/pythonfinder/linux/pyenv_search.py +0 -0
- {ducktools_pythonfinder-0.5.4 → ducktools_pythonfinder-0.5.5}/src/ducktools/pythonfinder/pythonorg_search.py +0 -0
- {ducktools_pythonfinder-0.5.4 → ducktools_pythonfinder-0.5.5}/src/ducktools/pythonfinder/win32/__init__.py +0 -0
- {ducktools_pythonfinder-0.5.4 → ducktools_pythonfinder-0.5.5}/src/ducktools/pythonfinder/win32/pyenv_search.py +0 -0
- {ducktools_pythonfinder-0.5.4 → ducktools_pythonfinder-0.5.5}/src/ducktools/pythonfinder/win32/registry_search.py +0 -0
- {ducktools_pythonfinder-0.5.4 → ducktools_pythonfinder-0.5.5}/src/ducktools_pythonfinder.egg-info/SOURCES.txt +0 -0
- {ducktools_pythonfinder-0.5.4 → ducktools_pythonfinder-0.5.5}/src/ducktools_pythonfinder.egg-info/dependency_links.txt +0 -0
- {ducktools_pythonfinder-0.5.4 → ducktools_pythonfinder-0.5.5}/src/ducktools_pythonfinder.egg-info/entry_points.txt +0 -0
- {ducktools_pythonfinder-0.5.4 → ducktools_pythonfinder-0.5.5}/src/ducktools_pythonfinder.egg-info/requires.txt +0 -0
- {ducktools_pythonfinder-0.5.4 → ducktools_pythonfinder-0.5.5}/src/ducktools_pythonfinder.egg-info/top_level.txt +0 -0
- {ducktools_pythonfinder-0.5.4 → ducktools_pythonfinder-0.5.5}/tests/conftest.py +0 -0
- {ducktools_pythonfinder-0.5.4 → ducktools_pythonfinder-0.5.5}/tests/sources/python_versions.txt +0 -0
- {ducktools_pythonfinder-0.5.4 → ducktools_pythonfinder-0.5.5}/tests/sources/release.json +0 -0
- {ducktools_pythonfinder-0.5.4 → ducktools_pythonfinder-0.5.5}/tests/sources/release_file.json +0 -0
- {ducktools_pythonfinder-0.5.4 → ducktools_pythonfinder-0.5.5}/tests/test_details_script.py +0 -0
- {ducktools_pythonfinder-0.5.4 → ducktools_pythonfinder-0.5.5}/tests/test_foldersearch.py +0 -0
- {ducktools_pythonfinder-0.5.4 → ducktools_pythonfinder-0.5.5}/tests/test_orgsearch.py +0 -0
- {ducktools_pythonfinder-0.5.4 → ducktools_pythonfinder-0.5.5}/tests/test_pyenv.py +0 -0
- {ducktools_pythonfinder-0.5.4 → ducktools_pythonfinder-0.5.5}/tests/test_shared.py +0 -0
{ducktools_pythonfinder-0.5.4 → ducktools_pythonfinder-0.5.5}/src/ducktools/pythonfinder/__main__.py
RENAMED
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
21
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
22
|
# SOFTWARE.
|
|
23
|
+
from __future__ import annotations
|
|
23
24
|
|
|
24
25
|
|
|
25
26
|
import sys
|
|
@@ -140,23 +141,16 @@ def display_local_installs(
|
|
|
140
141
|
compatible = tuple(int(i) for i in compatible.split("."))
|
|
141
142
|
|
|
142
143
|
installs = list_python_installs(query_executables=query_executables)
|
|
143
|
-
headings = ["Python Version", "Executable Location"]
|
|
144
|
-
max_executable_len = max(
|
|
145
|
-
len(headings[1]), max(len(inst.executable) for inst in installs)
|
|
146
|
-
)
|
|
147
|
-
headings_str = f"| {headings[0]} | {headings[1]:<{max_executable_len}s} |"
|
|
148
144
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
print(headings_str)
|
|
159
|
-
print(f"| {'-' * len(headings[0])} | {'-' * max_executable_len} |")
|
|
145
|
+
headings = ["Version", "Executable Location"]
|
|
146
|
+
|
|
147
|
+
install_collection: list[tuple[str, str]] = []
|
|
148
|
+
max_version_len = len(headings[0])
|
|
149
|
+
max_executable_len = len(headings[1])
|
|
150
|
+
|
|
151
|
+
alternate_implementations = False
|
|
152
|
+
|
|
153
|
+
# First collect the strings
|
|
160
154
|
for install in installs:
|
|
161
155
|
if min_ver and install.version < min_ver:
|
|
162
156
|
continue
|
|
@@ -190,7 +184,35 @@ def display_local_installs(
|
|
|
190
184
|
if install.shadowed:
|
|
191
185
|
version_str = f"[{version_str}]"
|
|
192
186
|
|
|
193
|
-
|
|
187
|
+
if install.implementation != "cpython":
|
|
188
|
+
alternate_implementations = True
|
|
189
|
+
version_str = f"({install.implementation_version_str}) {version_str}"
|
|
190
|
+
|
|
191
|
+
max_version_len = max(max_version_len, len(version_str))
|
|
192
|
+
max_executable_len = max(max_executable_len, len(install.executable))
|
|
193
|
+
|
|
194
|
+
install_collection.append((version_str, install.executable))
|
|
195
|
+
|
|
196
|
+
print("Discoverable Python Installs")
|
|
197
|
+
print()
|
|
198
|
+
if alternate_implementations:
|
|
199
|
+
print("Alternate implementation versions are listed in parentheses")
|
|
200
|
+
|
|
201
|
+
if sys.platform == "win32":
|
|
202
|
+
print("+ - Listed in the Windows Registry ")
|
|
203
|
+
print("^ - This is a 32-bit Python install")
|
|
204
|
+
if sys.platform != "win32":
|
|
205
|
+
print("[] - This Python install is shadowed by another on Path")
|
|
206
|
+
print("* - This is the active Python executable used to call this module")
|
|
207
|
+
print("** - This is the parent Python executable of the venv used to call this module")
|
|
208
|
+
print()
|
|
209
|
+
|
|
210
|
+
headings_str = f"| {headings[0]:<{max_version_len}s} | {headings[1]:<{max_executable_len}s} |"
|
|
211
|
+
print(headings_str)
|
|
212
|
+
print(f"| {'-' * max_version_len} | {'-' * max_executable_len} |")
|
|
213
|
+
|
|
214
|
+
for version_str, executable in install_collection:
|
|
215
|
+
print(f"| {version_str:>{max_version_len}s} | {executable:<{max_executable_len}s} |")
|
|
194
216
|
|
|
195
217
|
|
|
196
218
|
def display_remote_binaries(
|
|
@@ -26,6 +26,35 @@ Get the details from a python install as JSON
|
|
|
26
26
|
"""
|
|
27
27
|
import sys
|
|
28
28
|
|
|
29
|
+
FULL_PY_VER_RE = r"(?P<major>\d+)\.(?P<minor>\d+)\.?(?P<micro>\d*)-?(?P<releaselevel>[a-zA-Z]*)(?P<serial>\d*)"
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def version_str_to_tuple(version):
|
|
33
|
+
# Needed to parse GraalPy versions only available as strings
|
|
34
|
+
import re
|
|
35
|
+
|
|
36
|
+
parsed_version = re.fullmatch(FULL_PY_VER_RE, version)
|
|
37
|
+
|
|
38
|
+
major, minor, micro, releaselevel, serial = parsed_version.groups()
|
|
39
|
+
|
|
40
|
+
if releaselevel in {"a", "dev"}:
|
|
41
|
+
releaselevel = "alpha"
|
|
42
|
+
elif releaselevel == "b":
|
|
43
|
+
releaselevel = "beta"
|
|
44
|
+
elif releaselevel == "rc":
|
|
45
|
+
releaselevel = "candidate"
|
|
46
|
+
else:
|
|
47
|
+
releaselevel = "final"
|
|
48
|
+
|
|
49
|
+
version_tuple = (
|
|
50
|
+
int(major),
|
|
51
|
+
int(minor),
|
|
52
|
+
int(micro) if micro else 0,
|
|
53
|
+
releaselevel,
|
|
54
|
+
int(serial if serial != "" else 0),
|
|
55
|
+
)
|
|
56
|
+
return version_tuple
|
|
57
|
+
|
|
29
58
|
|
|
30
59
|
def get_details():
|
|
31
60
|
try:
|
|
@@ -37,7 +66,17 @@ def get_details():
|
|
|
37
66
|
implementation = platform.python_implementation().lower()
|
|
38
67
|
metadata = {}
|
|
39
68
|
else:
|
|
40
|
-
if implementation
|
|
69
|
+
if implementation == "graalpy":
|
|
70
|
+
# Special case GraalPy as it erroneously reports the CPython target
|
|
71
|
+
# instead of the Graal versiion
|
|
72
|
+
try:
|
|
73
|
+
ver = __graalpython__.get_graalvm_version()
|
|
74
|
+
metadata = {
|
|
75
|
+
"graalpy_version": version_str_to_tuple(ver)
|
|
76
|
+
}
|
|
77
|
+
except NameError:
|
|
78
|
+
metadata = {"{}_version".format(implementation): sys.implementation.version}
|
|
79
|
+
elif implementation != "cpython": # pragma: no cover
|
|
41
80
|
metadata = {"{}_version".format(implementation): sys.implementation.version}
|
|
42
81
|
else:
|
|
43
82
|
metadata = {}
|
{ducktools_pythonfinder-0.5.4 → ducktools_pythonfinder-0.5.5}/src/ducktools/pythonfinder/shared.py
RENAMED
|
@@ -46,7 +46,7 @@ _laz = LazyImporter(
|
|
|
46
46
|
)
|
|
47
47
|
|
|
48
48
|
|
|
49
|
-
FULL_PY_VER_RE = r"(?P<major>\d+)\.(?P<minor>\d+)\.?(?P<micro>\d*)(?P<releaselevel>[a-zA-Z]*)(?P<serial>\d*)"
|
|
49
|
+
FULL_PY_VER_RE = r"(?P<major>\d+)\.(?P<minor>\d+)\.?(?P<micro>\d*)-?(?P<releaselevel>[a-zA-Z]*)(?P<serial>\d*)"
|
|
50
50
|
|
|
51
51
|
|
|
52
52
|
def version_str_to_tuple(version):
|
|
@@ -57,7 +57,7 @@ def version_str_to_tuple(version):
|
|
|
57
57
|
|
|
58
58
|
major, minor, micro, releaselevel, serial = parsed_version.groups()
|
|
59
59
|
|
|
60
|
-
if releaselevel
|
|
60
|
+
if releaselevel in {"a", "dev"}:
|
|
61
61
|
releaselevel = "alpha"
|
|
62
62
|
elif releaselevel == "b":
|
|
63
63
|
releaselevel = "beta"
|
|
@@ -131,6 +131,7 @@ class PythonInstall(Prefab):
|
|
|
131
131
|
implementation: str = "cpython"
|
|
132
132
|
metadata: dict = attribute(default_factory=dict)
|
|
133
133
|
shadowed: bool = False
|
|
134
|
+
_implementation_version: tuple[int, int, int, str, int] | None = attribute(default=None, private=True)
|
|
134
135
|
|
|
135
136
|
def __prefab_post_init__(
|
|
136
137
|
self,
|
|
@@ -147,6 +148,22 @@ class PythonInstall(Prefab):
|
|
|
147
148
|
def version_str(self) -> str:
|
|
148
149
|
return version_tuple_to_str(self.version)
|
|
149
150
|
|
|
151
|
+
@property
|
|
152
|
+
def implementation_version(self) -> tuple[int, int, int, str, int] | None:
|
|
153
|
+
if self._implementation_version is None:
|
|
154
|
+
if self.implementation == "cpython":
|
|
155
|
+
self._implementation_version = self.version
|
|
156
|
+
elif implementation_ver := self.metadata.get(f"{self.implementation}_version"):
|
|
157
|
+
if len(implementation_ver) == 3:
|
|
158
|
+
self._implementation_version = tuple([*implementation_ver, "final", 0]) # type: ignore
|
|
159
|
+
else:
|
|
160
|
+
self._implementation_version = implementation_ver
|
|
161
|
+
return self._implementation_version
|
|
162
|
+
|
|
163
|
+
@property
|
|
164
|
+
def implementation_version_str(self) -> str:
|
|
165
|
+
return version_tuple_to_str(self.implementation_version)
|
|
166
|
+
|
|
150
167
|
@classmethod
|
|
151
168
|
def from_str(
|
|
152
169
|
cls,
|
|
@@ -242,7 +259,6 @@ def get_install_details(executable: str) -> PythonInstall | None:
|
|
|
242
259
|
try:
|
|
243
260
|
output = _laz.json.loads(detail_output)
|
|
244
261
|
except _laz.json.JSONDecodeError as e:
|
|
245
|
-
print(e)
|
|
246
262
|
return None
|
|
247
263
|
|
|
248
264
|
return PythonInstall.from_json(**output)
|
|
@@ -302,7 +318,7 @@ def _implementation_from_uv_dir(
|
|
|
302
318
|
if query_executables:
|
|
303
319
|
install = get_install_details(python_path)
|
|
304
320
|
else:
|
|
305
|
-
if implementation in {"cpython"
|
|
321
|
+
if implementation in {"cpython"}:
|
|
306
322
|
install = PythonInstall.from_str(
|
|
307
323
|
version=version,
|
|
308
324
|
executable=python_path,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ducktools_pythonfinder-0.5.4 → ducktools_pythonfinder-0.5.5}/scripts/print_python_versions.py
RENAMED
|
File without changes
|
|
File without changes
|
{ducktools_pythonfinder-0.5.4 → ducktools_pythonfinder-0.5.5}/src/ducktools/pythonfinder/__init__.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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ducktools_pythonfinder-0.5.4 → ducktools_pythonfinder-0.5.5}/tests/sources/python_versions.txt
RENAMED
|
File without changes
|
|
File without changes
|
{ducktools_pythonfinder-0.5.4 → ducktools_pythonfinder-0.5.5}/tests/sources/release_file.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|