Skip to content

Commit 3bc694d

Browse files
authored
bpo-43680: Deprecate io.OpenWrapper (GH-25357)
Deprecate io.OpenWrapper and _pyio.OpenWrapper: use io.open and _pyio.open instead. Until Python 3.9, _pyio.open was not a static method and builtins.open was set to OpenWrapper to not become a bound method when set to a class variable. _io.open is a built-in function whereas _pyio.open is a Python function. In Python 3.10, _pyio.open() is now a static method, and builtins.open() is now io.open().
1 parent 11159d2 commit 3bc694d

File tree

4 files changed

+44
-15
lines changed

4 files changed

+44
-15
lines changed

Lib/_pyio.py

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -311,18 +311,20 @@ def _open_code_with_warning(path):
311311
open_code = _open_code_with_warning
312312

313313

314-
class DocDescriptor:
315-
"""Helper for builtins.open.__doc__
316-
"""
317-
def __get__(self, obj, typ=None):
318-
return (
319-
"open(file, mode='r', buffering=-1, encoding=None, "
320-
"errors=None, newline=None, closefd=True)\n\n" +
321-
open.__doc__)
322-
323-
324-
# bpo-43680: Alias to open() kept for backward compatibility
325-
OpenWrapper = open
314+
def __getattr__(name):
315+
if name == "OpenWrapper":
316+
# bpo-43680: Until Python 3.9, _pyio.open was not a static method and
317+
# builtins.open was set to OpenWrapper to not become a bound method
318+
# when set to a class variable. _io.open is a built-in function whereas
319+
# _pyio.open is a Python function. In Python 3.10, _pyio.open() is now
320+
# a static method, and builtins.open() is now io.open().
321+
import warnings
322+
warnings.warn('OpenWrapper is deprecated, use open instead',
323+
DeprecationWarning, stacklevel=2)
324+
global OpenWrapper
325+
OpenWrapper = open
326+
return OpenWrapper
327+
raise AttributeError(name)
326328

327329

328330
# In normal operation, both `UnsupportedOperation`s should be bound to the

Lib/io.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,22 @@
5656
BufferedWriter, BufferedRWPair, BufferedRandom,
5757
IncrementalNewlineDecoder, text_encoding, TextIOWrapper)
5858

59-
OpenWrapper = _io.open # for compatibility with _pyio
59+
60+
def __getattr__(name):
61+
if name == "OpenWrapper":
62+
# bpo-43680: Until Python 3.9, _pyio.open was not a static method and
63+
# builtins.open was set to OpenWrapper to not become a bound method
64+
# when set to a class variable. _io.open is a built-in function whereas
65+
# _pyio.open is a Python function. In Python 3.10, _pyio.open() is now
66+
# a static method, and builtins.open() is now io.open().
67+
import warnings
68+
warnings.warn('OpenWrapper is deprecated, use open instead',
69+
DeprecationWarning, stacklevel=2)
70+
global OpenWrapper
71+
OpenWrapper = open
72+
return OpenWrapper
73+
raise AttributeError(name)
74+
6075

6176
# Pretend this exception was created here.
6277
UnsupportedOperation.__module__ = "io"

Lib/test/test_io.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4283,6 +4283,14 @@ def test_check_encoding_warning(self):
42834283
self.assertTrue(
42844284
warnings[1].startswith(b"<string>:8: EncodingWarning: "))
42854285

4286+
@support.cpython_only
4287+
# Depending if OpenWrapper was already created or not, the warning is
4288+
# emitted or not. For example, the attribute is already created when this
4289+
# test is run multiple times.
4290+
@warnings_helper.ignore_warnings(category=DeprecationWarning)
4291+
def test_openwrapper(self):
4292+
self.assertIs(self.io.OpenWrapper, self.io.open)
4293+
42864294

42874295
class CMiscIOTest(MiscIOTest):
42884296
io = io
@@ -4598,8 +4606,6 @@ def load_tests(*args):
45984606
globs = globals()
45994607
c_io_ns.update((x.__name__, globs["C" + x.__name__]) for x in mocks)
46004608
py_io_ns.update((x.__name__, globs["Py" + x.__name__]) for x in mocks)
4601-
# Avoid turning open into a bound method.
4602-
py_io_ns["open"] = pyio.OpenWrapper
46034609
for test in tests:
46044610
if test.__name__.startswith("C"):
46054611
for name, obj in c_io_ns.items():
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
Deprecate io.OpenWrapper and _pyio.OpenWrapper: use io.open and _pyio.open
2+
instead. Until Python 3.9, _pyio.open was not a static method and
3+
builtins.open was set to OpenWrapper to not become a bound method when set
4+
to a class variable. _io.open is a built-in function whereas _pyio.open is a
5+
Python function. In Python 3.10, _pyio.open() is now a static method, and
6+
builtins.open() is now io.open().

0 commit comments

Comments
 (0)