move the old assertion reinterpreting implementation to _assertionold.py
Also, seperate out some common code from the two. --HG-- branch : trunk
This commit is contained in:
		
							parent
							
								
									130046d245
								
							
						
					
					
						commit
						e596d9df13
					
				|  | @ -133,7 +133,7 @@ initpkg(__name__, | ||||||
|     'code.getrawcode'        : ('./code/code.py', 'getrawcode'), |     'code.getrawcode'        : ('./code/code.py', 'getrawcode'), | ||||||
|     'code.patch_builtins'    : ('./code/code.py', 'patch_builtins'), |     'code.patch_builtins'    : ('./code/code.py', 'patch_builtins'), | ||||||
|     'code.unpatch_builtins'  : ('./code/code.py', 'unpatch_builtins'), |     'code.unpatch_builtins'  : ('./code/code.py', 'unpatch_builtins'), | ||||||
|     'code._AssertionError'   : ('./code/_assertion.py', 'AssertionError'), |     'code._AssertionError'   : ('./code/assertion.py', 'AssertionError'), | ||||||
| 
 | 
 | ||||||
|     # backports and additions of builtins |     # backports and additions of builtins | ||||||
|     'builtin.__doc__'        : ('./builtin/__init__.py', '__doc__'), |     'builtin.__doc__'        : ('./builtin/__init__.py', '__doc__'), | ||||||
|  |  | ||||||
|  | @ -7,7 +7,7 @@ import sys | ||||||
| import ast | import ast | ||||||
| 
 | 
 | ||||||
| import py | import py | ||||||
| from py.__.code._assertion import _format_explanation, BuiltinAssertionError | from py.__.code.assertion import _format_explanation, BuiltinAssertionError | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class Failure(Exception): | class Failure(Exception): | ||||||
|  | @ -40,6 +40,8 @@ def getfailure(failure): | ||||||
|     value = failure.cause[1] |     value = failure.cause[1] | ||||||
|     if str(value): |     if str(value): | ||||||
|         lines = explanation.splitlines() |         lines = explanation.splitlines() | ||||||
|  |         if not lines: | ||||||
|  |             lines.append("") | ||||||
|         lines[0] += " << {0}".format(value) |         lines[0] += " << {0}".format(value) | ||||||
|         explanation = "\n".join(lines) |         explanation = "\n".join(lines) | ||||||
|     text = "{0}: {1}".format(failure.cause[0].__name__, explanation) |     text = "{0}: {1}".format(failure.cause[0].__name__, explanation) | ||||||
|  | @ -97,7 +99,7 @@ class DebugInterpreter(ast.NodeVisitor): | ||||||
|             mod = ast.Module([node]) |             mod = ast.Module([node]) | ||||||
|             co = self._compile(mod, "exec") |             co = self._compile(mod, "exec") | ||||||
|             try: |             try: | ||||||
|                 frame.exec_(co) |                 self.frame.exec_(co) | ||||||
|             except Exception: |             except Exception: | ||||||
|                 raise Failure() |                 raise Failure() | ||||||
|             return None, None |             return None, None | ||||||
|  | @ -107,6 +109,9 @@ class DebugInterpreter(ast.NodeVisitor): | ||||||
|     def _compile(self, source, mode="eval"): |     def _compile(self, source, mode="eval"): | ||||||
|         return compile(source, "<assertion interpretation>", mode) |         return compile(source, "<assertion interpretation>", mode) | ||||||
| 
 | 
 | ||||||
|  |     def visit_Expr(self, expr): | ||||||
|  |         return self.visit(expr.value) | ||||||
|  | 
 | ||||||
|     def visit_Module(self, mod): |     def visit_Module(self, mod): | ||||||
|         for stmt in mod.body: |         for stmt in mod.body: | ||||||
|             self.visit(stmt) |             self.visit(stmt) | ||||||
|  | @ -175,8 +180,8 @@ class DebugInterpreter(ast.NodeVisitor): | ||||||
|         left_explanation, left_result = self.visit(binop.left) |         left_explanation, left_result = self.visit(binop.left) | ||||||
|         right_explanation, right_result = self.visit(binop.right) |         right_explanation, right_result = self.visit(binop.right) | ||||||
|         symbol = operator_map[binop.op.__class__] |         symbol = operator_map[binop.op.__class__] | ||||||
|         explanation = "{0} {1} {2}".format(left_explanation, symbol, |         explanation = "({0} {1} {2})".format(left_explanation, symbol, | ||||||
|                                            right_explanation) |                                              right_explanation) | ||||||
|         source = "__exprinfo_left {0} __exprinfo_right".format(symbol) |         source = "__exprinfo_left {0} __exprinfo_right".format(symbol) | ||||||
|         co = self._compile(source) |         co = self._compile(source) | ||||||
|         try: |         try: | ||||||
|  |  | ||||||
|  | @ -1,8 +1,7 @@ | ||||||
| import py | import py | ||||||
| import sys, inspect | import sys, inspect | ||||||
| from compiler import parse, ast, pycodegen | from compiler import parse, ast, pycodegen | ||||||
| import __builtin__ as cpy_builtin | from py.__.code.assertion import BuiltinAssertionError, _format_explanation | ||||||
| BuiltinAssertionError = cpy_builtin.AssertionError |  | ||||||
| 
 | 
 | ||||||
| passthroughex = (KeyboardInterrupt, SystemExit, MemoryError) | passthroughex = (KeyboardInterrupt, SystemExit, MemoryError) | ||||||
| 
 | 
 | ||||||
|  | @ -97,42 +96,6 @@ def enumsubclasses(cls): | ||||||
|     yield cls |     yield cls | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| def _format_explanation(explanation): |  | ||||||
|     # uck!  See CallFunc for where \n{ and \n} escape sequences are used |  | ||||||
|     raw_lines = (explanation or '').split('\n') |  | ||||||
|     # escape newlines not followed by { and } |  | ||||||
|     lines = [raw_lines[0]] |  | ||||||
|     for l in raw_lines[1:]: |  | ||||||
|         if l.startswith('{') or l.startswith('}'): |  | ||||||
|             lines.append(l) |  | ||||||
|         else: |  | ||||||
|             lines[-1] += '\\n' + l |  | ||||||
| 
 |  | ||||||
|     result = lines[:1] |  | ||||||
|     stack = [0] |  | ||||||
|     stackcnt = [0] |  | ||||||
|     for line in lines[1:]: |  | ||||||
|         if line.startswith('{'): |  | ||||||
|             if stackcnt[-1]: |  | ||||||
|                 s = 'and   ' |  | ||||||
|             else: |  | ||||||
|                 s = 'where ' |  | ||||||
|             stack.append(len(result)) |  | ||||||
|             stackcnt[-1] += 1 |  | ||||||
|             stackcnt.append(0) |  | ||||||
|             result.append(' +' + '  '*(len(stack)-1) + s + line[1:]) |  | ||||||
|         else: |  | ||||||
|             assert line.startswith('}') |  | ||||||
|             stack.pop() |  | ||||||
|             stackcnt.pop() |  | ||||||
|             result[stack[-1]] += line[1:] |  | ||||||
|     assert len(stack) == 1 |  | ||||||
|     return '\n'.join(result) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| class Interpretable(View): | class Interpretable(View): | ||||||
|     """A parse tree node with a few extra methods.""" |     """A parse tree node with a few extra methods.""" | ||||||
|     explanation = None |     explanation = None | ||||||
|  | @ -566,39 +529,6 @@ def run(s, frame=None): | ||||||
|         report_failure(e) |         report_failure(e) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class AssertionError(BuiltinAssertionError): |  | ||||||
|     def __init__(self, *args): |  | ||||||
|         BuiltinAssertionError.__init__(self, *args) |  | ||||||
|         if args:  |  | ||||||
|             try: |  | ||||||
|                 self.msg = str(args[0]) |  | ||||||
|             except (KeyboardInterrupt, SystemExit): |  | ||||||
|                 raise |  | ||||||
|             except: |  | ||||||
|                 self.msg = "<[broken __repr__] %s at %0xd>" %( |  | ||||||
|                     args[0].__class__, id(args[0])) |  | ||||||
|              |  | ||||||
|         else:  |  | ||||||
|             f = py.code.Frame(sys._getframe(1)) |  | ||||||
|             try: |  | ||||||
|                 source = f.statement |  | ||||||
|                 source = str(source.deindent()).strip() |  | ||||||
|             except py.error.ENOENT: |  | ||||||
|                 source = None |  | ||||||
|                 # this can also occur during reinterpretation, when the |  | ||||||
|                 # co_filename is set to "<run>". |  | ||||||
|             if source: |  | ||||||
|                 if sys.version_info >= (2, 6): |  | ||||||
|                     from py.__.code._assertionnew import interpret as do_interp |  | ||||||
|                 else: |  | ||||||
|                     do_interp = interpret |  | ||||||
|                 self.msg = do_interp(source, f, should_fail=True) |  | ||||||
|                 if not self.args: |  | ||||||
|                     self.args = (self.msg,) |  | ||||||
|             else: |  | ||||||
|                 self.msg = None |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| if __name__ == '__main__': | if __name__ == '__main__': | ||||||
|     # example: |     # example: | ||||||
|     def f(): |     def f(): | ||||||
|  | @ -0,0 +1,76 @@ | ||||||
|  | try: | ||||||
|  |     import __builtin__ as builtins | ||||||
|  | except ImportError: | ||||||
|  |     import builtins | ||||||
|  | import sys | ||||||
|  | import py | ||||||
|  | 
 | ||||||
|  | BuiltinAssertionError = builtins.AssertionError | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def _format_explanation(explanation): | ||||||
|  |     # uck!  See CallFunc for where \n{ and \n} escape sequences are used | ||||||
|  |     raw_lines = (explanation or '').split('\n') | ||||||
|  |     # escape newlines not followed by { and } | ||||||
|  |     lines = [raw_lines[0]] | ||||||
|  |     for l in raw_lines[1:]: | ||||||
|  |         if l.startswith('{') or l.startswith('}'): | ||||||
|  |             lines.append(l) | ||||||
|  |         else: | ||||||
|  |             lines[-1] += '\\n' + l | ||||||
|  | 
 | ||||||
|  |     result = lines[:1] | ||||||
|  |     stack = [0] | ||||||
|  |     stackcnt = [0] | ||||||
|  |     for line in lines[1:]: | ||||||
|  |         if line.startswith('{'): | ||||||
|  |             if stackcnt[-1]: | ||||||
|  |                 s = 'and   ' | ||||||
|  |             else: | ||||||
|  |                 s = 'where ' | ||||||
|  |             stack.append(len(result)) | ||||||
|  |             stackcnt[-1] += 1 | ||||||
|  |             stackcnt.append(0) | ||||||
|  |             result.append(' +' + '  '*(len(stack)-1) + s + line[1:]) | ||||||
|  |         else: | ||||||
|  |             assert line.startswith('}') | ||||||
|  |             stack.pop() | ||||||
|  |             stackcnt.pop() | ||||||
|  |             result[stack[-1]] += line[1:] | ||||||
|  |     assert len(stack) == 1 | ||||||
|  |     return '\n'.join(result) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | if sys.version_info >= (2, 6): | ||||||
|  |     from py.__.code._assertionnew import interpret | ||||||
|  | else: | ||||||
|  |     from py.__.code._assertionold import interpret | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class AssertionError(BuiltinAssertionError): | ||||||
|  | 
 | ||||||
|  |     def __init__(self, *args): | ||||||
|  |         BuiltinAssertionError.__init__(self, *args) | ||||||
|  |         if args: | ||||||
|  |             try: | ||||||
|  |                 self.msg = str(args[0]) | ||||||
|  |             except (KeyboardInterrupt, SystemExit): | ||||||
|  |                 raise | ||||||
|  |             except: | ||||||
|  |                 self.msg = "<[broken __repr__] %s at %0xd>" %( | ||||||
|  |                     args[0].__class__, id(args[0])) | ||||||
|  |         else: | ||||||
|  |             f = py.code.Frame(sys._getframe(1)) | ||||||
|  |             try: | ||||||
|  |                 source = f.statement | ||||||
|  |                 source = str(source.deindent()).strip() | ||||||
|  |             except py.error.ENOENT: | ||||||
|  |                 source = None | ||||||
|  |                 # this can also occur during reinterpretation, when the | ||||||
|  |                 # co_filename is set to "<run>". | ||||||
|  |             if source: | ||||||
|  |                 self.msg = interpret(source, f, should_fail=True) | ||||||
|  |                 if not self.args: | ||||||
|  |                     self.args = (self.msg,) | ||||||
|  |             else: | ||||||
|  |                 self.msg = None | ||||||
|  | @ -197,9 +197,9 @@ class TracebackEntry(object): | ||||||
|         """Reinterpret the failing statement and returns a detailed information |         """Reinterpret the failing statement and returns a detailed information | ||||||
|            about what operations are performed.""" |            about what operations are performed.""" | ||||||
|         if self.exprinfo is None: |         if self.exprinfo is None: | ||||||
|             from py.__.code import _assertion  |             from py.__.code import assertion  | ||||||
|             source = str(self.statement).strip() |             source = str(self.statement).strip() | ||||||
|             x = _assertion.interpret(source, self.frame, should_fail=True) |             x = assertion.interpret(source, self.frame, should_fail=True) | ||||||
|             if not isinstance(x, str): |             if not isinstance(x, str): | ||||||
|                 raise TypeError("interpret returned non-string %r" % (x,)) |                 raise TypeError("interpret returned non-string %r" % (x,)) | ||||||
|             self.exprinfo = x  |             self.exprinfo = x  | ||||||
|  | @ -739,10 +739,10 @@ oldbuiltins = {} | ||||||
| def patch_builtins(assertion=True, compile=True): | def patch_builtins(assertion=True, compile=True): | ||||||
|     """ put compile and AssertionError builtins to Python's builtins. """ |     """ put compile and AssertionError builtins to Python's builtins. """ | ||||||
|     if assertion: |     if assertion: | ||||||
|         from py.__.code import _assertion |         from py.__.code import assertion | ||||||
|         l = oldbuiltins.setdefault('AssertionError', []) |         l = oldbuiltins.setdefault('AssertionError', []) | ||||||
|         l.append(py.builtin.builtins.AssertionError) |         l.append(py.builtin.builtins.AssertionError) | ||||||
|         py.builtin.builtins.AssertionError = _assertion.AssertionError |         py.builtin.builtins.AssertionError = assertion.AssertionError | ||||||
|     if compile:  |     if compile:  | ||||||
|         l = oldbuiltins.setdefault('compile', []) |         l = oldbuiltins.setdefault('compile', []) | ||||||
|         l.append(py.builtin.builtins.compile) |         l.append(py.builtin.builtins.compile) | ||||||
|  |  | ||||||
|  | @ -1,5 +1,5 @@ | ||||||
| import py | import py | ||||||
| from py.__.code._assertion import View | from py.__.code._assertionold import View | ||||||
| def exvalue(): | def exvalue(): | ||||||
|     return py.std.sys.exc_info()[1] |     return py.std.sys.exc_info()[1] | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue