Index: Objects/unicodeobject.c =================================================================== --- Objects/unicodeobject.c (revisión: 58710) +++ Objects/unicodeobject.c (copia de trabajo) @@ -6027,6 +6027,46 @@ return (PyObject*) u; } +/* +This function is a helper for the "find" family (find, rfind, index, +rindex), because they all have the same behaviour for the arguments. + +It does not touch the variables received until it knows everything +is ok. +*/ + +int +_ParseTupleFinds (PyObject *args, PyObject **substring, + Py_ssize_t *start, Py_ssize_t *end) { + PyObject *tmp_substring; + Py_ssize_t tmp_start = 0; + Py_ssize_t tmp_end = PY_SSIZE_T_MAX; + PyObject *obj_start=Py_None, *obj_end=Py_None; + + if (!PyArg_ParseTuple(args, "O|OO:find", &tmp_substring, + &obj_start, &obj_end)) + return 0; + + /* To support None in "start" and "end" arguments, meaning + the same as if they were not passed. + */ + if (obj_start != Py_None) + if (!_PyEval_SliceIndex(obj_start, &tmp_start)) + return 0; + if (obj_end != Py_None) + if (!_PyEval_SliceIndex(obj_end, &tmp_end)) + return 0; + + tmp_substring = PyUnicode_FromObject(tmp_substring); + if (!tmp_substring) + return 0; + + *start = tmp_start; + *end = tmp_end; + *substring = tmp_substring; + return 1; +} + PyDoc_STRVAR(find__doc__, "S.find(sub [,start [,end]]) -> int\n\ \n\ @@ -6040,16 +6080,12 @@ unicode_find(PyUnicodeObject *self, PyObject *args) { PyObject *substring; - Py_ssize_t start = 0; - Py_ssize_t end = PY_SSIZE_T_MAX; + Py_ssize_t start; + Py_ssize_t end; Py_ssize_t result; - if (!PyArg_ParseTuple(args, "O|O&O&:find", &substring, - _PyEval_SliceIndex, &start, _PyEval_SliceIndex, &end)) + if (!_ParseTupleFinds(args, &substring, &start, &end)) return NULL; - substring = PyUnicode_FromObject(substring); - if (!substring) - return NULL; result = stringlib_find_slice( PyUnicode_AS_UNICODE(self), PyUnicode_GET_SIZE(self), @@ -6110,15 +6146,11 @@ { Py_ssize_t result; PyObject *substring; - Py_ssize_t start = 0; - Py_ssize_t end = PY_SSIZE_T_MAX; + Py_ssize_t start; + Py_ssize_t end; - if (!PyArg_ParseTuple(args, "O|O&O&:index", &substring, - _PyEval_SliceIndex, &start, _PyEval_SliceIndex, &end)) + if (!_ParseTupleFinds(args, &substring, &start, &end)) return NULL; - substring = PyUnicode_FromObject(substring); - if (!substring) - return NULL; result = stringlib_find_slice( PyUnicode_AS_UNICODE(self), PyUnicode_GET_SIZE(self), @@ -6781,16 +6813,12 @@ unicode_rfind(PyUnicodeObject *self, PyObject *args) { PyObject *substring; - Py_ssize_t start = 0; - Py_ssize_t end = PY_SSIZE_T_MAX; + Py_ssize_t start; + Py_ssize_t end; Py_ssize_t result; - if (!PyArg_ParseTuple(args, "O|O&O&:rfind", &substring, - _PyEval_SliceIndex, &start, _PyEval_SliceIndex, &end)) - return NULL; - substring = PyUnicode_FromObject(substring); - if (!substring) - return NULL; + if (!_ParseTupleFinds(args, &substring, &start, &end)) + return NULL; result = stringlib_rfind_slice( PyUnicode_AS_UNICODE(self), PyUnicode_GET_SIZE(self), @@ -6812,16 +6840,12 @@ unicode_rindex(PyUnicodeObject *self, PyObject *args) { PyObject *substring; - Py_ssize_t start = 0; - Py_ssize_t end = PY_SSIZE_T_MAX; + Py_ssize_t start; + Py_ssize_t end; Py_ssize_t result; - if (!PyArg_ParseTuple(args, "O|O&O&:rindex", &substring, - _PyEval_SliceIndex, &start, _PyEval_SliceIndex, &end)) - return NULL; - substring = PyUnicode_FromObject(substring); - if (!substring) - return NULL; + if (!_ParseTupleFinds(args, &substring, &start, &end)) + return NULL; result = stringlib_rfind_slice( PyUnicode_AS_UNICODE(self), PyUnicode_GET_SIZE(self), Index: Objects/stringobject.c =================================================================== --- Objects/stringobject.c (revisión: 58710) +++ Objects/stringobject.c (copia de trabajo) @@ -1879,16 +1879,28 @@ const char *sub; Py_ssize_t sub_len; Py_ssize_t start=0, end=PY_SSIZE_T_MAX; + PyObject *obj_start=Py_None, *obj_end=Py_None; - if (!PyArg_ParseTuple(args, "O|O&O&:find/rfind/index/rindex", &subobj, - _PyEval_SliceIndex, &start, _PyEval_SliceIndex, &end)) + if (!PyArg_ParseTuple(args, "O|OO:find/rfind/index/rindex", &subobj, + &obj_start, &obj_end)) return -2; + /* To support None in "start" and "end" arguments, meaning + the same as if they were not passed. + */ + if (obj_start != Py_None) + if (!_PyEval_SliceIndex(obj_start, &start)) + return -2; + if (obj_end != Py_None) + if (!_PyEval_SliceIndex(obj_end, &end)) + return -2; + if (PyString_Check(subobj)) { sub = PyString_AS_STRING(subobj); sub_len = PyString_GET_SIZE(subobj); } + #ifdef Py_USING_UNICODE - else if (PyUnicode_Check(subobj)) + else if (PyUnicode_Check(subobj)) return PyUnicode_Find( (PyObject *)self, subobj, start, end, dir); #endif Index: Lib/test/string_tests.py =================================================================== --- Lib/test/string_tests.py (revisión: 58710) +++ Lib/test/string_tests.py (copia de trabajo) @@ -159,6 +159,13 @@ self.checkequal(3, 'abc', 'find', '', 3) self.checkequal(-1, 'abc', 'find', '', 4) + # to check the ability to pass None as defaults + self.checkequal( 2, 'rrarrrrrrrrra', 'find', 'a') + self.checkequal(12, 'rrarrrrrrrrra', 'find', 'a', 4) + self.checkequal(-1, 'rrarrrrrrrrra', 'find', 'a', 4, 6) + self.checkequal(12, 'rrarrrrrrrrra', 'find', 'a', 4, None) + self.checkequal( 2, 'rrarrrrrrrrra', 'find', 'a', None, 6) + self.checkraises(TypeError, 'hello', 'find') self.checkraises(TypeError, 'hello', 'find', 42) @@ -197,6 +204,13 @@ self.checkequal(3, 'abc', 'rfind', '', 3) self.checkequal(-1, 'abc', 'rfind', '', 4) + # to check the ability to pass None as defaults + self.checkequal(12, 'rrarrrrrrrrra', 'rfind', 'a') + self.checkequal(12, 'rrarrrrrrrrra', 'rfind', 'a', 4) + self.checkequal(-1, 'rrarrrrrrrrra', 'rfind', 'a', 4, 6) + self.checkequal(12, 'rrarrrrrrrrra', 'rfind', 'a', 4, None) + self.checkequal( 2, 'rrarrrrrrrrra', 'rfind', 'a', None, 6) + self.checkraises(TypeError, 'hello', 'rfind') self.checkraises(TypeError, 'hello', 'rfind', 42) @@ -211,6 +225,13 @@ self.checkraises(ValueError, 'abcdefghi', 'index', 'ghi', 8) self.checkraises(ValueError, 'abcdefghi', 'index', 'ghi', -1) + # to check the ability to pass None as defaults + self.checkequal( 2, 'rrarrrrrrrrra', 'index', 'a') + self.checkequal(12, 'rrarrrrrrrrra', 'index', 'a', 4) + self.checkraises(ValueError, 'rrarrrrrrrrra', 'index', 'a', 4, 6) + self.checkequal(12, 'rrarrrrrrrrra', 'index', 'a', 4, None) + self.checkequal( 2, 'rrarrrrrrrrra', 'index', 'a', None, 6) + self.checkraises(TypeError, 'hello', 'index') self.checkraises(TypeError, 'hello', 'index', 42) @@ -226,6 +247,13 @@ self.checkraises(ValueError, 'abcdefghi', 'rindex', 'ghi', 0, 8) self.checkraises(ValueError, 'abcdefghi', 'rindex', 'ghi', 0, -1) + # to check the ability to pass None as defaults + self.checkequal(12, 'rrarrrrrrrrra', 'rindex', 'a') + self.checkequal(12, 'rrarrrrrrrrra', 'rindex', 'a', 4) + self.checkraises(ValueError, 'rrarrrrrrrrra', 'rindex', 'a', 4, 6) + self.checkequal(12, 'rrarrrrrrrrra', 'rindex', 'a', 4, None) + self.checkequal( 2, 'rrarrrrrrrrra', 'rindex', 'a', None, 6) + self.checkraises(TypeError, 'hello', 'rindex') self.checkraises(TypeError, 'hello', 'rindex', 42)