Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 0 additions & 59 deletions Doc/library/sys.rst
Original file line number Diff line number Diff line change
Expand Up @@ -777,22 +777,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 @@ -1380,49 +1364,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 @@ -955,6 +955,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``.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't quite get it -- what's the point of keeping sys.get_coroutine_wrapper? Both should be removed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't quite get it -- what's the point of keeping sys.get_coroutine_wrapper? Both should be removed.

I remember reading to remove sys.set_coroutine_wrapper now and get_coro_wrapper later... but my memory might just be failing me. I'm happy to remove get_coro_wrapper as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, and rebased (Conflict, need to regen clinic).

: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