introduce resume/suspend functionality for FDCapture and SysCapture,
fixing problems with early bailouts (from argparse's parse() function e.g.) that wrote to stdout.
This commit is contained in:
		
							parent
							
								
									ca5e6830c6
								
							
						
					
					
						commit
						2e1f6c85f6
					
				|  | @ -46,13 +46,7 @@ def pytest_load_initial_conftests(early_config, parser, args, __multicall__): | ||||||
|     pluginmanager.register(capman, "capturemanager") |     pluginmanager.register(capman, "capturemanager") | ||||||
| 
 | 
 | ||||||
|     # make sure that capturemanager is properly reset at final shutdown |     # make sure that capturemanager is properly reset at final shutdown | ||||||
|     def teardown(): |     pluginmanager.add_shutdown(capman.reset_capturings) | ||||||
|         try: |  | ||||||
|             capman.reset_capturings() |  | ||||||
|         except ValueError: |  | ||||||
|             pass |  | ||||||
| 
 |  | ||||||
|     pluginmanager.add_shutdown(teardown) |  | ||||||
| 
 | 
 | ||||||
|     # make sure logging does not raise exceptions at the end |     # make sure logging does not raise exceptions at the end | ||||||
|     def silence_logging_at_shutdown(): |     def silence_logging_at_shutdown(): | ||||||
|  | @ -124,16 +118,18 @@ class CaptureManager: | ||||||
|             self._method2capture[method] = cap = self._getcapture(method) |             self._method2capture[method] = cap = self._getcapture(method) | ||||||
|             cap.start_capturing() |             cap.start_capturing() | ||||||
|         else: |         else: | ||||||
|             cap.pop_outerr_to_orig() |             cap.resume_capturing() | ||||||
| 
 | 
 | ||||||
|     def suspendcapture(self, item=None): |     def suspendcapture(self, item=None): | ||||||
|         self.deactivate_funcargs() |         self.deactivate_funcargs() | ||||||
|         method = self.__dict__.pop("_capturing", None) |         method = self.__dict__.pop("_capturing", None) | ||||||
|  |         outerr = "", "" | ||||||
|         if method is not None: |         if method is not None: | ||||||
|             cap = self._method2capture.get(method) |             cap = self._method2capture.get(method) | ||||||
|             if cap is not None: |             if cap is not None: | ||||||
|                 return cap.readouterr() |                 outerr = cap.readouterr() | ||||||
|         return "", "" |                 cap.suspend_capturing() | ||||||
|  |         return outerr | ||||||
| 
 | 
 | ||||||
|     def activate_funcargs(self, pyfuncitem): |     def activate_funcargs(self, pyfuncitem): | ||||||
|         capfuncarg = pyfuncitem.__dict__.pop("_capfuncarg", None) |         capfuncarg = pyfuncitem.__dict__.pop("_capfuncarg", None) | ||||||
|  | @ -316,6 +312,18 @@ class MultiCapture(object): | ||||||
|         if err: |         if err: | ||||||
|             self.err.writeorg(err) |             self.err.writeorg(err) | ||||||
| 
 | 
 | ||||||
|  |     def suspend_capturing(self): | ||||||
|  |         if self.out: | ||||||
|  |             self.out.suspend() | ||||||
|  |         if self.err: | ||||||
|  |             self.err.suspend() | ||||||
|  | 
 | ||||||
|  |     def resume_capturing(self): | ||||||
|  |         if self.out: | ||||||
|  |             self.out.resume() | ||||||
|  |         if self.err: | ||||||
|  |             self.err.resume() | ||||||
|  | 
 | ||||||
|     def stop_capturing(self): |     def stop_capturing(self): | ||||||
|         """ stop capturing and reset capturing streams """ |         """ stop capturing and reset capturing streams """ | ||||||
|         if hasattr(self, '_reset'): |         if hasattr(self, '_reset'): | ||||||
|  | @ -334,7 +342,7 @@ class MultiCapture(object): | ||||||
|                 self.err.snap() if self.err is not None else "") |                 self.err.snap() if self.err is not None else "") | ||||||
| 
 | 
 | ||||||
| class NoCapture: | class NoCapture: | ||||||
|     __init__ = start = done = lambda *args: None |     __init__ = start = done = suspend = resume = lambda *args: None | ||||||
| 
 | 
 | ||||||
| class FDCapture: | class FDCapture: | ||||||
|     """ Capture IO to/from a given os-level filedescriptor. """ |     """ Capture IO to/from a given os-level filedescriptor. """ | ||||||
|  |  | ||||||
|  | @ -335,6 +335,12 @@ class TestGeneralUsage: | ||||||
|         res = testdir.runpytest(p.basename) |         res = testdir.runpytest(p.basename) | ||||||
|         assert res.ret == 0 |         assert res.ret == 0 | ||||||
| 
 | 
 | ||||||
|  |     def test_unknown_option(self, testdir): | ||||||
|  |         result = testdir.runpytest("--qwlkej") | ||||||
|  |         result.stderr.fnmatch_lines(""" | ||||||
|  |             *unrecognized* | ||||||
|  |         """) | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| class TestInvocationVariants: | class TestInvocationVariants: | ||||||
|     def test_earlyinit(self, testdir): |     def test_earlyinit(self, testdir): | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue