aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason R. Coombs <jaraco@jaraco.com>2014-05-07 11:52:53 -0400
committerJason R. Coombs <jaraco@jaraco.com>2014-05-07 11:52:53 -0400
commit07e07db83c26af971b3b1eb31517d04252eb5442 (patch)
tree1afbe077ba2bc4e4995d5429069b721f16ea82de
parentad7c41a6e717a7d91a8dc08a2530e1187139b799 (diff)
parent2edec4688999a14f63cb842aa5df491464626b20 (diff)
downloadexternal_python_setuptools-07e07db83c26af971b3b1eb31517d04252eb5442.tar.gz
external_python_setuptools-07e07db83c26af971b3b1eb31517d04252eb5442.tar.bz2
external_python_setuptools-07e07db83c26af971b3b1eb31517d04252eb5442.zip
Merge Pull Request #483.5.2
-rw-r--r--CHANGES.txt7
-rwxr-xr-xsetuptools/command/easy_install.py51
2 files changed, 44 insertions, 14 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index a1d25194..65577273 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -3,6 +3,13 @@ CHANGES
=======
-----
+3.5.2
+-----
+
+* Issue #168: More robust handling of replaced zip files and stale caches.
+ Fixes ZipImportError complaining about a 'bad local header'.
+
+-----
3.5.1
-----
diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py
index 00cd300a..a5f324e3 100755
--- a/setuptools/command/easy_install.py
+++ b/setuptools/command/easy_install.py
@@ -646,6 +646,15 @@ Please make the appropriate changes for your system and try again.
def process_distribution(self, requirement, dist, deps=True, *info):
self.update_pth(dist)
self.package_index.add(dist)
+ # First remove the dist from self.local_index, to avoid problems using
+ # old cached data in case its underlying file has been replaced.
+ #
+ # This is a quick-fix for a zipimporter caching issue in case the dist
+ # has been implemented as and already loaded from a zip file that got
+ # replaced later on. For more detailed information see setuptools issue
+ # #168 at 'http://bitbucket.org/pypa/setuptools/issue/168'.
+ if dist in self.local_index[dist.key]:
+ self.local_index.remove(dist)
self.local_index.add(dist)
self.install_egg_scripts(dist)
self.installed_projects[dist.key] = dist
@@ -1574,20 +1583,34 @@ def auto_chmod(func, arg, exc):
reraise(et, (ev[0], ev[1] + (" %s %s" % (func,arg))))
def uncache_zipdir(path):
- """Ensure that the importer caches dont have stale info for `path`"""
- from zipimport import _zip_directory_cache as zdc
- _uncache(path, zdc)
- _uncache(path, sys.path_importer_cache)
-
-def _uncache(path, cache):
- if path in cache:
- del cache[path]
- else:
- path = normalize_path(path)
- for p in cache:
- if normalize_path(p)==path:
- del cache[p]
- return
+ """
+ Remove any globally cached zip file related data for `path`
+
+ Stale zipimport.zipimporter objects need to be removed when a zip file is
+ replaced as they contain cached zip file directory information. If they are
+ asked to get data from their zip file, they will use that cached
+ information to calculate the data location in the zip file. This calculated
+ location may be incorrect for the replaced zip file, which may in turn
+ cause the read operation to either fail or return incorrect data.
+
+ Note we have no way to clear any local caches from here. That is left up to
+ whomever is in charge of maintaining that cache.
+
+ """
+ normalized_path = normalize_path(path)
+ _uncache(normalized_path, zipimport._zip_directory_cache)
+ _uncache(normalized_path, sys.path_importer_cache)
+
+def _uncache(normalized_path, cache):
+ to_remove = []
+ prefix_len = len(normalized_path)
+ for p in cache:
+ np = normalize_path(p)
+ if (np.startswith(normalized_path) and
+ np[prefix_len:prefix_len + 1] in (os.sep, '')):
+ to_remove.append(p)
+ for p in to_remove:
+ del cache[p]
def is_python(text, filename='<string>'):
"Is this string a valid Python script?"