From c398d967e0281540d84e4ba2c14424eb1944288a Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Tue, 1 Jul 2014 10:12:10 +0200 Subject: Added support for loading resources. --- pluginbase.py | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) (limited to 'pluginbase.py') diff --git a/pluginbase.py b/pluginbase.py index 426a105..1158ed9 100644 --- a/pluginbase.py +++ b/pluginbase.py @@ -9,8 +9,10 @@ :copyright: (c) Copyright 2014 by Armin Ronacher. :license: BSD, see LICENSE for more details. """ +import os import sys import uuid +import errno import pkgutil import hashlib import threading @@ -23,9 +25,11 @@ PY2 = sys.version_info[0] == 2 if PY2: text_type = unicode string_types = (unicode, str) + from cStringIO import StringIO as NativeBytesIO else: text_type = str string_types = (str,) + from io import BytesIO as NativeBytesIO _local = threading.local() @@ -261,10 +265,36 @@ class PluginSource(object): :param name: the name of the plugin to load. """ + if '.' in name: + raise ImportError('Plugin names cannot contain dots.') with self: return __import__(self.base.package + '.' + name, globals(), {}, ['__name__']) + def open_resource(self, plugin, filename): + """This function locates a resource inside the plugin and returns + a byte stream to the contents of it. If the resource cannot be + loaded an :exc:`IOError` will be raised. Only plugins that are + real Python packages can contain resources. Plain old Python + modules do not allow this for obvious reasons. + + .. versionadded:: 0.3 + + :param plugin: the name of the plugin to open the resource of. + :param filename: the name of the file within the plugin to open. + """ + mod = self.load_plugin(plugin) + fn = getattr(mod, '__file__', None) + if fn is not None: + if fn.endswith(('.pyc', '.pyo')): + fn = fn[:-1] + if os.path.isfile(fn): + return open(os.path.join(os.path.dirname(fn), filename), 'rb') + buf = pkgutil.get_data(self.mod.__name__ + '.' + plugin, filename) + if buf is None: + raise IOError(errno.ENOEXITS, 'Could not find resource') + return NativeBytesIO(buf) + def cleanup(self): """Cleans up all loaded plugins manually. This is necessary to call only if :attr:`persist` is enabled. Otherwise this happens @@ -369,6 +399,7 @@ class _ImportHook(ModuleType): actual_name = space._rewrite_module_path(name) if actual_name is not None: import_name = actual_name + return self._system_import(import_name, globals, locals, fromlist, level) -- cgit v1.2.1