Skip to content

Commit 3880f26

Browse files
Carreaumiss-islington
authored andcommitted
bpo-36933: Remove sys.set_coroutine_wrapper (marked for removal in 3.8) (pythonGH-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
1 parent 436c2b0 commit 3880f26

File tree

11 files changed

+7
-287
lines changed

11 files changed

+7
-287
lines changed

Doc/library/sys.rst

-59
Original file line numberDiff line numberDiff line change
@@ -781,22 +781,6 @@ always available.
781781
for details.) Use it only for debugging purposes.
782782

783783

784-
.. function:: get_coroutine_wrapper()
785-
786-
Returns ``None``, or a wrapper set by :func:`set_coroutine_wrapper`.
787-
788-
.. versionadded:: 3.5
789-
See :pep:`492` for more details.
790-
791-
.. note::
792-
This function has been added on a provisional basis (see :pep:`411`
793-
for details.) Use it only for debugging purposes.
794-
795-
.. deprecated:: 3.7
796-
The coroutine wrapper functionality has been deprecated, and
797-
will be removed in 3.8. See :issue:`32591` for details.
798-
799-
800784
.. data:: hash_info
801785

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

1387-
.. function:: set_coroutine_wrapper(wrapper)
1388-
1389-
Allows intercepting creation of :term:`coroutine` objects (only ones that
1390-
are created by an :keyword:`async def` function; generators decorated with
1391-
:func:`types.coroutine` or :func:`asyncio.coroutine` will not be
1392-
intercepted).
1393-
1394-
The *wrapper* argument must be either:
1395-
1396-
* a callable that accepts one argument (a coroutine object);
1397-
* ``None``, to reset the wrapper.
1398-
1399-
If called twice, the new wrapper replaces the previous one. The function
1400-
is thread-specific.
1401-
1402-
The *wrapper* callable cannot define new coroutines directly or indirectly::
1403-
1404-
def wrapper(coro):
1405-
async def wrap(coro):
1406-
return await coro
1407-
return wrap(coro)
1408-
sys.set_coroutine_wrapper(wrapper)
1409-
1410-
async def foo():
1411-
pass
1412-
1413-
# The following line will fail with a RuntimeError, because
1414-
# ``wrapper`` creates a ``wrap(coro)`` coroutine:
1415-
foo()
1416-
1417-
See also :func:`get_coroutine_wrapper`.
1418-
1419-
.. versionadded:: 3.5
1420-
See :pep:`492` for more details.
1421-
1422-
.. note::
1423-
This function has been added on a provisional basis (see :pep:`411`
1424-
for details.) Use it only for debugging purposes.
1425-
1426-
.. deprecated-removed:: 3.7 3.8
1427-
The coroutine wrapper functionality has been deprecated, and
1428-
will be removed in 3.8. See :issue:`32591` for details.
1429-
14301371
.. function:: _enablelegacywindowsfsencoding()
14311372

14321373
Changes the default filesystem encoding and errors mode to 'mbcs' and

Doc/tools/susp-ignored.csv

-1
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,6 @@ library/zipapp,,:main,"$ python -m zipapp myapp -m ""myapp:main"""
337337
library/zipapp,,:fn,"pkg.mod:fn"
338338
library/zipapp,,:callable,"pkg.module:callable"
339339
library/stdtypes,,::,>>> m[::2].tolist()
340-
library/sys,,`,# ``wrapper`` creates a ``wrap(coro)`` coroutine:
341340
whatsnew/3.5,,:root,'WARNING:root:warning\n'
342341
whatsnew/3.5,,:warning,'WARNING:root:warning\n'
343342
whatsnew/3.5,,::,>>> addr6 = ipaddress.IPv6Address('::1')

Doc/whatsnew/3.8.rst

+4
Original file line numberDiff line numberDiff line change
@@ -973,6 +973,10 @@ The following features and APIs have been removed from Python 3.8:
973973
:func:`fileinput.FileInput` which was ignored and deprecated since Python 3.6
974974
has been removed. :issue:`36952` (Contributed by Matthias Bussonnier)
975975

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

977981
Porting to Python 3.8
978982
=====================

Include/ceval.h

-2
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,6 @@ PyAPI_FUNC(void) PyEval_SetProfile(Py_tracefunc, PyObject *);
3333
PyAPI_FUNC(void) PyEval_SetTrace(Py_tracefunc, PyObject *);
3434
PyAPI_FUNC(void) _PyEval_SetCoroutineOriginTrackingDepth(int new_depth);
3535
PyAPI_FUNC(int) _PyEval_GetCoroutineOriginTrackingDepth(void);
36-
PyAPI_FUNC(void) _PyEval_SetCoroutineWrapper(PyObject *);
37-
PyAPI_FUNC(PyObject *) _PyEval_GetCoroutineWrapper(void);
3836
PyAPI_FUNC(void) _PyEval_SetAsyncGenFirstiter(PyObject *);
3937
PyAPI_FUNC(PyObject *) _PyEval_GetAsyncGenFirstiter(void);
4038
PyAPI_FUNC(void) _PyEval_SetAsyncGenFinalizer(PyObject *);

Include/cpython/pystate.h

-3
Original file line numberDiff line numberDiff line change
@@ -126,9 +126,6 @@ struct _ts {
126126

127127
int coroutine_origin_tracking_depth;
128128

129-
PyObject *coroutine_wrapper;
130-
int in_coroutine_wrapper;
131-
132129
PyObject *async_gen_firstiter;
133130
PyObject *async_gen_finalizer;
134131

Lib/test/test_coroutines.py

-93
Original file line numberDiff line numberDiff line change
@@ -2146,99 +2146,6 @@ async def f():
21462146
self.assertEqual(buffer, [1, 2, 'MyException'])
21472147

21482148

2149-
class SysSetCoroWrapperTest(unittest.TestCase):
2150-
2151-
def test_set_wrapper_1(self):
2152-
async def foo():
2153-
return 'spam'
2154-
2155-
wrapped = None
2156-
def wrap(gen):
2157-
nonlocal wrapped
2158-
wrapped = gen
2159-
return gen
2160-
2161-
with self.assertWarns(DeprecationWarning):
2162-
self.assertIsNone(sys.get_coroutine_wrapper())
2163-
2164-
with self.assertWarns(DeprecationWarning):
2165-
sys.set_coroutine_wrapper(wrap)
2166-
with self.assertWarns(DeprecationWarning):
2167-
self.assertIs(sys.get_coroutine_wrapper(), wrap)
2168-
try:
2169-
f = foo()
2170-
self.assertTrue(wrapped)
2171-
2172-
self.assertEqual(run_async(f), ([], 'spam'))
2173-
finally:
2174-
with self.assertWarns(DeprecationWarning):
2175-
sys.set_coroutine_wrapper(None)
2176-
f.close()
2177-
2178-
with self.assertWarns(DeprecationWarning):
2179-
self.assertIsNone(sys.get_coroutine_wrapper())
2180-
2181-
wrapped = None
2182-
coro = foo()
2183-
self.assertFalse(wrapped)
2184-
coro.close()
2185-
2186-
def test_set_wrapper_2(self):
2187-
with self.assertWarns(DeprecationWarning):
2188-
self.assertIsNone(sys.get_coroutine_wrapper())
2189-
with self.assertRaisesRegex(TypeError, "callable expected, got int"):
2190-
with self.assertWarns(DeprecationWarning):
2191-
sys.set_coroutine_wrapper(1)
2192-
with self.assertWarns(DeprecationWarning):
2193-
self.assertIsNone(sys.get_coroutine_wrapper())
2194-
2195-
def test_set_wrapper_3(self):
2196-
async def foo():
2197-
return 'spam'
2198-
2199-
def wrapper(coro):
2200-
async def wrap(coro):
2201-
return await coro
2202-
return wrap(coro)
2203-
2204-
with self.assertWarns(DeprecationWarning):
2205-
sys.set_coroutine_wrapper(wrapper)
2206-
try:
2207-
with silence_coro_gc(), self.assertRaisesRegex(
2208-
RuntimeError,
2209-
r"coroutine wrapper.*\.wrapper at 0x.*attempted to "
2210-
r"recursively wrap .* wrap .*"):
2211-
2212-
foo()
2213-
2214-
finally:
2215-
with self.assertWarns(DeprecationWarning):
2216-
sys.set_coroutine_wrapper(None)
2217-
2218-
def test_set_wrapper_4(self):
2219-
@types.coroutine
2220-
def foo():
2221-
return 'spam'
2222-
2223-
wrapped = None
2224-
def wrap(gen):
2225-
nonlocal wrapped
2226-
wrapped = gen
2227-
return gen
2228-
2229-
with self.assertWarns(DeprecationWarning):
2230-
sys.set_coroutine_wrapper(wrap)
2231-
try:
2232-
foo()
2233-
self.assertIs(
2234-
wrapped, None,
2235-
"generator-based coroutine was wrapped via "
2236-
"sys.set_coroutine_wrapper")
2237-
finally:
2238-
with self.assertWarns(DeprecationWarning):
2239-
sys.set_coroutine_wrapper(None)
2240-
2241-
22422149
class OriginTrackingTest(unittest.TestCase):
22432150
def here(self):
22442151
info = inspect.getframeinfo(inspect.currentframe().f_back)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
The functions ``sys.set_coroutine_wrapper`` and ``sys.get_coroutine_wrapper``
2+
that were deprecated and marked for removal in 3.8 have been removed.

Python/ceval.c

-39
Original file line numberDiff line numberDiff line change
@@ -4143,19 +4143,8 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
41434143
/* Handle generator/coroutine/asynchronous generator */
41444144
if (co->co_flags & (CO_GENERATOR | CO_COROUTINE | CO_ASYNC_GENERATOR)) {
41454145
PyObject *gen;
4146-
PyObject *coro_wrapper = tstate->coroutine_wrapper;
41474146
int is_coro = co->co_flags & CO_COROUTINE;
41484147

4149-
if (is_coro && tstate->in_coroutine_wrapper) {
4150-
assert(coro_wrapper != NULL);
4151-
_PyErr_Format(tstate, PyExc_RuntimeError,
4152-
"coroutine wrapper %.200R attempted "
4153-
"to recursively wrap %.200R",
4154-
coro_wrapper,
4155-
co);
4156-
goto fail;
4157-
}
4158-
41594148
/* Don't need to keep the reference to f_back, it will be set
41604149
* when the generator is resumed. */
41614150
Py_CLEAR(f->f_back);
@@ -4175,14 +4164,6 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
41754164

41764165
_PyObject_GC_TRACK(f);
41774166

4178-
if (is_coro && coro_wrapper != NULL) {
4179-
PyObject *wrapped;
4180-
tstate->in_coroutine_wrapper = 1;
4181-
wrapped = PyObject_CallFunction(coro_wrapper, "N", gen);
4182-
tstate->in_coroutine_wrapper = 0;
4183-
return wrapped;
4184-
}
4185-
41864167
return gen;
41874168
}
41884169

@@ -4633,26 +4614,6 @@ _PyEval_GetCoroutineOriginTrackingDepth(void)
46334614
return tstate->coroutine_origin_tracking_depth;
46344615
}
46354616

4636-
void
4637-
_PyEval_SetCoroutineWrapper(PyObject *wrapper)
4638-
{
4639-
PyThreadState *tstate = _PyThreadState_GET();
4640-
4641-
if (PySys_Audit("sys.set_coroutine_wrapper", NULL) < 0) {
4642-
return;
4643-
}
4644-
4645-
Py_XINCREF(wrapper);
4646-
Py_XSETREF(tstate->coroutine_wrapper, wrapper);
4647-
}
4648-
4649-
PyObject *
4650-
_PyEval_GetCoroutineWrapper(void)
4651-
{
4652-
PyThreadState *tstate = _PyThreadState_GET();
4653-
return tstate->coroutine_wrapper;
4654-
}
4655-
46564617
void
46574618
_PyEval_SetAsyncGenFirstiter(PyObject *firstiter)
46584619
{

Python/clinic/sysmodule.c.h

+1-28
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/pystate.c

-4
Original file line numberDiff line numberDiff line change
@@ -606,9 +606,6 @@ new_threadstate(PyInterpreterState *interp, int init)
606606

607607
tstate->coroutine_origin_tracking_depth = 0;
608608

609-
tstate->coroutine_wrapper = NULL;
610-
tstate->in_coroutine_wrapper = 0;
611-
612609
tstate->async_gen_firstiter = NULL;
613610
tstate->async_gen_finalizer = NULL;
614611

@@ -802,7 +799,6 @@ PyThreadState_Clear(PyThreadState *tstate)
802799
Py_CLEAR(tstate->c_profileobj);
803800
Py_CLEAR(tstate->c_traceobj);
804801

805-
Py_CLEAR(tstate->coroutine_wrapper);
806802
Py_CLEAR(tstate->async_gen_firstiter);
807803
Py_CLEAR(tstate->async_gen_finalizer);
808804

0 commit comments

Comments
 (0)