Kaydet (Commit) 10c87919 authored tarafından Nadeem Vawda's avatar Nadeem Vawda

Fix GzipFile's handling of filenames given as bytes objects.

Add relevant tests for GzipFile, and also for BZ2File and LZMAFile.
...@@ -182,9 +182,8 @@ class GzipFile(io.BufferedIOBase): ...@@ -182,9 +182,8 @@ class GzipFile(io.BufferedIOBase):
if fileobj is None: if fileobj is None:
fileobj = self.myfileobj = builtins.open(filename, mode or 'rb') fileobj = self.myfileobj = builtins.open(filename, mode or 'rb')
if filename is None: if filename is None:
if hasattr(fileobj, 'name') and isinstance(fileobj.name, str): filename = getattr(fileobj, 'name', '')
filename = fileobj.name if not isinstance(filename, (str, bytes)):
else:
filename = '' filename = ''
if mode is None: if mode is None:
mode = getattr(fileobj, 'mode', 'rb') mode = getattr(fileobj, 'mode', 'rb')
...@@ -258,7 +257,8 @@ class GzipFile(io.BufferedIOBase): ...@@ -258,7 +257,8 @@ class GzipFile(io.BufferedIOBase):
# RFC 1952 requires the FNAME field to be Latin-1. Do not # RFC 1952 requires the FNAME field to be Latin-1. Do not
# include filenames that cannot be represented that way. # include filenames that cannot be represented that way.
fname = os.path.basename(self.name) fname = os.path.basename(self.name)
fname = fname.encode('latin-1') if not isinstance(fname, bytes):
fname = fname.encode('latin-1')
if fname.endswith(b'.gz'): if fname.endswith(b'.gz'):
fname = fname[:-3] fname = fname[:-3]
except UnicodeEncodeError: except UnicodeEncodeError:
......
...@@ -522,6 +522,21 @@ class BZ2FileTest(BaseTest): ...@@ -522,6 +522,21 @@ class BZ2FileTest(BaseTest):
with BZ2File(self.filename) as bz2f: with BZ2File(self.filename) as bz2f:
self.assertEqual(bz2f.read(), data1 + data2) self.assertEqual(bz2f.read(), data1 + data2)
def testOpenBytesFilename(self):
str_filename = self.filename
try:
bytes_filename = str_filename.encode("ascii")
except UnicodeEncodeError:
self.skipTest("Temporary file name needs to be ASCII")
with BZ2File(bytes_filename, "wb") as f:
f.write(self.DATA)
with BZ2File(bytes_filename, "rb") as f:
self.assertEqual(f.read(), self.DATA)
# Sanity check that we are actually operating on the right file.
with BZ2File(str_filename, "rb") as f:
self.assertEqual(f.read(), self.DATA)
# Tests for a BZ2File wrapping another file object: # Tests for a BZ2File wrapping another file object:
def testReadBytesIO(self): def testReadBytesIO(self):
......
...@@ -355,6 +355,20 @@ class TestGzip(BaseTest): ...@@ -355,6 +355,20 @@ class TestGzip(BaseTest):
with gzip.GzipFile(fileobj=f, mode="w") as g: with gzip.GzipFile(fileobj=f, mode="w") as g:
pass pass
def test_bytes_filename(self):
str_filename = self.filename
try:
bytes_filename = str_filename.encode("ascii")
except UnicodeEncodeError:
self.skipTest("Temporary file name needs to be ASCII")
with gzip.GzipFile(bytes_filename, "wb") as f:
f.write(data1 * 50)
with gzip.GzipFile(bytes_filename, "rb") as f:
self.assertEqual(f.read(), data1 * 50)
# Sanity check that we are actually operating on the right file.
with gzip.GzipFile(str_filename, "rb") as f:
self.assertEqual(f.read(), data1 * 50)
# Testing compress/decompress shortcut functions # Testing compress/decompress shortcut functions
def test_compress(self): def test_compress(self):
......
...@@ -655,6 +655,16 @@ class FileTestCase(unittest.TestCase): ...@@ -655,6 +655,16 @@ class FileTestCase(unittest.TestCase):
self.assertEqual(f.read(), INPUT) self.assertEqual(f.read(), INPUT)
self.assertEqual(f.read(), b"") self.assertEqual(f.read(), b"")
def test_read_from_file_with_bytes_filename(self):
try:
bytes_filename = TESTFN.encode("ascii")
except UnicodeEncodeError:
self.skipTest("Temporary file name needs to be ASCII")
with TempFile(TESTFN, COMPRESSED_XZ):
with LZMAFile(bytes_filename) as f:
self.assertEqual(f.read(), INPUT)
self.assertEqual(f.read(), b"")
def test_read_incomplete(self): def test_read_incomplete(self):
with LZMAFile(BytesIO(COMPRESSED_XZ[:128])) as f: with LZMAFile(BytesIO(COMPRESSED_XZ[:128])) as f:
self.assertRaises(EOFError, f.read) self.assertRaises(EOFError, f.read)
...@@ -814,6 +824,20 @@ class FileTestCase(unittest.TestCase): ...@@ -814,6 +824,20 @@ class FileTestCase(unittest.TestCase):
finally: finally:
unlink(TESTFN) unlink(TESTFN)
def test_write_to_file_with_bytes_filename(self):
try:
bytes_filename = TESTFN.encode("ascii")
except UnicodeEncodeError:
self.skipTest("Temporary file name needs to be ASCII")
try:
with LZMAFile(bytes_filename, "w") as f:
f.write(INPUT)
expected = lzma.compress(INPUT)
with open(TESTFN, "rb") as f:
self.assertEqual(f.read(), expected)
finally:
unlink(TESTFN)
def test_write_append_to_file(self): def test_write_append_to_file(self):
part1 = INPUT[:1024] part1 = INPUT[:1024]
part2 = INPUT[1024:1536] part2 = INPUT[1024:1536]
......
...@@ -31,6 +31,8 @@ Core and Builtins ...@@ -31,6 +31,8 @@ Core and Builtins
Library Library
------- -------
- Fix GzipFile's handling of filenames given as bytes objects.
- Issue #14772: Return destination values from some shutil functions. - Issue #14772: Return destination values from some shutil functions.
- Issue #15064: Implement context manager protocol for multiprocessing types - Issue #15064: Implement context manager protocol for multiprocessing types
......
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