| 458 | |
| 459 | @classmethod |
| 460 | def _extract_from_extended_frame_gen(klass, frame_gen, *, limit=None, |
| 461 | lookup_lines=True, capture_locals=False): |
| 462 | # Same as extract but operates on a frame generator that yields |
| 463 | # (frame, (lineno, end_lineno, colno, end_colno)) in the stack. |
| 464 | # Only lineno is required, the remaining fields can be None if the |
| 465 | # information is not available. |
| 466 | builtin_limit = limit is BUILTIN_EXCEPTION_LIMIT |
| 467 | if limit is None or builtin_limit: |
| 468 | limit = getattr(sys, 'tracebacklimit', None) |
| 469 | if limit is not None and limit < 0: |
| 470 | limit = 0 |
| 471 | if limit is not None: |
| 472 | if builtin_limit: |
| 473 | frame_gen = tuple(frame_gen) |
| 474 | frame_gen = frame_gen[len(frame_gen) - limit:] |
| 475 | elif limit >= 0: |
| 476 | frame_gen = itertools.islice(frame_gen, limit) |
| 477 | else: |
| 478 | frame_gen = collections.deque(frame_gen, maxlen=-limit) |
| 479 | |
| 480 | result = klass() |
| 481 | fnames = set() |
| 482 | for f, (lineno, end_lineno, colno, end_colno) in frame_gen: |
| 483 | co = f.f_code |
| 484 | filename = co.co_filename |
| 485 | name = co.co_name |
| 486 | fnames.add(filename) |
| 487 | linecache.lazycache(filename, f.f_globals) |
| 488 | # Must defer line lookups until we have called checkcache. |
| 489 | if capture_locals: |
| 490 | f_locals = f.f_locals |
| 491 | else: |
| 492 | f_locals = None |
| 493 | result.append( |
| 494 | FrameSummary(filename, lineno, name, |
| 495 | lookup_line=False, locals=f_locals, |
| 496 | end_lineno=end_lineno, colno=colno, end_colno=end_colno, |
| 497 | _code=f.f_code, |
| 498 | ) |
| 499 | ) |
| 500 | for filename in fnames: |
| 501 | linecache.checkcache(filename) |
| 502 | |
| 503 | # If immediate lookup was desired, trigger lookups now. |
| 504 | if lookup_lines: |
| 505 | for f in result: |
| 506 | f.line |
| 507 | return result |
| 508 | |
| 509 | @classmethod |
| 510 | def from_list(klass, a_list): |