classification
Title: Deprecate undocumented io.OpenWrapper and _pyio.OpenWrapper
Type: Stage: resolved
Components: Library (Lib) Versions: Python 3.10
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: Nosy List: christian.heimes, gvanrossum, methane, serhiy.storchaka, vstinner
Priority: normal Keywords: patch

Created on 2021-03-31 12:59 by vstinner, last changed 2021-04-14 01:26 by vstinner. This issue is now closed.

Pull Requests
URL Status Linked Edit
PR 25114 closed vstinner, 2021-03-31 13:13
PR 25354 merged vstinner, 2021-04-12 08:01
PR 25357 merged vstinner, 2021-04-12 09:33
PR 25395 closed methane, 2021-04-14 01:23
Messages (8)
msg389896 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2021-03-31 12:59
The OpenWrapper function of io and _pyio is an undocumented hack allowing to use the builtin open() function as a method:

class MyClass:
    method = open

MyClass.method(...)    # class method
MyClass().method(...)  # instance method

It is only needed by the _pyio module: the pure Python implementation of the io module:
---
class DocDescriptor:
    """Helper for builtins.open.__doc__
    """
    def __get__(self, obj, typ=None):
        return (
            "open(file, mode='r', buffering=-1, encoding=None, "
                 "errors=None, newline=None, closefd=True)\n\n" +
            open.__doc__)

class OpenWrapper:
    """Wrapper for builtins.open

    Trick so that open won't become a bound method when stored
    as a class variable (as dbm.dumb does).

    See initstdio() in Python/pylifecycle.c.
    """
    __doc__ = DocDescriptor()

    def __new__(cls, *args, **kwargs):
        return open(*args, **kwargs)
---

The io module simply uses an alias to open:
---
OpenWrapper = _io.open # for compatibility with _pyio
---

No wrapper is needed since built-in functions can be used directly as methods. Example:
---
class MyClass:
    method = len  # built-in function

print(MyClass.method("abc"))
print(MyClass().method("abc"))
---

This example works as expected, it displays "3" two times.


I propose to simply remove io.OpenWrapper and force developers to explicitly use staticmethod:

class MyClass:
    method = staticmethod(open)

io.OpenWrapper is not documented.

I don't understand the remark about dbm.dumb: I fail to see where the built-in open() function is used as a method.
msg389897 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2021-03-31 13:19
I also opened a discussion on python-dev about OpenWrapper and staticmethod:
https://mail.python.org/archives/list/python-dev@python.org/thread/QZ7SFW3IW3S2C5RMRJZOOUFSHHUINNME/
msg389899 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2021-03-31 14:09
As for dbm.dumb, it was an attempt to make _Database._commit() working at the shutdown stage (it is indirectly called from __del__()). See issue723231. Although in Python 2 __builtin__.open != io.open, and in Python 3.0 the code already uses io.open directly.

I afraid that this code is not reliable (and never was reliable), because modules os and io can be cleared before calling it, so os.unlink and io.open would not work. But this is a different issue.
msg389902 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2021-03-31 14:23
OpenWrapper was added in ce3a72aec6eaa0293c397c8d0407f7afe0072b2f (issue1267) and was only used to set __builtin__.open (I suppose that at thet moment dumbdbm.py still set open as a class attribute).

It is still can be set as a class attribute in user code, so I think that removing OpenWrapper needs a deprecated period.
msg389912 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2021-03-31 14:57
> OpenWrapper was added in ce3a72aec6eaa0293c397c8d0407f7afe0072b2f (issue1267) and was only used to set __builtin__.open

It is useless in CPython, since CPython always use the C implementation of the io module, and in the io module, io.OpenWrapper is just an alias to io.open.

$ python3
Python 3.9.2 (default, Feb 20 2021, 00:00:00) 
>>> import io
>>> io.OpenWrapper is io.open
True


> (I suppose that at thet moment dumbdbm.py still set open as a class attribute).

I failed to find where in Lib/dbm/dumb.py the open() function is used to define a method. Maybe the code changed since OpenWrapper was added?

At commit ce3a72aec6eaa0293c397c8d0407f7afe0072b2f, the io module was only implemented in Python (Lib/io.py, _io exist didn't exist). It was reimplemented in C in Python 3.1.
msg389913 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2021-03-31 14:59
> It is still can be set as a class attribute in user code, so I think that removing OpenWrapper needs a deprecated period.

I'm fine with deprecating the function by defining a __getattr__() function in io.py and _pyio.py. But only if it doesn't block the implementation of the PEP 597 ;-) The PEP 597 implementation issue is discussed at:
https://bugs.python.org/issue43510#msg389822
msg390828 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2021-04-12 08:45
New changeset 77d668b1221d0f8c3e9d6b6199f67aaf3c45f040 by Victor Stinner in branch 'master':
bpo-43680: _pyio.open() becomes a static method (GH-25354)
https://github.com/python/cpython/commit/77d668b1221d0f8c3e9d6b6199f67aaf3c45f040
msg391025 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2021-04-14 01:24
New changeset 3bc694d5f3d4eb2e5d2f0b83e498b19662845d4e by Victor Stinner in branch 'master':
bpo-43680: Deprecate io.OpenWrapper (GH-25357)
https://github.com/python/cpython/commit/3bc694d5f3d4eb2e5d2f0b83e498b19662845d4e
History
Date User Action Args
2021-04-14 01:26:31vstinnersetstatus: open -> closed
stage: patch review -> resolved
resolution: fixed
title: Remove undocumented io.OpenWrapper and _pyio.OpenWrapper -> Deprecate undocumented io.OpenWrapper and _pyio.OpenWrapper
2021-04-14 01:24:37vstinnersetmessages: + msg391025
2021-04-14 01:23:47methanesetpull_requests: + pull_request24128
2021-04-12 09:33:46vstinnersetpull_requests: + pull_request24091
2021-04-12 08:45:01vstinnersetmessages: + msg390828
2021-04-12 08:01:45vstinnersetpull_requests: + pull_request24089
2021-03-31 14:59:02vstinnersetmessages: + msg389913
2021-03-31 14:57:06vstinnersetmessages: + msg389912
2021-03-31 14:23:48serhiy.storchakasetnosy: + gvanrossum, christian.heimes
messages: + msg389902
2021-03-31 14:09:41serhiy.storchakasetnosy: + serhiy.storchaka
messages: + msg389899
2021-03-31 13:19:54vstinnersetmessages: + msg389897
2021-03-31 13:14:11vstinnersetnosy: + methane
2021-03-31 13:13:51vstinnersetkeywords: + patch
stage: patch review
pull_requests: + pull_request23858
2021-03-31 12:59:21vstinnercreate