aboutsummaryrefslogtreecommitdiffstats
path: root/pkg_resources.py
diff options
context:
space:
mode:
Diffstat (limited to 'pkg_resources.py')
-rw-r--r--pkg_resources.py146
1 files changed, 73 insertions, 73 deletions
diff --git a/pkg_resources.py b/pkg_resources.py
index b3ce9701..16604b8b 100644
--- a/pkg_resources.py
+++ b/pkg_resources.py
@@ -25,6 +25,7 @@ __all__ = [
'safe_name', 'safe_version', 'run_main', 'BINARY_DIST', 'run_script',
'get_default_cache', 'EmptyProvider', 'empty_provider', 'normalize_path',
'WorkingSet', 'working_set', 'add_activation_listener', 'CHECKOUT_DIST',
+ 'list_resources', 'resource_exists', 'resource_isdir',
]
import sys, os, zipimport, time, re, imp
@@ -38,7 +39,6 @@ from sets import ImmutableSet
-
class ResolutionError(Exception):
"""Abstract base for dependency resolution errors"""
@@ -68,18 +68,18 @@ def register_loader_type(loader_type, provider_factory):
"""
_provider_factories[loader_type] = provider_factory
-def get_provider(moduleName):
- """Return an IResourceProvider for the named module"""
+def get_provider(moduleOrReq):
+ """Return an IResourceProvider for the named module or requirement"""
+ if isinstance(moduleOrReq,Requirement):
+ return working_set.find(moduleOrReq) or require(str(moduleOrReq))[0]
try:
- module = sys.modules[moduleName]
+ module = sys.modules[moduleOrReq]
except KeyError:
- __import__(moduleName)
- module = sys.modules[moduleName]
+ __import__(moduleOrReq)
+ module = sys.modules[moduleOrReq]
loader = getattr(module, '__loader__', None)
return _find_adapter(_provider_factories, loader)(module)
-
-
def _macosx_vers(_cache=[]):
if not _cache:
info = os.popen('/usr/bin/sw_vers').read().splitlines()
@@ -627,7 +627,7 @@ class ResourceManager:
def resource_isdir(self, package_name, resource_name):
"""Does the named resource exist in the named package?"""
- return get_provider(package_name).resource_isdir(self, resource_name)
+ return get_provider(package_name).resource_isdir(resource_name)
def resource_filename(self, package_name, resource_name):
"""Return a true filesystem path for specified resource"""
@@ -648,7 +648,7 @@ class ResourceManager:
)
def list_resources(self, package_name, resource_name):
- return get_provider(package_name).resource_listdir(self, resource_name)
+ return get_provider(package_name).resource_listdir(resource_name)
@@ -913,8 +913,8 @@ class NullProvider:
register_loader_type(object, NullProvider)
-class DefaultProvider(NullProvider):
- """Provides access to package resources in the filesystem"""
+class EggProvider(NullProvider):
+ """Provider based on a virtual filesystem"""
def __init__(self,module):
NullProvider.__init__(self,module)
@@ -925,22 +925,28 @@ class DefaultProvider(NullProvider):
# of multiple eggs; that's why we use module_path instead of .archive
path = self.module_path
old = None
- self.prefix = []
while path!=old:
if path.lower().endswith('.egg'):
self.egg_name = os.path.basename(path)
self.egg_info = os.path.join(path, 'EGG-INFO')
+ self.egg_root = path
break
old = path
path, base = os.path.split(path)
- self.prefix.append(base)
- self.prefix.reverse()
- def _has(self, path):
- return os.path.exists(path)
+
+
+
+
+class DefaultProvider(EggProvider):
+ """Provides access to package resources in the filesystem"""
+
+ def _has(self, path):
+ return os.path.exists(path)
+
def _isdir(self,path):
return os.path.isdir(path)
@@ -976,67 +982,63 @@ empty_provider = EmptyProvider()
-
-
-
-
-
-
-class ZipProvider(DefaultProvider):
+class ZipProvider(EggProvider):
"""Resource support for zips and eggs"""
eagers = None
def __init__(self, module):
- DefaultProvider.__init__(self,module)
+ EggProvider.__init__(self,module)
self.zipinfo = zipimport._zip_directory_cache[self.loader.archive]
self.zip_pre = self.loader.archive+os.sep
- def _short_name(self, path):
- if path.startswith(self.zip_pre):
- return path[len(self.zip_pre):]
- return path
+ def _zipinfo_name(self, fspath):
+ # Convert a virtual filename (full path to file) into a zipfile subpath
+ # usable with the zipimport directory cache for our target archive
+ if fspath.startswith(self.zip_pre):
+ return fspath[len(self.zip_pre):]
+ raise AssertionError(
+ "%s is not a subpath of %s" % (fspath,self.zip_pre)
+ )
- def get_resource_stream(self, manager, resource_name):
- return StringIO(self.get_resource_string(manager, resource_name))
+ def _parts(self,zip_path):
+ # Convert a zipfile subpath into an egg-relative path part list
+ fspath = self.zip_pre+zip_path # pseudo-fs path
+ if fspath.startswith(self.egg_root+os.sep):
+ return fspath[len(self.egg_root)+1:].split(os.sep)
+ raise AssertionError(
+ "%s is not a subpath of %s" % (fspath,self.egg_root)
+ )
- def get_resource_filename(self, manager, resource_name):
+ def get_resource_filename(self, manager, resource_name):
if not self.egg_name:
raise NotImplementedError(
"resource_filename() only supported for .egg, not .zip"
)
-
# no need to lock for extraction, since we use temp names
+ zip_path = self._resource_to_zip(resource_name)
eagers = self._get_eager_resources()
- if resource_name in eagers:
+ if '/'.join(self._parts(zip_path)) in eagers:
for name in eagers:
- self._extract_resource(manager, name)
-
- return self._extract_resource(manager, resource_name)
-
- def _extract_directory(self, manager, resource_name):
- if resource_name.endswith('/'):
- resource_name = resource_name[:-1]
- for resource in self.resource_listdir(resource_name):
- last = self._extract_resource(manager, resource_name+'/'+resource)
- return os.path.dirname(last) # return the directory path
-
-
-
- def _extract_resource(self, manager, resource_name):
- if self.resource_isdir(resource_name):
- return self._extract_directory(manager, resource_name)
+ self._extract_resource(manager, self._eager_to_zip(name))
+ return self._extract_resource(manager, zip_path)
+
+ def _extract_resource(self, manager, zip_path):
+ if zip_path in self._index():
+ for name in self._index()[zip_path]:
+ last = self._extract_resource(
+ manager, os.path.join(zip_path, name)
+ )
+ return os.path.dirname(last) # return the extracted directory name
- parts = resource_name.split('/')
- zip_path = os.path.join(self.module_path, *parts)
- zip_stat = self.zipinfo[os.path.join(*self.prefix+parts)]
+ zip_stat = self.zipinfo[zip_path]
t,d,size = zip_stat[5], zip_stat[6], zip_stat[3]
date_time = (
(d>>9)+1980, (d>>5)&0xF, d&0x1F, # ymd
(t&0xFFFF)>>11, (t>>5)&0x3F, (t&0x1F) * 2, 0, 0, -1 # hms, etc.
)
timestamp = time.mktime(date_time)
- real_path = manager.get_cache_path(self.egg_name, self.prefix+parts)
+ real_path = manager.get_cache_path(self.egg_name, self._parts(zip_path))
if os.path.isfile(real_path):
stat = os.stat(real_path)
@@ -1060,10 +1062,8 @@ class ZipProvider(DefaultProvider):
# so we're done
return real_path
raise
-
return real_path
-
def _get_eager_resources(self):
if self.eagers is None:
eagers = []
@@ -1077,12 +1077,9 @@ class ZipProvider(DefaultProvider):
try:
return self._dirindex
except AttributeError:
- ind = {}; skip = len(self.prefix)
+ ind = {}
for path in self.zipinfo:
parts = path.split(os.sep)
- if parts[:skip] != self.prefix:
- continue # only include items under our prefix
- parts = parts[skip:] # but don't include prefix in paths
while parts:
parent = '/'.join(parts[:-1])
if parent in ind:
@@ -1093,26 +1090,26 @@ class ZipProvider(DefaultProvider):
self._dirindex = ind
return ind
- def _has(self, path):
- return self._short_name(path) in self.zipinfo or self._isdir(path)
+ def _has(self, fspath):
+ zip_path = self._zipinfo_name(fspath)
+ return zip_path in self.zipinfo or zip_path in self._index()
- def _isdir(self,path):
- return self._dir_name(path) in self._index()
+ def _isdir(self,fspath):
+ return self._zipinfo_name(fspath) in self._index()
- def _listdir(self,path):
- return list(self._index().get(self._dir_name(path), ()))
+ def _listdir(self,fspath):
+ return list(self._index().get(self._zipinfo_name(fspath), ()))
- def _dir_name(self,path):
- if path.startswith(self.module_path+os.sep):
- path = path[len(self.module_path+os.sep):]
- path = path.replace(os.sep,'/')
- if path.endswith('/'): path = path[:-1]
- return path
- _get = NullProvider._get
+
+ def _eager_to_zip(self,resource_name):
+ return self._zipinfo_name(self._fn(self.egg_root,resource_name))
+
+ def _resource_to_zip(self,resource_name):
+ return self._zipinfo_name(self._fn(self.module_path,resource_name))
register_loader_type(zipimport.zipimporter, ZipProvider)
@@ -1146,6 +1143,9 @@ register_loader_type(zipimport.zipimporter, ZipProvider)
+
+
+
class PathMetadata(DefaultProvider):
"""Metadata provider for egg directories