[Python-checkins] r68578 - in sandbox/trunk/io-c: _bufferedio.c _iomodule.h io.c test_io.py

antoine.pitrou python-checkins at python.org
Tue Jan 13 21:45:42 CET 2009


Author: antoine.pitrou
Date: Tue Jan 13 21:45:41 2009
New Revision: 68578

Log:
Define our own PyNumber_AsOff_t with the expected behaviour



Modified:
   sandbox/trunk/io-c/_bufferedio.c
   sandbox/trunk/io-c/_iomodule.h
   sandbox/trunk/io-c/io.c
   sandbox/trunk/io-c/test_io.py

Modified: sandbox/trunk/io-c/_bufferedio.c
==============================================================================
--- sandbox/trunk/io-c/_bufferedio.c	(original)
+++ sandbox/trunk/io-c/_bufferedio.c	Tue Jan 13 21:45:41 2009
@@ -737,10 +737,10 @@
 {
     Py_off_t target, n;
     int whence = 0;
-    PyObject *res = NULL;
+    PyObject *targetobj, *res = NULL;
 
     CHECK_INITIALIZED(self)
-    if (!PyArg_ParseTuple(args, OFF_T_ARG "|i:seek", &target, &whence)) {
+    if (!PyArg_ParseTuple(args, "O|i:seek", &targetobj, &whence)) {
         return NULL;
     }
     
@@ -749,6 +749,9 @@
                      "whence must be between 0 and 2, not %d", whence);
         return NULL;
     }
+    target = PyNumber_AsOff_t(targetobj, PyExc_ValueError);
+    if (target == -1 && PyErr_Occurred())
+        return NULL;
 
     ENTER_BUFFERED(self)
 

Modified: sandbox/trunk/io-c/_iomodule.h
==============================================================================
--- sandbox/trunk/io-c/_iomodule.h	(original)
+++ sandbox/trunk/io-c/_iomodule.h	Tue Jan 13 21:45:41 2009
@@ -53,36 +53,46 @@
 PyObject *PyExc_BlockingIOError;
 
 
+/*
+ * Offset type for positioning.
+ */
+
 #if defined(MS_WIN64) || defined(MS_WINDOWS)
 
 /* Windows uses long long for offsets */
 typedef PY_LONG_LONG Py_off_t;
-# define PyNumber_AsOff_t(o, exc) PyLong_AsLongLong(o)
-# define PyLong_FromOff_t         PyLong_FromLongLong
-# define OFF_T_ARG "L"
+# define PyLong_AsOff_t     PyLong_AsLongLong
+# define PyLong_FromOff_t   PyLong_FromLongLong
+# define PY_OFF_T_MAX       PY_LLONG_MAX
+# define PY_OFF_T_MIN       PY_LLONG_MIN
 
 #else
 
 /* Other platforms use off_t */
 typedef off_t Py_off_t;
 #if (SIZEOF_OFF_T == SIZEOF_SIZE_T)
-# define PyNumber_AsOff_t         PyNumber_AsSsize_t
-# define PyLong_FromOff_t         PyLong_FromSsize_t
-# define OFF_T_ARG "n"
+# define PyLong_AsOff_t     PyLong_AsSsize_t
+# define PyLong_FromOff_t   PyLong_FromSsize_t
+# define PY_OFF_T_MAX       PY_SSIZE_T_MAX
+# define PY_OFF_T_MIN       PY_SSIZE_T_MIN
 #elif (SIZEOF_OFF_T == SIZEOF_LONG_LONG)
-# define PyNumber_AsOff_t(o, exc) PyLong_AsLongLong(o)
-# define PyLong_FromOff_t         PyLong_FromLongLong
-# define OFF_T_ARG "L"
+# define PyLong_AsOff_t     PyLong_AsLongLong
+# define PyLong_FromOff_t   PyLong_FromLongLong
+# define PY_OFF_T_MAX       PY_LLONG_MAX
+# define PY_OFF_T_MIN       PY_LLONG_MIN
 #elif (SIZEOF_OFF_T == SIZEOF_LONG)
-# define PyNumber_AsOff_t(o, exc) PyLong_AsLong(o)
-# define PyLong_FromOff_t         PyLong_FromLong
-# define OFF_T_ARG "l"
+# define PyLong_AsOff_t     PyLong_AsLong
+# define PyLong_FromOff_t   PyLong_FromLong
+# define PY_OFF_T_MAX       LONG_MAX
+# define PY_OFF_T_MIN       LONG_MIN
 #else
 # error off_t does not match either size_t, long, or long long!
 #endif
 
 #endif
 
+extern Py_off_t PyNumber_AsOff_t(PyObject *item, PyObject *err);
+
 /* Implementation details */
 
 extern PyObject *_PyIO_str_close;

Modified: sandbox/trunk/io-c/io.c
==============================================================================
--- sandbox/trunk/io-c/io.c	(original)
+++ sandbox/trunk/io-c/io.c	Tue Jan 13 21:45:41 2009
@@ -509,6 +509,53 @@
     return NULL;
 }
 
+/*
+ * Private helpers for the io module.
+ */
+
+Py_off_t
+PyNumber_AsOff_t(PyObject *item, PyObject *err)
+{
+    Py_off_t result;
+    PyObject *runerr;
+    PyObject *value = PyNumber_Index(item);
+    if (value == NULL)
+        return -1;
+
+    /* We're done if PyLong_AsSsize_t() returns without error. */
+    result = PyLong_AsOff_t(value);
+    if (result != -1 || !(runerr = PyErr_Occurred()))
+        goto finish;
+
+    /* Error handling code -- only manage OverflowError differently */
+    if (!PyErr_GivenExceptionMatches(runerr, PyExc_OverflowError))
+        goto finish;
+
+    PyErr_Clear();
+    /* If no error-handling desired then the default clipping
+       is sufficient.
+     */
+    if (!err) {
+        assert(PyLong_Check(value));
+        /* Whether or not it is less than or equal to
+           zero is determined by the sign of ob_size
+        */
+        if (_PyLong_Sign(value) < 0)
+            result = PY_OFF_T_MIN;
+        else
+            result = PY_OFF_T_MAX;
+    }
+    else {
+        /* Otherwise replace the error with caller's error object. */
+        PyErr_Format(err,
+                     "cannot fit '%.200s' into an offset-sized integer",
+                     item->ob_type->tp_name);
+    }
+
+ finish:
+    Py_DECREF(value);
+    return result;
+}
 
 /*
  * Module definition

Modified: sandbox/trunk/io-c/test_io.py
==============================================================================
--- sandbox/trunk/io-c/test_io.py	(original)
+++ sandbox/trunk/io-c/test_io.py	Tue Jan 13 21:45:41 2009
@@ -177,8 +177,7 @@
         self.assertEqual(f.tell(), 13)
         self.assertEqual(f.truncate(12), 12)
         self.assertEqual(f.tell(), 12)
-        # Disabled until PyNumber_AsOff_t exists
-        #self.assertRaises(TypeError, f.seek, 0.0)
+        self.assertRaises(TypeError, f.seek, 0.0)
 
     def read_ops(self, f, buffered=False):
         data = f.read(5)
@@ -200,8 +199,7 @@
         self.assertEqual(f.seek(-6, 1), 5)
         self.assertEqual(f.read(5), b" worl")
         self.assertEqual(f.tell(), 10)
-        # Disabled until PyNumber_AsOff_t exists
-        #self.assertRaises(TypeError, f.seek, 0.0)
+        self.assertRaises(TypeError, f.seek, 0.0)
         if buffered:
             f.seek(0)
             self.assertEqual(f.read(), b"hello world\n")
@@ -915,8 +913,7 @@
         rw.seek(2, 1)
         self.assertEquals(7, rw.tell())
         self.assertEquals(b"fl", rw.read(11))
-        # Disabled until PyNumber_AsOff_t exists
-        #self.assertRaises(TypeError, rw.seek, 0.0)
+        self.assertRaises(TypeError, rw.seek, 0.0)
 
     def check_flush_and_read(self, read_func):
         raw = io.BytesIO(b"abcdefghi")


More information about the Python-checkins mailing list