+# 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.
"""
from ..config import Setting
-from ..util.graph import Node, Graph
+from ..util.pluggable import IsSubclass, construct_graph
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.
"""
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."""
The suggested section setting is::
- Setting(section='%s driver' % self.name, help=self.__doc__)
+ Setting(section=self.setting_section, help=self.__doc__)
"""
return []
# 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,