Author: Wim Lavrijsen <wlavrij...@lbl.gov>
Branch: reflex-support
Changeset: r53277:94adcd5155d2
Date: 2012-03-08 13:41 -0800
http://bitbucket.org/pypy/pypy/changeset/94adcd5155d2/

Log:    prevent infinite recursion on namespace lookups

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
@@ -90,16 +90,16 @@
     return property(binder, setter)
 
 
-def make_cppnamespace(namespace_name, cppns, build_in_full=True):
+def make_cppnamespace(scope, namespace_name, cppns, build_in_full=True):
     # build up a representation of a C++ namespace (namespaces are classes)
 
     # create a meta class to allow properties (for static data write access)
     metans = type(CppyyNamespaceMeta)(namespace_name+'_meta', 
(CppyyNamespaceMeta,), {})
 
     if cppns:
-        nsdct = {"_cpp_proxy" : cppns}
+        d = {"_cpp_proxy" : cppns}
     else:
-        nsdct = dict()
+        d = dict()
         def cpp_proxy_loader(cls):
             cpp_proxy = cppyy._type_byname(cls.__name__ != '::' and 
cls.__name__ or '')
             del cls.__class__._cpp_proxy
@@ -107,22 +107,27 @@
             return cpp_proxy
         metans._cpp_proxy = property(cpp_proxy_loader)
 
+    # create the python-side C++ namespace representation, cache in scope if 
given
+    pycppns = metans(namespace_name, (object,), d)
+    if scope:
+        setattr(scope, namespace_name, pycppns)
+
     if build_in_full:   # if False, rely on lazy build-up
         # insert static methods into the "namespace" dictionary
         for func_name in cppns.get_method_names():
             cppol = cppns.get_overload(func_name)
-            nsdct[func_name] = make_static_function(cppns, func_name, cppol)
+            pyfunc = make_static_function(cppns, func_name, cppol)
+            setattr(pycppns, func_name, pyfunc)
 
         # add all data members to the dictionary of the class to be created, 
and
         # static ones also to the meta class (needed for property setters)
         for dm in cppns.get_data_member_names():
             cppdm = cppns.get_data_member(dm)
             pydm = make_data_member(cppdm)
-            nsdct[dm] = pydm
+            setattr(pycppns, dm, pydm)
             setattr(metans, dm, pydm)
 
-    # create the python-side C++ namespace representation
-    return metans(namespace_name, (object,), nsdct)
+    return pycppns
 
 def _drop_cycles(bases):
     # TODO: figure this out, as it seems to be a PyPy bug?!
@@ -217,7 +222,7 @@
     cppitem = cppyy._type_byname(true_name)
     if cppitem:
         if cppitem.is_namespace():
-            pycppitem = make_cppnamespace(true_name, cppitem)
+            pycppitem = make_cppnamespace(scope, true_name, cppitem)
             setattr(scope, name, pycppitem)
         else:
             pycppitem = make_cppclass(scope, true_name, name, cppitem)
@@ -313,7 +318,6 @@
     if hasattr(pyclass, '__setitem__') and not hasattr(pyclass, 
'__getitem___'):
         pyclass.__getitem__ = pyclass.__setitem__
 
-
 _loaded_dictionaries = {}
 _loaded_dictionaries_isdirty = True     # should be per namespace
 def load_reflection_info(name):
@@ -330,7 +334,7 @@
 # user interface objects (note the two-step of not calling type_byname here:
 # creation of global functions may cause the creation of classes in the global
 # namespace, so gbl must exist at that point to cache them)
-gbl = make_cppnamespace("::", None, False)   # global C++ namespace
+gbl = make_cppnamespace(None, "::", None, False)   # global C++ namespace
 
 # mostly for the benefit of the CINT backend, which treats std as special
-gbl.std = make_cppnamespace("std", None, False)
+gbl.std = make_cppnamespace(None, "std", None, False)
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
@@ -3,3 +3,5 @@
 fragile::H::HH* fragile::H::HH::copy() {
     return (HH*)0;
 }
+
+fragile::I fragile::gI;
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
@@ -63,4 +63,11 @@
     HH* m_h;
 };
 
+class I {
+public:
+    operator bool() { return 0; }
+};
+
+extern I gI;
+
 } // namespace fragile
diff --git a/pypy/module/cppyy/test/fragile.xml 
b/pypy/module/cppyy/test/fragile.xml
--- a/pypy/module/cppyy/test/fragile.xml
+++ b/pypy/module/cppyy/test/fragile.xml
@@ -4,4 +4,6 @@
 
   <class pattern="fragile::[A-Z]" />
 
+  <variable name="fragile::gI" />
+
 </lcgdict>
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
@@ -14,5 +14,8 @@
 #pragma link C++ class fragile::F;
 #pragma link C++ class fragile::G;
 #pragma link C++ class fragile::H;
+#pragma link C++ class fragile::I;
+
+#pragma link C++ variable fragile::gI;
 
 #endif
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
@@ -145,3 +145,14 @@
         assert cppyy.gbl.fragile is fragile
 
         h = fragile.H()
+
+    def test09_operator_bool(self):
+        """Access to global vars with an operator bool() returning False"""
+
+        import cppyy
+
+        i = cppyy.gbl.fragile.I()
+        assert not i
+
+        g = cppyy.gbl.fragile.gI
+        assert not g
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to