[pypy-svn] r69554 - in pypy/trunk/pypy: annotation doc doc/config interpreter interpreter/pyparser interpreter/test lib lib/app_test module/__builtin__ module/_file module/exceptions module/exceptions/test module/pypyjit module/pypyjit/test objspace/std objspace/std/test rlib tool

arigo at codespeak.net arigo at codespeak.net
Mon Nov 23 16:42:02 CET 2009


Author: arigo
Date: Mon Nov 23 16:42:00 2009
New Revision: 69554

Added:
   pypy/trunk/pypy/doc/config/objspace.usemodules.exceptions.txt
      - copied unchanged from r69545, pypy/branch/faster-raise-2/pypy/doc/config/objspace.usemodules.exceptions.txt
   pypy/trunk/pypy/module/exceptions/   (props changed)
      - copied from r69545, pypy/branch/faster-raise-2/pypy/module/exceptions/
Removed:
   pypy/trunk/pypy/lib/_exceptions.py
   pypy/trunk/pypy/tool/_enum_exceptions_broken.py
Modified:
   pypy/trunk/pypy/annotation/description.py
   pypy/trunk/pypy/doc/geninterp.txt
   pypy/trunk/pypy/interpreter/baseobjspace.py
   pypy/trunk/pypy/interpreter/error.py
   pypy/trunk/pypy/interpreter/pyframe.py
   pypy/trunk/pypy/interpreter/pyopcode.py
   pypy/trunk/pypy/interpreter/pyparser/error.py
   pypy/trunk/pypy/interpreter/pytraceback.py
   pypy/trunk/pypy/interpreter/test/test_module.py
   pypy/trunk/pypy/interpreter/test/test_pyframe.py
   pypy/trunk/pypy/interpreter/test/test_raise.py
   pypy/trunk/pypy/interpreter/typedef.py
   pypy/trunk/pypy/lib/app_test/test_exception_extra.py
   pypy/trunk/pypy/module/__builtin__/__init__.py
   pypy/trunk/pypy/module/__builtin__/abstractinst.py
   pypy/trunk/pypy/module/_file/interp_file.py
   pypy/trunk/pypy/module/exceptions/test/   (props changed)
   pypy/trunk/pypy/module/pypyjit/interp_jit.py
   pypy/trunk/pypy/module/pypyjit/policy.py
   pypy/trunk/pypy/module/pypyjit/test/test_policy.py
   pypy/trunk/pypy/module/pypyjit/test/test_pypy_c.py
   pypy/trunk/pypy/objspace/std/objspace.py
   pypy/trunk/pypy/objspace/std/stdtypedef.py
   pypy/trunk/pypy/objspace/std/test/test_proxy_internals.py
   pypy/trunk/pypy/objspace/std/transparent.py
   pypy/trunk/pypy/objspace/std/typeobject.py
   pypy/trunk/pypy/rlib/rwin32.py
   pypy/trunk/pypy/tool/sourcetools.py
Log:
Merge the branch/faster-raise-2:
* move exceptions to interp-level.
* add helpers space.exception_getclass() & co.
* other similar small fixes all over the place.


Modified: pypy/trunk/pypy/annotation/description.py
==============================================================================
--- pypy/trunk/pypy/annotation/description.py	(original)
+++ pypy/trunk/pypy/annotation/description.py	Mon Nov 23 16:42:00 2009
@@ -453,7 +453,7 @@
             # is of type FunctionType.  But bookkeeper.immutablevalue()
             # will do the right thing in s_get_value().
 
-        if type(value) is MemberDescriptorType:
+        if type(value) in MemberDescriptorTypes:
             # skip __slots__, showing up in the class as 'member' objects
             return
         if name == '__init__' and self.is_builtin_exception_class():
@@ -896,5 +896,9 @@
 
 class Sample(object):
     __slots__ = 'x'
-MemberDescriptorType = type(Sample.x)
+MemberDescriptorTypes = [type(Sample.x)]
 del Sample
+try:
+    MemberDescriptorTypes.append(type(OSError.errno))
+except AttributeError:    # on CPython <= 2.4
+    pass

Modified: pypy/trunk/pypy/doc/geninterp.txt
==============================================================================
--- pypy/trunk/pypy/doc/geninterp.txt	(original)
+++ pypy/trunk/pypy/doc/geninterp.txt	Mon Nov 23 16:42:00 2009
@@ -18,20 +18,15 @@
 any longer to execute this code.
 
 .. _`application-level`: coding-guide.html#app-preferable
-.. _exceptions: ../../pypy/lib/_exceptions.py
 
-An example is exceptions_. They are
-needed in a very early phase of bootstrapping StdObjspace, but
-for simplicity, they are written as RPythonic application
-level code. This implies that the interpreter must be quite
-completely initialized to execute this code, which is
-impossible in the early phase, where we have neither
-exceptions implemented nor classes available.
+Bootstrap issue
++++++++++++++++
 
-Solution
-++++++++
+One issue we had so far was of bootstrapping: some pieces of the
+interpreter (e.g. exceptions) were written in geninterped code.
+It is unclear how much of it is left, thought.
 
-This bootstrap issue is solved by invoking a new bytecode interpreter
+That bootstrap issue is (was?) solved by invoking a new bytecode interpreter
 which runs on FlowObjspace. FlowObjspace is complete without
 complicated initialization. It is able to do abstract interpretation
 of any Rpythonic code, without actually implementing anything. It just
@@ -176,10 +171,8 @@
 Interplevel Snippets in the Sources
 +++++++++++++++++++++++++++++++++++
 
-.. _`_exceptions.py`: ../../pypy/lib/_exceptions.py
-
 Code written in application space can consist of complete files
-to be translated (e.g. `_exceptions.py`_), or they
+to be translated, or they
 can be tiny snippets scattered all over a source file, similar
 to our example from above.
 

Modified: pypy/trunk/pypy/interpreter/baseobjspace.py
==============================================================================
--- pypy/trunk/pypy/interpreter/baseobjspace.py	(original)
+++ pypy/trunk/pypy/interpreter/baseobjspace.py	Mon Nov 23 16:42:00 2009
@@ -9,7 +9,7 @@
 from pypy.rlib.objectmodel import we_are_translated
 from pypy.rlib.debug import make_sure_not_resized
 from pypy.rlib.timer import DummyTimer, Timer
-from pypy.rlib.jit import we_are_jitted, dont_look_inside
+from pypy.rlib.jit import we_are_jitted, dont_look_inside, unroll_safe
 import os, sys
 
 __all__ = ['ObjSpace', 'OperationError', 'Wrappable', 'W_Root']
@@ -389,12 +389,19 @@
     def make_builtins(self):
         "NOT_RPYTHON: only for initializing the space."
 
+        from pypy.module.exceptions import Module
+        w_name_exceptions = self.wrap('exceptions')
+        self.exceptions_module = Module(self, w_name_exceptions)
+
         from pypy.module.sys import Module
         w_name = self.wrap('sys')
         self.sys = Module(self, w_name)
         w_modules = self.sys.get('modules')
         self.setitem(w_modules, w_name, self.wrap(self.sys))
 
+        self.setitem(w_modules, w_name_exceptions,
+                     self.wrap(self.exceptions_module))
+
         from pypy.module.__builtin__ import Module
         w_name = self.wrap('__builtin__')
         self.builtin = Module(self, w_name)
@@ -405,6 +412,8 @@
         bootstrap_modules = ['sys', '__builtin__', 'exceptions']
         installed_builtin_modules = bootstrap_modules[:]
 
+        self.export_builtin_exceptions()
+
         # initialize with "bootstrap types" from objspace  (e.g. w_None)
         for name, value in self.__dict__.items():
             if name.startswith('w_') and not name.endswith('Type'):
@@ -430,6 +439,18 @@
         self.setitem(self.sys.w_dict, self.wrap('builtin_module_names'),
                      w_builtin_module_names)
 
+    def export_builtin_exceptions(self):
+        """NOT_RPYTHON"""
+        w_dic = self.exceptions_module.getdict()
+        names_w = self.unpackiterable(self.call_function(self.getattr(w_dic, self.wrap("keys"))))
+
+        for w_name in names_w:
+            name = self.str_w(w_name)
+            if not name.startswith('__'):
+                excname = name
+                w_exc = self.getitem(w_dic, w_name)
+                setattr(self, "w_"+excname, w_exc)
+
     def install_mixedmodule(self, mixedname, installed_builtin_modules):
         """NOT_RPYTHON"""
         modname = self.setbuiltinmodule(mixedname)
@@ -679,12 +700,19 @@
         """
         return self.unpackiterable(w_iterable, expected_length)
 
+    @unroll_safe
     def exception_match(self, w_exc_type, w_check_class):
         """Checks if the given exception type matches 'w_check_class'."""
         if self.is_w(w_exc_type, w_check_class):
             return True   # fast path (also here to handle string exceptions)
         try:
-            return self.abstract_issubclass_w(w_exc_type, w_check_class)
+            if self.is_true(self.isinstance(w_check_class, self.w_tuple)):
+                for w_t in self.fixedview(w_check_class):
+                    if self.exception_match(w_exc_type, w_t):
+                        return True
+                else:
+                    return False
+            return self.exception_issubclass_w(w_exc_type, w_check_class)
         except OperationError, e:
             if e.match(self, self.w_TypeError):   # string exceptions maybe
                 return False
@@ -806,34 +834,52 @@
         w_objtype = self.type(w_obj)
         return self.issubtype(w_objtype, w_type)
 
+    # The code below only works
+    # for the simple case (new-style instance).
+    # These methods are patched with the full logic by the __builtin__
+    # module when it is loaded
+
     def abstract_issubclass_w(self, w_cls1, w_cls2):
-        # Equivalent to 'issubclass(cls1, cls2)'.  The code below only works
-        # for the simple case (new-style class, new-style class).
-        # This method is patched with the full logic by the __builtin__
-        # module when it is loaded.
+        # Equivalent to 'issubclass(cls1, cls2)'.
         return self.is_true(self.issubtype(w_cls1, w_cls2))
 
     def abstract_isinstance_w(self, w_obj, w_cls):
-        # Equivalent to 'isinstance(obj, cls)'.  The code below only works
-        # for the simple case (new-style instance, new-style class).
-        # This method is patched with the full logic by the __builtin__
-        # module when it is loaded.
+        # Equivalent to 'isinstance(obj, cls)'.
         return self.is_true(self.isinstance(w_obj, w_cls))
 
     def abstract_isclass_w(self, w_obj):
-        # Equivalent to 'isinstance(obj, type)'.  The code below only works
-        # for the simple case (new-style instance without special stuff).
-        # This method is patched with the full logic by the __builtin__
-        # module when it is loaded.
+        # Equivalent to 'isinstance(obj, type)'.
         return self.is_true(self.isinstance(w_obj, self.w_type))
 
     def abstract_getclass(self, w_obj):
-        # Equivalent to 'obj.__class__'.  The code below only works
-        # for the simple case (new-style instance without special stuff).
-        # This method is patched with the full logic by the __builtin__
-        # module when it is loaded.
+        # Equivalent to 'obj.__class__'.
         return self.type(w_obj)
 
+    # CPython rules allows old style classes or subclasses
+    # of BaseExceptions to be exceptions.
+    # This is slightly less general than the case above, so we prefix
+    # it with exception_
+
+    def exception_is_valid_obj_as_class_w(self, w_obj):
+        if not self.is_true(self.isinstance(w_obj, self.w_type)):
+            return False
+        if not self.full_exceptions:
+            return True
+        return self.is_true(self.issubtype(w_obj, self.w_BaseException))
+
+    def exception_is_valid_class_w(self, w_cls):
+        if not self.full_exceptions:
+            return True
+        return self.is_true(self.issubtype(w_cls, self.w_BaseException))
+
+    def exception_getclass(self, w_obj):
+        return self.type(w_obj)
+
+    def exception_issubclass_w(self, w_cls1, w_cls2):
+        return self.is_true(self.issubtype(w_cls1, w_cls2))
+
+    # end of special support code
+
     def eval(self, expression, w_globals, w_locals, hidden_applevel=False):
         "NOT_RPYTHON: For internal debugging."
         import types
@@ -991,6 +1037,21 @@
             buffer = self.buffer_w(w_obj)
             return buffer.as_str()
 
+    def realstr_w(self, w_obj):
+        # Like str_w, but only works if w_obj is really of type 'str'.
+        if not self.is_true(self.isinstance(w_obj, self.w_str)):
+            raise OperationError(self.w_TypeError,
+                                 self.wrap('argument must be a string'))
+        return self.str_w(w_obj)
+
+    def realunicode_w(self, w_obj):
+        # Like unicode_w, but only works if w_obj is really of type
+        # 'unicode'.
+        if not self.is_true(self.isinstance(w_obj, self.w_unicode)):
+            raise OperationError(self.w_TypeError,
+                                 self.wrap('argument must be a unicode'))
+        return self.unicode_w(w_obj)
+
     def bool_w(self, w_obj):
         # Unwraps a bool, also accepting an int for compatibility.
         # This is here mostly just for gateway.int_unwrapping_space_method().

Modified: pypy/trunk/pypy/interpreter/error.py
==============================================================================
--- pypy/trunk/pypy/interpreter/error.py	(original)
+++ pypy/trunk/pypy/interpreter/error.py	Mon Nov 23 16:42:00 2009
@@ -73,13 +73,6 @@
         else:
             return '%s: %s' % (exc_typename, exc_value)
 
-    def getframe(self):
-        "The frame this exception was raised in, or None."
-        if self.application_traceback:
-            return self.application_traceback.frame
-        else:
-            return None
-
     def record_interpreter_traceback(self):
         """Records the current traceback inside the interpreter.
         This traceback is only useful to debug the interpreter, not the
@@ -102,7 +95,7 @@
             print >> file, "Traceback (application-level):"
             while tb is not None:
                 co = tb.frame.pycode
-                lineno = tb.lineno
+                lineno = tb.get_lineno()
                 fname = co.co_filename
                 if fname.startswith('<inline>\n'):
                     lines = fname.split('\n')
@@ -177,16 +170,15 @@
             while space.is_true(space.isinstance(w_type, space.w_tuple)):
                 w_type = space.getitem(w_type, space.wrap(0))
 
-        if (space.abstract_isclass_w(w_type) and
-            is_valid_exception_class(space, w_type)):
+        if space.exception_is_valid_obj_as_class_w(w_type):
             # this is for all cases of the form (Class, something)
             if space.is_w(w_value, space.w_None):
                 # raise Type: we assume we have to instantiate Type
                 w_value = space.call_function(w_type)
-                w_type = space.abstract_getclass(w_value)
+                w_type = space.exception_getclass(w_value)
             else:
-                w_valuetype = space.abstract_getclass(w_value)
-                if space.abstract_issubclass_w(w_valuetype, w_type):
+                w_valuetype = space.exception_getclass(w_value)
+                if space.exception_issubclass_w(w_valuetype, w_type):
                     # raise Type, Instance: let etype be the exact type of value
                     w_type = w_valuetype
                 else:
@@ -198,7 +190,7 @@
                     else:
                         # raise Type, X: assume X is the constructor argument
                         w_value = space.call_function(w_type, w_value)
-                    w_type = space.abstract_getclass(w_value)
+                    w_type = space.exception_getclass(w_value)
 
         elif space.full_exceptions and space.is_w(space.type(w_type),
                                                   space.w_str):
@@ -208,8 +200,8 @@
         else:
             # the only case left here is (inst, None), from a 'raise inst'.
             w_inst = w_type
-            w_instclass = space.abstract_getclass(w_inst)
-            if not is_valid_exception_class(space, w_instclass):
+            w_instclass = space.exception_getclass(w_inst)
+            if not space.exception_is_valid_class_w(w_instclass):
                 instclassname = w_instclass.getname(space, '?')
                 msg = ("exceptions must be classes, or instances,"
                        "or strings (deprecated) not %s" % (instclassname,))
@@ -240,23 +232,6 @@
         except OperationError:
             pass   # ignored
 
-
-def is_valid_exception_class(space, w_type):
-    """Assuming that 'w_type' is a new-style or old-style class, is it
-    correct to use it as the class of an exception?  The answer is no
-    if it is a new-style class that doesn't inherit from BaseException.
-    """
-    if not space.full_exceptions:
-        return True         # always, for the flow space
-    try:
-        return space.is_true(
-            space.issubtype(w_type, space.w_BaseException))
-    except OperationError, e:
-        if not e.match(space, space.w_TypeError):
-            raise
-        return True         # assuming w_type is an old-style class
-
-
 # Utilities
 from pypy.tool.ansi_print import ansi_print
 

Modified: pypy/trunk/pypy/interpreter/pyframe.py
==============================================================================
--- pypy/trunk/pypy/interpreter/pyframe.py	(original)
+++ pypy/trunk/pypy/interpreter/pyframe.py	Mon Nov 23 16:42:00 2009
@@ -56,7 +56,6 @@
         self.valuestack_w = [None] * code.co_stacksize
         self.valuestackdepth = 0
         self.lastblock = None
-        self.blockcount = 0
         if space.config.objspace.honor__builtins__:
             self.builtin = space.builtin.pick_builtin(w_globals)
         # regular functions always have CO_OPTIMIZED and CO_NEWLOCALS.
@@ -70,31 +69,29 @@
     def append_block(self, block):
         block.previous = self.lastblock
         self.lastblock = block
-        self.blockcount += 1
 
     def pop_block(self):
         block = self.lastblock
         self.lastblock = block.previous
-        self.blockcount -= 1
         return block
 
+    def blockstack_non_empty(self):
+        return self.lastblock is not None
+
     def get_blocklist(self):
         """Returns a list containing all the blocks in the frame"""
-        lst = [None] * self.blockcount
+        lst = []
         block = self.lastblock
-        i = 0
         while block is not None:
-            lst[i] = block
-            i += 1
+            lst.append(block)
             block = block.previous
         return lst
 
     def set_blocklist(self, lst):
         self.lastblock = None
-        self.blockcount = 0
-        i = len(lst)
-        while i > 0:
-            block = lst[i-1]
+        i = len(lst) - 1
+        while i >= 0:
+            block = lst[i]
             i -= 1
             self.append_block(block)
 
@@ -162,9 +159,6 @@
                 raise
             if not we_are_jitted():
                 executioncontext.return_trace(self, w_exitvalue)
-            # on exit, we try to release self.last_exception -- breaks an
-            # obvious reference cycle, so it helps refcounting implementations
-            self.last_exception = None
         finally:
             executioncontext.leave(self)
         return w_exitvalue
@@ -464,7 +458,7 @@
             
         if self.w_f_trace is None:
             raise OperationError(space.w_ValueError,
-                  space.wrap("f_lineo can only be set by a trace function."))
+                  space.wrap("f_lineno can only be set by a trace function."))
 
         if new_lineno < self.pycode.co_firstlineno:
             raise OperationError(space.w_ValueError,
@@ -559,7 +553,11 @@
             else:
                 addr += 1
 
-        f_iblock = self.blockcount
+        f_iblock = 0
+        block = self.lastblock
+        while block:
+            f_iblock += 1
+            block = block.previous
         min_iblock = f_iblock + min_delta_iblock
         if new_lasti > self.last_instr:
             new_iblock = f_iblock + delta_iblock

Modified: pypy/trunk/pypy/interpreter/pyopcode.py
==============================================================================
--- pypy/trunk/pypy/interpreter/pyopcode.py	(original)
+++ pypy/trunk/pypy/interpreter/pyopcode.py	Mon Nov 23 16:42:00 2009
@@ -274,11 +274,8 @@
 
     @jit.unroll_safe
     def unrollstack(self, unroller_kind):
-        n = self.blockcount
-        n = jit.hint(n, promote=True)
-        while n > 0:
+        while self.blockstack_non_empty():
             block = self.pop_block()
-            n -= 1
             if (block.handling_mask & unroller_kind) != 0:
                 return block
             block.cleanupstack(self)

Modified: pypy/trunk/pypy/interpreter/pyparser/error.py
==============================================================================
--- pypy/trunk/pypy/interpreter/pyparser/error.py	(original)
+++ pypy/trunk/pypy/interpreter/pyparser/error.py	Mon Nov 23 16:42:00 2009
@@ -8,7 +8,6 @@
         self.offset = offset
         self.text = text
         self.filename = filename
-        self.print_file_and_line = False
 
     def wrap_info(self, space):
         return space.newtuple([space.wrap(self.msg),

Modified: pypy/trunk/pypy/interpreter/pytraceback.py
==============================================================================
--- pypy/trunk/pypy/interpreter/pytraceback.py	(original)
+++ pypy/trunk/pypy/interpreter/pytraceback.py	Mon Nov 23 16:42:00 2009
@@ -5,20 +5,25 @@
 class PyTraceback(baseobjspace.Wrappable):
     """Traceback object
 
-    Public fields:
+    Public app-level fields:
      * 'tb_frame'
      * 'tb_lasti'
      * 'tb_lineno'
      * 'tb_next'
     """
 
-    def __init__(self, space, frame, lasti, lineno, next):
+    def __init__(self, space, frame, lasti, next):
         self.space = space
         self.frame = frame
         self.lasti = lasti
-        self.lineno = lineno
         self.next = next
 
+    def get_lineno(self):
+        return offset2lineno(self.frame.pycode, self.lasti)
+
+    def descr_tb_lineno(space, self):
+        return space.wrap(self.get_lineno())
+
     def descr__reduce__(self, space):
         from pypy.interpreter.mixedmodule import MixedModule
         w_mod    = space.getbuiltinmodule('_pickle_support')
@@ -30,7 +35,6 @@
         tup_state = [
             w(self.frame),
             w(self.lasti),
-            w(self.lineno),
             w(self.next),
             ]
         nt = space.newtuple
@@ -39,19 +43,17 @@
     def descr__setstate__(self, space, w_args):
         from pypy.interpreter.pyframe import PyFrame
         args_w = space.unpackiterable(w_args)
-        w_frame, w_lasti, w_lineno, w_next = args_w
+        w_frame, w_lasti, w_next = args_w
         self.frame = space.interp_w(PyFrame, w_frame)
         self.lasti = space.int_w(w_lasti)
-        self.lineno = space.int_w(w_lineno)
         self.next = space.interp_w(PyTraceback, w_next, can_be_None=True)
 
 def record_application_traceback(space, operror, frame, last_instruction):
     frame.force_f_back()
     if frame.pycode.hidden_applevel:
         return
-    lineno = offset2lineno(frame.pycode, last_instruction)
     tb = operror.application_traceback
-    tb = PyTraceback(space, frame, last_instruction, lineno, tb)
+    tb = PyTraceback(space, frame, last_instruction, tb)
     operror.application_traceback = tb
 
 def offset2lineno(c, stopat):

Modified: pypy/trunk/pypy/interpreter/test/test_module.py
==============================================================================
--- pypy/trunk/pypy/interpreter/test/test_module.py	(original)
+++ pypy/trunk/pypy/interpreter/test/test_module.py	Mon Nov 23 16:42:00 2009
@@ -54,13 +54,13 @@
         r = repr(sys)
         assert r == "<module 'sys' (built-in)>"
         
-        import _exceptions # known to be in pypy/lib
-        r = repr(_exceptions)
-        assert r.startswith("<module '_exceptions' from ") and \
-               'pypy/lib/_exceptions.py' in r and \
+        import _pypy_interact # known to be in pypy/lib
+        r = repr(_pypy_interact)
+        assert r.startswith("<module '_pypy_interact' from ") and \
+               'pypy/lib/_pypy_interact.py' in r and \
                r.endswith('>')
-        nofile = type(_exceptions)('nofile', 'foo')
+        nofile = type(_pypy_interact)('nofile', 'foo')
         assert repr(nofile) == "<module 'nofile' from ?>"
 
-        m = type(_exceptions).__new__(type(_exceptions))
+        m = type(_pypy_interact).__new__(type(_pypy_interact))
         assert repr(m).startswith("<module '?'")

Modified: pypy/trunk/pypy/interpreter/test/test_pyframe.py
==============================================================================
--- pypy/trunk/pypy/interpreter/test/test_pyframe.py	(original)
+++ pypy/trunk/pypy/interpreter/test/test_pyframe.py	Mon Nov 23 16:42:00 2009
@@ -42,6 +42,25 @@
         origin = g.func_code.co_firstlineno
         assert g() == [origin+3, origin+4, origin+5]
 
+    def test_f_lineno_set(self):
+        def tracer(f, *args):
+            def x(f, *args):
+                if f.f_lineno == origin + 1:
+                    f.f_lineno = origin + 2
+            return x
+
+        def function():
+            xyz
+            return 3
+        
+        def g():
+            import sys
+            sys.settrace(tracer)
+            function()
+            sys.settrace(None)
+        origin = function.func_code.co_firstlineno
+        g() # assert did not crash
+
     def test_f_back(self):
         import sys
         def f():

Modified: pypy/trunk/pypy/interpreter/test/test_raise.py
==============================================================================
--- pypy/trunk/pypy/interpreter/test/test_raise.py	(original)
+++ pypy/trunk/pypy/interpreter/test/test_raise.py	Mon Nov 23 16:42:00 2009
@@ -244,3 +244,50 @@
             assert 0
         except KeyError:
             pass
+
+    def test_catch_tuple(self):
+        class A:
+            pass
+        
+        try:
+            raise ValueError
+        except (ValueError, A):
+            pass
+        else:
+            fail("Did not raise")
+
+        try:
+            raise A()
+        except (ValueError, A):
+            pass
+        else:
+            fail("Did not raise")
+
+    def test_obscure_bases(self):
+        # this test checks bug-to-bug cpython compatibility
+        e = ValueError()
+        e.__bases__ = (5,)
+        try:
+            raise e
+        except ValueError:
+            pass
+
+        # explodes on CPython and py.test, not sure why
+
+        flag = False
+        class A(BaseException):
+            class __metaclass__(type):
+                def __getattribute__(self, name):
+                    if flag and name == '__bases__':
+                        fail("someone read bases attr")
+                    else:
+                        return type.__getattribute__(self, name)
+
+        try:
+            a = A()
+            flag = True
+            raise a
+        except 42:
+            pass
+        except A:
+            pass

Modified: pypy/trunk/pypy/interpreter/typedef.py
==============================================================================
--- pypy/trunk/pypy/interpreter/typedef.py	(original)
+++ pypy/trunk/pypy/interpreter/typedef.py	Mon Nov 23 16:42:00 2009
@@ -24,6 +24,7 @@
             self.weakrefable |= __base.weakrefable
         self.rawdict = {}
         self.acceptable_as_base_class = True
+        self.applevel_subclasses_base = None
         # xxx used by faking
         self.fakedcpytype = None
         self.add_entries(**rawdict)
@@ -561,6 +562,9 @@
 def descr_set_dict(space, w_obj, w_dict):
     w_obj.setdict(space, w_dict)
 
+def descr_del_dict(space, w_obj): # blame CPython for the existence of this one
+    w_obj.setdict(space, space.newdict())
+
 def descr_get_weakref(space, w_obj):
     lifeline = w_obj.getweakref()
     if lifeline is None:
@@ -825,7 +829,7 @@
                               unwrap_spec=['self', ObjSpace, W_Root]),
     tb_frame  = interp_attrproperty('frame', cls=PyTraceback),
     tb_lasti  = interp_attrproperty('lasti', cls=PyTraceback),
-    tb_lineno = interp_attrproperty('lineno', cls=PyTraceback),
+    tb_lineno = GetSetProperty(PyTraceback.descr_tb_lineno),
     tb_next   = interp_attrproperty('next', cls=PyTraceback),
     )
 PyTraceback.typedef.acceptable_as_base_class = False

Modified: pypy/trunk/pypy/lib/app_test/test_exception_extra.py
==============================================================================
--- pypy/trunk/pypy/lib/app_test/test_exception_extra.py	(original)
+++ pypy/trunk/pypy/lib/app_test/test_exception_extra.py	Mon Nov 23 16:42:00 2009
@@ -6,7 +6,7 @@
     e = ex.EnvironmentError(1, "hello")
     assert str(e) == "[Errno 1] hello"
     e = ex.EnvironmentError(1, "hello", "world")
-    assert str(e) == "[Errno 1] hello: world"
+    assert str(e) == "[Errno 1] hello: 'world'"
 
 def app_test_import():
     import exceptions

Modified: pypy/trunk/pypy/module/__builtin__/__init__.py
==============================================================================
--- pypy/trunk/pypy/module/__builtin__/__init__.py	(original)
+++ pypy/trunk/pypy/module/__builtin__/__init__.py	Mon Nov 23 16:42:00 2009
@@ -148,6 +148,10 @@
         space.abstract_issubclass_w = ab.abstract_issubclass_w.__get__(space)
         space.abstract_isclass_w = ab.abstract_isclass_w.__get__(space)
         space.abstract_getclass = ab.abstract_getclass.__get__(space)
+        space.exception_is_valid_class_w = ab.exception_is_valid_class_w.__get__(space)
+        space.exception_is_valid_obj_as_class_w = ab.exception_is_valid_obj_as_class_w.__get__(space)
+        space.exception_getclass = ab.exception_getclass.__get__(space)
+        space.exception_issubclass_w = ab.exception_issubclass_w.__get__(space)
 
     def startup(self, space):
         # install zipimport hook if --withmod-zipimport is used

Modified: pypy/trunk/pypy/module/__builtin__/abstractinst.py
==============================================================================
--- pypy/trunk/pypy/module/__builtin__/abstractinst.py	(original)
+++ pypy/trunk/pypy/module/__builtin__/abstractinst.py	Mon Nov 23 16:42:00 2009
@@ -11,6 +11,7 @@
 from pypy.interpreter.error import OperationError
 from pypy.module.__builtin__.interp_classobj import W_ClassObject
 from pypy.module.__builtin__.interp_classobj import W_InstanceObject
+from pypy.interpreter.baseobjspace import ObjSpace as BaseObjSpace
 
 def _get_bases(space, w_cls):
     """Returns 'cls.__bases__'.  Returns None if there is
@@ -152,6 +153,37 @@
                 " or tuple of classes and types")
     return _issubclass_recurse(space, w_derived, w_klass_or_tuple)
 
+# ------------------------------------------------------------
+# Exception helpers
+
+def exception_is_valid_obj_as_class_w(space, w_obj):
+    obj = space.interpclass_w(w_obj)
+    if isinstance(obj, W_ClassObject):
+        return True
+    return BaseObjSpace.exception_is_valid_obj_as_class_w(space, w_obj)
+
+def exception_is_valid_class_w(space, w_cls):
+    cls = space.interpclass_w(w_cls)
+    if isinstance(cls, W_ClassObject):
+        return True
+    return BaseObjSpace.exception_is_valid_class_w(space, w_cls)
+
+def exception_getclass(space, w_obj):
+    obj = space.interpclass_w(w_obj)
+    if isinstance(obj, W_InstanceObject):
+        return obj.w_class
+    return BaseObjSpace.exception_getclass(space, w_obj)
+
+def exception_issubclass_w(space, w_cls1, w_cls2):
+    cls1 = space.interpclass_w(w_cls1)
+    cls2 = space.interpclass_w(w_cls2)
+    if isinstance(cls1, W_ClassObject):
+        if isinstance(cls2, W_ClassObject):
+            return cls1.is_subclass_of(cls2)
+        return False
+    if isinstance(cls2, W_ClassObject):
+        return False
+    return BaseObjSpace.exception_issubclass_w(space, w_cls1, w_cls2)
 
 # ____________________________________________________________
 # App-level interface

Modified: pypy/trunk/pypy/module/_file/interp_file.py
==============================================================================
--- pypy/trunk/pypy/module/_file/interp_file.py	(original)
+++ pypy/trunk/pypy/module/_file/interp_file.py	Mon Nov 23 16:42:00 2009
@@ -387,7 +387,8 @@
             head = "closed"
         else:
             head = "open"
-        if self.space.abstract_isinstance_w(self.w_name, self.space.w_str):
+        if self.space.is_true(self.space.isinstance(self.w_name,
+                                                    self.space.w_str)):
             info = "%s file '%s', mode '%s'" % (
                 head,
                 self.space.str_w(self.w_name),

Modified: pypy/trunk/pypy/module/pypyjit/interp_jit.py
==============================================================================
--- pypy/trunk/pypy/module/pypyjit/interp_jit.py	(original)
+++ pypy/trunk/pypy/module/pypyjit/interp_jit.py	Mon Nov 23 16:42:00 2009
@@ -22,6 +22,7 @@
 PyFrame._virtualizable2_ = ['last_instr', 'pycode',
                             'valuestackdepth', 'valuestack_w[*]',
                             'fastlocals_w[*]', 'f_forward',
+                            'last_exception',
                             ]
 
 JUMP_ABSOLUTE = opmap['JUMP_ABSOLUTE']

Modified: pypy/trunk/pypy/module/pypyjit/policy.py
==============================================================================
--- pypy/trunk/pypy/module/pypyjit/policy.py	(original)
+++ pypy/trunk/pypy/module/pypyjit/policy.py	Mon Nov 23 16:42:00 2009
@@ -8,7 +8,7 @@
 
         if '.' in modname:
             modname, _ = modname.split('.', 1)
-        if modname in ['pypyjit', 'signal', 'micronumpy', 'math']:
+        if modname in ['pypyjit', 'signal', 'micronumpy', 'math', 'exceptions']:
             return True
         return False
 

Modified: pypy/trunk/pypy/module/pypyjit/test/test_policy.py
==============================================================================
--- pypy/trunk/pypy/module/pypyjit/test/test_policy.py	(original)
+++ pypy/trunk/pypy/module/pypyjit/test/test_policy.py	Mon Nov 23 16:42:00 2009
@@ -30,6 +30,7 @@
     assert not pypypolicy.look_inside_pypy_module('posix.interp_expat')
     assert pypypolicy.look_inside_pypy_module('__builtin__.operation')
     assert pypypolicy.look_inside_pypy_module('__builtin__.abstractinst')
+    assert pypypolicy.look_inside_pypy_module('exceptions.interp_exceptions')
     for modname in 'pypyjit', 'signal', 'micronumpy', 'math':
         assert pypypolicy.look_inside_pypy_module(modname)
         assert pypypolicy.look_inside_pypy_module(modname + '.foo')

Modified: pypy/trunk/pypy/module/pypyjit/test/test_pypy_c.py
==============================================================================
--- pypy/trunk/pypy/module/pypyjit/test/test_pypy_c.py	(original)
+++ pypy/trunk/pypy/module/pypyjit/test/test_pypy_c.py	Mon Nov 23 16:42:00 2009
@@ -373,6 +373,51 @@
         assert len(bytecode.get_opnames("call")) == 1 # the call to append
         assert len(bytecode.get_opnames("guard")) == 1 # guard_no_exception after the call
 
+    def test_exception_inside_loop_1(self):
+        py.test.skip("exceptions: in-progress")
+        self.run_source('''
+            def main(n):
+                while n:
+                    try:
+                        raise ValueError
+                    except ValueError:
+                        pass
+                    n -= 1
+                return n
+        ''',
+                  ([30], 0))
+
+        bytecode, = self.get_by_bytecode("SETUP_EXCEPT")
+        #assert not bytecode.get_opnames("new")   -- currently, we have
+        #               new_with_vtable(pypy.interpreter.pyopcode.ExceptBlock)
+        bytecode, = self.get_by_bytecode("RAISE_VARARGS")
+        assert not bytecode.get_opnames("new")
+        bytecode, = self.get_by_bytecode("COMPARE_OP")
+        assert not bytecode.get_opnames()
+
+    def test_exception_inside_loop_2(self):
+        py.test.skip("exceptions: in-progress")
+        self.run_source('''
+            def g(n):
+                raise ValueError(n)
+            def f(n):
+                g(n)
+            def main(n):
+                while n:
+                    try:
+                        f(n)
+                    except ValueError:
+                        pass
+                    n -= 1
+                return n
+        ''',
+                  ([30], 0))
+
+        bytecode, = self.get_by_bytecode("RAISE_VARARGS")
+        assert not bytecode.get_opnames("new")
+        bytecode, = self.get_by_bytecode("COMPARE_OP")
+        assert len(bytecode.get_opnames()) <= 2    # oois, guard_true
+
 
 class AppTestJIT(PyPyCJITTests):
     def setup_class(cls):

Modified: pypy/trunk/pypy/objspace/std/objspace.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/objspace.py	(original)
+++ pypy/trunk/pypy/objspace/std/objspace.py	Mon Nov 23 16:42:00 2009
@@ -322,9 +322,7 @@
             setattr(self, 'w_' + typedef.name, w_type)
 
         # exceptions & builtins
-        w_mod = self.setup_exceptions()
         self.make_builtins()
-        self.sys.setmodule(w_mod)
 
         # the type of old-style classes
         self.w_classobj = self.builtin.get('__metaclass__')
@@ -358,61 +356,6 @@
             self.setattr(w___pypy__, self.wrap('get_tproxy_controller'),
                           self.wrap(app_proxy_controller))
 
-    def create_builtin_module(self, pyname, publicname):
-        """NOT_RPYTHON
-        helper function which returns the wrapped module and its dict.
-        """
-        # generate on-the-fly
-        class Fake: pass
-        fake = Fake()
-        from pypy import lib
-        fname = os.path.join(os.path.split(lib.__file__)[0], pyname)
-        fake.filename = fname
-        fake.code = compile(file(fname).read(), fname, "exec")
-        fake.modname = publicname
-        w_dic = PyPyCacheDir.build_applevelinterp_dict(fake, self)
-        from pypy.interpreter.module import Module
-        mod = Module(self, self.wrap(publicname), w_dic)
-        w_mod = self.wrap(mod)
-        return w_mod, w_dic
-
-    def setup_exceptions(self):
-        """NOT_RPYTHON"""
-        ## hacking things in
-        def call(w_type, w_args):
-            space = self
-            # too early for unpackiterable as well :-(
-            name  = space.unwrap(space.getitem(w_args, space.wrap(0)))
-            bases = space.fixedview(space.getitem(w_args, space.wrap(1)))
-            dic   = space.unwrap(space.getitem(w_args, space.wrap(2)))
-            dic = dict([(key,space.wrap(value)) for (key, value) in dic.items()])
-            bases = list(bases)
-            if not bases:
-                bases = [space.w_object]
-            res = W_TypeObject(space, name, bases, dic)
-            res.ready()
-            return res
-        try:
-            # note that we hide the real call method by an instance variable!
-            self.call = call
-            mod, w_dic = self.create_builtin_module('_exceptions.py', 'exceptions')
-
-            self.w_IndexError = self.getitem(w_dic, self.wrap("IndexError"))
-            self.w_StopIteration = self.getitem(w_dic, self.wrap("StopIteration"))
-        finally:
-            del self.call # revert
-
-        names_w = self.unpackiterable(self.call_function(self.getattr(w_dic, self.wrap("keys"))))
-
-        for w_name in names_w:
-            name = self.str_w(w_name)
-            if not name.startswith('__'):
-                excname = name
-                w_exc = self.getitem(w_dic, w_name)
-                setattr(self, "w_"+excname, w_exc)
-
-        return mod
-
     def createexecutioncontext(self):
         # add space specific fields to execution context
         # note that this method must not call space methods that might need an
@@ -615,16 +558,18 @@
             # the purpose of the above check is to avoid the code below
             # to be annotated at all for 'cls' if it is not necessary
             w_subtype = w_type.check_user_subclass(w_subtype)
+            if cls.typedef.applevel_subclasses_base is not None:
+                cls = cls.typedef.applevel_subclasses_base
             subcls = get_unique_interplevel_subclass(
                     self.config, cls, w_subtype.hasdict, w_subtype.nslots != 0,
                     w_subtype.needsdel, w_subtype.weakrefable)
             instance = instantiate(subcls)
+            assert isinstance(instance, cls)
             instance.user_setup(self, w_subtype)
         else:
             raise OperationError(self.w_TypeError,
                 self.wrap("%s.__new__(%s): only for the type %s" % (
                     w_type.name, w_subtype.getname(self, '?'), w_type.name)))
-        assert isinstance(instance, cls)
         return instance
     allocate_instance._annspecialcase_ = "specialize:arg(1)"
 

Modified: pypy/trunk/pypy/objspace/std/stdtypedef.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/stdtypedef.py	(original)
+++ pypy/trunk/pypy/objspace/std/stdtypedef.py	Mon Nov 23 16:42:00 2009
@@ -2,7 +2,7 @@
 from pypy.interpreter.error import OperationError
 from pypy.interpreter.typedef import TypeDef, GetSetProperty, Member
 from pypy.interpreter.typedef import descr_get_dict, descr_set_dict
-from pypy.interpreter.typedef import no_hash_descr
+from pypy.interpreter.typedef import no_hash_descr, descr_del_dict
 from pypy.interpreter.baseobjspace import SpaceCache
 from pypy.objspace.std.model import StdObjSpaceMultiMethod
 from pypy.objspace.std.multimethod import FailedToImplement
@@ -39,9 +39,6 @@
         a = a.base
     return True
 
-def descr_del_dict(space, w_obj): # blame CPython for the existence of this one
-    w_obj.setdict(space, space.newdict())
-
 std_dict_descr = GetSetProperty(descr_get_dict, descr_set_dict, descr_del_dict)
 std_dict_descr.name = '__dict__'
 
@@ -91,8 +88,12 @@
         for descrname, descrvalue in rawdict.items():
             dict_w[descrname] = w(descrvalue)
 
+        if typedef.applevel_subclasses_base is not None:
+            overridetypedef = typedef.applevel_subclasses_base.typedef
+        else:
+            overridetypedef = typedef
         w_type = W_TypeObject(space, typedef.name, bases_w, dict_w,
-                              overridetypedef=typedef)
+                              overridetypedef=overridetypedef)
         w_type.lazyloaders = lazyloaders
         return w_type
 

Modified: pypy/trunk/pypy/objspace/std/test/test_proxy_internals.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/test/test_proxy_internals.py	(original)
+++ pypy/trunk/pypy/objspace/std/test/test_proxy_internals.py	Mon Nov 23 16:42:00 2009
@@ -1,7 +1,8 @@
 
 """ test proxy internals like code, traceback, frame
 """
-from pypy.conftest import gettestobjspace
+import py
+from pypy.conftest import gettestobjspace, option
 
 class AppProxy(object):
     def setup_class(cls):
@@ -21,6 +22,28 @@
         return get_proxy
         """)
 
+class AppTestProxyInterpOnly(AppProxy):
+    def setup_class(cls):
+        if option.runappdirect:
+            py.test.skip("interp only test")
+        from pypy.interpreter.typedef import TypeDef, interp2app
+        from pypy.interpreter.baseobjspace import Wrappable
+
+        class W_Stuff(Wrappable):
+            pass
+
+        def descr_new(space, w_subtype):
+            return W_Stuff()
+
+        W_Stuff.typedef = TypeDef(
+            'Stuff',
+            __new__ = interp2app(descr_new),
+        )
+        cls.w_Stuff = cls.space.gettypefor(W_Stuff)
+
+    def test_unproxyable(self):
+        raises(TypeError, self.get_proxy, self.Stuff())
+
 class AppTestProxyInternals(AppProxy):
     def test_traceback_basic(self):
         try:
@@ -31,7 +54,7 @@
         
         tb = self.get_proxy(e[2])
         assert tb.tb_frame is e[2].tb_frame
-    
+
     def test_traceback_catch(self):
         try:
             try:

Modified: pypy/trunk/pypy/objspace/std/transparent.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/transparent.py	(original)
+++ pypy/trunk/pypy/objspace/std/transparent.py	Mon Nov 23 16:42:00 2009
@@ -26,7 +26,6 @@
 completely controlled by the controller."""
     from pypy.interpreter.typedef import Function, PyTraceback, PyFrame, \
         PyCode, GeneratorIterator
-    
     if not space.is_true(space.callable(w_controller)):
         raise OperationError(space.w_TypeError, space.wrap("controller should be function"))
     
@@ -49,14 +48,12 @@
             return W_Transparent(space, w_type, w_controller)
     else:
         raise OperationError(space.w_TypeError, space.wrap("type expected as first argument"))
-    try:
-        w_lookup = w_type or w_type.w_besttype
-        for k, v in type_cache.cache:
-            if w_lookup == k:
-                return v(space, w_type, w_controller)
-    except KeyError:
-        raise OperationError(space.w_TypeError, space.wrap("Object type %s could not "\
-                                                           "be wrapped (YET)" % w_type.getname(space, "?")))
+    w_lookup = w_type
+    for k, v in type_cache.cache:
+        if w_lookup == k:
+            return v(space, w_type, w_controller)
+    raise OperationError(space.w_TypeError, space.wrap("Object type %s could not "\
+                                                       "be wrapped (YET)" % w_type.getname(space, "?")))
 
 def register_proxyable(space, cls):
     tpdef = cls.typedef

Modified: pypy/trunk/pypy/objspace/std/typeobject.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/typeobject.py	(original)
+++ pypy/trunk/pypy/objspace/std/typeobject.py	Mon Nov 23 16:42:00 2009
@@ -80,7 +80,6 @@
         w_self.hasdict = False
         w_self.needsdel = False
         w_self.weakrefable = False
-        w_self.w_same_layout_as = None
         w_self.weak_subclasses = []
         w_self.__flags__ = 0           # or _HEAPTYPE
         w_self.instancetypedef = overridetypedef
@@ -91,6 +90,7 @@
         else:
             setup_user_defined_type(w_self)
             custom_metaclass = not space.is_w(space.type(w_self), space.w_type)
+        w_self.w_same_layout_as = get_parent_layout(w_self)
 
         if space.config.objspace.std.withtypeversion:
             if w_self.instancetypedef.hasdict or custom_metaclass:
@@ -548,7 +548,6 @@
     hasoldstylebase = copy_flags_from_bases(w_self, w_bestbase)
     create_all_slots(w_self, hasoldstylebase)
 
-    w_self.w_same_layout_as = get_parent_layout(w_self)
     ensure_common_attributes(w_self)
 
 def setup_builtin_type(w_self):

Modified: pypy/trunk/pypy/rlib/rwin32.py
==============================================================================
--- pypy/trunk/pypy/rlib/rwin32.py	(original)
+++ pypy/trunk/pypy/rlib/rwin32.py	Mon Nov 23 16:42:00 2009
@@ -6,7 +6,7 @@
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
 from pypy.rpython.lltypesystem import lltype, rffi
 from pypy.rlib.rarithmetic import intmask
-import os, sys
+import os, sys, errno
 
 # This module can be imported on any platform,
 # but most symbols are not usable...
@@ -14,8 +14,13 @@
 
 if WIN32:
     eci = ExternalCompilationInfo(
-        includes = ['windows.h'],
+        includes = ['windows.h', 'errno.h'],
         libraries = ['kernel32'],
+        separate_module_sources = ["""
+        long WINAPI pypy_dosmaperr(long winerror)
+        { _dosmaperr(winerror); return errno; }
+        """],
+        export_symbols = ["pypy_dosmaperr"],
         )
 else:
     eci = ExternalCompilationInfo()
@@ -60,7 +65,6 @@
                     """.split():
             locals()[name] = rffi_platform.ConstantInteger(name)
 
-
 for k, v in rffi_platform.configure(CConfig).items():
     globals()[k] = v
 
@@ -93,6 +97,20 @@
 
     _get_osfhandle = rffi.llexternal('_get_osfhandle', [rffi.INT], HANDLE)
 
+    dosmaperr = winexternal('pypy_dosmaperr', [rffi.LONG], rffi.LONG)
+
+
+    def build_winerror_to_errno():
+        """Build a dictionary mapping windows error numbers to POSIX errno.
+        The function returns the dict, and the default value for codes not
+        in the dict."""
+        default = errno.EINVAL
+        errors = {}
+        for i in range(1, 65000):
+            error = dosmaperr(i)
+            if error != default:
+                errors[i] = error
+        return errors, default
 
     # A bit like strerror...
     def FormatError(code):

Modified: pypy/trunk/pypy/tool/sourcetools.py
==============================================================================
--- pypy/trunk/pypy/tool/sourcetools.py	(original)
+++ pypy/trunk/pypy/tool/sourcetools.py	Mon Nov 23 16:42:00 2009
@@ -236,12 +236,13 @@
                            'a' <= chr(i) <= 'z' or
                            'A' <= chr(i) <= 'Z') and chr(i) or '_')
                          for i in range(256)])
+PY_IDENTIFIER_MAX = 120
 
 def valid_identifier(stuff):
     stuff = str(stuff).translate(PY_IDENTIFIER)
     if not stuff or ('0' <= stuff[0] <= '9'):
         stuff = '_' + stuff
-    return stuff
+    return stuff[:PY_IDENTIFIER_MAX]
 
 CO_VARARGS      = 0x0004
 CO_VARKEYWORDS  = 0x0008



More information about the Pypy-commit mailing list