X-Git-Url: http://git.tremily.us/?a=blobdiff_plain;ds=sidebyside;f=hooke%2Futil%2Fpluggable.py;h=1379c82c4ed5f6d05d950743d127a08656d3bd99;hb=b90995fb4b6d8151df862d40edc8c369d7052cfa;hp=0a491cb67b9491f4719292c86697422a6fd749a6;hpb=c46aaa51003a6722a28eea0e49f63ef1bb0e882d;p=hooke.git diff --git a/hooke/util/pluggable.py b/hooke/util/pluggable.py index 0a491cb..1379c82 100644 --- a/hooke/util/pluggable.py +++ b/hooke/util/pluggable.py @@ -2,24 +2,27 @@ # # This file is part of Hooke. # -# Hooke is free software: you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation, either -# version 3 of the License, or (at your option) any later version. +# Hooke is free software: you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. # -# Hooke is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. +# Hooke is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General +# Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with Hooke. If not, see # . -"""`pluggable` +"""``pluggable`` provides utility functions for extensible plugin modules. """ -from ..util.graph import Node, Graph +import logging + +from ..compat.odict import odict +from .graph import Node, Graph class IsSubclass (object): @@ -58,6 +61,48 @@ class IsSubclass (object): return False return subclass + +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 + + def construct_graph(this_modname, submodnames, class_selector, assert_name_match=True): """Search the submodules `submodnames` of a module `this_modname` @@ -72,13 +117,7 @@ def construct_graph(this_modname, submodnames, class_selector, is returned. """ instances = {} - 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) - this_mod = __import__(this_modname, fromlist=[submodname]) - submod = getattr(this_mod, submodname) + for submodname,submod in submods(this_modname, submodnames): for objname in dir(submod): obj = getattr(submod, objname) if class_selector(obj):