4 from ..util.graph import Node, Graph
7 class IsSubclass (object):
8 """A safe subclass comparator.
18 >>> is_subclass = IsSubclass(A)
21 >>> is_subclass = IsSubclass(A, blacklist=[A])
29 def __init__(self, base_class, blacklist=None):
30 self.base_class = base_class
33 self.blacklist = blacklist
34 def __call__(self, other):
36 subclass = issubclass(other, self.base_class)
39 if other in self.blacklist:
43 def construct_graph(this_modname, submodnames, class_selector,
44 assert_name_match=True):
45 """Search the submodules `submodnames` of a module `this_modname`
46 for class objects for which `class_selector(class)` returns
47 `True`. These classes are instantiated, and the `instance.name`
48 is compared to the `submodname` (if `assert_name_match` is
51 The instances are further arranged into a dependency
52 :class:`hooke.util.graph.Graph` according to their
53 `instance.dependencies()` values. The topologically sorted graph
57 for submodname in submodnames:
58 count = len([s for s in submodnames if s == submodname])
59 assert count > 0, 'No %s entries: %s' % (submodname, submodnames)
60 assert count == 1, 'Multiple (%d) %s entries: %s' \
61 % (count, submodname, submodnames)
62 this_mod = __import__(this_modname, fromlist=[submodname])
63 submod = getattr(this_mod, submodname)
64 for objname in dir(submod):
65 obj = getattr(submod, objname)
66 if class_selector(obj):
68 if assert_name_match == True and instance.name != submodname:
70 'Instance name %s does not match module name %s'
71 % (instance.name, submodname))
72 instances[instance.name] = instance
74 for i in instances.values(): # make nodes for each instance
75 nodes[i.name] = Node(data=i)
76 for n in nodes.values(): # fill in dependencies for each node
77 n.extend([nodes[name] for name in n.data.dependencies()])
78 graph = Graph(nodes.values())
79 graph.topological_sort()