Skip to content

Commit 6b13388

Browse files
committed
use a more robust algo than a double loop
1 parent 3b89744 commit 6b13388

1 file changed

Lines changed: 19 additions & 14 deletions

File tree

python/private/pypi/pep508_deps.bzl

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,9 @@ def _resolve_extras(self_name, reqs, extras):
115115
# extras The empty string in the set is just a way to make the handling
116116
# of no extras and a single extra easier and having a set of {"", "foo"}
117117
# is equivalent to having {"foo"}.
118-
extras = extras or [""]
118+
#
119+
# Use a dict as a set here to simplify operations.
120+
extras = {x: None for x in extras or [""]}
119121

120122
self_reqs = []
121123
for req in reqs:
@@ -128,26 +130,29 @@ def _resolve_extras(self_name, reqs, extras):
128130
# easy to handle, lets do it.
129131
#
130132
# TODO @aignas 2023-12-08: add a test
131-
extras = extras + req.extras
133+
extras = extras | {x: None for x in req.extras}
132134
else:
133135
# process these in a separate loop
134136
self_reqs.append(req)
135137

136-
# A double loop is not strictly optimal, but always correct without recursion
137-
for req in self_reqs:
138-
if _evaluate_any(req, extras):
139-
extras = extras + req.extras
140-
else:
141-
continue
138+
for _ in range(10000):
139+
# handles packages with up to 10000 recursive extras
140+
new_extras = {}
141+
for req in self_reqs:
142+
if _evaluate_any(req, extras):
143+
new_extras.update({x: None for x in req.extras})
144+
else:
145+
continue
146+
147+
num_extras_before = len(extras)
148+
extras = extras | new_extras
149+
num_extras_after = len(new_extras)
142150

143-
# Iterate through all packages to ensure that we include all of the extras from previously
144-
# visited packages.
145-
for req_ in self_reqs:
146-
if _evaluate_any(req_, extras):
147-
extras = extras + req_.extras
151+
if num_extras_before == num_extras_after:
152+
break
148153

149154
# Poor mans set
150-
return sorted({x: None for x in extras})
155+
return sorted(extras)
151156

152157
def _evaluate_any(req, extras):
153158
for extra in extras:

0 commit comments

Comments
 (0)