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