Author: Wim Lavrijsen <[email protected]>
Branch: cppyy-packaging
Changeset: r94750:749cd13269b0
Date: 2018-06-10 16:10 -0700
http://bitbucket.org/pypy/pypy/changeset/749cd13269b0/
Log: py3 fixes
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
@@ -14,7 +14,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',
+ 'CPPInstance' : 'interp_cppyy.W_CPPInstance',
'addressof' : 'interp_cppyy.addressof',
'_bind_object' : 'interp_cppyy._bind_object',
'bind_object' : 'interp_cppyy.bind_object',
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
@@ -391,7 +391,7 @@
def from_memory(self, space, w_obj, w_pycppclass, offset):
address = self._get_raw_address(space, w_obj, offset)
charpptr = rffi.cast(rffi.CCHARPP, address)
- return space.newbytes(rffi.charp2str(charpptr[0]))
+ return space.newtext(rffi.charp2str(charpptr[0]))
def free_argument(self, space, arg, call_local):
lltype.free(rffi.cast(rffi.CCHARPP, arg)[0], flavor='raw')
@@ -408,7 +408,7 @@
strsize = self.size
if charpptr[self.size-1] == '\0':
strsize = self.size-1 # rffi will add \0 back
- return space.newbytes(rffi.charpsize2str(charpptr, strsize))
+ return space.newtext(rffi.charpsize2str(charpptr, strsize))
class VoidPtrConverter(TypeConverter):
diff --git a/pypy/module/_cppyy/ffitypes.py b/pypy/module/_cppyy/ffitypes.py
--- a/pypy/module/_cppyy/ffitypes.py
+++ b/pypy/module/_cppyy/ffitypes.py
@@ -79,10 +79,13 @@
value = rffi.cast(rffi.CHAR, space.c_int_w(w_value))
else:
- value = space.text_w(w_value)
+ if space.isinstance_w(w_value, space.w_text):
+ value = space.text_w(w_value)
+ else:
+ value = space.bytes_w(w_value)
if len(value) != 1:
raise oefmt(space.w_ValueError,
- "char expected, got string of size %d", len(value))
+ "char expected, got string of size %d", len(value))
value = rffi.cast(rffi.CHAR, value[0])
return value # turn it into a "char" to the annotator
@@ -110,10 +113,13 @@
value = rffi.cast(rffi.CHAR, space.c_int_w(w_value))
else:
- value = space.text_w(w_value)
+ if space.isinstance_w(w_value, space.w_text):
+ value = space.text_w(w_value)
+ else:
+ value = space.bytes_w(w_value)
if len(value) != 1:
raise oefmt(space.w_ValueError,
- "char expected, got string of size %d", len(value))
+ "usigned char expected, got string of size %d",
len(value))
value = rffi.cast(rffi.CHAR, value[0])
return value # turn it into a "char" to the annotator
diff --git a/pypy/module/_cppyy/helper.py b/pypy/module/_cppyy/helper.py
--- a/pypy/module/_cppyy/helper.py
+++ b/pypy/module/_cppyy/helper.py
@@ -1,3 +1,4 @@
+import sys
from rpython.rlib import rstring
@@ -116,6 +117,17 @@
# TODO: perhaps absorb or "pythonify" these operators?
return cppname
+if sys.hexversion < 0x3000000:
+ CPPYY__div__ = "__div__"
+ CPPYY__idiv__ = "__idiv__"
+ CPPYY__long__ = "__long__"
+ CPPYY__bool__ = "__nonzero__"
+else:
+ CPPYY__div__ = "__truediv__"
+ CPPYY__idiv__ = "__itruediv__"
+ CPPYY__long__ = "__int__"
+ CPPYY__bool__ = "__bool__"
+
# _operator_mappings["[]"] = "__setitem__" # depends on return type
# _operator_mappings["+"] = "__add__" # depends on # of args (see
__pos__)
# _operator_mappings["-"] = "__sub__" # id. (eq. __neg__)
@@ -123,7 +135,7 @@
# _operator_mappings["[]"] = "__getitem__" # depends on return type
_operator_mappings["()"] = "__call__"
-_operator_mappings["/"] = "__div__" # __truediv__ in p3
+_operator_mappings["/"] = CPPYY__div__
_operator_mappings["%"] = "__mod__"
_operator_mappings["**"] = "__pow__" # not C++
_operator_mappings["<<"] = "__lshift__"
@@ -136,7 +148,7 @@
_operator_mappings["+="] = "__iadd__"
_operator_mappings["-="] = "__isub__"
_operator_mappings["*="] = "__imul__"
-_operator_mappings["/="] = "__idiv__" # __itruediv__ in p3
+_operator_mappings["/="] = CPPYY__idiv__
_operator_mappings["%="] = "__imod__"
_operator_mappings["**="] = "__ipow__"
_operator_mappings["<<="] = "__ilshift__"
@@ -154,7 +166,7 @@
# the following type mappings are "exact"
_operator_mappings["const char*"] = "__str__"
_operator_mappings["int"] = "__int__"
-_operator_mappings["long"] = "__long__" # __int__ in p3
+_operator_mappings["long"] = CPPYY__long__
_operator_mappings["double"] = "__float__"
# the following type mappings are "okay"; the assumption is that they
@@ -163,13 +175,13 @@
_operator_mappings["char*"] = "__str__"
_operator_mappings["short"] = "__int__"
_operator_mappings["unsigned short"] = "__int__"
-_operator_mappings["unsigned int"] = "__long__" # __int__ in p3
-_operator_mappings["unsigned long"] = "__long__" # id.
-_operator_mappings["long long"] = "__long__" # id.
-_operator_mappings["unsigned long long"] = "__long__" # id.
+_operator_mappings["unsigned int"] = CPPYY__long__
+_operator_mappings["unsigned long"] = CPPYY__long__
+_operator_mappings["long long"] = CPPYY__long__
+_operator_mappings["unsigned long long"] = CPPYY__long__
_operator_mappings["float"] = "__float__"
-_operator_mappings["bool"] = "__nonzero__" # __bool__ in p3
+_operator_mappings["bool"] = CPPYY__bool__
# the following are not python, but useful to expose
_operator_mappings["->"] = "__follow__"
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
@@ -1470,7 +1470,9 @@
__init__ = interp2app(W_CPPInstance.instance__init__),
__eq__ = interp2app(W_CPPInstance.instance__eq__),
__ne__ = interp2app(W_CPPInstance.instance__ne__),
+ # should be based on python version, but syntax is simpler this way
__nonzero__ = interp2app(W_CPPInstance.instance__nonzero__),
+ __bool__ = interp2app(W_CPPInstance.instance__nonzero__),
__len__ = interp2app(W_CPPInstance.instance__len__),
__cmp__ = interp2app(W_CPPInstance.instance__cmp__),
__repr__ = interp2app(W_CPPInstance.instance__repr__),
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,10 +4,22 @@
import sys
-# 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 CPPScope(type):
+# Metaclasses are needed to store C++ static data members as properties and to
+# provide Python language features such as a customized __dir__ for namespaces
+# and __getattr__ for both. These features are used for lazy lookup/creation.
+# Since the interp-level does not support metaclasses, this is all done at the
+# app-level.
+#
+# C++ namespaces: are represented as Python classes, with CPPNamespace as the
+# base class, which is at the moment just a label, and CPPNamespaceMeta as
+# the base class of their invididualized meta class.
+#
+# C++ classes: are represented as Python classes, with CPPClass as the base
+# class, which is a subclass of the interp-level CPPInstance. The former
+# sets up the Python-class behavior for bound classes, the latter adds the
+# bound object behavior that lives at the class level.
+
+class CPPScopeMeta(type):
def __getattr__(self, name):
try:
return get_scoped_pycppitem(self, name) # will cache on self
@@ -15,18 +27,57 @@
raise AttributeError("%s object has no attribute '%s' (details:
%s)" %
(self, name, str(e)))
-class CPPMetaNamespace(CPPScope):
+class CPPNamespaceMeta(CPPScopeMeta):
def __dir__(self):
return self.__cppdecl__.__dir__()
-class CPPClass(CPPScope):
+class CPPClassMeta(CPPScopeMeta):
pass
-# namespace base class (class base class defined in _post_import_startup()
-class CPPNamespace(object):
- __metatype__ = CPPMetaNamespace
+# from six.py ---
+# Copyright (c) 2010-2017 Benjamin Peterson
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
all
+# copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+def with_metaclass(meta, *bases):
+ """Create a base class with a metaclass."""
+ # This requires a bit of explanation: the basic idea is to make a dummy
+ # metaclass for one level of class instantiation that replaces itself with
+ # the actual metaclass.
+ class metaclass(type):
+ def __new__(cls, name, this_bases, d):
+ return meta(name, bases, d)
+
+ @classmethod
+ def __prepare__(cls, name, this_bases):
+ return meta.__prepare__(name, bases)
+ return type.__new__(metaclass, 'temporary_class', (), {})
+# --- end from six.py
+
+# C++ namespace base class (the C++ class base class defined in
_post_import_startup)
+class CPPNamespace(with_metaclass(CPPNamespaceMeta, object)):
+ pass
+
+
+# TODO: this can be moved to the interp level (and share template argument
+# construction with function templates there)
class CPPTemplate(object):
def __init__(self, name, scope=None):
self._name = name
@@ -123,7 +174,7 @@
# create a metaclass to allow properties (for static data write access)
import _cppyy
- ns_meta = type(name+'_meta', (CPPMetaNamespace,), {})
+ ns_meta = type(CPPNamespace)(name+'_meta', (CPPNamespaceMeta,), {})
# create the python-side C++ namespace representation, cache in scope if
given
d = {"__cppdecl__" : decl,
@@ -164,7 +215,7 @@
# get a list of base classes for class creation
bases = [get_pycppclass(base) for base in decl.get_base_names()]
if not bases:
- bases = [CPPInstance,]
+ bases = [CPPClass,]
else:
# it's possible that the required class now has been built if one of
# the base classes uses it in e.g. a function interface
@@ -202,10 +253,10 @@
# create a metaclass to allow properties (for static data write access)
metabases = [type(base) for base in bases]
- metacpp = type(CPPScope)(cl_name+'_meta', _drop_cycles(metabases), d_meta)
+ cl_meta = type(CPPClassMeta)(cl_name+'_meta', _drop_cycles(metabases),
d_meta)
# create the python-side C++ class
- pycls = metacpp(cl_name, _drop_cycles(bases), d_class)
+ pycls = cl_meta(cl_name, _drop_cycles(bases), d_class)
# store the class on its outer scope
setattr(scope, cl_name, pycls)
@@ -284,7 +335,7 @@
def extract_namespace(name):
# find the namespace the named class lives in, take care of templates
tpl_open = 0
- for pos in xrange(len(name)-1, 1, -1):
+ for pos in range(len(name)-1, 1, -1):
c = name[pos]
# count '<' and '>' to be able to skip template contents
@@ -425,11 +476,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 CPPScope metaclass with the interp-level CPPInstanceBase
- global CPPInstance
- class CPPInstance(_cppyy.CPPInstanceBase):
- __metaclass__ = CPPScope
+ # root of all proxy classes: CPPClass in pythonify exists to combine the
+ # CPPClassMeta metaclass (for Python-side class behavior) with the
+ # interp-level CPPInstance (for bound object behavior)
+ global CPPClass
+ class CPPClass(with_metaclass(CPPClassMeta, _cppyy.CPPInstance)):
pass
# class generator callback
diff --git a/pypy/module/_cppyy/test/datatypes.h
b/pypy/module/_cppyy/test/datatypes.h
--- a/pypy/module/_cppyy/test/datatypes.h
+++ b/pypy/module/_cppyy/test/datatypes.h
@@ -44,16 +44,16 @@
m_cc_called(true), m_x(s.m_x), m_y(s.m_y), m_z(s.m_z), m_t(s.m_t) {}
double operator[](int i) {
- if (i == 0) return m_x;
- if (i == 1) return m_y;
- if (i == 2) return m_z;
- if (i == 3) return m_t;
- return -1;
+ if (i == 0) return m_x;
+ if (i == 1) return m_y;
+ if (i == 2) return m_z;
+ if (i == 3) return m_t;
+ return -1;
}
bool operator==(const FourVector& o) {
- return (m_x == o.m_x && m_y == o.m_y &&
- m_z == o.m_z && m_t == o.m_t);
+ return (m_x == o.m_x && m_y == o.m_y &&
+ m_z == o.m_z && m_t == o.m_t);
}
public:
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
@@ -673,5 +673,5 @@
try:
t.throw_exception()
- except Exception, e:
+ except Exception as e:
"C++ function failed" in str(e)
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
@@ -50,9 +50,13 @@
import sys, math
t = self.example01
+ pylong = int
+ if sys.hexversion < 0x3000000:
+ pylong = long
+
res = t.get_overload("staticAddOneToInt")(1)
assert res == 2
- res = t.get_overload("staticAddOneToInt")(1L)
+ res = t.get_overload("staticAddOneToInt")(pylong(1))
assert res == 2
res = t.get_overload("staticAddOneToInt")(1, 2)
assert res == 4
diff --git a/pypy/module/_cppyy/test/test_crossing.py
b/pypy/module/_cppyy/test/test_crossing.py
--- a/pypy/module/_cppyy/test/test_crossing.py
+++ b/pypy/module/_cppyy/test/test_crossing.py
@@ -93,7 +93,12 @@
%(body)s
PyMODINIT_FUNC
- init%(name)s(void) {
+ #if PY_MAJOR_VERSION >= 3
+ PyInit_%(name)s(void)
+ #else
+ init%(name)s(void)
+ #endif
+ {
%(init)s
}
""" % dict(name=name, init=init, body=body)
@@ -116,8 +121,20 @@
name = 'bar'
init = """
- if (Py_IsInitialized())
+ #if PY_MAJOR_VERSION >= 3
+ static struct PyModuleDef moduledef = {
+ PyModuleDef_HEAD_INIT,
+ "bar", "Module Doc", -1, methods, NULL, NULL, NULL, NULL,
+ };
+ #endif
+
+ if (Py_IsInitialized()) {
+ #if PY_MAJOR_VERSION >= 3
+ PyObject *module = PyModule_Create(&moduledef);
+ #else
Py_InitModule("bar", methods);
+ #endif
+ }
"""
# note: only the symbols are needed for C, none for python
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
@@ -71,7 +71,9 @@
self.name = name
self.__name__ = name
def getname(self, space, name):
- return self.name
+ if sys.hexversion < 0x3000000:
+ return self.name
+ return unicode(self.name)
class FakeBuffer(FakeBase):
typedname = "buffer"
def __init__(self, val):
@@ -108,9 +110,11 @@
class FakeSpace(object):
fake = True
- w_None = None
- w_str = FakeType("str")
- w_int = FakeType("int")
+ w_None = None
+ w_str = FakeType("str")
+ w_text = FakeType("str")
+ w_bytes = FakeType("str")
+ w_int = FakeType("int")
w_float = FakeType("float")
def __init__(self):
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit