diff -r 9f8b5053e30d Lib/test/test_bool.py --- a/Lib/test/test_bool.py Sun Nov 01 17:14:27 2015 +0200 +++ b/Lib/test/test_bool.py Sun Nov 01 18:40:37 2015 -0500 @@ -314,6 +314,16 @@ return -1 self.assertRaises(ValueError, bool, Eggs()) + def test_from_config_str(self): + self.assertRaises(TypeError, bool.from_config_str, 42) + self.assertRaises(ValueError, bool.from_config_str, '42') + trues = ['true', 'yes', 'on', '1'] + falses = ['false', 'no', 'off', '0', ''] + for expect, check in [(True, trues), (False, falses)]: + for val in check: + self.assertEqual(expect, bool.from_config_str(val)) + self.assertEqual(expect, bool.from_config_str(val.upper())) + def test_sane_len(self): # this test just tests our assumptions about __len__ # this will start failing if __len__ changes assertions diff -r 9f8b5053e30d Objects/boolobject.c --- a/Objects/boolobject.c Sun Nov 01 17:14:27 2015 +0200 +++ b/Objects/boolobject.c Sun Nov 01 18:40:37 2015 -0500 @@ -3,12 +3,37 @@ #include "Python.h" #include "longintrepr.h" +static const char *config_strs_true[] = {"true", "yes", "on", "1"}; +static const char *config_strs_false[] = {"false", "no", "off", "0", ""}; + /* We define bool_repr to return "False" or "True" */ static PyObject *false_str = NULL; static PyObject *true_str = NULL; static PyObject * +bool_from_config_str(PyTypeObject *type, PyObject *input) +{ + if (!PyObject_TypeCheck(input, &PyUnicode_Type)) { + PyErr_SetString(PyExc_TypeError, "input must be string"); + return NULL; + } + + const char *str = PyUnicode_AsUTF8(input); + + for (int i = 0; i < 4; i++) + if (!strcasecmp(str, config_strs_true[i])) + return Py_True; + + for (int i = 0; i < 5; i++) + if (!strcasecmp(str, config_strs_false[i])) + return Py_False; + + PyErr_SetString(PyExc_ValueError, "invalid config string"); + return NULL; +} + +static PyObject * bool_repr(PyObject *self) { PyObject *s; @@ -89,6 +114,22 @@ The builtins True and False are the only two instances of the class bool.\n\ The class bool is a subclass of the class int, and cannot be subclassed."); +PyDoc_STRVAR(bool_from_config_str__doc__, +"from_config_str(s) -> bool\n\ +\n\ +Converts the given string s to a bool.\n\ +Returns True if s is 'true', 'yes', 'on', or '1'.\n\ +Returns False if s is 'false', 'no', 'off', '0', or ''.\n\ +Throws ValueError if s is any other string.\n\ +Throws TypeError if s is not a string.\n\ +Comparisons are case-insensitive."); + +static PyMethodDef bool_methods[] = { + {"from_config_str", (PyCFunction)bool_from_config_str, METH_CLASS | METH_O, + bool_from_config_str__doc__}, + {NULL, NULL} /* sentinel */ +}; + /* Arithmetic methods -- only so we can override &, |, ^. */ static PyNumberMethods bool_as_number = { @@ -158,7 +199,7 @@ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ - 0, /* tp_methods */ + bool_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ &PyLong_Type, /* tp_base */ diff -r 9f8b5053e30d README --- a/README Sun Nov 01 17:14:27 2015 +0200 +++ b/README Sun Nov 01 18:40:37 2015 -0500 @@ -187,7 +187,7 @@ ------------------------- If you have a proposal to change Python, you may want to send an email to the -comp.lang.python or python-ideas mailing lists for inital feedback. A Python +comp.lang.python or python-ideas mailing lists for initial feedback. A Python Enhancement Proposal (PEP) may be submitted if your idea gains ground. All current PEPs, as well as guidelines for submitting a new PEP, are listed at http://www.python.org/dev/peps/.