diff -r bd6127a6354f Doc/library/grp.rst --- a/Doc/library/grp.rst Sat Jan 16 11:01:14 2016 +0000 +++ b/Doc/library/grp.rst Sun Jan 17 16:56:34 2016 +0200 @@ -42,6 +42,9 @@ It defines the following items: Return the group database entry for the given numeric group ID. :exc:`KeyError` is raised if the entry asked for cannot be found. + .. deprecated:: 3.6 + Since Python 3.6 the support of non-integer arguments like floats or + strings in :func:`getgrgid` is deprecated. .. function:: getgrnam(name) diff -r bd6127a6354f Lib/test/test_grp.py --- a/Lib/test/test_grp.py Sat Jan 16 11:01:14 2016 +0000 +++ b/Lib/test/test_grp.py Sun Jan 17 16:56:34 2016 +0200 @@ -92,5 +92,15 @@ class GroupDatabaseTestCase(unittest.Tes self.assertRaises(KeyError, grp.getgrgid, fakegid) + def test_noninteger_gid(self): + entries = grp.getgrall() + if not entries: + self.skipTest('no groups') + # Choose an existent gid. + gid = entries[0][2] + self.assertWarns(DeprecationWarning, grp.getgrgid, float(gid)) + self.assertWarns(DeprecationWarning, grp.getgrgid, str(gid)) + + if __name__ == "__main__": unittest.main() diff -r bd6127a6354f Modules/grpmodule.c --- a/Modules/grpmodule.c Sat Jan 16 11:01:14 2016 +0000 +++ b/Modules/grpmodule.c Sun Jan 17 16:56:34 2016 +0200 @@ -100,14 +100,23 @@ grp_getgrgid_impl(PyModuleDef *module, P gid_t gid; struct group *p; - py_int_id = PyNumber_Long(id); - if (!py_int_id) + if (!_Py_Gid_Converter(id, &gid)) { + if (!PyErr_ExceptionMatches(PyExc_TypeError)) return NULL; - if (!_Py_Gid_Converter(py_int_id, &gid)) { + PyErr_Clear(); + if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1, + "group id must be int, not %.200", + id->ob_type->tp_name) < 0) + return NULL; + py_int_id = PyNumber_Long(id); + if (!py_int_id) + return NULL; + if (!_Py_Gid_Converter(py_int_id, &gid)) { + Py_DECREF(py_int_id); + return NULL; + } Py_DECREF(py_int_id); - return NULL; } - Py_DECREF(py_int_id); if ((p = getgrgid(gid)) == NULL) { PyObject *gid_obj = _PyLong_FromGid(gid);