Add none check for unicode slicing, remove duplicate code, add test for non-ascii...
authorzaur <aintellimath@gmail.com>
Tue, 19 Feb 2013 09:48:20 +0000 (12:48 +0300)
committerzaur <aintellimath@gmail.com>
Tue, 19 Feb 2013 09:48:20 +0000 (12:48 +0300)
Cython/Compiler/ExprNodes.py
tests/run/slice_charptr.pyx
tests/run/unicode_slicing.pyx

index 47968ce..b263380 100755 (executable)
@@ -3457,8 +3457,6 @@ class SliceIndexNode(ExprNode):
         base_type = self.base.type
         if base_type.is_string or base_type.is_cpp_string:
             self.type = bytes_type
-        elif base_type is unicode_type:
-            self.type = unicode_type
         elif base_type.is_ptr:
             self.type = base_type
         elif base_type.is_array:
@@ -3488,6 +3486,15 @@ class SliceIndexNode(ExprNode):
             error(self.pos,
                   "Slicing is not currently supported for '%s'." % self.type)
             return
+
+        maybe_check = self.base.as_none_safe_node("'NoneType' object is not slicable")
+        if maybe_check.is_nonecheck:
+            maybe_check.generate_result_code(code)
+            
+        base_result = self.base.result()
+        result = self.result()
+        start_code = self.start_code()
+        stop_code = self.stop_code()
         if self.base.type.is_string:
             base_result = self.base.result()
             if self.base.type != PyrexTypes.c_char_ptr_type:
@@ -3495,60 +3502,37 @@ class SliceIndexNode(ExprNode):
             if self.stop is None:
                 code.putln(
                     "%s = PyBytes_FromString(%s + %s); %s" % (
-                        self.result(),
+                        result,
                         base_result,
-                        self.start_code(),
-                        code.error_goto_if_null(self.result(), self.pos)))
+                        start_code,
+                        code.error_goto_if_null(result, self.pos)))
             else:
                 code.putln(
                     "%s = PyBytes_FromStringAndSize(%s + %s, %s - %s); %s" % (
                         self.result(),
                         base_result,
-                        self.start_code(),
-                        self.stop_code(),
-                        self.start_code(),
-                        code.error_goto_if_null(self.result(), self.pos)))
+                        start_code,
+                        stop_code,
+                        start_code,
+                        code.error_goto_if_null(result, self.pos)))
         elif self.base.type is unicode_type:
-            base_result = self.base.result()
             code.globalstate.use_utility_code( 
                           UtilityCode.load_cached("PyUnicode_Substring", "StringTools.c")) 
-            if self.start is None:
-                if self.stop is None:
-                    code.putln(
-                        "%s = __Pyx_PyUnicode_Substring(%s, 0, PY_SSIZE_T_MAX); %s" % (
-                            self.result(),
-                            base_result,
-                            code.error_goto_if_null(self.result(), self.pos)))
-                else:
-                    code.putln(
-                        "%s = __Pyx_PyUnicode_Substring(%s, 0, %s); %s" % (
-                            self.result(),
-                            base_result,
-                            self.stop_code(),
-                            code.error_goto_if_null(self.result(), self.pos)))
-            elif self.stop is None:
-                code.putln(
-                    "%s = __Pyx_PyUnicode_Substring(%s, %s, PY_SSIZE_T_MAX); %s" % (
-                        self.result(),
-                        base_result,
-                        self.start_code(),
-                        code.error_goto_if_null(self.result(), self.pos)))
-            else:
-                code.putln(
-                    "%s = __Pyx_PyUnicode_Substring(%s, %s, %s); %s" % (
-                        self.result(),
-                        base_result,
-                        self.start_code(),
-                        self.stop_code(),
-                        code.error_goto_if_null(self.result(), self.pos)))
+            code.putln(
+                "%s = __Pyx_PyUnicode_Substring(%s, %s, %s); %s" % (
+                    result,
+                    base_result,
+                    start_code,
+                    stop_code,
+                    code.error_goto_if_null(result, self.pos)))
         else:
             code.putln(
                 "%s = __Pyx_PySequence_GetSlice(%s, %s, %s); %s" % (
-                    self.result(),
+                    result,
                     self.base.py_result(),
-                    self.start_code(),
-                    self.stop_code(),
-                    code.error_goto_if_null(self.result(), self.pos)))
+                    start_code,
+                    stop_code,
+                    code.error_goto_if_null(result, self.pos)))
         code.put_gotref(self.py_result())
 
     def generate_assignment_code(self, rhs, code):
@@ -4993,10 +4977,8 @@ class AttributeNode(ExprNode):
 
     def generate_result_code(self, code):
         if self.is_py_attr:
-            code.globalstate.use_utility_code(
-                UtilityCode.load_cached("PyObjectGetAttrStr", "ObjectHandling.c"))
             code.putln(
-                '%s = __Pyx_PyObject_GetAttrStr(%s, %s); %s' % (
+                '%s = PyObject_GetAttr(%s, %s); %s' % (
                     self.result(),
                     self.obj.py_result(),
                     code.intern_identifier(self.attribute),
@@ -9804,7 +9786,9 @@ class NoneCheckNode(CoercionNode):
         code.putln(
             "if (unlikely(%s == Py_None)) {" % self.condition())
 
-        if self.in_nogil_context:
+        in_nogil_context = getattr(self, "in_nogil_context", False)
+            
+        if in_nogil_context:
             code.put_ensure_gil()
 
         escape = StringEncoding.escape_byte_string
@@ -9820,7 +9804,7 @@ class NoneCheckNode(CoercionNode):
                 self.exception_type_cname,
                 escape(self.exception_message.encode('UTF-8'))))
 
-        if self.in_nogil_context:
+        if in_nogil_context:
             code.put_release_ensured_gil()
 
         code.putln(code.error_goto(self.pos))
@@ -10264,13 +10248,33 @@ class DocstringRefNode(ExprNode):
         code.put_gotref(self.result())
 
 
+
 #------------------------------------------------------------------------------------
 #
 #  Runtime support code
 #
 #------------------------------------------------------------------------------------
 
-get_name_interned_utility_code = UtilityCode.load("GetGlobalName", "ObjectHandling.c")
+get_name_interned_utility_code = UtilityCode(
+proto = """
+static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/
+""",
+impl = """
+static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name) {
+    PyObject *result;
+    result = PyObject_GetAttr(dict, name);
+    if (!result) {
+        if (dict != %(BUILTINS)s) {
+            PyErr_Clear();
+            result = PyObject_GetAttr(%(BUILTINS)s, name);
+        }
+        if (!result) {
+            PyErr_SetObject(PyExc_NameError, name);
+        }
+    }
+    return result;
+}
+""" % {'BUILTINS' : Naming.builtins_cname})
 
 #------------------------------------------------------------------------------------
 
@@ -10438,6 +10442,3 @@ proto="""
 #define UNARY_NEG_WOULD_OVERFLOW(x)    \
         (((x) < 0) & ((unsigned long)(x) == 0-(unsigned long)(x)))
 """)
-
-
-pyunicode_substring = UtilityCode.load_cached("PyUnicode_Substring", "StringTools.c")
index 6693c1f..301d22c 100644 (file)
@@ -1,8 +1,8 @@
 __doc__ = u"""
     >>> do_slice(b'abcdef', 2, 3)
-    (b'c', b'cdef', b'ab', b'abcdef')
+    (b'c', b'cdef', b'ab', b'abcdef', b'cdef', b'ab', b'abcdef')
     >>> do_slice(b'abcdef', 0, 5)
-    (b'abcde', b'abcdef', b'', b'abcdef')
+    (b'abcde', b'abcdef', b'', b'abcdef', b'abcdef', b'', b'abcdef')
 """
 
 import sys
@@ -12,5 +12,5 @@ if sys.version_info[0] < 3:
 
 def do_slice(s, int i, int j):
     cdef char* ss = s
-    return ss[i:j], ss[i:], ss[:i], ss[:]
+    return ss[i:j], ss[i:], ss[:i], ss[:], ss[i:None], ss[None:i], ss[None:None]
 
index 9652407..2ef2b1a 100644 (file)
@@ -1,9 +1,19 @@
-# coding=utf-8
+# coding: utf-8
+
 __doc__ = u"""
     >>> do_slice(u'abcdef', 2, 3)
-    (u'c', u'cdef', u'ab', u'abcdef')
+    (u'c', u'cdef', u'ab', u'abcdef', u'cdef', u'ab', u'abcdef')
     >>> do_slice(u'abcdef', 0, 5)
-    (u'abcde', u'abcdef', u'', u'abcdef')
+    (u'abcde', u'abcdef', u'', u'abcdef', u'abcdef', u'', u'abcdef')
+    >>> do_slice(u'aАbБcСdДeЕfФ', 2, 8)
+    (u'bБcСdД', u'bБcСdДeЕfФ', u'aА', u'aАbБcСdДeЕfФ', u'bБcСdДeЕfФ', u'aА', u'aАbБcСdДeЕfФ')
+    >>> do_slice(u'aАbБcСdДeЕfФ', 2, 8)
+    (u'bБcСdД', u'bБcСdДeЕfФ', u'aА', u'aАbБcСdДeЕfФ', u'bБcСdДeЕfФ', u'aА', u'aАbБcСdДeЕfФ')
+    >>> do_slice(u'АБСДЕФ', 2, 4)
+    (u'СД', u'СДЕФ', u'АБ', u'АБСДЕФ', u'СДЕФ', u'АБ', u'АБСДЕФ')
+    >>> do_slice(None, 2, 4)
+    Traceback (most recent call last):    
+    TypeError: 'NoneType' object is not slicable
 """
 
 import sys
@@ -12,5 +22,5 @@ if sys.version_info[0] >= 3:
     __doc__ = __doc__.replace(u"(u'", u"('").replace(u" u'", u" '")
 
 def do_slice(unicode s, int i, int j):
-    return s[i:j], s[i:], s[:i], s[:]
+    return s[i:j], s[i:], s[:i], s[:], s[i:None], s[None:i], s[None:None]