From 8aedb60cf7433b239ad682beaefd6fec6650bc24 Mon Sep 17 00:00:00 2001 From: Lisandro Dalcin Date: Thu, 23 Apr 2009 18:09:53 -0300 Subject: [PATCH] fixes int/long type slots in Py2/Py3 (ticket #287) --- Cython/Compiler/PyrexTypes.py | 10 ++-- Cython/Compiler/TypeSlots.py | 20 ++++++-- tests/run/c_int_types_T255.pyx | 11 +++++ tests/run/type_slots_int_long_T287.pyx | 66 ++++++++++++++++++++++++++ 4 files changed, 97 insertions(+), 10 deletions(-) create mode 100644 tests/run/type_slots_int_long_T287.pyx diff --git a/Cython/Compiler/PyrexTypes.py b/Cython/Compiler/PyrexTypes.py index 6cc6e511..5c62e575 100644 --- a/Cython/Compiler/PyrexTypes.py +++ b/Cython/Compiler/PyrexTypes.py @@ -1741,14 +1741,14 @@ static INLINE PyObject* __Pyx_PyNumber_Int(PyObject* x) { return Py_INCREF(x), x; m = Py_TYPE(x)->tp_as_number; #if PY_VERSION_HEX < 0x03000000 - if (m && m->nb_long) { - name = "long"; - res = PyNumber_Long(x); - } - else if (m && m->nb_int) { + if (m && m->nb_int) { name = "int"; res = PyNumber_Int(x); } + else if (m && m->nb_long) { + name = "long"; + res = PyNumber_Long(x); + } #else if (m && m->nb_int) { name = "int"; diff --git a/Cython/Compiler/TypeSlots.py b/Cython/Compiler/TypeSlots.py index bc70abcc..a6008a3b 100644 --- a/Cython/Compiler/TypeSlots.py +++ b/Cython/Compiler/TypeSlots.py @@ -154,7 +154,14 @@ class SlotDescriptor(object): code.putln("#if PY_MAJOR_VERSION >= 3") if flag: code.putln("#if (PY_MAJOR_VERSION >= 3) || (Py_TPFLAGS_DEFAULT & %s)" % flag) + if py3k == '': + code.putln("#if PY_MAJOR_VERSION >= 3") + code.putln("0, /*reserved*/") + code.putln("#else") + code.putln("%s, /*%s*/" % (value, self.slot_name)) + if py3k == '': + code.putln("#endif") if flag or (not py3k or not py2) or self.ifdef: code.putln("#endif") @@ -212,10 +219,13 @@ class MethodSlot(SlotDescriptor): def slot_code(self, scope): entry = scope.lookup_here(self.method_name) - if entry: + if entry and entry.func_cname: return entry.func_cname - else: - return "0" + if self.default is not None: + entry = scope.lookup_here(self.default) + if entry and entry.func_cname: + return entry.func_cname + return "0" class InternalMethodSlot(SlotDescriptor): @@ -557,8 +567,8 @@ PyNumberMethods = ( MethodSlot(binaryfunc, "nb_xor", "__xor__"), MethodSlot(binaryfunc, "nb_or", "__or__"), EmptySlot("nb_coerce", py3k = False), - MethodSlot(unaryfunc, "nb_int", "__int__"), - MethodSlot(unaryfunc, "nb_long", "__long__"), + MethodSlot(unaryfunc, "nb_int", "__int__", default="__long__"), + MethodSlot(unaryfunc, "nb_long", "__long__", default="__int__", py3k = ""), MethodSlot(unaryfunc, "nb_float", "__float__"), MethodSlot(unaryfunc, "nb_oct", "__oct__", py3k = False), MethodSlot(unaryfunc, "nb_hex", "__hex__", py3k = False), diff --git a/tests/run/c_int_types_T255.pyx b/tests/run/c_int_types_T255.pyx index 1dede216..1468aa13 100644 --- a/tests/run/c_int_types_T255.pyx +++ b/tests/run/c_int_types_T255.pyx @@ -666,6 +666,17 @@ class MyBadInt(MyInt): def __int__(self): return u"%s" % self.value +class MyInt2: + def __init__(self, value): + self.value = value + def __int__(self): + print(u"MyInt.__int__()") + return self.value + +class MyBadInt2(MyInt2): + def __int__(self): + return u"%s" % self.value + def test_convert_pyint(x): u""" >>> test_convert_pyint(None) diff --git a/tests/run/type_slots_int_long_T287.pyx b/tests/run/type_slots_int_long_T287.pyx new file mode 100644 index 00000000..9631ef82 --- /dev/null +++ b/tests/run/type_slots_int_long_T287.pyx @@ -0,0 +1,66 @@ +__doc__ = u""" +>>> print( "%d" % Int() ) +2 +>>> print( "%d" % Long() ) +3 +>>> print( "%d" % IntLongA() ) +2 +>>> print( "%d" % IntLongB() ) +2 +>>> print( "%d" % IntLongC() ) +3 + +>>> getint( Int() ) +2 +>>> getint( Long() ) +3 +>>> getint( IntLongA() ) +2 +>>> getint( IntLongB() ) +2 +>>> getint( IntLongC() ) +3 + +>>> getlong( Int() ) +2 +>>> getlong( Long() ) +3 +>>> getlong( IntLongA() ) +2 +>>> getlong( IntLongB() ) +2 +>>> getlong( IntLongC() ) +3 +""" + + +def getint(int i): + return i + +def getlong(long long i): + return i + + +cdef class Int: + def __int__(self): + return 2 + +cdef class Long: + def __long__(self): + return 3 + +cdef class IntLongA: + def __int__(self): + return 2 + def __long__(self): + return 3 + +cdef class IntLongB: + def __int__(self): + return 2 + __long__ = __int__ + +cdef class IntLongC: + def __long__(self): + return 3 + __int__ = __long__ -- 2.26.2