3131from typing import TYPE_CHECKING
3232from typing import TypeVar
3333from typing import Union
34- from weakref import ref
3534
3635import pluggy
3736
5251if TYPE_CHECKING :
5352 from typing_extensions import Literal
5453 from typing_extensions import SupportsIndex
55- from weakref import ReferenceType
5654
5755 _TracebackStyle = Literal ["long" , "short" , "line" , "no" , "native" , "value" , "auto" ]
5856
@@ -194,15 +192,13 @@ def getargs(self, var: bool = False):
194192class TracebackEntry :
195193 """A single entry in a Traceback."""
196194
197- __slots__ = ("_rawentry" , "_excinfo" , " _repr_style" )
195+ __slots__ = ("_rawentry" , "_repr_style" )
198196
199197 def __init__ (
200198 self ,
201199 rawentry : TracebackType ,
202- excinfo : Optional ["ReferenceType[ExceptionInfo[BaseException]]" ] = None ,
203200 ) -> None :
204201 self ._rawentry = rawentry
205- self ._excinfo = excinfo
206202 self ._repr_style : Optional ['Literal["short", "long"]' ] = None
207203
208204 @property
@@ -272,7 +268,7 @@ def getsource(
272268
273269 source = property (getsource )
274270
275- def ishidden (self ) -> bool :
271+ def ishidden (self , excinfo : Optional [ "ExceptionInfo[BaseException]" ] ) -> bool :
276272 """Return True if the current frame has a var __tracebackhide__
277273 resolving to True.
278274
@@ -296,7 +292,7 @@ def ishidden(self) -> bool:
296292 else :
297293 break
298294 if tbh and callable (tbh ):
299- return tbh (None if self . _excinfo is None else self . _excinfo () )
295+ return tbh (excinfo )
300296 return tbh
301297
302298 def __str__ (self ) -> str :
@@ -329,16 +325,14 @@ class Traceback(List[TracebackEntry]):
329325 def __init__ (
330326 self ,
331327 tb : Union [TracebackType , Iterable [TracebackEntry ]],
332- excinfo : Optional ["ReferenceType[ExceptionInfo[BaseException]]" ] = None ,
333328 ) -> None :
334329 """Initialize from given python traceback object and ExceptionInfo."""
335- self ._excinfo = excinfo
336330 if isinstance (tb , TracebackType ):
337331
338332 def f (cur : TracebackType ) -> Iterable [TracebackEntry ]:
339333 cur_ : Optional [TracebackType ] = cur
340334 while cur_ is not None :
341- yield TracebackEntry (cur_ , excinfo = excinfo )
335+ yield TracebackEntry (cur_ )
342336 cur_ = cur_ .tb_next
343337
344338 super ().__init__ (f (tb ))
@@ -378,7 +372,7 @@ def cut(
378372 continue
379373 if firstlineno is not None and x .frame .code .firstlineno != firstlineno :
380374 continue
381- return Traceback (x ._rawentry , self . _excinfo )
375+ return Traceback (x ._rawentry )
382376 return self
383377
384378 @overload
@@ -398,25 +392,36 @@ def __getitem__(
398392 return super ().__getitem__ (key )
399393
400394 def filter (
401- self , fn : Callable [[TracebackEntry ], bool ] = lambda x : not x .ishidden ()
395+ self ,
396+ # TODO(py38): change to positional only.
397+ _excinfo_or_fn : Union [
398+ "ExceptionInfo[BaseException]" ,
399+ Callable [[TracebackEntry ], bool ],
400+ ],
402401 ) -> "Traceback" :
403- """Return a Traceback instance with certain items removed
402+ """Return a Traceback instance with certain items removed.
404403
405- fn is a function that gets a single argument, a TracebackEntry
406- instance, and should return True when the item should be added
407- to the Traceback, False when not.
404+ If the filter is an `ExceptionInfo`, removes all the ``TracebackEntry``s
405+ which are hidden (see ishidden() above).
408406
409- By default this removes all the TracebackEntries which are hidden
410- (see ishidden() above).
407+ Otherwise, the filter is a function that gets a single argument, a
408+ ``TracebackEntry`` instance, and should return True when the item should
409+ be added to the ``Traceback``, False when not.
411410 """
412- return Traceback (filter (fn , self ), self ._excinfo )
411+ if isinstance (_excinfo_or_fn , ExceptionInfo ):
412+ fn = lambda x : not x .ishidden (_excinfo_or_fn ) # noqa: E731
413+ else :
414+ fn = _excinfo_or_fn
415+ return Traceback (filter (fn , self ))
413416
414- def getcrashentry (self ) -> Optional [TracebackEntry ]:
417+ def getcrashentry (
418+ self , excinfo : Optional ["ExceptionInfo[BaseException]" ]
419+ ) -> Optional [TracebackEntry ]:
415420 """Return last non-hidden traceback entry that lead to the exception of
416421 a traceback, or None if all hidden."""
417422 for i in range (- 1 , - len (self ) - 1 , - 1 ):
418423 entry = self [i ]
419- if not entry .ishidden ():
424+ if not entry .ishidden (excinfo ):
420425 return entry
421426 return None
422427
@@ -583,7 +588,7 @@ def typename(self) -> str:
583588 def traceback (self ) -> Traceback :
584589 """The traceback."""
585590 if self ._traceback is None :
586- self ._traceback = Traceback (self .tb , excinfo = ref ( self ) )
591+ self ._traceback = Traceback (self .tb )
587592 return self ._traceback
588593
589594 @traceback .setter
@@ -624,7 +629,7 @@ def errisinstance(
624629
625630 def _getreprcrash (self ) -> Optional ["ReprFileLocation" ]:
626631 exconly = self .exconly (tryshort = True )
627- entry = self .traceback .getcrashentry ()
632+ entry = self .traceback .getcrashentry (self )
628633 if entry is None :
629634 return None
630635 path , lineno = entry .frame .code .raw .co_filename , entry .lineno
@@ -882,7 +887,7 @@ def _makepath(self, path: Union[Path, str]) -> str:
882887 def repr_traceback (self , excinfo : ExceptionInfo [BaseException ]) -> "ReprTraceback" :
883888 traceback = excinfo .traceback
884889 if self .tbfilter :
885- traceback = traceback .filter ()
890+ traceback = traceback .filter (excinfo )
886891
887892 if isinstance (excinfo .value , RecursionError ):
888893 traceback , extraline = self ._truncate_recursive_traceback (traceback )
0 commit comments