diff --git a/SConstruct b/SConstruct index 81a89514c..841ebd208 100644 --- a/SConstruct +++ b/SConstruct @@ -286,6 +286,9 @@ for path in module_search_paths: # Note: custom modules can override built-in ones. modules_detected.update(modules) +# Sort modules dependencies +methods.sort_modules_dependencies(modules_detected) + # Add module options for name, path in modules_detected.items(): enabled = True diff --git a/methods.py b/methods.py index 651d9d46b..78c883798 100644 --- a/methods.py +++ b/methods.py @@ -1,6 +1,7 @@ import os import re import glob +import sys import subprocess from collections import OrderedDict from collections.abc import Mapping @@ -1053,3 +1054,74 @@ def dump(env): with open(".scons_env.json", "w") as f: dump(env.Dictionary(), f, indent=4, default=non_serializable) + +# uses the graph/topo sort from: +# https://www.geeksforgeeks.org/python-program-for-topological-sorting/ +# albeit highly modified +class ModuleDepGraph: + def __init__(self, modules: OrderedDict, dependencies: OrderedDict): + self.graph = dict() + self.vertices = [name for name in modules] + + # construct the edges + for name, deps in dependencies.items(): + self.graph[name] = [] + for dep_name in deps: + self.graph[name].append(dep_name) + + # A recursive function used by dependency_sort + def topological_sort_util(self, v, visited, stack): + + # Mark the current node as visited. + visited[v] = True + + # Recur for all the vertices adjacent to this vertex + for i in self.graph[v]: + if i in visited and visited[i] == False: + self.topological_sort_util(i, visited, stack) + + # Push current vertex to stack which stores result + stack.insert(0, v) + + # The function to performs a topological sort, and then reverses it to obtain the dependency sort. + def dependency_sort(self) -> []: + # Mark all the vertices as not visited + visited = dict() + for v in self.vertices: + visited[v] = False + + stack = [] + + # Call the recursive helper function to store Topological + # Sort starting from all vertices one by one + for v in self.vertices: + if visited[v] == False: + self.topological_sort_util(v, visited, stack) + + # reverse the topological sort + stack.reverse() + + return stack + + +def sort_modules_dependencies(modules): + out = OrderedDict() + deps = {} + for name, path in modules.items(): + sys.path.insert(0, path) + import config + + try: + deps[name] = config.get_module_dependencies() + except AttributeError: + deps[name] = {} + sys.path.remove(path) + sys.modules.pop("config") + + graph = ModuleDepGraph(modules, deps) + dep_sorted_names = graph.dependency_sort() + for n in dep_sorted_names: + modules.move_to_end(n) + return out + + diff --git a/modules/database_sqlite/config.py b/modules/database_sqlite/config.py index 02d8fcfee..8f65f5cee 100644 --- a/modules/database_sqlite/config.py +++ b/modules/database_sqlite/config.py @@ -55,3 +55,7 @@ def get_doc_classes(): def get_doc_path(): return "doc_classes" +def get_module_dependencies(): + return [ + "database", + ]