Return the graph's SCCs, topologically sorted by dependencies. The sort order is from leaves (nodes without dependencies) to roots (nodes on which no other nodes depend).
(graph: Graph)
| 5026 | |
| 5027 | |
| 5028 | def sorted_components(graph: Graph) -> list[SCC]: |
| 5029 | """Return the graph's SCCs, topologically sorted by dependencies. |
| 5030 | |
| 5031 | The sort order is from leaves (nodes without dependencies) to |
| 5032 | roots (nodes on which no other nodes depend). |
| 5033 | """ |
| 5034 | # Compute SCCs. |
| 5035 | vertices = set(graph) |
| 5036 | edges = {id: deps_filtered(graph, vertices, id, PRI_INDIRECT) for id in vertices} |
| 5037 | scc_dep_map = prepare_sccs_full(strongly_connected_components(vertices, edges), edges) |
| 5038 | # Topsort. |
| 5039 | res = [] |
| 5040 | for ready in topsort(scc_dep_map): |
| 5041 | # Sort the sets in ready by reversed smallest State.order. Examples: |
| 5042 | # |
| 5043 | # - If ready is [{x}, {y}], x.order == 1, y.order == 2, we get |
| 5044 | # [{y}, {x}]. |
| 5045 | # |
| 5046 | # - If ready is [{a, b}, {c, d}], a.order == 1, b.order == 3, |
| 5047 | # c.order == 2, d.order == 4, the sort keys become [1, 2] |
| 5048 | # and the result is [{c, d}, {a, b}]. |
| 5049 | sorted_ready = sorted(ready, key=lambda scc: -min(graph[id].order for id in scc.mod_ids)) |
| 5050 | for scc in sorted_ready: |
| 5051 | scc.size_hint = sum(graph[mid].size_hint for mid in scc.mod_ids) |
| 5052 | for dep in scc_dep_map[scc]: |
| 5053 | dep.direct_dependents.append(scc.id) |
| 5054 | # We compute dependencies hash here since we know no direct |
| 5055 | # dependencies will be added or suppressed after this point. |
| 5056 | trans_dep_hash = transitive_dep_hash(scc, graph) |
| 5057 | for id in scc.mod_ids: |
| 5058 | graph[id].trans_dep_hash = trans_dep_hash |
| 5059 | res.extend(sorted_ready) |
| 5060 | return res |
| 5061 | |
| 5062 | |
| 5063 | def sorted_components_inner( |
searching dependent graphs…