[Python-checkins] cpython: Issue #14705: Add 'p' format character to PyArg_ParseTuple* for bool support.

larry.hastings python-checkins at python.org
Sun May 6 01:55:38 CEST 2012


http://hg.python.org/cpython/rev/bc6d28e726d8
changeset:   76776:bc6d28e726d8
user:        Larry Hastings <larry at hastings.org>
date:        Sat May 05 16:54:29 2012 -0700
summary:
  Issue #14705: Add 'p' format character to PyArg_ParseTuple* for bool support.

files:
  Doc/c-api/arg.rst         |   9 +++++++
  Lib/test/test_getargs2.py |  31 +++++++++++++++++++++++++++
  Modules/_testcapimodule.c |  10 ++++++++
  Python/getargs.c          |  12 ++++++++++
  4 files changed, 62 insertions(+), 0 deletions(-)


diff --git a/Doc/c-api/arg.rst b/Doc/c-api/arg.rst
--- a/Doc/c-api/arg.rst
+++ b/Doc/c-api/arg.rst
@@ -317,6 +317,15 @@
    .. versionchanged:: 3.1
       ``Py_CLEANUP_SUPPORTED`` was added.
 
+``p`` (:class:`bool`) [int]
+   Tests the value passed in for truth (a boolean **p**\redicate) and converts
+   the result to its equivalent C true/false integer value.
+   Sets the int to 1 if the expression was true and 0 if it was false.
+   This accepts any valid Python value.  See :ref:`truth` for more
+   information about how Python tests values for truth.
+
+   .. versionchanged:: 3.3
+
 ``(items)`` (:class:`tuple`) [*matching-items*]
    The object must be a Python sequence whose length is the number of format units
    in *items*.  The C arguments must correspond to the individual format units in
diff --git a/Lib/test/test_getargs2.py b/Lib/test/test_getargs2.py
--- a/Lib/test/test_getargs2.py
+++ b/Lib/test/test_getargs2.py
@@ -214,6 +214,36 @@
 
         self.assertEqual(VERY_LARGE & ULLONG_MAX, getargs_K(VERY_LARGE))
 
+class Paradox:
+    "This statement is false."
+    def __bool__(self):
+        raise NotImplementedError
+
+class Boolean_TestCase(unittest.TestCase):
+    def test_p(self):
+        from _testcapi import getargs_p
+        self.assertEqual(0, getargs_p(False))
+        self.assertEqual(0, getargs_p(None))
+        self.assertEqual(0, getargs_p(0))
+        self.assertEqual(0, getargs_p(0.0))
+        self.assertEqual(0, getargs_p(0j))
+        self.assertEqual(0, getargs_p(''))
+        self.assertEqual(0, getargs_p(()))
+        self.assertEqual(0, getargs_p([]))
+        self.assertEqual(0, getargs_p({}))
+
+        self.assertEqual(1, getargs_p(True))
+        self.assertEqual(1, getargs_p(1))
+        self.assertEqual(1, getargs_p(1.0))
+        self.assertEqual(1, getargs_p(1j))
+        self.assertEqual(1, getargs_p('x'))
+        self.assertEqual(1, getargs_p((1,)))
+        self.assertEqual(1, getargs_p([1]))
+        self.assertEqual(1, getargs_p({1:2}))
+        self.assertEqual(1, getargs_p(unittest.TestCase))
+
+        self.assertRaises(NotImplementedError, getargs_p, Paradox())
+
 
 class Tuple_TestCase(unittest.TestCase):
     def test_tuple(self):
@@ -510,6 +540,7 @@
     tests = [
         Signed_TestCase,
         Unsigned_TestCase,
+        Boolean_TestCase,
         Tuple_TestCase,
         Keywords_TestCase,
         KeywordOnly_TestCase,
diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c
--- a/Modules/_testcapimodule.c
+++ b/Modules/_testcapimodule.c
@@ -916,6 +916,15 @@
     return PyLong_FromSsize_t(value);
 }
 
+static PyObject *
+getargs_p(PyObject *self, PyObject *args)
+{
+    int value;
+    if (!PyArg_ParseTuple(args, "p", &value))
+        return NULL;
+    return PyLong_FromLong(value);
+}
+
 #ifdef HAVE_LONG_LONG
 static PyObject *
 getargs_L(PyObject *self, PyObject *args)
@@ -2439,6 +2448,7 @@
     {"getargs_i",               getargs_i,                       METH_VARARGS},
     {"getargs_l",               getargs_l,                       METH_VARARGS},
     {"getargs_n",               getargs_n,                       METH_VARARGS},
+    {"getargs_p",               getargs_p,                       METH_VARARGS},
 #ifdef HAVE_LONG_LONG
     {"getargs_L",               getargs_L,                       METH_VARARGS},
     {"getargs_K",               getargs_K,                       METH_VARARGS},
diff --git a/Python/getargs.c b/Python/getargs.c
--- a/Python/getargs.c
+++ b/Python/getargs.c
@@ -814,6 +814,18 @@
         break;
     }
 
+    case 'p': {/* boolean *p*redicate */
+        int *p = va_arg(*p_va, int *);
+        int val = PyObject_IsTrue(arg);
+        if (val > 0)
+            *p = 1;
+        else if (val == 0)
+            *p = 0;
+        else
+            RETURN_ERR_OCCURRED;
+        break;
+    }
+
     /* XXX WAAAAH!  's', 'y', 'z', 'u', 'Z', 'e', 'w' codes all
        need to be cleaned up! */
 

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


More information about the Python-checkins mailing list