diff options
author | Jason R. Coombs <jaraco@jaraco.com> | 2014-05-07 11:52:53 -0400 |
---|---|---|
committer | Jason R. Coombs <jaraco@jaraco.com> | 2014-05-07 11:52:53 -0400 |
commit | 07e07db83c26af971b3b1eb31517d04252eb5442 (patch) | |
tree | 1afbe077ba2bc4e4995d5429069b721f16ea82de | |
parent | ad7c41a6e717a7d91a8dc08a2530e1187139b799 (diff) | |
parent | 2edec4688999a14f63cb842aa5df491464626b20 (diff) | |
download | external_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.txt | 7 | ||||
-rwxr-xr-x | setuptools/command/easy_install.py | 51 |
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?" |