summaryrefslogtreecommitdiff
path: root/pluginbase.py
diff options
context:
space:
mode:
authorArmin Ronacher <armin.ronacher@active-4.com>2014-07-01 10:12:10 +0200
committerArmin Ronacher <armin.ronacher@active-4.com>2014-07-01 10:12:10 +0200
commitc398d967e0281540d84e4ba2c14424eb1944288a (patch)
treec0638db9dda2a0998854d470c88511dad905559d /pluginbase.py
parent08f0c0b112e6cdaa7dbf2e830c7fe95f513acd6d (diff)
downloadpluginbase-c398d967e0281540d84e4ba2c14424eb1944288a.tar.gz
Added support for loading resources.
Diffstat (limited to 'pluginbase.py')
-rw-r--r--pluginbase.py31
1 files changed, 31 insertions, 0 deletions
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)