diff -r bba131e48852 Doc/c-api/arg.rst --- a/Doc/c-api/arg.rst Thu May 03 00:30:07 2012 -0700 +++ b/Doc/c-api/arg.rst Thu May 03 01:15:06 2012 -0700 @@ -317,6 +317,22 @@ .. 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 expression. See :ref:`truth` for more + information about how Python tests values for truth. + + .. versionchanged:: 3.3 + +``P`` (:class:`bool`) [int] + Convert a Python boolean constant into a C true/false integer value. + Sets the int to 1 if the value was ``True`` and 0 if it was ``False``\; + any other value will raise a :exc:`TypeError`. + + .. 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 bba131e48852 Lib/test/test_getargs2.py --- a/Lib/test/test_getargs2.py Thu May 03 00:30:07 2012 -0700 +++ b/Lib/test/test_getargs2.py Thu May 03 01:15:06 2012 -0700 @@ -215,6 +215,52 @@ self.assertEqual(VERY_LARGE & ULLONG_MAX, getargs_K(VERY_LARGE)) +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)) + + def test_P(self): + from _testcapi import getargs_P + self.assertEqual(0, getargs_P(False)) + self.assertRaises(TypeError, getargs_P, None) + self.assertRaises(TypeError, getargs_P, 0) + self.assertRaises(TypeError, getargs_P, 0.0) + self.assertRaises(TypeError, getargs_P, 0j) + self.assertRaises(TypeError, getargs_P, '') + self.assertRaises(TypeError, getargs_P, ()) + self.assertRaises(TypeError, getargs_P, []) + self.assertRaises(TypeError, getargs_P, {}) + + self.assertEqual(1, getargs_P(True)) + self.assertRaises(TypeError, getargs_P, 1) + self.assertRaises(TypeError, getargs_P, 1.0) + self.assertRaises(TypeError, getargs_P, 1j) + self.assertRaises(TypeError, getargs_P, 'x') + self.assertRaises(TypeError, getargs_P, (1,)) + self.assertRaises(TypeError, getargs_P, [1]) + self.assertRaises(TypeError, getargs_P, {1:2}) + self.assertRaises(TypeError, getargs_P, unittest.TestCase) + + class Tuple_TestCase(unittest.TestCase): def test_tuple(self): from _testcapi import getargs_tuple @@ -510,6 +556,7 @@ tests = [ Signed_TestCase, Unsigned_TestCase, + Boolean_TestCase, Tuple_TestCase, Keywords_TestCase, KeywordOnly_TestCase, diff -r bba131e48852 Modules/_testcapimodule.c --- a/Modules/_testcapimodule.c Thu May 03 00:30:07 2012 -0700 +++ b/Modules/_testcapimodule.c Thu May 03 01:15:06 2012 -0700 @@ -916,6 +916,24 @@ 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); +} + +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 +2457,8 @@ {"getargs_i", getargs_i, METH_VARARGS}, {"getargs_l", getargs_l, METH_VARARGS}, {"getargs_n", getargs_n, METH_VARARGS}, + {"getargs_p", getargs_p, 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 bba131e48852 Python/getargs.c --- a/Python/getargs.c Thu May 03 00:30:07 2012 -0700 +++ b/Python/getargs.c Thu May 03 01:15:06 2012 -0700 @@ -814,6 +814,27 @@ break; } + case 'p': {/* liberal boolean predicate */ + int *p = va_arg(*p_va, int *); + int val = PyObject_IsTrue(arg); + if (val == -1 || PyErr_Occurred()) + RETURN_ERR_OCCURRED; + else + *p = val; + break; + } + + case 'P': {/* strict type-enforced boolean predicate */ + int *p = va_arg(*p_va, int *); + if (arg == Py_True) + *p = 1; + else if (arg == Py_False) + *p = 0; + else + RETURN_ERR_OCCURRED; + break; + } + /* XXX WAAAAH! 's', 'y', 'z', 'u', 'Z', 'e', 'w' codes all need to be cleaned up! */