Ran update_copyright.py, updating all the copyright blurbs and adding AUTHORS.
[hooke.git] / hooke / driver / __init__.py
index 6eed3f70c0f77687004eef10d25c36a9fc90f403..92ae9729a81447f560f0983b70b6587de81edae1 100644 (file)
@@ -1,3 +1,21 @@
+# Copyright (C) 2010 W. Trevor King <wking@drexel.edu>
+#
+# 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 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/>.
+
 """The driver module provides :class:`Driver`\s for identifying and
 reading data files.
 
@@ -7,7 +25,7 @@ to write your own to handle your lab's specific format.
 """
 
 from ..config import Setting
-from ..util.graph import Node, Graph
+from ..util.pluggable import IsSubclass, construct_graph
 
 
 DRIVER_MODULES = [
@@ -26,11 +44,10 @@ DRIVER_MODULES = [
 default.  TODO: autodiscovery
 """
 
-class NotRecognized (ValueError):
-    def __init__(self, path):
-        msg = 'Not a recognizable curve format: %s' % self.path
-        ValueError.__init__(self, msg)
-        self.path = path
+DRIVER_SETTING_SECTION = 'drivers'
+"""Name of the config section which controls driver selection.
+"""
+
 
 class Driver(object):
     """Base class for file format drivers.
@@ -40,6 +57,7 @@ class Driver(object):
     """
     def __init__(self, name):
         self.name = name
+        self.setting_section = '%s driver' % self.name
 
     def dependencies(self):
         """Return a list of :class:`Driver`\s we require."""
@@ -51,7 +69,7 @@ class Driver(object):
 
         The suggested section setting is::
 
-            Setting(section='%s driver' % self.name, help=self.__doc__)
+            Setting(section=self.setting_section, help=self.__doc__)
         """
         return []
 
@@ -73,44 +91,23 @@ class Driver(object):
 
 # Construct driver dependency graph and load default drivers.
 
-DRIVERS = {}
-"""(name, instance) :class:`dict` of all possible :class:`Driver`\s.
+DRIVER_GRAPH = construct_graph(
+    this_modname=__name__,
+    submodnames=[name for name,include in DRIVER_MODULES],
+    class_selector=IsSubclass(Driver, blacklist=[Driver]))
+"""Topologically sorted list of all possible :class:`Driver`\s.
 """
 
-for driver_modname,default_include in DRIVER_MODULES:
-    assert len([mod_name for mod_name,di in DRIVER_MODULES]) == 1, \
-        'Multiple %s entries in DRIVER_MODULES' % mod_name
-    this_mod = __import__(__name__, fromlist=[driver_modname])
-    driver_mod = getattr(this_mod, driver_modname)
-    for objname in dir(driver_mod):
-        obj = getattr(driver_mod, objname)
-        try:
-            subclass = issubclass(obj, Driver)
-        except TypeError:
-            continue
-        if subclass == True and obj != Driver:
-            d = obj()
-            if d.name != driver_modname:
-                raise Exception('Driver name %s does not match module name %s'
-                                % (d.name, driver_modname))
-            DRIVERS[d.name] = d
-
-DRIVER_GRAPH = Graph([Node([DRIVERS[name] for name in d.dependencies()],
-                           data=d)
-                      for d in DRIVERS.values()])
-DRIVER_GRAPH.topological_sort()
-
-
 def default_settings():
-    settings = [Setting(
-            'drivers', help='Enable/disable default drivers.')]
+    settings = [Setting(DRIVER_SETTING_SECTION,
+                        help='Enable/disable default drivers.')]
     for dnode in DRIVER_GRAPH:
         driver = dnode.data
         default_include = [di for mod_name,di in DRIVER_MODULES
                            if mod_name == driver.name][0]
         help = driver.__doc__.split('\n', 1)[0]
         settings.append(Setting(
-                section='drivers',
+                section=DRIVER_SETTING_SECTION,
                 option=driver.name,
                 value=str(default_include),
                 help=help,