summaryrefslogtreecommitdiff
path: root/pkg_resources.py
diff options
context:
space:
mode:
authorPhilip Thiem <ptthiem@gmail.com>2014-04-16 15:26:18 -0500
committerPhilip Thiem <ptthiem@gmail.com>2014-04-16 15:26:18 -0500
commitb84464da6025f83488ad9f085692bc32c868fca7 (patch)
tree8d477ca6aaabd21528aaf03baff608025dd4937b /pkg_resources.py
parent5c08ba7d5c14f27fa44b6b8278a8f3cbbbbc8614 (diff)
downloadpython-setuptools-git-b84464da6025f83488ad9f085692bc32c868fca7.tar.gz
caching the zip manifests Fixes #154
--HG-- extra : rebase_source : 0f32792e01b6a1b746a1e07ffa4d7a85eeda1595
Diffstat (limited to 'pkg_resources.py')
-rw-r--r--pkg_resources.py71
1 files changed, 42 insertions, 29 deletions
diff --git a/pkg_resources.py b/pkg_resources.py
index 5734989d..fd1663c2 100644
--- a/pkg_resources.py
+++ b/pkg_resources.py
@@ -1530,33 +1530,48 @@ 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 ContextualZipFile(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 ZipManifests(object):
+
+ def __init__(self):
+ self.known = dict()
+
+ def __call__(self, path):
+ path = os.path.normpath(path)
+ stat = os.stat(path)
+
+ if path not in self.known or self.known[path][0] != stat.st_mtime:
+ self.known[path] = (stat.st_mtime, self.build_manifest(path))
+
+ return self.known[path][1]
+
+ def build_manifest(self, 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 ContextualZipFile(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
+build_zipmanifest = ZipManifests()
class ContextualZipFile(zipfile.ZipFile):
@@ -1586,7 +1601,6 @@ class ZipProvider(EggProvider):
def __init__(self, module):
EggProvider.__init__(self, module)
- self.zipinfo = build_zipmanifest(self.loader.archive)
self.zip_pre = self.loader.archive+os.sep
def _zipinfo_name(self, fspath):
@@ -1802,7 +1816,6 @@ class EggMetadata(ZipProvider):
def __init__(self, importer):
"""Create a metadata provider from a zipimporter"""
- self.zipinfo = build_zipmanifest(importer.archive)
self.zip_pre = importer.archive+os.sep
self.loader = importer
if importer.prefix: