Skip to content

Commit e2a0472

Browse files
authored
Make the order of linking of ports deterministic (#21995)
In python `dict()` ordering is deterministic, but `set()` ordering is not. Annoying. This change adds a simple `OrderedSet` and uses that for managing ports. Fixes: #21930
1 parent f307ec6 commit e2a0472

File tree

1 file changed

+34
-3
lines changed

1 file changed

+34
-3
lines changed

tools/ports/__init__.py

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -369,14 +369,45 @@ def write_file(filename, contents):
369369
utils.write_file(filename, contents)
370370

371371

372+
class OrderedSet:
373+
"""Partial implementation of OrderedSet. Just enough for what we need here."""
374+
def __init__(self, items):
375+
self.dict = dict()
376+
for i in items:
377+
self.dict[i] = True
378+
379+
def __repr__(self):
380+
return f"OrderedSet({list(self.dict.keys())})"
381+
382+
def __len__(self):
383+
return len(self.dict.keys())
384+
385+
def copy(self):
386+
return OrderedSet(self.dict.keys())
387+
388+
def __iter__(self):
389+
return iter(self.dict.keys())
390+
391+
def pop(self, index=-1):
392+
key = list(self.dict.keys())[index]
393+
self.dict.pop(key)
394+
return key
395+
396+
def add(self, item):
397+
self.dict[item] = True
398+
399+
def remove(self, item):
400+
del self.dict[item]
401+
402+
372403
def dependency_order(port_list):
373404
# Perform topological sort of ports according to the dependency DAG
374405
port_map = {p.name: p for p in port_list}
375406

376407
# Perform depth first search of dependecy graph adding nodes to
377408
# the stack only after all children have been explored.
378409
stack = []
379-
unsorted = set(port_list)
410+
unsorted = OrderedSet(port_list)
380411

381412
def dfs(node):
382413
for dep in node.deps:
@@ -492,14 +523,14 @@ def error_handler(message):
492523

493524
def get_needed_ports(settings):
494525
# Start with directly needed ports, and transitively add dependencies
495-
needed = set(p for p in ports if p.needed(settings))
526+
needed = OrderedSet(p for p in ports if p.needed(settings))
496527
resolve_dependencies(needed, settings)
497528
return needed
498529

499530

500531
def build_port(port_name, settings):
501532
port = ports_by_name[port_name]
502-
port_set = {port}
533+
port_set = OrderedSet([port])
503534
resolve_dependencies(port_set, settings)
504535
for port in dependency_order(port_set):
505536
port.get(Ports, settings, shared)

0 commit comments

Comments
 (0)