base_tasks.py 2.4 KB

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