Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 4e294f6

Browse filesBrowse files
methanehugovkvstinner
authored
gh-133036: Deprecate codecs.open (#133038)
Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Co-authored-by: Victor Stinner <vstinner@python.org>
1 parent 732d1b0 commit 4e294f6
Copy full SHA for 4e294f6

File tree

Expand file treeCollapse file tree

11 files changed

+58
-37
lines changed
Filter options
Expand file treeCollapse file tree

11 files changed

+58
-37
lines changed

‎Doc/deprecations/pending-removal-in-future.rst

Copy file name to clipboardExpand all lines: Doc/deprecations/pending-removal-in-future.rst
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ although there is currently no date scheduled for their removal.
4747
:data:`calendar.FEBRUARY`.
4848
(Contributed by Prince Roshan in :gh:`103636`.)
4949

50+
* :mod:`codecs`: use :func:`open` instead of :func:`codecs.open`. (:gh:`133038`)
51+
5052
* :attr:`codeobject.co_lnotab`: use the :meth:`codeobject.co_lines` method
5153
instead.
5254

‎Doc/library/codecs.rst

Copy file name to clipboardExpand all lines: Doc/library/codecs.rst
+4Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,10 @@ wider range of codecs when working with binary files:
208208
.. versionchanged:: 3.11
209209
The ``'U'`` mode has been removed.
210210

211+
.. deprecated:: next
212+
213+
:func:`codecs.open` has been superseded by :func:`open`.
214+
211215

212216
.. function:: EncodedFile(file, data_encoding, file_encoding=None, errors='strict')
213217

‎Doc/whatsnew/3.14.rst

Copy file name to clipboardExpand all lines: Doc/whatsnew/3.14.rst
+4Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1597,6 +1597,10 @@ Deprecated
15971597
as a single positional argument.
15981598
(Contributed by Serhiy Storchaka in :gh:`109218`.)
15991599

1600+
* :mod:`codecs`:
1601+
:func:`codecs.open` is now deprecated. Use :func:`open` instead.
1602+
(Contributed by Inada Naoki in :gh:`133036`.)
1603+
16001604
* :mod:`functools`:
16011605
Calling the Python implementation of :func:`functools.reduce` with *function*
16021606
or *sequence* as keyword arguments is now deprecated.

‎Lib/_pyio.py

Copy file name to clipboardExpand all lines: Lib/_pyio.py
+1-2Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2056,8 +2056,7 @@ def __init__(self, buffer, encoding=None, errors=None, newline=None,
20562056
raise ValueError("invalid encoding: %r" % encoding)
20572057

20582058
if not codecs.lookup(encoding)._is_text_encoding:
2059-
msg = ("%r is not a text encoding; "
2060-
"use codecs.open() to handle arbitrary codecs")
2059+
msg = "%r is not a text encoding"
20612060
raise LookupError(msg % encoding)
20622061

20632062
if errors is None:

‎Lib/codecs.py

Copy file name to clipboardExpand all lines: Lib/codecs.py
+4-2Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -884,7 +884,6 @@ def __reduce_ex__(self, proto):
884884
### Shortcuts
885885

886886
def open(filename, mode='r', encoding=None, errors='strict', buffering=-1):
887-
888887
""" Open an encoded file using the given mode and return
889888
a wrapped version providing transparent encoding/decoding.
890889
@@ -912,8 +911,11 @@ def open(filename, mode='r', encoding=None, errors='strict', buffering=-1):
912911
.encoding which allows querying the used encoding. This
913912
attribute is only available if an encoding was specified as
914913
parameter.
915-
916914
"""
915+
import warnings
916+
warnings.warn("codecs.open() is deprecated. Use open() instead.",
917+
DeprecationWarning, stacklevel=2)
918+
917919
if encoding is not None and \
918920
'b' not in mode:
919921
# Force opening of the file in binary mode

‎Lib/test/test_codecs.py

Copy file name to clipboardExpand all lines: Lib/test/test_codecs.py
+21-21Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import unittest
88
import encodings
99
from unittest import mock
10+
import warnings
1011

1112
from test import support
1213
from test.support import os_helper
@@ -20,13 +21,12 @@
2021
except ImportError:
2122
_testinternalcapi = None
2223

23-
try:
24-
import ctypes
25-
except ImportError:
26-
ctypes = None
27-
SIZEOF_WCHAR_T = -1
28-
else:
29-
SIZEOF_WCHAR_T = ctypes.sizeof(ctypes.c_wchar)
24+
25+
def codecs_open_no_warn(*args, **kwargs):
26+
"""Call codecs.open(*args, **kwargs) ignoring DeprecationWarning."""
27+
with warnings.catch_warnings():
28+
warnings.simplefilter("ignore")
29+
return codecs.open(*args, **kwargs)
3030

3131
def coding_checker(self, coder):
3232
def check(input, expect):
@@ -35,13 +35,13 @@ def check(input, expect):
3535

3636
# On small versions of Windows like Windows IoT or Windows Nano Server not all codepages are present
3737
def is_code_page_present(cp):
38-
from ctypes import POINTER, WINFUNCTYPE, WinDLL
38+
from ctypes import POINTER, WINFUNCTYPE, WinDLL, Structure
3939
from ctypes.wintypes import BOOL, BYTE, WCHAR, UINT, DWORD
4040

4141
MAX_LEADBYTES = 12 # 5 ranges, 2 bytes ea., 0 term.
4242
MAX_DEFAULTCHAR = 2 # single or double byte
4343
MAX_PATH = 260
44-
class CPINFOEXW(ctypes.Structure):
44+
class CPINFOEXW(Structure):
4545
_fields_ = [("MaxCharSize", UINT),
4646
("DefaultChar", BYTE*MAX_DEFAULTCHAR),
4747
("LeadByte", BYTE*MAX_LEADBYTES),
@@ -719,19 +719,19 @@ def test_bug691291(self):
719719
self.addCleanup(os_helper.unlink, os_helper.TESTFN)
720720
with open(os_helper.TESTFN, 'wb') as fp:
721721
fp.write(s)
722-
with codecs.open(os_helper.TESTFN, 'r',
722+
with codecs_open_no_warn(os_helper.TESTFN, 'r',
723723
encoding=self.encoding) as reader:
724724
self.assertEqual(reader.read(), s1)
725725

726726
def test_invalid_modes(self):
727727
for mode in ('U', 'rU', 'r+U'):
728728
with self.assertRaises(ValueError) as cm:
729-
codecs.open(os_helper.TESTFN, mode, encoding=self.encoding)
729+
codecs_open_no_warn(os_helper.TESTFN, mode, encoding=self.encoding)
730730
self.assertIn('invalid mode', str(cm.exception))
731731

732732
for mode in ('rt', 'wt', 'at', 'r+t'):
733733
with self.assertRaises(ValueError) as cm:
734-
codecs.open(os_helper.TESTFN, mode, encoding=self.encoding)
734+
codecs_open_no_warn(os_helper.TESTFN, mode, encoding=self.encoding)
735735
self.assertIn("can't have text and binary mode at once",
736736
str(cm.exception))
737737

@@ -1844,9 +1844,9 @@ def test_all(self):
18441844
def test_open(self):
18451845
self.addCleanup(os_helper.unlink, os_helper.TESTFN)
18461846
for mode in ('w', 'r', 'r+', 'w+', 'a', 'a+'):
1847-
with self.subTest(mode), \
1848-
codecs.open(os_helper.TESTFN, mode, 'ascii') as file:
1849-
self.assertIsInstance(file, codecs.StreamReaderWriter)
1847+
with self.subTest(mode), self.assertWarns(DeprecationWarning):
1848+
with codecs.open(os_helper.TESTFN, mode, 'ascii') as file:
1849+
self.assertIsInstance(file, codecs.StreamReaderWriter)
18501850

18511851
def test_undefined(self):
18521852
self.assertRaises(UnicodeError, codecs.encode, 'abc', 'undefined')
@@ -1863,7 +1863,7 @@ def test_file_closes_if_lookup_error_raised(self):
18631863
mock_open = mock.mock_open()
18641864
with mock.patch('builtins.open', mock_open) as file:
18651865
with self.assertRaises(LookupError):
1866-
codecs.open(os_helper.TESTFN, 'wt', 'invalid-encoding')
1866+
codecs_open_no_warn(os_helper.TESTFN, 'wt', 'invalid-encoding')
18671867

18681868
file().close.assert_called()
18691869

@@ -2883,7 +2883,7 @@ def test_seek0(self):
28832883
self.addCleanup(os_helper.unlink, os_helper.TESTFN)
28842884
for encoding in tests:
28852885
# Check if the BOM is written only once
2886-
with codecs.open(os_helper.TESTFN, 'w+', encoding=encoding) as f:
2886+
with codecs_open_no_warn(os_helper.TESTFN, 'w+', encoding=encoding) as f:
28872887
f.write(data)
28882888
f.write(data)
28892889
f.seek(0)
@@ -2892,7 +2892,7 @@ def test_seek0(self):
28922892
self.assertEqual(f.read(), data * 2)
28932893

28942894
# Check that the BOM is written after a seek(0)
2895-
with codecs.open(os_helper.TESTFN, 'w+', encoding=encoding) as f:
2895+
with codecs_open_no_warn(os_helper.TESTFN, 'w+', encoding=encoding) as f:
28962896
f.write(data[0])
28972897
self.assertNotEqual(f.tell(), 0)
28982898
f.seek(0)
@@ -2901,7 +2901,7 @@ def test_seek0(self):
29012901
self.assertEqual(f.read(), data)
29022902

29032903
# (StreamWriter) Check that the BOM is written after a seek(0)
2904-
with codecs.open(os_helper.TESTFN, 'w+', encoding=encoding) as f:
2904+
with codecs_open_no_warn(os_helper.TESTFN, 'w+', encoding=encoding) as f:
29052905
f.writer.write(data[0])
29062906
self.assertNotEqual(f.writer.tell(), 0)
29072907
f.writer.seek(0)
@@ -2911,7 +2911,7 @@ def test_seek0(self):
29112911

29122912
# Check that the BOM is not written after a seek() at a position
29132913
# different than the start
2914-
with codecs.open(os_helper.TESTFN, 'w+', encoding=encoding) as f:
2914+
with codecs_open_no_warn(os_helper.TESTFN, 'w+', encoding=encoding) as f:
29152915
f.write(data)
29162916
f.seek(f.tell())
29172917
f.write(data)
@@ -2920,7 +2920,7 @@ def test_seek0(self):
29202920

29212921
# (StreamWriter) Check that the BOM is not written after a seek()
29222922
# at a position different than the start
2923-
with codecs.open(os_helper.TESTFN, 'w+', encoding=encoding) as f:
2923+
with codecs_open_no_warn(os_helper.TESTFN, 'w+', encoding=encoding) as f:
29242924
f.writer.write(data)
29252925
f.writer.seek(f.writer.tell())
29262926
f.writer.write(data)

‎Lib/test/test_multibytecodec.py

Copy file name to clipboardExpand all lines: Lib/test/test_multibytecodec.py
+2-1Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,8 @@ def test_bug1728403(self):
314314
f.write(b'\xa1')
315315
finally:
316316
f.close()
317-
f = codecs.open(TESTFN, encoding='cp949')
317+
with self.assertWarns(DeprecationWarning):
318+
f = codecs.open(TESTFN, encoding='cp949')
318319
try:
319320
self.assertRaises(UnicodeDecodeError, f.read, 2)
320321
finally:

‎Lib/test/test_sax.py

Copy file name to clipboardExpand all lines: Lib/test/test_sax.py
+3-3Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
# regression test for SAX 2.0
2-
# $Id$
32

43
from xml.sax import make_parser, ContentHandler, \
54
SAXException, SAXReaderNotAvailable, SAXParseException
@@ -832,8 +831,9 @@ class StreamReaderWriterXmlgenTest(XmlgenTest, unittest.TestCase):
832831
fname = os_helper.TESTFN + '-codecs'
833832

834833
def ioclass(self):
835-
writer = codecs.open(self.fname, 'w', encoding='ascii',
836-
errors='xmlcharrefreplace', buffering=0)
834+
with self.assertWarns(DeprecationWarning):
835+
writer = codecs.open(self.fname, 'w', encoding='ascii',
836+
errors='xmlcharrefreplace', buffering=0)
837837
def cleanup():
838838
writer.close()
839839
os_helper.unlink(self.fname)
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
:func:`codecs.open` is now deprecated. Use :func:`open` instead. Contributed
2+
by Inada Naoki.

‎Modules/_io/textio.c

Copy file name to clipboardExpand all lines: Modules/_io/textio.c
+2-3Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1185,7 +1185,7 @@ _io_TextIOWrapper___init___impl(textio *self, PyObject *buffer,
11851185
}
11861186

11871187
/* Check we have been asked for a real text encoding */
1188-
codec_info = _PyCodec_LookupTextEncoding(encoding, "codecs.open()");
1188+
codec_info = _PyCodec_LookupTextEncoding(encoding, NULL);
11891189
if (codec_info == NULL) {
11901190
Py_CLEAR(self->encoding);
11911191
goto error;
@@ -1324,8 +1324,7 @@ textiowrapper_change_encoding(textio *self, PyObject *encoding,
13241324
}
13251325

13261326
// Create new encoder & decoder
1327-
PyObject *codec_info = _PyCodec_LookupTextEncoding(
1328-
c_encoding, "codecs.open()");
1327+
PyObject *codec_info = _PyCodec_LookupTextEncoding(c_encoding, NULL);
13291328
if (codec_info == NULL) {
13301329
Py_DECREF(encoding);
13311330
Py_DECREF(errors);

‎Python/codecs.c

Copy file name to clipboardExpand all lines: Python/codecs.c
+13-5Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -540,11 +540,19 @@ PyObject * _PyCodec_LookupTextEncoding(const char *encoding,
540540
Py_DECREF(attr);
541541
if (is_text_codec <= 0) {
542542
Py_DECREF(codec);
543-
if (!is_text_codec)
544-
PyErr_Format(PyExc_LookupError,
545-
"'%.400s' is not a text encoding; "
546-
"use %s to handle arbitrary codecs",
547-
encoding, alternate_command);
543+
if (!is_text_codec) {
544+
if (alternate_command != NULL) {
545+
PyErr_Format(PyExc_LookupError,
546+
"'%.400s' is not a text encoding; "
547+
"use %s to handle arbitrary codecs",
548+
encoding, alternate_command);
549+
}
550+
else {
551+
PyErr_Format(PyExc_LookupError,
552+
"'%.400s' is not a text encoding",
553+
encoding);
554+
}
555+
}
548556
return NULL;
549557
}
550558
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.