Commit 6f95c7e3 authored by Stefan Behnel's avatar Stefan Behnel

merged in latest cython-devel

parents 1a3d6371 f31aac14
......@@ -11,7 +11,8 @@ import Symtab
class AutoTestDictTransform(ScopeTrackingTransform):
# Handles autotestdict directive
blacklist = ['__cinit__', '__dealloc__', '__richcmp__', '__nonzero__',
blacklist = ['__cinit__', '__dealloc__', '__richcmp__',
'__nonzero__', '__bool__',
'__len__', '__contains__']
def visit_ModuleNode(self, node):
......
......@@ -329,8 +329,9 @@ class ExprNode(Node):
# time we get the result.
self.analyse_types(env)
bool = self.coerce_to_boolean(env)
temp_bool = bool.coerce_to_temp(env)
return temp_bool
if not bool.is_simple():
bool = bool.coerce_to_temp(env)
return bool
# --------------- Type Inference -----------------
......@@ -559,7 +560,10 @@ class ExprNode(Node):
if dst_type.is_pyobject:
if not src.type.is_pyobject:
src = CoerceToPyTypeNode(src, env)
if dst_type is bytes_type and src.type.is_int:
src = CoerceIntToBytesNode(src, env)
else:
src = CoerceToPyTypeNode(src, env)
if not src.type.subtype_of(dst_type):
if not isinstance(src, NoneNode):
src = PyTypeTestNode(src, dst_type, env)
......@@ -2023,6 +2027,7 @@ class IndexNode(ExprNode):
"Attempting to index non-array type '%s'" %
self.base.type)
self.type = PyrexTypes.error_type
gil_message = "Indexing Python object"
def nogil_check(self, env):
......@@ -4668,7 +4673,12 @@ class TypecastNode(ExprNode):
if from_py and not to_py and self.operand.is_ephemeral() and not self.type.is_numeric:
error(self.pos, "Casting temporary Python object to non-numeric non-Python type")
if to_py and not from_py:
if self.operand.type.can_coerce_to_pyobject(env):
if self.type is bytes_type and self.operand.type.is_int:
# FIXME: the type cast node isn't needed in this case
# and can be dropped once analyse_types() can return a
# different node
self.operand = CoerceIntToBytesNode(self.operand, env)
elif self.operand.type.can_coerce_to_pyobject(env):
self.result_ctype = py_object_type
self.operand = self.operand.coerce_to_pyobject(env)
else:
......@@ -5580,11 +5590,13 @@ class CmpNode(object):
func = compile_time_binary_operators[self.operator]
operand2_result = self.operand2.constant_result
result = func(operand1_result, operand2_result)
if result and self.cascade:
result = result and \
self.cascade.cascaded_compile_time_value(operand2_result)
self.constant_result = result
if self.cascade:
self.cascade.calculate_cascaded_constant_result(operand2_result)
if self.cascade.constant_result:
self.constant_result = result and self.cascade.constant_result
else:
self.constant_result = result
def cascaded_compile_time_value(self, operand1, denv):
func = get_compile_time_binop(self)
operand2 = self.operand2.compile_time_value(denv)
......@@ -5597,7 +5609,7 @@ class CmpNode(object):
cascade = self.cascade
if cascade:
# FIXME: I bet this must call cascaded_compile_time_value()
result = result and cascade.compile_time_value(operand2, denv)
result = result and cascade.cascaded_compile_time_value(operand2, denv)
return result
def is_cpp_comparison(self):
......@@ -5727,10 +5739,8 @@ class CmpNode(object):
def is_c_string_contains(self):
return self.operator in ('in', 'not_in') and \
((self.operand1.type in (PyrexTypes.c_char_type, PyrexTypes.c_uchar_type)
and self.operand2.type in (PyrexTypes.c_char_ptr_type,
PyrexTypes.c_uchar_ptr_type,
bytes_type)) or
((self.operand1.type.is_int
and (self.operand2.type.is_string or self.operand2.type is bytes_type)) or
(self.operand1.type is PyrexTypes.c_py_unicode_type
and self.operand2.type is unicode_type))
......@@ -5894,8 +5904,7 @@ class PrimaryCmpNode(ExprNode, CmpNode):
return ()
def calculate_constant_result(self):
self.constant_result = self.calculate_cascaded_constant_result(
self.operand1.constant_result)
self.calculate_cascaded_constant_result(self.operand1.constant_result)
def compile_time_value(self, denv):
operand1 = self.operand1.compile_time_value(denv)
......@@ -6073,6 +6082,10 @@ class CascadedCmpNode(Node, CmpNode):
def type_dependencies(self, env):
return ()
def has_constant_result(self):
return self.constant_result is not constant_value_not_set and \
self.constant_result is not not_a_constant
def analyse_types(self, env):
self.operand2.analyse_types(env)
if self.cascade:
......@@ -6294,7 +6307,7 @@ class CoerceToPyTypeNode(CoercionNode):
CoercionNode.__init__(self, arg)
if not arg.type.create_to_py_utility_code(env):
error(arg.pos,
"Cannot convert '%s' to Python object" % arg.type)
"Cannot convert '%s' to Python object" % arg.type)
if type is not py_object_type:
self.type = py_object_type
elif arg.type.is_string:
......@@ -6330,6 +6343,46 @@ class CoerceToPyTypeNode(CoercionNode):
code.put_gotref(self.py_result())
class CoerceIntToBytesNode(CoerceToPyTypeNode):
# This node is used to convert a C int type to a Python bytes
# object.
is_temp = 1
def __init__(self, arg, env):
arg = arg.coerce_to_simple(env)
CoercionNode.__init__(self, arg)
self.type = Builtin.bytes_type
def generate_result_code(self, code):
arg = self.arg
arg_result = arg.result()
if arg.type not in (PyrexTypes.c_char_type,
PyrexTypes.c_uchar_type,
PyrexTypes.c_schar_type):
if arg.type.signed:
code.putln("if ((%s < 0) || (%s > 255)) {" % (
arg_result, arg_result))
else:
code.putln("if (%s > 255) {" % arg_result)
code.putln('PyErr_Format(PyExc_OverflowError, '
'"value too large to pack into a byte"); %s' % (
code.error_goto(self.pos)))
code.putln('}')
temp = None
if arg.type is not PyrexTypes.c_char_type:
temp = code.funcstate.allocate_temp(PyrexTypes.c_char_type, manage_ref=False)
code.putln("%s = (char)%s;" % (temp, arg_result))
arg_result = temp
code.putln('%s = PyBytes_FromStringAndSize(&%s, 1); %s' % (
self.result(),
arg_result,
code.error_goto_if_null(self.result(), self.pos)))
if temp is not None:
code.funcstate.release_temp(temp)
code.put_gotref(self.py_result())
class CoerceFromPyTypeNode(CoercionNode):
# This node is used to convert a Python object
# to a C data type.
......@@ -6445,6 +6498,7 @@ class CoerceToTempNode(CoercionNode):
def __init__(self, arg, env):
CoercionNode.__init__(self, arg)
self.type = self.arg.type
self.constant_result = self.arg.constant_result
self.is_temp = 1
if self.type.is_pyobject:
self.result_ctype = py_object_type
......@@ -6457,6 +6511,8 @@ class CoerceToTempNode(CoercionNode):
def coerce_to_boolean(self, env):
self.arg = self.arg.coerce_to_boolean(env)
if self.arg.is_simple():
return self.arg
self.type = self.arg.type
self.result_ctype = self.type
return self
......
......@@ -4038,24 +4038,42 @@ class IfStatNode(StatNode):
if_clause.analyse_expressions(env)
if self.else_clause:
self.else_clause.analyse_expressions(env)
# eliminate dead code based on constant condition results
if_clauses = []
condition_result = None
for if_clause in self.if_clauses:
condition_result = if_clause.get_constant_condition_result()
if condition_result != False:
if_clauses.append(if_clause)
if condition_result == True:
# other conditions can no longer apply
self.else_clause = None
break
self.if_clauses = if_clauses
# FIXME: if only one active code body is left here, we can
# replace the whole node
def generate_execution_code(self, code):
code.mark_pos(self.pos)
end_label = code.new_label()
for if_clause in self.if_clauses:
if_clause.generate_execution_code(code, end_label)
if self.else_clause:
code.putln("/*else*/ {")
if self.if_clauses:
end_label = code.new_label()
for if_clause in self.if_clauses:
if_clause.generate_execution_code(code, end_label)
if self.else_clause:
code.putln("/*else*/ {")
self.else_clause.generate_execution_code(code)
code.putln("}")
code.put_label(end_label)
elif self.else_clause:
self.else_clause.generate_execution_code(code)
code.putln("}")
code.put_label(end_label)
def generate_function_definitions(self, env, code):
for clause in self.if_clauses:
clause.generate_function_definitions(env, code)
if self.else_clause is not None:
self.else_clause.generate_function_definitions(env, code)
def annotate(self, code):
for if_clause in self.if_clauses:
if_clause.annotate(code)
......@@ -4082,7 +4100,13 @@ class IfClauseNode(Node):
self.condition = \
self.condition.analyse_temp_boolean_expression(env)
self.body.analyse_expressions(env)
def get_constant_condition_result(self):
if self.condition.has_constant_result():
return self.condition.constant_result
else:
return None
def generate_execution_code(self, code, end_label):
self.condition.generate_evaluation_code(code)
code.putln(
......@@ -5258,8 +5282,7 @@ if Options.gcc_branch_hints:
"""
#ifdef __GNUC__
/* Test for GCC > 2.95 */
#if __GNUC__ > 2 || \
(__GNUC__ == 2 && (__GNUC_MINOR__ > 95))
#if __GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95))
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
#else /* __GNUC__ > 2 ... */
......
......@@ -1187,8 +1187,72 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
if isinstance(arg, ExprNodes.SimpleCallNode):
if node.type.is_int or node.type.is_float:
return self._optimise_numeric_cast_call(node, arg)
elif isinstance(arg, ExprNodes.IndexNode) and not arg.is_buffer_access:
index_node = arg.index
if isinstance(index_node, ExprNodes.CoerceToPyTypeNode):
index_node = index_node.arg
if index_node.type.is_int:
return self._optimise_int_indexing(node, arg, index_node)
return node
PyUnicode_GetItemInt_func_type = PyrexTypes.CFuncType(
PyrexTypes.c_py_unicode_type, [
PyrexTypes.CFuncTypeArg("unicode", Builtin.unicode_type, None),
PyrexTypes.CFuncTypeArg("index", PyrexTypes.c_py_ssize_t_type, None),
PyrexTypes.CFuncTypeArg("check_bounds", PyrexTypes.c_int_type, None),
],
exception_value = "((Py_UNICODE)-1)",
exception_check = True)
PyBytes_GetItemInt_func_type = PyrexTypes.CFuncType(
PyrexTypes.c_char_type, [
PyrexTypes.CFuncTypeArg("bytes", Builtin.bytes_type, None),
PyrexTypes.CFuncTypeArg("index", PyrexTypes.c_py_ssize_t_type, None),
PyrexTypes.CFuncTypeArg("check_bounds", PyrexTypes.c_int_type, None),
],
exception_value = "((char)-1)",
exception_check = True)
def _optimise_int_indexing(self, coerce_node, arg, index_node):
env = self.current_env()
bound_check_bool = env.directives['boundscheck'] and 1 or 0
if arg.base.type is Builtin.unicode_type:
if coerce_node.type is PyrexTypes.c_py_unicode_type:
# unicode[index] -> Py_UNICODE
bound_check_node = ExprNodes.IntNode(
coerce_node.pos, value=str(bound_check_bool),
constant_result=bound_check_bool)
return ExprNodes.PythonCapiCallNode(
coerce_node.pos, "__Pyx_PyUnicode_GetItemInt",
self.PyUnicode_GetItemInt_func_type,
args = [
arg.base.as_none_safe_node("'NoneType' object is not subscriptable"),
index_node.coerce_to(PyrexTypes.c_py_ssize_t_type, env),
bound_check_node,
],
is_temp = True,
utility_code=unicode_index_utility_code)
elif arg.base.type is Builtin.bytes_type:
if coerce_node.type in (PyrexTypes.c_char_type, PyrexTypes.c_uchar_type):
# bytes[index] -> char
bound_check_node = ExprNodes.IntNode(
coerce_node.pos, value=str(bound_check_bool),
constant_result=bound_check_bool)
node = ExprNodes.PythonCapiCallNode(
coerce_node.pos, "__Pyx_PyBytes_GetItemInt",
self.PyBytes_GetItemInt_func_type,
args = [
arg.base.as_none_safe_node("'NoneType' object is not subscriptable"),
index_node.coerce_to(PyrexTypes.c_py_ssize_t_type, env),
bound_check_node,
],
is_temp = True,
utility_code=bytes_index_utility_code)
if coerce_node.type is not PyrexTypes.c_char_type:
node = node.coerce_to(coerce_node.type, env)
return node
return coerce_node
def _optimise_numeric_cast_call(self, node, arg):
function = arg.function
if not isinstance(function, ExprNodes.NameNode) \
......@@ -2140,14 +2204,17 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
def _inject_int_default_argument(self, node, args, arg_index, type, default_value):
assert len(args) >= arg_index
if len(args) == arg_index:
args.append(ExprNodes.IntNode(node.pos, value=str(default_value), type=type))
args.append(ExprNodes.IntNode(node.pos, value=str(default_value),
type=type, constant_result=default_value))
else:
args[arg_index] = args[arg_index].coerce_to(type, self.current_env())
def _inject_bint_default_argument(self, node, args, arg_index, default_value):
assert len(args) >= arg_index
if len(args) == arg_index:
args.append(ExprNodes.BoolNode(node.pos, value=bool(default_value)))
default_value = bool(default_value)
args.append(ExprNodes.BoolNode(node.pos, value=default_value,
constant_result=default_value))
else:
args[arg_index] = args[arg_index].coerce_to_boolean(self.current_env())
......@@ -2348,6 +2415,48 @@ bad:
)
unicode_index_utility_code = UtilityCode(
proto = """
static CYTHON_INLINE Py_UNICODE __Pyx_PyUnicode_GetItemInt(PyObject* unicode, Py_ssize_t index, int check_bounds); /* proto */
""",
impl = """
static CYTHON_INLINE Py_UNICODE __Pyx_PyUnicode_GetItemInt(PyObject* unicode, Py_ssize_t index, int check_bounds) {
if (check_bounds) {
if (unlikely(index >= PyUnicode_GET_SIZE(unicode)) |
unlikely(index < -PyUnicode_GET_SIZE(unicode))) {
PyErr_Format(PyExc_IndexError, "string index out of range");
return (Py_UNICODE)-1;
}
}
if (index < 0)
index += PyUnicode_GET_SIZE(unicode);
return PyUnicode_AS_UNICODE(unicode)[index];
}
"""
)
bytes_index_utility_code = UtilityCode(
proto = """
static CYTHON_INLINE char __Pyx_PyBytes_GetItemInt(PyObject* unicode, Py_ssize_t index, int check_bounds); /* proto */
""",
impl = """
static CYTHON_INLINE char __Pyx_PyBytes_GetItemInt(PyObject* bytes, Py_ssize_t index, int check_bounds) {
if (check_bounds) {
if (unlikely(index >= PyBytes_GET_SIZE(bytes)) |
unlikely(index < -PyBytes_GET_SIZE(bytes))) {
PyErr_Format(PyExc_IndexError, "string index out of range");
return -1;
}
}
if (index < 0)
index += PyBytes_GET_SIZE(bytes);
return PyBytes_AS_STRING(bytes)[index];
}
"""
)
include_string_h_utility_code = UtilityCode(
proto = """
#include <string.h>
......
......@@ -881,17 +881,60 @@ class CBIntType(CIntType):
class CPyUnicodeIntType(CIntType):
# Py_UNICODE
# Conversion from a unicode string to Py_UNICODE at runtime is not
# currently supported and may never be - we only convert from and
# to integers here. The maximum value for a Py_UNICODE is
# 1114111, so PyInt_FromLong() will do just fine here.
# Py_UNICODE coerces from and to single character unicode strings,
# but we also allow Python integers as input. The value range for
# Py_UNICODE is 0..1114111, which is checked when converting from
# an integer value.
to_py_function = "PyInt_FromLong"
from_py_function = "__Pyx_PyInt_AsPy_UNICODE"
to_py_function = "PyUnicode_FromOrdinal"
from_py_function = "__Pyx_PyObject_AsPy_UNICODE"
def create_from_py_utility_code(self, env):
env.use_utility_code(pyobject_as_py_unicode_utility_code)
return True
def sign_and_name(self):
return "Py_UNICODE"
pyobject_as_py_unicode_utility_code = UtilityCode(
proto='''
static CYTHON_INLINE Py_UNICODE __Pyx_PyObject_AsPy_UNICODE(PyObject*);
''',
impl='''
static CYTHON_INLINE Py_UNICODE __Pyx_PyObject_AsPy_UNICODE(PyObject* x) {
static long maxval = 0;
long ival;
if (PyUnicode_Check(x)) {
if (unlikely(PyUnicode_GET_SIZE(x) != 1)) {
PyErr_Format(PyExc_ValueError,
"only single character unicode strings can be converted to Py_UNICODE, got length "
#if PY_VERSION_HEX < 0x02050000
"%d",
#else
"%zd",
#endif
PyUnicode_GET_SIZE(x));
return (Py_UNICODE)-1;
}
return PyUnicode_AS_UNICODE(x)[0];
}
if (unlikely(!maxval))
maxval = (long)PyUnicode_GetMax();
ival = __Pyx_PyInt_AsLong(x);
if (unlikely(ival < 0)) {
if (!PyErr_Occurred())
PyErr_SetString(PyExc_OverflowError,
"cannot convert negative value to Py_UNICODE");
return (Py_UNICODE)-1;
} else if (unlikely(ival > maxval)) {
PyErr_SetString(PyExc_OverflowError,
"value too large to convert to Py_UNICODE");
return (Py_UNICODE)-1;
}
return (Py_UNICODE)ival;
}
''')
class CPySSizeTType(CIntType):
......@@ -2512,10 +2555,6 @@ type_conversion_predeclarations = """
static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject*);
static CYTHON_INLINE PyObject* __Pyx_PyNumber_Int(PyObject* x);
#ifdef Py_USING_UNICODE
static CYTHON_INLINE Py_UNICODE __Pyx_PyInt_AsPy_UNICODE(PyObject*);
#endif
static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject*);
static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t);
static CYTHON_INLINE size_t __Pyx_PyInt_AsSize_t(PyObject*);
......@@ -2580,26 +2619,6 @@ static CYTHON_INLINE PyObject* __Pyx_PyNumber_Int(PyObject* x) {
return res;
}
#ifdef Py_USING_UNICODE
static CYTHON_INLINE Py_UNICODE __Pyx_PyInt_AsPy_UNICODE(PyObject* x) {
long ival = __Pyx_PyInt_AsLong(x);
static long maxval = 0;
if (unlikely(!maxval))
maxval = (long)PyUnicode_GetMax();
if (unlikely(ival < 0)) {
if (!PyErr_Occurred())
PyErr_SetString(PyExc_OverflowError,
"can't convert negative value to Py_UNICODE");
return (Py_UNICODE)-1;
} else if (unlikely(ival > maxval)) {
PyErr_SetString(PyExc_OverflowError,
"value too large to convert to Py_UNICODE");
return (Py_UNICODE)-1;
}
return (Py_UNICODE)ival;
}
#endif
static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject* b) {
Py_ssize_t ival;
PyObject* x = PyNumber_Index(b);
......
This diff is collapsed.
......@@ -16,11 +16,14 @@ except: pass
try: break
finally: pass
if True:
if bool_result():
break
else:
break
def bool_result():
return True
_ERRORS = u'''
2:0: break statement not inside loop
......
......@@ -16,11 +16,13 @@ except: pass
try: continue
finally: pass
if True:
if bool_result():
continue
else:
continue
def bool_result():
return True
_ERRORS = u'''
2:0: continue statement not inside loop
......
def f():
cdef int* p
if False:
if false():
p = [1, 2, 3]
def false():
return False
_ERRORS = u"""
4:10: Literal list must be assigned to pointer at time of declaration
"""
......@@ -126,4 +126,20 @@ cdef class MyCdefClass:
False
"""
cdef class MyOtherCdefClass:
"""
Needs no hack
>>> True
True
"""
def __bool__(self):
"""
Should not be included, as it can't be looked up with getattr in Py 2
>>> True
False
"""
cdeffunc()
cimport cython
def coerce_char_default(char c):
"""
Default char -> int coercion
>>> coerce_char_default(ord('A')) == ord('A')
True
"""
return c
def coerce_uchar_default(unsigned char c):
"""
Default char -> int coercion
>>> coerce_uchar_default(ord('A')) == ord('A')
True
"""
return c
@cython.test_assert_path_exists("//CoerceIntToBytesNode")
@cython.test_fail_if_path_exists("//CoerceToPyTypeNode")
def coerce_char_bytes_cast(char c):
"""
Explicit char -> bytes coercion
>>> coerce_char_bytes_cast(ord('A')) == 'A'.encode('ASCII')
True
"""
return <bytes>c
@cython.test_assert_path_exists("//CoerceIntToBytesNode")
@cython.test_fail_if_path_exists("//CoerceToPyTypeNode")
def coerce_uchar_bytes_cast(unsigned char c):
"""
Explicit uchar -> bytes coercion
>>> coerce_uchar_bytes_cast(ord('A')) == 'A'.encode('ASCII')
True
>>> b = coerce_uchar_bytes_cast(ord('\\xff'))
>>> b == '\\xff' or b == '\\xff'.encode('ISO-8859-1') # Py2 or Py3
True
"""
return <bytes>c
@cython.test_assert_path_exists("//CoerceIntToBytesNode")
@cython.test_fail_if_path_exists("//CoerceToPyTypeNode")
def coerce_int_bytes_cast(int c):
"""
Explicit int -> bytes coercion
>>> coerce_int_bytes_cast(ord('A')) == 'A'.encode('ASCII')
True
>>> coerce_int_bytes_cast(ord('A') + 0x100)
Traceback (most recent call last):
OverflowError: value too large to pack into a byte
>>> coerce_int_bytes_cast(ord('A') - 0x100)
Traceback (most recent call last):
OverflowError: value too large to pack into a byte
"""
return <bytes>c
@cython.test_assert_path_exists("//CoerceIntToBytesNode")
@cython.test_fail_if_path_exists("//CoerceToPyTypeNode")
def coerce_uint_bytes_cast(unsigned int c):
"""
Explicit uint -> bytes coercion
>>> coerce_uint_bytes_cast(ord('A')) == 'A'.encode('ASCII')
True
>>> b = coerce_uint_bytes_cast(ord('\\xff'))
>>> b == '\\xff' or b == '\\xff'.encode('ISO-8859-1') # Py2 or Py3
True
>>> coerce_uint_bytes_cast(ord('A') + 0x100)
Traceback (most recent call last):
OverflowError: value too large to pack into a byte
"""
return <bytes>c
@cython.test_assert_path_exists("//CoerceIntToBytesNode")
@cython.test_fail_if_path_exists("//CoerceToPyTypeNode")
def coerce_char_bytes_assign(char c):
"""
Implicit char -> bytes coercion in assignments
>>> coerce_char_bytes_assign(ord('A')) == 'A'.encode('ASCII')
True
"""
cdef bytes s = c
return s
@cython.test_assert_path_exists("//CoerceIntToBytesNode")
@cython.test_fail_if_path_exists("//CoerceToPyTypeNode")
def coerce_uchar_bytes_assign(unsigned char c):
"""
Implicit uchar -> bytes coercion in assignments
>>> coerce_uchar_bytes_assign(ord('A')) == 'A'.encode('ASCII')
True
>>> b = coerce_uchar_bytes_assign(ord('\\xff'))
>>> b == '\\xff' or b == '\\xff'.encode('ISO-8859-1') # Py2 or Py3
True
"""
cdef bytes s = c
return s
@cython.test_assert_path_exists("//CoerceIntToBytesNode")
@cython.test_fail_if_path_exists("//CoerceToPyTypeNode")
def coerce_int_bytes_assign(int c):
"""
Implicit int -> bytes coercion in assignments
>>> coerce_int_bytes_assign(ord('A')) == 'A'.encode('ASCII')
True
>>> coerce_int_bytes_assign(ord('A') + 0x100)
Traceback (most recent call last):
OverflowError: value too large to pack into a byte
>>> coerce_int_bytes_assign(ord('A') - 0x100)
Traceback (most recent call last):
OverflowError: value too large to pack into a byte
"""
cdef bytes s = c
return s
@cython.test_assert_path_exists("//CoerceIntToBytesNode")
@cython.test_fail_if_path_exists("//CoerceToPyTypeNode")
def coerce_uint_bytes_assign(unsigned int c):
"""
Implicit uint -> bytes coercion in assignments
>>> coerce_uint_bytes_assign(ord('A')) == 'A'.encode('ASCII')
True
>>> b = coerce_uint_bytes_assign(ord('\\xff'))
>>> b == '\\xff' or b == '\\xff'.encode('ISO-8859-1') # Py2 or Py3
True
>>> coerce_uint_bytes_assign(ord('A') + 0x100)
Traceback (most recent call last):
OverflowError: value too large to pack into a byte
"""
cdef bytes s = c
return s
cimport cython
cdef bytes b12345 = b'12345'
def index_literal(int i):
"""
Python 3 returns integer values on indexing, Py2 returns byte
string literals...
>>> index_literal(0) in (ord('1'), '1')
True
>>> index_literal(-5) in (ord('1'), '1')
True
>>> index_literal(2) in (ord('3'), '3')
True
>>> index_literal(4) in (ord('5'), '5')
True
"""
return b"12345"[i]
@cython.test_assert_path_exists("//PythonCapiCallNode")
@cython.test_fail_if_path_exists("//IndexNode",
"//CoerceFromPyTypeNode")
def index_literal_char_cast(int i):
"""
>>> index_literal_char_cast(0) == ord('1')
True
>>> index_literal_char_cast(-5) == ord('1')
True
>>> index_literal_char_cast(2) == ord('3')
True
>>> index_literal_char_cast(4) == ord('5')
True
>>> index_literal_char_cast(6)
Traceback (most recent call last):
IndexError: string index out of range
"""
return <char>(b"12345"[i])
@cython.test_assert_path_exists("//PythonCapiCallNode")
@cython.test_fail_if_path_exists("//IndexNode",
"//CoerceFromPyTypeNode")
def index_nonliteral_char_cast(int i):
"""
>>> index_nonliteral_char_cast(0) == ord('1')
True
>>> index_nonliteral_char_cast(-5) == ord('1')
True
>>> index_nonliteral_char_cast(2) == ord('3')
True
>>> index_nonliteral_char_cast(4) == ord('5')
True
>>> index_nonliteral_char_cast(6)
Traceback (most recent call last):
IndexError: string index out of range
"""
return <char>(b12345[i])
@cython.test_assert_path_exists("//PythonCapiCallNode")
@cython.test_fail_if_path_exists("//IndexNode",
"//CoerceFromPyTypeNode")
def index_literal_uchar_cast(int i):
"""
>>> index_literal_uchar_cast(0) == ord('1')
True
>>> index_literal_uchar_cast(-5) == ord('1')
True
>>> index_literal_uchar_cast(2) == ord('3')
True
>>> index_literal_uchar_cast(4) == ord('5')
True
>>> index_literal_uchar_cast(6)
Traceback (most recent call last):
IndexError: string index out of range
"""
return <unsigned char>(b"12345"[i])
@cython.test_assert_path_exists("//PythonCapiCallNode")
@cython.test_fail_if_path_exists("//IndexNode",
"//CoerceFromPyTypeNode")
def index_nonliteral_uchar_cast(int i):
"""
>>> index_nonliteral_uchar_cast(0) == ord('1')
True
>>> index_nonliteral_uchar_cast(-5) == ord('1')
True
>>> index_nonliteral_uchar_cast(2) == ord('3')
True
>>> index_nonliteral_uchar_cast(4) == ord('5')
True
>>> index_nonliteral_uchar_cast(6)
Traceback (most recent call last):
IndexError: string index out of range
"""
return <unsigned char>(b12345[i])
@cython.test_assert_path_exists("//PythonCapiCallNode")
@cython.test_fail_if_path_exists("//IndexNode",
"//CoerceFromPyTypeNode")
def index_literal_char_coerce(int i):
"""
>>> index_literal_char_coerce(0) == ord('1')
True
>>> index_literal_char_coerce(-5) == ord('1')
True
>>> index_literal_char_coerce(2) == ord('3')
True
>>> index_literal_char_coerce(4) == ord('5')
True
>>> index_literal_char_coerce(6)
Traceback (most recent call last):
IndexError: string index out of range
"""
cdef char result = b"12345"[i]
return result
@cython.test_assert_path_exists("//PythonCapiCallNode")
@cython.test_fail_if_path_exists("//IndexNode",
"//CoerceFromPyTypeNode")
def index_nonliteral_char_coerce(int i):
"""
>>> index_nonliteral_char_coerce(0) == ord('1')
True
>>> index_nonliteral_char_coerce(-5) == ord('1')
True
>>> index_nonliteral_char_coerce(2) == ord('3')
True
>>> index_nonliteral_char_coerce(4) == ord('5')
True
>>> index_nonliteral_char_coerce(6)
Traceback (most recent call last):
IndexError: string index out of range
"""
cdef char result = b12345[i]
return result
@cython.test_assert_path_exists("//PythonCapiCallNode")
@cython.test_fail_if_path_exists("//IndexNode",
"//CoerceFromPyTypeNode")
@cython.boundscheck(False)
def index_literal_char_coerce_no_check(int i):
"""
>>> index_literal_char_coerce_no_check(0) == ord('1')
True
>>> index_literal_char_coerce_no_check(-5) == ord('1')
True
>>> index_literal_char_coerce_no_check(2) == ord('3')
True
>>> index_literal_char_coerce_no_check(4) == ord('5')
True
"""
cdef char result = b"12345"[i]
return result
@cython.test_assert_path_exists("//PythonCapiCallNode")
@cython.test_fail_if_path_exists("//IndexNode",
"//CoerceFromPyTypeNode")
@cython.boundscheck(False)
def index_nonliteral_char_coerce_no_check(int i):
"""
>>> index_nonliteral_char_coerce_no_check(0) == ord('1')
True
>>> index_nonliteral_char_coerce_no_check(-5) == ord('1')
True
>>> index_nonliteral_char_coerce_no_check(2) == ord('3')
True
>>> index_nonliteral_char_coerce_no_check(4) == ord('5')
True
"""
cdef char result = b12345[i]
return result
import sys
IS_PY3 = sys.version_info[0] >= 3
cimport cython
DEF INT_VAL = 1
def _func(a,b,c):
return a+b+c
......@@ -76,3 +80,76 @@ def lists():
True
"""
return [1,2,3] + [4,5,6]
def int_bool_result():
"""
>>> int_bool_result()
True
"""
if 5:
return True
else:
return False
@cython.test_fail_if_path_exists("//PrimaryCmpNode")
def if_compare_true():
"""
>>> if_compare_true()
True
"""
if 0 == 0:
return True
else:
return False
@cython.test_fail_if_path_exists("//PrimaryCmpNode")
def if_compare_false():
"""
>>> if_compare_false()
False
"""
if 0 == 1 or 1 == 0:
return True
else:
return False
@cython.test_fail_if_path_exists("//PrimaryCmpNode")
def if_compare_cascaded():
"""
>>> if_compare_cascaded()
True
"""
if 0 < 1 < 2 < 3:
return True
else:
return False
@cython.test_fail_if_path_exists("//CoerceToBooleanNode",
"//ListNode")
def list_bool_result():
"""
>>> list_bool_result()
True
"""
if [1,2,3]:
return True
else:
return False
def compile_time_DEF():
"""
>>> compile_time_DEF()
(1, False, True, True, False)
"""
return INT_VAL, INT_VAL == 0, INT_VAL != 0, INT_VAL == 1, INT_VAL != 1
@cython.test_fail_if_path_exists("//PrimaryCmpNode")
def compile_time_DEF_if():
"""
>>> compile_time_DEF_if()
True
"""
if INT_VAL != 0:
return True
else:
return False
......@@ -70,6 +70,36 @@ def for_char_in_enumerate_bytes(bytes s):
else:
return 'X'
@cython.test_assert_path_exists("//ForFromStatNode")
@cython.test_fail_if_path_exists("//ForInStatNode")
def for_pyvar_in_char_ptr(char* c_string):
"""
>>> for_pyvar_in_char_ptr( (bytes_abc+bytes_ABC) * 2 )
[True, True, True, False, False, False, True, True, True, False]
>>> for_pyvar_in_char_ptr( bytes_abc_null * 2 )
[True, False, True, False, True, True, False, True, False, True]
"""
in_test = []
cdef object c
for c in c_string[:10]:
in_test.append( c in b'abc' )
return in_test
@cython.test_assert_path_exists("//ForFromStatNode")
@cython.test_fail_if_path_exists("//ForInStatNode")
def for_char_in_char_ptr(char* c_string):
"""
>>> for_char_in_char_ptr( (bytes_abc+bytes_ABC) * 2 )
[True, True, True, False, False, False, True, True, True, False]
>>> for_char_in_char_ptr( bytes_abc_null * 2 )
[True, False, True, False, True, True, False, True, False, True]
"""
in_test = []
cdef char c
for c in c_string[:10]:
in_test.append( c in b'abc' )
return in_test
@cython.test_assert_path_exists("//ForFromStatNode")
@cython.test_fail_if_path_exists("//ForInStatNode")
def for_pyunicode_in_unicode(unicode s):
......
# -*- coding: iso-8859-1 -*-
cimport cython
cdef Py_UNICODE char_ASCII = u'A'
cdef Py_UNICODE char_KLINGON = u'\uF8D2'
def compare_ASCII():
"""
>>> compare_ASCII()
......@@ -16,9 +17,9 @@ def compare_ASCII():
print(char_ASCII == u'\uF8D2')
def compare_KLINGON():
def compare_klingon():
"""
>>> compare_ASCII()
>>> compare_klingon()
True
False
False
......@@ -39,31 +40,114 @@ def index_literal(int i):
>>> index_literal(4) == '5'
True
"""
# runtime casts are not currently supported
#return <Py_UNICODE>(u"12345"[i])
return u"12345"[i]
def unicode_cardinal(Py_UNICODE i):
@cython.test_assert_path_exists("//PythonCapiCallNode")
@cython.test_fail_if_path_exists("//IndexNode",
"//CoerceFromPyTypeNode")
def index_literal_pyunicode_cast(int i):
"""
>>> index_literal_pyunicode_cast(0) == '1'
True
>>> index_literal_pyunicode_cast(-5) == '1'
True
>>> index_literal_pyunicode_cast(2) == '3'
True
>>> index_literal_pyunicode_cast(4) == '5'
True
>>> index_literal_pyunicode_coerce(6)
Traceback (most recent call last):
IndexError: string index out of range
"""
return <Py_UNICODE>(u"12345"[i])
@cython.test_assert_path_exists("//PythonCapiCallNode")
@cython.test_fail_if_path_exists("//IndexNode",
"//CoerceFromPyTypeNode")
def index_literal_pyunicode_coerce(int i):
"""
>>> index_literal_pyunicode_coerce(0) == '1'
True
>>> index_literal_pyunicode_coerce(-5) == '1'
True
>>> index_literal_pyunicode_coerce(2) == '3'
True
>>> index_literal_pyunicode_coerce(4) == '5'
True
>>> index_literal_pyunicode_coerce(6)
Traceback (most recent call last):
IndexError: string index out of range
"""
cdef Py_UNICODE result = u"12345"[i]
return result
@cython.test_assert_path_exists("//PythonCapiCallNode")
@cython.test_fail_if_path_exists("//IndexNode",
"//CoerceFromPyTypeNode")
@cython.boundscheck(False)
def index_literal_pyunicode_coerce_no_check(int i):
"""
>>> import sys
>>> index_literal_pyunicode_coerce_no_check(0) == '1'
True
>>> index_literal_pyunicode_coerce_no_check(-5) == '1'
True
>>> index_literal_pyunicode_coerce_no_check(2) == '3'
True
>>> index_literal_pyunicode_coerce_no_check(4) == '5'
True
"""
cdef Py_UNICODE result = u"12345"[i]
return result
>>> unicode_cardinal(0)
0
>>> unicode_cardinal(1)
1
>>> unicode_cardinal(sys.maxunicode) == sys.maxunicode
from cpython.unicode cimport PyUnicode_FromOrdinal
import sys
u0 = u'\x00'
u1 = u'\x01'
umax = PyUnicode_FromOrdinal(sys.maxunicode)
def unicode_ordinal(Py_UNICODE i):
"""
>>> ord(unicode_ordinal(0)) == 0
True
>>> ord(unicode_ordinal(1)) == 1
True
>>> ord(unicode_ordinal(sys.maxunicode)) == sys.maxunicode
True
>>> unicode_cardinal(-1) #doctest: +ELLIPSIS
>>> ord(unicode_ordinal(u0)) == 0
True
>>> ord(unicode_ordinal(u1)) == 1
True
>>> ord(unicode_ordinal(umax)) == sys.maxunicode
True
Value too small:
>>> unicode_ordinal(-1) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
>>> unicode_cardinal(sys.maxunicode+1) #doctest: +ELLIPSIS
Value too large:
>>> unicode_ordinal(sys.maxunicode+1) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
Less than one character:
>>> unicode_ordinal(u0[:0])
Traceback (most recent call last):
...
ValueError: only single character unicode strings can be converted to Py_UNICODE, got length 0
More than one character:
>>> unicode_ordinal(u0+u1)
Traceback (most recent call last):
...
ValueError: only single character unicode strings can be converted to Py_UNICODE, got length 2
"""
return i
__doc__ = """
>>> not not BoolA(0)
False
>>> not not BoolA(1)
True
>>> not not BoolB(0)
False
>>> not not BoolB(1)
True
>>> not not BoolX(0)
False
>>> not not BoolX(1)
True
>>> not not BoolY(0)
False
>>> not not BoolY(1)
True
"""
cdef class BoolA:
cdef bint value
def __cinit__(self, bint value):
self.value = value
def __nonzero__(self):
return self.value
cdef class BoolB:
cdef bint value
def __cinit__(self, bint value):
self.value = value
def __bool__(self):
return self.value
cdef class BoolX(BoolA):
pass
cdef class BoolY(BoolB):
pass
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