From 940f318b318c8e9f8c7e2bfd448ac5971c7dd9b1 Mon Sep 17 00:00:00 2001 From: Stefan van der Walt Date: Sun, 1 Nov 2009 12:38:36 +0200 Subject: [PATCH] Remove plugin functionality from io.py. Implement setting default plugins and querying the plugins available. --- scikits/image/io/__init__.py | 1 + scikits/image/io/io.py | 42 +--------- scikits/image/io/plugin.py | 106 ++++++++++++++++++++++++++ scikits/image/io/tests/test_plugin.py | 13 ++++ 4 files changed, 124 insertions(+), 38 deletions(-) diff --git a/scikits/image/io/__init__.py b/scikits/image/io/__init__.py index 3c701ff1..da516861 100644 --- a/scikits/image/io/__init__.py +++ b/scikits/image/io/__init__.py @@ -4,6 +4,7 @@ import pil_plugin import matplotlib_plugin from plugin import register as register_plugin + from sift import * from collection import * diff --git a/scikits/image/io/io.py b/scikits/image/io/io.py index c4d61f99..11369bec 100644 --- a/scikits/image/io/io.py +++ b/scikits/image/io/io.py @@ -1,40 +1,6 @@ __all__ = ['imread', 'imsave', 'imshow'] -from scikits.image.io.plugin import plugin_store - -def _call_plugin(kind, *args, **kwargs): - """Find the appropriate plugin of 'kind' and execute it. - - Parameters - ---------- - kind : {'imshow', 'imsave', 'imread'} - Function to look up. - plugin : str, optional - Plugin to load. Defaults to None, in which case the first - matching plugin is used. - *args, **kwargs : arguments and keyword arguments - Passed to the plugin function. - - """ - if not kind in plugin_store: - raise ValueError('Invalid function (%s) requested.' % kind) - - plugin_funcs = plugin_store[kind] - if len(plugin_funcs) == 0: - raise RuntimeError('No suitable plugin registered for %s' % kind) - - plugin = kwargs.pop('plugin', None) - if plugin is None: - _, func = plugin_funcs[0] - else: - try: - func = [f for (p,f) in plugin_funcs if p == plugin][0] - except IndexError: - raise RuntimeError('Could not find the plugin "%s" for %s.' % \ - (plugin, kind)) - - return func(*args, **kwargs) - +from scikits.image.io import plugin as _plugin def imread(fname, as_grey=False, dtype=None, plugin=None, flatten=None, **plugin_args): @@ -78,7 +44,7 @@ def imread(fname, as_grey=False, dtype=None, plugin=None, flatten=None, if flatten is not None: as_grey = flatten - return _call_plugin('read', fname, as_grey=as_grey, dtype=dtype, + return _plugin.call('read', fname, as_grey=as_grey, dtype=dtype, plugin=plugin, **plugin_args) def imsave(fname, arr, plugin=None, **plugin_args): @@ -101,7 +67,7 @@ def imsave(fname, arr, plugin=None, **plugin_args): Passed to the given plugin. """ - return _call_plugin('save', fname, arr, plugin=plugin, **plugin_args) + return _plugin.call('save', fname, arr, plugin=plugin, **plugin_args) def imshow(arr, plugin=None, **plugin_args): """Display an image. @@ -121,4 +87,4 @@ def imshow(arr, plugin=None, **plugin_args): Passed to the given plugin. """ - return _call_plugin('show', arr, plugin=plugin, **plugin_args) + return _plugin.call('show', arr, plugin=plugin, **plugin_args) diff --git a/scikits/image/io/plugin.py b/scikits/image/io/plugin.py index 3557e2d8..42146bfc 100644 --- a/scikits/image/io/plugin.py +++ b/scikits/image/io/plugin.py @@ -2,6 +2,10 @@ """ +__all__ = ['register', 'use'] + +import warnings + plugin_store = {'read': [], 'save': [], 'show': []} @@ -35,3 +39,105 @@ def register(name, **kwds): raise ValueError('Can only register functions as plugins.') plugin_store[kind].append((name, func)) + + +def call(kind, *args, **kwargs): + """Find the appropriate plugin of 'kind' and execute it. + + Parameters + ---------- + kind : {'show', 'save', 'read'} + Function to look up. + plugin : str, optional + Plugin to load. Defaults to None, in which case the first + matching plugin is used. + *args, **kwargs : arguments and keyword arguments + Passed to the plugin function. + + """ + if not kind in plugin_store: + raise ValueError('Invalid function (%s) requested.' % kind) + + plugin_funcs = plugin_store[kind] + if len(plugin_funcs) == 0: + raise RuntimeError('No suitable plugin registered for %s' % kind) + + plugin = kwargs.pop('plugin', None) + if plugin is None: + _, func = plugin_funcs[0] + else: + try: + func = [f for (p,f) in plugin_funcs if p == plugin][0] + except IndexError: + raise RuntimeError('Could not find the plugin "%s" for %s.' % \ + (plugin, kind)) + + return func(*args, **kwargs) + +def use(name, kind=None): + """Set the default plugin for a specified operation. + + Parameters + ---------- + name : str + Name of plugin. + kind : {'save', 'read', 'show'}, optional + Set the plugin for this function. By default, + the plugin is set for all functions. + + Examples + -------- + + Use Python Imaging Library to read images: + + >>> from scikits.image.io import plugin + >>> plugin.use('PIL', 'read') + + """ + if kind is None: + kind = plugin_store.keys() + else: + kind = [kind] + + for k in kind: + if not k in plugin_store: + raise RuntimeError("Could not find plugin for '%s'" % k) + + funcs = plugin_store[k] + + # Shuffle the plugins so that the requested plugin stands first + # in line + funcs = [(n, f) for (n, f) in funcs if n == name] + \ + [(n, f) for (n, f) in funcs if n != name] + + n, f = funcs[0] + if not n == name: + warnings.warn(RuntimeWarning('Could not set plugin "%s" for' + ' function "%s".' % (name, k))) + + plugin_store[k] = funcs + +def available(kind=None): + """List available plugins. + + Parameters + ---------- + kind : {'show', 'save', 'read'}, optional + Display the plugin list for the given function type. If not specified, + return a dictionary with the plugins for all functions. + + """ + if kind is None: + kind = plugin_store.keys() + else: + kind = [kind] + + d = {} + for k in kind: + if not k in plugin_store: + raise ValueError('No function "%s" exists in the plugin registry.' + % kind) + + d[k] = [name for (name, func) in plugin_store[k]] + + return d diff --git a/scikits/image/io/tests/test_plugin.py b/scikits/image/io/tests/test_plugin.py index 85ae7694..987ea8c7 100644 --- a/scikits/image/io/tests/test_plugin.py +++ b/scikits/image/io/tests/test_plugin.py @@ -18,9 +18,13 @@ def show(arr, plugin_arg=None): assert arr == [1, 2, 3] assert plugin_arg == (1, 2) +def show_other(arr): + return "other" + def setup_module(self): self.backup_plugin_store = deepcopy(plugin.plugin_store) plugin.register('test', read=read, save=save, show=show) + plugin.register('other', show=show_other) def teardown_module(self): plugin.plugin_store = self.backup_plugin_store @@ -35,5 +39,14 @@ class TestPlugin: def test_show(self): io.imshow([1, 2, 3], plugin_arg=(1, 2), plugin='test') + def test_use(self): + plugin.use('other', 'show') + assert io.imshow(None) == 'other' + + def test_available(self): + plugin.use('other', 'show') + d = plugin.available('show') + assert d['show'][0] == 'other' + if __name__ == "__main__": run_module_suite()