Author: Armin Rigo <ar...@tunes.org> Branch: Changeset: r60795:620c44fd4b9f Date: 2013-01-31 22:28 +0100 http://bitbucket.org/pypy/pypy/changeset/620c44fd4b9f/
Log: merge heads diff --git a/lib-python/2.7/test/test_zipfile.py b/lib-python/2.7/test/test_zipfile.py --- a/lib-python/2.7/test/test_zipfile.py +++ b/lib-python/2.7/test/test_zipfile.py @@ -1213,6 +1213,17 @@ self.assertEqual(data1, '1'*FIXEDTEST_SIZE) self.assertEqual(data2, '2'*FIXEDTEST_SIZE) + def test_many_opens(self): + # Verify that read() and open() promptly close the file descriptor, + # and don't rely on the garbage collector to free resources. + with zipfile.ZipFile(TESTFN2, mode="r") as zipf: + for x in range(100): + zipf.read('ones') + with zipf.open('ones') as zopen1: + pass + for x in range(10): + self.assertLess(open('/dev/null').fileno(), 100) + def tearDown(self): unlink(TESTFN2) diff --git a/lib-python/2.7/zipfile.py b/lib-python/2.7/zipfile.py --- a/lib-python/2.7/zipfile.py +++ b/lib-python/2.7/zipfile.py @@ -475,9 +475,11 @@ # Search for universal newlines or line chunks. PATTERN = re.compile(r'^(?P<chunk>[^\r\n]+)|(?P<newline>\n|\r\n?)') - def __init__(self, fileobj, mode, zipinfo, decrypter=None): + def __init__(self, fileobj, mode, zipinfo, decrypter=None, + close_fileobj=False): self._fileobj = fileobj self._decrypter = decrypter + self._close_fileobj = close_fileobj self._compress_type = zipinfo.compress_type self._compress_size = zipinfo.compress_size @@ -649,6 +651,12 @@ self._offset += len(data) return data + def close(self): + try: + if self._close_fileobj: + self._fileobj.close() + finally: + super(ZipExtFile, self).close() class ZipFile: @@ -866,7 +874,8 @@ def read(self, name, pwd=None): """Return file bytes (as a string) for name.""" - return self.open(name, "r", pwd).read() + with self.open(name, "r", pwd) as fp: + return fp.read() def open(self, name, mode="r", pwd=None): """Return file-like object for 'name'.""" @@ -889,8 +898,12 @@ zinfo = name else: # Get info object for name - zinfo = self.getinfo(name) - + try: + zinfo = self.getinfo(name) + except KeyError: + if not self._filePassed: + zef_file.close() + raise zef_file.seek(zinfo.header_offset, 0) # Skip the file header: @@ -904,6 +917,8 @@ zef_file.read(fheader[_FH_EXTRA_FIELD_LENGTH]) if fname != zinfo.orig_filename: + if not self._filePassed: + zef_file.close() raise BadZipfile, \ 'File name in directory "%s" and header "%s" differ.' % ( zinfo.orig_filename, fname) @@ -915,6 +930,8 @@ if not pwd: pwd = self.pwd if not pwd: + if not self._filePassed: + zef_file.close() raise RuntimeError, "File %s is encrypted, " \ "password required for extraction" % name @@ -933,9 +950,12 @@ # compare against the CRC otherwise check_byte = (zinfo.CRC >> 24) & 0xff if ord(h[11]) != check_byte: + if not self._filePassed: + zef_file.close() raise RuntimeError("Bad password for file", name) - return ZipExtFile(zef_file, mode, zinfo, zd) + return ZipExtFile(zef_file, mode, zinfo, zd, + close_fileobj=not self._filePassed) def extract(self, member, path=None, pwd=None): """Extract a member from the archive to the current working directory, @@ -993,7 +1013,7 @@ return targetpath source = self.open(member, pwd=pwd) - target = file(targetpath, "wb") + target = open(targetpath, "wb") shutil.copyfileobj(source, target) source.close() target.close() _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit