Commit c666fe52 authored by zaur's avatar zaur

Add none check for unicode slicing, remove duplicate code, add test for...

Add none check for unicode slicing, remove duplicate code, add test for non-ascii unicode strings and None
parent fa2620f9
...@@ -3457,8 +3457,6 @@ class SliceIndexNode(ExprNode): ...@@ -3457,8 +3457,6 @@ class SliceIndexNode(ExprNode):
base_type = self.base.type base_type = self.base.type
if base_type.is_string or base_type.is_cpp_string: if base_type.is_string or base_type.is_cpp_string:
self.type = bytes_type self.type = bytes_type
elif base_type is unicode_type:
self.type = unicode_type
elif base_type.is_ptr: elif base_type.is_ptr:
self.type = base_type self.type = base_type
elif base_type.is_array: elif base_type.is_array:
...@@ -3488,6 +3486,15 @@ class SliceIndexNode(ExprNode): ...@@ -3488,6 +3486,15 @@ class SliceIndexNode(ExprNode):
error(self.pos, error(self.pos,
"Slicing is not currently supported for '%s'." % self.type) "Slicing is not currently supported for '%s'." % self.type)
return 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: if self.base.type.is_string:
base_result = self.base.result() base_result = self.base.result()
if self.base.type != PyrexTypes.c_char_ptr_type: if self.base.type != PyrexTypes.c_char_ptr_type:
...@@ -3495,60 +3502,37 @@ class SliceIndexNode(ExprNode): ...@@ -3495,60 +3502,37 @@ class SliceIndexNode(ExprNode):
if self.stop is None: if self.stop is None:
code.putln( code.putln(
"%s = PyBytes_FromString(%s + %s); %s" % ( "%s = PyBytes_FromString(%s + %s); %s" % (
self.result(), result,
base_result, base_result,
self.start_code(), start_code,
code.error_goto_if_null(self.result(), self.pos))) code.error_goto_if_null(result, self.pos)))
else: else:
code.putln( code.putln(
"%s = PyBytes_FromStringAndSize(%s + %s, %s - %s); %s" % ( "%s = PyBytes_FromStringAndSize(%s + %s, %s - %s); %s" % (
self.result(), self.result(),
base_result, base_result,
self.start_code(), start_code,
self.stop_code(), stop_code,
self.start_code(), start_code,
code.error_goto_if_null(self.result(), self.pos))) code.error_goto_if_null(result, self.pos)))
elif self.base.type is unicode_type: elif self.base.type is unicode_type:
base_result = self.base.result()
code.globalstate.use_utility_code( code.globalstate.use_utility_code(
UtilityCode.load_cached("PyUnicode_Substring", "StringTools.c")) UtilityCode.load_cached("PyUnicode_Substring", "StringTools.c"))
if self.start is None: code.putln(
if self.stop is None: "%s = __Pyx_PyUnicode_Substring(%s, %s, %s); %s" % (
code.putln( result,
"%s = __Pyx_PyUnicode_Substring(%s, 0, PY_SSIZE_T_MAX); %s" % ( base_result,
self.result(), start_code,
base_result, stop_code,
code.error_goto_if_null(self.result(), self.pos))) code.error_goto_if_null(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)))
else: else:
code.putln( code.putln(
"%s = __Pyx_PySequence_GetSlice(%s, %s, %s); %s" % ( "%s = __Pyx_PySequence_GetSlice(%s, %s, %s); %s" % (
self.result(), result,
self.base.py_result(), self.base.py_result(),
self.start_code(), start_code,
self.stop_code(), stop_code,
code.error_goto_if_null(self.result(), self.pos))) code.error_goto_if_null(result, self.pos)))
code.put_gotref(self.py_result()) code.put_gotref(self.py_result())
def generate_assignment_code(self, rhs, code): def generate_assignment_code(self, rhs, code):
...@@ -4993,10 +4977,8 @@ class AttributeNode(ExprNode): ...@@ -4993,10 +4977,8 @@ class AttributeNode(ExprNode):
def generate_result_code(self, code): def generate_result_code(self, code):
if self.is_py_attr: if self.is_py_attr:
code.globalstate.use_utility_code(
UtilityCode.load_cached("PyObjectGetAttrStr", "ObjectHandling.c"))
code.putln( code.putln(
'%s = __Pyx_PyObject_GetAttrStr(%s, %s); %s' % ( '%s = PyObject_GetAttr(%s, %s); %s' % (
self.result(), self.result(),
self.obj.py_result(), self.obj.py_result(),
code.intern_identifier(self.attribute), code.intern_identifier(self.attribute),
...@@ -9804,7 +9786,9 @@ class NoneCheckNode(CoercionNode): ...@@ -9804,7 +9786,9 @@ class NoneCheckNode(CoercionNode):
code.putln( code.putln(
"if (unlikely(%s == Py_None)) {" % self.condition()) "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() code.put_ensure_gil()
escape = StringEncoding.escape_byte_string escape = StringEncoding.escape_byte_string
...@@ -9820,7 +9804,7 @@ class NoneCheckNode(CoercionNode): ...@@ -9820,7 +9804,7 @@ class NoneCheckNode(CoercionNode):
self.exception_type_cname, self.exception_type_cname,
escape(self.exception_message.encode('UTF-8')))) escape(self.exception_message.encode('UTF-8'))))
if self.in_nogil_context: if in_nogil_context:
code.put_release_ensured_gil() code.put_release_ensured_gil()
code.putln(code.error_goto(self.pos)) code.putln(code.error_goto(self.pos))
...@@ -10264,13 +10248,33 @@ class DocstringRefNode(ExprNode): ...@@ -10264,13 +10248,33 @@ class DocstringRefNode(ExprNode):
code.put_gotref(self.result()) code.put_gotref(self.result())
#------------------------------------------------------------------------------------ #------------------------------------------------------------------------------------
# #
# Runtime support code # 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=""" ...@@ -10438,6 +10442,3 @@ proto="""
#define UNARY_NEG_WOULD_OVERFLOW(x) \ #define UNARY_NEG_WOULD_OVERFLOW(x) \
(((x) < 0) & ((unsigned long)(x) == 0-(unsigned long)(x))) (((x) < 0) & ((unsigned long)(x) == 0-(unsigned long)(x)))
""") """)
pyunicode_substring = UtilityCode.load_cached("PyUnicode_Substring", "StringTools.c")
__doc__ = u""" __doc__ = u"""
>>> do_slice(b'abcdef', 2, 3) >>> 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) >>> 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 import sys
...@@ -12,5 +12,5 @@ if sys.version_info[0] < 3: ...@@ -12,5 +12,5 @@ if sys.version_info[0] < 3:
def do_slice(s, int i, int j): def do_slice(s, int i, int j):
cdef char* ss = s 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]
# coding=utf-8 # coding: utf-8
__doc__ = u""" __doc__ = u"""
>>> do_slice(u'abcdef', 2, 3) >>> 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) >>> 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 import sys
...@@ -12,5 +22,5 @@ if sys.version_info[0] >= 3: ...@@ -12,5 +22,5 @@ if sys.version_info[0] >= 3:
__doc__ = __doc__.replace(u"(u'", u"('").replace(u" u'", u" '") __doc__ = __doc__.replace(u"(u'", u"('").replace(u" u'", u" '")
def do_slice(unicode s, int i, int j): 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]
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment