base_tasks.py 2.6 KB

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