fixes int/long type slots in Py2/Py3 (ticket #287)
authorLisandro Dalcin <dalcinl@gmail.com>
Thu, 23 Apr 2009 21:09:53 +0000 (18:09 -0300)
committerLisandro Dalcin <dalcinl@gmail.com>
Thu, 23 Apr 2009 21:09:53 +0000 (18:09 -0300)
Cython/Compiler/PyrexTypes.py
Cython/Compiler/TypeSlots.py
tests/run/c_int_types_T255.pyx
tests/run/type_slots_int_long_T287.pyx [new file with mode: 0644]

index 6cc6e511929891bca8b49ff76924eb97ddb6af70..5c62e575deb36e06cc5883a05c73c256a8d084de 100644 (file)
@@ -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";
index bc70abcc44349e2b5e4fc60b17a26a84e5c2fee0..a6008a3b488e675fae377d49abea4cc21a25254f 100644 (file)
@@ -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 == '<RESERVED>':
+            code.putln("#if PY_MAJOR_VERSION >= 3")
+            code.putln("0, /*reserved*/")
+            code.putln("#else")
+
         code.putln("%s, /*%s*/" % (value, self.slot_name))
+        if py3k == '<RESERVED>':
+            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 = "<RESERVED>"),
     MethodSlot(unaryfunc, "nb_float", "__float__"),
     MethodSlot(unaryfunc, "nb_oct", "__oct__", py3k = False),
     MethodSlot(unaryfunc, "nb_hex", "__hex__", py3k = False),
index 1dede216c7506f205a0985338afadb4bbe3d48b8..1468aa132b508a41b0b9de3634f05c106b943343 100644 (file)
@@ -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 (file)
index 0000000..9631ef8
--- /dev/null
@@ -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 <int>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__