diff --git a/Cython/Compiler/ExprNodes.py b/Cython/Compiler/ExprNodes.py index 47968ce80cf750db70b8eb56fc4c51ae3efec87c..b263380068f110a0b0ef1bc3be735210c473f6a4 100755 --- a/Cython/Compiler/ExprNodes.py +++ b/Cython/Compiler/ExprNodes.py @@ -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") diff --git a/tests/run/slice_charptr.pyx b/tests/run/slice_charptr.pyx index 6693c1f04728d354dc6790922575e09dfe2c042f..301d22c0f6e6cf4c02b3dfa75fd0d7f4cdedd72d 100644 --- a/tests/run/slice_charptr.pyx +++ b/tests/run/slice_charptr.pyx @@ -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] diff --git a/tests/run/unicode_slicing.pyx b/tests/run/unicode_slicing.pyx index 9652407aef19e65764560251000acd091c744507..2ef2b1af2a7cb7403a6e6ff3f5655ac50463e6a2 100644 --- a/tests/run/unicode_slicing.pyx +++ b/tests/run/unicode_slicing.pyx @@ -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]