1import linecache 2import traceback 3 4from . import base_futures 5from . import coroutines 6 7 8def _task_repr_info(task): 9 info = base_futures._future_repr_info(task) 10 11 if task._must_cancel: 12 # replace status 13 info[0] = 'cancelling' 14 15 coro = coroutines._format_coroutine(task._coro) 16 info.insert(1, f'coro=<{coro}>') 17 18 if task._fut_waiter is not None: 19 info.insert(2, f'wait_for={task._fut_waiter!r}') 20 return info 21 22 23def _task_get_stack(task, limit): 24 frames = [] 25 try: 26 # 'async def' coroutines 27 f = task._coro.cr_frame 28 except AttributeError: 29 f = task._coro.gi_frame 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 50 51def _task_print_stack(task, limit, file): 52 extracted_list = [] 53 checked = set() 54 for f in task.get_stack(limit=limit): 55 lineno = f.f_lineno 56 co = f.f_code 57 filename = co.co_filename 58 name = co.co_name 59 if filename not in checked: 60 checked.add(filename) 61 linecache.checkcache(filename) 62 line = linecache.getline(filename, lineno, f.f_globals) 63 extracted_list.append((filename, lineno, name, line)) 64 65 exc = task._exception 66 if not extracted_list: 67 print(f'No stack for {task!r}', file=file) 68 elif exc is not None: 69 print(f'Traceback for {task!r} (most recent call last):', file=file) 70 else: 71 print(f'Stack for {task!r} (most recent call last):', file=file) 72 73 traceback.print_list(extracted_list, file=file) 74 if exc is not None: 75 for line in traceback.format_exception_only(exc.__class__, exc): 76 print(line, file=file, end='') 77