]> granicus.if.org Git - python/commitdiff
Now in find, rfind, index, and rindex, you can use None as defaults,
authorFacundo Batista <facundobatista@gmail.com>
Fri, 16 Nov 2007 18:04:14 +0000 (18:04 +0000)
committerFacundo Batista <facundobatista@gmail.com>
Fri, 16 Nov 2007 18:04:14 +0000 (18:04 +0000)
as usual with slicing (both with str and unicode strings).  This
fixes issue 1259.

For str only the stringobject.c file was modified.  But for unicode,
I needed to repeat in the four functions a lot of code, so created
a new function that does part of the job for them (and placed it in
find.h, following a suggestion of Barry).

Also added tests for this behaviour.

Lib/test/string_tests.py
Objects/stringlib/find.h
Objects/stringobject.c
Objects/unicodeobject.c

index d0f8c03c7ef41a412da1c7098ebc5183d21421c8..cefdcacfec6abc06312e30bc24ba1681f29d7ed0 100644 (file)
@@ -159,6 +159,13 @@ class CommonTest(unittest.TestCase):
         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 @@ class CommonTest(unittest.TestCase):
         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 @@ class CommonTest(unittest.TestCase):
         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 @@ class CommonTest(unittest.TestCase):
         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)
 
index 4cdbb096da365465a60b86728699bd81b2ac2b97..38f13ab66f167a153a2e63a46288ab2cf245b28b 100644 (file)
@@ -103,6 +103,53 @@ stringlib_contains_obj(PyObject* str, PyObject* sub)
 
 #endif /* STRINGLIB_STR */
 
+/*
+This function is a helper for the "find" family (find, rfind, index,
+rindex) of unicodeobject.c file, because they all have the same 
+behaviour for the arguments.
+
+It does not touch the variables received until it knows everything 
+is ok.
+
+Note that we receive a pointer to the pointer of the substring object,
+so when we create that object in this function we don't DECREF it,
+because it continues living in the caller functions (those functions, 
+after finishing using the substring, must DECREF it).
+*/
+
+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;
+}
+
+
 #endif /* STRINGLIB_FIND_H */
 
 /*
index ce24154becc8ba7d9ee654594d3a0f77db373684..a0e2837a9478fb2224a94105f053896d39d7d4ff 100644 (file)
@@ -1880,10 +1880,21 @@ string_find_internal(PyStringObject *self, PyObject *args, int dir)
        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);
index 1f6f738c6df8201225d95026ecef7964d126c2cc..06c8fc3b5a86a1353979c70d5c295dc3c9c7cd0f 100644 (file)
@@ -6040,16 +6040,12 @@ static PyObject *
 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 +6106,11 @@ unicode_index(PyUnicodeObject *self, PyObject *args)
 {
     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 +6773,12 @@ static PyObject *
 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 +6800,12 @@ static PyObject *
 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),