introduced pytest_keyboardinterrupt hook
removed optional argument from pytest_sessionfinish hook --HG-- branch : 1.0.x
This commit is contained in:
		
							parent
							
								
									04a98700d9
								
							
						
					
					
						commit
						8be0ea942a
					
				|  | @ -1,6 +1,9 @@ | ||||||
| Changes between 1.0.0b7 and 1.0.0b8 | Changes between 1.0.0b7 and 1.0.0b8 | ||||||
| ===================================== | ===================================== | ||||||
| 
 | 
 | ||||||
|  | * introduced pytest_keyboardinterrupt hook and  | ||||||
|  |   refined pytest_sessionfinish hooked.  | ||||||
|  | 
 | ||||||
| * workaround a buggy logging module interaction ("closing already closed | * workaround a buggy logging module interaction ("closing already closed | ||||||
|   files").  Thanks to Sridhar Ratnakumar for triggering.  |   files").  Thanks to Sridhar Ratnakumar for triggering.  | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -75,7 +75,7 @@ class DSession(Session): | ||||||
|         self.setup() |         self.setup() | ||||||
|         exitstatus = self.loop(colitems) |         exitstatus = self.loop(colitems) | ||||||
|         self.teardown() |         self.teardown() | ||||||
|         self.sessionfinishes()  |         self.sessionfinishes(exitstatus=exitstatus)  | ||||||
|         return exitstatus |         return exitstatus | ||||||
| 
 | 
 | ||||||
|     def loop_once(self, loopstate): |     def loop_once(self, loopstate): | ||||||
|  |  | ||||||
|  | @ -94,11 +94,11 @@ def pytest_runtest_logreport(rep): | ||||||
| def pytest_sessionstart(session): | def pytest_sessionstart(session): | ||||||
|     """ before session.main() is called. """ |     """ before session.main() is called. """ | ||||||
| 
 | 
 | ||||||
| def pytest_sessionfinish(session, exitstatus, excrepr=None): | def pytest_sessionfinish(session, exitstatus): | ||||||
|     """ whole test run finishes. """ |     """ whole test run finishes. """ | ||||||
| 
 | 
 | ||||||
| # ------------------------------------------------------------------------- | # ------------------------------------------------------------------------- | ||||||
| # generic reporting hooks (invoked from pytest_terminal) | # hooks for influencing reporting (invoked from pytest_terminal) | ||||||
| # ------------------------------------------------------------------------- | # ------------------------------------------------------------------------- | ||||||
| 
 | 
 | ||||||
| def pytest_report_teststatus(rep): | def pytest_report_teststatus(rep): | ||||||
|  | @ -140,7 +140,7 @@ def pytest_looponfailinfo(failreports, rootdirs): | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| # ------------------------------------------------------------------------- | # ------------------------------------------------------------------------- | ||||||
| # internal debugging hooks  | # error handling and internal debugging hooks  | ||||||
| # ------------------------------------------------------------------------- | # ------------------------------------------------------------------------- | ||||||
| 
 | 
 | ||||||
| def pytest_plugin_registered(plugin): | def pytest_plugin_registered(plugin): | ||||||
|  | @ -152,5 +152,8 @@ def pytest_plugin_unregistered(plugin): | ||||||
| def pytest_internalerror(excrepr): | def pytest_internalerror(excrepr): | ||||||
|     """ called for internal errors. """ |     """ called for internal errors. """ | ||||||
| 
 | 
 | ||||||
|  | def pytest_keyboard_interrupt(excinfo): | ||||||
|  |     """ called for keyboard interrupt. """ | ||||||
|  | 
 | ||||||
| def pytest_trace(category, msg): | def pytest_trace(category, msg): | ||||||
|     """ called for debug info. """  |     """ called for debug info. """  | ||||||
|  |  | ||||||
|  | @ -24,7 +24,7 @@ class Execnetcleanup: | ||||||
|     def pytest_sessionstart(self, session): |     def pytest_sessionstart(self, session): | ||||||
|         self._gateways = [] |         self._gateways = [] | ||||||
| 
 | 
 | ||||||
|     def pytest_sessionfinish(self, session, exitstatus, excrepr=None): |     def pytest_sessionfinish(self, session, exitstatus): | ||||||
|         l = [] |         l = [] | ||||||
|         for gw in self._gateways: |         for gw in self._gateways: | ||||||
|             gw.exit() |             gw.exit() | ||||||
|  |  | ||||||
|  | @ -19,11 +19,10 @@ def pytest_addoption(parser): | ||||||
| def pytest_configure(config): | def pytest_configure(config): | ||||||
|     config._setupstate = SetupState() |     config._setupstate = SetupState() | ||||||
| 
 | 
 | ||||||
| def pytest_sessionfinish(session, exitstatus, excrepr=None): | def pytest_sessionfinish(session, exitstatus): | ||||||
|     # XXX see above |     # XXX see above | ||||||
|     if hasattr(session.config, '_setupstate'): |     if hasattr(session.config, '_setupstate'): | ||||||
|         session.config._setupstate.teardown_all() |         session.config._setupstate.teardown_all() | ||||||
| 
 |  | ||||||
|     # prevent logging module atexit handler from choking on  |     # prevent logging module atexit handler from choking on  | ||||||
|     # its attempt to close already closed streams  |     # its attempt to close already closed streams  | ||||||
|     # see http://bugs.python.org/issue6333 |     # see http://bugs.python.org/issue6333 | ||||||
|  |  | ||||||
|  | @ -231,20 +231,29 @@ class TerminalReporter: | ||||||
|         for i, testarg in py.builtin.enumerate(self.config.args): |         for i, testarg in py.builtin.enumerate(self.config.args): | ||||||
|             self.write_line("test object %d: %s" %(i+1, testarg)) |             self.write_line("test object %d: %s" %(i+1, testarg)) | ||||||
| 
 | 
 | ||||||
|     def pytest_sessionfinish(self, __call__, session, exitstatus, excrepr=None): |     def pytest_sessionfinish(self, __call__, session, exitstatus): | ||||||
|         __call__.execute()  |         __call__.execute()  | ||||||
|         self._tw.line("") |         self._tw.line("") | ||||||
|         if exitstatus in (0, 1, 2): |         if exitstatus in (0, 1, 2): | ||||||
|             self.summary_failures() |             self.summary_failures() | ||||||
|             self.summary_skips() |             self.summary_skips() | ||||||
|             self.config.hook.pytest_terminal_summary(terminalreporter=self) |             self.config.hook.pytest_terminal_summary(terminalreporter=self) | ||||||
|         if excrepr is not None: |  | ||||||
|             self.summary_final_exc(excrepr) |  | ||||||
|         if exitstatus == 2: |         if exitstatus == 2: | ||||||
|             self.write_sep("!", "KEYBOARD INTERRUPT") |             self._report_keyboardinterrupt() | ||||||
|         self.summary_deselected() |         self.summary_deselected() | ||||||
|         self.summary_stats() |         self.summary_stats() | ||||||
| 
 | 
 | ||||||
|  |     def pytest_keyboard_interrupt(self, excinfo): | ||||||
|  |         self._keyboardinterrupt_memo = excinfo.getrepr() | ||||||
|  | 
 | ||||||
|  |     def _report_keyboardinterrupt(self): | ||||||
|  |         self.write_sep("!", "KEYBOARD INTERRUPT") | ||||||
|  |         excrepr = self._keyboardinterrupt_memo | ||||||
|  |         if self.config.option.verbose: | ||||||
|  |             excrepr.toterminal(self._tw) | ||||||
|  |         else: | ||||||
|  |             excrepr.reprcrash.toterminal(self._tw) | ||||||
|  | 
 | ||||||
|     def pytest_looponfailinfo(self, failreports, rootdirs): |     def pytest_looponfailinfo(self, failreports, rootdirs): | ||||||
|         if failreports: |         if failreports: | ||||||
|             self.write_sep("#", "LOOPONFAILING", red=True) |             self.write_sep("#", "LOOPONFAILING", red=True) | ||||||
|  | @ -334,14 +343,6 @@ class TerminalReporter: | ||||||
|                     for num, fspath, lineno, reason in fskips: |                     for num, fspath, lineno, reason in fskips: | ||||||
|                         self._tw.line("%s:%d: [%d] %s" %(fspath, lineno, num, reason)) |                         self._tw.line("%s:%d: [%d] %s" %(fspath, lineno, num, reason)) | ||||||
| 
 | 
 | ||||||
|     def summary_final_exc(self, excrepr): |  | ||||||
|         self.write_sep("!") |  | ||||||
|         if self.config.option.verbose: |  | ||||||
|             excrepr.toterminal(self._tw) |  | ||||||
|         else: |  | ||||||
|             excrepr.reprcrash.toterminal(self._tw) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| class CollectonlyReporter: | class CollectonlyReporter: | ||||||
|     INDENT = "  " |     INDENT = "  " | ||||||
| 
 | 
 | ||||||
|  | @ -373,7 +374,7 @@ class CollectonlyReporter: | ||||||
|             self._failed.append(rep) |             self._failed.append(rep) | ||||||
|         self.indent = self.indent[:-len(self.INDENT)] |         self.indent = self.indent[:-len(self.INDENT)] | ||||||
| 
 | 
 | ||||||
|     def pytest_sessionfinish(self, session, exitstatus, excrepr=None): |     def pytest_sessionfinish(self, session, exitstatus): | ||||||
|         if self._failed: |         if self._failed: | ||||||
|             self.out.sep("!", "collection failures") |             self.out.sep("!", "collection failures") | ||||||
|         for rep in self._failed: |         for rep in self._failed: | ||||||
|  |  | ||||||
|  | @ -86,12 +86,11 @@ class Session(object): | ||||||
|                 self.shouldstop = True |                 self.shouldstop = True | ||||||
|     pytest_collectreport = pytest_runtest_logreport |     pytest_collectreport = pytest_runtest_logreport | ||||||
| 
 | 
 | ||||||
|     def sessionfinishes(self, exitstatus=0, excinfo=None): |     def sessionfinishes(self, exitstatus): | ||||||
|         """ teardown any resources after a test run. """  |         """ teardown any resources after a test run. """  | ||||||
|         self.config.hook.pytest_sessionfinish( |         self.config.hook.pytest_sessionfinish( | ||||||
|             session=self,  |             session=self,  | ||||||
|             exitstatus=exitstatus,  |             exitstatus=exitstatus,  | ||||||
|             excrepr=excinfo and excinfo.getrepr() or None |  | ||||||
|         ) |         ) | ||||||
| 
 | 
 | ||||||
|     def getinitialitems(self, colitems): |     def getinitialitems(self, colitems): | ||||||
|  | @ -114,13 +113,14 @@ class Session(object): | ||||||
|                 if not self.config.option.collectonly:  |                 if not self.config.option.collectonly:  | ||||||
|                     item.config.hook.pytest_runtest_protocol(item=item) |                     item.config.hook.pytest_runtest_protocol(item=item) | ||||||
|         except KeyboardInterrupt: |         except KeyboardInterrupt: | ||||||
|             captured_excinfo = py.code.ExceptionInfo() |             excinfo = py.code.ExceptionInfo() | ||||||
|  |             item.config.hook.pytest_keyboard_interrupt(excinfo=excinfo) | ||||||
|             exitstatus = outcome.EXIT_INTERRUPTED |             exitstatus = outcome.EXIT_INTERRUPTED | ||||||
|         except: |         except: | ||||||
|             captured_excinfo = py.code.ExceptionInfo() |             excinfo = py.code.ExceptionInfo() | ||||||
|             self.config.pluginmanager.notify_exception(captured_excinfo) |             self.config.pluginmanager.notify_exception(captured_excinfo) | ||||||
|             exitstatus = outcome.EXIT_INTERNALERROR |             exitstatus = outcome.EXIT_INTERNALERROR | ||||||
|         if exitstatus == 0 and self._testsfailed: |         if exitstatus == 0 and self._testsfailed: | ||||||
|             exitstatus = outcome.EXIT_TESTSFAILED |             exitstatus = outcome.EXIT_TESTSFAILED | ||||||
|         self.sessionfinishes(exitstatus=exitstatus, excinfo=captured_excinfo) |         self.sessionfinishes(exitstatus=exitstatus) | ||||||
|         return exitstatus |         return exitstatus | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue