[pypy-commit] pypy cppyy-packaging: clearer naming and __cppname__ property for classes
wlav
pypy.commits at gmail.com
Sat Oct 7 09:08:58 EDT 2017
Author: Wim Lavrijsen <WLavrijsen at lbl.gov>
Branch: cppyy-packaging
Changeset: r92592:0a1c3153a7e5
Date: 2017-09-22 15:17 -0700
http://bitbucket.org/pypy/pypy/changeset/0a1c3153a7e5/
Log: clearer naming and __cppname__ property for classes
diff --git a/pypy/module/_cppyy/__init__.py b/pypy/module/_cppyy/__init__.py
--- a/pypy/module/_cppyy/__init__.py
+++ b/pypy/module/_cppyy/__init__.py
@@ -13,7 +13,7 @@
'_set_function_generator': 'interp_cppyy.set_function_generator',
'_register_class' : 'interp_cppyy.register_class',
'_get_nullptr' : 'interp_cppyy.get_nullptr',
- 'CPPInstanceBase' : 'interp_cppyy.W_CPPInstance',
+ 'CPPClassBase' : 'interp_cppyy.W_CPPClass',
'addressof' : 'interp_cppyy.addressof',
'bind_object' : 'interp_cppyy.bind_object',
}
diff --git a/pypy/module/_cppyy/capi/loadable_capi.py b/pypy/module/_cppyy/capi/loadable_capi.py
--- a/pypy/module/_cppyy/capi/loadable_capi.py
+++ b/pypy/module/_cppyy/capi/loadable_capi.py
@@ -594,7 +594,7 @@
"""Return a python string taking into account \0"""
from pypy.module._cppyy import interp_cppyy
- cppstr = space.interp_w(interp_cppyy.W_CPPInstance, w_self, can_be_None=False)
+ cppstr = space.interp_w(interp_cppyy.W_CPPClass, w_self, can_be_None=False)
return space.newtext(c_stdstring2charp(space, cppstr._rawobject))
# setup pythonizations for later use at run-time
diff --git a/pypy/module/_cppyy/converter.py b/pypy/module/_cppyy/converter.py
--- a/pypy/module/_cppyy/converter.py
+++ b/pypy/module/_cppyy/converter.py
@@ -22,8 +22,8 @@
def get_rawobject(space, w_obj):
- from pypy.module._cppyy.interp_cppyy import W_CPPInstance
- cppinstance = space.interp_w(W_CPPInstance, w_obj, can_be_None=True)
+ from pypy.module._cppyy.interp_cppyy import W_CPPClass
+ cppinstance = space.interp_w(W_CPPClass, w_obj, can_be_None=True)
if cppinstance:
rawobject = cppinstance.get_rawobject()
assert lltype.typeOf(rawobject) == capi.C_OBJECT
@@ -31,15 +31,15 @@
return capi.C_NULL_OBJECT
def set_rawobject(space, w_obj, address):
- from pypy.module._cppyy.interp_cppyy import W_CPPInstance
- cppinstance = space.interp_w(W_CPPInstance, w_obj, can_be_None=True)
+ from pypy.module._cppyy.interp_cppyy import W_CPPClass
+ cppinstance = space.interp_w(W_CPPClass, w_obj, can_be_None=True)
if cppinstance:
assert lltype.typeOf(cppinstance._rawobject) == capi.C_OBJECT
cppinstance._rawobject = rffi.cast(capi.C_OBJECT, address)
def get_rawobject_nonnull(space, w_obj):
- from pypy.module._cppyy.interp_cppyy import W_CPPInstance
- cppinstance = space.interp_w(W_CPPInstance, w_obj, can_be_None=True)
+ from pypy.module._cppyy.interp_cppyy import W_CPPClass
+ cppinstance = space.interp_w(W_CPPClass, w_obj, can_be_None=True)
if cppinstance:
cppinstance._nullcheck()
rawobject = cppinstance.get_rawobject()
@@ -484,24 +484,24 @@
typecode = 'V'
class InstanceRefConverter(TypeConverter):
- _immutable_fields_ = ['typecode', 'cppclass']
+ _immutable_fields_ = ['typecode', 'clsdecl']
typecode = 'V'
- def __init__(self, space, cppclass):
- from pypy.module._cppyy.interp_cppyy import W_CPPClass
- assert isinstance(cppclass, W_CPPClass)
- self.cppclass = cppclass
+ def __init__(self, space, clsdecl):
+ from pypy.module._cppyy.interp_cppyy import W_CPPClassDecl
+ assert isinstance(clsdecl, W_CPPClassDecl)
+ self.clsdecl = clsdecl
def _unwrap_object(self, space, w_obj):
- from pypy.module._cppyy.interp_cppyy import W_CPPInstance
- if isinstance(w_obj, W_CPPInstance):
- if capi.c_is_subtype(space, w_obj.cppclass, self.cppclass):
+ from pypy.module._cppyy.interp_cppyy import W_CPPClass
+ if isinstance(w_obj, W_CPPClass):
+ if capi.c_is_subtype(space, w_obj.cppclass, self.clsdecl):
rawobject = w_obj.get_rawobject()
- offset = capi.c_base_offset(space, w_obj.cppclass, self.cppclass, rawobject, 1)
+ offset = capi.c_base_offset(space, w_obj.cppclass, self.clsdecl, rawobject, 1)
obj_address = capi.direct_ptradd(rawobject, offset)
return rffi.cast(capi.C_OBJECT, obj_address)
raise oefmt(space.w_TypeError,
- "cannot pass %T as %s", w_obj, self.cppclass.name)
+ "cannot pass %T as %s", w_obj, self.clsdecl.name)
def cffi_type(self, space):
state = space.fromcache(ffitypes.State)
@@ -527,7 +527,7 @@
def from_memory(self, space, w_obj, w_pycppclass, offset):
address = rffi.cast(capi.C_OBJECT, self._get_raw_address(space, w_obj, offset))
from pypy.module._cppyy import interp_cppyy
- return interp_cppyy.wrap_cppobject(space, address, self.cppclass, do_cast=False)
+ return interp_cppyy.wrap_cppobject(space, address, self.clsdecl, do_cast=False)
def to_memory(self, space, w_obj, w_value, offset):
self._is_abstract(space)
@@ -548,7 +548,7 @@
def from_memory(self, space, w_obj, w_pycppclass, offset):
address = rffi.cast(capi.C_OBJECT, self._get_raw_address(space, w_obj, offset))
from pypy.module._cppyy import interp_cppyy
- return interp_cppyy.wrap_cppobject(space, address, self.cppclass, do_cast=False)
+ return interp_cppyy.wrap_cppobject(space, address, self.clsdecl, do_cast=False)
def to_memory(self, space, w_obj, w_value, offset):
address = rffi.cast(rffi.VOIDPP, self._get_raw_address(space, w_obj, offset))
@@ -574,15 +574,15 @@
raise FastCallNotPossible
def finalize_call(self, space, w_obj, call_local):
- from pypy.module._cppyy.interp_cppyy import W_CPPInstance
- assert isinstance(w_obj, W_CPPInstance)
+ from pypy.module._cppyy.interp_cppyy import W_CPPClass
+ assert isinstance(w_obj, W_CPPClass)
r = rffi.cast(rffi.VOIDPP, call_local)
w_obj._rawobject = rffi.cast(capi.C_OBJECT, r[0])
def from_memory(self, space, w_obj, w_pycppclass, offset):
address = rffi.cast(capi.C_OBJECT, self._get_raw_address(space, w_obj, offset))
from pypy.module._cppyy import interp_cppyy
- return interp_cppyy.wrap_cppobject(space, address, self.cppclass,
+ return interp_cppyy.wrap_cppobject(space, address, self.clsdecl,
do_cast=False, is_ref=True)
class StdStringConverter(InstanceConverter):
@@ -593,8 +593,8 @@
InstanceConverter.__init__(self, space, cppclass)
def _unwrap_object(self, space, w_obj):
- from pypy.module._cppyy.interp_cppyy import W_CPPInstance
- if isinstance(w_obj, W_CPPInstance):
+ from pypy.module._cppyy.interp_cppyy import W_CPPClass
+ if isinstance(w_obj, W_CPPClass):
arg = InstanceConverter._unwrap_object(self, space, w_obj)
return capi.c_stdstring2stdstring(space, arg)
else:
@@ -603,15 +603,15 @@
def to_memory(self, space, w_obj, w_value, offset):
try:
address = rffi.cast(capi.C_OBJECT, self._get_raw_address(space, w_obj, offset))
- assign = self.cppclass.get_overload("__assign__")
+ assign = self.clsdecl.get_overload("__assign__")
from pypy.module._cppyy import interp_cppyy
assign.call(
- interp_cppyy.wrap_cppobject(space, address, self.cppclass, do_cast=False), [w_value])
+ interp_cppyy.wrap_cppobject(space, address, self.clsdecl, do_cast=False), [w_value])
except Exception:
InstanceConverter.to_memory(self, space, w_obj, w_value, offset)
def free_argument(self, space, arg, call_local):
- capi.c_destruct(space, self.cppclass, rffi.cast(capi.C_OBJECT, rffi.cast(rffi.VOIDPP, arg)[0]))
+ capi.c_destruct(space, self.clsdecl, rffi.cast(capi.C_OBJECT, rffi.cast(rffi.VOIDPP, arg)[0]))
class StdStringRefConverter(InstancePtrConverter):
_immutable_fields_ = ['cppclass', 'typecode']
@@ -710,19 +710,19 @@
# 4) generalized cases (covers basically all user classes)
from pypy.module._cppyy import interp_cppyy
- cppclass = interp_cppyy.scope_byname(space, clean_name)
- if cppclass:
+ scope_decl = interp_cppyy.scope_byname(space, clean_name)
+ if scope_decl:
# type check for the benefit of the annotator
- from pypy.module._cppyy.interp_cppyy import W_CPPClass
- cppclass = space.interp_w(W_CPPClass, cppclass, can_be_None=False)
+ from pypy.module._cppyy.interp_cppyy import W_CPPClassDecl
+ clsdecl = space.interp_w(W_CPPClassDecl, scope_decl, can_be_None=False)
if compound == "*":
- return InstancePtrConverter(space, cppclass)
+ return InstancePtrConverter(space, clsdecl)
elif compound == "&":
- return InstanceRefConverter(space, cppclass)
+ return InstanceRefConverter(space, clsdecl)
elif compound == "**":
- return InstancePtrPtrConverter(space, cppclass)
+ return InstancePtrPtrConverter(space, clsdecl)
elif compound == "":
- return InstanceConverter(space, cppclass)
+ return InstanceConverter(space, clsdecl)
elif capi.c_is_enum(space, clean_name):
return _converters['unsigned'](space, default)
diff --git a/pypy/module/_cppyy/executor.py b/pypy/module/_cppyy/executor.py
--- a/pypy/module/_cppyy/executor.py
+++ b/pypy/module/_cppyy/executor.py
@@ -281,8 +281,8 @@
cppclass = interp_cppyy.scope_byname(space, clean_name)
if cppclass:
# type check for the benefit of the annotator
- from pypy.module._cppyy.interp_cppyy import W_CPPClass
- cppclass = space.interp_w(W_CPPClass, cppclass, can_be_None=False)
+ from pypy.module._cppyy.interp_cppyy import W_CPPClassDecl
+ cppclass = space.interp_w(W_CPPClassDecl, cppclass, can_be_None=False)
if compound == '':
return InstanceExecutor(space, cppclass)
elif compound == '*' or compound == '&':
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
@@ -34,7 +34,7 @@
class State(object):
def __init__(self, space):
self.cppscope_cache = {
- "void" : W_CPPClass(space, "void", capi.C_NULL_TYPE) }
+ "void" : W_CPPClassDecl(space, "void", capi.C_NULL_TYPE) }
self.w_nullptr = None
self.cpptemplate_cache = {}
self.cppclass_registry = {}
@@ -77,11 +77,11 @@
if opaque_handle:
final_name = capi.c_final_name(space, opaque_handle)
if capi.c_is_namespace(space, opaque_handle):
- cppscope = W_CPPNamespace(space, final_name, opaque_handle)
+ cppscope = W_CPPNamespaceDecl(space, final_name, opaque_handle)
elif capi.c_has_complex_hierarchy(space, opaque_handle):
- cppscope = W_ComplexCPPClass(space, final_name, opaque_handle)
+ cppscope = W_CPPComplexClass(space, final_name, opaque_handle)
else:
- cppscope = W_CPPClass(space, final_name, opaque_handle)
+ cppscope = W_CPPClassDecl(space, final_name, opaque_handle)
state.cppscope_cache[name] = cppscope
cppscope._build_methods()
@@ -119,8 +119,8 @@
state.w_fngen_callback = w_callback
def register_class(space, w_pycppclass):
- w_cppclass = space.findattr(w_pycppclass, space.newtext("_cpp_proxy"))
- cppclass = space.interp_w(W_CPPClass, w_cppclass, can_be_None=False)
+ w_cppclass = space.findattr(w_pycppclass, space.newtext("__cppdecl__"))
+ cppclass = space.interp_w(W_CPPClassDecl, w_cppclass, can_be_None=False)
# add back-end specific method pythonizations (doing this on the wrapped
# class allows simple aliasing of methods)
capi.pythonize(space, cppclass.name, w_pycppclass)
@@ -169,7 +169,7 @@
@staticmethod
def unpack_cppthis(space, w_cppinstance, declaring_scope):
- cppinstance = space.interp_w(W_CPPInstance, w_cppinstance, can_be_None=False)
+ cppinstance = space.interp_w(W_CPPClass, w_cppinstance, can_be_None=False)
cppinstance._nullcheck()
return cppinstance.get_cppthis(declaring_scope)
@@ -593,7 +593,7 @@
def call(self, w_cppinstance, args_w):
w_result = W_CPPOverload.call(self, w_cppinstance, args_w)
newthis = rffi.cast(capi.C_OBJECT, self.space.uint_w(w_result))
- cppinstance = self.space.interp_w(W_CPPInstance, w_cppinstance, can_be_None=True)
+ cppinstance = self.space.interp_w(W_CPPClass, w_cppinstance, can_be_None=True)
if cppinstance is not None:
cppinstance._rawobject = newthis
memory_regulator.register(cppinstance)
@@ -650,7 +650,7 @@
return offset
def get(self, w_cppinstance, w_pycppclass):
- cppinstance = self.space.interp_w(W_CPPInstance, w_cppinstance, can_be_None=True)
+ cppinstance = self.space.interp_w(W_CPPClass, w_cppinstance, can_be_None=True)
if not cppinstance:
raise oefmt(self.space.w_ReferenceError,
"attribute access requires an instance")
@@ -658,7 +658,7 @@
return self.converter.from_memory(self.space, w_cppinstance, w_pycppclass, offset)
def set(self, w_cppinstance, w_value):
- cppinstance = self.space.interp_w(W_CPPInstance, w_cppinstance, can_be_None=True)
+ cppinstance = self.space.interp_w(W_CPPClass, w_cppinstance, can_be_None=True)
if not cppinstance:
raise oefmt(self.space.w_ReferenceError,
"attribute access requires an instance")
@@ -704,7 +704,7 @@
except Exception:
return space.w_False
-class W_CPPScope(W_Root):
+class W_CPPScopeDecl(W_Root):
_attrs_ = ['space', 'name', 'handle', 'methods', 'datamembers']
_immutable_fields_ = ['handle', 'name']
@@ -725,6 +725,7 @@
def get_method_names(self):
return self.space.newlist([self.space.newtext(name) for name in self.methods])
+ @unwrap_spec(name='text')
def get_overload(self, name):
try:
return self.methods[name]
@@ -737,6 +738,7 @@
def get_datamember_names(self):
return self.space.newlist([self.space.newtext(name) for name in self.datamembers])
+ @unwrap_spec(name='text')
def get_datamember(self, name):
try:
return self.datamembers[name]
@@ -746,7 +748,8 @@
self.datamembers[name] = new_dm
return new_dm
- def dispatch(self, name, signature):
+ @unwrap_spec(name='text', signature='text')
+ def scope__dispatch__(self, name, signature):
overload = self.get_overload(name)
sig = '(%s)' % signature
for f in overload.functions:
@@ -765,8 +768,7 @@
# with info from multiple dictionaries and do not need to bother with meta
# classes for inheritance. Both are python classes, though, and refactoring
# may be in order at some point.
-class W_CPPNamespace(W_CPPScope):
-
+class W_CPPNamespaceDecl(W_CPPScopeDecl):
def _make_cppfunction(self, pyname, index):
num_args = capi.c_method_num_args(self.space, self, index)
args_required = capi.c_method_req_args(self.space, self, index)
@@ -838,25 +840,24 @@
"namespace '%s' has no attribute %s", self.name, name)
-W_CPPNamespace.typedef = TypeDef(
- 'CPPNamespace',
- get_method_names = interp2app(W_CPPNamespace.get_method_names),
- get_overload = interp2app(W_CPPNamespace.get_overload, unwrap_spec=['self', 'text']),
- get_datamember_names = interp2app(W_CPPNamespace.get_datamember_names),
- get_datamember = interp2app(W_CPPNamespace.get_datamember, unwrap_spec=['self', 'text']),
- is_namespace = interp2app(W_CPPNamespace.is_namespace),
- __dir__ = interp2app(W_CPPNamespace.ns__dir__),
+W_CPPNamespaceDecl.typedef = TypeDef(
+ 'CPPNamespaceDecl',
+ get_method_names = interp2app(W_CPPNamespaceDecl.get_method_names),
+ get_overload = interp2app(W_CPPNamespaceDecl.get_overload),
+ get_datamember_names = interp2app(W_CPPNamespaceDecl.get_datamember_names),
+ get_datamember = interp2app(W_CPPNamespaceDecl.get_datamember),
+ is_namespace = interp2app(W_CPPNamespaceDecl.is_namespace),
+ __cppname__ = interp_attrproperty('name', W_CPPNamespaceDecl, wrapfn="newtext"),
+ __dispatch__ = interp2app(W_CPPNamespaceDecl.scope__dispatch__),
+ __dir__ = interp2app(W_CPPNamespaceDecl.ns__dir__),
)
-W_CPPNamespace.typedef.acceptable_as_base_class = False
+W_CPPNamespaceDecl.typedef.acceptable_as_base_class = False
-class W_CPPClass(W_CPPScope):
+class W_CPPClassDecl(W_CPPScopeDecl):
_attrs_ = ['space', 'name', 'handle', 'methods', 'datamembers']
_immutable_fields_ = ['handle', 'constructor', 'methods[*]', 'datamembers[*]']
- def __init__(self, space, name, opaque_handle):
- W_CPPScope.__init__(self, space, name, opaque_handle)
-
def _build_methods(self):
assert len(self.methods) == 0
methods_temp = {}
@@ -956,22 +957,21 @@
"class '%s' has no attribute %s", self.name, name)
-W_CPPClass.typedef = TypeDef(
- 'CPPClass',
- type_name = interp_attrproperty('name', W_CPPClass, wrapfn="newtext"),
- get_base_names = interp2app(W_CPPClass.get_base_names),
- get_method_names = interp2app(W_CPPClass.get_method_names),
- get_overload = interp2app(W_CPPClass.get_overload, unwrap_spec=['self', 'text']),
- get_datamember_names = interp2app(W_CPPClass.get_datamember_names),
- get_datamember = interp2app(W_CPPClass.get_datamember, unwrap_spec=['self', 'text']),
- is_namespace = interp2app(W_CPPClass.is_namespace),
- dispatch = interp2app(W_CPPClass.dispatch, unwrap_spec=['self', 'text', 'text'])
+W_CPPClassDecl.typedef = TypeDef(
+ 'CPPClassDecl',
+ get_base_names = interp2app(W_CPPClassDecl.get_base_names),
+ get_method_names = interp2app(W_CPPClassDecl.get_method_names),
+ get_overload = interp2app(W_CPPClassDecl.get_overload),
+ get_datamember_names = interp2app(W_CPPClassDecl.get_datamember_names),
+ get_datamember = interp2app(W_CPPClassDecl.get_datamember),
+ is_namespace = interp2app(W_CPPClassDecl.is_namespace),
+ __cppname__ = interp_attrproperty('name', W_CPPClassDecl, wrapfn="newtext"),
+ __dispatch__ = interp2app(W_CPPClassDecl.scope__dispatch__)
)
-W_CPPClass.typedef.acceptable_as_base_class = False
+W_CPPClassDecl.typedef.acceptable_as_base_class = False
-class W_ComplexCPPClass(W_CPPClass):
-
+class W_CPPComplexClassDecl(W_CPPClassDecl):
def get_base_offset(self, cppinstance, calling_scope):
assert self == cppinstance.cppclass
offset = capi.c_base_offset(self.space,
@@ -983,18 +983,18 @@
offset = self.get_base_offset(cppinstance, calling_scope)
return capi.direct_ptradd(cppinstance.get_rawobject(), offset)
-W_ComplexCPPClass.typedef = TypeDef(
- 'ComplexCPPClass',
- type_name = interp_attrproperty('name', W_CPPClass, wrapfn="newtext"),
- get_base_names = interp2app(W_ComplexCPPClass.get_base_names),
- get_method_names = interp2app(W_ComplexCPPClass.get_method_names),
- get_overload = interp2app(W_ComplexCPPClass.get_overload, unwrap_spec=['self', 'text']),
- get_datamember_names = interp2app(W_ComplexCPPClass.get_datamember_names),
- get_datamember = interp2app(W_ComplexCPPClass.get_datamember, unwrap_spec=['self', 'text']),
- is_namespace = interp2app(W_ComplexCPPClass.is_namespace),
- dispatch = interp2app(W_CPPClass.dispatch, unwrap_spec=['self', 'text', 'text'])
+W_CPPComplexClassDecl.typedef = TypeDef(
+ 'CPPComplexClassDecl',
+ get_base_names = interp2app(W_CPPComplexClassDecl.get_base_names),
+ get_method_names = interp2app(W_CPPComplexClassDecl.get_method_names),
+ get_overload = interp2app(W_CPPComplexClassDecl.get_overload),
+ get_datamember_names = interp2app(W_CPPComplexClassDecl.get_datamember_names),
+ get_datamember = interp2app(W_CPPComplexClassDecl.get_datamember),
+ is_namespace = interp2app(W_CPPComplexClassDecl.is_namespace),
+ __cppname__ = interp_attrproperty('name', W_CPPComplexClassDecl, wrapfn="newtext"),
+ __dispatch__ = interp2app(W_CPPComplexClassDecl.scope__dispatch__)
)
-W_ComplexCPPClass.typedef.acceptable_as_base_class = False
+W_CPPComplexClassDecl.typedef.acceptable_as_base_class = False
class W_CPPTemplateType(W_Root):
@@ -1018,7 +1018,7 @@
W_CPPTemplateType.typedef.acceptable_as_base_class = False
-class W_CPPInstance(W_Root):
+class W_CPPClass(W_Root):
_attrs_ = ['space', 'cppclass', '_rawobject', 'isref', 'python_owns',
'finalizer_registered']
_immutable_fields_ = ["cppclass", "isref"]
@@ -1094,8 +1094,8 @@
# find a global overload in gbl, in __gnu_cxx (for iterators), or in the
# scopes of the argument classes (TODO: implement that last option)
try:
- # TODO: expecting w_other to be an W_CPPInstance is too limiting
- other = self.space.interp_w(W_CPPInstance, w_other, can_be_None=False)
+ # TODO: expecting w_other to be an W_CPPClass is too limiting
+ other = self.space.interp_w(W_CPPClass, w_other, can_be_None=False)
for name in ["", "__gnu_cxx", "__1"]:
nss = scope_byname(self.space, name)
meth_idx = capi.c_get_global_operator(
@@ -1117,7 +1117,7 @@
# fallback 2: direct pointer comparison (the class comparison is needed since
# the first data member in a struct and the struct have the same address)
- other = self.space.interp_w(W_CPPInstance, w_other, can_be_None=False) # TODO: factor out
+ other = self.space.interp_w(W_CPPClass, w_other, can_be_None=False) # TODO: factor out
iseq = (self._rawobject == other._rawobject) and (self.cppclass == other.cppclass)
return self.space.newbool(iseq)
@@ -1160,20 +1160,20 @@
if self.python_owns:
self.destruct()
-W_CPPInstance.typedef = TypeDef(
- 'CPPInstance',
- cppclass = interp_attrproperty_w('cppclass', cls=W_CPPInstance),
- _python_owns = GetSetProperty(W_CPPInstance.fget_python_owns, W_CPPInstance.fset_python_owns),
- __init__ = interp2app(W_CPPInstance.instance__init__),
- __eq__ = interp2app(W_CPPInstance.instance__eq__),
- __ne__ = interp2app(W_CPPInstance.instance__ne__),
- __nonzero__ = interp2app(W_CPPInstance.instance__nonzero__),
- __len__ = interp2app(W_CPPInstance.instance__len__),
- __cmp__ = interp2app(W_CPPInstance.instance__cmp__),
- __repr__ = interp2app(W_CPPInstance.instance__repr__),
- __destruct__ = interp2app(W_CPPInstance.destruct),
+W_CPPClass.typedef = TypeDef(
+ 'CPPClass',
+ cppclass = interp_attrproperty_w('cppclass', cls=W_CPPClass),
+ _python_owns = GetSetProperty(W_CPPClass.fget_python_owns, W_CPPClass.fset_python_owns),
+ __init__ = interp2app(W_CPPClass.instance__init__),
+ __eq__ = interp2app(W_CPPClass.instance__eq__),
+ __ne__ = interp2app(W_CPPClass.instance__ne__),
+ __nonzero__ = interp2app(W_CPPClass.instance__nonzero__),
+ __len__ = interp2app(W_CPPClass.instance__len__),
+ __cmp__ = interp2app(W_CPPClass.instance__cmp__),
+ __repr__ = interp2app(W_CPPClass.instance__repr__),
+ __destruct__ = interp2app(W_CPPClass.destruct),
)
-W_CPPInstance.typedef.acceptable_as_base_class = True
+W_CPPClass.typedef.acceptable_as_base_class = True
class MemoryRegulator:
@@ -1185,7 +1185,7 @@
# Note that for now, the associated test carries an m_padding to make
# a difference in the addresses.
def __init__(self):
- self.objects = rweakref.RWeakValueDictionary(int, W_CPPInstance)
+ self.objects = rweakref.RWeakValueDictionary(int, W_CPPClass)
def register(self, obj):
if not obj._rawobject:
@@ -1233,8 +1233,8 @@
w_pycppclass = get_pythonized_cppclass(space, actual)
offset = capi.c_base_offset1(space, actual, cppclass, rawobject, -1)
rawobject = capi.direct_ptradd(rawobject, offset)
- w_cppclass = space.findattr(w_pycppclass, space.newtext("_cpp_proxy"))
- cppclass = space.interp_w(W_CPPClass, w_cppclass, can_be_None=False)
+ w_cppclass = space.findattr(w_pycppclass, space.newtext("__cppdecl__"))
+ cppclass = space.interp_w(W_CPPClassDecl, 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
@@ -1251,8 +1251,8 @@
return obj
# fresh creation
- w_cppinstance = space.allocate_instance(W_CPPInstance, w_pycppclass)
- cppinstance = space.interp_w(W_CPPInstance, w_cppinstance, can_be_None=False)
+ w_cppinstance = space.allocate_instance(W_CPPClass, w_pycppclass)
+ cppinstance = space.interp_w(W_CPPClass, w_cppinstance, can_be_None=False)
cppinstance.__init__(space, cppclass, rawobject, is_ref, python_owns)
memory_regulator.register(cppinstance)
return w_cppinstance
@@ -1281,11 +1281,11 @@
except Exception:
# accept integer value as address
rawobject = rffi.cast(capi.C_OBJECT, space.uint_w(w_obj))
- w_cppclass = space.findattr(w_pycppclass, space.newtext("_cpp_proxy"))
+ w_cppclass = space.findattr(w_pycppclass, space.newtext("__cppdecl__"))
if not w_cppclass:
w_cppclass = scope_byname(space, space.text_w(w_pycppclass))
if not w_cppclass:
raise oefmt(space.w_TypeError,
"no such class: %s", space.text_w(w_pycppclass))
- cppclass = space.interp_w(W_CPPClass, w_cppclass, can_be_None=False)
+ cppclass = space.interp_w(W_CPPClassDecl, w_cppclass, can_be_None=False)
return wrap_cppobject(space, rawobject, cppclass, do_cast=cast, python_owns=owns)
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
@@ -4,11 +4,10 @@
import sys
-# For now, keep namespaces and classes separate as namespaces are extensible
-# with info from multiple dictionaries and do not need to bother with meta
-# classes for inheritance. Both are python classes, though, and refactoring
-# may be in order at some point.
-class CPPScope(type):
+# Metaclasses are needed to store C++ static data members as properties. Since
+# the interp-level does not support metaclasses, they are created at app-level.
+# These are the metaclass base classes:
+class CPPMetaScope(type):
def __getattr__(self, name):
try:
return get_pycppitem(self, name) # will cache on self
@@ -16,14 +15,17 @@
raise AttributeError("%s object has no attribute '%s' (details: %s)" %
(self, name, str(e)))
-class CPPNamespace(CPPScope):
- def __dir__(cls):
- return cls._cpp_proxy.__dir__()
+class CPPMetaNamespace(CPPMetaScope):
+ def __dir__(self):
+ return self.__cppdecl__.__dir__()
-class CPPClass(CPPScope):
+class CPPMetaClass(CPPMetaScope):
pass
-# class CPPInstance defined in _init_pythonify()
+# namespace base class (class base class defined in _init_pythonify)
+class CPPNamespace(object):
+ __metatype__ = CPPMetaNamespace
+
class CPPTemplate(object):
def __init__(self, name, scope=None):
@@ -88,24 +90,25 @@
return method
-def make_cppnamespace(scope, namespace_name, cppns, build_in_full=False):
+def make_cppnamespace(scope, name, decl):
# 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(CPPNamespace)(namespace_name+'_meta', (CPPNamespace,), {})
+ # create a metaclass to allow properties (for static data write access)
+ import _cppyy
+ ns_meta = type(name+'_meta', (CPPMetaNamespace,), {})
# create the python-side C++ namespace representation, cache in scope if given
- d = {"_cpp_proxy" : cppns}
- pycppns = metans(namespace_name, (object,), d)
+ d = {"__cppdecl__" : decl, "__cppname__" : decl.__cppname__ }
+ pyns = ns_meta(name, (CPPNamespace,), d)
if scope:
- setattr(scope, namespace_name, pycppns)
+ setattr(scope, name, pyns)
# install as modules to allow importing from (note naming: cppyy)
modname = 'cppyy.gbl'
if scope:
- modname = 'cppyy.gbl.'+pycppns.__name__.replace('::', '.')
- sys.modules[modname] = pycppns
- return pycppns
+ modname = 'cppyy.gbl.'+pyns.__cppname__.replace('::', '.')
+ sys.modules[modname] = pyns
+ return pyns
def _drop_cycles(bases):
# TODO: figure this out, as it seems to be a PyPy bug?!
@@ -126,12 +129,12 @@
return instance
return __new__
-def make_cppclass(scope, class_name, final_class_name, cppclass):
+def make_cppclass(scope, class_name, final_class_name, decl):
# get a list of base classes for class creation
- bases = [get_pycppclass(base) for base in cppclass.get_base_names()]
+ bases = [get_pycppclass(base) for base in decl.get_base_names()]
if not bases:
- bases = [CPPInstance,]
+ bases = [CPPClass,]
else:
# it's technically possible that the required class now has been built
# if one of the base classes uses it in e.g. a function interface
@@ -140,50 +143,50 @@
except KeyError:
pass
- # prepare dictionary for meta class
+ # prepare dictionary for metaclass
d_meta = {}
# prepare dictionary for python-side C++ class representation
def dispatch(self, name, signature):
- cppol = cppclass.dispatch(name, signature)
+ cppol = decl.dispatch(name, signature)
return types.MethodType(make_method(name, cppol), self, type(self))
- d_class = {"_cpp_proxy" : cppclass,
- "__dispatch__" : dispatch,
+ d_class = {"__cppdecl__" : decl,
+ "__cppname__" : decl.__cppname__,
"__new__" : make_new(class_name),
}
# insert (static) methods into the class dictionary
- for name in cppclass.get_method_names():
- cppol = cppclass.get_overload(name)
+ for name in decl.get_method_names():
+ cppol = decl.get_overload(name)
if cppol.is_static():
d_class[name] = make_static_function(name, cppol)
else:
d_class[name] = make_method(name, cppol)
# 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 name in cppclass.get_datamember_names():
- cppdm = cppclass.get_datamember(name)
+ # static ones also to the metaclass (needed for property setters)
+ for name in decl.get_datamember_names():
+ cppdm = decl.get_datamember(name)
d_class[name] = cppdm
if cppdm.is_static():
d_meta[name] = cppdm
- # create a meta class to allow properties (for static data write access)
+ # create a metaclass to allow properties (for static data write access)
metabases = [type(base) for base in bases]
- metacpp = type(CPPClass)(class_name+'_meta', _drop_cycles(metabases), d_meta)
+ metacpp = type(CPPMetaScope)(class_name+'_meta', _drop_cycles(metabases), d_meta)
# create the python-side C++ class
- pycppclass = metacpp(class_name, _drop_cycles(bases), d_class)
+ pycls = metacpp(class_name, _drop_cycles(bases), d_class)
# store the class on its outer scope
- setattr(scope, final_class_name, pycppclass)
+ setattr(scope, final_class_name, pycls)
# the call to register will add back-end specific pythonizations and thus
# needs to run first, so that the generic pythonizations can use them
import _cppyy
- _cppyy._register_class(pycppclass)
- _pythonize(pycppclass)
- return pycppclass
+ _cppyy._register_class(pycls)
+ _pythonize(pycls)
+ return pycls
def make_cpptemplatetype(scope, template_name):
return CPPTemplate(template_name, scope)
@@ -203,11 +206,14 @@
# classes
cppitem = _cppyy._scope_byname(true_name)
if cppitem:
+ name = true_name
+ if scope != gbl:
+ name = true_name[len(scope.__cppname__)+2:]
if cppitem.is_namespace():
- pycppitem = make_cppnamespace(scope, true_name, cppitem)
+ pycppitem = make_cppnamespace(scope, name, cppitem)
setattr(scope, name, pycppitem)
else:
- pycppitem = make_cppclass(scope, true_name, name, cppitem)
+ pycppitem = make_cppclass(scope, name, true_name, cppitem)
# templates
if not cppitem:
@@ -219,7 +225,7 @@
# functions
if not cppitem:
try:
- cppitem = scope._cpp_proxy.get_overload(name)
+ cppitem = scope.__cppdecl__.get_overload(name)
pycppitem = make_static_function(name, cppitem)
setattr(scope.__class__, name, pycppitem)
pycppitem = getattr(scope, name) # binds function as needed
@@ -229,7 +235,7 @@
# data
if not cppitem:
try:
- cppdm = scope._cpp_proxy.get_datamember(name)
+ cppdm = scope.__cppdecl__.get_datamember(name)
setattr(scope, name, cppdm)
if cppdm.is_static():
setattr(scope.__class__, name, cppdm)
@@ -388,11 +394,11 @@
# at pypy-c startup, rather than on the "import _cppyy" statement
import _cppyy
- # root of all proxy classes: CPPInstance in pythonify exists to combine the
- # CPPClass meta class with the interp-level CPPInstanceBase
- global CPPInstance
- class CPPInstance(_cppyy.CPPInstanceBase):
- __metaclass__ = CPPClass
+ # root of all proxy classes: CPPClass in pythonify exists to combine the
+ # CPPMetaScope metaclass with the interp-level CPPClassBase
+ global CPPClass
+ class CPPClass(_cppyy.CPPClassBase):
+ __metaclass__ = CPPMetaScope
pass
# class generator callback
@@ -403,8 +409,9 @@
# user interface objects
global gbl
- gbl = make_cppnamespace(None, '::', _cppyy._scope_byname(''))
- gbl.__doc__ = "Global C++ namespace."
+ gbl = make_cppnamespace(None, 'gbl', _cppyy._scope_byname(''))
+ gbl.__module__ = 'cppyy'
+ gbl.__doc__ = 'Global C++ namespace.'
# pre-create std to allow direct importing
gbl.std = make_cppnamespace(gbl, 'std', _cppyy._scope_byname('std'))
diff --git a/pypy/module/_cppyy/src/dummy_backend.cxx b/pypy/module/_cppyy/src/dummy_backend.cxx
--- a/pypy/module/_cppyy/src/dummy_backend.cxx
+++ b/pypy/module/_cppyy/src/dummy_backend.cxx
@@ -164,6 +164,14 @@
static long s_scope_id = 0;
static long s_method_id = 0;
+ { // namespace ''
+ s_handles[""] = (cppyy_scope_t)++s_scope_id;
+ }
+
+ { // namespace std
+ s_handles["std"] = (cppyy_scope_t)++s_scope_id;
+ }
+
{ // class example01 --
s_handles["example01"] = (cppyy_scope_t)++s_scope_id;
diff --git a/pypy/module/_cppyy/test/test_cppyy.py b/pypy/module/_cppyy/test/test_cppyy.py
--- a/pypy/module/_cppyy/test/test_cppyy.py
+++ b/pypy/module/_cppyy/test/test_cppyy.py
@@ -95,7 +95,7 @@
assert t.get_overload("getCount").call(None) == 0
- e1 = t.get_overload(t.type_name).call(None, 7)
+ e1 = t.get_overload(t.__cppname__).call(None, 7)
assert t.get_overload("getCount").call(None) == 1
res = t.get_overload("addDataToInt").call(e1, 4)
assert res == 11
@@ -105,8 +105,8 @@
assert t.get_overload("getCount").call(None) == 0
raises(ReferenceError, 't.get_overload("addDataToInt").call(e1, 4)')
- e1 = t.get_overload(t.type_name).call(None, 7)
- e2 = t.get_overload(t.type_name).call(None, 8)
+ e1 = t.get_overload(t.__cppname__).call(None, 7)
+ e2 = t.get_overload(t.__cppname__).call(None, 8)
assert t.get_overload("getCount").call(None) == 2
e1.__destruct__()
assert t.get_overload("getCount").call(None) == 1
@@ -128,7 +128,7 @@
assert t.get_overload("getCount").call(None) == 0
- e1 = t.get_overload(t.type_name).call(None, 7)
+ e1 = t.get_overload(t.__cppname__).call(None, 7)
assert t.get_overload("getCount").call(None) == 1
res = t.get_overload("addDataToInt").call(e1, 4)
assert res == 11
@@ -138,8 +138,8 @@
gc.collect()
assert t.get_overload("getCount").call(None) == 0
- e1 = t.get_overload(t.type_name).call(None, 7)
- e2 = t.get_overload(t.type_name).call(None, 8)
+ e1 = t.get_overload(t.__cppname__).call(None, 7)
+ e2 = t.get_overload(t.__cppname__).call(None, 8)
assert t.get_overload("getCount").call(None) == 2
e1 = None
gc.collect()
@@ -159,7 +159,7 @@
assert t.get_overload("getCount").call(None) == 0
- e1 = t.get_overload(t.type_name).call(None, 7)
+ e1 = t.get_overload(t.__cppname__).call(None, 7)
assert t.get_overload("getCount").call(None) == 1
assert e1._python_owns == True
e1._python_owns = False
@@ -178,12 +178,12 @@
t = self.example01
- e = t.get_overload(t.type_name).call(None, 13)
+ e = t.get_overload(t.__cppname__).call(None, 13)
res = t.get_overload("addDataToDouble").call(e, 16)
assert round(res-29, 8) == 0.
e.__destruct__()
- e = t.get_overload(t.type_name).call(None, -13)
+ e = t.get_overload(t.__cppname__).call(None, -13)
res = t.get_overload("addDataToDouble").call(e, 16)
assert round(res-3, 8) == 0.
e.__destruct__()
@@ -196,7 +196,7 @@
t = self.example01
- e = t.get_overload(t.type_name).call(None, 42)
+ e = t.get_overload(t.__cppname__).call(None, 42)
res = t.get_overload("addDataToAtoi").call(e, "13")
assert res == 55
res = t.get_overload("addToStringValue").call(e, "12") # TODO: this leaks
@@ -213,12 +213,12 @@
t1 = self.example01
t2 = self.payload
- pl = t2.get_overload(t2.type_name).call(None, 3.14)
+ pl = t2.get_overload(t2.__cppname__).call(None, 3.14)
assert round(t2.get_overload("getData").call(pl)-3.14, 8) == 0
- t1.get_overload("staticSetPayload").call(None, pl, 41.) # now pl is a CPPInstance
+ t1.get_overload("staticSetPayload").call(None, pl, 41.)
assert t2.get_overload("getData").call(pl) == 41.
- e = t1.get_overload(t1.type_name).call(None, 50)
+ e = t1.get_overload(t1.__cppname__).call(None, 50)
t1.get_overload("setPayload").call(e, pl);
assert round(t2.get_overload("getData").call(pl)-50., 8) == 0
@@ -233,12 +233,12 @@
t1 = self.example01
t2 = self.payload
- pl1 = t2.get_overload(t2.type_name).call(None, 3.14)
+ pl1 = t2.get_overload(t2.__cppname__).call(None, 3.14)
assert round(t2.get_overload("getData").call(pl1)-3.14, 8) == 0
pl2 = t1.get_overload("staticCyclePayload").call(None, pl1, 38.)
assert t2.get_overload("getData").call(pl2) == 38.
- e = t1.get_overload(t1.type_name).call(None, 50)
+ e = t1.get_overload(t1.__cppname__).call(None, 50)
pl2 = t1.get_overload("cyclePayload").call(e, pl1);
assert round(t2.get_overload("getData").call(pl2)-50., 8) == 0
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
@@ -34,7 +34,7 @@
assert fragile.B == fragile.B
assert fragile.B().check() == ord('B')
- raises(AttributeError, getattr, fragile.B().gime_no_such(), "_cpp_proxy")
+ raises(AttributeError, getattr, fragile.B().gime_no_such(), "__cppdecl__")
assert fragile.C == fragile.C
assert fragile.C().check() == ord('C')
@@ -237,17 +237,35 @@
from cppyy.gbl.fragile import nested1
assert _cppyy.gbl.fragile.nested1 is nested1
+ assert nested1.__name__ == 'nested1'
+ assert nested1.__module__ == 'cppyy.gbl.fragile'
+ assert nested1.__cppname__ == 'nested1'
from cppyy.gbl.fragile.nested1 import A, nested2
assert _cppyy.gbl.fragile.nested1.A is A
+ assert A.__name__ == 'A'
+ assert A.__module__ == 'cppyy.gbl.fragile.nested1'
+ assert A.__cppname__ == 'fragile::nested1::A'
assert _cppyy.gbl.fragile.nested1.nested2 is nested2
+ assert A.__name__ == 'A'
+ assert A.__module__ == 'cppyy.gbl.fragile.nested1'
+ assert nested2.__cppname__ == 'fragile::nested1::nested2'
from cppyy.gbl.fragile.nested1.nested2 import A, nested3
assert _cppyy.gbl.fragile.nested1.nested2.A is A
+ assert A.__name__ == 'A'
+ assert A.__module__ == 'cppyy.gbl.fragile.nested1'
+ assert A.__cppname__ == 'fragile::nested1::nested2::A'
assert _cppyy.gbl.fragile.nested1.nested2.nested3 is nested3
+ assert A.__name__ == 'A'
+ assert A.__module__ == 'cppyy.gbl.fragile.nested1'
+ assert nested3.__cppname__ == 'fragile::nested1::nested2::nested3'
from cppyy.gbl.fragile.nested1.nested2.nested3 import A
assert _cppyy.gbl.fragile.nested1.nested2.nested3.A is nested3.A
+ assert A.__name__ == 'A'
+ assert A.__module__ == 'cppyy.gbl.fragile.nested1'
+ assert A.__cppname__ == 'fragile::nested1::nested2::nested3::A'
def test12_missing_casts(self):
"""Test proper handling when a hierarchy is not fully available"""
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
@@ -281,7 +281,7 @@
cls = interp_cppyy.scope_byname(space, "example01")
inst = cls.get_overload("example01").call(None, [FakeInt(0)])
cppmethod = cls.get_overload(method_name)
- assert isinstance(inst, interp_cppyy.W_CPPInstance)
+ assert isinstance(inst, interp_cppyy.W_CPPClass)
i = 10
while i > 0:
drv.jit_merge_point(inst=inst, cppmethod=cppmethod, i=i)
More information about the pypy-commit
mailing list