+
+def submods(this_modname, submodnames):
+ """Iterate through (submodname, submod) pairs.
+ """
+ for submodname in submodnames:
+ count = len([s for s in submodnames if s == submodname])
+ assert count > 0, 'No %s entries: %s' % (submodname, submodnames)
+ assert count == 1, 'Multiple (%d) %s entries: %s' \
+ % (count, submodname, submodnames)
+ try:
+ this_mod = __import__(this_modname, fromlist=[submodname])
+ except ImportError, e:
+ # Use the root logger because the 'hooke' logger is
+ # configured by a Hooke instance after module imports.
+ logging.warn('could not import %s from %s: %s'
+ % (submodname, this_modname, e))
+ continue
+ submod = getattr(this_mod, submodname)
+ yield (submodname, submod)
+
+
+def construct_odict(this_modname, submodnames, class_selector,
+ instantiate=True):
+ """Search the submodules `submodnames` of a module `this_modname`
+ for class objects for which `class_selector(class)` returns
+ `True`. If `instantiate == True` these classes are instantiated
+ and stored in the returned :class:`hooke.compat.odict.odict` in
+ the order in which they were discovered. Otherwise, the class
+ itself is stored.
+ """
+ objs = odict()
+ for submodname,submod in submods(this_modname, submodnames):
+ for objname in dir(submod):
+ obj = getattr(submod, objname)
+ if class_selector(obj):
+ if instantiate == True:
+ obj = obj()
+ name = getattr(obj, 'name', submodname)
+ objs[name] = obj
+ return objs
+
+