summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Doc/library/pkgutil.rst23
-rw-r--r--Lib/pkgutil.py37
-rw-r--r--Misc/NEWS3
3 files changed, 62 insertions, 1 deletions
diff --git a/Doc/library/pkgutil.rst b/Doc/library/pkgutil.rst
index 1fbfb041dc..d086ada013 100644
--- a/Doc/library/pkgutil.rst
+++ b/Doc/library/pkgutil.rst
@@ -8,7 +8,7 @@
.. versionadded:: 2.3
-This module provides a single function:
+This module provides functions to manipulate packages:
.. function:: extend_path(path, name)
@@ -41,3 +41,24 @@ This module provides a single function:
this function to raise an exception (in line with :func:`os.path.isdir`
behavior).
+.. function:: get_data(package, resource)
+
+ Get a resource from a package.
+
+ This is a wrapper round the PEP 302 loader :func:`get_data` API. The package
+ argument should be the name of a package, in standard module format
+ (foo.bar). The resource argument should be in the form of a relative
+ filename, using ``/`` as the path separator. The parent directory name
+ ``..`` is not allowed, and nor is a rooted name (starting with a ``/``).
+
+ The function returns a binary string, which is the contents of the
+ specified resource.
+
+ For packages located in the filesystem, which have already been imported,
+ this is the rough equivalent of::
+
+ d = os.path.dirname(sys.modules[package].__file__)
+ data = open(os.path.join(d, resource), 'rb').read()
+
+ If the package cannot be located or loaded, or it uses a PEP 302 loader
+ which does not support :func:`get_data`, then None is returned.
diff --git a/Lib/pkgutil.py b/Lib/pkgutil.py
index 37738e4a75..c50928f701 100644
--- a/Lib/pkgutil.py
+++ b/Lib/pkgutil.py
@@ -544,3 +544,40 @@ def extend_path(path, name):
f.close()
return path
+
+def get_data(package, resource):
+ """Get a resource from a package.
+
+ This is a wrapper round the PEP 302 loader get_data API. The package
+ argument should be the name of a package, in standard module format
+ (foo.bar). The resource argument should be in the form of a relative
+ filename, using '/' as the path separator. The parent directory name '..'
+ is not allowed, and nor is a rooted name (starting with a '/').
+
+ The function returns a binary string, which is the contents of the
+ specified resource.
+
+ For packages located in the filesystem, which have already been imported,
+ this is the rough equivalent of
+
+ d = os.path.dirname(sys.modules[package].__file__)
+ data = open(os.path.join(d, resource), 'rb').read()
+
+ If the package cannot be located or loaded, or it uses a PEP 302 loader
+ which does not support get_data(), then None is returned.
+ """
+
+ loader = get_loader(package)
+ if loader is None or not hasattr(loader, 'get_data'):
+ return None
+ mod = sys.modules.get(package) or loader.load_module(package)
+ if mod is None or not hasattr(mod, '__file__'):
+ return None
+
+ # Modify the resource name to be compatible with the loader.get_data
+ # signature - an os.path format "filename" starting with the dirname of
+ # the package's __file__
+ parts = resource.split('/')
+ parts.insert(0, os.path.dirname(mod.__file__))
+ resource_name = os.path.join(*parts)
+ return loader.get_data(resource_name)
diff --git a/Misc/NEWS b/Misc/NEWS
index b4077e5af2..6cc3678c4f 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -29,6 +29,9 @@ Extensions Modules
Library
-------
+- Issue #2439: Added new function pkgutil.get_data(), which is a
+ convenience wrapper for the PEP 302 get_data() API.
+
- Issue #2616: The ctypes.pointer() and ctypes.POINTER() functions are
now implemented in C for better performance.