return f'cb=[{cb}]'
-# bpo-42183: _repr_running is needed for repr protection
-# when a Future or Task result contains itself directly or indirectly.
-# The logic is borrowed from @reprlib.recursive_repr decorator.
-# Unfortunately, the direct decorator usage is impossible because of
-# AttributeError: '_asyncio.Task' object has no attribute '__module__' error.
-#
-# After fixing this thing we can return to the decorator based approach.
-_repr_running = set()
-
-
def _future_repr_info(future):
# (Future) -> str
"""helper function for Future.__repr__"""
if future._exception is not None:
info.append(f'exception={future._exception!r}')
else:
- key = id(future), get_ident()
- if key in _repr_running:
- result = '...'
- else:
- _repr_running.add(key)
- try:
- # use reprlib to limit the length of the output, especially
- # for very long strings
- result = reprlib.repr(future._result)
- finally:
- _repr_running.discard(key)
+ # use reprlib to limit the length of the output, especially
+ # for very long strings
+ result = reprlib.repr(future._result)
info.append(f'result={result}')
if future._callbacks:
info.append(_format_callbacks(future._callbacks))
frame = future._source_traceback[-1]
info.append(f'created at {frame[0]}:{frame[1]}')
return info
+
+
+@reprlib.recursive_repr()
+def _future_repr(future):
+ info = ' '.join(_future_repr_info(future))
+ return f'<{future.__class__.__name__} {info}>'
static PyObject *asyncio_mod;
static PyObject *traceback_extract_stack;
static PyObject *asyncio_get_event_loop_policy;
-static PyObject *asyncio_future_repr_info_func;
+static PyObject *asyncio_future_repr_func;
static PyObject *asyncio_iscoroutine_func;
static PyObject *asyncio_task_get_stack_func;
static PyObject *asyncio_task_print_stack_func;
-static PyObject *asyncio_task_repr_info_func;
+static PyObject *asyncio_task_repr_func;
static PyObject *asyncio_InvalidStateError;
static PyObject *asyncio_CancelledError;
static PyObject *context_kwname;
return ret;
}
+static PyObject *
+FutureObj_repr(FutureObj *fut)
+{
+ ENSURE_FUTURE_ALIVE(fut)
+ return PyObject_CallOneArg(asyncio_future_repr_func, (PyObject *)fut);
+}
+
/*[clinic input]
_asyncio.Future._make_cancelled_error
return create_cancelled_error(self);
}
-/*[clinic input]
-_asyncio.Future._repr_info
-[clinic start generated code]*/
-
-static PyObject *
-_asyncio_Future__repr_info_impl(FutureObj *self)
-/*[clinic end generated code: output=fa69e901bd176cfb input=f21504d8e2ae1ca2]*/
-{
- return PyObject_CallOneArg(asyncio_future_repr_info_func, (PyObject *)self);
-}
-
-static PyObject *
-FutureObj_repr(FutureObj *fut)
-{
- _Py_IDENTIFIER(_repr_info);
-
- ENSURE_FUTURE_ALIVE(fut)
-
- PyObject *rinfo = _PyObject_CallMethodIdNoArgs((PyObject*)fut,
- &PyId__repr_info);
- if (rinfo == NULL) {
- return NULL;
- }
-
- PyObject *rinfo_s = PyUnicode_Join(NULL, rinfo);
- Py_DECREF(rinfo);
- if (rinfo_s == NULL) {
- return NULL;
- }
-
- PyObject *rstr = PyUnicode_FromFormat("<%s %U>",
- _PyType_Name(Py_TYPE(fut)), rinfo_s);
- Py_DECREF(rinfo_s);
- return rstr;
-}
-
static void
FutureObj_finalize(FutureObj *fut)
{
_ASYNCIO_FUTURE_DONE_METHODDEF
_ASYNCIO_FUTURE_GET_LOOP_METHODDEF
_ASYNCIO_FUTURE__MAKE_CANCELLED_ERROR_METHODDEF
- _ASYNCIO_FUTURE__REPR_INFO_METHODDEF
{"__class_getitem__", Py_GenericAlias, METH_O|METH_CLASS, PyDoc_STR("See PEP 585")},
{NULL, NULL} /* Sentinel */
};
Py_RETURN_NONE;
}
+static PyObject *
+TaskObj_repr(TaskObj *task)
+{
+ return PyObject_CallOneArg(asyncio_task_repr_func, (PyObject *)task);
+}
+
+
/*[clinic input]
_asyncio.Task._make_cancelled_error
}
-/*[clinic input]
-_asyncio.Task._repr_info
-[clinic start generated code]*/
-
-static PyObject *
-_asyncio_Task__repr_info_impl(TaskObj *self)
-/*[clinic end generated code: output=6a490eb66d5ba34b input=3c6d051ed3ddec8b]*/
-{
- return PyObject_CallOneArg(asyncio_task_repr_info_func, (PyObject *)self);
-}
-
/*[clinic input]
_asyncio.Task.cancel
_ASYNCIO_TASK_GET_STACK_METHODDEF
_ASYNCIO_TASK_PRINT_STACK_METHODDEF
_ASYNCIO_TASK__MAKE_CANCELLED_ERROR_METHODDEF
- _ASYNCIO_TASK__REPR_INFO_METHODDEF
_ASYNCIO_TASK_GET_NAME_METHODDEF
_ASYNCIO_TASK_SET_NAME_METHODDEF
_ASYNCIO_TASK_GET_CORO_METHODDEF
.tp_base = &FutureType,
.tp_dealloc = TaskObj_dealloc,
.tp_as_async = &FutureType_as_async,
- .tp_repr = (reprfunc)FutureObj_repr,
+ .tp_repr = (reprfunc)TaskObj_repr,
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
.tp_doc = _asyncio_Task___init____doc__,
.tp_traverse = (traverseproc)TaskObj_traverse,
{
Py_CLEAR(asyncio_mod);
Py_CLEAR(traceback_extract_stack);
- Py_CLEAR(asyncio_future_repr_info_func);
+ Py_CLEAR(asyncio_future_repr_func);
Py_CLEAR(asyncio_get_event_loop_policy);
Py_CLEAR(asyncio_iscoroutine_func);
Py_CLEAR(asyncio_task_get_stack_func);
Py_CLEAR(asyncio_task_print_stack_func);
- Py_CLEAR(asyncio_task_repr_info_func);
+ Py_CLEAR(asyncio_task_repr_func);
Py_CLEAR(asyncio_InvalidStateError);
Py_CLEAR(asyncio_CancelledError);
GET_MOD_ATTR(asyncio_get_event_loop_policy, "get_event_loop_policy")
WITH_MOD("asyncio.base_futures")
- GET_MOD_ATTR(asyncio_future_repr_info_func, "_future_repr_info")
+ GET_MOD_ATTR(asyncio_future_repr_func, "_future_repr")
WITH_MOD("asyncio.exceptions")
GET_MOD_ATTR(asyncio_InvalidStateError, "InvalidStateError")
GET_MOD_ATTR(asyncio_CancelledError, "CancelledError")
WITH_MOD("asyncio.base_tasks")
- GET_MOD_ATTR(asyncio_task_repr_info_func, "_task_repr_info")
+ GET_MOD_ATTR(asyncio_task_repr_func, "_task_repr")
GET_MOD_ATTR(asyncio_task_get_stack_func, "_task_get_stack")
GET_MOD_ATTR(asyncio_task_print_stack_func, "_task_print_stack")
return _asyncio_Future__make_cancelled_error_impl(self);
}
-PyDoc_STRVAR(_asyncio_Future__repr_info__doc__,
-"_repr_info($self, /)\n"
-"--\n"
-"\n");
-
-#define _ASYNCIO_FUTURE__REPR_INFO_METHODDEF \
- {"_repr_info", (PyCFunction)_asyncio_Future__repr_info, METH_NOARGS, _asyncio_Future__repr_info__doc__},
-
-static PyObject *
-_asyncio_Future__repr_info_impl(FutureObj *self);
-
-static PyObject *
-_asyncio_Future__repr_info(FutureObj *self, PyObject *Py_UNUSED(ignored))
-{
- return _asyncio_Future__repr_info_impl(self);
-}
-
PyDoc_STRVAR(_asyncio_Task___init____doc__,
"Task(coro, *, loop=None, name=None, context=None)\n"
"--\n"
return _asyncio_Task__make_cancelled_error_impl(self);
}
-PyDoc_STRVAR(_asyncio_Task__repr_info__doc__,
-"_repr_info($self, /)\n"
-"--\n"
-"\n");
-
-#define _ASYNCIO_TASK__REPR_INFO_METHODDEF \
- {"_repr_info", (PyCFunction)_asyncio_Task__repr_info, METH_NOARGS, _asyncio_Task__repr_info__doc__},
-
-static PyObject *
-_asyncio_Task__repr_info_impl(TaskObj *self);
-
-static PyObject *
-_asyncio_Task__repr_info(TaskObj *self, PyObject *Py_UNUSED(ignored))
-{
- return _asyncio_Task__repr_info_impl(self);
-}
-
PyDoc_STRVAR(_asyncio_Task_cancel__doc__,
"cancel($self, /, msg=None)\n"
"--\n"
exit:
return return_value;
}
-/*[clinic end generated code: output=540ed3caf5a4d57d input=a9049054013a1b77]*/
+/*[clinic end generated code: output=64b3836574e8a18c input=a9049054013a1b77]*/