diff -r 3884a7e3df1c Doc/library/re.rst --- a/Doc/library/re.rst Sun Oct 16 19:14:23 2016 +0200 +++ b/Doc/library/re.rst Sun Oct 16 23:26:27 2016 +0300 @@ -1064,11 +1064,17 @@ Match objects support the following meth Return a dictionary containing all the *named* subgroups of the match, keyed by the subgroup name. The *default* argument is used for groups that did not - participate in the match; it defaults to ``None``. For example: + participate in the match. For example: - >>> m = re.match(r"(?P\w+) (?P\w+)", "Malcolm Reynolds") - >>> m.groupdict() - {'first_name': 'Malcolm', 'last_name': 'Reynolds'} + >>> m = re.match(r"(?PMrs |Mr |Dr )?(?P<first_name>\w+) (?P<last_name>\w+)", "Malcolm Reynolds") + >>> m.groupdict(None) + {'title': None, 'first_name': 'Malcolm', 'last_name': 'Reynolds'} + + .. deprecated:: 3.7 + + If the *default* argument is not specified, the result is the same as + if call :meth:`~match.groupdict` with ``None``. This will be changed + in future releases of Python. .. method:: match.start([group]) diff -r 3884a7e3df1c Lib/test/test_re.py --- a/Lib/test/test_re.py Sun Oct 16 19:14:23 2016 +0200 +++ b/Lib/test/test_re.py Sun Oct 16 23:26:27 2016 +0300 @@ -578,9 +578,13 @@ class ReTests(unittest.TestCase): self.checkPatternError(r'(abc\1)', 'cannot refer to an open group', 4) def test_groupdict(self): - self.assertEqual(re.match('(?P<first>first) (?P<second>second)', - 'first second').groupdict(), - {'first':'first', 'second':'second'}) + m = re.match('(?P<first>first) ?(?P<second>second)? ?(?P<third>third)', + 'first third') + self.assertEqual(m.groupdict('N/A'), + {'first': 'first', 'second': 'N/A', 'third': 'third'}) + with self.assertWarns(FutureWarning): + self.assertEqual(m.groupdict(), + {'first': 'first', 'second': None, 'third': 'third'}) def test_expand(self): self.assertEqual(re.match("(?P<first>first) (?P<second>second)", diff -r 3884a7e3df1c Modules/_sre.c --- a/Modules/_sre.c Sun Oct 16 19:14:23 2016 +0200 +++ b/Modules/_sre.c Sun Oct 16 23:26:27 2016 +0300 @@ -2019,7 +2019,7 @@ match_getslice_by_index(MatchObject* sel if (self->string == Py_None || self->mark[index] < 0) { /* return default value if the string or group is undefined */ - Py_INCREF(def); + Py_XINCREF(def); return def; } @@ -2163,7 +2163,7 @@ static PyObject * /*[clinic input] _sre.SRE_Match.groupdict - default: object = None + default: object = NULL Is used for groups that did not participate in the match. Return a dictionary containing all the named subgroups of the match, keyed by the subgroup name. @@ -2171,7 +2171,7 @@ Return a dictionary containing all the n static PyObject * _sre_SRE_Match_groupdict_impl(MatchObject *self, PyObject *default_value) -/*[clinic end generated code: output=29917c9073e41757 input=0ded7960b23780aa]*/ +/*[clinic end generated code: output=29917c9073e41757 input=cba63577c6f64449]*/ { PyObject* result; PyObject* keys; @@ -2193,8 +2193,20 @@ static PyObject * if (!key) goto failed; value = match_getslice(self, key, default_value); - if (!value) - goto failed; + if (!value) { + if (PyErr_Occurred()) + goto failed; + if (PyErr_WarnEx(PyExc_FutureWarning, + "The result of groupdict() without argument " + "includes unmatched groups. This will be " + "changed in future. Use groupdict(None) to " + "silence the warning.", + 1) < 0) { + goto failed; + } + value = Py_None; + Py_INCREF(value); + } status = PyDict_SetItem(result, key, value); Py_DECREF(value); if (status < 0) diff -r 3884a7e3df1c Modules/clinic/_sre.c.h --- a/Modules/clinic/_sre.c.h Sun Oct 16 19:14:23 2016 +0200 +++ b/Modules/clinic/_sre.c.h Sun Oct 16 23:26:27 2016 +0300 @@ -540,7 +540,7 @@ static PyObject * PyObject *return_value = NULL; static const char * const _keywords[] = {"default", NULL}; static _PyArg_Parser _parser = {"|O:groupdict", _keywords, 0}; - PyObject *default_value = Py_None; + PyObject *default_value = NULL; if (!_PyArg_ParseStack(args, nargs, kwnames, &_parser, &default_value)) { @@ -728,4 +728,4 @@ static PyObject * { return _sre_SRE_Scanner_search_impl(self); } -/*[clinic end generated code: output=a4a246bca1963bc9 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=2dd1305659b6db7f input=a9049054013a1b77]*/