-
-
Notifications
You must be signed in to change notification settings - Fork 31.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Deprecate undocumented io.OpenWrapper and _pyio.OpenWrapper #87846
Comments
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
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. |
I also opened a discussion on python-dev about OpenWrapper and staticmethod: |
As for dbm.dumb, it was an attempt to make _Database._commit() working at the shutdown stage (it is indirectly called from __del__()). See bpo-723231. 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. |
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 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 ce3a72a, 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. |
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: |
The deprecated `OpenWrapper` is added to the module on demand in `__getattr__`, so it might or might not show up in `dir(io)` depending on whether e.g. `test_openwrapper` was run. Add in to `not_exported` so that check__all__ ignores it when it exists. This deterministically fails on some refleaks buildbots (but not when the test is re-run, so it's only marked as a warning). Locally, it can be reproduced by running `test_openwrapper` and `test__all__`, twice: ./python -m test test_io test_io -m '*test_[o_][p_][ea][nl][wl]*' -v
The deprecated `OpenWrapper` is added to the module on demand in `__getattr__`, so it might or might not show up in `dir(io)` depending on whether e.g. `test_openwrapper` was run. Add in to `not_exported` so that check__all__ ignores it when it exists. This consistently fails on some refleaks buildbots (but not when the test is re-run, so it's only marked as a warning). Locally, it can be reproduced by running `test_openwrapper` and `test__all__`, twice: ./python -m test test_io test_io -m '*test_[o_][p_][ea][nl][wl]*' -v
The deprecated `OpenWrapper` is added to the module on demand in `__getattr__`, so it might or might not show up in `dir(io)` depending on whether e.g. `test_openwrapper` was run. Add in to `not_exported` so that check__all__ ignores it when it exists. This consistently fails on some refleaks buildbots (but not when the test is re-run, so it's only marked as a warning). Locally, it can be reproduced by running `test_openwrapper` and `test__all__`, twice: ./python -m test test_io test_io -m '*test_[o_][p_][ea][nl][wl]*' -v
The deprecated `OpenWrapper` is added to the module on demand in `__getattr__`, so it might or might not show up in `dir(io)` depending on whether e.g. `test_openwrapper` was run. Add it to `not_exported` so that check__all__ ignores it when it exists. The test consistently failed on some refleaks buildbots (but not when the test is re-run, so it was only marked as a warning). Locally, it can be reproduced by running `test_openwrapper` and `test__all__`, twice: ./python -m test test_io test_io -m '*test_[o_][p_][ea][nl][wl]*' -v
This can make |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
Linked PRs
The text was updated successfully, but these errors were encountered: