merge PR192, streamline a bit.
This commit is contained in:
		
						commit
						d16fdb378c
					
				|  | @ -3,6 +3,10 @@ NEXT | |||
| 
 | ||||
| - No longer show line numbers in the --verbose output, the output is now | ||||
|   purely the nodeid.  The line number is still shown in failure reports. | ||||
|   Thanks Floris Bruynooghe. | ||||
| 
 | ||||
| - fix issue437 where assertion rewriting could cause pytest-xdist slaves | ||||
|   to collect different tests. Thanks Bruno Oliveira. | ||||
| 
 | ||||
| - fix issue547 capsys/capfd also work when output capturing ("-s") is disabled. | ||||
| 
 | ||||
|  |  | |||
|  | @ -131,7 +131,7 @@ class AssertionRewritingHook(object): | |||
|         pyc = os.path.join(cache_dir, cache_name) | ||||
|         # Notice that even if we're in a read-only directory, I'm going | ||||
|         # to check for a cached pyc. This may not be optimal... | ||||
|         co = _read_pyc(fn_pypath, pyc) | ||||
|         co = _read_pyc(fn_pypath, pyc, state.trace) | ||||
|         if co is None: | ||||
|             state.trace("rewriting %r" % (fn,)) | ||||
|             co = _rewrite_test(state, fn_pypath) | ||||
|  | @ -289,7 +289,7 @@ def _make_rewritten_pyc(state, fn, pyc, co): | |||
|         if _write_pyc(state, co, fn, proc_pyc): | ||||
|             os.rename(proc_pyc, pyc) | ||||
| 
 | ||||
| def _read_pyc(source, pyc): | ||||
| def _read_pyc(source, pyc, trace=lambda x: None): | ||||
|     """Possibly read a pytest pyc containing rewritten code. | ||||
| 
 | ||||
|     Return rewritten code if successful or None if not. | ||||
|  | @ -298,23 +298,27 @@ def _read_pyc(source, pyc): | |||
|         fp = open(pyc, "rb") | ||||
|     except IOError: | ||||
|         return None | ||||
|     try: | ||||
|     with fp: | ||||
|         try: | ||||
|             mtime = int(source.mtime()) | ||||
|             data = fp.read(8) | ||||
|         except EnvironmentError: | ||||
|         except EnvironmentError as e: | ||||
|             trace('_read_pyc(%s): EnvironmentError %s' % (source, e)) | ||||
|             return None | ||||
|         # Check for invalid or out of date pyc file. | ||||
|         if (len(data) != 8 or data[:4] != imp.get_magic() or | ||||
|                 struct.unpack("<l", data[4:])[0] != mtime): | ||||
|             trace('_read_pyc(%s): invalid or out of date pyc' % source) | ||||
|             return None | ||||
|         try: | ||||
|             co = marshal.load(fp) | ||||
|         except Exception as e: | ||||
|             trace('_read_pyc(%s): marshal.load error %s' % (source, e)) | ||||
|             return None | ||||
|         if not isinstance(co, types.CodeType): | ||||
|             # That's interesting.... | ||||
|             trace('_read_pyc(%s): not a code object' % source) | ||||
|             return None | ||||
|         return co | ||||
|     finally: | ||||
|         fp.close() | ||||
| 
 | ||||
| 
 | ||||
| def rewrite_asserts(mod): | ||||
|  |  | |||
|  | @ -539,3 +539,25 @@ class TestAssertionRewriteHookDetails(object): | |||
|         result.stdout.fnmatch_lines([ | ||||
|             '* 1 passed*', | ||||
|         ]) | ||||
| 
 | ||||
|     def test_read_pyc(self, tmpdir): | ||||
|         """ | ||||
|         Ensure that the `_read_pyc` can properly deal with corrupted pyc files. | ||||
|         In those circumstances it should just give up instead of generating | ||||
|         an exception that is propagated to the caller. | ||||
|         """ | ||||
|         import py_compile | ||||
|         from _pytest.assertion.rewrite import _read_pyc | ||||
| 
 | ||||
|         source = tmpdir.join('source.py') | ||||
|         pyc = source + 'c' | ||||
| 
 | ||||
|         source.write('def test(): pass') | ||||
|         py_compile.compile(str(source), str(pyc)) | ||||
| 
 | ||||
|         contents = pyc.read(mode='rb') | ||||
|         strip_bytes = 20  # header is around 8 bytes, strip a little more | ||||
|         assert len(contents) > strip_bytes | ||||
|         pyc.write(contents[:strip_bytes], mode='wb') | ||||
| 
 | ||||
|         assert _read_pyc(source, str(pyc)) is None  # no error | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue