Allow creating ExceptionInfo from existing exc_info for better typing
This way the ExceptionInfo generic parameter can be inferred from the passed-in exc_info. See for example the replaced cast().
This commit is contained in:
		
							parent
							
								
									3f1fb62584
								
							
						
					
					
						commit
						11f1f79222
					
				|  | @ -396,6 +396,33 @@ class ExceptionInfo(Generic[_E]): | |||
|     _striptext = attr.ib(type=str, default="") | ||||
|     _traceback = attr.ib(type=Optional[Traceback], default=None) | ||||
| 
 | ||||
|     @classmethod | ||||
|     def from_exc_info( | ||||
|         cls, | ||||
|         exc_info: Tuple["Type[_E]", "_E", TracebackType], | ||||
|         exprinfo: Optional[str] = None, | ||||
|     ) -> "ExceptionInfo[_E]": | ||||
|         """returns an ExceptionInfo for an existing exc_info tuple. | ||||
| 
 | ||||
|         .. warning:: | ||||
| 
 | ||||
|             Experimental API | ||||
| 
 | ||||
| 
 | ||||
|         :param exprinfo: a text string helping to determine if we should | ||||
|                          strip ``AssertionError`` from the output, defaults | ||||
|                          to the exception message/``__str__()`` | ||||
|         """ | ||||
|         _striptext = "" | ||||
|         if exprinfo is None and isinstance(exc_info[1], AssertionError): | ||||
|             exprinfo = getattr(exc_info[1], "msg", None) | ||||
|             if exprinfo is None: | ||||
|                 exprinfo = saferepr(exc_info[1]) | ||||
|             if exprinfo and exprinfo.startswith(cls._assert_start_repr): | ||||
|                 _striptext = "AssertionError: " | ||||
| 
 | ||||
|         return cls(exc_info, _striptext) | ||||
| 
 | ||||
|     @classmethod | ||||
|     def from_current( | ||||
|         cls, exprinfo: Optional[str] = None | ||||
|  | @ -411,20 +438,12 @@ class ExceptionInfo(Generic[_E]): | |||
|                          strip ``AssertionError`` from the output, defaults | ||||
|                          to the exception message/``__str__()`` | ||||
|         """ | ||||
|         tup_ = sys.exc_info() | ||||
|         assert tup_[0] is not None, "no current exception" | ||||
|         assert tup_[1] is not None, "no current exception" | ||||
|         assert tup_[2] is not None, "no current exception" | ||||
|         tup = (tup_[0], tup_[1], tup_[2]) | ||||
|         _striptext = "" | ||||
|         if exprinfo is None and isinstance(tup[1], AssertionError): | ||||
|             exprinfo = getattr(tup[1], "msg", None) | ||||
|             if exprinfo is None: | ||||
|                 exprinfo = saferepr(tup[1]) | ||||
|             if exprinfo and exprinfo.startswith(cls._assert_start_repr): | ||||
|                 _striptext = "AssertionError: " | ||||
| 
 | ||||
|         return cls(tup, _striptext) | ||||
|         tup = sys.exc_info() | ||||
|         assert tup[0] is not None, "no current exception" | ||||
|         assert tup[1] is not None, "no current exception" | ||||
|         assert tup[2] is not None, "no current exception" | ||||
|         exc_info = (tup[0], tup[1], tup[2]) | ||||
|         return cls.from_exc_info(exc_info) | ||||
| 
 | ||||
|     @classmethod | ||||
|     def for_later(cls) -> "ExceptionInfo[_E]": | ||||
|  |  | |||
|  | @ -707,11 +707,11 @@ def raises( | |||
|             ) | ||||
|         try: | ||||
|             func(*args[1:], **kwargs) | ||||
|         except expected_exception: | ||||
|             # Cast to narrow the type to expected_exception (_E). | ||||
|             return cast( | ||||
|                 _pytest._code.ExceptionInfo[_E], | ||||
|                 _pytest._code.ExceptionInfo.from_current(), | ||||
|         except expected_exception as e: | ||||
|             # We just caught the exception - there is a traceback. | ||||
|             assert e.__traceback__ is not None | ||||
|             return _pytest._code.ExceptionInfo.from_exc_info( | ||||
|                 (type(e), e, e.__traceback__) | ||||
|             ) | ||||
|     fail(message) | ||||
| 
 | ||||
|  |  | |||
|  | @ -58,7 +58,7 @@ class TWMock: | |||
|     fullwidth = 80 | ||||
| 
 | ||||
| 
 | ||||
| def test_excinfo_simple(): | ||||
| def test_excinfo_simple() -> None: | ||||
|     try: | ||||
|         raise ValueError | ||||
|     except ValueError: | ||||
|  | @ -66,6 +66,14 @@ def test_excinfo_simple(): | |||
|     assert info.type == ValueError | ||||
| 
 | ||||
| 
 | ||||
| def test_excinfo_from_exc_info_simple(): | ||||
|     try: | ||||
|         raise ValueError | ||||
|     except ValueError as e: | ||||
|         info = _pytest._code.ExceptionInfo.from_exc_info((type(e), e, e.__traceback__)) | ||||
|     assert info.type == ValueError | ||||
| 
 | ||||
| 
 | ||||
| def test_excinfo_getstatement(): | ||||
|     def g(): | ||||
|         raise ValueError | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue