bpo-32311: Implement asyncio.create_task() shortcut (#4848) · python/cpython@f74ef45 (original) (raw)
`@@ -11,86 +11,14 @@
`
11
11
`'_get_running_loop',
`
12
12
`)
`
13
13
``
14
``
`-
import functools
`
15
``
`-
import inspect
`
16
14
`import os
`
17
``
`-
import reprlib
`
18
15
`import socket
`
19
16
`import subprocess
`
20
17
`import sys
`
21
18
`import threading
`
22
``
`-
import traceback
`
23
19
``
24
20
`from . import constants
`
25
``
-
26
``
-
27
``
`-
def _get_function_source(func):
`
28
``
`-
func = inspect.unwrap(func)
`
29
``
`-
if inspect.isfunction(func):
`
30
``
`-
code = func.code
`
31
``
`-
return (code.co_filename, code.co_firstlineno)
`
32
``
`-
if isinstance(func, functools.partial):
`
33
``
`-
return _get_function_source(func.func)
`
34
``
`-
if isinstance(func, functools.partialmethod):
`
35
``
`-
return _get_function_source(func.func)
`
36
``
`-
return None
`
37
``
-
38
``
-
39
``
`-
def _format_args_and_kwargs(args, kwargs):
`
40
``
`-
"""Format function arguments and keyword arguments.
`
41
``
-
42
``
`-
Special case for a single parameter: ('hello',) is formatted as ('hello').
`
43
``
`-
"""
`
44
``
`-
use reprlib to limit the length of the output
`
45
``
`-
items = []
`
46
``
`-
if args:
`
47
``
`-
items.extend(reprlib.repr(arg) for arg in args)
`
48
``
`-
if kwargs:
`
49
``
`-
items.extend(f'{k}={reprlib.repr(v)}' for k, v in kwargs.items())
`
50
``
`-
return '({})'.format(', '.join(items))
`
51
``
-
52
``
-
53
``
`-
def _format_callback(func, args, kwargs, suffix=''):
`
54
``
`-
if isinstance(func, functools.partial):
`
55
``
`-
suffix = _format_args_and_kwargs(args, kwargs) + suffix
`
56
``
`-
return _format_callback(func.func, func.args, func.keywords, suffix)
`
57
``
-
58
``
`-
if hasattr(func, 'qualname'):
`
59
``
`-
func_repr = getattr(func, 'qualname')
`
60
``
`-
elif hasattr(func, 'name'):
`
61
``
`-
func_repr = getattr(func, 'name')
`
62
``
`-
else:
`
63
``
`-
func_repr = repr(func)
`
64
``
-
65
``
`-
func_repr += _format_args_and_kwargs(args, kwargs)
`
66
``
`-
if suffix:
`
67
``
`-
func_repr += suffix
`
68
``
`-
return func_repr
`
69
``
-
70
``
-
71
``
`-
def _format_callback_source(func, args):
`
72
``
`-
func_repr = _format_callback(func, args, None)
`
73
``
`-
source = _get_function_source(func)
`
74
``
`-
if source:
`
75
``
`-
func_repr += f' at {source[0]}:{source[1]}'
`
76
``
`-
return func_repr
`
77
``
-
78
``
-
79
``
`-
def extract_stack(f=None, limit=None):
`
80
``
`-
"""Replacement for traceback.extract_stack() that only does the
`
81
``
`-
necessary work for asyncio debug mode.
`
82
``
`-
"""
`
83
``
`-
if f is None:
`
84
``
`-
f = sys._getframe().f_back
`
85
``
`-
if limit is None:
`
86
``
`-
Limit the amount of work to a reasonable amount, as extract_stack()
`
87
``
`-
can be called for each coroutine and future in debug mode.
`
88
``
`-
limit = constants.DEBUG_STACK_DEPTH
`
89
``
`-
stack = traceback.StackSummary.extract(traceback.walk_stack(f),
`
90
``
`-
limit=limit,
`
91
``
`-
lookup_lines=False)
`
92
``
`-
stack.reverse()
`
93
``
`-
return stack
`
``
21
`+
from . import format_helpers
`
94
22
``
95
23
``
96
24
`class Handle:
`
`@@ -106,7 +34,8 @@ def init(self, callback, args, loop):
`
106
34
`self._cancelled = False
`
107
35
`self._repr = None
`
108
36
`if self._loop.get_debug():
`
109
``
`-
self._source_traceback = extract_stack(sys._getframe(1))
`
``
37
`+
self._source_traceback = format_helpers.extract_stack(
`
``
38
`+
sys._getframe(1))
`
110
39
`else:
`
111
40
`self._source_traceback = None
`
112
41
``
`@@ -115,7 +44,8 @@ def _repr_info(self):
`
115
44
`if self._cancelled:
`
116
45
`info.append('cancelled')
`
117
46
`if self._callback is not None:
`
118
``
`-
info.append(_format_callback_source(self._callback, self._args))
`
``
47
`+
info.append(format_helpers._format_callback_source(
`
``
48
`+
self._callback, self._args))
`
119
49
`if self._source_traceback:
`
120
50
`frame = self._source_traceback[-1]
`
121
51
`info.append(f'created at {frame[0]}:{frame[1]}')
`
`@@ -145,7 +75,8 @@ def _run(self):
`
145
75
`try:
`
146
76
`self._callback(*self._args)
`
147
77
`except Exception as exc:
`
148
``
`-
cb = _format_callback_source(self._callback, self._args)
`
``
78
`+
cb = format_helpers._format_callback_source(
`
``
79
`+
self._callback, self._args)
`
149
80
`msg = f'Exception in callback {cb}'
`
150
81
`context = {
`
151
82
`'message': msg,
`