Author: Wim Lavrijsen <wlavrij...@lbl.gov> Branch: cppyy-packaging Changeset: r94868:c67865f23398 Date: 2018-07-15 20:17 -0700 http://bitbucket.org/pypy/pypy/changeset/c67865f23398/
Log: more settable overload properties 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 @@ -24,6 +24,7 @@ INSTANCE_FLAGS_IS_RVALUE = 0x0004 OVERLOAD_FLAGS_USE_FFI = 0x0001 +OVERLOAD_FLAGS_CREATES = 0x0002 FUNCTION_IS_GLOBAL = 0x0001 FUNCTION_IS_STATIC = 0x0001 @@ -458,6 +459,36 @@ # need forwarding, which the normal instancemethod does not provide, hence this # derived class. class MethodWithProps(Method): + # set life management of result from the call + def fget_creates(self, space): + f = space.interp_w(W_CPPOverload, self.w_function) + return f.fget_creates(space) + + @unwrap_spec(value=bool) + def fset_creates(self, space, value): + f = space.interp_w(W_CPPOverload, self.w_function) + f.fset_creates(space, value) + + # set ownership policy of arguments (not yet implemented) + def fget_mempolicy(self, space): + f = space.interp_w(W_CPPOverload, self.w_function) + return f.fget_mempolicy(space) + + @unwrap_spec(value=int) + def fset_mempolicy(self, space, value): + f = space.interp_w(W_CPPOverload, self.w_function) + f.fset_mempolicy(space, value) + + # set to release the gil during call (not yet implemented) + def fget_release_gil(self, space): + f = space.interp_w(W_CPPOverload, self.w_function) + return f.fget_release_gil(space) + + @unwrap_spec(value=bool) + def fset_release_gil(self, space, value): + f = space.interp_w(W_CPPOverload, self.w_function) + f.fset_release_gil(space, value) + # allow user to determine ffi use rules per overload def fget_useffi(self, space): f = space.interp_w(W_CPPOverload, self.w_function) @@ -473,22 +504,25 @@ __doc__ = """cpp_instancemethod(function, instance, class) Create an instance method object.""", - __new__ = interp2app(MethodWithProps.descr_method__new__.im_func), - __call__ = interp2app(MethodWithProps.descr_method_call), - __get__ = interp2app(MethodWithProps.descr_method_get), - im_func = interp_attrproperty_w('w_function', cls=MethodWithProps), - __func__ = interp_attrproperty_w('w_function', cls=MethodWithProps), - im_self = interp_attrproperty_w('w_instance', cls=MethodWithProps), - __self__ = interp_attrproperty_w('w_instance', cls=MethodWithProps), - im_class = interp_attrproperty_w('w_class', cls=MethodWithProps), + __new__ = interp2app(MethodWithProps.descr_method__new__.im_func), + __call__ = interp2app(MethodWithProps.descr_method_call), + __get__ = interp2app(MethodWithProps.descr_method_get), + im_func = interp_attrproperty_w('w_function', cls=MethodWithProps), + __func__ = interp_attrproperty_w('w_function', cls=MethodWithProps), + im_self = interp_attrproperty_w('w_instance', cls=MethodWithProps), + __self__ = interp_attrproperty_w('w_instance', cls=MethodWithProps), + im_class = interp_attrproperty_w('w_class', cls=MethodWithProps), __getattribute__ = interp2app(MethodWithProps.descr_method_getattribute), - __eq__ = interp2app(MethodWithProps.descr_method_eq), - __ne__ = descr_generic_ne, - __hash__ = interp2app(MethodWithProps.descr_method_hash), - __repr__ = interp2app(MethodWithProps.descr_method_repr), - __reduce__ = interp2app(MethodWithProps.descr_method__reduce__), - __weakref__ = make_weakref_descr(MethodWithProps), - __useffi__ = GetSetProperty(MethodWithProps.fget_useffi, MethodWithProps.fset_useffi), + __eq__ = interp2app(MethodWithProps.descr_method_eq), + __ne__ = descr_generic_ne, + __hash__ = interp2app(MethodWithProps.descr_method_hash), + __repr__ = interp2app(MethodWithProps.descr_method_repr), + __reduce__ = interp2app(MethodWithProps.descr_method__reduce__), + __weakref__ = make_weakref_descr(MethodWithProps), + __creates__ = GetSetProperty(MethodWithProps.fget_creates, MethodWithProps.fset_creates), + __mempolicy__ = GetSetProperty(MethodWithProps.fget_mempolicy, MethodWithProps.fset_mempolicy), + __release_gil__ = GetSetProperty(MethodWithProps.fget_release_gil, MethodWithProps.fset_release_gil), + __useffi__ = GetSetProperty(MethodWithProps.fget_useffi, MethodWithProps.fset_useffi), ) MethodWithProps.typedef.acceptable_as_base_class = False @@ -551,7 +585,12 @@ for i in range(len(self.functions)): cppyyfunc = self.functions[i] try: - return cppyyfunc.call(cppthis, args_w, self.flags & OVERLOAD_FLAGS_USE_FFI) + w_result = cppyyfunc.call(cppthis, args_w, self.flags & OVERLOAD_FLAGS_USE_FFI) + if self.flags & OVERLOAD_FLAGS_CREATES: + if isinstance(w_result, W_CPPInstance): + cppinstance = self.space.interp_w(W_CPPInstance, w_result) + cppinstance.fset_python_owns(self.space, self.space.w_True) + return w_result except Exception: pass @@ -564,6 +603,7 @@ for i in range(len(self.functions)): cppyyfunc = self.functions[i] try: + # no need to set ownership on the return value, as none of the methods execute return cppyyfunc.call(cppthis, args_w, self.flags & OVERLOAD_FLAGS_USE_FFI) except OperationError as e: # special case if there's just one function, to prevent clogging the error message @@ -602,6 +642,33 @@ return W_CPPOverload(self.space, self.scope, [f]) raise oefmt(self.space.w_LookupError, "signature '%s' not found", signature) + # set life management of result from the call + def fget_creates(self, space): + return space.newbool(bool(self.flags & OVERLOAD_FLAGS_CREATES)) + + @unwrap_spec(value=bool) + def fset_creates(self, space, value): + if space.is_true(value): + self.flags |= OVERLOAD_FLAGS_CREATES + else: + self.flags &= ~OVERLOAD_FLAGS_CREATES + + # set ownership policy of arguments (not yet implemented) + def fget_mempolicy(self, space): + return space.newint(0) + + @unwrap_spec(value=int) + def fset_mempolicy(self, space, value): + pass + + # set to release the gil during call (not yet implemented) + def fget_release_gil(self, space): + return space.newbool(True) + + @unwrap_spec(value=bool) + def fset_release_gil(self, space, value): + pass + # allow user to determine ffi use rules per overload def fget_useffi(self, space): return space.newbool(bool(self.flags & OVERLOAD_FLAGS_USE_FFI)) @@ -625,11 +692,14 @@ W_CPPOverload.typedef = TypeDef( 'CPPOverload', - __get__ = interp2app(W_CPPOverload.descr_get), - __call__ = interp2app(W_CPPOverload.call_args), - __useffi__ = GetSetProperty(W_CPPOverload.fget_useffi, W_CPPOverload.fset_useffi), - __overload__ = interp2app(W_CPPOverload.mp_overload), - __doc__ = GetSetProperty(W_CPPOverload.fget_doc) + __get__ = interp2app(W_CPPOverload.descr_get), + __call__ = interp2app(W_CPPOverload.call_args), + __creates__ = GetSetProperty(W_CPPOverload.fget_creates, W_CPPOverload.fset_creates), + __mempolicy__ = GetSetProperty(W_CPPOverload.fget_mempolicy, W_CPPOverload.fset_mempolicy), + __release_gil__ = GetSetProperty(W_CPPOverload.fget_release_gil, W_CPPOverload.fset_release_gil), + __useffi__ = GetSetProperty(W_CPPOverload.fget_useffi, W_CPPOverload.fset_useffi), + __overload__ = interp2app(W_CPPOverload.mp_overload), + __doc__ = GetSetProperty(W_CPPOverload.fget_doc) ) @@ -658,11 +728,14 @@ W_CPPStaticOverload.typedef = TypeDef( 'CPPStaticOverload', - __get__ = interp2app(W_CPPStaticOverload.descr_get), - __call__ = interp2app(W_CPPStaticOverload.call_args), - __useffi__ = GetSetProperty(W_CPPStaticOverload.fget_useffi, W_CPPStaticOverload.fset_useffi), - __overload__ = interp2app(W_CPPStaticOverload.mp_overload), - __doc__ = GetSetProperty(W_CPPStaticOverload.fget_doc) + __get__ = interp2app(W_CPPStaticOverload.descr_get), + __call__ = interp2app(W_CPPStaticOverload.call_args), + __creates__ = GetSetProperty(W_CPPStaticOverload.fget_creates, W_CPPStaticOverload.fset_creates), + __mempolicy__ = GetSetProperty(W_CPPStaticOverload.fget_mempolicy, W_CPPStaticOverload.fset_mempolicy), + __release_gil__ = GetSetProperty(W_CPPStaticOverload.fget_release_gil, W_CPPStaticOverload.fset_release_gil), + __useffi__ = GetSetProperty(W_CPPStaticOverload.fget_useffi, W_CPPStaticOverload.fset_useffi), + __overload__ = interp2app(W_CPPStaticOverload.mp_overload), + __doc__ = GetSetProperty(W_CPPStaticOverload.fget_doc) ) @@ -871,11 +944,14 @@ W_CPPTemplateOverload.typedef = TypeDef( 'CPPTemplateOverload', - __get__ = interp2app(W_CPPTemplateOverload.descr_get), - __getitem__ = interp2app(W_CPPTemplateOverload.getitem), - __call__ = interp2app(W_CPPTemplateOverload.call_args), - __useffi__ = GetSetProperty(W_CPPTemplateOverload.fget_useffi, W_CPPTemplateOverload.fset_useffi), - __doc__ = GetSetProperty(W_CPPTemplateOverload.fget_doc) + __get__ = interp2app(W_CPPTemplateOverload.descr_get), + __getitem__ = interp2app(W_CPPTemplateOverload.getitem), + __call__ = interp2app(W_CPPTemplateOverload.call_args), + __creates__ = GetSetProperty(W_CPPTemplateOverload.fget_creates, W_CPPTemplateOverload.fset_creates), + __mempolicy__ = GetSetProperty(W_CPPTemplateOverload.fget_mempolicy, W_CPPTemplateOverload.fset_mempolicy), + __release_gil__ = GetSetProperty(W_CPPTemplateOverload.fget_release_gil, W_CPPTemplateOverload.fset_release_gil), + __useffi__ = GetSetProperty(W_CPPTemplateOverload.fget_useffi, W_CPPTemplateOverload.fset_useffi), + __doc__ = GetSetProperty(W_CPPTemplateOverload.fget_doc) ) class W_CPPTemplateStaticOverload(W_CPPStaticOverload, TemplateOverloadMixin): @@ -929,11 +1005,18 @@ W_CPPTemplateStaticOverload.typedef = TypeDef( 'CPPTemplateStaticOverload', - __get__ = interp2app(W_CPPTemplateStaticOverload.descr_get), - __getitem__ = interp2app(W_CPPTemplateStaticOverload.getitem), - __call__ = interp2app(W_CPPTemplateStaticOverload.call_args), - __useffi__ = GetSetProperty(W_CPPTemplateStaticOverload.fget_useffi, W_CPPTemplateStaticOverload.fset_useffi), - __doc__ = GetSetProperty(W_CPPTemplateStaticOverload.fget_doc) + __get__ = interp2app(W_CPPTemplateStaticOverload.descr_get), + __getitem__ = interp2app(W_CPPTemplateStaticOverload.getitem), + __call__ = interp2app(W_CPPTemplateStaticOverload.call_args), + __creates__ = GetSetProperty(W_CPPTemplateStaticOverload.fget_creates, + W_CPPTemplateStaticOverload.fset_creates), + __mempolicy__ = GetSetProperty(W_CPPTemplateStaticOverload.fget_mempolicy, + W_CPPTemplateStaticOverload.fset_mempolicy), + __release_gil__ = GetSetProperty(W_CPPTemplateStaticOverload.fget_release_gil, + W_CPPTemplateStaticOverload.fset_release_gil), + __useffi__ = GetSetProperty(W_CPPTemplateStaticOverload.fget_useffi, + W_CPPTemplateStaticOverload.fset_useffi), + __doc__ = GetSetProperty(W_CPPTemplateStaticOverload.fget_doc) ) diff --git a/pypy/module/_cppyy/test/pythonizables.cxx b/pypy/module/_cppyy/test/pythonizables.cxx --- a/pypy/module/_cppyy/test/pythonizables.cxx +++ b/pypy/module/_cppyy/test/pythonizables.cxx @@ -27,3 +27,5 @@ unsigned int pyzables::pass_mine_rp(Countable c) { return c.m_check; } unsigned int pyzables::pass_mine_rp_ref(const Countable& c) { return c.m_check; } unsigned int pyzables::pass_mine_rp_ptr(const Countable* c) { return c->m_check; } + +pyzables::Countable* pyzables::gime_naked_countable() { return new Countable{}; } diff --git a/pypy/module/_cppyy/test/pythonizables.h b/pypy/module/_cppyy/test/pythonizables.h --- a/pypy/module/_cppyy/test/pythonizables.h +++ b/pypy/module/_cppyy/test/pythonizables.h @@ -57,4 +57,6 @@ unsigned int pass_mine_rp_ref(const Countable&); unsigned int pass_mine_rp_ptr(const Countable*); +Countable* gime_naked_countable(); + } // namespace pyzables diff --git a/pypy/module/_cppyy/test/test_advancedcpp.py b/pypy/module/_cppyy/test/test_advancedcpp.py --- a/pypy/module/_cppyy/test/test_advancedcpp.py +++ b/pypy/module/_cppyy/test/test_advancedcpp.py @@ -686,11 +686,11 @@ assert cppyy.gbl.my_global_double == 12. assert len(cppyy.gbl.my_global_array) == 500 assert cppyy.gbl.my_global_string1 == "aap noot mies" - return # next line currently crashes assert cppyy.gbl.my_global_string2 == "zus jet teun" # TODO: currently fails b/c double** not understood as &double* #assert cppyy.gbl.my_global_ptr[0] == 1234. + return v = cppyy.gbl.my_global_int_holders assert len(v) == 5 expected_vals = [13, 42, 88, -1, 17] diff --git a/pypy/module/_cppyy/test/test_pythonization.py b/pypy/module/_cppyy/test/test_pythonization.py --- a/pypy/module/_cppyy/test/test_pythonization.py +++ b/pypy/module/_cppyy/test/test_pythonization.py @@ -17,14 +17,20 @@ cls.w_datatypes = cls.space.appexec([], """(): import ctypes, _cppyy _cppyy._post_import_startup() + class py(object): + pass + py.add_pythonization = _cppyy.add_pythonization + py.remove_pythonization = _cppyy.remove_pythonization + py.pin_type = _cppyy._pin_type + _cppyy.py = py return ctypes.CDLL(%r, ctypes.RTLD_GLOBAL)""" % (test_dct, )) def test00_api(self): """Test basic semantics of the pythonization API""" - import _cppyy + import _cppyy as cppyy - raises(TypeError, _cppyy.add_pythonization, 1) + raises(TypeError, cppyy.py.add_pythonization, 1) def pythonizor1(klass, name): pass @@ -34,31 +40,26 @@ pythonizor3 = pythonizor1 - _cppyy.add_pythonization(pythonizor1) - assert _cppyy.remove_pythonization(pythonizor2) == False - assert _cppyy.remove_pythonization(pythonizor3) == True - - def test01_more_api(self): - """Further API semantics""" - - import _cppyy as cppyy + cppyy.py.add_pythonization(pythonizor1) + assert cppyy.py.remove_pythonization(pythonizor2) == False + assert cppyy.py.remove_pythonization(pythonizor3) == True def pythonizor(klass, name): if name == 'pyzables::SomeDummy1': klass.test = 1 - cppyy.add_pythonization(pythonizor) + cppyy.py.add_pythonization(pythonizor) assert cppyy.gbl.pyzables.SomeDummy1.test == 1 def pythonizor(klass, name): if name == 'SomeDummy2': klass.test = 2 - cppyy.add_pythonization(pythonizor, 'pyzables') + cppyy.py.add_pythonization(pythonizor, 'pyzables') def pythonizor(klass, name): if name == 'pyzables::SomeDummy2': klass.test = 3 - cppyy.add_pythonization(pythonizor) + cppyy.py.add_pythonization(pythonizor) assert cppyy.gbl.pyzables.SomeDummy2.test == 2 @@ -66,28 +67,24 @@ if name == 'TString': klass.__len__ = klass.Length - cppyy.add_pythonization(root_pythonizor) + cppyy.py.add_pythonization(root_pythonizor) assert len(cppyy.gbl.TString("aap")) == 3 - def test02_type_pinning(self): + def test01_type_pinning(self): """Verify pinnability of returns""" import _cppyy as cppyy - # TODO: disabled for now until decided on proper naming/iface - return - - cppyy.gbl.pyzables.GimeDerived._creates = True + cppyy.gbl.pyzables.GimeDerived.__creates__ = True result = cppyy.gbl.pyzables.GimeDerived() assert type(result) == cppyy.gbl.pyzables.MyDerived - cppyy._pin_type(cppyy.gbl.pyzables.MyBase) + cppyy.py.pin_type(cppyy.gbl.pyzables.MyBase) assert type(result) == cppyy.gbl.pyzables.MyDerived - - def test03_transparency(self): + def test02_transparency(self): """Transparent use of smart pointers""" import _cppyy as cppyy @@ -101,7 +98,7 @@ assert mine.__smartptr__().get().m_check == 0xcdcdcdcd assert mine.say_hi() == "Hi!" - def test04_converters(self): + def test03_converters(self): """Smart pointer argument passing""" import _cppyy as cppyy @@ -126,7 +123,7 @@ # cppyy.gbl.mine = mine pz.renew_mine() - def test05_executors(self): + def test04_executors(self): """Smart pointer return types""" import _cppyy as cppyy @@ -154,3 +151,25 @@ assert type(mine.__smartptr__()) == cppyy.gbl.std.shared_ptr(Countable) assert mine.__smartptr__().get().m_check == 0xcdcdcdcd assert mine.say_hi() == "Hi!" + + def test05_creates_flag(self): + """Effect of creates flag on return type""" + + import _cppyy as cppyy + import gc + + pz = cppyy.gbl.pyzables + Countable = pz.Countable + + gc.collect() + oldcount = Countable.sInstances # there's eg. one global variable + + pz.gime_naked_countable.__creates__ = True + for i in range(10): + cnt = pz.gime_naked_countable() + gc.collect() + assert Countable.sInstances == oldcount + 1 + del cnt + gc.collect() + + assert Countable.sInstances == oldcount diff --git a/pypy/module/_cppyy/test/test_zjit.py b/pypy/module/_cppyy/test/test_zjit.py --- a/pypy/module/_cppyy/test/test_zjit.py +++ b/pypy/module/_cppyy/test/test_zjit.py @@ -141,6 +141,9 @@ self.w_TypeError = FakeException(self, "TypeError") self.w_ValueError = FakeException(self, "ValueError") + self.w_True = FakeBool(True) + self.w_False = FakeBool(False) + def issequence_w(self, w_obj): return True _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit