Skip to content

Commit d5e2a47

Browse files
committed
Reimplement alias merging algorithm
1 parent 804876b commit d5e2a47

File tree

3 files changed

+72
-52
lines changed

3 files changed

+72
-52
lines changed

src/manage/install_command.py

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -344,37 +344,33 @@ def print_cli_shortcuts(cmd):
344344
LOGGER.debug("Failed to display PATH warning", exc_info=True)
345345
return
346346

347+
from .installs import get_install_alias_names
347348
installs = cmd.get_installs()
348349
tags = getattr(cmd, "tags", None)
349350
seen = set("python.exe".casefold())
350351
verbose = LOGGER.would_log_to_console(VERBOSE)
351352
for i in installs:
352-
# We only show windowed aliases if -v is enabled. But we log them as
353-
# debug info unconditionally. This involves a bit of a dance to keep the
354-
# 'windowed' flag around and then drop entries based on whether
355-
# LOGGER.verbose would be printed to the console.
356-
aliases = sorted((a["name"], a.get("windowed", 0)) for a in i["alias"]
357-
if a["name"].casefold() not in seen)
358-
seen.update(n.casefold() for n, *_ in aliases)
353+
# We need to pre-filter aliases before getting the nice names.
354+
aliases = [a for a in i["alias"] if a["name"].casefold() not in seen]
355+
seen.update(n["name"].casefold() for n in aliases)
359356
if not verbose:
360357
if i.get("default"):
361358
LOGGER.debug("%s will be launched by !G!python.exe!W!", i["display-name"])
362-
LOGGER.debug("%s will be launched by %s", i["display-name"],
363-
", ".join([n for n, *_ in aliases]))
364-
aliases = [n for n, w in aliases if not w]
365-
else:
366-
aliases = [n for n, *_ in aliases]
359+
names = get_install_alias_names(aliases, windowed=True)
360+
LOGGER.debug("%s will be launched by %s", i["display-name"], ", ".join(names))
367361

368362
if tags and not install_matches_any(i, cmd.tags):
369363
continue
370-
if i.get("default") and aliases:
364+
365+
names = get_install_alias_names(aliases, windowed=False)
366+
if i.get("default") and names:
371367
LOGGER.info("%s will be launched by !G!python.exe!W! and also %s",
372-
i["display-name"], ", ".join(aliases))
368+
i["display-name"], ", ".join(names))
373369
elif i.get("default"):
374370
LOGGER.info("%s will be launched by !G!python.exe!W!.", i["display-name"])
375-
elif aliases:
371+
elif names:
376372
LOGGER.info("%s will be launched by %s",
377-
i["display-name"], ", ".join(aliases))
373+
i["display-name"], ", ".join(names))
378374
else:
379375
LOGGER.info("Installed %s to %s", i["display-name"], i["prefix"])
380376

src/manage/installs.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,62 @@ def get_installs(
120120
return installs
121121

122122

123+
def _make_alias_key(alias):
124+
from .tagutils import SUPPORTED_PLATFORM_SUFFIXES
125+
n1, sep, n3 = alias.rpartition(".")
126+
n2 = ""
127+
n3 = sep + n3
128+
if n1.endswith(SUPPORTED_PLATFORM_SUFFIXES):
129+
n1, sep, plat = n1.rpartition("-")
130+
plat = sep + plat
131+
else:
132+
plat = ""
133+
134+
while n1 and n1[-1] in "0123456789.-":
135+
n2 = n1[-1] + n2
136+
n1 = n1[:-1]
137+
w = ""
138+
if n1 and n1[-1] == "w":
139+
w = "w"
140+
n1 = n1[:-1]
141+
return n1, w, n2, plat, n3
142+
143+
144+
def _make_opt_part(parts):
145+
if not parts:
146+
return ""
147+
if len(parts) == 1:
148+
return list(parts)[0]
149+
return "[{}]".format("|".join(sorted(p for p in parts if p)))
150+
151+
152+
def get_install_alias_names(aliases, friendly=True, windowed=True):
153+
if not windowed:
154+
aliases = [a for a in aliases if not a.get("windowed")]
155+
if not friendly:
156+
return sorted(a["name"] for a in aliases)
157+
158+
seen = {}
159+
has_w = {}
160+
plats = {}
161+
for n1, w, n2, plat, n3 in (_make_alias_key(a["name"]) for a in aliases):
162+
k = n1.casefold(), n2.casefold(), n3.casefold()
163+
seen.setdefault(k, (n1, n2, n3))
164+
has_w.setdefault(k, set()).add(w)
165+
plats.setdefault(k, set()).add(plat)
166+
167+
result = []
168+
for k, (n1, n2, n3) in seen.items():
169+
result.append("".join([
170+
n1,
171+
_make_opt_part(has_w.get(k)),
172+
n2,
173+
_make_opt_part(plats.get(k)),
174+
n3,
175+
]))
176+
return sorted(result)
177+
178+
123179
def _patch_install_to_run(i, run_for):
124180
return {
125181
**i,

src/manage/list_command.py

Lines changed: 4 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -7,43 +7,11 @@
77
LOGGER = logging.LOGGER
88

99

10-
def _exe_partition(n):
11-
n1, sep, n2 = n.rpartition(".")
12-
n2 = sep + n2
13-
while n1 and n1[-1] in "0123456789.-":
14-
n2 = n1[-1] + n2
15-
n1 = n1[:-1]
16-
w = ""
17-
if n1 and n1[-1] == "w":
18-
w = "w"
19-
n1 = n1[:-1]
20-
return n1, w, n2
21-
22-
2310
def _format_alias(i, seen):
24-
try:
25-
alias = i["alias"]
26-
except KeyError:
27-
return ""
28-
if not alias:
29-
return ""
30-
if len(alias) == 1:
31-
a = i["alias"][0]
32-
n = a["name"].casefold()
33-
if n in seen:
34-
return ""
35-
seen.add(n)
36-
return i["alias"][0]["name"]
37-
names = {_exe_partition(a["name"].casefold()): a["name"] for a in alias
38-
if a["name"].casefold() not in seen}
39-
seen.update(a["name"].casefold() for a in alias)
40-
for n1, w, n2 in list(names):
41-
k = (n1, "", n2)
42-
if w and k in names:
43-
del names[n1, w, n2]
44-
n1, _, n2 = _exe_partition(names[k])
45-
names[k] = f"{n1}[w]{n2}"
46-
return ", ".join(names[n] for n in sorted(names))
11+
from manage.installs import get_install_alias_names
12+
aliases = [a for a in i.get("alias", ()) if a["name"].casefold() not in seen]
13+
seen.update(a["name"].casefold() for a in aliases)
14+
return ", ".join(get_install_alias_names(aliases))
4715

4816

4917
def _format_tag_with_co(cmd, i):

0 commit comments

Comments
 (0)