5
5
from inspect import CO_VARARGS
6
6
from inspect import CO_VARKEYWORDS
7
7
from traceback import format_exception_only
8
+ from types import TracebackType
9
+ from typing import Optional
10
+ from typing import Pattern
11
+ from typing import Tuple
12
+ from typing import Union
8
13
from weakref import ref
9
14
10
15
import attr
15
20
from _pytest ._io .saferepr import safeformat
16
21
from _pytest ._io .saferepr import saferepr
17
22
23
+ if False : # TYPE_CHECKING
24
+ from typing import Type
25
+
18
26
19
27
class Code :
20
28
""" wrapper around Python code objects """
@@ -379,12 +387,14 @@ class ExceptionInfo:
379
387
380
388
_assert_start_repr = "AssertionError('assert "
381
389
382
- _excinfo = attr .ib ()
383
- _striptext = attr .ib (default = "" )
384
- _traceback = attr .ib (default = None )
390
+ _excinfo = attr .ib (
391
+ type = Optional [Tuple ["Type[BaseException]" , BaseException , TracebackType ]]
392
+ )
393
+ _striptext = attr .ib (type = str , default = "" )
394
+ _traceback = attr .ib (type = Optional [Traceback ], default = None )
385
395
386
396
@classmethod
387
- def from_current (cls , exprinfo = None ):
397
+ def from_current (cls , exprinfo : Optional [ str ] = None ) -> "ExceptionInfo" :
388
398
"""returns an ExceptionInfo matching the current traceback
389
399
390
400
.. warning::
@@ -396,8 +406,11 @@ def from_current(cls, exprinfo=None):
396
406
strip ``AssertionError`` from the output, defaults
397
407
to the exception message/``__str__()``
398
408
"""
399
- tup = sys .exc_info ()
400
- assert tup [0 ] is not None , "no current exception"
409
+ tup_ = sys .exc_info ()
410
+ assert tup_ [0 ] is not None , "no current exception"
411
+ assert tup_ [1 ] is not None , "no current exception"
412
+ assert tup_ [2 ] is not None , "no current exception"
413
+ tup = (tup_ [0 ], tup_ [1 ], tup_ [2 ])
401
414
_striptext = ""
402
415
if exprinfo is None and isinstance (tup [1 ], AssertionError ):
403
416
exprinfo = getattr (tup [1 ], "msg" , None )
@@ -409,48 +422,60 @@ def from_current(cls, exprinfo=None):
409
422
return cls (tup , _striptext )
410
423
411
424
@classmethod
412
- def for_later (cls ):
425
+ def for_later (cls ) -> "ExceptionInfo" :
413
426
"""return an unfilled ExceptionInfo
414
427
"""
415
428
return cls (None )
416
429
417
430
@property
418
- def type (self ):
431
+ def type (self ) -> "Type[BaseException]" :
419
432
"""the exception class"""
433
+ assert (
434
+ self ._excinfo is not None
435
+ ), ".type can only be used after the context manager exits"
420
436
return self ._excinfo [0 ]
421
437
422
438
@property
423
- def value (self ):
439
+ def value (self ) -> BaseException :
424
440
"""the exception value"""
441
+ assert (
442
+ self ._excinfo is not None
443
+ ), ".value can only be used after the context manager exits"
425
444
return self ._excinfo [1 ]
426
445
427
446
@property
428
- def tb (self ):
447
+ def tb (self ) -> TracebackType :
429
448
"""the exception raw traceback"""
449
+ assert (
450
+ self ._excinfo is not None
451
+ ), ".tb can only be used after the context manager exits"
430
452
return self ._excinfo [2 ]
431
453
432
454
@property
433
- def typename (self ):
455
+ def typename (self ) -> str :
434
456
"""the type name of the exception"""
457
+ assert (
458
+ self ._excinfo is not None
459
+ ), ".typename can only be used after the context manager exits"
435
460
return self .type .__name__
436
461
437
462
@property
438
- def traceback (self ):
463
+ def traceback (self ) -> Traceback :
439
464
"""the traceback"""
440
465
if self ._traceback is None :
441
466
self ._traceback = Traceback (self .tb , excinfo = ref (self ))
442
467
return self ._traceback
443
468
444
469
@traceback .setter
445
- def traceback (self , value ) :
470
+ def traceback (self , value : Traceback ) -> None :
446
471
self ._traceback = value
447
472
448
- def __repr__ (self ):
473
+ def __repr__ (self ) -> str :
449
474
if self ._excinfo is None :
450
475
return "<ExceptionInfo for raises contextmanager>"
451
476
return "<ExceptionInfo %s tblen=%d>" % (self .typename , len (self .traceback ))
452
477
453
- def exconly (self , tryshort = False ):
478
+ def exconly (self , tryshort : bool = False ) -> str :
454
479
""" return the exception as a string
455
480
456
481
when 'tryshort' resolves to True, and the exception is a
@@ -466,25 +491,25 @@ def exconly(self, tryshort=False):
466
491
text = text [len (self ._striptext ) :]
467
492
return text
468
493
469
- def errisinstance (self , exc ) :
494
+ def errisinstance (self , exc : "Type[BaseException]" ) -> bool :
470
495
""" return True if the exception is an instance of exc """
471
496
return isinstance (self .value , exc )
472
497
473
- def _getreprcrash (self ):
498
+ def _getreprcrash (self ) -> "ReprFileLocation" :
474
499
exconly = self .exconly (tryshort = True )
475
500
entry = self .traceback .getcrashentry ()
476
501
path , lineno = entry .frame .code .raw .co_filename , entry .lineno
477
502
return ReprFileLocation (path , lineno + 1 , exconly )
478
503
479
504
def getrepr (
480
505
self ,
481
- showlocals = False ,
482
- style = "long" ,
483
- abspath = False ,
484
- tbfilter = True ,
485
- funcargs = False ,
486
- truncate_locals = True ,
487
- chain = True ,
506
+ showlocals : bool = False ,
507
+ style : str = "long" ,
508
+ abspath : bool = False ,
509
+ tbfilter : bool = True ,
510
+ funcargs : bool = False ,
511
+ truncate_locals : bool = True ,
512
+ chain : bool = True ,
488
513
):
489
514
"""
490
515
Return str()able representation of this exception info.
@@ -535,7 +560,7 @@ def getrepr(
535
560
)
536
561
return fmt .repr_excinfo (self )
537
562
538
- def match (self , regexp ) :
563
+ def match (self , regexp : Union [ str , Pattern ]) -> bool :
539
564
"""
540
565
Check whether the regular expression 'regexp' is found in the string
541
566
representation of the exception using ``re.search``. If it matches
0 commit comments