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,

`