[Python-checkins] cpython: Issue #1172711: Add 'long long' support to the array module.

meador.inge python-checkins at python.org
Wed Sep 21 03:04:06 CEST 2011


http://hg.python.org/cpython/rev/15659e0e2b2e
changeset:   72430:15659e0e2b2e
user:        Meador Inge <meadori at gmail.com>
date:        Tue Sep 20 19:55:51 2011 -0500
summary:
  Issue #1172711: Add 'long long' support to the array module.

Initial patch by Oren Tirosh and Hirokazu Yamamoto.

files:
  Doc/library/array.rst  |  66 ++++++++++++++----------
  Lib/test/test_array.py |  21 +++++++
  Misc/NEWS              |   3 +
  Modules/arraymodule.c  |  79 +++++++++++++++++++++++++++++-
  4 files changed, 141 insertions(+), 28 deletions(-)


diff --git a/Doc/library/array.rst b/Doc/library/array.rst
--- a/Doc/library/array.rst
+++ b/Doc/library/array.rst
@@ -14,37 +14,49 @@
 :dfn:`type code`, which is a single character.  The following type codes are
 defined:
 
-+-----------+----------------+-------------------+-----------------------+
-| Type code | C Type         | Python Type       | Minimum size in bytes |
-+===========+================+===================+=======================+
-| ``'b'``   | signed char    | int               | 1                     |
-+-----------+----------------+-------------------+-----------------------+
-| ``'B'``   | unsigned char  | int               | 1                     |
-+-----------+----------------+-------------------+-----------------------+
-| ``'u'``   | Py_UNICODE     | Unicode character | 2 (see note)          |
-+-----------+----------------+-------------------+-----------------------+
-| ``'h'``   | signed short   | int               | 2                     |
-+-----------+----------------+-------------------+-----------------------+
-| ``'H'``   | unsigned short | int               | 2                     |
-+-----------+----------------+-------------------+-----------------------+
-| ``'i'``   | signed int     | int               | 2                     |
-+-----------+----------------+-------------------+-----------------------+
-| ``'I'``   | unsigned int   | int               | 2                     |
-+-----------+----------------+-------------------+-----------------------+
-| ``'l'``   | signed long    | int               | 4                     |
-+-----------+----------------+-------------------+-----------------------+
-| ``'L'``   | unsigned long  | int               | 4                     |
-+-----------+----------------+-------------------+-----------------------+
-| ``'f'``   | float          | float             | 4                     |
-+-----------+----------------+-------------------+-----------------------+
-| ``'d'``   | double         | float             | 8                     |
-+-----------+----------------+-------------------+-----------------------+
++-----------+--------------------+-------------------+-----------------------+-------+
+| Type code | C Type             | Python Type       | Minimum size in bytes | Notes |
++===========+====================+===================+=======================+=======+
+| ``'b'``   | signed char        | int               | 1                     |       |
++-----------+--------------------+-------------------+-----------------------+-------+
+| ``'B'``   | unsigned char      | int               | 1                     |       |
++-----------+--------------------+-------------------+-----------------------+-------+
+| ``'u'``   | Py_UNICODE         | Unicode character | 2                     | \(1)  |
++-----------+--------------------+-------------------+-----------------------+-------+
+| ``'h'``   | signed short       | int               | 2                     |       |
++-----------+--------------------+-------------------+-----------------------+-------+
+| ``'H'``   | unsigned short     | int               | 2                     |       |
++-----------+--------------------+-------------------+-----------------------+-------+
+| ``'i'``   | signed int         | int               | 2                     |       |
++-----------+--------------------+-------------------+-----------------------+-------+
+| ``'I'``   | unsigned int       | int               | 2                     |       |
++-----------+--------------------+-------------------+-----------------------+-------+
+| ``'l'``   | signed long        | int               | 4                     |       |
++-----------+--------------------+-------------------+-----------------------+-------+
+| ``'L'``   | unsigned long      | int               | 4                     |       |
++-----------+--------------------+-------------------+-----------------------+-------+
+| ``'q'``   | signed long long   | int               | 8                     | \(2)  |
++-----------+--------------------+-------------------+-----------------------+-------+
+| ``'Q'``   | unsigned long long | int               | 8                     | \(2)  |
++-----------+--------------------+-------------------+-----------------------+-------+
+| ``'f'``   | float              | float             | 4                     |       |
++-----------+--------------------+-------------------+-----------------------+-------+
+| ``'d'``   | double             | float             | 8                     |       |
++-----------+--------------------+-------------------+-----------------------+-------+
 
-.. note::
+Notes:
 
-   The ``'u'`` typecode corresponds to Python's unicode character.  On narrow
+(1)
+   The ``'u'`` type code corresponds to Python's unicode character.  On narrow
    Unicode builds this is 2-bytes, on wide builds this is 4-bytes.
 
+(2)
+   The ``'q'`` and ``'Q'`` type codes are available only if
+   the platform C compiler used to build Python supports C :ctype:`long long`,
+   or, on Windows, :ctype:`__int64`.
+
+   .. versionadded:: 3.3
+
 The actual representation of values is determined by the machine architecture
 (strictly speaking, by the C implementation).  The actual size can be accessed
 through the :attr:`itemsize` attribute.
diff --git a/Lib/test/test_array.py b/Lib/test/test_array.py
--- a/Lib/test/test_array.py
+++ b/Lib/test/test_array.py
@@ -16,6 +16,13 @@
 import array
 from array import _array_reconstructor as array_reconstructor
 
+try:
+    # Try to determine availability of long long independently
+    # of the array module under test
+    struct.calcsize('@q')
+    have_long_long = True
+except struct.error:
+    have_long_long = False
 
 class ArraySubclass(array.array):
     pass
@@ -26,6 +33,8 @@
 
 tests = [] # list to accumulate all tests
 typecodes = "ubBhHiIlLfd"
+if have_long_long:
+    typecodes += 'qQ'
 
 class BadConstructorTest(unittest.TestCase):
 
@@ -1205,6 +1214,18 @@
     minitemsize = 4
 tests.append(UnsignedLongTest)
 
+ at unittest.skipIf(not have_long_long, 'need long long support')
+class LongLongTest(SignedNumberTest):
+    typecode = 'q'
+    minitemsize = 8
+tests.append(LongLongTest)
+
+ at unittest.skipIf(not have_long_long, 'need long long support')
+class UnsignedLongLongTest(UnsignedNumberTest):
+    typecode = 'Q'
+    minitemsize = 8
+tests.append(UnsignedLongLongTest)
+
 class FPTest(NumberTest):
     example = [-42.0, 0, 42, 1e5, -1e10]
     smallerexample = [-42.0, 0, 42, 1e5, -2e10]
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -1287,6 +1287,9 @@
 Extension Modules
 -----------------
 
+- Issue #1172711: Add 'long long' support to the array module.
+  Initial patch by Oren Tirosh and Hirokazu Yamamoto.
+
 - Issue #12483: ctypes: Fix a crash when the destruction of a callback
   object triggers the garbage collector.
 
diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c
--- a/Modules/arraymodule.c
+++ b/Modules/arraymodule.c
@@ -356,6 +356,59 @@
     return 0;
 }
 
+#ifdef HAVE_LONG_LONG
+
+static PyObject *
+q_getitem(arrayobject *ap, Py_ssize_t i)
+{
+    return PyLong_FromLongLong(((PY_LONG_LONG *)ap->ob_item)[i]);
+}
+
+static int
+q_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
+{
+    PY_LONG_LONG x;
+    if (!PyArg_Parse(v, "L;array item must be integer", &x))
+        return -1;
+    if (i >= 0)
+        ((PY_LONG_LONG *)ap->ob_item)[i] = x;
+    return 0;
+}
+
+static PyObject *
+QQ_getitem(arrayobject *ap, Py_ssize_t i)
+{
+    return PyLong_FromUnsignedLongLong(
+        ((unsigned PY_LONG_LONG *)ap->ob_item)[i]);
+}
+
+static int
+QQ_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
+{
+    unsigned PY_LONG_LONG x;
+    if (PyLong_Check(v)) {
+        x = PyLong_AsUnsignedLongLong(v);
+        if (x == (unsigned PY_LONG_LONG) -1 && PyErr_Occurred())
+            return -1;
+    }
+    else {
+        PY_LONG_LONG y;
+        if (!PyArg_Parse(v, "L;array item must be integer", &y))
+            return -1;
+        if (y < 0) {
+            PyErr_SetString(PyExc_OverflowError,
+                "unsigned long long is less than minimum");
+            return -1;
+        }
+        x = (unsigned PY_LONG_LONG)y;
+    }
+
+    if (i >= 0)
+        ((unsigned PY_LONG_LONG *)ap->ob_item)[i] = x;
+    return 0;
+}
+#endif
+
 static PyObject *
 f_getitem(arrayobject *ap, Py_ssize_t i)
 {
@@ -406,6 +459,10 @@
     {'I', sizeof(int), II_getitem, II_setitem, "I", 1, 0},
     {'l', sizeof(long), l_getitem, l_setitem, "l", 1, 1},
     {'L', sizeof(long), LL_getitem, LL_setitem, "L", 1, 0},
+#ifdef HAVE_LONG_LONG
+    {'q', sizeof(PY_LONG_LONG), q_getitem, q_setitem, "q", 1, 1},
+    {'Q', sizeof(PY_LONG_LONG), QQ_getitem, QQ_setitem, "Q", 1, 0},
+#endif
     {'f', sizeof(float), f_getitem, f_setitem, "f", 0, 0},
     {'d', sizeof(double), d_getitem, d_setitem, "d", 0, 0},
     {'\0', 0, 0, 0, 0, 0, 0} /* Sentinel */
@@ -1655,6 +1712,16 @@
         intsize = sizeof(long);
         is_signed = 0;
         break;
+#if HAVE_LONG_LONG
+    case 'q':
+        intsize = sizeof(PY_LONG_LONG);
+        is_signed = 1;
+        break;
+    case 'Q':
+        intsize = sizeof(PY_LONG_LONG);
+        is_signed = 0;
+        break;
+#endif 
     default:
         return UNKNOWN_FORMAT;
     }
@@ -2501,7 +2568,11 @@
         }
     }
     PyErr_SetString(PyExc_ValueError,
+#ifdef HAVE_LONG_LONG
+        "bad typecode (must be b, B, u, h, H, i, I, l, L, q, Q, f or d)");
+#else
         "bad typecode (must be b, B, u, h, H, i, I, l, L, f or d)");
+#endif
     return NULL;
 }
 
@@ -2524,12 +2595,18 @@
     'I'         unsigned integer   2 \n\
     'l'         signed integer     4 \n\
     'L'         unsigned integer   4 \n\
+    'q'         signed integer     8 (see note) \n\
+    'Q'         unsigned integer   8 (see note) \n\
     'f'         floating point     4 \n\
     'd'         floating point     8 \n\
 \n\
-NOTE: The 'u' typecode corresponds to Python's unicode character. On \n\
+NOTE: The 'u' type code corresponds to Python's unicode character. On \n\
 narrow builds this is 2-bytes on wide builds this is 4-bytes.\n\
 \n\
+NOTE: The 'q' and 'Q' type codes are only available if the platform \n\
+C compiler used to build Python supports 'long long', or, on Windows, \n\
+'__int64'.\n\
+\n\
 The constructor is:\n\
 \n\
 array(typecode [, initializer]) -- create a new array\n\

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list