[pypy-svn] r5353 - in pypy/trunk/src/pypy: interpreter interpreter/test objspace/flow
arigo at codespeak.net
arigo at codespeak.net
Sat Jun 26 14:49:22 CEST 2004
Author: arigo
Date: Sat Jun 26 14:47:07 2004
New Revision: 5353
Added:
pypy/trunk/src/pypy/interpreter/test/test_raise.py
- copied, changed from r5339, pypy/trunk/src/pypy/interpreter/test/test_interpreter.py
Modified:
pypy/trunk/src/pypy/interpreter/pyframe.py
pypy/trunk/src/pypy/interpreter/pyopcode.py
pypy/trunk/src/pypy/interpreter/test/test_interpreter.py
pypy/trunk/src/pypy/objspace/flow/specialcase.py
Log:
* Exceptions were still not right.
* Unified prepare_raise() and normalize_exception(), which looks better.
* Lots of tests. Moved them to a new test_raise, even.
Modified: pypy/trunk/src/pypy/interpreter/pyframe.py
==============================================================================
--- pypy/trunk/src/pypy/interpreter/pyframe.py (original)
+++ pypy/trunk/src/pypy/interpreter/pyframe.py Sat Jun 26 14:47:07 2004
@@ -152,8 +152,10 @@
if frame.space.full_exceptions:
w_normalized = normalize_exception(frame.space, w_type, w_value)
w_type, w_value = frame.space.unpacktuple(w_normalized, 2)
- # this is to make sure that sys.exc_info() etc see
- # normalized exception -- not sure here is best place!
+ # save the normalized exception back into the OperationError
+ # -- in particular it makes sure that sys.exc_info() etc see
+ # normalized exception.
+ operationerr.w_type = w_type
operationerr.w_value = w_value
# the stack setup is slightly different than in CPython:
# instead of the traceback, we store the unroller object,
@@ -165,25 +167,43 @@
return True # stop unrolling
return False
-def app_normalize_exception(etype, evalue):
- # XXX should really be defined as a method on OperationError,
- # but this is not so easy because OperationError cannot be
- # at the same time an old-style subclass of Exception and a
- # new-style subclass of Wrappable :-(
- # moreover, try importing gateway from errors.py and you'll see :-(
-
+def app_normalize_exception(etype, value):
+ """Normalize an (exc_type, exc_value) pair:
+ exc_value will be an exception instance and exc_type its class.
+ """
# mistakes here usually show up as infinite recursion, which is fun.
- if isinstance(evalue, etype):
- return etype, evalue
- if isinstance(etype, type) and issubclass(etype, Exception):
- if evalue is None:
- evalue = ()
- elif not isinstance(evalue, tuple):
- evalue = (evalue,)
- evalue = etype(*evalue)
+ while isinstance(etype, tuple):
+ etype = etype[0]
+ if isinstance(etype, type):
+ if not isinstance(value, etype):
+ if value is None:
+ # raise Type: we assume we have to instantiate Type
+ value = etype()
+ elif isinstance(value, tuple):
+ # raise Type, Tuple: assume Tuple contains the constructor args
+ value = etype(*value)
+ else:
+ # raise Type, X: assume X is the constructor argument
+ value = etype(value)
+ # raise Type, Instance: let etype be the exact type of value
+ etype = value.__class__
+ elif type(etype) is str:
+ # XXX warn -- deprecated
+ if value is not None and type(value) is not str:
+ raise TypeError("string exceptions can only have a string value")
else:
- raise Exception, "?!" # XXX
- return etype, evalue
+ # raise X: we assume that X is an already-built instance
+ if value is not None:
+ raise TypeError("instance exception may not have a separate value")
+ value = etype
+ etype = value.__class__
+ # for the sake of language consistency we should not allow
+ # things like 'raise 1', but it's probably fine (i.e.
+ # not ambiguous) to allow them in the explicit form 'raise int, 1'
+ if not hasattr(value, '__dict__') and not hasattr(value, '__slots__'):
+ raise TypeError("raising built-in objects can be ambiguous, "
+ "use 'raise type, value' instead")
+ return etype, value
normalize_exception = gateway.app2interp(app_normalize_exception)
Modified: pypy/trunk/src/pypy/interpreter/pyopcode.py
==============================================================================
--- pypy/trunk/src/pypy/interpreter/pyopcode.py (original)
+++ pypy/trunk/src/pypy/interpreter/pyopcode.py Sat Jun 26 14:47:07 2004
@@ -316,7 +316,7 @@
if nbargs >= 3: w_traceback = f.valuestack.pop()
if nbargs >= 2: w_value = f.valuestack.pop()
if 1: w_type = f.valuestack.pop()
- w_resulttuple = prepare_raise(f.space, w_type, w_value)
+ w_resulttuple = pyframe.normalize_exception(f.space, w_type, w_value)
w_type, w_value = f.space.unpacktuple(w_resulttuple, 2)
tb = f.space.unwrap(w_traceback)
if tb is not None:
@@ -834,41 +834,6 @@
stream.write("\n")
file_softspace(stream, False)
-def app_prepare_raise(etype, value):
- # careful if 'import types' is added here!
- # we get an infinite loop if this import fails:
- # import types -> IMPORT_NAME -> import_name -> raise ImportError
- # -> RAISE_VARARGS -> prepare_raise -> import types ...
- while isinstance(etype, tuple):
- etype = etype[0]
- if isinstance(etype, type):
- if not isinstance(value, etype):
- if value is None:
- # raise Type: we assume we have to instantiate Type
- value = etype()
- else:
- # raise Type, X: assume X is the constructor argument
- value = etype(value)
- # raise Type, Instance: let etype be the exact type of value
- etype = value.__class__
- elif type(etype) is str:
- # XXX warn -- deprecated
- if value is not None and type(value) is not str:
- raise TypeError("string exceptions can only have a string value")
- else:
- # raise X: we assume that X is an already-built instance
- if value is not None:
- raise TypeError("instance exception may not have a separate value")
- value = etype
- etype = value.__class__
- # for the sake of language consistency we should not allow
- # things like 'raise 1', but it's probably fine (i.e.
- # not ambiguous) to allow them in the explicit form 'raise int, 1'
- if not hasattr(value, '__dict__') and not hasattr(value, '__slots__'):
- raise TypeError("raising built-in objects can be ambiguous, "
- "use 'raise type, value' instead")
- return etype, value
-
def app_find_metaclass(bases, namespace, globals):
if '__metaclass__' in namespace:
return namespace['__metaclass__']
Modified: pypy/trunk/src/pypy/interpreter/test/test_interpreter.py
==============================================================================
--- pypy/trunk/src/pypy/interpreter/test/test_interpreter.py (original)
+++ pypy/trunk/src/pypy/interpreter/test/test_interpreter.py Sat Jun 26 14:47:07 2004
@@ -143,61 +143,10 @@
1+2+3 + 5+6+7+8+900)
class AppTestInterpreter(testit.AppTestCase):
- def test_exception(self):
- try:
- raise Exception, 1
- except Exception, e:
- self.assertEquals(e.args[0], 1)
-
def test_trivial(self):
x = 42
self.assertEquals(x, 42)
- def test_raise(self):
- def f():
- raise Exception
- self.assertRaises(Exception, f)
-
- def test_exception(self):
- try:
- raise Exception
- self.fail("exception failed to raise")
- except:
- pass
- else:
- self.fail("exception executing else clause!")
-
- def test_raise2(self):
- def f(r):
- try:
- raise r
- except LookupError:
- return 1
- self.assertRaises(Exception, f, Exception)
- self.assertEquals(f(IndexError), 1)
-
- def test_raise3(self):
- try:
- raise 1
- except TypeError:
- pass
- else:
- self.fail("shouldn't be able to raise 1")
-
- def test_raise_three_args(self):
- import sys
- try:
- raise ValueError
- except:
- exc_type,exc_val,exc_tb = sys.exc_info()
- try:
- raise exc_type,exc_val,exc_tb
- except:
- exc_type2,exc_val2,exc_tb2 = sys.exc_info()
- self.assertEquals(exc_type,exc_type2)
- self.assertEquals(exc_val,exc_val2)
- self.assertEquals(exc_tb,exc_tb2)
-
def test_trivial_call(self):
def f(): return 42
self.assertEquals(f(), 42)
Copied: pypy/trunk/src/pypy/interpreter/test/test_raise.py (from r5339, pypy/trunk/src/pypy/interpreter/test/test_interpreter.py)
==============================================================================
--- pypy/trunk/src/pypy/interpreter/test/test_interpreter.py (original)
+++ pypy/trunk/src/pypy/interpreter/test/test_raise.py Sat Jun 26 14:47:07 2004
@@ -1,173 +1,67 @@
import autopath
from pypy.tool import testit
-class TestInterpreter(testit.TestCase):
- def codetest(self, source, functionname, args):
- """Compile and run the given code string, and then call its function
- named by 'functionname' with arguments 'args'."""
- from pypy.interpreter import baseobjspace, executioncontext
- from pypy.interpreter import pyframe, gateway, module
- space = self.space
-
- compile = space.builtin.compile
- w = space.wrap
- w_code = compile(w(source), w('<string>'), w('exec'), w(0), w(0))
-
- ec = executioncontext.ExecutionContext(space)
-
- tempmodule = module.Module(space, w("__temp__"))
- w_glob = tempmodule.w_dict
- space.setitem(w_glob, w("__builtins__"), space.w_builtins)
-
- code = space.unwrap(w_code)
- code.exec_code(space, w_glob, w_glob)
-
- wrappedargs = [w(a) for a in args]
- wrappedfunc = space.getitem(w_glob, w(functionname))
- try:
- w_output = space.call_function(wrappedfunc, *wrappedargs)
- except baseobjspace.OperationError, e:
- #e.print_detailed_traceback(space)
- return '<<<%s>>>' % e.errorstr(space)
+class AppTestRaise(testit.AppTestCase):
+ def test_control_flow(self):
+ try:
+ raise Exception
+ self.fail("exception failed to raise")
+ except:
+ pass
else:
- return space.unwrap(w_output)
+ self.fail("exception executing else clause!")
- def setUp(self):
- self.space = testit.objspace()
+ def test_1arg(self):
+ try:
+ raise SystemError, 1
+ except Exception, e:
+ self.assertEquals(e.args[0], 1)
- def test_exception_trivial(self):
- x = self.codetest('''
-def f():
- try:
- raise Exception()
- except Exception, e:
- return 1
- return 2
-''', 'f', [])
- self.assertEquals(x, 1)
-
- def test_exception(self):
- x = self.codetest('''
-def f():
- try:
- raise Exception, 1
- except Exception, e:
- return e.args[0]
-''', 'f', [])
- self.assertEquals(x, 1)
-
- def test_finally(self):
- code = '''
-def f(a):
- try:
- if a:
- raise Exception
- a = -12
- finally:
- return a
-'''
- self.assertEquals(self.codetest(code, 'f', [0]), -12)
- self.assertEquals(self.codetest(code, 'f', [1]), 1)
-
-## def test_raise(self):
-## x = self.codetest('''
-## def f():
-## raise 1
-## ''', 'f', [])
-## self.assertEquals(x, '<<<TypeError: exceptions must be instances or subclasses of Exception or strings (deprecated), not int>>>')
-
- def test_except2(self):
- x = self.codetest('''
-def f():
- try:
- z = 0
- try:
- "x"+1
- except TypeError, e:
- z = 5
- raise e
- except TypeError:
- return z
-''', 'f', [])
- self.assertEquals(x, 5)
-
- def test_except3(self):
- code = '''
-def f(v):
- z = 0
- try:
- z = 1//v
- except ZeroDivisionError, e:
- z = "infinite result"
- return z
-'''
- self.assertEquals(self.codetest(code, 'f', [2]), 0)
- self.assertEquals(self.codetest(code, 'f', [0]), "infinite result")
- ess = "TypeError: unsupported operand type"
- res = self.codetest(code, 'f', ['x'])
- self.failUnless(res.find(ess) >= 0)
- # the following (original) test was a bit too strict...:
- # self.assertEquals(self.codetest(code, 'f', ['x']), "<<<TypeError: unsupported operand type(s) for //: 'int' and 'str'>>>")
-
- def test_break(self):
- code = '''
-def f(n):
- total = 0
- for i in range(n):
- try:
- if i == 4:
- break
- finally:
- total += i
- return total
-'''
- self.assertEquals(self.codetest(code, 'f', [4]), 1+2+3)
- self.assertEquals(self.codetest(code, 'f', [9]), 1+2+3+4)
-
- def test_continue(self):
- code = '''
-def f(n):
- total = 0
- for i in range(n):
- try:
- if i == 4:
- continue
- finally:
- total += 100
- total += i
- return total
-'''
- self.assertEquals(self.codetest(code, 'f', [4]), 1+2+3+400)
- self.assertEquals(self.codetest(code, 'f', [9]),
- 1+2+3 + 5+6+7+8+900)
+ def test_2args(self):
+ try:
+ raise SystemError, (1, 2)
+ except Exception, e:
+ self.assertEquals(e.args[0], 1)
+ self.assertEquals(e.args[1], 2)
-class AppTestInterpreter(testit.AppTestCase):
- def test_exception(self):
+ def test_instancearg(self):
try:
- raise Exception, 1
+ raise SystemError, SystemError(1, 2)
except Exception, e:
self.assertEquals(e.args[0], 1)
+ self.assertEquals(e.args[1], 2)
- def test_trivial(self):
- x = 42
- self.assertEquals(x, 42)
+ def test_more_precise_instancearg(self):
+ try:
+ raise Exception, SystemError(1, 2)
+ except SystemError, e:
+ self.assertEquals(e.args[0], 1)
+ self.assertEquals(e.args[1], 2)
- def test_raise(self):
- def f():
- raise Exception
- self.assertRaises(Exception, f)
+ def test_stringexc(self):
+ a = "hello world"
+ try:
+ raise a
+ except a, e:
+ self.assertEquals(e, None)
+ try:
+ raise a, "message"
+ except a, e:
+ self.assertEquals(e, "message")
- def test_exception(self):
+ def test_builtin_exc(self):
try:
- raise Exception
- self.fail("exception failed to raise")
- except:
- pass
- else:
- self.fail("exception executing else clause!")
+ [][0]
+ except IndexError, e:
+ self.assert_(isinstance(e, IndexError))
+
+ def test_raise_cls(self):
+ def f():
+ raise IndexError
+ self.assertRaises(IndexError, f)
- def test_raise2(self):
+ def test_raise_cls_catch(self):
def f(r):
try:
raise r
@@ -176,7 +70,7 @@
self.assertRaises(Exception, f, Exception)
self.assertEquals(f(IndexError), 1)
- def test_raise3(self):
+ def test_raise_wrong(self):
try:
raise 1
except TypeError:
@@ -198,34 +92,38 @@
self.assertEquals(exc_val,exc_val2)
self.assertEquals(exc_tb,exc_tb2)
- def test_trivial_call(self):
- def f(): return 42
- self.assertEquals(f(), 42)
-
- def test_trivial_call2(self):
- def f(): return 1 + 1
- self.assertEquals(f(), 2)
-
- def test_print(self):
- import sys
- save = sys.stdout
- class Out:
- def __init__(self):
- self.args = []
- def write(self, *args):
- self.args.extend(args)
- out = Out()
- try:
- sys.stdout = out
- print 10
- self.assertEquals(out.args, ['10','\n'])
- finally:
- sys.stdout = save
-
- def test_identity(self):
- def f(x): return x
- self.assertEquals(f(666), 666)
+ def test_tuple_type(self):
+ def f():
+ raise ((StopIteration, 123), 456, 789)
+ self.assertRaises(StopIteration, f)
+ def test_userclass(self):
+ class A:
+ def __init__(self, x=None):
+ self.x = x
+ class B(A):
+ pass
+ try:
+ raise A
+ except A, a:
+ self.assertEquals(a.x, None)
+ try:
+ raise A(42)
+ except A, a:
+ self.assertEquals(a.x, 42)
+ try:
+ raise A, 42
+ except A, a:
+ self.assertEquals(a.x, 42)
+ try:
+ raise B
+ except A, b:
+ self.assertEquals(type(b), B)
+ try:
+ raise A, B(42)
+ except B, b:
+ self.assertEquals(type(b), B)
+ self.assertEquals(b.x, 42)
if __name__ == '__main__':
testit.main()
Modified: pypy/trunk/src/pypy/objspace/flow/specialcase.py
==============================================================================
--- pypy/trunk/src/pypy/objspace/flow/specialcase.py (original)
+++ pypy/trunk/src/pypy/objspace/flow/specialcase.py Sat Jun 26 14:47:07 2004
@@ -1,5 +1,5 @@
import types
-from pypy.interpreter import pyopcode
+from pypy.interpreter import pyframe
from pypy.interpreter.error import OperationError
from pypy.objspace.flow.objspace import UnwrapException
from pypy.objspace.flow.model import Variable
@@ -48,5 +48,5 @@
def setup(space):
return {
- pyopcode.prepare_raise.get_function(space): prepare_raise,
+ pyframe.normalize_exception.get_function(space): prepare_raise,
}
More information about the Pypy-commit
mailing list