Replace .config rather than reconstructing plugins, drivers, and UIs.
[hooke.git] / hooke / util / pluggable.py
index 14eaeb0209ed0f9bd4f6326dd19d85e355df3fe9..1379c82c4ed5f6d05d950743d127a08656d3bd99 100644 (file)
@@ -2,23 +2,25 @@
 #
 # 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
 # <http://www.gnu.org/licenses/>.
 
-"""`pluggable`
+"""``pluggable`` provides utility functions for extensible plugin modules.
 """
 
+import logging
+
 from ..compat.odict import odict
 from .graph import Node, Graph
 
@@ -60,6 +62,26 @@ class IsSubclass (object):
         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`
@@ -70,13 +92,7 @@ def construct_odict(this_modname, submodnames, class_selector,
     itself is stored.
     """
     objs = odict()
-    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):
@@ -101,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):