Commit e9aab0fb authored by Benjamin Peterson's avatar Benjamin Peterson

backout #19081 to fix #20621

parent 33b8219a
...@@ -395,145 +395,57 @@ class ZipFileModifiedAfterImportTestCase(ImportHooksBaseTestCase): ...@@ -395,145 +395,57 @@ class ZipFileModifiedAfterImportTestCase(ImportHooksBaseTestCase):
def setUp(self): def setUp(self):
zipimport._zip_directory_cache.clear() zipimport._zip_directory_cache.clear()
zipimport._zip_stat_cache.clear() zipimport._zip_stat_cache.clear()
# save sys.modules so we can unimport everything done by our tests.
self._sys_modules_orig = dict(sys.modules)
ImportHooksBaseTestCase.setUp(self) ImportHooksBaseTestCase.setUp(self)
def tearDown(self): def tearDown(self):
ImportHooksBaseTestCase.tearDown(self) ImportHooksBaseTestCase.tearDown(self)
# The closest we can come to un-importing our zipped up test modules.
sys.modules.clear()
sys.modules.update(self._sys_modules_orig)
if os.path.exists(TEMP_ZIP): if os.path.exists(TEMP_ZIP):
os.remove(TEMP_ZIP) os.remove(TEMP_ZIP)
def setUpZipFileModuleAndTestImports(self): def testZipFileChangesAfterFirstImport(self):
# Create a .zip file to test with """Alter the zip file after caching its index and try an import."""
self.zipfile_path = TEMP_ZIP
packdir = TESTPACK + os.sep packdir = TESTPACK + os.sep
files = {packdir + "__init__" + pyc_ext: (NOW, test_pyc), files = {packdir + "__init__" + pyc_ext: (NOW, test_pyc),
packdir + TESTMOD + ".py": (NOW, "test_value = 38\n"), packdir + TESTMOD + ".py": (NOW, "test_value = 38\n"),
"ziptest_a.py": (NOW, "test_value = 23\n"), "ziptest_a.py": (NOW, "test_value = 23\n"),
"ziptest_b.py": (NOW, "test_value = 42\n"), "ziptest_b.py": (NOW, "test_value = 42\n"),
"ziptest_c.py": (NOW, "test_value = 1337\n")} "ziptest_c.py": (NOW, "test_value = 1337\n")}
_write_zip_package(self.zipfile_path, files) zipfile_path = TEMP_ZIP
self.assertTrue(os.path.exists(self.zipfile_path)) _write_zip_package(zipfile_path, files)
sys.path.insert(0, self.zipfile_path) self.assertTrue(os.path.exists(zipfile_path))
sys.path.insert(0, zipfile_path)
self.testpack_testmod = TESTPACK + "." + TESTMOD
with io.open(self.zipfile_path, "rb") as orig_zip_file:
self.orig_zip_file_contents = orig_zip_file.read()
# Import something out of the zipfile and confirm it is correct. # Import something out of the zipfile and confirm it is correct.
testmod = __import__(self.testpack_testmod, testmod = __import__(TESTPACK + "." + TESTMOD,
globals(), locals(), ["__dummy__"]) globals(), locals(), ["__dummy__"])
self.assertEqual(testmod.test_value, 38) self.assertEqual(testmod.test_value, 38)
del sys.modules[TESTPACK]
del sys.modules[self.testpack_testmod]
# Import something else out of the zipfile and confirm it is correct. # Import something else out of the zipfile and confirm it is correct.
ziptest_b = __import__("ziptest_b", globals(), locals(), ["test_value"]) ziptest_b = __import__("ziptest_b", globals(), locals(), ["test_value"])
self.assertEqual(ziptest_b.test_value, 42) self.assertEqual(ziptest_b.test_value, 42)
del sys.modules["ziptest_b"]
def truncateAndFillZipWithNonZipGarbage(self): # Truncate and fill the zip file with non-zip garbage.
with io.open(self.zipfile_path, "wb") as byebye_valid_zip_file: with io.open(zipfile_path, "rb") as orig_zip_file:
orig_zip_file_contents = orig_zip_file.read()
with io.open(zipfile_path, "wb") as byebye_valid_zip_file:
byebye_valid_zip_file.write(b"Tear down this wall!\n"*1987) byebye_valid_zip_file.write(b"Tear down this wall!\n"*1987)
def restoreZipFileWithDifferentHeaderOffsets(self):
"""Make it a valid zipfile with some garbage at the start."""
# This alters all of the caches offsets within the file.
with io.open(self.zipfile_path, "wb") as new_zip_file:
new_zip_file.write(b"X"*1991) # The year Python was created.
new_zip_file.write(self.orig_zip_file_contents)
def testZipFileChangesAfterFirstImport(self):
"""Alter the zip file after caching its index and try an import."""
self.setUpZipFileModuleAndTestImports()
# The above call cached the .zip table of contents during its tests.
self.truncateAndFillZipWithNonZipGarbage()
# Now that the zipfile has been replaced, import something else from it # Now that the zipfile has been replaced, import something else from it
# which should fail as the file contents are now garbage. # which should fail as the file contents are now garbage.
with self.assertRaises(ImportError): with self.assertRaises(ImportError):
ziptest_a = __import__("ziptest_a", {}, {}, ["test_value"]) ziptest_a = __import__("ziptest_a", globals(), locals(),
# The code path used by the __import__ call is different than ["test_value"])
# that used by import statements. Try these as well. Some of
# these may create new zipimporter instances. We need to
# function properly using the global zipimport caches
# regardless of how many zipimporter instances for the same
# .zip file exist.
with self.assertRaises(ImportError):
import ziptest_a
with self.assertRaises(ImportError):
from ziptest_a import test_value
with self.assertRaises(ImportError):
exec("from {} import {}".format(TESTPACK, TESTMOD), {})
# Alters all of the offsets within the file # Now lets make it a valid zipfile that has some garbage at the start.
self.restoreZipFileWithDifferentHeaderOffsets() # This alters all of the offsets within the file
with io.open(zipfile_path, "wb") as new_zip_file:
new_zip_file.write(b"X"*1991) # The year Python was created.
new_zip_file.write(orig_zip_file_contents)
# Now that the zip file has been "restored" to a valid but different # Now that the zip file has been "restored" to a valid but different
# zipfile all zipimporter instances should *successfully* re-read the # zipfile the zipimporter should *successfully* re-read the new zip
# new file's end of file central index and be able to import again. # file's end of file central index and be able to import from it again.
ziptest_a = __import__("ziptest_a", globals(), locals(), ["test_value"])
# Importing a submodule triggers a different import code path.
test_ns = {}
exec("import " + self.testpack_testmod, test_ns)
self.assertEqual(getattr(test_ns[TESTPACK], TESTMOD).test_value, 38)
test_ns = {}
exec("from {} import {}".format(TESTPACK, TESTMOD), test_ns)
self.assertEqual(test_ns[TESTMOD].test_value, 38)
ziptest_a = __import__("ziptest_a", {}, {}, ["test_value"])
self.assertEqual(ziptest_a.test_value, 23)
ziptest_c = __import__("ziptest_c", {}, {}, ["test_value"])
self.assertEqual(ziptest_c.test_value, 1337)
def testZipFileSubpackageImport(self):
"""Import via multiple sys.path entries into parts of the zip."""
self.setUpZipFileModuleAndTestImports()
# Put a subdirectory within the zip file into the import path.
sys.path.insert(0, self.zipfile_path + os.sep + TESTPACK)
testmod = __import__(TESTMOD, {}, {}, ["test_value"])
self.assertEqual(testmod.test_value, 38)
del sys.modules[TESTMOD]
test_ns = {}
exec("from {} import test_value".format(TESTMOD), test_ns)
self.assertEqual(test_ns["test_value"], 38)
del sys.modules[TESTMOD]
# Confirm that imports from the top level of the zip file
# (already in sys.path from the setup call above) still work.
ziptest_a = __import__("ziptest_a", {}, {}, ["test_value"])
self.assertEqual(ziptest_a.test_value, 23)
del sys.modules["ziptest_a"]
import ziptest_c
self.assertEqual(ziptest_c.test_value, 1337)
del sys.modules["ziptest_c"]
self.truncateAndFillZipWithNonZipGarbage()
# Imports should now fail.
with self.assertRaises(ImportError):
testmod = __import__(TESTMOD, {}, {}, ["test_value"])
with self.assertRaises(ImportError):
exec("from {} import test_value".format(TESTMOD), {})
with self.assertRaises(ImportError):
import ziptest_a
self.restoreZipFileWithDifferentHeaderOffsets()
# Imports should work again, the central directory TOC will be re-read.
testmod = __import__(TESTMOD, {}, {}, ["test_value"])
self.assertEqual(testmod.test_value, 38)
del sys.modules[TESTMOD]
test_ns = {}
exec("from {} import test_value".format(TESTMOD), test_ns)
self.assertEqual(test_ns['test_value'], 38)
ziptest_a = __import__("ziptest_a", {}, {}, ["test_value"])
self.assertEqual(ziptest_a.test_value, 23) self.assertEqual(ziptest_a.test_value, 23)
import ziptest_c ziptest_c = __import__("ziptest_c", globals(), locals(), ["test_value"])
self.assertEqual(ziptest_c.test_value, 1337) self.assertEqual(ziptest_c.test_value, 1337)
......
...@@ -18,11 +18,6 @@ Core and Builtins ...@@ -18,11 +18,6 @@ Core and Builtins
- Issue #17825: Cursor "^" is correctly positioned for SyntaxError and - Issue #17825: Cursor "^" is correctly positioned for SyntaxError and
IndentationError. IndentationError.
- Issue #19081: When a zipimport .zip file in sys.path being imported from
is modified during the lifetime of the Python process after zipimport has
already cached the zip's table of contents we detect this and recover
rather than read bad data from the .zip (causing odd import errors).
- Raise a better error when non-unicode codecs are used for a file's coding - Raise a better error when non-unicode codecs are used for a file's coding
cookie. cookie.
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment