6 from ..util.graph import Node, Graph
9 class IsSubclass (object):
10 """A safe subclass comparator.
20 >>> is_subclass = IsSubclass(A)
23 >>> is_subclass = IsSubclass(A, blacklist=[A])
31 def __init__(self, base_class, blacklist=None):
32 self.base_class = base_class
35 self.blacklist = blacklist
36 def __call__(self, other):
38 subclass = issubclass(other, self.base_class)
41 if other in self.blacklist:
45 def construct_graph(this_modname, submodnames, class_selector,
46 assert_name_match=True):
47 """Search the submodules `submodnames` of a module `this_modname`
48 for class objects for which `class_selector(class)` returns
49 `True`. These classes are instantiated, and the `instance.name`
50 is compared to the `submodname` (if `assert_name_match` is
53 The instances are further arranged into a dependency
54 :class:`hooke.util.graph.Graph` according to their
55 `instance.dependencies()` values. The topologically sorted graph
59 for submodname in submodnames:
60 count = len([s for s in submodnames if s == submodname])
61 assert count > 0, 'No %s entries: %s' % (submodname, submodnames)
62 assert count == 1, 'Multiple (%d) %s entries: %s' \
63 % (count, submodname, submodnames)
64 this_mod = __import__(this_modname, fromlist=[submodname])
65 submod = getattr(this_mod, submodname)
66 for objname in dir(submod):
67 obj = getattr(submod, objname)
68 if class_selector(obj):
70 if assert_name_match == True and instance.name != submodname:
72 'Instance name %s does not match module name %s'
73 % (instance.name, submodname))
74 instances[instance.name] = instance
76 for i in instances.values(): # make nodes for each instance
77 nodes[i.name] = Node(data=i)
78 for n in nodes.values(): # fill in dependencies for each node
79 n.extend([nodes[name] for name in n.data.dependencies()])
80 graph = Graph(nodes.values())
81 graph.topological_sort()