Author: Wim Lavrijsen <[email protected]>
Branch: reflex-support
Changeset: r59758:4024dbe01c52
Date: 2013-01-04 19:10 -0800
http://bitbucket.org/pypy/pypy/changeset/4024dbe01c52/

Log:    o) tests and fix for shadowed data members o) some cleanup

diff --git a/pypy/module/cppyy/interp_cppyy.py 
b/pypy/module/cppyy/interp_cppyy.py
--- a/pypy/module/cppyy/interp_cppyy.py
+++ b/pypy/module/cppyy/interp_cppyy.py
@@ -9,7 +9,6 @@
 
 from pypy.rlib import jit, rdynload, rweakref
 from pypy.rlib import jit_libffi, clibffi
-from pypy.rlib.objectmodel import we_are_translated
 
 from pypy.module.cppyy import converter, executor, helper
 
@@ -1025,17 +1024,17 @@
         final_name = capi.c_scoped_final_name(handle)
         # the callback will cache the class by calling register_class
         w_pycppclass = space.call_function(state.w_clgen_callback, 
space.wrap(final_name))
-        assert w_pycppclass is state.cppclass_registry[handle]
     return w_pycppclass
 
 def wrap_new_cppobject_nocast(space, w_pycppclass, cppclass, rawobject, isref, 
python_owns):
     rawobject = rffi.cast(capi.C_OBJECT, rawobject)
     if space.is_w(w_pycppclass, space.w_None):
         w_pycppclass = get_pythonized_cppclass(space, cppclass.handle)
-    cppinstance = space.allocate_instance(W_CPPInstance, w_pycppclass)
-    W_CPPInstance.__init__(cppinstance, space, cppclass, rawobject, isref, 
python_owns)
+    w_cppinstance = space.allocate_instance(W_CPPInstance, w_pycppclass)
+    cppinstance = space.interp_w(W_CPPInstance, w_cppinstance)
+    cppinstance.__init__(space, cppclass, rawobject, isref, python_owns)
     memory_regulator.register(cppinstance)
-    return space.wrap(cppinstance)
+    return w_cppinstance
 
 def wrap_cppobject_nocast(space, w_pycppclass, cppclass, rawobject, isref, 
python_owns):
     rawobject = rffi.cast(capi.C_OBJECT, rawobject)
@@ -1049,11 +1048,17 @@
     if rawobject:
         actual = capi.c_actual_class(cppclass, rawobject)
         if actual != cppclass.handle:
-            offset = capi._c_base_offset(actual, cppclass.handle, rawobject, 
-1)
-            rawobject = capi.direct_ptradd(rawobject, offset)
-            w_pycppclass = get_pythonized_cppclass(space, actual)
-            w_cppclass = space.findattr(w_pycppclass, space.wrap("_cpp_proxy"))
-            cppclass = space.interp_w(W_CPPClass, w_cppclass, 
can_be_None=False)
+            try:
+                w_pycppclass = get_pythonized_cppclass(space, actual)
+                offset = capi._c_base_offset(actual, cppclass.handle, 
rawobject, -1)
+                rawobject = capi.direct_ptradd(rawobject, offset)
+                w_cppclass = space.findattr(w_pycppclass, 
space.wrap("_cpp_proxy"))
+                cppclass = space.interp_w(W_CPPClass, w_cppclass, 
can_be_None=False)
+            except Exception:
+                # failed to locate/build the derived class, so stick to the 
base (note
+                # that only get_pythonized_cppclass is expected to raise, so 
none of
+                # the variables are re-assigned yet)
+                pass
     return wrap_cppobject_nocast(space, w_pycppclass, cppclass, rawobject, 
isref, python_owns)
 
 @unwrap_spec(cppinstance=W_CPPInstance)
diff --git a/pypy/module/cppyy/pythonify.py b/pypy/module/cppyy/pythonify.py
--- a/pypy/module/cppyy/pythonify.py
+++ b/pypy/module/cppyy/pythonify.py
@@ -11,8 +11,9 @@
     def __getattr__(self, name):
         try:
             return get_pycppitem(self, name)  # will cache on self
-        except TypeError, t:
-            raise AttributeError("%s object has no attribute '%s'" % (self, 
name))
+        except Exception, e:
+            raise AttributeError("%s object has no attribute '%s' (details: 
%s)" %
+                                 (self, name, str(e)))
 
 class CppyyNamespaceMeta(CppyyScopeMeta):
     def __dir__(cls):
@@ -198,9 +199,12 @@
         cppdm = cppclass.get_datamember(dm_name)
         pydm = make_datamember(cppdm)
 
-        setattr(pycppclass, dm_name, pydm)
+        # here, setattr() can not be used, because a data member can shadow 
one in
+        # its base class, resulting in the __set__() of its base class being 
called
+        # by setattr(); so, store directly on the dictionary
+        pycppclass.__dict__[dm_name] = pydm
         if cppdm.is_static():
-            setattr(metacpp, dm_name, pydm)
+            metacpp.__dict__[dm_name] = pydm
 
     # the call to register will add back-end specific pythonizations and thus
     # needs to run first, so that the generic pythonizations can use them
diff --git a/pypy/module/cppyy/test/fragile.cxx 
b/pypy/module/cppyy/test/fragile.cxx
--- a/pypy/module/cppyy/test/fragile.cxx
+++ b/pypy/module/cppyy/test/fragile.cxx
@@ -9,3 +9,31 @@
 void fragile::fglobal(int, double, char) {
     /* empty; only used for doc-string testing */
 }
+
+namespace fragile {
+
+    class Kderived : public K {
+    public:
+        virtual ~Kderived();
+    };
+
+} // namespace fragile
+
+fragile::Kderived::~Kderived() {}
+
+fragile::K::~K() {}
+
+fragile::K* fragile::K::GimeK(bool derived) {
+    if (!derived) return this;
+    else {
+        static Kderived kd;
+        return &kd;
+    }
+};
+
+fragile::K* fragile::K::GimeL() {
+    static L l;
+    return &l;
+}
+
+fragile::L::~L() {}
diff --git a/pypy/module/cppyy/test/fragile.h b/pypy/module/cppyy/test/fragile.h
--- a/pypy/module/cppyy/test/fragile.h
+++ b/pypy/module/cppyy/test/fragile.h
@@ -87,4 +87,28 @@
     } // namespace nested2
 } // namespace nested1
 
+class K {
+public:
+    virtual ~K();
+    K* GimeK(bool derived);
+    K* GimeL();
+};
+
+class L : public K {
+public:
+    virtual ~L();
+    no_such_class* m_no_such;
+};
+
+class M {
+public:
+    enum E1 { kOnce=42 };
+    enum E2 { kTwice=12 };
+};
+
+class N : public M {
+public:
+    enum E2 { kTwice=12 };
+};
+
 } // namespace fragile
diff --git a/pypy/module/cppyy/test/fragile_LinkDef.h 
b/pypy/module/cppyy/test/fragile_LinkDef.h
--- a/pypy/module/cppyy/test/fragile_LinkDef.h
+++ b/pypy/module/cppyy/test/fragile_LinkDef.h
@@ -19,6 +19,10 @@
 #pragma link C++ class fragile::H;
 #pragma link C++ class fragile::I;
 #pragma link C++ class fragile::J;
+#pragma link C++ class fragile::K;
+#pragma link C++ class fragile::L;
+#pragma link C++ class fragile::M;
+#pragma link C++ class fragile::N;
 #pragma link C++ class fragile::nested1::A;
 #pragma link C++ class fragile::nested1::nested2::A;
 #pragma link C++ class fragile::nested1::nested2::nested3::A;
diff --git a/pypy/module/cppyy/test/test_cint.py 
b/pypy/module/cppyy/test/test_cint.py
--- a/pypy/module/cppyy/test/test_cint.py
+++ b/pypy/module/cppyy/test/test_cint.py
@@ -254,7 +254,7 @@
     def test05_branch_activation(self):
         """Test of automatic branch activation"""
 
-        from cppyy import gbl               # bootstraps, only needed for tests
+        from cppyy import gbl
         from cppyy.gbl import TFile, TTree
         from cppyy.gbl.std import vector
 
@@ -306,3 +306,19 @@
             i += 1
         assert i == self.N
 
+
+class AppTestRegression:
+    spaceconfig = dict(usemodules=['cppyy'])
+
+    def test01_regression(self):
+        """TPaveText::AddText() used to result in KeyError"""
+
+        # This is where the original problem was discovered, and the test is
+        # left in. However, the detailed underlying problem, as well as the
+        # solution to it, is tested in test_fragile.py
+
+        from cppyy import gbl
+        from cppyy.gbl import TPaveText
+
+        hello = TPaveText( .1, .8, .9, .97 )
+        hello.AddText( 'Hello, World!' )
diff --git a/pypy/module/cppyy/test/test_fragile.py 
b/pypy/module/cppyy/test/test_fragile.py
--- a/pypy/module/cppyy/test/test_fragile.py
+++ b/pypy/module/cppyy/test/test_fragile.py
@@ -255,3 +255,32 @@
 
         from cppyy.gbl.fragile.nested1.nested2.nested3 import A
         assert cppyy.gbl.fragile.nested1.nested2.nested3.A is nested3.A
+
+    def test13_missing_casts(self):
+        """Test proper handling when a hierarchy is not fully available"""
+
+        import cppyy
+
+        k = cppyy.gbl.fragile.K()
+
+        assert k is k.GimeK(False)
+        assert k is not k.GimeK(True)
+
+        kd = k.GimeK(True)
+        assert kd is k.GimeK(True)
+        assert kd is not k.GimeK(False)
+
+        l = k.GimeL()
+        assert l is k.GimeL()
+
+    def test14_double_enum_trouble(self):
+        """Test a redefinition of enum in a derived class"""
+
+        import cppyy
+
+        M = cppyy.gbl.fragile.M
+        N = cppyy.gbl.fragile.N
+
+        assert M.kOnce == N.kOnce
+        assert M.kTwice == N.kTwice
+        assert M.__dict__['kTwice'] is not N.__dict__['kTwice']
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to