diff -r e1c2c575fc0e Doc/c-api/arg.rst --- a/Doc/c-api/arg.rst Sat May 05 09:44:08 2012 -0400 +++ b/Doc/c-api/arg.rst Sat May 05 11:06:30 2012 -0700 @@ -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 -r e1c2c575fc0e Lib/test/test_getargs2.py --- a/Lib/test/test_getargs2.py Sat May 05 09:44:08 2012 -0400 +++ b/Lib/test/test_getargs2.py Sat May 05 11:06:30 2012 -0700 @@ -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 -r e1c2c575fc0e Modules/_testcapimodule.c --- a/Modules/_testcapimodule.c Sat May 05 09:44:08 2012 -0400 +++ b/Modules/_testcapimodule.c Sat May 05 11:06:30 2012 -0700 @@ -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 -r e1c2c575fc0e Python/getargs.c --- a/Python/getargs.c Sat May 05 09:44:08 2012 -0400 +++ b/Python/getargs.c Sat May 05 11:06:30 2012 -0700 @@ -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! */