# HG changeset patch # User Paul Boddie # Date 1489412864 -3600 # Node ID 3d89317842b9cd3da265603d4facb160a50e577f # Parent 823020deac339cf696c6ace4d95561a7e3a3141b Made dependency ordering a generic function for possible use elsewhere. diff -r 823020deac33 -r 3d89317842b9 common.py --- a/common.py Mon Mar 13 01:49:11 2017 +0100 +++ b/common.py Mon Mar 13 14:47:44 2017 +0100 @@ -987,6 +987,56 @@ def same(s1, s2): return set(s1) == set(s2) +def order_dependencies(all_depends): + + """ + Produce a dependency ordering for the 'all_depends' mapping. This mapping + has the form "A depends on B, C...". The result will order A, B, C, and so + on. + """ + + # Record the reverse dependencies, making a mapping of the form + # "B is needed by A", "C is needed by A", and so on. + + usage = {} + + # Record path-based dependencies. + + for key in all_depends.keys(): + usage[key] = set() + + for key, depends in all_depends.items(): + for depend in depends: + init_item(usage, depend, set) + usage[depend].add(key) + + # Produce an ordering by obtaining exposed items (required by items already + # processed) and putting them at the start of the list. + + ordered = [] + + while usage: + have_next = False + + for path, n in usage.items(): + if not n: + ordered.insert(0, path) + depends = all_depends.get(path) + + # Reduce usage of the referenced items. + + if depends: + for depend in depends: + usage[depend].remove(path) + + del usage[path] + have_next = True + + if not have_next: + raise ValueError, usage + + return ordered + # General input/output. def readfile(filename): diff -r 823020deac33 -r 3d89317842b9 importer.py --- a/importer.py Mon Mar 13 01:49:11 2017 +0100 +++ b/importer.py Mon Mar 13 14:47:44 2017 +0100 @@ -23,7 +23,7 @@ from errors import ProgramError from os.path import exists, extsep, getmtime, join from os import listdir, makedirs, remove -from common import init_item, readfile, writefile +from common import init_item, order_dependencies, readfile, writefile from modules import CachedModule from referencing import Reference import inspector @@ -673,44 +673,10 @@ self.condense_dependencies() - # Record the number of modules using or depending on each module. - - usage = {} - - # Record path-based dependencies. - - for path in self.depends.keys(): - usage[path] = set() - - for path, depends in self.depends.items(): - for origin in depends: - init_item(usage, origin, set) - usage[origin].add(path) - - # Produce an ordering by obtaining exposed modules (required by modules - # already processed) and putting them at the start of the list. - - ordered = [] - - while usage: - have_next = False - - for path, n in usage.items(): - if not n: - ordered.insert(0, path) - depends = self.depends.get(path) - - # Reduce usage of the referenced objects. - - if depends: - for origin in depends: - usage[origin].remove(path) - - del usage[path] - have_next = True - - if not have_next: - raise ProgramError("Modules with unresolvable dependencies exist: %s" % ", ".join(usage.keys())) + try: + ordered = order_dependencies(self.depends) + except ValueError, exc: + raise ProgramError("Modules with unresolvable dependencies exist: %s" % ", ".join(exc.args[0].keys())) if "__main__" in ordered: ordered.remove("__main__")