Skip to content

Commit f28b0c7

Browse files
bpo-38971: Open file in codecs.open() closes if exception raised. (GH-17666)
Open issue in the BPO indicated a desire to make the implementation of codecs.open() at parity with io.open(), which implements a try/except to assure file stream gets closed before an exception is raised. (cherry picked from commit 2565ede) Co-authored-by: Chris A <[email protected]>
1 parent 87a4cd5 commit f28b0c7

File tree

3 files changed

+22
-5
lines changed

3 files changed

+22
-5
lines changed

Lib/codecs.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -905,11 +905,16 @@ def open(filename, mode='r', encoding=None, errors='strict', buffering=-1):
905905
file = builtins.open(filename, mode, buffering)
906906
if encoding is None:
907907
return file
908-
info = lookup(encoding)
909-
srw = StreamReaderWriter(file, info.streamreader, info.streamwriter, errors)
910-
# Add attributes to simplify introspection
911-
srw.encoding = encoding
912-
return srw
908+
909+
try:
910+
info = lookup(encoding)
911+
srw = StreamReaderWriter(file, info.streamreader, info.streamwriter, errors)
912+
# Add attributes to simplify introspection
913+
srw.encoding = encoding
914+
return srw
915+
except:
916+
file.close()
917+
raise
913918

914919
def EncodedFile(file, data_encoding, file_encoding=None, errors='strict'):
915920

Lib/test/test_codecs.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1142,6 +1142,7 @@ def test_stream_bare(self):
11421142
got = ostream.getvalue()
11431143
self.assertEqual(got, unistring)
11441144

1145+
11451146
class EscapeDecodeTest(unittest.TestCase):
11461147
def test_empty(self):
11471148
self.assertEqual(codecs.escape_decode(b""), (b"", 0))
@@ -1713,6 +1714,14 @@ def test_undefined(self):
17131714
self.assertRaises(UnicodeError,
17141715
codecs.decode, b'abc', 'undefined', errors)
17151716

1717+
def test_file_closes_if_lookup_error_raised(self):
1718+
mock_open = mock.mock_open()
1719+
with mock.patch('builtins.open', mock_open) as file:
1720+
with self.assertRaises(LookupError):
1721+
codecs.open(support.TESTFN, 'wt', 'invalid-encoding')
1722+
1723+
file().close.assert_called()
1724+
17161725

17171726
class StreamReaderTest(unittest.TestCase):
17181727

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Open issue in the BPO indicated a desire to make the implementation of
2+
codecs.open() at parity with io.open(), which implements a try/except to
3+
assure file stream gets closed before an exception is raised.

0 commit comments

Comments
 (0)