base_tasks.py 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. import linecache
  2. import reprlib
  3. import traceback
  4. from . import base_futures
  5. from . import coroutines
  6. def _task_repr_info(task):
  7. info = base_futures._future_repr_info(task)
  8. if task.cancelling() and not task.done():
  9. # replace status
  10. info[0] = 'cancelling'
  11. info.insert(1, 'name=%r' % task.get_name())
  12. coro = coroutines._format_coroutine(task._coro)
  13. info.insert(2, f'coro=<{coro}>')
  14. if task._fut_waiter is not None:
  15. info.insert(3, f'wait_for={task._fut_waiter!r}')
  16. return info
  17. @reprlib.recursive_repr()
  18. def _task_repr(task):
  19. info = ' '.join(_task_repr_info(task))
  20. return f'<{task.__class__.__name__} {info}>'
  21. def _task_get_stack(task, limit):
  22. frames = []
  23. if hasattr(task._coro, 'cr_frame'):
  24. # case 1: 'async def' coroutines
  25. f = task._coro.cr_frame
  26. elif hasattr(task._coro, 'gi_frame'):
  27. # case 2: legacy coroutines
  28. f = task._coro.gi_frame
  29. elif hasattr(task._coro, 'ag_frame'):
  30. # case 3: async generators
  31. f = task._coro.ag_frame
  32. else:
  33. # case 4: unknown objects
  34. f = None
  35. if f is not None:
  36. while f is not None:
  37. if limit is not None:
  38. if limit <= 0:
  39. break
  40. limit -= 1
  41. frames.append(f)
  42. f = f.f_back
  43. frames.reverse()
  44. elif task._exception is not None:
  45. tb = task._exception.__traceback__
  46. while tb is not None:
  47. if limit is not None:
  48. if limit <= 0:
  49. break
  50. limit -= 1
  51. frames.append(tb.tb_frame)
  52. tb = tb.tb_next
  53. return frames
  54. def _task_print_stack(task, limit, file):
  55. extracted_list = []
  56. checked = set()
  57. for f in task.get_stack(limit=limit):
  58. lineno = f.f_lineno
  59. co = f.f_code
  60. filename = co.co_filename
  61. name = co.co_name
  62. if filename not in checked:
  63. checked.add(filename)
  64. linecache.checkcache(filename)
  65. line = linecache.getline(filename, lineno, f.f_globals)
  66. extracted_list.append((filename, lineno, name, line))
  67. exc = task._exception
  68. if not extracted_list:
  69. print(f'No stack for {task!r}', file=file)
  70. elif exc is not None:
  71. print(f'Traceback for {task!r} (most recent call last):', file=file)
  72. else:
  73. print(f'Stack for {task!r} (most recent call last):', file=file)
  74. traceback.print_list(extracted_list, file=file)
  75. if exc is not None:
  76. for line in traceback.format_exception_only(exc.__class__, exc):
  77. print(line, file=file, end='')