Skip to content

Commit 0080c5e

Browse files
authored
Merge pull request #69 from DavidCEllis/resolve-uv-symlinks
Make the UV python listing manager use the keys as given
2 parents 05ce5ca + db7dfb9 commit 0080c5e

File tree

5 files changed

+573
-466
lines changed

5 files changed

+573
-466
lines changed

pyproject.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ license = "MIT"
1616
license-files = ["LICENSE"]
1717
requires-python = ">=3.10"
1818
dependencies = [
19-
"ducktools-classbuilder>=0.10.0",
20-
"ducktools-pythonfinder>=0.10.3",
19+
"ducktools-classbuilder>=0.11.1",
20+
"ducktools-pythonfinder>=0.10.4",
2121
"ducktools-lazyimporter>=0.8.4",
22-
"textual>=5.0.1",
22+
"textual>=8.0.0",
2323
]
2424
classifiers = [
2525
"Development Status :: 2 - Pre-Alpha",

requirements.txt

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# This file was autogenerated by uv via the following command:
22
# uv pip compile /home/ducksual/src/ducktools-pytui/pyproject.toml --universal --generate-hashes -o /home/ducksual/src/ducktools-pytui/requirements.txt
3-
ducktools-classbuilder==0.11.1 \
4-
--hash=sha256:abb415d654a5414067d5ff0886e540bb463aac9f14b472e7384e6dd5dda2df96 \
5-
--hash=sha256:fdf2044e125a1b823c939c892cf97c9af124fa5870d4923cca853a3442f19002
3+
ducktools-classbuilder==0.12.4 \
4+
--hash=sha256:43b31b6576fa43d481c7f6e51481589d7bdeb487af71f6711c9530ae04c20df4 \
5+
--hash=sha256:676d681749a854818fd4f7e8cbcb0e699927c98fe92df086e50861efee968f26
66
# via
77
# ducktools-pytui (pyproject.toml)
88
# ducktools-pythonfinder
@@ -12,9 +12,9 @@ ducktools-lazyimporter==0.8.4 \
1212
# via
1313
# ducktools-pytui (pyproject.toml)
1414
# ducktools-pythonfinder
15-
ducktools-pythonfinder==0.10.3 \
16-
--hash=sha256:118ecae6b4ec5bd428ed907c006958d6465379465bf696b6712c13117b4d792b \
17-
--hash=sha256:301ca8d4cd244e512cc679fb3559e1c952e2dd0c90e1382a0b12ee1821937afa
15+
ducktools-pythonfinder==0.10.4 \
16+
--hash=sha256:4bbcd5167581b78392d9a358fa12c3de9e3fbef8b51d54d835c33143566e34b1 \
17+
--hash=sha256:9af72d67afd3d95c4baf8c470c6250c2c16d971acecde23bb44059a4c340a42d
1818
# via ducktools-pytui (pyproject.toml)
1919
linkify-it-py==2.0.3 \
2020
--hash=sha256:68cda27e162e9215c17d786649d1da0021a451bdc436ef9e0fa0ba5234b9b048 \
@@ -35,27 +35,27 @@ mdurl==0.1.2 \
3535
--hash=sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8 \
3636
--hash=sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba
3737
# via markdown-it-py
38-
packaging==25.0 \
39-
--hash=sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484 \
40-
--hash=sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f
38+
packaging==26.0 \
39+
--hash=sha256:00243ae351a257117b6a241061796684b084ed1c516a08c48a3f7e147a9d80b4 \
40+
--hash=sha256:b36f1fef9334a5588b4166f8bcd26a14e521f2b55e6b9de3aaa80d3ff7a37529
4141
# via ducktools-pythonfinder
42-
platformdirs==4.5.0 \
43-
--hash=sha256:70ddccdd7c99fc5942e9fc25636a8b34d04c24b335100223152c2803e4063312 \
44-
--hash=sha256:e578a81bb873cbb89a41fcc904c7ef523cc18284b7e3b3ccf06aca1403b7ebd3
42+
platformdirs==4.9.2 \
43+
--hash=sha256:9170634f126f8efdae22fb58ae8a0eaa86f38365bc57897a6c4f781d1f5875bd \
44+
--hash=sha256:9a33809944b9db043ad67ca0db94b14bf452cc6aeaac46a88ea55b26e2e9d291
4545
# via textual
4646
pygments==2.19.2 \
4747
--hash=sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887 \
4848
--hash=sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b
4949
# via
5050
# rich
5151
# textual
52-
rich==14.2.0 \
53-
--hash=sha256:73ff50c7c0c1c77c8243079283f4edb376f0f6442433aecb8ce7e6d0b92d1fe4 \
54-
--hash=sha256:76bc51fe2e57d2b1be1f96c524b890b816e334ab4c1e45888799bfaab0021edd
52+
rich==14.3.3 \
53+
--hash=sha256:793431c1f8619afa7d3b52b2cdec859562b950ea0d4b6b505397612db8d5362d \
54+
--hash=sha256:b8daa0b9e4eef54dd8cf7c86c03713f53241884e814f4e2f5fb342fe520f639b
5555
# via textual
56-
textual==6.4.0 \
57-
--hash=sha256:b346dbb8e12f17cefb33ddfdf7f19bdc9e66c29daf82fc981a8db6b7d985e115 \
58-
--hash=sha256:f40df9165a001c10249698d532f2f5a71708b70f0e4ef3fce081a9dd93ffeaaa
56+
textual==8.0.0 \
57+
--hash=sha256:8908f4ebe93a6b4f77ca7262197784a52162bc88b05f4ecf50ac93a92d49bb8f \
58+
--hash=sha256:ce48f83a3d686c0fac0e80bf9136e1f8851c653aa6a4502e43293a151df18809
5959
# via ducktools-pytui (pyproject.toml)
6060
typing-extensions==4.15.0 \
6161
--hash=sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466 \

src/ducktools/pytui/runtime_installers/base.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,6 @@ def find_matching_listing(self, install: PythonInstall) -> Listing | None:
139139
if py.path is not None
140140
}
141141

142-
install_path = os.path.dirname(install.executable)
142+
install_path = os.path.realpath(os.path.dirname(install.executable))
143143

144144
return installed_dict.get(install_path, None)

src/ducktools/pytui/runtime_installers/uv.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,13 @@ def __prefab_post_init__(self, key: str, path: str | None) -> None:
5252
self.path = path
5353
else:
5454
# Resolve path always, sometimes UV gives a relative path to cwd.
55-
self.path = os.path.abspath(path)
55+
# Sometimes the path is also a symlink
56+
self.path = os.path.realpath(os.path.abspath(path))
5657

5758
# UV bug - key and path can mismatch if someone typoed the metadata
5859
base_path = self.manager.runtime_folder
5960
if base_path:
61+
base_path = os.path.realpath(base_path) # resolve base path symlink too
6062
key_path = str(Path(self.path).relative_to(base_path).parts[0])
6163
self.key = key if key == key_path else key_path
6264

@@ -75,7 +77,7 @@ def from_dict(cls, manager: UVManager, entry: dict[str, Any]) -> UVPythonListing
7577
def install(self) -> subprocess.CompletedProcess | None:
7678
if self.manager.executable is None:
7779
raise FileNotFoundError("Could not find the 'uv' executable on PATH")
78-
80+
7981
if self.path:
8082
# Can't install already installed Python
8183
return None
@@ -96,7 +98,7 @@ def install(self) -> subprocess.CompletedProcess | None:
9698
def uninstall(self) -> subprocess.CompletedProcess | None:
9799
if self.manager.executable is None:
98100
raise FileNotFoundError("Could not find the 'uv' executable on PATH")
99-
101+
100102
if not (self.path and os.path.exists(self.path)):
101103
# Can't uninstall non-installed Python
102104
return None

0 commit comments

Comments
 (0)