summaryrefslogtreecommitdiff
path: root/pkg_resources.py
diff options
context:
space:
mode:
authorPhilip Thiem <ptthiem@gmail.com>2013-02-02 18:26:56 -0600
committerPhilip Thiem <ptthiem@gmail.com>2013-02-02 18:26:56 -0600
commit1f43ab9b03178a3eb3a00f509338dc1bd40808a1 (patch)
tree47a63bfb9459aa598a5aa411ecb3f2edb11eec3b /pkg_resources.py
parentc0a6a1347041a816d51331285a183fd8b8f69182 (diff)
downloadpython-setuptools-git-1f43ab9b03178a3eb3a00f509338dc1bd40808a1.tar.gz
This changes distribute to use zipfile for obtaining a manifest of zip files
instead of zipimpot._zip_directory_cache. As I don't see any place that the cache is being clear, should in effect remove the zipimport private variable dependency --HG-- branch : distribute extra : rebase_source : 275dd3d5a2f55dba541f7f12a1bf8ee7c3465825
Diffstat (limited to 'pkg_resources.py')
-rw-r--r--pkg_resources.py48
1 files changed, 37 insertions, 11 deletions
diff --git a/pkg_resources.py b/pkg_resources.py
index f8de449e..e1bf9ee0 100644
--- a/pkg_resources.py
+++ b/pkg_resources.py
@@ -13,7 +13,8 @@ The package resource API is designed to work with normal filesystem packages,
method.
"""
-import sys, os, zipimport, time, re, imp, types
+import sys, os, zipimport, time, re, imp, types
+import zipfile
from urlparse import urlparse, urlunparse
try:
@@ -1348,7 +1349,33 @@ class EmptyProvider(NullProvider):
empty_provider = EmptyProvider()
-
+def build_zipmanifest(path):
+ """
+ This builds a similar dictionary to the zipimport directory
+ caches. However instead of tuples, ZipInfo objects are stored.
+
+ The translation of the tuple is as follows:
+ * [0] - zipinfo.filename on stock pythons this needs "/" --> os.sep
+ on pypy it is the same (one reason why distribute did work
+ in some cases on pypy and win32).
+ * [1] - zipinfo.compress_type
+ * [2] - zipinfo.compress_size
+ * [3] - zipinfo.file_size
+ * [4] - len(utf-8 encoding of filename) if zipinfo & 0x800
+ len(ascii encoding of filename) otherwise
+ * [5] - (zipinfo.date_time[0] - 1980) << 9 |
+ zipinfo.date_time[1] << 5 | zipinfo.date_time[2]
+ * [6] - (zipinfo.date_time[3] - 1980) << 11 |
+ zipinfo.date_time[4] << 5 | (zipinfo.date_time[5] // 2)
+ * [7] - zipinfo.CRC
+ """
+ zipinfo = dict()
+ with zipfile.ZipFile(path) as zfile:
+ for zitem in zfile.namelist():
+ zpath = zitem.replace('/', os.sep)
+ zipinfo[zpath] = zfile.getinfo(zitem)
+ assert zipinfo[zpath] is not None
+ return zipinfo
class ZipProvider(EggProvider):
@@ -1358,7 +1385,7 @@ class ZipProvider(EggProvider):
def __init__(self, module):
EggProvider.__init__(self,module)
- self.zipinfo = zipimport._zip_directory_cache[self.loader.archive]
+ self.zipinfo = build_zipmanifest(self.load.archive)
self.zip_pre = self.loader.archive+os.sep
def _zipinfo_name(self, fspath):
@@ -1393,12 +1420,10 @@ class ZipProvider(EggProvider):
return self._extract_resource(manager, zip_path)
@staticmethod
- def _get_date_and_size(zip_stat):
- 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.
- )
+ def _get_date_and_size(zip_stat):
+ size = zip_stat.file_size
+ date_time = zip_stat.date_time + (0, 0, -1) #ymdhms+wday, yday, dst
+ #1980 offset already done
timestamp = time.mktime(date_time)
return timestamp, size
@@ -1411,7 +1436,7 @@ class ZipProvider(EggProvider):
)
return os.path.dirname(last) # return the extracted directory name
- timestamp, size = self._get_date_and_size(self.zipinfo[zip_path])
+ timestamp, size = self._get_date_and_size(self.zipinfo[zip_path])
if not WRITE_SUPPORT:
raise IOError('"os.rename" and "os.unlink" are not supported '
@@ -1610,7 +1635,7 @@ class EggMetadata(ZipProvider):
def __init__(self, importer):
"""Create a metadata provider from a zipimporter"""
- self.zipinfo = zipimport._zip_directory_cache[importer.archive]
+ self.zipinfo = build_zipmanifest(importer.archive)
self.zip_pre = importer.archive+os.sep
self.loader = importer
if importer.prefix:
@@ -2841,3 +2866,4 @@ run_main = run_script # backward compatibility
add_activation_listener(lambda dist: dist.activate())
working_set.entries=[]; map(working_set.add_entry,sys.path) # match order
+