Author: Wim Lavrijsen <wlavrij...@lbl.gov> 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 pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit