[pypy-svn] pypy default: Improve api.py to detect when we mess up the return type -- at least

arigo commits-noreply at bitbucket.org
Thu Jan 27 15:53:35 CET 2011


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r41395:c68ceebd52ab
Date: 2011-01-27 15:52 +0100
http://bitbucket.org/pypy/pypy/changeset/c68ceebd52ab/

Log:	Improve api.py to detect when we mess up the return type -- at least
	when we return an integer when a wrapped object is expected or vice-
	versa. Fix cdatetime.py accordingly.

diff --git a/pypy/module/cpyext/test/test_datetime.py b/pypy/module/cpyext/test/test_datetime.py
--- a/pypy/module/cpyext/test/test_datetime.py
+++ b/pypy/module/cpyext/test/test_datetime.py
@@ -10,11 +10,9 @@
         assert api.PyDate_Check(w_date)
         assert api.PyDate_CheckExact(w_date)
 
-        assert space.unwrap(space.newtuple([
-            api.PyDateTime_GET_YEAR(w_date),
-            api.PyDateTime_GET_MONTH(w_date),
-            api.PyDateTime_GET_DAY(w_date)])) == (
-            2010, 06, 03)
+        assert api.PyDateTime_GET_YEAR(w_date) == 2010
+        assert api.PyDateTime_GET_MONTH(w_date) == 6
+        assert api.PyDateTime_GET_DAY(w_date) == 3
 
     def test_time(self, space, api):
         w_time = api.PyTime_FromTime(23, 15, 40, 123456)
@@ -23,12 +21,10 @@
         assert api.PyTime_Check(w_time)
         assert api.PyTime_CheckExact(w_time)
 
-        assert space.unwrap(space.newtuple([
-            api.PyDateTime_TIME_GET_HOUR(w_time),
-            api.PyDateTime_TIME_GET_MINUTE(w_time),
-            api.PyDateTime_TIME_GET_SECOND(w_time),
-            api.PyDateTime_TIME_GET_MICROSECOND(w_time)])) == (
-            23, 15, 40, 123456)
+        assert api.PyDateTime_TIME_GET_HOUR(w_time) == 23
+        assert api.PyDateTime_TIME_GET_MINUTE(w_time) == 15
+        assert api.PyDateTime_TIME_GET_SECOND(w_time) == 40
+        assert api.PyDateTime_TIME_GET_MICROSECOND(w_time) == 123456
 
     def test_datetime(self, space, api):
         w_date = api.PyDateTime_FromDateAndTime(
@@ -40,15 +36,13 @@
         assert api.PyDate_Check(w_date)
         assert not api.PyDate_CheckExact(w_date)
 
-        assert space.unwrap(space.newtuple([
-            api.PyDateTime_GET_YEAR(w_date),
-            api.PyDateTime_GET_MONTH(w_date),
-            api.PyDateTime_GET_DAY(w_date),
-            api.PyDateTime_DATE_GET_HOUR(w_date),
-            api.PyDateTime_DATE_GET_MINUTE(w_date),
-            api.PyDateTime_DATE_GET_SECOND(w_date),
-            api.PyDateTime_DATE_GET_MICROSECOND(w_date)])) == (
-            2010, 06, 03, 23, 15, 40, 123456)
+        assert api.PyDateTime_GET_YEAR(w_date) == 2010
+        assert api.PyDateTime_GET_MONTH(w_date) == 6
+        assert api.PyDateTime_GET_DAY(w_date) == 3
+        assert api.PyDateTime_DATE_GET_HOUR(w_date) == 23
+        assert api.PyDateTime_DATE_GET_MINUTE(w_date) == 15
+        assert api.PyDateTime_DATE_GET_SECOND(w_date) == 40
+        assert api.PyDateTime_DATE_GET_MICROSECOND(w_date) == 123456
 
     def test_delta(self, space, api):
         w_delta = space.appexec(
@@ -63,11 +57,9 @@
         assert api.PyDelta_Check(w_delta)
         assert api.PyDelta_CheckExact(w_delta)
 
-        assert space.unwrap(space.newtuple([
-            api.PyDateTime_DELTA_GET_DAYS(w_delta),
-            api.PyDateTime_DELTA_GET_SECONDS(w_delta),
-            api.PyDateTime_DELTA_GET_MICROSECONDS(w_delta)])) == (
-            10, 20, 30)
+        assert api.PyDateTime_DELTA_GET_DAYS(w_delta) == 10
+        assert api.PyDateTime_DELTA_GET_SECONDS(w_delta) == 20
+        assert api.PyDateTime_DELTA_GET_MICROSECONDS(w_delta) == 30
 
     def test_fromtimestamp(self, space, api):
         w_args = space.wrap((0,))

diff --git a/pypy/module/cpyext/cdatetime.py b/pypy/module/cpyext/cdatetime.py
--- a/pypy/module/cpyext/cdatetime.py
+++ b/pypy/module/cpyext/cdatetime.py
@@ -171,67 +171,67 @@
 def PyDateTime_GET_YEAR(space, w_obj):
     """Return the year, as a positive int.
     """
-    return space.getattr(w_obj, space.wrap("year"))
+    return space.int_w(space.getattr(w_obj, space.wrap("year")))
 
 @cpython_api([PyDateTime_Date], rffi.INT_real, error=CANNOT_FAIL)
 def PyDateTime_GET_MONTH(space, w_obj):
     """Return the month, as an int from 1 through 12.
     """
-    return space.getattr(w_obj, space.wrap("month"))
+    return space.int_w(space.getattr(w_obj, space.wrap("month")))
 
 @cpython_api([PyDateTime_Date], rffi.INT_real, error=CANNOT_FAIL)
 def PyDateTime_GET_DAY(space, w_obj):
     """Return the day, as an int from 1 through 31.
     """
-    return space.getattr(w_obj, space.wrap("day"))
+    return space.int_w(space.getattr(w_obj, space.wrap("day")))
 
 @cpython_api([PyDateTime_DateTime], rffi.INT_real, error=CANNOT_FAIL)
 def PyDateTime_DATE_GET_HOUR(space, w_obj):
     """Return the hour, as an int from 0 through 23.
     """
-    return space.getattr(w_obj, space.wrap("hour"))
+    return space.int_w(space.getattr(w_obj, space.wrap("hour")))
 
 @cpython_api([PyDateTime_DateTime], rffi.INT_real, error=CANNOT_FAIL)
 def PyDateTime_DATE_GET_MINUTE(space, w_obj):
     """Return the minute, as an int from 0 through 59.
     """
-    return space.getattr(w_obj, space.wrap("minute"))
+    return space.int_w(space.getattr(w_obj, space.wrap("minute")))
 
 @cpython_api([PyDateTime_DateTime], rffi.INT_real, error=CANNOT_FAIL)
 def PyDateTime_DATE_GET_SECOND(space, w_obj):
     """Return the second, as an int from 0 through 59.
     """
-    return space.getattr(w_obj, space.wrap("second"))
+    return space.int_w(space.getattr(w_obj, space.wrap("second")))
 
 @cpython_api([PyDateTime_DateTime], rffi.INT_real, error=CANNOT_FAIL)
 def PyDateTime_DATE_GET_MICROSECOND(space, w_obj):
     """Return the microsecond, as an int from 0 through 999999.
     """
-    return space.getattr(w_obj, space.wrap("microsecond"))
+    return space.int_w(space.getattr(w_obj, space.wrap("microsecond")))
 
 @cpython_api([PyDateTime_Time], rffi.INT_real, error=CANNOT_FAIL)
 def PyDateTime_TIME_GET_HOUR(space, w_obj):
     """Return the hour, as an int from 0 through 23.
     """
-    return space.getattr(w_obj, space.wrap("hour"))
+    return space.int_w(space.getattr(w_obj, space.wrap("hour")))
 
 @cpython_api([PyDateTime_Time], rffi.INT_real, error=CANNOT_FAIL)
 def PyDateTime_TIME_GET_MINUTE(space, w_obj):
     """Return the minute, as an int from 0 through 59.
     """
-    return space.getattr(w_obj, space.wrap("minute"))
+    return space.int_w(space.getattr(w_obj, space.wrap("minute")))
 
 @cpython_api([PyDateTime_Time], rffi.INT_real, error=CANNOT_FAIL)
 def PyDateTime_TIME_GET_SECOND(space, w_obj):
     """Return the second, as an int from 0 through 59.
     """
-    return space.getattr(w_obj, space.wrap("second"))
+    return space.int_w(space.getattr(w_obj, space.wrap("second")))
 
 @cpython_api([PyDateTime_Time], rffi.INT_real, error=CANNOT_FAIL)
 def PyDateTime_TIME_GET_MICROSECOND(space, w_obj):
     """Return the microsecond, as an int from 0 through 999999.
     """
-    return space.getattr(w_obj, space.wrap("microsecond"))
+    return space.int_w(space.getattr(w_obj, space.wrap("microsecond")))
 
 # XXX these functions are not present in the Python API
 # But it does not seem possible to expose a different structure
@@ -239,12 +239,12 @@
 
 @cpython_api([PyDateTime_Delta], rffi.INT_real, error=CANNOT_FAIL)
 def PyDateTime_DELTA_GET_DAYS(space, w_obj):
-    return space.getattr(w_obj, space.wrap("days"))
+    return space.int_w(space.getattr(w_obj, space.wrap("days")))
 
 @cpython_api([PyDateTime_Delta], rffi.INT_real, error=CANNOT_FAIL)
 def PyDateTime_DELTA_GET_SECONDS(space, w_obj):
-    return space.getattr(w_obj, space.wrap("seconds"))
+    return space.int_w(space.getattr(w_obj, space.wrap("seconds")))
 
 @cpython_api([PyDateTime_Delta], rffi.INT_real, error=CANNOT_FAIL)
 def PyDateTime_DELTA_GET_MICROSECONDS(space, w_obj):
-    return space.getattr(w_obj, space.wrap("microseconds"))
+    return space.int_w(space.getattr(w_obj, space.wrap("microseconds")))

diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py
--- a/pypy/module/cpyext/api.py
+++ b/pypy/module/cpyext/api.py
@@ -199,6 +199,8 @@
             error = CANNOT_FAIL
     if type(error) is int:
         error = rffi.cast(restype, error)
+    expect_integer = (isinstance(restype, lltype.Primitive) and
+                      rffi.cast(restype, 0) == 0)
 
     def decorate(func):
         func_name = func.func_name
@@ -268,6 +270,9 @@
                             return None
                         else:
                             return api_function.error_value
+                    if not we_are_translated():
+                        got_integer = isinstance(res, (int, long, float))
+                        assert got_integer == expect_integer
                     if res is None:
                         return None
                     elif isinstance(res, Reference):


More information about the Pypy-commit mailing list