Skip to content

Commit f4d709f

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 d3c2435 commit f4d709f

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
@@ -904,11 +904,16 @@ def open(filename, mode='r', encoding=None, errors='strict', buffering=1):
904904
file = builtins.open(filename, mode, buffering)
905905
if encoding is None:
906906
return file
907-
info = lookup(encoding)
908-
srw = StreamReaderWriter(file, info.streamreader, info.streamwriter, errors)
909-
# Add attributes to simplify introspection
910-
srw.encoding = encoding
911-
return srw
907+
908+
try:
909+
info = lookup(encoding)
910+
srw = StreamReaderWriter(file, info.streamreader, info.streamwriter, errors)
911+
# Add attributes to simplify introspection
912+
srw.encoding = encoding
913+
return srw
914+
except:
915+
file.close()
916+
raise
912917

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

Lib/test/test_codecs.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1206,6 +1206,7 @@ def test_stream_bare(self):
12061206
got = ostream.getvalue()
12071207
self.assertEqual(got, unistring)
12081208

1209+
12091210
class EscapeDecodeTest(unittest.TestCase):
12101211
def test_empty(self):
12111212
self.assertEqual(codecs.escape_decode(b""), (b"", 0))
@@ -1869,6 +1870,14 @@ def test_undefined(self):
18691870
self.assertRaises(UnicodeError,
18701871
codecs.decode, b'abc', 'undefined', errors)
18711872

1873+
def test_file_closes_if_lookup_error_raised(self):
1874+
mock_open = mock.mock_open()
1875+
with mock.patch('builtins.open', mock_open) as file:
1876+
with self.assertRaises(LookupError):
1877+
codecs.open(support.TESTFN, 'wt', 'invalid-encoding')
1878+
1879+
file().close.assert_called()
1880+
18721881

18731882
class StreamReaderTest(unittest.TestCase):
18741883

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)