[pypy-svn] r73610 - in pypy/branch/cpython-extension/pypy/module/cpyext: . include test

jandem at codespeak.net jandem at codespeak.net
Sat Apr 10 13:48:55 CEST 2010


Author: jandem
Date: Sat Apr 10 13:48:53 2010
New Revision: 73610

Modified:
   pypy/branch/cpython-extension/pypy/module/cpyext/api.py
   pypy/branch/cpython-extension/pypy/module/cpyext/include/object.h
   pypy/branch/cpython-extension/pypy/module/cpyext/object.py
   pypy/branch/cpython-extension/pypy/module/cpyext/test/test_object.py
Log:
add PyObject_RichCompare{Bool}, with tests


Modified: pypy/branch/cpython-extension/pypy/module/cpyext/api.py
==============================================================================
--- pypy/branch/cpython-extension/pypy/module/cpyext/api.py	(original)
+++ pypy/branch/cpython-extension/pypy/module/cpyext/api.py	Sat Apr 10 13:48:53 2010
@@ -59,6 +59,7 @@
 METH_COEXIST METH_STATIC METH_CLASS 
 METH_NOARGS METH_VARARGS METH_KEYWORDS METH_O
 Py_TPFLAGS_HEAPTYPE Py_TPFLAGS_HAVE_CLASS
+Py_LT Py_LE Py_EQ Py_NE Py_GT Py_GE
 """.split()
 for name in constant_names:
     setattr(CConfig_constants, name, rffi_platform.ConstantInteger(name))

Modified: pypy/branch/cpython-extension/pypy/module/cpyext/include/object.h
==============================================================================
--- pypy/branch/cpython-extension/pypy/module/cpyext/include/object.h	(original)
+++ pypy/branch/cpython-extension/pypy/module/cpyext/include/object.h	Sat Apr 10 13:48:53 2010
@@ -57,6 +57,21 @@
 
 #define Py_None (&_Py_NoneStruct)
 
+/*
+Py_NotImplemented is a singleton used to signal that an operation is
+not implemented for a given type combination.
+*/
+PyAPI_DATA(PyObject) _Py_NotImplementedStruct; /* Don't use this directly */
+#define Py_NotImplemented (&_Py_NotImplementedStruct)
+
+/* Rich comparison opcodes */
+#define Py_LT 0
+#define Py_LE 1
+#define Py_EQ 2
+#define Py_NE 3
+#define Py_GT 4
+#define Py_GE 5
+
 struct _typeobject;
 typedef void (*freefunc)(void *);
 typedef void (*destructor)(PyObject *);

Modified: pypy/branch/cpython-extension/pypy/module/cpyext/object.py
==============================================================================
--- pypy/branch/cpython-extension/pypy/module/cpyext/object.py	(original)
+++ pypy/branch/cpython-extension/pypy/module/cpyext/object.py	Sat Apr 10 13:48:53 2010
@@ -1,6 +1,7 @@
 from pypy.rpython.lltypesystem import rffi, lltype
 from pypy.module.cpyext.api import cpython_api, generic_cpy_call, CANNOT_FAIL,\
-        Py_ssize_t, PyVarObject, Py_TPFLAGS_HEAPTYPE
+        Py_ssize_t, PyVarObject, Py_TPFLAGS_HEAPTYPE,\
+        Py_LT, Py_LE, Py_EQ, Py_NE, Py_GT, Py_GE
 from pypy.module.cpyext.pyobject import PyObject, make_ref, from_ref
 from pypy.module.cpyext.pyobject import Py_IncRef, Py_DecRef
 from pypy.module.cpyext.state import State
@@ -112,3 +113,31 @@
     Python expression repr(o).  Called by the repr() built-in function and
     by reverse quotes."""
     return space.repr(w_obj)
+
+ at cpython_api([PyObject, PyObject, rffi.INT_real], PyObject)
+def PyObject_RichCompare(space, w_o1, w_o2, opid):
+    """Compare the values of o1 and o2 using the operation specified by opid,
+    which must be one of Py_LT, Py_LE, Py_EQ,
+    Py_NE, Py_GT, or Py_GE, corresponding to <,
+    <=, ==, !=, >, or >= respectively. This is the equivalent of
+    the Python expression o1 op o2, where op is the operator corresponding
+    to opid. Returns the value of the comparison on success, or NULL on failure."""
+    if opid == Py_LT: return space.lt(w_o1, w_o2)
+    if opid == Py_LE: return space.le(w_o1, w_o2)
+    if opid == Py_EQ: return space.eq(w_o1, w_o2)
+    if opid == Py_NE: return space.ne(w_o1, w_o2)
+    if opid == Py_GT: return space.gt(w_o1, w_o2)
+    if opid == Py_GE: return space.ge(w_o1, w_o2)
+    PyErr_BadInternalCall(space)
+
+ at cpython_api([PyObject, PyObject, rffi.INT_real], rffi.INT_real, error=-1)
+def PyObject_RichCompareBool(space, ref1, ref2, opid):
+    """Compare the values of o1 and o2 using the operation specified by opid,
+    which must be one of Py_LT, Py_LE, Py_EQ,
+    Py_NE, Py_GT, or Py_GE, corresponding to <,
+    <=, ==, !=, >, or >= respectively. Returns -1 on error,
+    0 if the result is false, 1 otherwise. This is the equivalent of the
+    Python expression o1 op o2, where op is the operator corresponding to
+    opid."""
+    w_res = PyObject_RichCompare(space, ref1, ref2, opid)
+    return PyObject_IsTrue(space, w_res)

Modified: pypy/branch/cpython-extension/pypy/module/cpyext/test/test_object.py
==============================================================================
--- pypy/branch/cpython-extension/pypy/module/cpyext/test/test_object.py	(original)
+++ pypy/branch/cpython-extension/pypy/module/cpyext/test/test_object.py	Sat Apr 10 13:48:53 2010
@@ -2,7 +2,8 @@
 
 from pypy.module.cpyext.test.test_api import BaseApiTest
 from pypy.rpython.lltypesystem import rffi, lltype
-
+from pypy.module.cpyext.api import Py_LT, Py_LE, Py_NE, Py_EQ,\
+    Py_GE, Py_GT
 
 class TestObject(BaseApiTest):
     def test_IsTrue(self, space, api):
@@ -53,7 +54,6 @@
         lltype.free(charp1, flavor="raw")
         lltype.free(charp2, flavor="raw")
 
-    
     def test_getitem(self, space, api):
         w_t = space.wrap((1, 2, 3, 4, 5))
         assert space.unwrap(api.PyObject_GetItem(w_t, space.wrap(3))) == 4
@@ -68,3 +68,28 @@
     def test_repr(self, space, api):
         w_list = space.newlist([space.w_None, space.wrap(42)])
         assert space.str_w(api.PyObject_Repr(w_list)) == "[None, 42]"
+        
+    def test_RichCompare(self, space, api):
+        w_i1 = space.wrap(1)
+        w_i2 = space.wrap(2)
+        w_i3 = space.wrap(3)
+        
+        def compare(w_o1, w_o2, opid):
+            res = api.PyObject_RichCompareBool(w_o1, w_o2, opid)
+            w_res = api.PyObject_RichCompare(w_o1, w_o2, opid)
+            assert space.is_true(w_res) == res
+            return res
+        
+        def test_compare(o1, o2):
+            w_o1 = space.wrap(o1)
+            w_o2 = space.wrap(o2)
+            
+            for opid, expected in [
+                    (Py_LT, o1 <  o2), (Py_LE, o1 <= o2),
+                    (Py_NE, o1 != o2), (Py_EQ, o1 == o2),
+                    (Py_GT, o1 >  o2), (Py_GE, o1 >= o2)]:
+                assert compare(w_o1, w_o2, opid) == expected
+
+        test_compare(1, 2)
+        test_compare(2, 2)
+        test_compare('2', '1')



More information about the Pypy-commit mailing list