Skip to content

Commit

Permalink
bpo-36933: Remove sys.set_coroutine_wrapper (marked for removal in 3.…
Browse files Browse the repository at this point in the history
…8) (GH-13577)

It has been documented as deprecated and to be removed in 3.8; 

From a comment on another thread – which I can't find ; leave get_coro_wrapper() for now, but always return `None`.


https://bugs.python.org/issue36933
  • Loading branch information
Carreau authored and miss-islington committed May 28, 2019
1 parent 436c2b0 commit 3880f26
Show file tree
Hide file tree
Showing 11 changed files with 7 additions and 287 deletions.
59 changes: 0 additions & 59 deletions Doc/library/sys.rst
Original file line number Diff line number Diff line change
Expand Up @@ -781,22 +781,6 @@ always available.
for details.) Use it only for debugging purposes.


.. function:: get_coroutine_wrapper()

Returns ``None``, or a wrapper set by :func:`set_coroutine_wrapper`.

.. versionadded:: 3.5
See :pep:`492` for more details.

.. note::
This function has been added on a provisional basis (see :pep:`411`
for details.) Use it only for debugging purposes.

.. deprecated:: 3.7
The coroutine wrapper functionality has been deprecated, and
will be removed in 3.8. See :issue:`32591` for details.


.. data:: hash_info

A :term:`struct sequence` giving parameters of the numeric hash
Expand Down Expand Up @@ -1384,49 +1368,6 @@ always available.
This function has been added on a provisional basis (see :pep:`411`
for details.) Use it only for debugging purposes.

.. function:: set_coroutine_wrapper(wrapper)

Allows intercepting creation of :term:`coroutine` objects (only ones that
are created by an :keyword:`async def` function; generators decorated with
:func:`types.coroutine` or :func:`asyncio.coroutine` will not be
intercepted).

The *wrapper* argument must be either:

* a callable that accepts one argument (a coroutine object);
* ``None``, to reset the wrapper.

If called twice, the new wrapper replaces the previous one. The function
is thread-specific.

The *wrapper* callable cannot define new coroutines directly or indirectly::

def wrapper(coro):
async def wrap(coro):
return await coro
return wrap(coro)
sys.set_coroutine_wrapper(wrapper)

async def foo():
pass

# The following line will fail with a RuntimeError, because
# ``wrapper`` creates a ``wrap(coro)`` coroutine:
foo()

See also :func:`get_coroutine_wrapper`.

.. versionadded:: 3.5
See :pep:`492` for more details.

.. note::
This function has been added on a provisional basis (see :pep:`411`
for details.) Use it only for debugging purposes.

.. deprecated-removed:: 3.7 3.8
The coroutine wrapper functionality has been deprecated, and
will be removed in 3.8. See :issue:`32591` for details.

.. function:: _enablelegacywindowsfsencoding()

Changes the default filesystem encoding and errors mode to 'mbcs' and
Expand Down
1 change: 0 additions & 1 deletion Doc/tools/susp-ignored.csv
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,6 @@ library/zipapp,,:main,"$ python -m zipapp myapp -m ""myapp:main"""
library/zipapp,,:fn,"pkg.mod:fn"
library/zipapp,,:callable,"pkg.module:callable"
library/stdtypes,,::,>>> m[::2].tolist()
library/sys,,`,# ``wrapper`` creates a ``wrap(coro)`` coroutine:
whatsnew/3.5,,:root,'WARNING:root:warning\n'
whatsnew/3.5,,:warning,'WARNING:root:warning\n'
whatsnew/3.5,,::,>>> addr6 = ipaddress.IPv6Address('::1')
Expand Down
4 changes: 4 additions & 0 deletions Doc/whatsnew/3.8.rst
Original file line number Diff line number Diff line change
Expand Up @@ -973,6 +973,10 @@ The following features and APIs have been removed from Python 3.8:
:func:`fileinput.FileInput` which was ignored and deprecated since Python 3.6
has been removed. :issue:`36952` (Contributed by Matthias Bussonnier)

* The function :func:`sys.set_coroutine_wrapper` deprecated in Python 3.7 has
been removed; :func:`sys.get_coroutine_wrapper` now always return ``None``.
:issue:`36933` (Contributed by Matthias Bussonnier)


Porting to Python 3.8
=====================
Expand Down
2 changes: 0 additions & 2 deletions Include/ceval.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@ PyAPI_FUNC(void) PyEval_SetProfile(Py_tracefunc, PyObject *);
PyAPI_FUNC(void) PyEval_SetTrace(Py_tracefunc, PyObject *);
PyAPI_FUNC(void) _PyEval_SetCoroutineOriginTrackingDepth(int new_depth);
PyAPI_FUNC(int) _PyEval_GetCoroutineOriginTrackingDepth(void);
PyAPI_FUNC(void) _PyEval_SetCoroutineWrapper(PyObject *);
PyAPI_FUNC(PyObject *) _PyEval_GetCoroutineWrapper(void);
PyAPI_FUNC(void) _PyEval_SetAsyncGenFirstiter(PyObject *);
PyAPI_FUNC(PyObject *) _PyEval_GetAsyncGenFirstiter(void);
PyAPI_FUNC(void) _PyEval_SetAsyncGenFinalizer(PyObject *);
Expand Down
3 changes: 0 additions & 3 deletions Include/cpython/pystate.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,9 +126,6 @@ struct _ts {

int coroutine_origin_tracking_depth;

PyObject *coroutine_wrapper;
int in_coroutine_wrapper;

PyObject *async_gen_firstiter;
PyObject *async_gen_finalizer;

Expand Down
93 changes: 0 additions & 93 deletions Lib/test/test_coroutines.py
Original file line number Diff line number Diff line change
Expand Up @@ -2146,99 +2146,6 @@ async def f():
self.assertEqual(buffer, [1, 2, 'MyException'])


class SysSetCoroWrapperTest(unittest.TestCase):

def test_set_wrapper_1(self):
async def foo():
return 'spam'

wrapped = None
def wrap(gen):
nonlocal wrapped
wrapped = gen
return gen

with self.assertWarns(DeprecationWarning):
self.assertIsNone(sys.get_coroutine_wrapper())

with self.assertWarns(DeprecationWarning):
sys.set_coroutine_wrapper(wrap)
with self.assertWarns(DeprecationWarning):
self.assertIs(sys.get_coroutine_wrapper(), wrap)
try:
f = foo()
self.assertTrue(wrapped)

self.assertEqual(run_async(f), ([], 'spam'))
finally:
with self.assertWarns(DeprecationWarning):
sys.set_coroutine_wrapper(None)
f.close()

with self.assertWarns(DeprecationWarning):
self.assertIsNone(sys.get_coroutine_wrapper())

wrapped = None
coro = foo()
self.assertFalse(wrapped)
coro.close()

def test_set_wrapper_2(self):
with self.assertWarns(DeprecationWarning):
self.assertIsNone(sys.get_coroutine_wrapper())
with self.assertRaisesRegex(TypeError, "callable expected, got int"):
with self.assertWarns(DeprecationWarning):
sys.set_coroutine_wrapper(1)
with self.assertWarns(DeprecationWarning):
self.assertIsNone(sys.get_coroutine_wrapper())

def test_set_wrapper_3(self):
async def foo():
return 'spam'

def wrapper(coro):
async def wrap(coro):
return await coro
return wrap(coro)

with self.assertWarns(DeprecationWarning):
sys.set_coroutine_wrapper(wrapper)
try:
with silence_coro_gc(), self.assertRaisesRegex(
RuntimeError,
r"coroutine wrapper.*\.wrapper at 0x.*attempted to "
r"recursively wrap .* wrap .*"):

foo()

finally:
with self.assertWarns(DeprecationWarning):
sys.set_coroutine_wrapper(None)

def test_set_wrapper_4(self):
@types.coroutine
def foo():
return 'spam'

wrapped = None
def wrap(gen):
nonlocal wrapped
wrapped = gen
return gen

with self.assertWarns(DeprecationWarning):
sys.set_coroutine_wrapper(wrap)
try:
foo()
self.assertIs(
wrapped, None,
"generator-based coroutine was wrapped via "
"sys.set_coroutine_wrapper")
finally:
with self.assertWarns(DeprecationWarning):
sys.set_coroutine_wrapper(None)


class OriginTrackingTest(unittest.TestCase):
def here(self):
info = inspect.getframeinfo(inspect.currentframe().f_back)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
The functions ``sys.set_coroutine_wrapper`` and ``sys.get_coroutine_wrapper``
that were deprecated and marked for removal in 3.8 have been removed.
39 changes: 0 additions & 39 deletions Python/ceval.c
Original file line number Diff line number Diff line change
Expand Up @@ -4143,19 +4143,8 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
/* Handle generator/coroutine/asynchronous generator */
if (co->co_flags & (CO_GENERATOR | CO_COROUTINE | CO_ASYNC_GENERATOR)) {
PyObject *gen;
PyObject *coro_wrapper = tstate->coroutine_wrapper;
int is_coro = co->co_flags & CO_COROUTINE;

if (is_coro && tstate->in_coroutine_wrapper) {
assert(coro_wrapper != NULL);
_PyErr_Format(tstate, PyExc_RuntimeError,
"coroutine wrapper %.200R attempted "
"to recursively wrap %.200R",
coro_wrapper,
co);
goto fail;
}

/* Don't need to keep the reference to f_back, it will be set
* when the generator is resumed. */
Py_CLEAR(f->f_back);
Expand All @@ -4175,14 +4164,6 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,

_PyObject_GC_TRACK(f);

if (is_coro && coro_wrapper != NULL) {
PyObject *wrapped;
tstate->in_coroutine_wrapper = 1;
wrapped = PyObject_CallFunction(coro_wrapper, "N", gen);
tstate->in_coroutine_wrapper = 0;
return wrapped;
}

return gen;
}

Expand Down Expand Up @@ -4633,26 +4614,6 @@ _PyEval_GetCoroutineOriginTrackingDepth(void)
return tstate->coroutine_origin_tracking_depth;
}

void
_PyEval_SetCoroutineWrapper(PyObject *wrapper)
{
PyThreadState *tstate = _PyThreadState_GET();

if (PySys_Audit("sys.set_coroutine_wrapper", NULL) < 0) {
return;
}

Py_XINCREF(wrapper);
Py_XSETREF(tstate->coroutine_wrapper, wrapper);
}

PyObject *
_PyEval_GetCoroutineWrapper(void)
{
PyThreadState *tstate = _PyThreadState_GET();
return tstate->coroutine_wrapper;
}

void
_PyEval_SetAsyncGenFirstiter(PyObject *firstiter)
{
Expand Down
29 changes: 1 addition & 28 deletions Python/clinic/sysmodule.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 0 additions & 4 deletions Python/pystate.c
Original file line number Diff line number Diff line change
Expand Up @@ -606,9 +606,6 @@ new_threadstate(PyInterpreterState *interp, int init)

tstate->coroutine_origin_tracking_depth = 0;

tstate->coroutine_wrapper = NULL;
tstate->in_coroutine_wrapper = 0;

tstate->async_gen_firstiter = NULL;
tstate->async_gen_finalizer = NULL;

Expand Down Expand Up @@ -802,7 +799,6 @@ PyThreadState_Clear(PyThreadState *tstate)
Py_CLEAR(tstate->c_profileobj);
Py_CLEAR(tstate->c_traceobj);

Py_CLEAR(tstate->coroutine_wrapper);
Py_CLEAR(tstate->async_gen_firstiter);
Py_CLEAR(tstate->async_gen_finalizer);

Expand Down
Loading

0 comments on commit 3880f26

Please sign in to comment.