refactor CallInfo constructor magic into named constructor
This commit is contained in:
		
							parent
							
								
									b531f7d585
								
							
						
					
					
						commit
						847eacea19
					
				|  | @ -23,7 +23,9 @@ def get_skip_exceptions(): | |||
| def pytest_runtest_makereport(item, call): | ||||
|     if call.excinfo and call.excinfo.errisinstance(get_skip_exceptions()): | ||||
|         # let's substitute the excinfo with a pytest.skip one | ||||
|         call2 = call.__class__(lambda: runner.skip(str(call.excinfo.value)), call.when) | ||||
|         call2 = runner.CallInfo.from_call( | ||||
|             lambda: runner.skip(str(call.excinfo.value)), call.when | ||||
|         ) | ||||
|         call.excinfo = call2.excinfo | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -8,6 +8,7 @@ import os | |||
| import sys | ||||
| from time import time | ||||
| 
 | ||||
| import attr | ||||
| import six | ||||
| 
 | ||||
| from .reports import CollectErrorRepr | ||||
|  | @ -189,43 +190,57 @@ def check_interactive_exception(call, report): | |||
| def call_runtest_hook(item, when, **kwds): | ||||
|     hookname = "pytest_runtest_" + when | ||||
|     ihook = getattr(item.ihook, hookname) | ||||
|     return CallInfo( | ||||
|     return CallInfo.from_call( | ||||
|         lambda: ihook(item=item, **kwds), | ||||
|         when=when, | ||||
|         treat_keyboard_interrupt_as_exception=item.config.getvalue("usepdb"), | ||||
|         reraise=KeyboardInterrupt if not item.config.getvalue("usepdb") else (), | ||||
|     ) | ||||
| 
 | ||||
| 
 | ||||
| @attr.s(repr=False) | ||||
| class CallInfo(object): | ||||
|     """ Result/Exception info a function invocation. """ | ||||
| 
 | ||||
|     #: None or ExceptionInfo object. | ||||
|     excinfo = None | ||||
|     _result = attr.ib() | ||||
|     # type: Optional[ExceptionInfo] | ||||
|     excinfo = attr.ib() | ||||
|     start = attr.ib() | ||||
|     stop = attr.ib() | ||||
|     when = attr.ib() | ||||
| 
 | ||||
|     def __init__(self, func, when, treat_keyboard_interrupt_as_exception=False): | ||||
|     @property | ||||
|     def result(self): | ||||
|         if self.excinfo is not None: | ||||
|             raise AttributeError("{!r} has no valid result".format(self)) | ||||
|         return self._result | ||||
| 
 | ||||
|     @classmethod | ||||
|     def from_call(cls, func, when, reraise=None): | ||||
|         #: context of invocation: one of "setup", "call", | ||||
|         #: "teardown", "memocollect" | ||||
|         self.when = when | ||||
|         self.start = time() | ||||
|         start = time() | ||||
|         excinfo = None | ||||
|         try: | ||||
|             self.result = func() | ||||
|         except KeyboardInterrupt: | ||||
|             if treat_keyboard_interrupt_as_exception: | ||||
|                 self.excinfo = ExceptionInfo.from_current() | ||||
|             else: | ||||
|                 self.stop = time() | ||||
|                 raise | ||||
|             result = func() | ||||
|         except:  # noqa | ||||
|             self.excinfo = ExceptionInfo.from_current() | ||||
|         self.stop = time() | ||||
|             excinfo = ExceptionInfo.from_current() | ||||
|             if reraise is not None and excinfo.errisinstance(reraise): | ||||
|                 raise | ||||
|             result = None | ||||
|         stop = time() | ||||
|         return cls(start=start, stop=stop, when=when, result=result, excinfo=excinfo) | ||||
| 
 | ||||
|     def __repr__(self): | ||||
|         if self.excinfo: | ||||
|             status = "exception: %s" % str(self.excinfo.value) | ||||
|         if self.excinfo is not None: | ||||
|             status = "exception" | ||||
|             value = self.excinfo.value | ||||
|         else: | ||||
|             result = getattr(self, "result", "<NOTSET>") | ||||
|             status = "result: %r" % (result,) | ||||
|         return "<CallInfo when=%r %s>" % (self.when, status) | ||||
|             # TODO: investigate unification | ||||
|             value = repr(self._result) | ||||
|             status = "result" | ||||
|         return "<CallInfo when={when!r} {status}: {value}>".format( | ||||
|             when=self.when, value=value, status=status | ||||
|         ) | ||||
| 
 | ||||
| 
 | ||||
| def pytest_runtest_makereport(item, call): | ||||
|  | @ -269,7 +284,7 @@ def pytest_runtest_makereport(item, call): | |||
| 
 | ||||
| 
 | ||||
| def pytest_make_collect_report(collector): | ||||
|     call = CallInfo(lambda: list(collector.collect()), "collect") | ||||
|     call = CallInfo.from_call(lambda: list(collector.collect()), "collect") | ||||
|     longrepr = None | ||||
|     if not call.excinfo: | ||||
|         outcome = "passed" | ||||
|  |  | |||
|  | @ -487,13 +487,13 @@ def test_report_extra_parameters(reporttype): | |||
| 
 | ||||
| 
 | ||||
| def test_callinfo(): | ||||
|     ci = runner.CallInfo(lambda: 0, "123") | ||||
|     ci = runner.CallInfo.from_call(lambda: 0, "123") | ||||
|     assert ci.when == "123" | ||||
|     assert ci.result == 0 | ||||
|     assert "result" in repr(ci) | ||||
|     assert repr(ci) == "<CallInfo when='123' result: 0>" | ||||
| 
 | ||||
|     ci = runner.CallInfo(lambda: 0 / 0, "123") | ||||
|     ci = runner.CallInfo.from_call(lambda: 0 / 0, "123") | ||||
|     assert ci.when == "123" | ||||
|     assert not hasattr(ci, "result") | ||||
|     assert repr(ci) == "<CallInfo when='123' exception: division by zero>" | ||||
|  | @ -501,16 +501,6 @@ def test_callinfo(): | |||
|     assert "exc" in repr(ci) | ||||
| 
 | ||||
| 
 | ||||
| def test_callinfo_repr_while_running(): | ||||
|     def repr_while_running(): | ||||
|         f = sys._getframe().f_back | ||||
|         assert "func" in f.f_locals | ||||
|         assert repr(f.f_locals["self"]) == "<CallInfo when='when' result: '<NOTSET>'>" | ||||
| 
 | ||||
|     ci = runner.CallInfo(repr_while_running, "when") | ||||
|     assert repr(ci) == "<CallInfo when='when' result: None>" | ||||
| 
 | ||||
| 
 | ||||
| # design question: do we want general hooks in python files? | ||||
| # then something like the following functional tests makes sense | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue