1 # Copyright (C) 2010 W. Trevor King <wking@drexel.edu>
3 # This file is part of Hooke.
5 # Hooke is free software: you can redistribute it and/or
6 # modify it under the terms of the GNU Lesser General Public
7 # License as published by the Free Software Foundation, either
8 # version 3 of the License, or (at your option) any later version.
10 # Hooke is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU Lesser General Public License for more details.
15 # You should have received a copy of the GNU Lesser General Public
16 # License along with Hooke. If not, see
17 # <http://www.gnu.org/licenses/>.
22 from ..util.graph import Node, Graph
25 class IsSubclass (object):
26 """A safe subclass comparator.
36 >>> is_subclass = IsSubclass(A)
39 >>> is_subclass = IsSubclass(A, blacklist=[A])
47 def __init__(self, base_class, blacklist=None):
48 self.base_class = base_class
51 self.blacklist = blacklist
52 def __call__(self, other):
54 subclass = issubclass(other, self.base_class)
57 if other in self.blacklist:
61 def construct_graph(this_modname, submodnames, class_selector,
62 assert_name_match=True):
63 """Search the submodules `submodnames` of a module `this_modname`
64 for class objects for which `class_selector(class)` returns
65 `True`. These classes are instantiated, and the `instance.name`
66 is compared to the `submodname` (if `assert_name_match` is
69 The instances are further arranged into a dependency
70 :class:`hooke.util.graph.Graph` according to their
71 `instance.dependencies()` values. The topologically sorted graph
75 for submodname in submodnames:
76 count = len([s for s in submodnames if s == submodname])
77 assert count > 0, 'No %s entries: %s' % (submodname, submodnames)
78 assert count == 1, 'Multiple (%d) %s entries: %s' \
79 % (count, submodname, submodnames)
80 this_mod = __import__(this_modname, fromlist=[submodname])
81 submod = getattr(this_mod, submodname)
82 for objname in dir(submod):
83 obj = getattr(submod, objname)
84 if class_selector(obj):
86 if assert_name_match == True and instance.name != submodname:
88 'Instance name %s does not match module name %s'
89 % (instance.name, submodname))
90 instances[instance.name] = instance
92 for i in instances.values(): # make nodes for each instance
93 nodes[i.name] = Node(data=i)
94 for n in nodes.values(): # fill in dependencies for each node
95 n.extend([nodes[name] for name in n.data.dependencies()])
96 graph = Graph(nodes.values())
97 graph.topological_sort()