From c786d3c0763bb01fbe0619faf304c9731031511f Mon Sep 17 00:00:00 2001 From: Stefan Behnel Date: Fri, 9 May 2008 19:02:36 +0200 Subject: [PATCH] original Py3 code generation patch by Lisandro Dalcin --- Cython/Compiler/ExprNodes.py | 10 ++-- Cython/Compiler/ModuleNode.py | 93 ++++++++++++++++++++++++++++------- Cython/Compiler/Nodes.py | 43 +++++++++++++--- Cython/Compiler/PyrexTypes.py | 2 +- Cython/Compiler/Symtab.py | 2 +- Cython/Compiler/TypeSlots.py | 27 ++++++---- 6 files changed, 138 insertions(+), 39 deletions(-) diff --git a/Cython/Compiler/ExprNodes.py b/Cython/Compiler/ExprNodes.py index 491d0b8b..5210701e 100644 --- a/Cython/Compiler/ExprNodes.py +++ b/Cython/Compiler/ExprNodes.py @@ -4066,7 +4066,7 @@ static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) { if (obj == Py_None || PyObject_TypeCheck(obj, type)) return 1; PyErr_Format(PyExc_TypeError, "Cannot convert %s to %s", - obj->ob_type->tp_name, type->tp_name); + Py_TYPE(obj)->tp_name, type->tp_name); return 0; } """] @@ -4082,13 +4082,17 @@ static PyObject *__Pyx_CreateClass( { PyObject *py_modname; PyObject *result = 0; - + py_modname = PyString_FromString(modname); if (!py_modname) goto bad; if (PyDict_SetItemString(dict, "__module__", py_modname) < 0) goto bad; + #if PY_MAJOR_VERSION < 3 result = PyClass_New(bases, dict, name); + #else + result = PyObject_CallFunctionObjArgs((PyObject *)&PyType_Type, name, bases, dict, NULL); + #endif bad: Py_XDECREF(py_modname); return result; @@ -4135,4 +4139,4 @@ static inline PyObject* __Pyx_PyObject_Append(PyObject* L, PyObject* x) { } } ""","" -] \ No newline at end of file +] diff --git a/Cython/Compiler/ModuleNode.py b/Cython/Compiler/ModuleNode.py index ade6af22..27882058 100644 --- a/Cython/Compiler/ModuleNode.py +++ b/Cython/Compiler/ModuleNode.py @@ -367,6 +367,10 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): code.putln("#ifndef PY_LONG_LONG") code.putln(" #define PY_LONG_LONG LONG_LONG") code.putln("#endif") + code.putln("#if PY_VERSION_HEX < 0x02040000") + code.putln(" #define METH_COEXIST 0") + code.putln("#endif") + code.putln("#if PY_VERSION_HEX < 0x02050000") code.putln(" typedef int Py_ssize_t;") code.putln(" #define PY_SSIZE_T_MAX INT_MAX") @@ -376,9 +380,41 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): code.putln(" #define PyNumber_Index(o) PyNumber_Int(o)") code.putln(" #define PyIndex_Check(o) PyNumber_Check(o)") code.putln("#endif") - code.putln("#if PY_VERSION_HEX < 0x02040000") - code.putln(" #define METH_COEXIST 0") + + code.putln("#if PY_VERSION_HEX < 0x02060000") + code.putln(" #define Py_REFCNT(ob) (((PyObject*)(ob))->ob_refcnt)") + code.putln(" #define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)") + code.putln(" #define Py_SIZE(ob) ((PyVarObject*)(ob))->ob_size)") + code.putln(" #define PyVarObject_HEAD_INIT(type, size) \\") + code.putln(" PyObject_HEAD_INIT(type) size,") code.putln("#endif") + + code.put(builtin_module_name_utility_code[0]) + + code.putln("#if PY_MAJOR_VERSION >= 3") + code.putln(" #define Py_TPFLAGS_CHECKTYPES 0") + code.putln(" #define Py_TPFLAGS_HAVE_INDEX 0") + code.putln("#endif") + + code.putln("#if PY_MAJOR_VERSION >= 3") + code.putln(" #define PyInt_Check(op) PyLong_Check(op)") + code.putln(" #define PyInt_CheckExact(op) PyLong_CheckExact(op)") + code.putln(" #define PyInt_FromString PyLong_FromString") + code.putln(" #define PyInt_FromUnicode PyLong_FromUnicode") + code.putln(" #define PyInt_FromLong PyLong_FromLong") + code.putln(" #define PyInt_FromSize_t PyLong_FromSize_t") + code.putln(" #define PyInt_FromSsize_t PyLong_FromSsize_t") + code.putln(" #define PyInt_AsLong PyLong_AsLong") + code.putln(" #define PyInt_AS_LONG PyLong_AS_LONG") + code.putln(" #define PyInt_AsSsize_t PyLong_AsSsize_t") + code.putln(" #define PyInt_AsUnsignedLongMask PyLong_AsUnsignedLongMask") + code.putln(" #define PyInt_AsUnsignedLongLongMask PyLong_AsUnsignedLongLongMask") + code.putln("#endif") + + code.putln("#if PY_MAJOR_VERSION >= 3") + code.putln(" #define PyMethod_New(func, self, klass) (func!=NULL?(Py_INCREF(func),func):NULL)") + code.putln("#endif") + code.putln("#ifndef __stdcall") code.putln(" #define __stdcall") code.putln("#endif") @@ -787,7 +823,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): "%s(o);" % tp_dealloc) else: code.putln( - "(*o->ob_type->tp_free)(o);") + "(*Py_TYPE(o)->tp_free)(o);") code.putln( "}") @@ -801,14 +837,14 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): code.putln( "PyErr_Fetch(&etype, &eval, &etb);") code.putln( - "++o->ob_refcnt;") + "++Py_REFCNT(o);") code.putln( "%s(o);" % entry.func_cname) code.putln( "if (PyErr_Occurred()) PyErr_WriteUnraisable(o);") code.putln( - "--o->ob_refcnt;") + "--Py_REFCNT(o);") code.putln( "PyErr_Restore(etype, eval, etb);") code.putln( @@ -906,7 +942,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): code.putln( "PyObject *x = PyInt_FromSsize_t(i); if(!x) return 0;") code.putln( - "r = o->ob_type->tp_as_mapping->mp_subscript(o, x);") + "r = Py_TYPE(o)->tp_as_mapping->mp_subscript(o, x);") code.putln( "Py_DECREF(x);") code.putln( @@ -937,7 +973,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): code.putln( "PyErr_Format(PyExc_NotImplementedError,") code.putln( - ' "Subscript assignment not supported by %s", o->ob_type->tp_name);') + ' "Subscript assignment not supported by %s", Py_TYPE(o)->tp_name);') code.putln( "return -1;") code.putln( @@ -954,7 +990,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): code.putln( "PyErr_Format(PyExc_NotImplementedError,") code.putln( - ' "Subscript deletion not supported by %s", o->ob_type->tp_name);') + ' "Subscript deletion not supported by %s", Py_TYPE(o)->tp_name);') code.putln( "return -1;") code.putln( @@ -1004,7 +1040,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): code.putln( "PyErr_Format(PyExc_NotImplementedError,") code.putln( - ' "2-element slice assignment not supported by %s", o->ob_type->tp_name);') + ' "2-element slice assignment not supported by %s", Py_TYPE(o)->tp_name);') code.putln( "return -1;") code.putln( @@ -1021,7 +1057,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): code.putln( "PyErr_Format(PyExc_NotImplementedError,") code.putln( - ' "2-element slice deletion not supported by %s", o->ob_type->tp_name);') + ' "2-element slice deletion not supported by %s", Py_TYPE(o)->tp_name);') code.putln( "return -1;") code.putln( @@ -1242,9 +1278,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): #code.putln(header % scope.parent_type.typeobj_cname) code.putln(header % type.typeobj_cname) code.putln( - "PyObject_HEAD_INIT(0)") - code.putln( - "0, /*ob_size*/") + "PyVarObject_HEAD_INIT(0, 0)") code.putln( '"%s.%s", /*tp_name*/' % ( self.full_module_name, scope.class_name)) @@ -1477,7 +1511,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): env.module_cname, code.error_goto(self.pos))); code.putln( - '%s = PyImport_AddModule("__builtin__");' % + '%s = PyImport_AddModule(__Pyx_BUILTIN_MODULE_NAME);' % Naming.builtins_cname) code.putln( "if (!%s) %s;" % ( @@ -1643,9 +1677,14 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): objstruct = type.objstruct_cname else: objstruct = "struct %s" % type.objstruct_cname - code.putln('%s = __Pyx_ImportType("%s", "%s", sizeof(%s)); %s' % ( + module_name = type.module_name + if module_name not in ('__builtin__', 'builtins'): + module_name = '"%s"' % module_name + else: + module_name = '__Pyx_BUILTIN_MODULE_NAME' + code.putln('%s = __Pyx_ImportType(%s, "%s", sizeof(%s)); %s' % ( type.typeptr_cname, - type.module_name, + module_name, type.name, objstruct, error_code)) @@ -1740,6 +1779,16 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): # #------------------------------------------------------------------------------------ +builtin_module_name_utility_code = [ +"""\ +#if PY_MAJOR_VERSION < 3 + #define __Pyx_BUILTIN_MODULE_NAME "__builtin__" +#else + #define __Pyx_BUILTIN_MODULE_NAME "builtins" +#endif +"""] + + import_module_utility_code = [ """ static PyObject *__Pyx_ImportModule(char *name); /*proto*/ @@ -1749,8 +1798,12 @@ static PyObject *__Pyx_ImportModule(char *name); /*proto*/ static PyObject *__Pyx_ImportModule(char *name) { PyObject *py_name = 0; PyObject *py_module = 0; - + + #if PY_MAJOR_VERSION < 3 py_name = PyString_FromString(name); + #else + py_name = PyUnicode_FromString(name); + #endif if (!py_name) goto bad; py_module = PyImport_Import(py_name); @@ -1777,8 +1830,12 @@ static PyTypeObject *__Pyx_ImportType(char *module_name, char *class_name, PyObject *py_module = 0; PyObject *result = 0; PyObject *py_name = 0; - + + #if PY_MAJOR_VERSION < 3 py_name = PyString_FromString(module_name); + #else + py_name = PyUnicode_FromString(module_name); + #endif if (!py_name) goto bad; diff --git a/Cython/Compiler/Nodes.py b/Cython/Compiler/Nodes.py index 352ee77e..4625e41c 100644 --- a/Cython/Compiler/Nodes.py +++ b/Cython/Compiler/Nodes.py @@ -1923,7 +1923,7 @@ class OverrideCheckNode(StatNode): if self.py_func.is_module_scope: code.putln("else {") else: - code.putln("else if (unlikely(%s->ob_type->tp_dictoffset != 0)) {" % self_arg) + code.putln("else if (unlikely(Py_TYPE(%s)->tp_dictoffset != 0)) {" % self_arg) err = code.error_goto_if_null(self_arg, self.pos) # need to get attribute manually--scope would return cdef method if Options.intern_names: @@ -1931,7 +1931,7 @@ class OverrideCheckNode(StatNode): else: code.putln('%s = PyObject_GetAttrString(%s, "%s"); %s' % (self.func_node.result_code, self_arg, self.py_func.entry.name, err)) # It appears that this type is not anywhere exposed in the Python/C API - is_builtin_function_or_method = '(strcmp(%s->ob_type->tp_name, "builtin_function_or_method") == 0)' % self.func_node.result_code + is_builtin_function_or_method = '(strcmp(Py_TYPE(%s)->tp_name, "builtin_function_or_method") == 0)' % self.func_node.result_code is_overridden = '(PyCFunction_GET_FUNCTION(%s) != (void *)&%s)' % (self.func_node.result_code, self.py_func.entry.func_cname) code.putln('if (!%s || %s) {' % (is_builtin_function_or_method, is_overridden)) self.body.generate_execution_code(code) @@ -3872,7 +3872,7 @@ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb) { goto raise_error; } #else - type = (PyObject*) type->ob_type; + type = (PyObject*) Py_TYPE(type); Py_INCREF(type); if (!PyType_IsSubtype((PyTypeObject *)type, (PyTypeObject *)PyExc_BaseException)) { PyErr_SetString(PyExc_TypeError, @@ -3922,14 +3922,14 @@ static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed } if (none_allowed && obj == Py_None) return 1; else if (exact) { - if (obj->ob_type == type) return 1; + if (Py_TYPE(obj) == type) return 1; } else { if (PyObject_TypeCheck(obj, type)) return 1; } PyErr_Format(PyExc_TypeError, "Argument '%s' has incorrect type (expected %s, got %s)", - name, type->tp_name, obj->ob_type->tp_name); + name, type->tp_name, Py_TYPE(obj)->tp_name); return 0; } """] @@ -4067,7 +4067,11 @@ static int __Pyx_SplitKeywords( if (!*kwds2) goto bad; for (i = 0, p = kwd_list; *p; i++, p++) { + #if PY_MAJOR_VERSION < 3 s = PyString_FromString(*p); + #else + s = PyUnicode_FromString(*p); + #endif x = PyDict_GetItem(*kwds, s); if (x) { if (PyDict_SetItem(kwds1, s, x) < 0) @@ -4147,7 +4151,11 @@ static void __Pyx_WriteUnraisable(char *name) { PyObject *old_exc, *old_val, *old_tb; PyObject *ctx; PyErr_Fetch(&old_exc, &old_val, &old_tb); + #if PY_MAJOR_VERSION < 3 ctx = PyString_FromString(name); + #else + ctx = PyUnicode_FromString(name); + #endif PyErr_Restore(old_exc, old_val, old_tb); if (!ctx) ctx = Py_None; @@ -4172,14 +4180,26 @@ static void __Pyx_AddTraceback(char *funcname) { PyObject *empty_string = 0; PyCodeObject *py_code = 0; PyFrameObject *py_frame = 0; - + + #if PY_MAJOR_VERSION < 3 py_srcfile = PyString_FromString(%(FILENAME)s); + #else + py_srcfile = PyUnicode_FromString(%(FILENAME)s); + #endif if (!py_srcfile) goto bad; if (%(CLINENO)s) { + #if PY_MAJOR_VERSION < 3 py_funcname = PyString_FromFormat( "%%s (%%s:%%u)", funcname, %(CFILENAME)s, %(CLINENO)s); + #else + py_funcname = PyUnicode_FromFormat( "%%s (%%s:%%u)", funcname, %(CFILENAME)s, %(CLINENO)s); + #endif } else { + #if PY_MAJOR_VERSION < 3 py_funcname = PyString_FromString(funcname); + #else + py_funcname = PyUnicode_FromString(funcname); + #endif } if (!py_funcname) goto bad; py_globals = PyModule_GetDict(%(GLOBALS)s); @@ -4188,6 +4208,9 @@ static void __Pyx_AddTraceback(char *funcname) { if (!empty_string) goto bad; py_code = PyCode_New( 0, /*int argcount,*/ + #if PY_MAJOR_VERSION >= 3 + 0, /*int kwonlyargcount,*/ + #endif 0, /*int nlocals,*/ 0, /*int stacksize,*/ 0, /*int flags,*/ @@ -4289,7 +4312,11 @@ static int __Pyx_InternStrings(__Pyx_InternTabEntry *t); /*proto*/ """,""" static int __Pyx_InternStrings(__Pyx_InternTabEntry *t) { while (t->p) { + #if PY_MAJOR_VERSION < 3 *t->p = PyString_InternFromString(t->s); + #else + *t->p = PyUnicode_InternFromString(t->s); + #endif if (!*t->p) return -1; ++t; @@ -4309,7 +4336,11 @@ static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) { if (t->is_unicode) { *t->p = PyUnicode_DecodeUTF8(t->s, t->n - 1, NULL); } else { + #if PY_MAJOR_VERSION < 3 *t->p = PyString_FromStringAndSize(t->s, t->n - 1); + #else + *t->p = PyUnicode_FromStringAndSize(t->s, t->n - 1); + #endif } if (!*t->p) return -1; diff --git a/Cython/Compiler/PyrexTypes.py b/Cython/Compiler/PyrexTypes.py index fcc04e09..e44de190 100644 --- a/Cython/Compiler/PyrexTypes.py +++ b/Cython/Compiler/PyrexTypes.py @@ -249,7 +249,7 @@ class BuiltinObjectType(PyObjectType): return type.is_pyobject and self.assignable_from(type) def type_test_code(self, arg): - return 'likely(Py%s_CheckExact(%s)) || (%s) == Py_None || (PyErr_Format(PyExc_TypeError, "Expected %s, got %%s", %s->ob_type->tp_name), 0)' % (self.name[0].upper() + self.name[1:], arg, arg, self.name, arg) + return 'likely(Py%s_CheckExact(%s)) || (%s) == Py_None || (PyErr_Format(PyExc_TypeError, "Expected %s, got %%s", Py_TYPE(%s)->tp_name), 0)' % (self.name[0].upper() + self.name[1:], arg, arg, self.name, arg) class PyExtensionType(PyObjectType): diff --git a/Cython/Compiler/Symtab.py b/Cython/Compiler/Symtab.py index b729e432..5e067ddf 100644 --- a/Cython/Compiler/Symtab.py +++ b/Cython/Compiler/Symtab.py @@ -1401,7 +1401,7 @@ static PyObject* __Pyx_Method_ClassMethod(PyObject *method); /*proto*/ static PyObject* __Pyx_Method_ClassMethod(PyObject *method) { /* It appears that PyMethodDescr_Type is not anywhere exposed in the Python/C API */ /* if (!PyObject_TypeCheck(method, &PyMethodDescr_Type)) { */ - if (strcmp(method->ob_type->tp_name, "method_descriptor") == 0) { /* cdef classes */ + if (strcmp(Py_TYPE(method)->tp_name, "method_descriptor") == 0) { /* cdef classes */ PyMethodDescrObject *descr = (PyMethodDescrObject *)method; return PyDescr_NewClassMethod(descr->d_type, descr->d_method); } diff --git a/Cython/Compiler/TypeSlots.py b/Cython/Compiler/TypeSlots.py index 29179b75..ed87b0c6 100644 --- a/Cython/Compiler/TypeSlots.py +++ b/Cython/Compiler/TypeSlots.py @@ -121,11 +121,13 @@ class SlotDescriptor: # slot_name string Member name of the slot in the type object # is_initialised_dynamically Is initialised by code in the module init function # flag Py_TPFLAGS_XXX value indicating presence of slot + # py3k Indicates presence of slot in Python 3 - def __init__(self, slot_name, dynamic = 0, flag = None): + def __init__(self, slot_name, dynamic = 0, flag = None, py3k = True): self.slot_name = slot_name self.is_initialised_dynamically = dynamic self.flag = flag + self.py3k = py3k def generate(self, scope, code): if self.is_initialised_dynamically: @@ -133,9 +135,14 @@ class SlotDescriptor: else: value = self.slot_code(scope) flag = self.flag + py3k = self.py3k + if not py3k: + code.putln("#if PY_MAJOR_VERSION < 3") if flag: - code.putln("#if Py_TPFLAGS_DEFAULT & %s" % flag) + code.putln("#if (PY_MAJOR_VERSION >= 3) || (Py_TPFLAGS_DEFAULT & %s)" % flag) code.putln("%s, /*%s*/" % (value, self.slot_name)) + if not py3k: + code.putln("#endif") if flag: code.putln("#endif") @@ -183,8 +190,8 @@ class MethodSlot(SlotDescriptor): # method_name string The __xxx__ name of the method # default string or None Default value of the slot - def __init__(self, signature, slot_name, method_name, default = None, flag = None): - SlotDescriptor.__init__(self, slot_name, flag = flag) + def __init__(self, signature, slot_name, method_name, default = None, flag = None, py3k=True): + SlotDescriptor.__init__(self, slot_name, flag = flag, py3k = py3k) self.signature = signature self.slot_name = slot_name self.method_name = method_name @@ -515,7 +522,7 @@ PyNumberMethods = ( MethodSlot(binaryfunc, "nb_add", "__add__"), MethodSlot(binaryfunc, "nb_subtract", "__sub__"), MethodSlot(binaryfunc, "nb_multiply", "__mul__"), - MethodSlot(binaryfunc, "nb_divide", "__div__"), + MethodSlot(binaryfunc, "nb_divide", "__div__", py3k = False), MethodSlot(binaryfunc, "nb_remainder", "__mod__"), MethodSlot(binaryfunc, "nb_divmod", "__divmod__"), MethodSlot(ternaryfunc, "nb_power", "__pow__"), @@ -540,7 +547,7 @@ PyNumberMethods = ( MethodSlot(ibinaryfunc, "nb_inplace_add", "__iadd__"), MethodSlot(ibinaryfunc, "nb_inplace_subtract", "__isub__"), MethodSlot(ibinaryfunc, "nb_inplace_multiply", "__imul__"), - MethodSlot(ibinaryfunc, "nb_inplace_divide", "__idiv__"), + MethodSlot(ibinaryfunc, "nb_inplace_divide", "__idiv__", py3k = False), MethodSlot(ibinaryfunc, "nb_inplace_remainder", "__imod__"), MethodSlot(ternaryfunc, "nb_inplace_power", "__ipow__"), # NOT iternaryfunc!!! MethodSlot(ibinaryfunc, "nb_inplace_lshift", "__ilshift__"), @@ -580,10 +587,10 @@ PyMappingMethods = ( ) PyBufferProcs = ( - MethodSlot(getreadbufferproc, "bf_getreadbuffer", "__getreadbuffer__"), - MethodSlot(getwritebufferproc, "bf_getwritebuffer", "__getwritebuffer__"), - MethodSlot(getsegcountproc, "bf_getsegcount", "__getsegcount__"), - MethodSlot(getcharbufferproc, "bf_getcharbuffer", "__getcharbuffer__"), + MethodSlot(getreadbufferproc, "bf_getreadbuffer", "__getreadbuffer__", py3k = False), + MethodSlot(getwritebufferproc, "bf_getwritebuffer", "__getwritebuffer__", py3k = False), + MethodSlot(getsegcountproc, "bf_getsegcount", "__getsegcount__", py3k = False), + MethodSlot(getcharbufferproc, "bf_getcharbuffer", "__getcharbuffer__", py3k = False), ) #------------------------------------------------------------------------------------------ -- 2.26.2