Commits

Lenard Lindstrom committed 09ef757

CPython C-api additions for Pygame base.c and surface.c

Comments (0)

Files changed (3)

PyLong_FromVoidPtr

+# HG changeset patch
+# Parent 7ab619834c25a08a249146817edca903fdaacd67
+ensure PyLong_FromVoidPtr returns a non-negative value (Python 2.5 and up)
+
+A negative int instance is incompatible with Python 2.7:
+http://docs.python.org/2/c-api/long.html#PyLong_FromVoidPtr
+
+For Pygame, a negative (void *) address lead to a pygame.base module unit
+test fail in test_PgObject_GetBuffer_array_interface() of base_test.py.
+
+diff -r 7ab619834c25 -r f164df25a4bf pypy/module/cpyext/longobject.py
+--- a/pypy/module/cpyext/longobject.py	Wed Oct 30 19:47:23 2013 +0100
++++ b/pypy/module/cpyext/longobject.py	Wed Oct 30 13:49:00 2013 -0700
+@@ -6,8 +6,9 @@
+ from pypy.interpreter.error import OperationError
+ from pypy.module.cpyext.intobject import PyInt_AsUnsignedLongMask
+ from rpython.rlib.rbigint import rbigint
+-from rpython.rlib.rarithmetic import intmask
++from rpython.rlib.rarithmetic import intmask, LONG_TEST
+ 
++LONG_MAX = int(LONG_TEST - 1)
+ 
+ PyLong_Check, PyLong_CheckExact = build_type_checkers("Long")
+ 
+@@ -192,7 +193,10 @@
+     can be retrieved from the resulting value using PyLong_AsVoidPtr().
+ 
+     If the integer is larger than LONG_MAX, a positive long integer is returned."""
+-    return space.wrap(rffi.cast(ADDR, p))
++    addr = rffi.cast(lltype.Unsigned, p)
++    if addr <= LONG_MAX:
++        return space.wrap(intmask(addr))
++    return space.wrap(addr)
+ 
+ @cpython_api([PyObject], rffi.VOIDP, error=lltype.nullptr(rffi.VOIDP.TO))
+ def PyLong_AsVoidPtr(space, w_long):
+diff -r 7ab619834c25 -r f164df25a4bf pypy/module/cpyext/test/test_longobject.py
+--- a/pypy/module/cpyext/test/test_longobject.py	Wed Oct 30 19:47:23 2013 +0100
++++ b/pypy/module/cpyext/test/test_longobject.py	Wed Oct 30 13:49:00 2013 -0700
+@@ -4,6 +4,7 @@
+ from pypy.objspace.std.longobject import W_LongObject
+ from pypy.module.cpyext.test.test_api import BaseApiTest
+ from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
++from rpython.rlib.rarithmetic import LONG_TEST
+ 
+ 
+ class TestLongObject(BaseApiTest):
+@@ -106,6 +107,12 @@
+         assert space.unwrap(w_l) == 0L
+         assert api.PyLong_AsVoidPtr(w_l) == lltype.nullptr(rffi.VOIDP.TO)
+ 
++        #PyLong_FromVoidPtr always returns a non-negative value
++        vp = rffi.cast(rffi.VOIDP, LONG_TEST)
++        w_l = api.PyLong_FromVoidPtr(vp)
++        assert space.is_true(space.isinstance(w_l, space.w_long))
++        assert space.is_true(space.ge(w_l, space.wrap(0)))
++        
+     def test_sign_and_bits(self, space, api):
+         if space.is_true(space.lt(space.sys.get('version_info'),
+                                   space.wrap((2, 7)))):

PyWeakref_CheckRef

+# HG changeset patch
+# Parent f164df25a4bf4caad0c0dd18990fd6f1c73bdd12
+add PyWeakref_CheckRef CPython C-api function
+
+http://docs.python.org/2/c-api/weakref.html#PyWeakref_CheckRef
+
+Used by the Pygame pygame.Surface extension class (defined in src/surface.c).
+
+diff -r f164df25a4bf -r 0e09316f5b62 pypy/module/cpyext/test/test_weakref.py
+--- a/pypy/module/cpyext/test/test_weakref.py	Wed Oct 30 13:49:00 2013 -0700
++++ b/pypy/module/cpyext/test/test_weakref.py	Wed Oct 30 14:00:28 2013 -0700
+@@ -1,5 +1,6 @@
+ from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
+ from pypy.module.cpyext.test.test_api import BaseApiTest
++from pypy.module._weakref.interp__weakref import W_Weakref
+ 
+ class TestWeakReference(BaseApiTest):
+     def test_weakref(self, space, api):
+@@ -34,3 +35,22 @@
+         del w_obj
+         import gc; gc.collect()
+         assert space.is_w(api.PyWeakref_LockObject(w_ref), space.w_None)
++
++    def test_weakref_checkref(self, space, api):
++        w_obj = space.w_Exception # some weakrefable object
++        w_ref = api.PyWeakref_NewRef(w_obj, space.w_None)
++        assert w_ref is not None
++        assert api.PyWeakref_CheckRef(w_ref)
++
++        # ReferenceType can be subclassed
++        w_weakref = space.gettypeobject(W_Weakref.typedef)
++        w_subclass = space.call_function(space.w_type,
++                                         space.wrap("WeakrefSubclass"),
++                                         space.newtuple([w_weakref]),
++                                         space.newdict())
++        assert space.is_true(space.issubtype(w_subclass, w_weakref))
++        w_ref = space.call_function(w_weakref, w_obj)
++        assert api.PyWeakref_CheckRef(w_ref)
++
++        assert not api.PyWeakref_CheckRef(w_obj)
++        assert not api.PyWeakref_CheckRef(None)
+diff -r f164df25a4bf -r 0e09316f5b62 pypy/module/cpyext/weakrefobject.py
+--- a/pypy/module/cpyext/weakrefobject.py	Wed Oct 30 13:49:00 2013 -0700
++++ b/pypy/module/cpyext/weakrefobject.py	Wed Oct 30 14:00:28 2013 -0700
+@@ -1,4 +1,5 @@
+-from pypy.module.cpyext.api import cpython_api
++from rpython.rtyper.lltypesystem import rffi
++from pypy.module.cpyext.api import cpython_api, CANNOT_FAIL
+ from pypy.module.cpyext.pyobject import PyObject, borrow_from
+ from pypy.module._weakref.interp__weakref import W_Weakref, proxy
+ 
+@@ -51,3 +52,13 @@
+     """
+     return space.call_function(w_ref)
+ 
++@cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL)
++def PyWeakref_CheckRef(space, w_obj):
++    """Return true if *ob* is a reference object.
++    """
++    if w_obj is None:
++        return False
++    w_obj_type = space.type(w_obj)
++    w_weakref = space.gettypeobject(W_Weakref.typedef)
++    return (space.is_w(w_obj_type, w_weakref) or
++            space.is_true(space.issubtype(w_obj_type, w_weakref)))
+PyLong_FromVoidPtr
+PyWeakref_CheckRef
 # Placed by Bitbucket