[pypy-commit] pypy cppyy-packaging: more settable overload properties
wlav
pypy.commits at gmail.com
Tue Jul 17 02:01:36 EDT 2018
Author: Wim Lavrijsen <WLavrijsen at 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
More information about the pypy-commit
mailing list