[svn r63797] introduce a clean "guardedcall" interface for performing calls with exception catching and stdout/stderr capturing
--HG-- branch : trunk
This commit is contained in:
		
							parent
							
								
									4893c58d22
								
							
						
					
					
						commit
						bba69f207b
					
				|  | @ -286,6 +286,28 @@ class Config(object): | ||||||
|             roots.append(pydir) |             roots.append(pydir) | ||||||
|         return roots  |         return roots  | ||||||
| 
 | 
 | ||||||
|  |     def guardedcall(self, func): | ||||||
|  |         excinfo = result = None | ||||||
|  |         capture = self._getcapture() | ||||||
|  |         try: | ||||||
|  |             try: | ||||||
|  |                 result = func() | ||||||
|  |             except KeyboardInterrupt: | ||||||
|  |                 raise | ||||||
|  |             except: | ||||||
|  |                 excinfo = py.code.ExceptionInfo() | ||||||
|  |         finally: | ||||||
|  |             stdout, stderr = capture.reset() | ||||||
|  |         return CallResult(result, excinfo, stdout, stderr) | ||||||
|  | 
 | ||||||
|  | class CallResult: | ||||||
|  |     def __init__(self, result, excinfo, stdout, stderr): | ||||||
|  |         self.stdout = stdout  | ||||||
|  |         self.stderr = stderr | ||||||
|  |         self.outerr = (self.stdout, self.stderr) | ||||||
|  |         self.excinfo = excinfo | ||||||
|  |         if excinfo is None: | ||||||
|  |             self.result = result  | ||||||
|      |      | ||||||
| # | # | ||||||
| # helpers | # helpers | ||||||
|  |  | ||||||
|  | @ -198,41 +198,22 @@ class SetupState(object): | ||||||
|             self.stack.append(col)  |             self.stack.append(col)  | ||||||
| 
 | 
 | ||||||
|     def do_setup(self, item): |     def do_setup(self, item): | ||||||
|         excinfo, outerr = guarded_call(item.config._getcapture(),  |         call = item.config.guardedcall(lambda: self.prepare(item)) | ||||||
|                 lambda: self.prepare(item) |         rep = ItemSetupReport(item, call.excinfo, call.outerr) | ||||||
|         ) |  | ||||||
|         rep = ItemSetupReport(item, excinfo, outerr) |  | ||||||
|         item.config.pytestplugins.notify("itemsetupreport", rep) |         item.config.pytestplugins.notify("itemsetupreport", rep) | ||||||
|         return not excinfo  |         return not call.excinfo  | ||||||
| 
 | 
 | ||||||
|     def do_teardown(self, item): |     def do_teardown(self, item): | ||||||
|         excinfo, outerr = guarded_call(item.config._getcapture(),  |         call = item.config.guardedcall(lambda: self.teardown_exact(item)) | ||||||
|                 lambda: self.teardown_exact(item) |         if call.excinfo: | ||||||
|         ) |             rep = ItemSetupReport(item, call.excinfo, call.outerr) | ||||||
|         if excinfo: |  | ||||||
|             rep = ItemSetupReport(item, excinfo, outerr) |  | ||||||
|             item.config.pytestplugins.notify("itemsetupreport", rep) |             item.config.pytestplugins.notify("itemsetupreport", rep) | ||||||
| 
 | 
 | ||||||
|     def do_fixture_and_runtest(self, item): |     def do_fixture_and_runtest(self, item): | ||||||
|         """ setup fixture and perform actual item.runtest(). """ |         """ setup fixture and perform actual item.runtest(). """ | ||||||
|         if self.do_setup(item): |         if self.do_setup(item): | ||||||
|             excinfo, outerr = guarded_call(item.config._getcapture(),  |             call = item.config.guardedcall(lambda: item.runtest()) | ||||||
|                    lambda: item.runtest()) |  | ||||||
|             item.config.pytestplugins.notify( |             item.config.pytestplugins.notify( | ||||||
|                 "item_runtest_finished",  |                 "item_runtest_finished",  | ||||||
|                 item=item, excinfo=excinfo, outerr=outerr) |                 item=item, excinfo=call.excinfo, outerr=call.outerr) | ||||||
|             self.do_teardown(item) |             self.do_teardown(item) | ||||||
| 
 |  | ||||||
| def guarded_call(capture, call): |  | ||||||
|     excinfo = None |  | ||||||
|     try: |  | ||||||
|         try: |  | ||||||
|             call() |  | ||||||
|         except (KeyboardInterrupt, Exit): |  | ||||||
|             raise |  | ||||||
|         except: |  | ||||||
|             excinfo = py.code.ExceptionInfo() |  | ||||||
|     finally: |  | ||||||
|         outerr = capture.reset() |  | ||||||
|     return excinfo, outerr  |  | ||||||
| 
 |  | ||||||
|  |  | ||||||
|  | @ -137,8 +137,7 @@ class TestConfigAPI: | ||||||
|         assert pl[1] == somepath |         assert pl[1] == somepath | ||||||
| 
 | 
 | ||||||
|     def test_setsessionclass_and_initsession(self, testdir): |     def test_setsessionclass_and_initsession(self, testdir): | ||||||
|         from py.__.test.config import Config  |         config = testdir.Config() | ||||||
|         config = Config() |  | ||||||
|         class Session1:  |         class Session1:  | ||||||
|             def __init__(self, config): |             def __init__(self, config): | ||||||
|                 self.config = config  |                 self.config = config  | ||||||
|  | @ -149,7 +148,6 @@ class TestConfigAPI: | ||||||
|         py.test.raises(ValueError, "config.setsessionclass(Session1)") |         py.test.raises(ValueError, "config.setsessionclass(Session1)") | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| class TestConfigApi_getcolitems: | class TestConfigApi_getcolitems: | ||||||
|     def test_getcolitems_onedir(self, tmpdir): |     def test_getcolitems_onedir(self, tmpdir): | ||||||
|         config = py.test.config._reparse([tmpdir]) |         config = py.test.config._reparse([tmpdir]) | ||||||
|  | @ -214,6 +212,37 @@ class TestConfigApi_getcolitems: | ||||||
|             assert col.config is config  |             assert col.config is config  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | class TestGuardedCall: | ||||||
|  |     def test_guardedcall_ok(self, testdir): | ||||||
|  |         config = testdir.parseconfig() | ||||||
|  |         def myfunc(x): | ||||||
|  |             print x | ||||||
|  |             print >>py.std.sys.stderr, "hello" | ||||||
|  |             return 7 | ||||||
|  |         call = config.guardedcall(lambda: myfunc(3)) | ||||||
|  |         assert call.excinfo is None | ||||||
|  |         assert call.result == 7 | ||||||
|  |         assert call.stdout.startswith("3") | ||||||
|  |         assert call.stderr.startswith("hello") | ||||||
|  | 
 | ||||||
|  |     def test_guardedcall_fail(self, testdir): | ||||||
|  |         config = testdir.parseconfig() | ||||||
|  |         def myfunc(x): | ||||||
|  |             print x | ||||||
|  |             raise ValueError(17) | ||||||
|  |         call = config.guardedcall(lambda: myfunc(3)) | ||||||
|  |         assert call.excinfo  | ||||||
|  |         assert call.excinfo.type == ValueError  | ||||||
|  |         assert not hasattr(call, 'result') | ||||||
|  |         assert call.stdout.startswith("3") | ||||||
|  |         assert not call.stderr  | ||||||
|  | 
 | ||||||
|  |     def test_guardedcall_keyboardinterrupt(self, testdir): | ||||||
|  |         config = testdir.parseconfig() | ||||||
|  |         def myfunc(): | ||||||
|  |             raise KeyboardInterrupt | ||||||
|  |         py.test.raises(KeyboardInterrupt, config.guardedcall, myfunc) | ||||||
|  | 
 | ||||||
| class TestOptionEffects: | class TestOptionEffects: | ||||||
|     def test_boxed_option_default(self, testdir): |     def test_boxed_option_default(self, testdir): | ||||||
|         tmpdir = testdir.tmpdir.ensure("subdir", dir=1) |         tmpdir = testdir.tmpdir.ensure("subdir", dir=1) | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue