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