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

merged in latest cython-devel

parents 4856376e 19209090
......@@ -11,7 +11,8 @@ import Symtab
class AutoTestDictTransform(ScopeTrackingTransform):
# Handles autotestdict directive
blacklist = ['__cinit__', '__dealloc__', '__richcmp__', '__nonzero__']
blacklist = ['__cinit__', '__dealloc__', '__richcmp__', '__nonzero__',
'__len__', '__contains__']
def visit_ModuleNode(self, node):
if node.is_pxd:
......
......@@ -44,8 +44,9 @@ class AnnotationCCodeWriter(CCodeWriter):
if pos is not None:
CCodeWriter.mark_pos(self, pos)
if self.last_pos:
code = self.code.get(self.last_pos[1], "")
self.code[self.last_pos[1]] = code + self.annotation_buffer.getvalue()
pos_code = self.code.setdefault(self.last_pos[0].get_description(),{})
code = pos_code.get(self.last_pos[1], "")
pos_code[self.last_pos[1]] = code + self.annotation_buffer.getvalue()
self.annotation_buffer = StringIO()
self.last_pos = pos
......@@ -63,8 +64,9 @@ class AnnotationCCodeWriter(CCodeWriter):
lines[k] = line
f.close()
all = []
if False:
for pos, item in self.annotations:
if pos[0] == source_filename:
if pos[0].filename == source_filename:
start = item.start()
size, end = item.end()
if size:
......@@ -136,11 +138,12 @@ function toggleDiv(id) {
error_goto = re.compile(ur'((; *if .*)? \{__pyx_filename = .*goto __pyx_L\w+;\})')
refnanny = re.compile(u'(__Pyx_X?(GOT|GIVE)REF|__Pyx_RefNanny[A-Za-z]+)')
code_source_file = self.code[source_filename]
for line in lines:
k += 1
try:
code = self.code[k]
code = code_source_file[k]
except KeyError:
code = ''
......
......@@ -413,16 +413,19 @@ def init_builtins():
init_builtin_funcs()
init_builtin_types()
init_builtin_structs()
global list_type, tuple_type, dict_type, set_type, type_type
global bytes_type, str_type, unicode_type, float_type
global list_type, tuple_type, dict_type, set_type, frozenset_type
global bytes_type, str_type, unicode_type
global float_type, bool_type, type_type
type_type = builtin_scope.lookup('type').type
list_type = builtin_scope.lookup('list').type
tuple_type = builtin_scope.lookup('tuple').type
dict_type = builtin_scope.lookup('dict').type
set_type = builtin_scope.lookup('set').type
frozenset_type = builtin_scope.lookup('frozenset').type
bytes_type = builtin_scope.lookup('bytes').type
str_type = builtin_scope.lookup('str').type
unicode_type = builtin_scope.lookup('unicode').type
float_type = builtin_scope.lookup('float').type
bool_type = builtin_scope.lookup('bool').type
init_builtins()
......@@ -10,7 +10,7 @@ debug_temp_code_comments = 0
debug_trace_code_generation = 0
# Do not replace exceptions with user-friendly error messages
debug_no_exception_intercept = 0
debug_no_exception_intercept = 1
# Print a message each time a new stage in the pipeline is entered
debug_verbose_pipeline = 0
......@@ -274,6 +274,10 @@ class ExprNode(Node):
# ConstantFolding transform will do this.
pass
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 compile_time_value(self, denv):
# Return value of compile-time expression, or report error.
error(self.pos, "Invalid compile-time expression")
......@@ -594,11 +598,18 @@ class ExprNode(Node):
def coerce_to_boolean(self, env):
# Coerce result to something acceptable as
# a boolean value.
# if it's constant, calculate the result now
if self.has_constant_result():
bool_value = bool(self.constant_result)
return BoolNode(self.pos, value=bool_value,
constant_result=bool_value)
type = self.type
if type.is_pyobject or type.is_ptr or type.is_float:
return CoerceToBooleanNode(self, env)
else:
if not type.is_int and not type.is_error:
if not (type.is_int or type.is_enum or type.is_error):
error(self.pos,
"Type '%s' not acceptable as a boolean" % type)
return self
......@@ -631,9 +642,21 @@ class ExprNode(Node):
# reference, or temporary.
return self.result_in_temp()
def may_be_none(self):
return self.type.is_pyobject
def as_cython_attribute(self):
return None
def as_none_safe_node(self, message, error="PyExc_TypeError"):
# Wraps the node in a NoneCheckNode if it is not known to be
# not-None (e.g. because it is a Python literal).
if self.may_be_none():
return NoneCheckNode(self, error, message)
else:
return self
class AtomicExprNode(ExprNode):
# Abstract base class for expression nodes which have
# no sub-expressions.
......@@ -655,6 +678,9 @@ class PyConstNode(AtomicExprNode):
def is_simple(self):
return 1
def may_be_none(self):
return False
def analyse_types(self, env):
pass
......@@ -677,6 +703,10 @@ class NoneNode(PyConstNode):
def compile_time_value(self, denv):
return None
def may_be_none(self):
return True
class EllipsisNode(PyConstNode):
# '...' in a subscript list.
......@@ -699,6 +729,9 @@ class ConstNode(AtomicExprNode):
def is_simple(self):
return 1
def may_be_none(self):
return False
def analyse_types(self, env):
pass # Types are held in class variables
......@@ -853,10 +886,18 @@ class BytesNode(ConstNode):
def can_coerce_to_char_literal(self):
return len(self.value) == 1
def coerce_to_boolean(self, env):
# This is special because we start off as a C char*. Testing
# that for truth directly would yield the wrong result.
return BoolNode(self.pos, value=bool(self.value))
def coerce_to(self, dst_type, env):
if dst_type.is_int:
if not self.can_coerce_to_char_literal():
error(self.pos, "Only single-character strings can be coerced into ints.")
error(self.pos, "Only single-character string literals can be coerced into ints.")
return self
if dst_type is PyrexTypes.c_py_unicode_type:
error(self.pos, "Bytes literals cannot coerce to Py_UNICODE, use a unicode literal instead.")
return self
return CharNode(self.pos, value=self.value)
......@@ -911,13 +952,22 @@ class UnicodeNode(PyConstNode):
def coerce_to(self, dst_type, env):
if dst_type is self.type:
pass
elif dst_type is PyrexTypes.c_py_unicode_type:
if not self.can_coerce_to_char_literal():
error(self.pos, "Only single-character Unicode string literals can be coerced into Py_UNICODE.")
return self
int_value = ord(self.value)
return IntNode(self.pos, value=int_value, constant_result=int_value)
elif not dst_type.is_pyobject:
error(self.pos, "Unicode objects do not support coercion to C types.")
error(self.pos, "Unicode literals do not support coercion to C types other than Py_UNICODE.")
elif dst_type is not py_object_type:
if not self.check_for_coercion_error(dst_type):
self.fail_assignment(dst_type)
return self
def can_coerce_to_char_literal(self):
return len(self.value) == 1
def generate_evaluation_code(self, code):
self.result_code = code.get_py_string_const(self.value)
......@@ -996,6 +1046,9 @@ class LongNode(AtomicExprNode):
def analyse_types(self, env):
self.is_temp = 1
def may_be_none(self):
return False
gil_message = "Constructing Python long int"
def generate_result_code(self, code):
......@@ -1023,6 +1076,9 @@ class ImagNode(AtomicExprNode):
def analyse_types(self, env):
self.type.create_declaration_utility_code(env)
def may_be_none(self):
return False
def coerce_to(self, dst_type, env):
if self.type is dst_type:
return self
......@@ -1083,6 +1139,9 @@ class NewExprNode(AtomicExprNode):
if self.type is None:
self.infer_type(env)
def may_be_none(self):
return False
def generate_result_code(self, code):
pass
......@@ -2259,14 +2318,14 @@ class SliceIndexNode(ExprNode):
if self.base.type.is_string:
if self.stop is None:
code.putln(
"%s = __Pyx_PyBytes_FromString(%s + %s); %s" % (
"%s = PyBytes_FromString(%s + %s); %s" % (
self.result(),
self.base.result(),
self.start_code(),
code.error_goto_if_null(self.result(), self.pos)))
else:
code.putln(
"%s = __Pyx_PyBytes_FromStringAndSize(%s + %s, %s - %s); %s" % (
"%s = PyBytes_FromStringAndSize(%s + %s, %s - %s); %s" % (
self.result(),
self.base.result(),
self.start_code(),
......@@ -2943,6 +3002,9 @@ class AsTupleNode(ExprNode):
self.type = tuple_type
self.is_temp = 1
def may_be_none(self):
return False
nogil_check = Node.gil_error
gil_message = "Constructing Python tuple"
......@@ -3419,6 +3481,9 @@ class SequenceNode(ExprNode):
self.type = py_object_type
self.is_temp = 1
def may_be_none(self):
return False
def analyse_target_types(self, env):
self.iterator = PyTempNode(self.pos, env)
self.unpacked_items = []
......@@ -3802,6 +3867,9 @@ class ComprehensionNode(ExprNode):
self.type = self.target.type
self.loop.analyse_expressions(env)
def may_be_none(self):
return False
def calculate_result_code(self):
return self.target.result()
......@@ -3882,6 +3950,9 @@ class SetNode(ExprNode):
self.type = set_type
self.is_temp = 1
def may_be_none(self):
return False
def calculate_constant_result(self):
self.constant_result = set([
arg.constant_result for arg in self.args])
......@@ -3950,6 +4021,9 @@ class DictNode(ExprNode):
self.obj_conversion_errors = held_errors()
release_errors(ignore=True)
def may_be_none(self):
return False
def coerce_to(self, dst_type, env):
if dst_type.is_pyobject:
self.release_errors()
......@@ -4079,6 +4153,9 @@ class ClassNode(ExprNode):
self.is_temp = 1
env.use_utility_code(create_class_utility_code);
def may_be_none(self):
return False
gil_message = "Constructing Python class"
def generate_result_code(self, code):
......@@ -4140,6 +4217,9 @@ class UnboundMethodNode(ExprNode):
def analyse_types(self, env):
self.function.analyse_types(env)
def may_be_none(self):
return False
gil_message = "Constructing an unbound method"
def generate_result_code(self, code):
......@@ -4173,6 +4253,9 @@ class PyCFunctionNode(ExprNode):
if self.binding:
env.use_utility_code(binding_cfunc_utility_code)
def may_be_none(self):
return False
gil_message = "Constructing Python function"
def self_result_code(self):
......@@ -4762,6 +4845,9 @@ class TypeofNode(ExprNode):
self.literal.analyse_types(env)
self.literal = self.literal.coerce_to_pyobject(env)
def may_be_none(self):
return False
def generate_evaluation_code(self, code):
self.literal.generate_evaluation_code(code)
......@@ -5123,7 +5209,7 @@ class DivNode(NumBinopNode):
if not self.type.is_pyobject:
self.zerodivision_check = (
self.cdivision is None and not env.directives['cdivision']
and (self.operand2.constant_result is not_a_constant or
and (not self.operand2.has_constant_result() or
self.operand2.constant_result == 0))
if self.zerodivision_check or env.directives['cdivision_warnings']:
# Need to check ahead of time to warn or raise zero division error
......@@ -5524,10 +5610,10 @@ class CmpNode(object):
type1_can_be_int = False
type2_can_be_int = False
if isinstance(operand1, (StringNode, BytesNode)) \
if isinstance(operand1, (StringNode, BytesNode, UnicodeNode)) \
and operand1.can_coerce_to_char_literal():
type1_can_be_int = True
if isinstance(operand2, (StringNode, BytesNode)) \
if isinstance(operand2, (StringNode, BytesNode, UnicodeNode)) \
and operand2.can_coerce_to_char_literal():
type2_can_be_int = True
......@@ -5621,7 +5707,8 @@ class CmpNode(object):
(op, operand1.type, operand2.type))
def is_python_comparison(self):
return (self.has_python_operands()
return not self.is_c_string_contains() and (
self.has_python_operands()
or (self.cascade and self.cascade.is_python_comparison())
or self.operator in ('in', 'not_in'))
......@@ -5634,12 +5721,22 @@ class CmpNode(object):
def is_python_result(self):
return ((self.has_python_operands() and
self.operator not in ('is', 'is_not', 'in', 'not_in'))
self.operator not in ('is', 'is_not', 'in', 'not_in') and
not self.is_c_string_contains())
or (self.cascade and self.cascade.is_python_result()))
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 PyrexTypes.c_py_unicode_type
and self.operand2.type is unicode_type))
def generate_operation_code(self, code, result_code,
operand1, op , operand2):
if self.type is PyrexTypes.py_object_type:
if self.type.is_pyobject:
coerce_result = "__Pyx_PyBool_FromLong"
else:
coerce_result = ""
......@@ -5648,8 +5745,8 @@ class CmpNode(object):
else:
negation = ""
if op == 'in' or op == 'not_in':
code.globalstate.use_utility_code(contians_utility_code)
if self.type is PyrexTypes.py_object_type:
code.globalstate.use_utility_code(contains_utility_code)
if self.type.is_pyobject:
coerce_result = "__Pyx_PyBoolOrNull_FromLong"
if op == 'not_in':
negation = "__Pyx_NegateNonNeg"
......@@ -5663,7 +5760,7 @@ class CmpNode(object):
method = "PyDict_Contains"
else:
method = "PySequence_Contains"
if self.type is PyrexTypes.py_object_type:
if self.type.is_pyobject:
error_clause = code.error_goto_if_null
got_ref = "__Pyx_XGOTREF(%s); " % result_code
else:
......@@ -5730,7 +5827,7 @@ class CmpNode(object):
else:
return op
contians_utility_code = UtilityCode(
contains_utility_code = UtilityCode(
proto="""
static CYTHON_INLINE long __Pyx_NegateNonNeg(long b) { return unlikely(b < 0) ? b : !b; }
static CYTHON_INLINE PyObject* __Pyx_PyBoolOrNull_FromLong(long b) {
......@@ -5738,6 +5835,38 @@ static CYTHON_INLINE PyObject* __Pyx_PyBoolOrNull_FromLong(long b) {
}
""")
char_in_bytes_utility_code = UtilityCode(
proto="""
static CYTHON_INLINE int __Pyx_BytesContains(PyObject* bytes, char character); /*proto*/
""",
impl="""
static CYTHON_INLINE int __Pyx_BytesContains(PyObject* bytes, char character) {
const Py_ssize_t length = PyBytes_GET_SIZE(bytes);
char* char_start = PyBytes_AS_STRING(bytes);
char* pos;
for (pos=char_start; pos < char_start+length; pos++) {
if (character == pos[0]) return 1;
}
return 0;
}
""")
pyunicode_in_unicode_utility_code = UtilityCode(
proto="""
static CYTHON_INLINE int __Pyx_UnicodeContains(PyObject* unicode, Py_UNICODE character); /*proto*/
""",
impl="""
static CYTHON_INLINE int __Pyx_UnicodeContains(PyObject* unicode, Py_UNICODE character) {
const Py_ssize_t length = PyUnicode_GET_SIZE(unicode);
Py_UNICODE* char_start = PyUnicode_AS_UNICODE(unicode);
Py_UNICODE* pos;
for (pos=char_start; pos < char_start+length; pos++) {
if (character == pos[0]) return 1;
}
return 0;
}
""")
class PrimaryCmpNode(ExprNode, CmpNode):
# Non-cascaded comparison or first comparison of
......@@ -5784,13 +5913,30 @@ class PrimaryCmpNode(ExprNode, CmpNode):
self.cascade.analyse_types(env)
if self.operator in ('in', 'not_in'):
if self.is_c_string_contains():
self.is_pycmp = False
common_type = None
if self.cascade:
error(self.pos, "Cascading comparison not yet supported for 'int_val in string'.")
return
if self.operand2.type is unicode_type:
env.use_utility_code(pyunicode_in_unicode_utility_code)
else:
if self.operand1.type is PyrexTypes.c_uchar_type:
self.operand1 = self.operand1.coerce_to(PyrexTypes.c_char_type, env)
if self.operand2.type is not bytes_type:
self.operand2 = self.operand2.coerce_to(bytes_type, env)
env.use_utility_code(char_in_bytes_utility_code)
self.operand2 = self.operand2.as_none_safe_node(
"argument of type 'NoneType' is not iterable")
else:
common_type = py_object_type
self.is_pycmp = True
else:
common_type = self.find_common_type(env, self.operator, self.operand1)
self.is_pycmp = common_type.is_pyobject
if not common_type.is_error:
if common_type is not None and not common_type.is_error:
if self.operand1.type != common_type:
self.operand1 = self.operand1.coerce_to(common_type, env)
self.coerce_operands_to(common_type, env)
......@@ -5851,6 +5997,20 @@ class PrimaryCmpNode(ExprNode, CmpNode):
self.operand1.type.binary_op('=='),
self.operand1.result(),
self.operand2.result())
elif self.is_c_string_contains():
if self.operand2.type is bytes_type:
method = "__Pyx_BytesContains"
else:
method = "__Pyx_UnicodeContains"
if self.operator == "not_in":
negation = "!"
else:
negation = ""
return "(%s%s(%s, %s))" % (
negation,
method,
self.operand2.result(),
self.operand1.result())
else:
return "(%s %s %s)" % (
self.operand1.result(),
......@@ -6097,6 +6257,9 @@ class NoneCheckNode(CoercionNode):
def analyse_types(self, env):
pass
def may_be_none(self):
return False
def result_in_temp(self):
return self.arg.result_in_temp()
......@@ -6139,6 +6302,10 @@ class CoerceToPyTypeNode(CoercionNode):
gil_message = "Converting to Python object"
def may_be_none(self):
# FIXME: is this always safe?
return False
def coerce_to_boolean(self, env):
return self.arg.coerce_to_boolean(env).coerce_to_temp(env)
......@@ -6202,6 +6369,13 @@ class CoerceToBooleanNode(CoercionNode):
type = PyrexTypes.c_bint_type
_special_builtins = {
Builtin.list_type : 'PyList_GET_SIZE',
Builtin.tuple_type : 'PyTuple_GET_SIZE',
Builtin.bytes_type : 'PyBytes_GET_SIZE',
Builtin.unicode_type : 'PyUnicode_GET_SIZE',
}
def __init__(self, arg, env):
CoercionNode.__init__(self, arg)
if arg.type.is_pyobject:
......@@ -6223,7 +6397,16 @@ class CoerceToBooleanNode(CoercionNode):
return "(%s != 0)" % self.arg.result()
def generate_result_code(self, code):
if self.arg.type.is_pyobject:
if not self.is_temp:
return
test_func = self._special_builtins.get(self.arg.type)
if test_func is not None:
code.putln("%s = (%s != Py_None) && (%s(%s) != 0);" % (
self.result(),
self.arg.py_result(),
test_func,
self.arg.py_result()))
else:
code.putln(
"%s = __Pyx_PyObject_IsTrue(%s); %s" % (
self.result(),
......@@ -6345,6 +6528,9 @@ class ModuleRefNode(ExprNode):
def analyse_types(self, env):
pass
def may_be_none(self):
return False
def calculate_result_code(self):
return Naming.module_cname
......@@ -6401,14 +6587,14 @@ static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list); /*proto*/
""",
impl = """
static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list) {
PyObject *__import__ = 0;
PyObject *py_import = 0;
PyObject *empty_list = 0;
PyObject *module = 0;
PyObject *global_dict = 0;
PyObject *empty_dict = 0;
PyObject *list;
__import__ = __Pyx_GetAttrString(%(BUILTINS)s, "__import__");
if (!__import__)
py_import = __Pyx_GetAttrString(%(BUILTINS)s, "__import__");
if (!py_import)
goto bad;
if (from_list)
list = from_list;
......@@ -6424,11 +6610,11 @@ static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list) {
empty_dict = PyDict_New();
if (!empty_dict)
goto bad;
module = PyObject_CallFunctionObjArgs(__import__,
module = PyObject_CallFunctionObjArgs(py_import,
name, global_dict, empty_dict, list, NULL);
bad:
Py_XDECREF(empty_list);
Py_XDECREF(__import__);
Py_XDECREF(py_import);
Py_XDECREF(empty_dict);
return module;
}
......@@ -6635,11 +6821,11 @@ static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j
""" + ''.join([
"""
#define __Pyx_GetItemInt_%(type)s(o, i, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \\
__Pyx_GetItemInt_%(type)s_Fast(o, i, size <= sizeof(long)) : \\
#define __Pyx_GetItemInt_%(type)s(o, i, size, to_py_func) (((size) <= sizeof(Py_ssize_t)) ? \\
__Pyx_GetItemInt_%(type)s_Fast(o, i) : \\
__Pyx_GetItemInt_Generic(o, to_py_func(i)))
static CYTHON_INLINE PyObject *__Pyx_GetItemInt_%(type)s_Fast(PyObject *o, Py_ssize_t i, int fits_long) {
static CYTHON_INLINE PyObject *__Pyx_GetItemInt_%(type)s_Fast(PyObject *o, Py_ssize_t i) {
if (likely(o != Py_None)) {
if (likely((0 <= i) & (i < Py%(type)s_GET_SIZE(o)))) {
PyObject *r = Py%(type)s_GET_ITEM(o, i);
......@@ -6652,16 +6838,16 @@ static CYTHON_INLINE PyObject *__Pyx_GetItemInt_%(type)s_Fast(PyObject *o, Py_ss
return r;
}
}
return __Pyx_GetItemInt_Generic(o, fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i));
return __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i));
}
""" % {'type' : type_name} for type_name in ('List', 'Tuple')
]) + """
#define __Pyx_GetItemInt(o, i, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \\
__Pyx_GetItemInt_Fast(o, i, size <= sizeof(long)) : \\
#define __Pyx_GetItemInt(o, i, size, to_py_func) (((size) <= sizeof(Py_ssize_t)) ? \\
__Pyx_GetItemInt_Fast(o, i) : \\
__Pyx_GetItemInt_Generic(o, to_py_func(i)))
static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i, int fits_long) {
static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i) {
PyObject *r;
if (PyList_CheckExact(o) && ((0 <= i) & (i < PyList_GET_SIZE(o)))) {
r = PyList_GET_ITEM(o, i);
......@@ -6675,7 +6861,7 @@ static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i,
r = PySequence_GetItem(o, i);
}
else {
r = __Pyx_GetItemInt_Generic(o, fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i));
r = __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i));
}
return r;
}
......@@ -6689,8 +6875,8 @@ impl = """
setitem_int_utility_code = UtilityCode(
proto = """
#define __Pyx_SetItemInt(o, i, v, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \\
__Pyx_SetItemInt_Fast(o, i, v, size <= sizeof(long)) : \\
#define __Pyx_SetItemInt(o, i, v, size, to_py_func) (((size) <= sizeof(Py_ssize_t)) ? \\
__Pyx_SetItemInt_Fast(o, i, v) : \\
__Pyx_SetItemInt_Generic(o, to_py_func(i), v))
static CYTHON_INLINE int __Pyx_SetItemInt_Generic(PyObject *o, PyObject *j, PyObject *v) {
......@@ -6701,7 +6887,7 @@ static CYTHON_INLINE int __Pyx_SetItemInt_Generic(PyObject *o, PyObject *j, PyOb
return r;
}
static CYTHON_INLINE int __Pyx_SetItemInt_Fast(PyObject *o, Py_ssize_t i, PyObject *v, int fits_long) {
static CYTHON_INLINE int __Pyx_SetItemInt_Fast(PyObject *o, Py_ssize_t i, PyObject *v) {
if (PyList_CheckExact(o) && ((0 <= i) & (i < PyList_GET_SIZE(o)))) {
Py_INCREF(v);
Py_DECREF(PyList_GET_ITEM(o, i));
......@@ -6711,7 +6897,7 @@ static CYTHON_INLINE int __Pyx_SetItemInt_Fast(PyObject *o, Py_ssize_t i, PyObje
else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_ass_item && (likely(i >= 0)))
return PySequence_SetItem(o, i, v);
else {
PyObject *j = fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i);
PyObject *j = PyInt_FromSsize_t(i);
return __Pyx_SetItemInt_Generic(o, j, v);
}
}
......@@ -6723,8 +6909,8 @@ impl = """
delitem_int_utility_code = UtilityCode(
proto = """
#define __Pyx_DelItemInt(o, i, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \\
__Pyx_DelItemInt_Fast(o, i, size <= sizeof(long)) : \\
#define __Pyx_DelItemInt(o, i, size, to_py_func) (((size) <= sizeof(Py_ssize_t)) ? \\
__Pyx_DelItemInt_Fast(o, i) : \\
__Pyx_DelItem_Generic(o, to_py_func(i)))
static CYTHON_INLINE int __Pyx_DelItem_Generic(PyObject *o, PyObject *j) {
......@@ -6735,11 +6921,11 @@ static CYTHON_INLINE int __Pyx_DelItem_Generic(PyObject *o, PyObject *j) {
return r;
}
static CYTHON_INLINE int __Pyx_DelItemInt_Fast(PyObject *o, Py_ssize_t i, int fits_long) {
static CYTHON_INLINE int __Pyx_DelItemInt_Fast(PyObject *o, Py_ssize_t i) {
if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_ass_item && likely(i >= 0))
return PySequence_DelItem(o, i);
else {
PyObject *j = fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i);
PyObject *j = PyInt_FromSsize_t(i);
return __Pyx_DelItem_Generic(o, j);
}
}
......
......@@ -2,7 +2,7 @@
# Cython Top Level
#
import os, sys, re, codecs
import os, sys, re
if sys.version_info[:2] < (2, 3):
sys.stderr.write("Sorry, Cython requires Python 2.3 or later\n")
sys.exit(1)
......@@ -78,8 +78,8 @@ class Context(object):
self.pxds = {} # full name -> node tree
standard_include_path = os.path.abspath(
os.path.join(os.path.dirname(__file__), '..', 'Includes'))
standard_include_path = os.path.abspath(os.path.normpath(
os.path.join(os.path.dirname(__file__), os.path.pardir, 'Includes')))
self.include_directories = include_directories + [standard_include_path]
def create_pipeline(self, pxd, py=False):
......@@ -358,17 +358,17 @@ class Context(object):
for dir in dirs:
path = os.path.join(dir, dotted_filename)
if os.path.exists(path):
if Utils.path_exists(path):
return path
if not include:
package_dir = self.check_package_dir(dir, package_names)
if package_dir is not None:
path = os.path.join(package_dir, module_filename)
if os.path.exists(path):
if Utils.path_exists(path):
return path
path = os.path.join(dir, package_dir, module_name,
package_filename)
if os.path.exists(path):
if Utils.path_exists(path):
return path
return None
......@@ -381,20 +381,12 @@ class Context(object):
dir = parent
return dir
def is_package_dir(self, dir):
package_init = os.path.join(dir, "__init__.py")
return os.path.exists(package_init) or \
os.path.exists(package_init + "x") # same with .pyx
def check_package_dir(self, dir, package_names):
package_dir = os.path.join(dir, *package_names)
if not os.path.exists(package_dir):
return None
for dirname in package_names:
dir = os.path.join(dir, dirname)
if not self.is_package_dir(dir):
return None
return package_dir
return dir
def c_file_out_of_date(self, source_path):
c_path = Utils.replace_suffix(source_path, ".c")
......@@ -424,9 +416,11 @@ class Context(object):
def is_package_dir(self, dir_path):
# Return true if the given directory is a package directory.
for filename in ("__init__.py", "__init__.pyx"):
for filename in ("__init__.py",
"__init__.pyx",
"__init__.pxd"):
path = os.path.join(dir_path, filename)
if os.path.exists(path):
if Utils.path_exists(path):
return 1
def read_dependency_file(self, source_path):
......
......@@ -411,7 +411,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
for module in modules:
defined_here = module is env
modulecode.putln("/* Module declarations from %s */" %
module.qualified_name.encode("ASCII", "ignore"))
module.qualified_name)
self.generate_global_declarations(module, modulecode, defined_here)
self.generate_cfunction_predeclarations(module, modulecode, defined_here)
......@@ -525,11 +525,29 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
#if PY_MAJOR_VERSION >= 3
#define PyBaseString_Type PyUnicode_Type
#define PyStringObject PyUnicodeObject
#define PyString_Type PyUnicode_Type
#define PyString_Check PyUnicode_Check
#define PyString_CheckExact PyUnicode_CheckExact
#else
#endif
#if PY_VERSION_HEX < 0x02060000
#define PyBytesObject PyStringObject
#define PyBytes_Type PyString_Type
#define PyBytes_Check PyString_Check
#define PyBytes_CheckExact PyString_CheckExact
#define PyBytes_FromString PyString_FromString
#define PyBytes_FromStringAndSize PyString_FromStringAndSize
#define PyBytes_FromFormat PyString_FromFormat
#define PyBytes_DecodeEscape PyString_DecodeEscape
#define PyBytes_AsString PyString_AsString
#define PyBytes_AsStringAndSize PyString_AsStringAndSize
#define PyBytes_Size PyString_Size
#define PyBytes_AS_STRING PyString_AS_STRING
#define PyBytes_GET_SIZE PyString_GET_SIZE
#define PyBytes_Repr PyString_Repr
#define PyBytes_Concat PyString_Concat
#define PyBytes_ConcatAndDel PyString_ConcatAndDel
#endif
#if PY_MAJOR_VERSION >= 3
......@@ -634,11 +652,11 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
def generate_includes(self, env, cimported_modules, code):
includes = []
for filename in env.include_files:
# fake decoding of filenames to their original byte sequence
if filename[0] == '<' and filename[-1] == '>':
code.putln('#include %s' % filename)
byte_decoded_filenname = str(filename)
if byte_decoded_filenname[0] == '<' and byte_decoded_filenname[-1] == '>':
code.putln('#include %s' % byte_decoded_filenname)
else:
code.putln('#include "%s"' % filename)
code.putln('#include "%s"' % byte_decoded_filenname)
def generate_filename_table(self, code):
code.putln("")
......@@ -1537,7 +1555,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
def generate_method_table(self, env, code):
code.putln("")
code.putln(
"static struct PyMethodDef %s[] = {" %
"static PyMethodDef %s[] = {" %
env.method_table_cname)
for entry in env.pyfunc_entries:
code.put_pymethoddef(entry, ",")
......@@ -1659,7 +1677,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln("#endif")
code.putln("%s = PyTuple_New(0); %s" % (Naming.empty_tuple, code.error_goto_if_null(Naming.empty_tuple, self.pos)));
code.putln("%s = __Pyx_PyBytes_FromStringAndSize(\"\", 0); %s" % (Naming.empty_bytes, code.error_goto_if_null(Naming.empty_bytes, self.pos)));
code.putln("%s = PyBytes_FromStringAndSize(\"\", 0); %s" % (Naming.empty_bytes, code.error_goto_if_null(Naming.empty_bytes, self.pos)));
code.putln("#ifdef %s_USED" % Naming.binding_cfunc)
code.putln("if (%s_init() < 0) %s" % (Naming.binding_cfunc, code.error_goto(self.pos)))
......@@ -2177,7 +2195,11 @@ static PyTypeObject *__Pyx_ImportType(const char *module_name, const char *class
PyOS_snprintf(warning, sizeof(warning),
"%s.%s size changed, may indicate binary incompatibility",
module_name, class_name);
#if PY_VERSION_HEX < 0x02050000
PyErr_Warn(NULL, warning);
#else
PyErr_WarnEx(NULL, warning, 0);
#endif
}
else if (((PyTypeObject *)result)->tp_basicsize != size) {
PyErr_Format(PyExc_ValueError,
......
......@@ -630,6 +630,8 @@ class CArgDeclNode(Node):
# base_type CBaseTypeNode
# declarator CDeclaratorNode
# not_none boolean Tagged with 'not None'
# or_none boolean Tagged with 'or None'
# accept_none boolean Resolved boolean for not_none/or_none
# default ExprNode or None
# default_value PyObjectConst constant for default value
# annotation ExprNode or None Py3 function arg annotation
......@@ -1024,10 +1026,8 @@ class CppClassNode(CStructOrUnionDefNode):
def analyse_declarations(self, env):
scope = None
if self.attributes:
if self.attributes is not None:
scope = CppClassScope(self.name, env)
else:
self.attributes = None
base_class_types = []
for base_class_name in self.base_classes:
base_class_entry = env.lookup(base_class_name)
......@@ -1458,6 +1458,33 @@ class FuncDefNode(StatNode, BlockNode):
"Argument type '%s' is incomplete" % arg.type)
return env.declare_arg(arg.name, arg.type, arg.pos)
def generate_arg_type_test(self, arg, code):
# Generate type test for one argument.
if arg.type.typeobj_is_available():
code.globalstate.use_utility_code(arg_type_test_utility_code)
typeptr_cname = arg.type.typeptr_cname
arg_code = "((PyObject *)%s)" % arg.entry.cname
code.putln(
'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
arg_code,
typeptr_cname,
arg.accept_none,
arg.name,
arg.type.is_builtin_type,
code.error_goto(arg.pos)))
else:
error(arg.pos, "Cannot test type of extern C class "
"without type object name specification")
def generate_arg_none_check(self, arg, code):
# Generate None check for one argument.
code.globalstate.use_utility_code(arg_type_test_utility_code)
code.putln('if (unlikely(((PyObject *)%s) == Py_None)) {' % arg.entry.cname)
code.putln('''PyErr_Format(PyExc_TypeError, "Argument '%s' must not be None"); %s''' % (
arg.name,
code.error_goto(arg.pos)))
code.putln('}')
def generate_wrapper_functions(self, code):
pass
......@@ -1709,23 +1736,8 @@ class CFuncDefNode(FuncDefNode):
for arg in self.type.args:
if arg.needs_type_test:
self.generate_arg_type_test(arg, code)
def generate_arg_type_test(self, arg, code):
# Generate type test for one argument.
if arg.type.typeobj_is_available():
typeptr_cname = arg.type.typeptr_cname
arg_code = "((PyObject *)%s)" % arg.cname
code.putln(
'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
arg_code,
typeptr_cname,
not arg.not_none,
arg.name,
type.is_builtin_type,
code.error_goto(arg.pos)))
else:
error(arg.pos, "Cannot test type of extern C class "
"without type object name specification")
elif arg.type.is_pyobject and not arg.accept_none:
self.generate_arg_none_check(arg, code)
def error_value(self):
if self.return_type.is_pyobject:
......@@ -1921,6 +1933,7 @@ class DefNode(FuncDefNode):
def analyse_argument_types(self, env):
directive_locals = self.directive_locals = env.directives['locals']
allow_none_for_extension_args = env.directives['allow_none_for_extension_args']
for arg in self.args:
if hasattr(arg, 'name'):
type = arg.type
......@@ -1949,12 +1962,29 @@ class DefNode(FuncDefNode):
arg.needs_conversion = 0
arg.needs_type_test = 0
arg.is_generic = 1
if arg.not_none and not arg.type.is_extension_type:
error(self.pos,
"Only extension type arguments can have 'not None'")
if arg.type.is_pyobject:
if arg.or_none:
arg.accept_none = True
elif arg.not_none:
arg.accept_none = False
elif arg.type.is_extension_type or arg.type.is_builtin_type:
if arg.default and arg.default.constant_result is None:
# special case: def func(MyType obj = None)
arg.accept_none = True
else:
# default depends on compiler directive
arg.accept_none = allow_none_for_extension_args
else:
# probably just a plain 'object'
arg.accept_none = True
else:
arg.accept_none = True # won't be used, but must be there
if arg.not_none:
error(arg.pos, "Only Python type arguments can have 'not None'")
if arg.or_none:
error(arg.pos, "Only Python type arguments can have 'or None'")
def analyse_signature(self, env):
any_type_tests_needed = 0
if self.entry.is_special:
self.entry.trivial_signature = len(self.args) == 1 and not (self.star_arg or self.starstar_arg)
elif not env.directives['always_allow_keywords'] and not (self.star_arg or self.starstar_arg):
......@@ -1999,7 +2029,6 @@ class DefNode(FuncDefNode):
if not arg.type.same_as(arg.hdr_type):
if arg.hdr_type.is_pyobject and arg.type.is_pyobject:
arg.needs_type_test = 1
any_type_tests_needed = 1
else:
arg.needs_conversion = 1
if arg.needs_conversion:
......@@ -2017,9 +2046,6 @@ class DefNode(FuncDefNode):
if arg.is_generic and \
(arg.type.is_extension_type or arg.type.is_builtin_type):
arg.needs_type_test = 1
any_type_tests_needed = 1
if any_type_tests_needed:
env.use_utility_code(arg_type_test_utility_code)
def bad_signature(self):
sig = self.entry.signature
......@@ -2175,7 +2201,11 @@ class DefNode(FuncDefNode):
code.putln("%s; /*proto*/" % header)
if proto_only:
return
if self.entry.doc and Options.docstrings:
if (Options.docstrings and self.entry.doc and
(not self.entry.is_special or
self.entry.signature.method_flags()) and
not self.entry.scope.is_property_scope
):
docstr = self.entry.doc
if docstr.is_unicode:
docstr = docstr.utf8encode()
......@@ -2714,10 +2744,13 @@ class DefNode(FuncDefNode):
func = new_type.from_py_function
# copied from CoerceFromPyTypeNode
if func:
code.putln("%s = %s(%s); %s" % (
arg.entry.cname,
func,
arg.hdr_cname,
lhs = arg.entry.cname
rhs = "%s(%s)" % (func, arg.hdr_cname)
if new_type.is_enum:
rhs = PyrexTypes.typecast(new_type, PyrexTypes.c_long_type, rhs)
code.putln("%s = %s; %s" % (
lhs,
rhs,
code.error_goto_if(new_type.error_condition(arg.entry.cname), arg.pos)))
else:
error(arg.pos,
......@@ -2746,23 +2779,8 @@ class DefNode(FuncDefNode):
for arg in self.args:
if arg.needs_type_test:
self.generate_arg_type_test(arg, code)
def generate_arg_type_test(self, arg, code):
# Generate type test for one argument.
if arg.type.typeobj_is_available():
typeptr_cname = arg.type.typeptr_cname
arg_code = "((PyObject *)%s)" % arg.entry.cname
code.putln(
'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
arg_code,
typeptr_cname,
not arg.not_none,
arg.name,
arg.type.is_builtin_type,
code.error_goto(arg.pos)))
else:
error(arg.pos, "Cannot test type of extern C class "
"without type object name specification")
elif not arg.accept_none and arg.type.is_pyobject:
self.generate_arg_none_check(arg, code)
def error_value(self):
return self.entry.signature.error_value
......
......@@ -95,7 +95,11 @@ class IterationTransform(Visitor.VisitorTransform):
return self._transform_carray_iteration(node, iterator)
elif iterator.type.is_array:
return self._transform_carray_iteration(node, iterator)
elif not isinstance(iterator, ExprNodes.SimpleCallNode):
elif iterator.type in (Builtin.bytes_type, Builtin.unicode_type):
return self._transform_string_iteration(node, iterator)
# the rest is based on function calls
if not isinstance(iterator, ExprNodes.SimpleCallNode):
return node
function = iterator.function
......@@ -132,6 +136,70 @@ class IterationTransform(Visitor.VisitorTransform):
return node
PyUnicode_AS_UNICODE_func_type = PyrexTypes.CFuncType(
PyrexTypes.c_py_unicode_ptr_type, [
PyrexTypes.CFuncTypeArg("s", Builtin.unicode_type, None)
])
PyUnicode_GET_SIZE_func_type = PyrexTypes.CFuncType(
PyrexTypes.c_py_ssize_t_type, [
PyrexTypes.CFuncTypeArg("s", Builtin.unicode_type, None)
])
PyBytes_AS_STRING_func_type = PyrexTypes.CFuncType(
PyrexTypes.c_char_ptr_type, [
PyrexTypes.CFuncTypeArg("s", Builtin.bytes_type, None)
])
PyBytes_GET_SIZE_func_type = PyrexTypes.CFuncType(
PyrexTypes.c_py_ssize_t_type, [
PyrexTypes.CFuncTypeArg("s", Builtin.bytes_type, None)
])
def _transform_string_iteration(self, node, slice_node):
if not node.target.type.is_int:
return node
if slice_node.type is Builtin.unicode_type:
unpack_func = "PyUnicode_AS_UNICODE"
len_func = "PyUnicode_GET_SIZE"
unpack_func_type = self.PyUnicode_AS_UNICODE_func_type
len_func_type = self.PyUnicode_GET_SIZE_func_type
elif slice_node.type is Builtin.bytes_type:
unpack_func = "PyBytes_AS_STRING"
unpack_func_type = self.PyBytes_AS_STRING_func_type
len_func = "PyBytes_GET_SIZE"
len_func_type = self.PyBytes_GET_SIZE_func_type
else:
return node
unpack_temp_node = UtilNodes.LetRefNode(
slice_node.as_none_safe_node("'NoneType' is not iterable"))
slice_base_node = ExprNodes.PythonCapiCallNode(
slice_node.pos, unpack_func, unpack_func_type,
args = [unpack_temp_node],
is_temp = 0,
)
len_node = ExprNodes.PythonCapiCallNode(
slice_node.pos, len_func, len_func_type,
args = [unpack_temp_node],
is_temp = 0,
)
return UtilNodes.LetNode(
unpack_temp_node,
self._transform_carray_iteration(
node,
ExprNodes.SliceIndexNode(
slice_node.pos,
base = slice_base_node,
start = None,
step = None,
stop = len_node,
type = slice_base_node.type,
is_temp = 1,
)))
def _transform_carray_iteration(self, node, slice_node):
if isinstance(slice_node, ExprNodes.SliceIndexNode):
slice_base = slice_node.base
......@@ -166,7 +234,7 @@ class IterationTransform(Visitor.VisitorTransform):
stop_ptr_node = ExprNodes.AddNode(
stop.pos,
operand1=carray_ptr,
operand1=ExprNodes.CloneNode(carray_ptr),
operator='+',
operand2=stop,
type=ptr_type
......@@ -507,7 +575,9 @@ class SwitchTransform(Visitor.VisitorTransform):
The requirement is that every clause be an (or of) var == value, where the var
is common among all clauses and both var and value are ints.
"""
def extract_conditions(self, cond):
NO_MATCH = (None, None, None)
def extract_conditions(self, cond, allow_not_in):
while True:
if isinstance(cond, ExprNodes.CoerceToTempNode):
cond = cond.arg
......@@ -519,55 +589,185 @@ class SwitchTransform(Visitor.VisitorTransform):
else:
break
if (isinstance(cond, ExprNodes.PrimaryCmpNode)
and cond.cascade is None
and cond.operator == '=='
and not cond.is_python_comparison()):
if isinstance(cond, ExprNodes.PrimaryCmpNode):
if cond.cascade is None and not cond.is_python_comparison():
if cond.operator == '==':
not_in = False
elif allow_not_in and cond.operator == '!=':
not_in = True
elif cond.is_c_string_contains() and \
isinstance(cond.operand2, (ExprNodes.UnicodeNode, ExprNodes.BytesNode)):
not_in = cond.operator == 'not_in'
if not_in and not allow_not_in:
return self.NO_MATCH
# this looks somewhat silly, but it does the right
# checks for NameNode and AttributeNode
if is_common_value(cond.operand1, cond.operand1):
return not_in, cond.operand1, self.extract_in_string_conditions(cond.operand2)
else:
return self.NO_MATCH
else:
return self.NO_MATCH
# this looks somewhat silly, but it does the right
# checks for NameNode and AttributeNode
if is_common_value(cond.operand1, cond.operand1):
if cond.operand2.is_literal:
return cond.operand1, [cond.operand2]
elif hasattr(cond.operand2, 'entry') and cond.operand2.entry and cond.operand2.entry.is_const:
return cond.operand1, [cond.operand2]
return not_in, cond.operand1, [cond.operand2]
elif getattr(cond.operand2, 'entry', None) \
and cond.operand2.entry.is_const:
return not_in, cond.operand1, [cond.operand2]
if is_common_value(cond.operand2, cond.operand2):
if cond.operand1.is_literal:
return cond.operand2, [cond.operand1]
elif hasattr(cond.operand1, 'entry') and cond.operand1.entry and cond.operand1.entry.is_const:
return cond.operand2, [cond.operand1]
elif (isinstance(cond, ExprNodes.BoolBinopNode)
and cond.operator == 'or'):
t1, c1 = self.extract_conditions(cond.operand1)
t2, c2 = self.extract_conditions(cond.operand2)
if is_common_value(t1, t2):
return t1, c1+c2
return None, None
return not_in, cond.operand2, [cond.operand1]
elif getattr(cond.operand1, 'entry', None) \
and cond.operand1.entry.is_const:
return not_in, cond.operand2, [cond.operand1]
elif isinstance(cond, ExprNodes.BoolBinopNode):
if cond.operator == 'or' or (allow_not_in and cond.operator == 'and'):
allow_not_in = (cond.operator == 'and')
not_in_1, t1, c1 = self.extract_conditions(cond.operand1, allow_not_in)
not_in_2, t2, c2 = self.extract_conditions(cond.operand2, allow_not_in)
if t1 is not None and not_in_1 == not_in_2 and is_common_value(t1, t2):
if (not not_in_1) or allow_not_in:
return not_in_1, t1, c1+c2
return self.NO_MATCH
def extract_in_string_conditions(self, string_literal):
if isinstance(string_literal, ExprNodes.UnicodeNode):
charvals = map(ord, set(string_literal.value))
charvals.sort()
return [ ExprNodes.IntNode(string_literal.pos, value=str(charval),
constant_result=charval)
for charval in charvals ]
else:
# this is a bit tricky as Py3's bytes type returns
# integers on iteration, whereas Py2 returns 1-char byte
# strings
characters = string_literal.value
characters = list(set([ characters[i:i+1] for i in range(len(characters)) ]))
characters.sort()
return [ ExprNodes.CharNode(string_literal.pos, value=charval,
constant_result=charval)
for charval in characters ]
def extract_common_conditions(self, common_var, condition, allow_not_in):
not_in, var, conditions = self.extract_conditions(condition, allow_not_in)
if var is None:
return self.NO_MATCH
elif common_var is not None and not is_common_value(var, common_var):
return self.NO_MATCH
elif not var.type.is_int or sum([not cond.type.is_int for cond in conditions]):
return self.NO_MATCH
return not_in, var, conditions
def has_duplicate_values(self, condition_values):
# duplicated values don't work in a switch statement
seen = set()
for value in condition_values:
if value.constant_result is not ExprNodes.not_a_constant:
if value.constant_result in seen:
return True
seen.add(value.constant_result)
else:
# this isn't completely safe as we don't know the
# final C value, but this is about the best we can do
seen.add(getattr(getattr(value, 'entry', None), 'cname'))
return False
def visit_IfStatNode(self, node):
self.visitchildren(node)
common_var = None
case_count = 0
cases = []
for if_clause in node.if_clauses:
var, conditions = self.extract_conditions(if_clause.condition)
if var is None:
return node
elif common_var is not None and not is_common_value(var, common_var):
return node
elif not var.type.is_int or sum([not cond.type.is_int for cond in conditions]):
_, common_var, conditions = self.extract_common_conditions(
common_var, if_clause.condition, False)
if common_var is None:
self.visitchildren(node)
return node
else:
common_var = var
case_count += len(conditions)
cases.append(Nodes.SwitchCaseNode(pos = if_clause.pos,
conditions = conditions,
body = if_clause.body))
if case_count < 2:
if sum([ len(case.conditions) for case in cases ]) < 2:
self.visitchildren(node)
return node
if self.has_duplicate_values(sum([case.conditions for case in cases], [])):
self.visitchildren(node)
return node
common_var = unwrap_node(common_var)
return Nodes.SwitchStatNode(pos = node.pos,
switch_node = Nodes.SwitchStatNode(pos = node.pos,
test = common_var,
cases = cases,
else_clause = node.else_clause)
return switch_node
def visit_CondExprNode(self, node):
not_in, common_var, conditions = self.extract_common_conditions(
None, node.test, True)
if common_var is None \
or len(conditions) < 2 \
or self.has_duplicate_values(conditions):
self.visitchildren(node)
return node
return self.build_simple_switch_statement(
node, common_var, conditions, not_in,
node.true_val, node.false_val)
def visit_BoolBinopNode(self, node):
not_in, common_var, conditions = self.extract_common_conditions(
None, node, True)
if common_var is None \
or len(conditions) < 2 \
or self.has_duplicate_values(conditions):
self.visitchildren(node)
return node
return self.build_simple_switch_statement(
node, common_var, conditions, not_in,
ExprNodes.BoolNode(node.pos, value=True, constant_result=True),
ExprNodes.BoolNode(node.pos, value=False, constant_result=False))
def visit_PrimaryCmpNode(self, node):
not_in, common_var, conditions = self.extract_common_conditions(
None, node, True)
if common_var is None \
or len(conditions) < 2 \
or self.has_duplicate_values(conditions):
self.visitchildren(node)
return node
return self.build_simple_switch_statement(
node, common_var, conditions, not_in,
ExprNodes.BoolNode(node.pos, value=True, constant_result=True),
ExprNodes.BoolNode(node.pos, value=False, constant_result=False))
def build_simple_switch_statement(self, node, common_var, conditions,
not_in, true_val, false_val):
result_ref = UtilNodes.ResultRefNode(node)
true_body = Nodes.SingleAssignmentNode(
node.pos,
lhs = result_ref,
rhs = true_val,
first = True)
false_body = Nodes.SingleAssignmentNode(
node.pos,
lhs = result_ref,
rhs = false_val,
first = True)
if not_in:
true_body, false_body = false_body, true_body
cases = [Nodes.SwitchCaseNode(pos = node.pos,
conditions = conditions,
body = true_body)]
common_var = unwrap_node(common_var)
switch_node = Nodes.SwitchStatNode(pos = node.pos,
test = common_var,
cases = cases,
else_clause = false_body)
return UtilNodes.TempResultFromStatNode(result_ref, switch_node)
visit_Node = Visitor.VisitorTransform.recurse_to_children
......@@ -591,7 +791,9 @@ class FlattenInListTransform(Visitor.VisitorTransform, SkipDeclarations):
else:
return node
if not isinstance(node.operand2, (ExprNodes.TupleNode, ExprNodes.ListNode)):
if not isinstance(node.operand2, (ExprNodes.TupleNode,
ExprNodes.ListNode,
ExprNodes.SetNode)):
return node
args = node.operand2.args
......@@ -778,7 +980,7 @@ class EarlyReplaceBuiltinCalls(Visitor.EnvTransform):
def _function_is_builtin_name(self, function):
if not function.is_name:
return False
entry = self.env_stack[-1].lookup(function.name)
entry = self.current_env().lookup(function.name)
if not entry or getattr(entry, 'scope', None) is not Builtin.builtin_scope:
return False
return True
......@@ -907,6 +1109,8 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
arg_tuple = node.positional_args
if not isinstance(arg_tuple, ExprNodes.TupleNode):
return node
if node.starstar_arg:
return node
args = arg_tuple.args
return self._dispatch_to_handler(
node, function, args, node.keyword_args)
......@@ -937,6 +1141,27 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
return node
return node.arg
def visit_TypecastNode(self, node):
"""
Drop redundant type casts.
"""
self.visitchildren(node)
if node.type == node.operand.type:
return node.operand
return node
def visit_CoerceToBooleanNode(self, node):
"""Drop redundant conversion nodes after tree changes.
"""
self.visitchildren(node)
arg = node.arg
if isinstance(arg, ExprNodes.PyTypeTestNode):
arg = arg.arg
if isinstance(arg, ExprNodes.CoerceToPyTypeNode):
if arg.type in (PyrexTypes.py_object_type, Builtin.bool_type):
return arg.arg.coerce_to_boolean(self.current_env())
return node
def visit_CoerceFromPyTypeNode(self, node):
"""Drop redundant conversion nodes after tree changes.
......@@ -951,11 +1176,20 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
if node.type == arg.type:
return arg
else:
return arg.coerce_to(node.type, self.env_stack[-1])
if not isinstance(arg, ExprNodes.SimpleCallNode):
return node
if not (node.type.is_int or node.type.is_float):
return arg.coerce_to(node.type, self.current_env())
if isinstance(arg, ExprNodes.PyTypeTestNode):
arg = arg.arg
if isinstance(arg, ExprNodes.CoerceToPyTypeNode):
if arg.type is PyrexTypes.py_object_type:
if node.type.assignable_from(arg.arg.type):
# completely redundant C->Py->C coercion
return arg.arg.coerce_to(node.type, self.current_env())
if isinstance(arg, ExprNodes.SimpleCallNode):
if node.type.is_int or node.type.is_float:
return self._optimise_numeric_cast_call(node, arg)
return node
def _optimise_numeric_cast_call(self, node, arg):
function = arg.function
if not isinstance(function, ExprNodes.NameNode) \
or not function.type.is_builtin_type \
......@@ -1079,8 +1313,7 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
return node
arg = pos_args[0]
if arg.type is Builtin.dict_type:
arg = ExprNodes.NoneCheckNode(
arg, "PyExc_TypeError", "'NoneType' is not iterable")
arg = arg.as_none_safe_node("'NoneType' is not iterable")
return ExprNodes.PythonCapiCallNode(
node.pos, "PyDict_Copy", self.PyDict_Copy_func_type,
args = [arg],
......@@ -1103,8 +1336,7 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
return node
if not isinstance(list_arg, (ExprNodes.ComprehensionNode,
ExprNodes.ListNode)):
pos_args[0] = ExprNodes.NoneCheckNode(
list_arg, "PyExc_TypeError",
pos_args[0] = list_arg.as_none_safe_node(
"'NoneType' object is not iterable")
return ExprNodes.PythonCapiCallNode(
......@@ -1126,8 +1358,12 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
"""
# Note: this requires the float() function to be typed as
# returning a C 'double'
if len(pos_args) != 1:
self._error_wrong_arg_count('float', node, pos_args, 1)
if len(pos_args) == 0:
return ExprNode.FloatNode(
node, value="0.0", constant_result=0.0
).coerce_to(Builtin.float_type, self.current_env())
elif len(pos_args) != 1:
self._error_wrong_arg_count('float', node, pos_args, '0 or 1')
return node
func_arg = pos_args[0]
if isinstance(func_arg, ExprNodes.CoerceToPyTypeNode):
......@@ -1145,6 +1381,19 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
utility_code = pyobject_as_double_utility_code,
py_name = "float")
def _handle_simple_function_bool(self, node, pos_args):
"""Transform bool(x) into a type coercion to a boolean.
"""
if len(pos_args) == 0:
return ExprNodes.BoolNode(
node.pos, value=False, constant_result=False
).coerce_to(Builtin.bool_type, self.current_env())
elif len(pos_args) != 1:
self._error_wrong_arg_count('bool', node, pos_args, '0 or 1')
return node
return pos_args[0].coerce_to_boolean(
self.current_env()).coerce_to_pyobject(self.current_env())
### builtin functions
PyObject_GetAttr2_func_type = PyrexTypes.CFuncType(
......@@ -1211,8 +1460,25 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
PyrexTypes.CFuncTypeArg("bytes", PyrexTypes.c_char_ptr_type, None)
])
PyObject_Size_func_type = PyrexTypes.CFuncType(
PyrexTypes.c_py_ssize_t_type, [
PyrexTypes.CFuncTypeArg("obj", PyrexTypes.py_object_type, None)
])
_map_to_capi_len_function = {
Builtin.unicode_type : "PyUnicode_GET_SIZE",
Builtin.str_type : "Py_SIZE", # works in Py2 and Py3
Builtin.bytes_type : "PyBytes_GET_SIZE",
Builtin.list_type : "PyList_GET_SIZE",
Builtin.tuple_type : "PyTuple_GET_SIZE",
Builtin.dict_type : "PyDict_Size",
Builtin.set_type : "PySet_Size",
Builtin.frozenset_type : "PySet_Size",
}.get
def _handle_simple_function_len(self, node, pos_args):
"""Replace len(char*) by the equivalent call to strlen().
"""Replace len(char*) by the equivalent call to strlen() and
len(known_builtin_type) by an equivalent C-API call.
"""
if len(pos_args) != 1:
self._error_wrong_arg_count('len', node, pos_args, 1)
......@@ -1220,22 +1486,28 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
arg = pos_args[0]
if isinstance(arg, ExprNodes.CoerceToPyTypeNode):
arg = arg.arg
if not arg.type.is_string:
return node
if not node.type.is_numeric:
# this optimisation only works when we already replaced
# len() by PyObject_Length() which returns a Py_ssize_t
# instead of a Python object, so we can return a plain
# size_t instead without caring about Python object
# conversion etc.
return node
node = ExprNodes.PythonCapiCallNode(
if arg.type.is_string:
new_node = ExprNodes.PythonCapiCallNode(
node.pos, "strlen", self.Pyx_strlen_func_type,
args = [arg],
is_temp = node.is_temp,
utility_code = include_string_h_utility_code
)
utility_code = include_string_h_utility_code)
elif arg.type.is_pyobject:
cfunc_name = self._map_to_capi_len_function(arg.type)
if cfunc_name is None:
return node
if not arg.is_literal:
arg = arg.as_none_safe_node(
"object of type 'NoneType' has no len()")
new_node = ExprNodes.PythonCapiCallNode(
node.pos, cfunc_name, self.PyObject_Size_func_type,
args = [arg],
is_temp = node.is_temp)
else:
return node
if node.type not in (PyrexTypes.c_size_t_type, PyrexTypes.c_py_ssize_t_type):
new_node = new_node.coerce_to(node.type, self.current_env())
return new_node
Pyx_Type_func_type = PyrexTypes.CFuncType(
Builtin.type_type, [
......@@ -1289,8 +1561,7 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
if not type_arg.type_entry:
# arbitrary variable, needs a None check for safety
type_arg = ExprNodes.NoneCheckNode(
type_arg, "PyExc_TypeError",
type_arg = type_arg.as_none_safe_node(
"object.__new__(X): X is not a type object (NoneType)")
return ExprNodes.PythonCapiCallNode(
......@@ -1405,8 +1676,7 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
PyrexTypes.CFuncTypeArg("dict", PyrexTypes.py_object_type, None),
PyrexTypes.CFuncTypeArg("key", PyrexTypes.py_object_type, None),
PyrexTypes.CFuncTypeArg("default", PyrexTypes.py_object_type, None),
],
exception_value = "NULL")
])
def _handle_simple_method_dict_get(self, node, args, is_unbound_method):
"""Replace dict.get() by a call to PyDict_GetItem().
......@@ -1422,19 +1692,206 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
'get', is_unbound_method, args,
utility_code = dict_getitem_default_utility_code)
### unicode type methods
PyUnicode_Splitlines_func_type = PyrexTypes.CFuncType(
Builtin.list_type, [
PyrexTypes.CFuncTypeArg("str", Builtin.unicode_type, None),
PyrexTypes.CFuncTypeArg("keepends", PyrexTypes.c_bint_type, None),
])
def _handle_simple_method_unicode_splitlines(self, node, args, is_unbound_method):
"""Replace unicode.splitlines(...) by a direct call to the
corresponding C-API function.
"""
if len(args) not in (1,2):
self._error_wrong_arg_count('unicode.splitlines', node, args, "1 or 2")
return node
self._inject_bint_default_argument(node, args, 1, False)
return self._substitute_method_call(
node, "PyUnicode_Splitlines", self.PyUnicode_Splitlines_func_type,
'splitlines', is_unbound_method, args)
PyUnicode_Join_func_type = PyrexTypes.CFuncType(
Builtin.unicode_type, [
PyrexTypes.CFuncTypeArg("sep", Builtin.unicode_type, None),
PyrexTypes.CFuncTypeArg("iterable", PyrexTypes.py_object_type, None),
])
def _handle_simple_method_unicode_join(self, node, args, is_unbound_method):
"""Replace unicode.join(...) by a direct call to the
corresponding C-API function.
"""
if len(args) != 2:
self._error_wrong_arg_count('unicode.join', node, args, 2)
return node
return self._substitute_method_call(
node, "PyUnicode_Join", self.PyUnicode_Join_func_type,
'join', is_unbound_method, args)
PyUnicode_Split_func_type = PyrexTypes.CFuncType(
Builtin.list_type, [
PyrexTypes.CFuncTypeArg("str", Builtin.unicode_type, None),
PyrexTypes.CFuncTypeArg("sep", PyrexTypes.py_object_type, None),
PyrexTypes.CFuncTypeArg("maxsplit", PyrexTypes.c_py_ssize_t_type, None),
]
)
def _handle_simple_method_unicode_split(self, node, args, is_unbound_method):
"""Replace unicode.split(...) by a direct call to the
corresponding C-API function.
"""
if len(args) not in (1,2,3):
self._error_wrong_arg_count('unicode.split', node, args, "1-3")
return node
if len(args) < 2:
args.append(ExprNodes.NullNode(node.pos))
self._inject_int_default_argument(
node, args, 2, PyrexTypes.c_py_ssize_t_type, "-1")
return self._substitute_method_call(
node, "PyUnicode_Split", self.PyUnicode_Split_func_type,
'split', is_unbound_method, args)
PyUnicode_Tailmatch_func_type = PyrexTypes.CFuncType(
PyrexTypes.c_bint_type, [
PyrexTypes.CFuncTypeArg("str", Builtin.unicode_type, None),
PyrexTypes.CFuncTypeArg("substring", PyrexTypes.py_object_type, None),
PyrexTypes.CFuncTypeArg("start", PyrexTypes.c_py_ssize_t_type, None),
PyrexTypes.CFuncTypeArg("end", PyrexTypes.c_py_ssize_t_type, None),
PyrexTypes.CFuncTypeArg("direction", PyrexTypes.c_int_type, None),
],
exception_value = '-1')
def _handle_simple_method_unicode_endswith(self, node, args, is_unbound_method):
return self._inject_unicode_tailmatch(
node, args, is_unbound_method, 'endswith', +1)
def _handle_simple_method_unicode_startswith(self, node, args, is_unbound_method):
return self._inject_unicode_tailmatch(
node, args, is_unbound_method, 'startswith', -1)
def _inject_unicode_tailmatch(self, node, args, is_unbound_method,
method_name, direction):
"""Replace unicode.startswith(...) and unicode.endswith(...)
by a direct call to the corresponding C-API function.
"""
if len(args) not in (2,3,4):
self._error_wrong_arg_count('unicode.%s' % method_name, node, args, "2-4")
return node
self._inject_int_default_argument(
node, args, 2, PyrexTypes.c_py_ssize_t_type, "0")
self._inject_int_default_argument(
node, args, 3, PyrexTypes.c_py_ssize_t_type, "PY_SSIZE_T_MAX")
args.append(ExprNodes.IntNode(
node.pos, value=str(direction), type=PyrexTypes.c_int_type))
method_call = self._substitute_method_call(
node, "__Pyx_PyUnicode_Tailmatch", self.PyUnicode_Tailmatch_func_type,
method_name, is_unbound_method, args,
utility_code = unicode_tailmatch_utility_code)
return method_call.coerce_to(Builtin.bool_type, self.current_env())
PyUnicode_Find_func_type = PyrexTypes.CFuncType(
PyrexTypes.c_py_ssize_t_type, [
PyrexTypes.CFuncTypeArg("str", Builtin.unicode_type, None),
PyrexTypes.CFuncTypeArg("substring", PyrexTypes.py_object_type, None),
PyrexTypes.CFuncTypeArg("start", PyrexTypes.c_py_ssize_t_type, None),
PyrexTypes.CFuncTypeArg("end", PyrexTypes.c_py_ssize_t_type, None),
PyrexTypes.CFuncTypeArg("direction", PyrexTypes.c_int_type, None),
],
exception_value = '-2')
def _handle_simple_method_unicode_find(self, node, args, is_unbound_method):
return self._inject_unicode_find(
node, args, is_unbound_method, 'find', +1)
def _handle_simple_method_unicode_rfind(self, node, args, is_unbound_method):
return self._inject_unicode_find(
node, args, is_unbound_method, 'rfind', -1)
def _inject_unicode_find(self, node, args, is_unbound_method,
method_name, direction):
"""Replace unicode.find(...) and unicode.rfind(...) by a
direct call to the corresponding C-API function.
"""
if len(args) not in (2,3,4):
self._error_wrong_arg_count('unicode.%s' % method_name, node, args, "2-4")
return node
self._inject_int_default_argument(
node, args, 2, PyrexTypes.c_py_ssize_t_type, "0")
self._inject_int_default_argument(
node, args, 3, PyrexTypes.c_py_ssize_t_type, "PY_SSIZE_T_MAX")
args.append(ExprNodes.IntNode(
node.pos, value=str(direction), type=PyrexTypes.c_int_type))
method_call = self._substitute_method_call(
node, "PyUnicode_Find", self.PyUnicode_Find_func_type,
method_name, is_unbound_method, args)
return method_call.coerce_to_pyobject(self.current_env())
PyUnicode_Count_func_type = PyrexTypes.CFuncType(
PyrexTypes.c_py_ssize_t_type, [
PyrexTypes.CFuncTypeArg("str", Builtin.unicode_type, None),
PyrexTypes.CFuncTypeArg("substring", PyrexTypes.py_object_type, None),
PyrexTypes.CFuncTypeArg("start", PyrexTypes.c_py_ssize_t_type, None),
PyrexTypes.CFuncTypeArg("end", PyrexTypes.c_py_ssize_t_type, None),
],
exception_value = '-1')
def _handle_simple_method_unicode_count(self, node, args, is_unbound_method):
"""Replace unicode.count(...) by a direct call to the
corresponding C-API function.
"""
if len(args) not in (2,3,4):
self._error_wrong_arg_count('unicode.count', node, args, "2-4")
return node
self._inject_int_default_argument(
node, args, 2, PyrexTypes.c_py_ssize_t_type, "0")
self._inject_int_default_argument(
node, args, 3, PyrexTypes.c_py_ssize_t_type, "PY_SSIZE_T_MAX")
method_call = self._substitute_method_call(
node, "PyUnicode_Count", self.PyUnicode_Count_func_type,
'count', is_unbound_method, args)
return method_call.coerce_to_pyobject(self.current_env())
PyUnicode_Replace_func_type = PyrexTypes.CFuncType(
Builtin.unicode_type, [
PyrexTypes.CFuncTypeArg("str", Builtin.unicode_type, None),
PyrexTypes.CFuncTypeArg("substring", PyrexTypes.py_object_type, None),
PyrexTypes.CFuncTypeArg("replstr", PyrexTypes.py_object_type, None),
PyrexTypes.CFuncTypeArg("maxcount", PyrexTypes.c_py_ssize_t_type, None),
])
def _handle_simple_method_unicode_replace(self, node, args, is_unbound_method):
"""Replace unicode.replace(...) by a direct call to the
corresponding C-API function.
"""
if len(args) not in (3,4):
self._error_wrong_arg_count('unicode.replace', node, args, "3-4")
return node
self._inject_int_default_argument(
node, args, 3, PyrexTypes.c_py_ssize_t_type, "-1")
return self._substitute_method_call(
node, "PyUnicode_Replace", self.PyUnicode_Replace_func_type,
'replace', is_unbound_method, args)
PyUnicode_AsEncodedString_func_type = PyrexTypes.CFuncType(
Builtin.bytes_type, [
PyrexTypes.CFuncTypeArg("obj", Builtin.unicode_type, None),
PyrexTypes.CFuncTypeArg("encoding", PyrexTypes.c_char_ptr_type, None),
PyrexTypes.CFuncTypeArg("errors", PyrexTypes.c_char_ptr_type, None),
],
exception_value = "NULL")
])
PyUnicode_AsXyzString_func_type = PyrexTypes.CFuncType(
Builtin.bytes_type, [
PyrexTypes.CFuncTypeArg("obj", Builtin.unicode_type, None),
],
exception_value = "NULL")
])
_special_encodings = ['UTF8', 'UTF16', 'Latin1', 'ASCII',
'unicode_escape', 'raw_unicode_escape']
......@@ -1498,8 +1955,7 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
PyrexTypes.CFuncTypeArg("string", PyrexTypes.c_char_ptr_type, None),
PyrexTypes.CFuncTypeArg("size", PyrexTypes.c_py_ssize_t_type, None),
PyrexTypes.CFuncTypeArg("errors", PyrexTypes.c_char_ptr_type, None),
],
exception_value = "NULL")
])
PyUnicode_Decode_func_type = PyrexTypes.CFuncType(
Builtin.unicode_type, [
......@@ -1507,8 +1963,7 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
PyrexTypes.CFuncTypeArg("size", PyrexTypes.c_py_ssize_t_type, None),
PyrexTypes.CFuncTypeArg("encoding", PyrexTypes.c_char_ptr_type, None),
PyrexTypes.CFuncTypeArg("errors", PyrexTypes.c_char_ptr_type, None),
],
exception_value = "NULL")
])
def _handle_simple_method_bytes_decode(self, node, args, is_unbound_method):
"""Replace char*.decode() by a direct C-API call to the
......@@ -1529,7 +1984,7 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
start = None
else:
if start.type.is_pyobject:
start = start.coerce_to(PyrexTypes.c_py_ssize_t_type, self.env_stack[-1])
start = start.coerce_to(PyrexTypes.c_py_ssize_t_type, self.current_env())
if stop:
start = UtilNodes.LetRefNode(start)
temps.append(start)
......@@ -1541,7 +1996,7 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
type=string_node.type
)
if stop and stop.type.is_pyobject:
stop = stop.coerce_to(PyrexTypes.c_py_ssize_t_type, self.env_stack[-1])
stop = stop.coerce_to(PyrexTypes.c_py_ssize_t_type, self.current_env())
elif isinstance(args[0], ExprNodes.CoerceToPyTypeNode) \
and args[0].arg.type.is_string:
# use strlen() to find the string length, just as CPython would
......@@ -1560,7 +2015,7 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
args = [string_node],
is_temp = False,
utility_code = include_string_h_utility_code,
).coerce_to(PyrexTypes.c_py_ssize_t_type, self.env_stack[-1])
).coerce_to(PyrexTypes.c_py_ssize_t_type, self.current_env())
elif start:
stop = ExprNodes.SubNode(
pos = stop.pos,
......@@ -1614,6 +2069,9 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
return None
def _unpack_encoding_and_error_mode(self, pos, args):
null_node = ExprNodes.NullNode(pos)
if len(args) >= 2:
encoding_node = args[1]
if isinstance(encoding_node, ExprNodes.CoerceToPyTypeNode):
encoding_node = encoding_node.arg
......@@ -1626,8 +2084,10 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
encoding = None
else:
return None
else:
encoding = None
encoding_node = null_node
null_node = ExprNodes.NullNode(pos)
if len(args) == 3:
error_handling_node = args[2]
if isinstance(error_handling_node, ExprNodes.CoerceToPyTypeNode):
......@@ -1652,21 +2112,23 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
return (encoding, encoding_node, error_handling, error_handling_node)
### helpers
def _substitute_method_call(self, node, name, func_type,
attr_name, is_unbound_method, args=(),
utility_code=None):
args = list(args)
if args:
if args and not args[0].is_literal:
self_arg = args[0]
if is_unbound_method:
self_arg = ExprNodes.NoneCheckNode(
self_arg, "PyExc_TypeError",
self_arg = self_arg.as_none_safe_node(
"descriptor '%s' requires a '%s' object but received a 'NoneType'" % (
attr_name, node.function.obj.name))
else:
self_arg = ExprNodes.NoneCheckNode(
self_arg, "PyExc_AttributeError",
"'NoneType' object has no attribute '%s'" % attr_name)
self_arg = self_arg.as_none_safe_node(
"'NoneType' object has no attribute '%s'" % attr_name,
error = "PyExc_AttributeError")
args[0] = self_arg
return ExprNodes.PythonCapiCallNode(
node.pos, name, func_type,
......@@ -1675,6 +2137,48 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
utility_code = utility_code
)
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))
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)))
else:
args[arg_index] = args[arg_index].coerce_to_boolean(self.current_env())
unicode_tailmatch_utility_code = UtilityCode(
# Python's unicode.startswith() and unicode.endswith() support a
# tuple of prefixes/suffixes, whereas it's much more common to
# test for a single unicode string.
proto = '''
static int __Pyx_PyUnicode_Tailmatch(PyObject* s, PyObject* substr, \
Py_ssize_t start, Py_ssize_t end, int direction);
''',
impl = '''
static int __Pyx_PyUnicode_Tailmatch(PyObject* s, PyObject* substr,
Py_ssize_t start, Py_ssize_t end, int direction) {
if (unlikely(PyTuple_Check(substr))) {
int result;
Py_ssize_t i;
for (i = 0; i < PyTuple_GET_SIZE(substr); i++) {
result = PyUnicode_Tailmatch(s, PyTuple_GET_ITEM(substr, i),
start, end, direction);
if (result) {
return result;
}
}
return 0;
}
return PyUnicode_Tailmatch(s, substr, start, end, direction);
}
''',
)
dict_getitem_default_utility_code = UtilityCode(
proto = '''
......@@ -1736,6 +2240,7 @@ impl = ""
pop_utility_code = UtilityCode(
proto = """
static CYTHON_INLINE PyObject* __Pyx_PyObject_Pop(PyObject* L) {
PyObject *r, *m;
#if PY_VERSION_HEX >= 0x02040000
if (likely(PyList_CheckExact(L))
/* Check that both the size is positive and no reallocation shrinking needs to be done. */
......@@ -1744,7 +2249,6 @@ static CYTHON_INLINE PyObject* __Pyx_PyObject_Pop(PyObject* L) {
return PyList_GET_ITEM(L, PyList_GET_SIZE(L));
}
#endif
PyObject *r, *m;
m = __Pyx_GetAttrString(L, "pop");
if (!m) return NULL;
r = PyObject_CallObject(m, NULL);
......
......@@ -58,6 +58,7 @@ directive_defaults = {
'cdivision': False, # was True before 0.12
'cdivision_warnings': False,
'always_allow_keywords': False,
'allow_none_for_extension_args': True,
'wraparound' : True,
'ccomplex' : False, # use C99/C++ for complex types and arith
'callspec' : "",
......
......@@ -1310,8 +1310,8 @@ class TransformBuiltinMethods(EnvTransform):
node = BoolNode(node.pos, value=True)
elif attribute == u'NULL':
node = NullNode(node.pos)
elif attribute == u'set':
node = NameNode(node.pos, name=EncodedString('set'))
elif attribute in (u'set', u'frozenset'):
node = NameNode(node.pos, name=EncodedString(attribute))
elif not PyrexTypes.parse_basic_type(attribute):
error(node.pos, u"'%s' not a valid cython attribute or is being used incorrectly" % attribute)
return node
......
......@@ -45,7 +45,7 @@ cpdef p_atom(PyrexScanner s)
cpdef p_name(PyrexScanner s, name)
cpdef p_cat_string_literal(PyrexScanner s)
cpdef p_opt_string_literal(PyrexScanner s)
cpdef p_string_literal(PyrexScanner s)
cpdef p_string_literal(PyrexScanner s, kind_override=*)
cpdef p_list_maker(PyrexScanner s)
cpdef p_comp_iter(PyrexScanner s, body)
cpdef p_comp_for(PyrexScanner s, body)
......
......@@ -11,14 +11,6 @@ import os
import re
import sys
try:
from __builtin__ import set
except (ImportError, AttributeError):
try:
from builtins import set
except (ImportError, AttributeError):
from sets import Set as set
from Cython.Compiler.Scanning import PyrexScanner, FileSourceDescriptor
import Nodes
import ExprNodes
......@@ -678,7 +670,7 @@ def p_opt_string_literal(s):
else:
return None
def p_string_literal(s):
def p_string_literal(s, kind_override=None):
# A single string or char literal.
# Returns (kind, value) where kind in ('b', 'c', 'u')
# s.sy == 'BEGIN_STRING'
......@@ -695,6 +687,8 @@ def p_string_literal(s):
if Future.unicode_literals in s.context.future_directives:
if kind == '':
kind = 'u'
if kind_override is not None and kind_override in 'ub':
kind = kind_override
if kind == 'u':
chars = StringEncoding.UnicodeLiteralBuilder()
else:
......@@ -1907,7 +1901,9 @@ basic_c_type_names = ("void", "char", "int", "float", "double", "bint")
special_basic_c_types = {
# name : (signed, longness)
"Py_UNICODE" : (0, 0),
"Py_ssize_t" : (2, 0),
"ssize_t" : (2, 0),
"size_t" : (0, 0),
}
......@@ -2000,7 +1996,7 @@ def p_c_func_declarator(s, pos, ctx, base, cmethod_flag):
exception_value = exc_val, exception_check = exc_check,
nogil = nogil or ctx.nogil or with_gil, with_gil = with_gil)
supported_overloaded_operators = set([
supported_overloaded_operators = cython.set([
'+', '-', '*', '/', '%',
'++', '--', '~', '|', '&', '^', '<<', '>>',
'==', '!=', '>=', '>', '<=', '<',
......@@ -2139,7 +2135,7 @@ def p_optional_ellipsis(s):
def p_c_arg_decl(s, ctx, in_pyfunc, cmethod_flag = 0, nonempty = 0,
kw_only = 0, annotated = 1):
pos = s.position()
not_none = 0
not_none = or_none = 0
default = None
annotation = None
if s.in_python_file:
......@@ -2152,15 +2148,17 @@ def p_c_arg_decl(s, ctx, in_pyfunc, cmethod_flag = 0, nonempty = 0,
else:
base_type = p_c_base_type(s, cmethod_flag, nonempty = nonempty)
declarator = p_c_declarator(s, ctx, nonempty = nonempty)
if s.sy == 'not' and not s.in_python_file:
if s.sy in ('not', 'or') and not s.in_python_file:
kind = s.sy
s.next()
if s.sy == 'IDENT' and s.systring == 'None':
s.next()
else:
s.error("Expected 'None'")
if not in_pyfunc:
error(pos, "'not None' only allowed in Python functions")
not_none = 1
error(pos, "'%s None' only allowed in Python functions" % kind)
or_none = kind == 'or'
not_none = kind == 'not'
if annotated and s.sy == ':':
s.next()
annotation = p_simple_expr(s)
......@@ -2177,6 +2175,7 @@ def p_c_arg_decl(s, ctx, in_pyfunc, cmethod_flag = 0, nonempty = 0,
base_type = base_type,
declarator = declarator,
not_none = not_none,
or_none = or_none,
default = default,
annotation = annotation,
kw_only = kw_only)
......@@ -2243,10 +2242,10 @@ def p_cdef_extern_block(s, pos, ctx):
s.next()
else:
_, include_file = p_string_literal(s)
ctx = ctx(cdef_flag = 1, visibility = 'extern')
if s.systring == "namespace":
s.next()
ctx.namespace = p_string_literal(s)[1]
ctx = ctx(cdef_flag = 1, visibility = 'extern')
ctx.namespace = p_string_literal(s, kind_override='u')[1]
if p_nogil(s):
ctx.nogil = 1
body = p_suite(s, ctx)
......@@ -2720,6 +2719,7 @@ def p_cpp_class_definition(s, pos, ctx):
s.expect_newline("Expected a newline")
s.expect_dedent()
else:
attributes = None
s.expect_newline("Syntax error in C++ class definition")
return Nodes.CppClassNode(pos,
name = class_name,
......
#
# Pyrex - Types
#
......@@ -162,6 +160,12 @@ class PyrexType(BaseType):
return 1
def public_decl(base_code, dll_linkage):
if dll_linkage:
return "%s(%s)" % (dll_linkage, base_code)
else:
return base_code
def create_typedef_type(name, base_type, cname, is_external=0):
if base_type.is_complex:
if is_external:
......@@ -170,6 +174,7 @@ def create_typedef_type(name, base_type, cname, is_external=0):
else:
return CTypedefType(name, base_type, cname, is_external)
class CTypedefType(BaseType):
#
# Pseudo-type defined with a ctypedef statement in a
......@@ -286,6 +291,7 @@ class CTypedefType(BaseType):
def __getattr__(self, name):
return getattr(self.typedef_base_type, name)
class BufferType(BaseType):
#
# Delegates most attribute
......@@ -320,11 +326,6 @@ class BufferType(BaseType):
def __repr__(self):
return "<BufferType %r>" % self.base
def public_decl(base, dll_linkage):
if dll_linkage:
return "%s(%s)" % (dll_linkage, base)
else:
return base
class PyObjectType(PyrexType):
#
......@@ -355,9 +356,11 @@ class PyObjectType(PyrexType):
def declaration_code(self, entity_code,
for_display = 0, dll_linkage = None, pyrex = 0):
if pyrex or for_display:
return self.base_declaration_code("object", entity_code)
base_code = "object"
else:
return "%s *%s" % (public_decl("PyObject", dll_linkage), entity_code)
base_code = public_decl("PyObject", dll_linkage)
entity_code = "*%s" % entity_code
return self.base_declaration_code(base_code, entity_code)
def as_pyobject(self, cname):
if (not self.is_complete()) or self.is_extension_type:
......@@ -436,9 +439,11 @@ class BuiltinObjectType(PyObjectType):
def declaration_code(self, entity_code,
for_display = 0, dll_linkage = None, pyrex = 0):
if pyrex or for_display:
return self.base_declaration_code(self.name, entity_code)
base_code = self.name
else:
return "%s *%s" % (public_decl("PyObject", dll_linkage), entity_code)
base_code = public_decl("PyObject", dll_linkage)
entity_code = "*%s" % entity_code
return self.base_declaration_code(base_code, entity_code)
class PyExtensionType(PyObjectType):
......@@ -514,17 +519,18 @@ class PyExtensionType(PyObjectType):
def declaration_code(self, entity_code,
for_display = 0, dll_linkage = None, pyrex = 0, deref = 0):
if pyrex or for_display:
return self.base_declaration_code(self.name, entity_code)
base_code = self.name
else:
if self.typedef_flag:
objstruct = self.objstruct_cname
else:
objstruct = "struct %s" % self.objstruct_cname
base = public_decl(objstruct, dll_linkage)
base_code = public_decl(objstruct, dll_linkage)
if deref:
return "%s %s" % (base, entity_code)
assert not entity_code
else:
return "%s *%s" % (base, entity_code)
entity_code = "*%s" % entity_code
return self.base_declaration_code(base_code, entity_code)
def type_test_code(self, py_arg, notnone=False):
......@@ -584,6 +590,10 @@ class CType(PyrexType):
class CVoidType(CType):
#
# C "void" type
#
is_void = 1
def __repr__(self):
......@@ -591,8 +601,11 @@ class CVoidType(CType):
def declaration_code(self, entity_code,
for_display = 0, dll_linkage = None, pyrex = 0):
base = public_decl("void", dll_linkage)
return self.base_declaration_code(base, entity_code)
if pyrex or for_display:
base_code = "void"
else:
base_code = public_decl("void", dll_linkage)
return self.base_declaration_code(base_code, entity_code)
def is_complete(self):
return 0
......@@ -625,10 +638,12 @@ class CNumericType(CType):
def declaration_code(self, entity_code,
for_display = 0, dll_linkage = None, pyrex = 0):
base = public_decl(self.sign_and_name(), dll_linkage)
if for_display:
base = base.replace('PY_LONG_LONG', 'long long')
return self.base_declaration_code(base, entity_code)
type_name = self.sign_and_name()
if pyrex or for_display:
base_code = type_name.replace('PY_LONG_LONG', 'long long')
else:
base_code = public_decl(type_name, dll_linkage)
return self.base_declaration_code(base_code, entity_code)
type_conversion_predeclarations = ""
......@@ -775,27 +790,40 @@ class CIntType(CNumericType):
is_int = 1
typedef_flag = 0
to_py_function = "PyInt_FromLong"
from_py_function = "__Pyx_PyInt_AsInt"
to_py_function = None
from_py_function = None
exception_value = -1
def __init__(self, rank, signed, is_returncode = 0):
def __init__(self, rank, signed = 1):
CNumericType.__init__(self, rank, signed)
self.is_returncode = is_returncode
if self.from_py_function == "__Pyx_PyInt_AsInt":
self.from_py_function = self.get_type_conversion()
def get_type_conversion(self):
ctype = self.declaration_code('')
bits = ctype.split(" ", 1)
if len(bits) == 1:
sign_word, type_name = "", bits[0]
else:
sign_word, type_name = bits
type_name = type_name.replace("PY_LONG_LONG","long long")
SignWord = sign_word.title()
if self.to_py_function is None:
self.to_py_function = self.get_to_py_type_conversion()
if self.from_py_function is None:
self.from_py_function = self.get_from_py_type_conversion()
def get_to_py_type_conversion(self):
if self.rank < list(rank_to_type_name).index('int'):
# This assumes sizeof(short) < sizeof(int)
return "PyInt_FromLong"
else:
# Py{Int|Long}_From[Unsigned]Long[Long]
Prefix = "Int"
SignWord = ""
TypeName = "Long"
if not self.signed:
Prefix = "Long"
SignWord = "Unsigned"
if self.rank >= list(rank_to_type_name).index('PY_LONG_LONG'):
Prefix = "Long"
TypeName = "LongLong"
return "Py%s_From%s%s" % (Prefix, SignWord, TypeName)
def get_from_py_type_conversion(self):
type_name = rank_to_type_name[self.rank]
type_name = type_name.replace("PY_LONG_LONG", "long long")
TypeName = type_name.title().replace(" ", "")
if "Long" in TypeName:
SignWord = self.sign_words[self.signed].strip().title()
if self.rank >= list(rank_to_type_name).index('long'):
utility_code = c_long_from_py_function
else:
utility_code = c_int_from_py_function
......@@ -809,16 +837,6 @@ class CIntType(CNumericType):
return src_type.is_int or src_type.is_enum or src_type is error_type
class CBIntType(CIntType):
to_py_function = "__Pyx_PyBool_FromLong"
from_py_function = "__Pyx_PyObject_IsTrue"
exception_check = 0
def __repr__(self):
return "<CNumericType bint>"
class CAnonEnumType(CIntType):
is_enum = 1
......@@ -827,30 +845,34 @@ class CAnonEnumType(CIntType):
return 'int'
class CUIntType(CIntType):
class CReturnCodeType(CIntType):
to_py_function = "PyLong_FromUnsignedLong"
exception_value = -1
class CLongType(CIntType):
to_py_function = "PyInt_FromLong"
is_returncode = 1
class CULongType(CUIntType):
class CBIntType(CIntType):
to_py_function = "PyLong_FromUnsignedLong"
to_py_function = "__Pyx_PyBool_FromLong"
from_py_function = "__Pyx_PyObject_IsTrue"
exception_check = 0
def __repr__(self):
return "<CNumericType bint>"
class CLongLongType(CIntType):
to_py_function = "PyLong_FromLongLong"
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.
class CULongLongType(CUIntType):
to_py_function = "PyInt_FromLong"
from_py_function = "__Pyx_PyInt_AsPy_UNICODE"
to_py_function = "PyLong_FromUnsignedLongLong"
def sign_and_name(self):
return "Py_UNICODE"
class CPySSizeTType(CIntType):
......@@ -859,16 +881,23 @@ class CPySSizeTType(CIntType):
from_py_function = "__Pyx_PyIndex_AsSsize_t"
def sign_and_name(self):
return rank_to_type_name[self.rank]
return "Py_ssize_t"
class CSSizeTType(CIntType):
class CSizeTType(CUIntType):
to_py_function = "PyInt_FromSsize_t"
from_py_function = "PyInt_AsSsize_t"
def sign_and_name(self):
return "ssize_t"
class CSizeTType(CIntType):
to_py_function = "__Pyx_PyInt_FromSize_t"
from_py_function = "__Pyx_PyInt_AsSize_t"
def sign_and_name(self):
return rank_to_type_name[self.rank]
return "size_t"
class CFloatType(CNumericType):
......@@ -937,15 +966,17 @@ class CComplexType(CNumericType):
def declaration_code(self, entity_code,
for_display = 0, dll_linkage = None, pyrex = 0):
if for_display:
base = public_decl(self.real_type.sign_and_name() + " complex", dll_linkage)
if pyrex or for_display:
real_code = self.real_type.declaration_code("", for_display, dll_linkage, pyrex)
base_code = "%s complex" % real_code
else:
base = public_decl(self.sign_and_name(), dll_linkage)
return self.base_declaration_code(base, entity_code)
base_code = public_decl(self.sign_and_name(), dll_linkage)
return self.base_declaration_code(base_code, entity_code)
def sign_and_name(self):
real_type_name = self.real_type.specialization_name()
real_type_name = real_type_name.replace('long__double','long_double')
real_type_name = real_type_name.replace('PY_LONG_LONG','long_long')
return Naming.type_prefix + real_type_name + "_complex"
def assignable_from(self, src_type):
......@@ -1639,6 +1670,11 @@ class CFuncTypeArg(object):
# type PyrexType
# pos source file position
# FIXME: is this the right setup? should None be allowed here?
not_none = False
or_none = False
accept_none = True
def __init__(self, name, type, pos, cname=None):
self.name = name
if cname is not None:
......@@ -1647,7 +1683,6 @@ class CFuncTypeArg(object):
self.cname = Naming.var_prefix + name
self.type = type
self.pos = pos
self.not_none = False
self.needs_type_test = False # TODO: should these defaults be set in analyse_types()?
def __repr__(self):
......@@ -1748,16 +1783,15 @@ class CStructOrUnionType(CType):
def declaration_code(self, entity_code,
for_display = 0, dll_linkage = None, pyrex = 0):
if pyrex:
return self.base_declaration_code(self.name, entity_code)
if pyrex or for_display:
base_code = self.name
else:
if for_display:
base = self.name
elif self.typedef_flag:
base = self.cname
if self.typedef_flag:
base_code = self.cname
else:
base = "%s %s" % (self.kind, self.cname)
return self.base_declaration_code(public_decl(base, dll_linkage), entity_code)
base_code = "%s %s" % (self.kind, self.cname)
base_code = public_decl(base_code, dll_linkage)
return self.base_declaration_code(base_code, entity_code)
def __eq__(self, other):
try:
......@@ -1847,20 +1881,24 @@ class CppClassType(CType):
specialized.namespace = self.namespace.specialize(values)
return specialized
def declaration_code(self, entity_code, for_display = 0, dll_linkage = None, pyrex = 0):
def declaration_code(self, entity_code,
for_display = 0, dll_linkage = None, pyrex = 0):
if self.templates:
template_strings = [param.declaration_code('', for_display, pyrex) for param in self.templates]
templates = "<" + ",".join(template_strings) + ">"
template_strings = [param.declaration_code('', for_display, None, pyrex)
for param in self.templates]
templates = "<%s>" % ",".join(template_strings)
if templates[-2:] == ">>":
templates = templates[:-2] + "> >"
else:
templates = ""
if for_display or pyrex:
name = self.name
if pyrex or for_display:
base_code = "%s%s" % (self.name, templates)
else:
base_code = "%s%s" % (self.cname, templates)
if self.namespace is not None:
name = "%s::%s" % (self.namespace.declaration_code(''), self.cname)
else:
name = self.cname
return "%s%s %s" % (name, templates, entity_code)
base_code = "%s::%s" % (self.namespace.declaration_code(''), base_code)
base_code = public_decl(base_code, dll_linkage)
return self.base_declaration_code(base_code, entity_code)
def is_subclass(self, other_type):
# TODO(danilo): Handle templates.
......@@ -1899,7 +1937,8 @@ class TemplatePlaceholderType(CType):
def __init__(self, name):
self.name = name
def declaration_code(self, entity_code, for_display = 0, dll_linkage = None, pyrex = 0):
def declaration_code(self, entity_code,
for_display = 0, dll_linkage = None, pyrex = 0):
if entity_code:
return self.name + " " + entity_code
else:
......@@ -1952,14 +1991,15 @@ class CEnumType(CType):
def declaration_code(self, entity_code,
for_display = 0, dll_linkage = None, pyrex = 0):
if pyrex:
return self.base_declaration_code(self.cname, entity_code)
if pyrex or for_display:
base_code = self.name
else:
if self.typedef_flag:
base = self.cname
base_code = self.cname
else:
base = "enum %s" % self.cname
return self.base_declaration_code(public_decl(base, dll_linkage), entity_code)
base_code = "enum %s" % self.cname
base_code = public_decl(base_code, dll_linkage)
return self.base_declaration_code(base_code, entity_code)
class CStringType(object):
......@@ -1968,8 +2008,8 @@ class CStringType(object):
is_string = 1
is_unicode = 0
to_py_function = "__Pyx_PyBytes_FromString"
from_py_function = "__Pyx_PyBytes_AsString"
to_py_function = "PyBytes_FromString"
from_py_function = "PyBytes_AsString"
exception_value = "NULL"
def literal_code(self, value):
......@@ -2056,61 +2096,70 @@ rank_to_type_name = (
"short", # 1
"int", # 2
"long", # 3
"Py_ssize_t", # 4
"size_t", # 5
"PY_LONG_LONG", # 6
"float", # 7
"double", # 8
"long double", # 9
"PY_LONG_LONG", # 4
"float", # 5
"double", # 6
"long double", # 7
)
py_object_type = PyObjectType()
RANK_INT = list(rank_to_type_name).index('int')
RANK_LONG = list(rank_to_type_name).index('long')
UNSIGNED = 0
SIGNED = 2
c_void_type = CVoidType()
c_void_ptr_type = CPtrType(c_void_type)
c_void_ptr_ptr_type = CPtrType(c_void_ptr_type)
c_uchar_type = CIntType(0, 0)
c_ushort_type = CIntType(1, 0)
c_uint_type = CUIntType(2, 0)
c_ulong_type = CULongType(3, 0)
c_ulonglong_type = CULongLongType(6, 0)
c_char_type = CIntType(0, 1)
c_short_type = CIntType(1, 1)
c_int_type = CIntType(2, 1)
c_long_type = CLongType(3, 1)
c_longlong_type = CLongLongType(6, 1)
c_bint_type = CBIntType(2, 1)
c_schar_type = CIntType(0, 2)
c_sshort_type = CIntType(1, 2)
c_sint_type = CIntType(2, 2)
c_slong_type = CLongType(3, 2)
c_slonglong_type = CLongLongType(6, 2)
c_py_ssize_t_type = CPySSizeTType(4, 2)
c_size_t_type = CSizeTType(5, 0)
py_object_type = PyObjectType()
c_float_type = CFloatType(7, math_h_modifier='f')
c_double_type = CFloatType(8)
c_longdouble_type = CFloatType(9, math_h_modifier='l')
c_void_type = CVoidType()
c_uchar_type = CIntType(0, UNSIGNED)
c_ushort_type = CIntType(1, UNSIGNED)
c_uint_type = CIntType(2, UNSIGNED)
c_ulong_type = CIntType(3, UNSIGNED)
c_ulonglong_type = CIntType(4, UNSIGNED)
c_char_type = CIntType(0)
c_short_type = CIntType(1)
c_int_type = CIntType(2)
c_long_type = CIntType(3)
c_longlong_type = CIntType(4)
c_schar_type = CIntType(0, SIGNED)
c_sshort_type = CIntType(1, SIGNED)
c_sint_type = CIntType(2, SIGNED)
c_slong_type = CIntType(3, SIGNED)
c_slonglong_type = CIntType(4, SIGNED)
c_float_type = CFloatType(5, math_h_modifier='f')
c_double_type = CFloatType(6)
c_longdouble_type = CFloatType(7, math_h_modifier='l')
c_float_complex_type = CComplexType(c_float_type)
c_double_complex_type = CComplexType(c_double_type)
c_longdouble_complex_type = CComplexType(c_longdouble_type)
c_anon_enum_type = CAnonEnumType(-1)
c_returncode_type = CReturnCodeType(RANK_INT)
c_bint_type = CBIntType(RANK_INT)
c_py_unicode_type = CPyUnicodeIntType(RANK_INT-0.5, UNSIGNED)
c_py_ssize_t_type = CPySSizeTType(RANK_LONG+0.5, SIGNED)
c_ssize_t_type = CSSizeTType(RANK_LONG+0.5, SIGNED)
c_size_t_type = CSizeTType(RANK_LONG+0.5, UNSIGNED)
c_null_ptr_type = CNullPtrType(c_void_type)
c_void_ptr_type = CPtrType(c_void_type)
c_void_ptr_ptr_type = CPtrType(c_void_ptr_type)
c_char_array_type = CCharArrayType(None)
c_char_ptr_type = CCharPtrType()
c_uchar_ptr_type = CUCharPtrType()
c_utf8_char_array_type = CUTF8CharArrayType(None)
c_char_ptr_ptr_type = CPtrType(c_char_ptr_type)
c_int_ptr_type = CPtrType(c_int_type)
c_py_unicode_ptr_type = CPtrType(c_py_unicode_type)
c_py_ssize_t_ptr_type = CPtrType(c_py_ssize_t_type)
c_ssize_t_ptr_type = CPtrType(c_ssize_t_type)
c_size_t_ptr_type = CPtrType(c_size_t_type)
c_returncode_type = CIntType(2, 1, is_returncode = 1)
c_anon_enum_type = CAnonEnumType(-1, 1)
# the Py_buffer type is defined in Builtin.py
c_py_buffer_type = CStructOrUnionType("Py_buffer", "struct", None, 1, "Py_buffer")
......@@ -2119,99 +2168,57 @@ c_py_buffer_ptr_type = CPtrType(c_py_buffer_type)
error_type = ErrorType()
unspecified_type = UnspecifiedType()
sign_and_rank_to_type = {
#(signed, rank)
(0, 0): c_uchar_type,
(0, 1): c_ushort_type,
(0, 2): c_uint_type,
(0, 3): c_ulong_type,
(0, 6): c_ulonglong_type,
(1, 0): c_char_type,
(1, 1): c_short_type,
(1, 2): c_int_type,
(1, 3): c_long_type,
(1, 6): c_longlong_type,
(2, 0): c_schar_type,
(2, 1): c_sshort_type,
(2, 2): c_sint_type,
(2, 3): c_slong_type,
(2, 6): c_slonglong_type,
(0, 4): c_py_ssize_t_type,
(1, 4): c_py_ssize_t_type,
(2, 4): c_py_ssize_t_type,
(0, 5): c_size_t_type,
(1, 5): c_size_t_type,
(2, 5): c_size_t_type,
(1, 7): c_float_type,
(1, 8): c_double_type,
(1, 9): c_longdouble_type,
# In case we're mixing unsigned ints and floats...
(0, 7): c_float_type,
(0, 8): c_double_type,
(0, 9): c_longdouble_type,
}
modifiers_and_name_to_type = {
#(signed, longness, name)
#(signed, longness, name) : type
(0, 0, "char"): c_uchar_type,
(1, 0, "char"): c_char_type,
(2, 0, "char"): c_schar_type,
(0, -1, "int"): c_ushort_type,
(0, 0, "int"): c_uint_type,
(0, 1, "int"): c_ulong_type,
(0, 2, "int"): c_ulonglong_type,
(1, 0, "void"): c_void_type,
(1, 0, "char"): c_char_type,
(1, -1, "int"): c_short_type,
(1, 0, "int"): c_int_type,
(1, 1, "int"): c_long_type,
(1, 2, "int"): c_longlong_type,
(1, 0, "float"): c_float_type,
(1, 0, "double"): c_double_type,
(1, 1, "double"): c_longdouble_type,
(1, 0, "object"): py_object_type,
(1, 0, "bint"): c_bint_type,
(2, 0, "char"): c_schar_type,
(2, -1, "int"): c_sshort_type,
(2, 0, "int"): c_sint_type,
(2, 1, "int"): c_slong_type,
(2, 2, "int"): c_slonglong_type,
(1, 0, "float"): c_float_type,
(1, 0, "double"): c_double_type,
(1, 1, "double"): c_longdouble_type,
(1, 0, "complex"): c_float_complex_type,
(1, 0, "floatcomplex"): c_float_complex_type,
(1, 0, "doublecomplex"): c_double_complex_type,
(1, 1, "doublecomplex"): c_longdouble_complex_type,
#
(1, 0, "void"): c_void_type,
(1, 0, "bint"): c_bint_type,
(0, 0, "Py_UNICODE"): c_py_unicode_type,
(2, 0, "Py_ssize_t"): c_py_ssize_t_type,
(2, 0, "ssize_t") : c_ssize_t_type,
(0, 0, "size_t") : c_size_t_type,
(1, 0, "long"): c_long_type,
(1, 0, "short"): c_short_type,
(1, 0, "longlong"): c_longlong_type,
(1, 0, "bint"): c_bint_type,
(1, 0, "object"): py_object_type,
}
def is_promotion0(src_type, dst_type):
if src_type.is_numeric and dst_type.is_numeric:
if src_type.is_int and dst_type.is_int:
if src_type.is_enum:
return True
elif src_type.signed:
return dst_type.signed and src_type.rank <= dst_type.rank
elif dst_type.signed: # and not src_type.signed
src_type.rank < dst_type.rank
else:
return src_type.rank <= dst_type.rank
elif src_type.is_float and dst_type.is_float:
return src_type.rank <= dst_type.rank
else:
return False
else:
return False
def is_promotion(src_type, dst_type):
# It's hard to find a hard definition of promotion, but empirical
# evidence suggests that the below is all that's allowed.
if src_type.is_numeric:
if dst_type.same_as(c_int_type):
return src_type.is_enum or (src_type.is_int and (not src_type.signed) + src_type.rank < dst_type.rank)
unsigned = (not src_type.signed)
return (src_type.is_enum or
(src_type.is_int and
unsigned + src_type.rank < dst_type.rank))
elif dst_type.same_as(c_double_type):
return src_type.is_float and src_type.rank <= dst_type.rank
return False
......@@ -2275,8 +2282,11 @@ def best_match(args, functions, pos=None):
if len(candidates) == 1:
return candidates[0][0]
elif len(candidates) == 0:
if len(errors) == 1 and pos is not None:
if pos is not None:
if len(errors) == 1:
error(pos, errors[0][1])
else:
error(pos, "no suitable method found")
return None
possibilities = []
......@@ -2316,30 +2326,31 @@ def best_match(args, functions, pos=None):
error(pos, "no suitable method found")
return None
def widest_numeric_type(type1, type2):
# Given two numeric types, return the narrowest type
# encompassing both of them.
if type1 == type2:
return type1
if type1.is_complex:
if type2.is_complex:
return CComplexType(widest_numeric_type(type1.real_type, type2.real_type))
else:
return CComplexType(widest_numeric_type(type1.real_type, type2))
elif type2.is_complex:
return CComplexType(widest_numeric_type(type1, type2.real_type))
if type1.is_enum and type2.is_enum:
return c_int_type
elif type1 is type2:
return type1
elif (type1.signed and type2.signed) or (not type1.signed and not type2.signed):
if type2.rank > type1.rank:
return type2
else:
return type1
else:
return sign_and_rank_to_type[min(type1.signed, type2.signed), max(type1.rank, type2.rank)]
widest_type = type1
elif type1.is_complex or type2.is_complex:
def real_type(ntype):
if ntype.is_complex:
return ntype.real_type
return ntype
widest_type = CComplexType(
widest_numeric_type(
real_type(type1),
real_type(type2)))
elif type1.is_enum and type2.is_enum:
widest_type = c_int_type
elif type1.rank < type2.rank:
widest_type = type2
elif type1.rank > type2.rank:
widest_type = type1
elif type1.signed < type2.signed:
widest_type = type1
else:
widest_type = type2
return widest_type
def spanning_type(type1, type2):
# Return a type assignable from both type1 and type2.
......@@ -2394,10 +2405,39 @@ def parse_basic_type(name):
base = parse_basic_type(name[:-1])
if base:
return CPtrType(base)
elif name.startswith('u'):
return simple_c_type(0, 0, name[1:])
else:
return simple_c_type(1, 0, name)
#
basic_type = simple_c_type(1, 0, name)
if basic_type:
return basic_type
#
signed = 1
longness = 0
if name == 'Py_UNICODE':
signed = 0
elif name == 'Py_ssize_t':
signed = 2
elif name == 'ssize_t':
signed = 2
elif name == 'size_t':
signed = 0
else:
if name.startswith('u'):
name = name[1:]
signed = 0
elif (name.startswith('s') and
not name.startswith('short')):
name = name[1:]
signed = 2
longness = 0
while name.startswith('short'):
name = name.replace('short', '', 1).strip()
longness -= 1
while name.startswith('long'):
name = name.replace('long', '', 1).strip()
longness += 1
if longness != 0 and not name:
name = 'int'
return simple_c_type(signed, longness, name)
def c_array_type(base_type, size):
# Construct a C array type.
......@@ -2426,19 +2466,6 @@ def c_ref_type(base_type):
else:
return CReferenceType(base_type)
def Node_to_type(node, env):
from ExprNodes import NameNode, AttributeNode, StringNode, error
if isinstance(node, StringNode):
node = NameNode(node.pos, name=node.value)
if isinstance(node, NameNode) and node.name in rank_to_type_name:
return simple_c_type(1, 0, node.name)
elif isinstance(node, (AttributeNode, NameNode)):
node.analyze_types(env)
if not node.entry.is_type:
pass
else:
error(node.pos, "Bad type")
def same_type(type1, type2):
return type1.same_as(type2)
......@@ -2460,23 +2487,17 @@ def typecast(to_type, from_type, expr_code):
type_conversion_predeclarations = """
/* Type Conversion Predeclarations */
#if PY_MAJOR_VERSION < 3
#define __Pyx_PyBytes_FromString PyString_FromString
#define __Pyx_PyBytes_FromStringAndSize PyString_FromStringAndSize
#define __Pyx_PyBytes_AsString PyString_AsString
#else
#define __Pyx_PyBytes_FromString PyBytes_FromString
#define __Pyx_PyBytes_FromStringAndSize PyBytes_FromStringAndSize
#define __Pyx_PyBytes_AsString PyBytes_AsString
#endif
#define __Pyx_PyBytes_FromUString(s) __Pyx_PyBytes_FromString((char*)s)
#define __Pyx_PyBytes_AsUString(s) ((unsigned char*) __Pyx_PyBytes_AsString(s))
#define __Pyx_PyBytes_FromUString(s) PyBytes_FromString((char*)s)
#define __Pyx_PyBytes_AsUString(s) ((unsigned char*) PyBytes_AsString(s))
#define __Pyx_PyBool_FromLong(b) ((b) ? (Py_INCREF(Py_True), Py_True) : (Py_INCREF(Py_False), Py_False))
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*);
......@@ -2541,6 +2562,26 @@ 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);
......@@ -2578,4 +2619,3 @@ static CYTHON_INLINE size_t __Pyx_PyInt_AsSize_t(PyObject* x) {
""" + type_conversion_functions
......@@ -2,12 +2,9 @@
# Cython Scanner
#
import sys
import os
import platform
import stat
import sys
import codecs
from time import time
import cython
cython.declare(EncodedString=object, string_prefixes=object, raw_prefixes=object, IDENT=object,
......
......@@ -210,6 +210,8 @@ class Scope(object):
# is_py_class_scope boolean Is a Python class scope
# is_c_class_scope boolean Is an extension type scope
# is_closure_scope boolean
# is_cpp_class_scope boolean Is a C++ class scope
# is_property_scope boolean Is a extension type property scope
# scope_prefix string Disambiguator for C names
# in_cinclude boolean Suppress C declaration code
# qualified_name string "modname" or "modname.classname"
......@@ -225,6 +227,7 @@ class Scope(object):
is_c_class_scope = 0
is_closure_scope = 0
is_cpp_class_scope = 0
is_property_scope = 0
is_module_scope = 0
is_internal = 0
scope_prefix = ""
......@@ -415,7 +418,7 @@ class Scope(object):
error(pos, "C++ classes may only be extern")
if cname is None:
cname = name
entry = self.lookup(name)
entry = self.lookup_here(name)
if not entry:
type = PyrexTypes.CppClassType(
name, scope, cname, base_classes, templates = templates)
......@@ -439,6 +442,7 @@ class Scope(object):
for base_class in base_classes:
declare_inherited_attributes(entry, base_class.base_classes)
entry.type.scope.declare_inherited_cpp_attributes(base_class.scope)
if entry.type.scope:
declare_inherited_attributes(entry, base_classes)
if self.is_cpp_class_scope:
entry.type.namespace = self.outer_scope.lookup(self.name).type
......@@ -1665,6 +1669,8 @@ class PropertyScope(Scope):
#
# parent_type PyExtensionType The type to which the property belongs
is_property_scope = 1
def declare_pyfunction(self, name, pos):
# Add an entry for a method.
signature = get_property_accessor_signature(name)
......
......@@ -117,6 +117,7 @@ class ResultRefNode(AtomicExprNode):
# must be set externally (usually a temp name).
subexprs = []
lhs_of_first_assignment = False
def __init__(self, expression):
self.pos = expression.pos
......@@ -148,6 +149,7 @@ class ResultRefNode(AtomicExprNode):
def generate_assignment_code(self, rhs, code):
if self.type.is_pyobject:
rhs.make_owned_reference(code)
if not self.lhs_of_first_assignment:
code.put_decref(self.result(), self.ctype())
code.putln('%s = %s;' % (self.result(), rhs.result_as(self.ctype())))
rhs.generate_post_assignment_code(code)
......@@ -250,3 +252,26 @@ class LetNode(Nodes.StatNode, LetNodeMixin):
self.setup_temp_expr(code)
self.body.generate_execution_code(code)
self.teardown_temp_expr(code)
class TempResultFromStatNode(ExprNodes.ExprNode):
# An ExprNode wrapper around a StatNode that executes the StatNode
# body. Requires a ResultRefNode that it sets up to refer to its
# own temp result. The StatNode must assign a value to the result
# node, which then becomes the result of this node.
#
# This can only be used in/after type analysis.
#
subexprs = []
child_attrs = ['body']
def __init__(self, result_ref, body):
self.result_ref = result_ref
self.pos = body.pos
self.body = body
self.type = result_ref.type
self.is_temp = 1
def generate_result_code(self, code):
self.result_ref.result_code = self.result()
self.body.generate_execution_code(code)
......@@ -326,6 +326,9 @@ class EnvTransform(CythonTransform):
self.env_stack = [root.scope]
return super(EnvTransform, self).__call__(root)
def current_env(self):
return self.env_stack[-1]
def visit_FuncDefNode(self, node):
self.env_stack.append(node.local_scope)
self.visitchildren(node)
......
from cpython.unicode cimport Py_UNICODE
cdef extern from "Python.h":
ctypedef long long PY_LONG_LONG
......
cdef extern from *:
ctypedef unsigned int Py_UNICODE
# Return true if the object o is a Unicode object or an instance
# of a Unicode subtype. Changed in version 2.2: Allowed subtypes
# to be accepted.
......@@ -91,6 +89,13 @@ cdef extern from *:
# when u is NULL.
object PyUnicode_FromUnicode(Py_UNICODE *u, Py_ssize_t size)
# Create a Unicode Object from the given Unicode code point ordinal.
#
# The ordinal must be in range(0x10000) on narrow Python builds
# (UCS2), and range(0x110000) on wide builds (UCS4). A ValueError
# is raised in case it is not.
object PyUnicode_FromOrdinal(int ordinal)
# Return a read-only pointer to the Unicode object's internal
# Py_UNICODE buffer, NULL if unicode is not a Unicode object.
Py_UNICODE* PyUnicode_AsUnicode(object o) except NULL
......
......@@ -3,39 +3,44 @@ from pair cimport pair
cdef extern from "<deque>" namespace "std":
cdef cppclass deque[T]:
cppclass iterator:
T operator*()
T& operator*()
iterator operator++()
iterator operator--()
bint operator==(iterator)
bint operator!=(iterator)
cppclass const_iterator(iterator):
pass
cppclass reverse_iterator(iterator):
pass
cppclass const_reverse_iterator(iterator):
pass
cppclass reverse_iterator:
T& operator*()
iterator operator++()
iterator operator--()
bint operator==(iterator)
bint operator!=(iterator)
#cppclass const_iterator(iterator):
# pass
#cppclass const_reverse_iterator(reverse_iterator):
# pass
deque()
deque(deque&)
deque(size_t, T& val = T())
#deque(input_iterator, input_iterator)
TYPE& operator[]( size_type index )
const TYPE& operator[]( size_type index ) const
deque(size_t)
deque(size_t, T&)
#deque[input_iterator](input_iterator, input_iterator)
T& operator[](size_t)
#deque& operator=(deque&)
bool operator==(deque&, deque&)
bool operator!=(deque&, deque&)
bool operator<(deque&, deque&)
bool operator>(deque&, deque&)
bool operator<=(deque&, deque&)
bool operator>=(deque&, deque&)
void assign(size_t, TYPE&)
bint operator==(deque&, deque&)
bint operator!=(deque&, deque&)
bint operator<(deque&, deque&)
bint operator>(deque&, deque&)
bint operator<=(deque&, deque&)
bint operator>=(deque&, deque&)
void assign(size_t, T&)
void assign(input_iterator, input_iterator)
T& at(size_t)
T& back()
iterator begin()
const_iterator begin()
#const_iterator begin()
void clear()
bool empty()
bint empty()
iterator end()
const_iterator end()
#const_iterator end()
iterator erase(iterator)
iterator erase(iterator, iterator)
T& front()
......@@ -48,9 +53,10 @@ cdef extern from "<deque>" namespace "std":
void push_back(T&)
void push_front(T&)
reverse_iterator rbegin()
const_reverse_iterator rbegin()
#const_reverse_iterator rbegin()
reverse_iterator rend()
const_reverse_iterator rend()
void resize(size_t, T val = T())
#const_reverse_iterator rend()
void resize(size_t)
void resize(size_t, T&)
size_t size()
void swap(deque&)
cdef extern from "<list>" namespace "std":
cdef cppclass list[T]:
cppclass iterator:
T& operator*()
iterator operator++()
iterator operator--()
bint operator==(iterator)
bint operator!=(iterator)
cppclass reverse_iterator:
T& operator*()
iterator operator++()
iterator operator--()
bint operator==(iterator)
bint operator!=(iterator)
#cppclass const_iterator(iterator):
# pass
#cppclass const_reverse_iterator(reverse_iterator):
# pass
list()
list(list&)
list(size_t, T&)
#list operator=(list&)
bint operator==(list&, list&)
bint operator!=(list&, list&)
bint operator<(list&, list&)
bint operator>(list&, list&)
bint operator<=(list&, list&)
bint operator>=(list&, list&)
void assign(size_t, T&)
T& back()
iterator begin()
#const_iterator begin()
bint empty()
iterator end()
#const_iterator end()
iterator erase(iterator)
iterator erase(iterator, iterator)
T& front()
iterator insert(iterator, T&)
void insert(iterator, size_t, T&)
size_t max_size()
void merge(list&)
#void merge(list&, BinPred)
void pop_back()
void pop_front()
void push_back(T&)
void push_front(T&)
reverse_iterator rbegin()
#const_reverse_iterator rbegin()
void remove(T&)
#void remove_if(UnPred)
reverse_iterator rend()
#const_reverse_iterator rend()
void resize(size_t, T&)
void reverse()
size_t size()
void sort()
#void sort(BinPred)
void splice(iterator, list&)
void splice(iterator, list&, iterator)
void splice(iterator, list&, iterator, iterator)
void swap(list&)
void unique()
#void unique(BinPred)
from pair cimport pair
cdef extern from "<map>" namespace "std":
cdef cppclass map[T, U]:
cppclass iterator:
pair[T,U]& operator*()
iterator operator++()
iterator operator--()
bint operator==(iterator)
bint operator!=(iterator)
cppclass reverse_iterator:
pair[T,U] operator*()
iterator operator++()
iterator operator--()
bint operator==(iterator)
bint operator!=(iterator)
#cppclass const_iterator(iterator):
# pass
#cppclass const_reverse_iterator(reverse_iterator):
# pass
map()
map(map&)
#map(key_compare&)
U& operator[](T&)
#map& operator=(map&)
bint operator==(map&, map&)
bint operator!=(map&, map&)
bint operator<(map&, map&)
bint operator>(map&, map&)
bint operator<=(map&, map&)
bint operator>=(map&, map&)
U& at(T&)
iterator begin()
#const_iterator begin()
void clear()
size_t count(T&)
bint empty()
iterator end()
#const_iterator end()
pair[iterator, iterator] equal_range(T&)
#pair[const_iterator, const_iterator] equal_range(key_type&)
void erase(iterator)
void erase(iterator, iterator)
size_t erase(T&)
iterator find(T&)
#const_iterator find(key_type&)
pair[iterator, bint] insert(pair[T,U]) # XXX pair[T,U]&
iterator insert(iterator, pair[T,U]) # XXX pair[T,U]&
#void insert(input_iterator, input_iterator)
#key_compare key_comp()
iterator lower_bound(T&)
#const_iterator lower_bound(key_type&)
size_t max_size()
reverse_iterator rbegin()
#const_reverse_iterator rbegin()
reverse_iterator rend()
#const_reverse_iterator rend()
size_t size()
void swap(map&)
iterator upper_bound(T&)
#const_iterator upper_bound(key_type&)
#value_compare value_comp()
cdef extern from "pair.h":
cdef extern from "<utility>" namespace "std":
cdef cppclass pair[T, U]:
T first
U second
pair()
pair(pair&)
pair(T&, U&)
from pair cimport pair
cdef extern from "<queue>" namespace "std":
cdef cppclass queue[T]:
queue()
queue(queue&)
#queue(Container&)
T& back()
bool empty()
bint empty()
T& front()
void pop()
void push(T&)
size_t size()
cdef cppclass priority_queue[T]:
priority_queue()
priority_queue(priority_queue&)
#priority_queue(Container&)
bint empty()
void pop()
void push(T&)
size_t size()
T& top()
......@@ -5,51 +5,56 @@ cdef extern from "<set>" namespace "std":
cppclass iterator:
T operator*()
iterator operator++()
iterator operator--()
bint operator==(iterator)
bint operator!=(iterator)
cppclass const_iterator(iterator):
pass
cppclass reverse_iterator(iterator):
pass
cppclass const_reverse_iterator(iterator):
pass
cppclass reverse_iterator:
T operator*()
iterator operator++()
iterator operator--()
bint operator==(iterator)
bint operator!=(iterator)
#cppclass const_iterator(iterator):
# pass
#cppclass const_reverse_iterator(reverse_iterator):
# pass
set()
set(set&)
#set set(key_compare&)
#set(key_compare&)
#set& operator=(set&)
bool operator==(set&, set&)
bool operator!=(set&, set&)
bool operator<(set&, set&)
bool operator>(set&, set&)
bool operator<=(set&, set&)
bool operator>=(set&, set&)
bint operator==(set&, set&)
bint operator!=(set&, set&)
bint operator<(set&, set&)
bint operator>(set&, set&)
bint operator<=(set&, set&)
bint operator>=(set&, set&)
iterator begin()
const_iterator begin()
#const_iterator begin()
void clear()
#size_t count(key_type&)
bool empty()
size_t count(T&)
bint empty()
iterator end()
const_iterator end()
#pair[iterator, iterator] equal_range(key_type&)
#pair[const_iterator, const_iterator] equal_range(key_type&)
#const_iterator end()
pair[iterator, iterator] equal_range(T&)
#pair[const_iterator, const_iterator] equal_range(T&)
void erase(iterator)
void erase(iterator, iterator)
#size_t erase(key_type&)
#iterator find(key_type&)
#const_iterator find(key_type&)
#pair[iterator, bool] insert(T&)
size_t erase(T&)
iterator find(T&)
#const_iterator find(T&)
pair[iterator, bint] insert(T&)
iterator insert(iterator, T&)
#void insert(input_iterator, input_iterator)
#key_compare key_comp()
#iterator lower_bound(key_type&)
#const_iterator lower_bound(key_type&)
iterator lower_bound(T&)
#const_iterator lower_bound(T&)
size_t max_size()
reverse_iterator rbegin()
const_reverse_iterator rbegin()
#const_reverse_iterator rbegin()
reverse_iterator rend()
const_reverse_iterator rend()
#const_reverse_iterator rend()
size_t size()
void swap(set&)
#iterator upper_bound(key_type&)
#const_iterator upper_bound(key_type&)
iterator upper_bound(T&)
#const_iterator upper_bound(T&)
#value_compare value_comp()
from pair cimport pair
cdef extern from "<list>" namespace "std":
cdef cppclass list[T]:
cppclass iterator:
T operator*()
iterator operator++()
bint operator==(iterator)
bint operator!=(iterator)
cppclass const_iterator(iterator):
pass
cppclass reverse_iterator(iterator):
pass
cppclass const_reverse_iterator(iterator):
pass
list()
list(list&)
list(size_t, T&)
#list operator=(list&)
bool operator==(list&, list&)
bool operator!=(list&, list&)
bool operator<(list&, list&)
bool operator>(list&, list&)
bool operator<=(list&, list&)
bool operator>=(list&, list&)
void assign(size_t, T&)
T& back()
iterator begin()
const_iterator begin()
bool empty()
iterator end()
const_iterator end()
iterator erase(iterator)
iterator erase(iterator, iterator)
T& front()
iterator insert(iterator, T&)
void insert(iterator, size_t, T&)
size_t max_size()
void merge(list&)
#voide merge(list&, BinPred)
void pop_back()
void pop_front()
void push_back(T&)
void push_front(T&)
reverse_iterator rbegin()
const_reverse_iterator rbegin()
void remove(T&)
#void remove_if(UnPred)
reverse_iterator rend()
const_reverse_iterator rend()
void resize(size_t, T&)
void reverse()
cdef extern from "<stack>" namespace "std":
cdef cppclass stack[T]:
stack()
stack(stack&)
#stack(Container&)
bint empty()
void pop()
void push(T&)
size_t size()
void sort()
#void sort(BinPred)
void splice(iterator, list&)
void splice(iterator, list&, iterator)
void splice(iterator, list&, iterator, iterator)
void swap(list&)
void unique()
#void unique(BinPred)
T& top()
from pair cimport pair
cdef extern from "<vector>" namespace "std":
cdef cppclass vector[T]:
cppclass iterator:
T operator*()
T& operator*()
iterator operator++()
iterator operator--()
bint operator==(iterator)
bint operator!=(iterator)
cppclass const_iterator(iterator):
pass
cppclass reverse_iterator(iterator):
pass
cppclass const_reverse_iterator(iterator):
pass
#cppclass input_iterator(iterator):
cppclass reverse_iterator:
T& operator*()
iterator operator++()
iterator operator--()
bint operator==(iterator)
bint operator!=(iterator)
#cppclass const_iterator(iterator):
# pass
#cppclass const_reverse_iterator(reverse_iterator):
# pass
vector()
#vector(vector&)
#vector(size_t, T&)
vector(vector&)
vector(size_t)
vector(size_t, T&)
#vector[input_iterator](input_iterator, input_iterator)
T& operator[](size_t)
#vector& operator=(vector&)
bool operator==(vector&, vector&)
bool operator!=(vector&, vector&)
bool operator<(vector&, vector&)
bool operator>(vector&, vector&)
bool operator<=(vector&, vector&)
bool operator>=(vector&, vector&)
bint operator==(vector&, vector&)
bint operator!=(vector&, vector&)
bint operator<(vector&, vector&)
bint operator>(vector&, vector&)
bint operator<=(vector&, vector&)
bint operator>=(vector&, vector&)
void assign(size_t, T&)
#void assign(input_iterator, input_iterator)
#void assign[input_iterator](input_iterator, input_iterator)
T& at(size_t)
T& back()
iterator begin()
const_iterator begin()
#const_iterator begin()
size_t capacity()
void clear()
bool empty()
bint empty()
iterator end()
const_iterator end()
#const_iterator end()
iterator erase(iterator)
iterator erase(iterator, iterator)
T& front()
......@@ -48,10 +50,11 @@ cdef extern from "<vector>" namespace "std":
void pop_back()
void push_back(T&)
reverse_iterator rbegin()
const_reverse_iterator rbegin()
#const_reverse_iterator rbegin()
reverse_iterator rend()
const_reverse_iterator rend()
#const_reverse_iterator rend()
void reserve(size_t)
void resize(size_t, T)
void resize(size_t)
void resize(size_t, T&)
size_t size()
void swap(vector&)
......@@ -481,8 +481,8 @@ cdef extern from "numpy/arrayobject.h":
bint PyArray_FROM_OT(object m, int type)
bint PyArray_FROM_OTF(object m, int type, int flags)
object PyArray_FROMANY(object m, int type, int min, int max, int flags)
bint PyArray_ZEROS(ndarray m, dims, int type, int fortran)
object PyArray_EMPTY(object m, dims, int type, int fortran)
bint PyArray_ZEROS(ndarray m, npy_intp* dims, int type, int fortran)
object PyArray_EMPTY(object m, npy_intp* dims, int type, int fortran)
void PyArray_FILLWBYTE(object, int val)
npy_intp PyArray_REFCOUNT(object)
object PyArray_ContiguousFromAny(op, int, int min_depth, int max_depth)
......
......@@ -153,40 +153,50 @@ class typedef(CythonType):
py_float = float
py_int = int
try:
py_long = long
except NameError: # Py3
py_long = int
py_float = float
py_complex = complex
try:
# Python 3
from builtins import set
from builtins import set, frozenset
except ImportError:
try:
# Python 2.4+
from __builtin__ import set
from __builtin__ import set, frozenset
except ImportError:
# Py 2.3
from sets import Set as set
from sets import Set as set, ImmutableSet as frozenset
# Predefined types
int_types = ['char', 'short', 'int', 'long', 'longlong', 'Py_ssize_t']
float_types = ['double', 'float']
int_types = ['char', 'short', 'Py_UNICODE', 'int', 'long', 'longlong', 'Py_ssize_t', 'size_t']
float_types = ['longdouble', 'double', 'float']
complex_types = ['longdoublecomplex', 'doublecomplex', 'floatcomplex', 'complex']
other_types = ['bint', 'void']
gs = globals()
for name in int_types:
gs[name] = typedef(py_int)
if name != 'Py_UNICODE' and not name.endswith('size_t'):
gs['u'+name] = typedef(py_int)
gs['s'+name] = typedef(py_int)
for name in float_types:
gs[name] = typedef(py_float)
for name in complex_types:
gs[name] = typedef(py_complex)
double = float = typedef(py_float)
bint = typedef(bool)
void = typedef(int)
for t in int_types + float_types + other_types:
for t in int_types + float_types + complex_types + other_types:
for i in range(1, 4):
gs["%s_%s" % ('p'*i, t)] = globals()[t]._pointer(i)
......
......@@ -45,6 +45,27 @@ def file_newer_than(path, time):
ftime = modification_time(path)
return ftime > time
def path_exists(path):
# try on the filesystem first
if os.path.exists(path):
return True
# figure out if a PEP 302 loader is around
try:
loader = __loader__
# XXX the code below assumes as 'zipimport.zipimporter' instance
# XXX should be easy to generalize, but too lazy right now to write it
if path.startswith(loader.archive):
nrmpath = os.path.normpath(path)
arcname = nrmpath[len(loader.archive)+1:]
try:
loader.get_data(arcname)
return True
except IOError:
return False
except NameError:
pass
return False
# support for source file encoding detection
def encode_filename(filename):
......@@ -109,18 +130,31 @@ class NormalisedNewlineStream(object):
data = self._read(0x1000)
return u''.join(content).split(u'\n')
try:
from io import open as io_open
except ImportError:
io_open = None
io = None
if sys.version_info >= (2,6):
try:
import io
except ImportError:
pass
def open_source_file(source_filename, mode="r",
encoding=None, error_handling=None,
require_normalised_newlines=True):
if encoding is None:
encoding = detect_file_encoding(source_filename)
if io_open is not None:
return io_open(source_filename, mode=mode,
#
try:
loader = __loader__
if source_filename.startswith(loader.archive):
return open_source_from_loader(
loader, source_filename,
encoding, error_handling,
require_normalised_newlines)
except (NameError, AttributeError):
pass
#
if io is not None:
return io.open(source_filename, mode=mode,
encoding=encoding, errors=error_handling)
else:
# codecs module doesn't have universal newline support
......@@ -130,6 +164,28 @@ def open_source_file(source_filename, mode="r",
stream = NormalisedNewlineStream(stream)
return stream
def open_source_from_loader(loader,
source_filename,
encoding=None, error_handling=None,
require_normalised_newlines=True):
nrmpath = os.path.normpath(source_filename)
arcname = nrmpath[len(loader.archive)+1:]
data = loader.get_data(arcname)
if io is not None:
return io.TextIOWrapper(io.BytesIO(data),
encoding=encoding,
errors=error_handling)
else:
try:
import cStringIO as StringIO
except ImportError:
import StringIO
reader = codecs.getreader(encoding)
stream = reader(StringIO.StringIO(data))
if require_normalised_newlines:
stream = NormalisedNewlineStream(stream)
return stream
def str_to_number(value):
# note: this expects a string as input that was accepted by the
# parser already
......
......@@ -178,6 +178,9 @@ class TestBuilder(object):
def build_tests(self, test_class, path, workdir, module, expect_errors):
if expect_errors:
if 'cpp' in module and 'cpp' in self.languages:
languages = ['cpp']
else:
languages = self.languages[:1]
else:
languages = self.languages
......@@ -752,6 +755,9 @@ if __name__ == '__main__':
parser.add_option("-C", "--coverage", dest="coverage",
action="store_true", default=False,
help="collect source coverage data for the Compiler")
parser.add_option("--coverage-xml", dest="coverage_xml",
action="store_true", default=False,
help="collect source coverage data for the Compiler in XML format")
parser.add_option("-A", "--annotate", dest="annotate_source",
action="store_true", default=True,
help="generate annotated HTML versions of the test source files")
......@@ -799,11 +805,12 @@ if __name__ == '__main__':
WITH_CYTHON = options.with_cython
if options.coverage:
if options.coverage or options.coverage_xml:
if not WITH_CYTHON:
options.coverage = False
options.coverage = options.coverage_xml = False
else:
import coverage
from coverage import coverage as _coverage
coverage = _coverage(branch=True)
coverage.erase()
coverage.start()
......@@ -924,14 +931,17 @@ if __name__ == '__main__':
result = test_runner.run(test_suite)
if options.coverage:
if options.coverage or options.coverage_xml:
coverage.stop()
ignored_modules = ('Options', 'Version', 'DebugFlags', 'CmdLine')
modules = [ module for name, module in sys.modules.items()
if module is not None and
name.startswith('Cython.Compiler.') and
name[len('Cython.Compiler.'):] not in ignored_modules ]
if options.coverage:
coverage.report(modules, show_missing=0)
if options.coverage_xml:
coverage.xml_report(modules, outfile="coverage-report.xml")
if missing_dep_excluder.tests_missing_deps:
sys.stderr.write("Following tests excluded because of missing dependencies on your system:\n")
......
......@@ -85,7 +85,7 @@ else:
else:
scripts = ["cython.py"]
def compile_cython_modules():
def compile_cython_modules(profile=False):
source_root = os.path.abspath(os.path.dirname(__file__))
compiled_modules = ["Cython.Plex.Scanners",
"Cython.Compiler.Scanning",
......@@ -116,6 +116,10 @@ def compile_cython_modules():
del sys.modules[module]
sys.path.insert(0, os.path.join(source_root, self.build_lib))
if profile:
from Cython.Compiler.Options import directive_defaults
directive_defaults['profile'] = True
print("Enabled profiling for the Cython binary modules")
build_ext_orig.build_extensions(self)
setup_args['ext_modules'] = extensions
......@@ -132,6 +136,10 @@ def compile_cython_modules():
print("Compilation of '%s' failed" % ext.sources[0])
from Cython.Compiler.Main import compile
from Cython import Utils
if profile:
from Cython.Compiler.Options import directive_defaults
directive_defaults['profile'] = True
print("Enabled profiling for the Cython binary modules")
source_root = os.path.dirname(__file__)
for module in compiled_modules:
source_file = os.path.join(source_root, *module.split('.'))
......@@ -159,10 +167,14 @@ def compile_cython_modules():
print("ERROR: %s" % sys.exc_info()[1])
print("Extension module compilation failed, using plain Python implementation")
cython_profile = '--cython-profile' in sys.argv
if cython_profile:
sys.argv.remove('--cython-profile')
try:
sys.argv.remove("--no-cython-compile")
except ValueError:
compile_cython_modules()
compile_cython_modules(cython_profile)
setup_args.update(setuptools_extra_args)
......
#ifdef __cplusplus
extern "C" {
#endif
extern DL_EXPORT(int) f1(void);
extern DL_EXPORT(int) __cdecl f2(void);
extern DL_EXPORT(int) __stdcall f3(void);
extern DL_EXPORT(int) __fastcall f4(void);
#ifdef __cplusplus
}
#endif
int f1(void) {return 0;}
int __cdecl f2(void) {return 0;}
int __stdcall f3(void) {return 0;}
int __fastcall f4(void) {return 0;}
#ifdef __cplusplus
extern "C" {
#endif
extern int (*p1)(void);
extern int (__cdecl *p2)(void);
extern int (__stdcall *p3)(void);
extern int (__fastcall *p4)(void);
#ifdef __cplusplus
}
#endif
int (*p1)(void);
int (__cdecl *p2)(void);
int (__stdcall *p3)(void);
int (__fastcall *p4)(void);
cdef extern from "callingconvention.h":
pass
cdef extern int f1()
cdef extern int __cdecl f2()
......
#ifdef __cplusplus
extern "C" {
#endif
extern char *cp;
extern char *cpa[5];
extern int (*ifnpa[5])(void);
extern char *(*cpfnpa[5])(void);
extern int (*ifnp)(void);
extern int (*iap)[5];
#ifdef __cplusplus
}
#endif
char *cp;
char *cpa[5];
int (*ifnpa[5])(void);
char *(*cpfnpa[5])(void);
int (*ifnp)(void);
int (*iap)[5];
#ifdef __cplusplus
extern "C" {
#endif
extern DL_EXPORT(int) ifn(void);
extern DL_EXPORT(char *) cpfn(void);
extern DL_EXPORT(int) fnargfn(int (void));
extern DL_EXPORT(int) (*iapfn(void))[5];
extern DL_EXPORT(char *)(*cpapfn(void))[5];
#ifdef __cplusplus
}
#endif
int ifn(void) {return 0;}
char *cpfn(void) {return 0;}
int fnargfn(int f(void)) {return 0;}
#ifdef __cplusplus
extern "C" {
#endif
extern int ia[];
extern int iaa[][3];
extern DL_EXPORT(int) a(int[][3], int[][3][5]);
#ifdef __cplusplus
}
#endif
int ia[1];
int iaa[1][3];
int a(int a[][3], int b[][3][5]) {return 0;}
cdef extern from "declarations.h":
pass
cdef extern char *cp
cdef extern char *cpa[5]
cdef extern int (*ifnpa[5])()
......
#ifdef __cplusplus
extern "C" {
#endif
extern DL_EXPORT(int) spam(void);
extern DL_EXPORT(void) grail(void);
extern DL_EXPORT(char *)tomato(void);
#ifdef __cplusplus
}
#endif
int spam(void) {return 0;}
void grail(void) {return;}
char *tomato(void) {return 0;}
cdef extern from "excvalcheck.h":
pass
cdef extern int spam() except -1
cdef extern void grail() except *
cdef extern char *tomato() except? NULL
......
cimport libc
cimport libc.stdio
cimport libc.errno
cimport libc.float
cimport libc.limits
cimport libc.locale
cimport libc.signal
cimport libc.stddef
cimport libc.stdint
cimport libc.stdio
cimport libc.stdlib
cimport libc.string
from libc cimport errno
from libc cimport float
from libc cimport limits
from libc cimport locale
from libc cimport signal
from libc cimport stddef
from libc cimport stdint
from libc cimport stdio
from libc cimport stdlib
from libc cimport string
from libc.errno cimport *
from libc.float cimport *
from libc.limits cimport *
......@@ -8,3 +33,7 @@ from libc.stdint cimport *
from libc.stdio cimport *
from libc.stdlib cimport *
from libc.string cimport *
libc.stdio.printf("hello %s\n", b"world")
stdio.printf("hello %s\n", b"world")
printf("hello %s\n", b"world")
cimport libcpp
cimport libcpp.deque
cimport libcpp.list
cimport libcpp.map
cimport libcpp.pair
cimport libcpp.queue
cimport libcpp.set
cimport libcpp.stack
cimport libcpp.vector
from libcpp.deque cimport *
from libcpp.list cimport *
from libcpp.map cimport *
from libcpp.pair cimport *
from libcpp.queue cimport *
from libcpp.set cimport *
from libcpp.stack cimport *
from libcpp.vector cimport *
cdef libcpp.deque.deque[int] d1 = deque[int]()
cdef libcpp.list.list[int] l1 = list[int]()
cdef libcpp.map.map[int,int] m1 = map[int,int]()
cdef libcpp.pair.pair[int,int] p1 = pair[int,int](1,2)
cdef libcpp.queue.queue[int] q1 = queue[int]()
cdef libcpp.set.set[int] s1 = set[int]()
cdef libcpp.stack.stack[int] t1 = stack[int]()
cdef libcpp.vector.vector[int] v1 = vector[int]()
cdef deque[int].iterator id1 = d1.begin()
cdef deque[int].iterator id2 = d1.end()
cdef deque[int].reverse_iterator rid1 = d1.rbegin()
cdef deque[int].reverse_iterator rid2 = d1.rend()
cdef list[int].iterator il1 = l1.begin()
cdef list[int].iterator il2 = l1.end()
cdef list[int].reverse_iterator ril1 = l1.rbegin()
cdef list[int].reverse_iterator ril2 = l1.rend()
cdef map[int,int].iterator im1 = m1.begin()
cdef map[int,int].iterator im2 = m1.end()
cdef map[int,int].reverse_iterator rim1 = m1.rbegin()
cdef map[int,int].reverse_iterator rim2 = m1.rend()
cdef pair[map[int,int].iterator, bint] pimb = m1.insert(p1)
cdef set[int].iterator is1 = s1.begin()
cdef set[int].iterator is2 = s1.end()
cdef set[int].reverse_iterator ris1 = s1.rbegin()
cdef set[int].reverse_iterator ris2 = s1.rend()
cdef pair[set[int].iterator, bint] pisb = s1.insert(4)
cdef vector[int].iterator iv1 = v1.begin()
cdef vector[int].iterator iv2 = v1.end()
cdef vector[int].reverse_iterator riv1 = v1.rbegin()
cdef vector[int].reverse_iterator riv2 = v1.rend()
void e1(void);
void *e2(void);
#ifdef __cplusplus
extern "C" {
#endif
extern DL_EXPORT(void) e1(void);
extern DL_EXPORT(void *) e2(void);
#ifdef __cplusplus
}
#endif
void e1(void) {return;}
void *e2(void) {return 0;}
#ifdef __cplusplus
extern "C" {
#endif
extern DL_EXPORT(PyObject *) g(PyObject*);
extern DL_EXPORT(void) g2(PyObject*);
#ifdef __cplusplus
}
#endif
PyObject *g(PyObject* o) {return 0;}
void g2(PyObject* o) {return;}
cdef class C:
def __cinit__(self):
"This is an unusable docstring."
def __init__(self):
"This is an unusable docstring."
def __dealloc__(self):
"This is an unusable docstring."
def __richcmp__(self, other, int op):
"This is an unusable docstring."
def __nonzero__(self):
"This is an unusable docstring."
return False
def __contains__(self, other):
"This is an unusable docstring."
property foo:
def __get__(self):
"So is this."
def __set__(self, x):
"And here is another one."
def __add__(self, other):
"usable docstring"
def __iter__(self):
"usable docstring"
return False
def __next__(self):
"usable docstring"
return False
cdef extern from *:
cdef cppclass Foo:
Foo()
Foo(int)
new Foo(1, 2)
_ERRORS = u"""
6:7: no suitable method found
"""
def eggs(int x not None, y not None):
def eggs(int x not None, char* y not None):
pass
_ERRORS = u"""
1:0: Only extension type arguments can have 'not None'
1:0: Only extension type arguments can have 'not None'
1: 9: Only Python type arguments can have 'not None'
1:25: Only Python type arguments can have 'not None'
"""
......@@ -4,12 +4,14 @@ cdef int cx = "test" # fails
cdef int x1 = "\xFF" # works
cdef int x2 = "\u0FFF" # fails
cdef int x3 = u"\xFF" # fails
cdef Py_UNICODE u1 = u"\xFF" # works
cdef int u3 = u"\xFF" # fails
_ERRORS = u"""
2:14: Only single-character strings can be coerced into ints.
3:14: Only single-character strings can be coerced into ints.
6:15: Only single-character strings can be coerced into ints.
7:14: Unicode objects do not support coercion to C types.
_ERRORS = """
2:14: Only single-character string literals can be coerced into ints.
3:14: Only single-character string literals can be coerced into ints.
6:15: Only single-character string literals can be coerced into ints.
9:14: Unicode literals do not support coercion to C types other than Py_UNICODE.
"""
# -*- coding: iso-8859-1 -*-
cdef Py_UNICODE char_ASCII = u'A'
cdef Py_UNICODE char_KLINGON = u'\uF8D2'
def char_too_long_ASCII():
cdef Py_UNICODE c = u'AB'
def char_too_long_Unicode():
cdef Py_UNICODE c = u'A\uF8D2'
def char_too_long_bytes():
cdef Py_UNICODE c = b'AB'
def char_too_long_latin1():
cdef Py_UNICODE char_bytes_latin1 = b'\xf6'
_ERRORS = """
7:24: Only single-character Unicode string literals can be coerced into Py_UNICODE.
10:24: Only single-character Unicode string literals can be coerced into Py_UNICODE.
13:24: Only single-character string literals can be coerced into ints.
16:40: Bytes literals cannot coerce to Py_UNICODE, use a unicode literal instead.
"""
......@@ -50,7 +50,7 @@ cdef list l_f2 = b1
cdef list l_f3 = u1
_ERRORS = u"""
25:20: Unicode objects do not support coercion to C types.
25:20: Unicode literals do not support coercion to C types other than Py_UNICODE.
26:22: Unicode objects do not support coercion to C types.
27:22: 'str' objects do not support coercion to C types (use 'bytes'?).
......
......@@ -110,4 +110,20 @@ cdef class MyCdefClass:
False
"""
def __len__(self):
"""
Should not be included, as it can't be looked up with getattr in Py 3.1
>>> True
False
"""
def __contains__(self, value):
"""
Should not be included, as it can't be looked up with getattr in Py 3.1
>>> True
False
"""
cdeffunc()
def bool_list(list obj):
"""
>>> bool_list( [] )
False
>>> bool_list( [1] )
True
>>> bool_list(None)
False
"""
return bool(obj)
def if_list(list obj):
"""
>>> if_list( [] )
False
>>> if_list( [1] )
True
>>> if_list(None)
False
"""
if obj:
return True
else:
return False
def if_list_literal(t):
"""
>>> if_list_literal(True)
True
>>> if_list_literal(False)
False
"""
if t:
if [1,2,3]:
return True
else:
return False
else:
if []:
return True
else:
return False
def bool_tuple(tuple obj):
"""
>>> bool_tuple( () )
False
>>> bool_tuple( (1,) )
True
>>> bool_tuple(None)
False
"""
return bool(obj)
def if_tuple(tuple obj):
"""
>>> if_tuple( () )
False
>>> if_tuple( (1,) )
True
>>> if_tuple(None)
False
"""
if obj:
return True
else:
return False
def if_tuple_literal(t):
"""
>>> if_tuple_literal(True)
True
>>> if_tuple_literal(False)
False
"""
if t:
if (1,2,3):
return True
else:
return False
else:
if ():
return True
else:
return False
b0 = b''
b1 = b'abc'
def bool_bytes(bytes obj):
"""
>>> bool_bytes(b0)
False
>>> bool_bytes(b1)
True
>>> bool_bytes(None)
False
"""
return bool(obj)
def if_bytes(bytes obj):
"""
>>> if_bytes(b0)
False
>>> if_bytes(b1)
True
>>> if_bytes(None)
False
"""
if obj:
return True
else:
return False
def if_bytes_literal(t):
"""
>>> if_bytes_literal(True)
True
>>> if_bytes_literal(False)
False
"""
if t:
if b'abc':
return True
else:
return False
else:
if b'':
return True
else:
return False
u0 = u''
u1 = u'abc'
def bool_unicode(unicode obj):
"""
>>> bool_unicode(u0)
False
>>> bool_unicode(u1)
True
>>> bool_unicode(None)
False
"""
return bool(obj)
def if_unicode(unicode obj):
"""
>>> if_unicode(u0)
False
>>> if_unicode(u1)
True
>>> if_unicode(None)
False
"""
if obj:
return True
else:
return False
def if_unicode_literal(t):
"""
>>> if_unicode_literal(True)
True
>>> if_unicode_literal(False)
False
"""
if t:
if u'abc':
return True
else:
return False
else:
if u'':
return True
else:
return False
......@@ -17,6 +17,19 @@ def slice_charptr_decode():
cstring[:3].decode('UTF-8'),
cstring[:9].decode('UTF-8'))
@cython.test_assert_path_exists("//PythonCapiCallNode")
@cython.test_fail_if_path_exists("//AttributeNode")
def slice_charptr_decode_platform_encoding():
"""
>>> print(str(slice_charptr_decode()).replace("u'", "'"))
('a', 'abc', 'abcABCqtp')
"""
cdef bytes s = u'abcABCqtp'.encode()
cdef char* cstr = s
return (cstr[:1].decode(),
cstr[:3].decode(),
cstr[:9].decode())
@cython.test_assert_path_exists("//PythonCapiCallNode")
@cython.test_fail_if_path_exists("//AttributeNode")
def slice_charptr_decode_unknown_encoding():
......
......@@ -69,15 +69,9 @@ def lentest_uchar_c():
return l
@cython.test_assert_path_exists(
"//SimpleCallNode",
)
def lentest_py():
return len(pystr)
@cython.test_assert_path_exists(
"//SimpleCallNode",
)
def lentest_py_c():
cdef Py_ssize_t l = len(pystr)
return l
......@@ -44,3 +44,17 @@ def test_conjugate(long complex z):
(2-3j)
"""
return z.conjugate()
def test_conjugate2(short complex z):
"""
>>> test_conjugate2(2+3j)
(2-3j)
"""
return z.conjugate()
def test_conjugate3(long long complex z):
"""
>>> test_conjugate3(2+3j)
(2-3j)
"""
return z.conjugate()
......@@ -26,3 +26,20 @@ def test_wrap_pair(int i, double x):
return wrap.get().first(), wrap.get().second(), deref(wrap) == deref(wrap)
finally:
del wrap
def test_wrap_pair_pair(int i, int j, double x):
"""
>>> test_wrap_pair_pair(1, 3, 1.5)
(1, 3, 1.5, True)
>>> test_wrap_pair_pair(2, 5, 2.25)
(2, 5, 2.25, True)
"""
try:
wrap = new Wrap[Pair[int, Pair[int, double]]](
Pair[int, Pair[int, double]](i,Pair[int, double](j, x)))
return (wrap.get().first(),
wrap.get().second().first(),
wrap.get().second().second(),
deref(wrap) == deref(wrap))
finally:
del wrap
......@@ -13,6 +13,7 @@ class Pair {
T1 _first;
T2 _second;
public:
Pair() { }
Pair(T1 u, T2 v) { _first = u; _second = v; }
T1 first(void) { return _first; }
T2 second(void) { return _second; }
......
......@@ -78,7 +78,7 @@ def test_attr_int(TestExtInt e):
return False
ctypedef union _aux:
int i
size_t i
void *p
cdef class TestExtPtr:
......
cimport cython
@cython.test_assert_path_exists("//PythonCapiCallNode")
@cython.test_fail_if_path_exists("//AttributeNode")
def get(dict d, key):
"""
>>> d = { 1: 10 }
......@@ -38,6 +43,9 @@ def get(dict d, key):
"""
return d.get(key)
@cython.test_assert_path_exists("//PythonCapiCallNode")
@cython.test_fail_if_path_exists("//AttributeNode")
def get_default(dict d, key, default):
"""
>>> d = { 1: 10 }
......@@ -69,3 +77,14 @@ def get_default(dict d, key, default):
ValueError
"""
return d.get(key, default)
@cython.test_assert_path_exists("//PythonCapiCallNode")
@cython.test_fail_if_path_exists("//AttributeNode")
def get_in_condition(dict d, key, expected_result):
"""
>>> d = dict(a=1, b=2)
>>> get_in_condition(d, 'a', 1)
True
"""
return d.get(key) is expected_result
......@@ -32,3 +32,12 @@ def test(dict d, index):
cdef class Subscriptable:
def __getitem__(self, key):
return key
def getitem_in_condition(dict d, key, expected_result):
"""
>>> d = dict(a=1, b=2)
>>> getitem_in_condition(d, 'a', 1)
True
"""
return d[key] is expected_result
cimport cython
import sys
IS_PY3 = sys.version_info[0] >= 3
def _bool():
"""
>>> _bool() == bool()
True
"""
return bool()
def _int():
"""
>>> _int() == int()
True
"""
return int()
def _long():
"""
>>> IS_PY3 or _long() == long()
True
"""
return long()
def _float():
"""
>>> _float() == float()
True
"""
return float()
def _complex():
"""
>>> _complex() == complex()
True
"""
return complex()
def _bytes():
"""
>>> IS_PY3 and _bytes() == bytes() or _bytes() == str()
True
"""
return bytes()
def _str():
"""
>>> _str() == str()
True
"""
return str()
def _unicode():
"""
>>> IS_PY3 and _unicode() == str() or _unicode() == unicode()
True
"""
return unicode()
def _tuple():
"""
>>> _tuple() == tuple()
True
"""
return tuple()
def _list():
"""
>>> _list() == list()
True
"""
return list()
def _dict():
"""
>>> _dict() == dict()
True
"""
return dict()
py_set = cython.set
def _set():
"""
>>> _set() == py_set()
True
"""
return set()
py_frozenset = cython.frozenset
def _frozenset():
"""
>>> _frozenset() == py_frozenset()
True
"""
return frozenset()
cdef public enum Truth:
FALSE=0
TRUE=1
def enum_boolctx(Truth arg):
"""
>>> enum_boolctx(FALSE)
False
>>> enum_boolctx(TRUE)
True
"""
if arg:
return True
else:
return False
cdef extern from *:
enum: FALSE_VALUE "(0)"
enum: TRUE_VALUE "(1)"
def extern_enum_false():
"""
>>> extern_enum_false()
"""
if FALSE_VALUE:
raise ValueError
def extern_enum_true():
"""
>>> extern_enum_true()
"""
if not TRUE_VALUE:
raise ValueError
def extern_enum_false_true():
"""
>>> extern_enum_false_true()
"""
if not TRUE_VALUE or FALSE_VALUE:
raise ValueError
cimport cython
### extension types
cdef class MyExtType:
cdef object attr
def __cinit__(self):
self.attr = 123
cdef attr(MyExtType x):
return x is None and 321 or x.attr
# defaults, without 'not/or None'
def ext_default(MyExtType x): # currently behaves like 'or None'
"""
>>> ext_default(MyExtType())
123
>>> ext_default(None)
321
"""
return attr(x)
@cython.allow_none_for_extension_args(False)
def ext_default_none(MyExtType x=None): # special cased default arg
"""
>>> ext_default_none(MyExtType())
123
>>> ext_default_none(None)
321
>>> ext_default_none()
321
"""
return attr(x)
@cython.allow_none_for_extension_args(True)
def ext_default_check_off(MyExtType x):
"""
>>> ext_default_check_off(MyExtType())
123
>>> ext_default_check_off(None)
321
"""
return attr(x)
@cython.allow_none_for_extension_args(False)
def ext_default_check_on(MyExtType x):
"""
>>> ext_default_check_on(MyExtType())
123
>>> ext_default_check_on(None)
Traceback (most recent call last):
TypeError: Argument 'x' has incorrect type (expected ext_type_none_arg.MyExtType, got NoneType)
"""
return attr(x)
# with 'or/not None'
def ext_or_none(MyExtType x or None):
"""
>>> ext_or_none(MyExtType())
123
>>> ext_or_none(None)
321
"""
return attr(x)
def ext_not_none(MyExtType x not None):
"""
>>> ext_not_none(MyExtType())
123
>>> ext_not_none(None)
Traceback (most recent call last):
TypeError: Argument 'x' has incorrect type (expected ext_type_none_arg.MyExtType, got NoneType)
"""
return attr(x)
### builtin types (using list)
cdef litem(list L, int item):
return L is None and 321 or L[item]
# defaults, without 'not/or None'
def builtin_default(list L): # currently behaves like 'or None'
"""
>>> builtin_default([123])
123
>>> builtin_default(None)
321
"""
return litem(L, 0)
@cython.allow_none_for_extension_args(False)
def builtin_default_none(list L=None): # special cased default arg
"""
>>> builtin_default_none([123])
123
>>> builtin_default_none(None)
321
>>> builtin_default_none()
321
"""
return litem(L, 0)
@cython.allow_none_for_extension_args(True)
def builtin_default_check_off(list L):
"""
>>> builtin_default_check_off([123])
123
>>> builtin_default_check_off(None)
321
"""
return litem(L, 0)
@cython.allow_none_for_extension_args(False)
def builtin_default_check_on(list L):
"""
>>> builtin_default_check_on([123])
123
>>> builtin_default_check_on(None)
Traceback (most recent call last):
TypeError: Argument 'L' has incorrect type (expected list, got NoneType)
"""
return litem(L, 0)
# with 'or/not None'
def builtin_or_none(list L or None):
"""
>>> builtin_or_none([123])
123
>>> builtin_or_none(None)
321
"""
return litem(L, 0)
def builtin_not_none(list L not None):
"""
>>> builtin_not_none([123])
123
>>> builtin_not_none(None)
Traceback (most recent call last):
TypeError: Argument 'L' has incorrect type (expected list, got NoneType)
"""
return litem(L, 0)
## builtin type 'object' - isinstance(None, object) is True!
@cython.allow_none_for_extension_args(False)
def object_default(object o): # always behaves like 'or None'
"""
>>> object_default(object())
'object'
>>> object_default([])
'list'
>>> object_default(None)
'NoneType'
"""
return type(o).__name__
@cython.allow_none_for_extension_args(False)
def object_default_none(object o=None): # behaves like 'or None'
"""
>>> object_default_none(object())
'object'
>>> object_default_none([])
'list'
>>> object_default_none(None)
'NoneType'
>>> object_default_none()
'NoneType'
"""
return type(o).__name__
@cython.allow_none_for_extension_args(False)
def object_or_none(object o or None):
"""
>>> object_or_none(object())
'object'
>>> object_or_none([])
'list'
>>> object_or_none(None)
'NoneType'
"""
return type(o).__name__
@cython.allow_none_for_extension_args(False)
def object_not_none(object o not None):
"""
>>> object_not_none(object())
'object'
>>> object_not_none([])
'list'
>>> object_not_none(None)
Traceback (most recent call last):
TypeError: Argument 'o' must not be None
"""
return type(o).__name__
## untyped 'object' - isinstance(None, object) is True!
@cython.allow_none_for_extension_args(False)
def notype_default(o): # behaves like 'or None'
"""
>>> notype_default(object())
'object'
>>> notype_default([])
'list'
>>> notype_default(None)
'NoneType'
"""
return type(o).__name__
@cython.allow_none_for_extension_args(False)
def notype_default_none(o=None): # behaves like 'or None'
"""
>>> notype_default_none(object())
'object'
>>> notype_default_none([])
'list'
>>> notype_default_none(None)
'NoneType'
>>> notype_default_none()
'NoneType'
"""
return type(o).__name__
@cython.allow_none_for_extension_args(False)
def notype_or_none(o or None):
"""
>>> notype_or_none(object())
'object'
>>> notype_or_none([])
'list'
>>> notype_or_none(None)
'NoneType'
"""
return type(o).__name__
@cython.allow_none_for_extension_args(False)
def notype_not_none(o not None):
"""
>>> notype_not_none(object())
'object'
>>> notype_not_none([])
'list'
>>> notype_not_none(None)
Traceback (most recent call last):
TypeError: Argument 'o' must not be None
"""
return type(o).__name__
cimport cython
bytes_abc = b'abc'
bytes_ABC = b'ABC'
bytes_abc_null = b'a\0b\0c'
bytes_ABC_null = b'A\0B\0C'
unicode_abc = u'abc'
unicode_ABC = u'ABC'
unicode_abc_null = u'a\0b\0c'
unicode_ABC_null = u'A\0B\0C'
def for_in_bytes(bytes s):
"""
>>> for_in_bytes(bytes_abc)
'X'
>>> for_in_bytes(bytes_ABC)
'C'
>>> for_in_bytes(bytes_abc_null)
'X'
>>> for_in_bytes(bytes_ABC_null)
'C'
"""
for c in s:
# Py2/Py3
if c == b'C' or c == c'C':
return 'C'
else:
return 'X'
@cython.test_assert_path_exists("//ForFromStatNode")
@cython.test_fail_if_path_exists("//ForInStatNode")
def for_char_in_bytes(bytes s):
"""
>>> for_char_in_bytes(bytes_abc)
'X'
>>> for_char_in_bytes(bytes_ABC)
'C'
>>> for_char_in_bytes(bytes_abc_null)
'X'
>>> for_char_in_bytes(bytes_ABC_null)
'C'
"""
cdef char c
for c in s:
if c == b'C':
return 'C'
else:
return 'X'
@cython.test_assert_path_exists("//ForFromStatNode")
@cython.test_fail_if_path_exists("//ForInStatNode")
def for_char_in_enumerate_bytes(bytes s):
"""
>>> for_char_in_enumerate_bytes(bytes_abc)
'X'
>>> for_char_in_enumerate_bytes(bytes_ABC)
2
>>> for_char_in_enumerate_bytes(bytes_abc_null)
'X'
>>> for_char_in_enumerate_bytes(bytes_ABC_null)
4
"""
cdef char c
cdef Py_ssize_t i
for i, c in enumerate(s):
if c == b'C':
return i
else:
return 'X'
@cython.test_assert_path_exists("//ForFromStatNode")
@cython.test_fail_if_path_exists("//ForInStatNode")
def for_pyunicode_in_unicode(unicode s):
"""
>>> for_pyunicode_in_unicode(unicode_abc)
'X'
>>> for_pyunicode_in_unicode(unicode_ABC)
'C'
>>> for_pyunicode_in_unicode(unicode_abc_null)
'X'
>>> for_pyunicode_in_unicode(unicode_ABC_null)
'C'
"""
cdef Py_UNICODE c
for c in s:
if c == u'C':
return 'C'
else:
return 'X'
@cython.test_assert_path_exists("//ForFromStatNode")
@cython.test_fail_if_path_exists("//ForInStatNode")
def for_pyunicode_in_enumerate_unicode(unicode s):
"""
>>> for_pyunicode_in_enumerate_unicode(unicode_abc)
'X'
>>> for_pyunicode_in_enumerate_unicode(unicode_ABC)
2
>>> for_pyunicode_in_enumerate_unicode(unicode_abc_null)
'X'
>>> for_pyunicode_in_enumerate_unicode(unicode_ABC_null)
4
"""
cdef Py_UNICODE c
cdef Py_ssize_t i
for i, c in enumerate(s):
if c == u'C':
return i
else:
return 'X'
cimport cython
def f(a,b):
"""
>>> f(1,[1,2,3])
......@@ -42,6 +45,7 @@ def j(b):
cdef int result = 2 in b
return result
@cython.test_fail_if_path_exists("//SwitchStatNode")
def k(a):
"""
>>> k(1)
......@@ -52,16 +56,209 @@ def k(a):
cdef int result = a in [1,2,3,4]
return result
def m(int a):
@cython.test_assert_path_exists("//SwitchStatNode")
@cython.test_fail_if_path_exists("//BoolBinopNode", "//PrimaryCmpNode")
def m_list(int a):
"""
>>> m(2)
>>> m_list(2)
1
>>> m(5)
>>> m_list(5)
0
"""
cdef int result = a in [1,2,3,4]
return result
@cython.test_assert_path_exists("//SwitchStatNode")
@cython.test_fail_if_path_exists("//BoolBinopNode", "//PrimaryCmpNode")
def m_tuple(int a):
"""
>>> m_tuple(2)
1
>>> m_tuple(5)
0
"""
cdef int result = a in (1,2,3,4)
return result
@cython.test_assert_path_exists("//SwitchStatNode")
@cython.test_fail_if_path_exists("//BoolBinopNode", "//PrimaryCmpNode")
def m_set(int a):
"""
>>> m_set(2)
1
>>> m_set(5)
0
"""
cdef int result = a in {1,2,3,4}
return result
cdef bytes bytes_string = b'ab\0cde\0f\0g'
py_bytes_string = bytes_string
@cython.test_assert_path_exists("//PrimaryCmpNode")
@cython.test_fail_if_path_exists("//SwitchStatNode", "//BoolBinopNode")
def m_bytes(char a, bytes bytes_string):
"""
>>> m_bytes(ord('f'), py_bytes_string)
1
>>> m_bytes(ord('X'), py_bytes_string)
0
>>> 'f'.encode('ASCII') in None
Traceback (most recent call last):
TypeError: argument of type 'NoneType' is not iterable
>>> m_bytes(ord('f'), None)
Traceback (most recent call last):
TypeError: argument of type 'NoneType' is not iterable
"""
cdef int result = a in bytes_string
return result
@cython.test_assert_path_exists("//PrimaryCmpNode")
@cython.test_fail_if_path_exists("//SwitchStatNode", "//BoolBinopNode")
def m_bytes_unsigned(unsigned char a, bytes bytes_string):
"""
>>> m_bytes(ord('f'), py_bytes_string)
1
>>> m_bytes(ord('X'), py_bytes_string)
0
>>> 'f'.encode('ASCII') in None
Traceback (most recent call last):
TypeError: argument of type 'NoneType' is not iterable
>>> m_bytes(ord('f'), None)
Traceback (most recent call last):
TypeError: argument of type 'NoneType' is not iterable
"""
cdef int result = a in bytes_string
return result
@cython.test_assert_path_exists("//SwitchStatNode")
@cython.test_fail_if_path_exists("//BoolBinopNode", "//PrimaryCmpNode")
def m_bytes_literal(char a):
"""
>>> m_bytes_literal(ord('f'))
1
>>> m_bytes_literal(ord('X'))
0
"""
cdef int result = a in b'ab\0cde\0f\0g'
return result
@cython.test_assert_path_exists("//SwitchStatNode")
@cython.test_fail_if_path_exists("//BoolBinopNode", "//PrimaryCmpNode")
def m_bytes_literal_unsigned(unsigned char a):
"""
>>> m_bytes_literal(ord('f'))
1
>>> m_bytes_literal(ord('X'))
0
"""
cdef int result = a in b'ab\0cde\0f\0g'
return result
cdef unicode unicode_string = u'abc\0defg\u1234\uF8D2'
py_unicode_string = unicode_string
@cython.test_assert_path_exists("//PrimaryCmpNode")
@cython.test_fail_if_path_exists("//SwitchStatNode", "//BoolBinopNode")
def m_unicode(Py_UNICODE a, unicode unicode_string):
"""
>>> m_unicode(ord('f'), py_unicode_string)
1
>>> m_unicode(ord('X'), py_unicode_string)
0
>>> m_unicode(ord(py_klingon_character), py_unicode_string)
1
>>> 'f' in None
Traceback (most recent call last):
TypeError: argument of type 'NoneType' is not iterable
>>> m_unicode(ord('f'), None)
Traceback (most recent call last):
TypeError: argument of type 'NoneType' is not iterable
"""
cdef int result = a in unicode_string
return result
cdef unicode klingon_character = u'\uF8D2'
py_klingon_character = klingon_character
@cython.test_assert_path_exists("//SwitchStatNode")
@cython.test_fail_if_path_exists("//BoolBinopNode", "//PrimaryCmpNode")
def m_unicode_literal(Py_UNICODE a):
"""
>>> m_unicode_literal(ord('f'))
1
>>> m_unicode_literal(ord('X'))
0
>>> m_unicode_literal(ord(py_klingon_character))
1
"""
cdef int result = a in u'abc\0defg\u1234\uF8D2'
return result
@cython.test_assert_path_exists("//SwitchStatNode")
@cython.test_fail_if_path_exists("//BoolBinopNode", "//PrimaryCmpNode")
def conditional_int(int a):
"""
>>> conditional_int(1)
1
>>> conditional_int(0)
2
>>> conditional_int(5)
2
"""
return 1 if a in (1,2,3,4) else 2
@cython.test_assert_path_exists("//SwitchStatNode")
@cython.test_fail_if_path_exists("//BoolBinopNode", "//PrimaryCmpNode")
def conditional_object(int a):
"""
>>> conditional_object(1)
1
>>> conditional_object(0)
'2'
>>> conditional_object(5)
'2'
"""
return 1 if a in (1,2,3,4) else '2'
@cython.test_assert_path_exists("//SwitchStatNode")
@cython.test_fail_if_path_exists("//BoolBinopNode", "//PrimaryCmpNode")
def conditional_bytes(char a):
"""
>>> conditional_bytes(ord('a'))
1
>>> conditional_bytes(ord('X'))
'2'
>>> conditional_bytes(0)
'2'
"""
return 1 if a in b'abc' else '2'
@cython.test_assert_path_exists("//SwitchStatNode")
@cython.test_fail_if_path_exists("//BoolBinopNode", "//PrimaryCmpNode")
def conditional_unicode(Py_UNICODE a):
"""
>>> conditional_unicode(ord('a'))
1
>>> conditional_unicode(ord('X'))
'2'
>>> conditional_unicode(0)
'2'
"""
return 1 if a in u'abc' else '2'
@cython.test_assert_path_exists("//SwitchStatNode")
@cython.test_fail_if_path_exists("//BoolBinopNode", "//PrimaryCmpNode")
def conditional_none(int a):
"""
>>> conditional_none(1)
>>> conditional_none(0)
1
>>> conditional_none(5)
1
"""
return None if a in {1,2,3,4} else 1
def n(a):
"""
>>> n('d *')
......
cimport cython
dict_size = 4
d = dict(zip(range(10,dict_size+10), range(dict_size)))
@cython.test_fail_if_path_exists(
"//WhileStatNode")
def items(dict d):
"""
>>> items(d)
......@@ -12,6 +17,10 @@ def items(dict d):
l.sort()
return l
@cython.test_assert_path_exists(
"//WhileStatNode",
"//WhileStatNode/SimpleCallNode",
"//WhileStatNode/SimpleCallNode/NameNode")
def iteritems(dict d):
"""
>>> iteritems(d)
......@@ -23,6 +32,10 @@ def iteritems(dict d):
l.sort()
return l
@cython.test_assert_path_exists(
"//WhileStatNode",
"//WhileStatNode/SimpleCallNode",
"//WhileStatNode/SimpleCallNode/NameNode")
def iteritems_int(dict d):
"""
>>> iteritems_int(d)
......@@ -35,6 +48,10 @@ def iteritems_int(dict d):
l.sort()
return l
@cython.test_assert_path_exists(
"//WhileStatNode",
"//WhileStatNode/SimpleCallNode",
"//WhileStatNode/SimpleCallNode/NameNode")
def iteritems_tuple(dict d):
"""
>>> iteritems_tuple(d)
......@@ -46,11 +63,19 @@ def iteritems_tuple(dict d):
l.sort()
return l
@cython.test_assert_path_exists(
"//WhileStatNode",
"//WhileStatNode/SimpleCallNode",
"//WhileStatNode/SimpleCallNode/NameNode")
def iteritems_listcomp(dict d):
cdef list l = [(k,v) for k,v in d.iteritems()]
l.sort()
return l
@cython.test_assert_path_exists(
"//WhileStatNode",
"//WhileStatNode/SimpleCallNode",
"//WhileStatNode/SimpleCallNode/NameNode")
def iterkeys(dict d):
"""
>>> iterkeys(d)
......@@ -62,6 +87,10 @@ def iterkeys(dict d):
l.sort()
return l
@cython.test_assert_path_exists(
"//WhileStatNode",
"//WhileStatNode/SimpleCallNode",
"//WhileStatNode/SimpleCallNode/NameNode")
def iterkeys_int(dict d):
"""
>>> iterkeys_int(d)
......@@ -74,6 +103,10 @@ def iterkeys_int(dict d):
l.sort()
return l
@cython.test_assert_path_exists(
"//WhileStatNode",
"//WhileStatNode/SimpleCallNode",
"//WhileStatNode/SimpleCallNode/NameNode")
def iterdict(dict d):
"""
>>> iterdict(d)
......@@ -85,6 +118,10 @@ def iterdict(dict d):
l.sort()
return l
@cython.test_assert_path_exists(
"//WhileStatNode",
"//WhileStatNode/SimpleCallNode",
"//WhileStatNode/SimpleCallNode/NameNode")
def iterdict_int(dict d):
"""
>>> iterdict_int(d)
......@@ -97,6 +134,10 @@ def iterdict_int(dict d):
l.sort()
return l
@cython.test_assert_path_exists(
"//WhileStatNode",
"//WhileStatNode/SimpleCallNode",
"//WhileStatNode/SimpleCallNode/NameNode")
def iterdict_reassign(dict d):
"""
>>> iterdict_reassign(d)
......@@ -110,11 +151,23 @@ def iterdict_reassign(dict d):
l.sort()
return l
@cython.test_assert_path_exists(
"//WhileStatNode",
"//WhileStatNode/SimpleCallNode",
"//WhileStatNode/SimpleCallNode/NameNode")
def iterdict_listcomp(dict d):
"""
>>> iterdict_listcomp(d)
[10, 11, 12, 13]
"""
cdef list l = [k for k in d]
l.sort()
return l
@cython.test_assert_path_exists(
"//WhileStatNode",
"//WhileStatNode/SimpleCallNode",
"//WhileStatNode/SimpleCallNode/NameNode")
def itervalues(dict d):
"""
>>> itervalues(d)
......@@ -126,6 +179,10 @@ def itervalues(dict d):
l.sort()
return l
@cython.test_assert_path_exists(
"//WhileStatNode",
"//WhileStatNode/SimpleCallNode",
"//WhileStatNode/SimpleCallNode/NameNode")
def itervalues_int(dict d):
"""
>>> itervalues_int(d)
......@@ -138,7 +195,28 @@ def itervalues_int(dict d):
l.sort()
return l
@cython.test_assert_path_exists(
"//WhileStatNode",
"//WhileStatNode/SimpleCallNode",
"//WhileStatNode/SimpleCallNode/NameNode")
def itervalues_listcomp(dict d):
"""
>>> itervalues_listcomp(d)
[0, 1, 2, 3]
"""
cdef list l = [v for v in d.itervalues()]
l.sort()
return l
@cython.test_assert_path_exists(
"//WhileStatNode",
"//WhileStatNode/SimpleCallNode",
"//WhileStatNode/SimpleCallNode/NameNode")
def itervalues_kwargs(**d):
"""
>>> itervalues_kwargs(a=1, b=2, c=3, d=4)
[1, 2, 3, 4]
"""
cdef list l = [v for v in d.itervalues()]
l.sort()
return l
cimport cython
def f(a,b):
"""
>>> f(1,[1,2,3])
......@@ -44,6 +47,7 @@ def j(b):
result = 2 not in b
return result
@cython.test_fail_if_path_exists("//SwitchStatNode")
def k(a):
"""
>>> k(1)
......@@ -54,16 +58,227 @@ def k(a):
cdef int result = a not in [1,2,3,4]
return result
def m(int a):
@cython.test_assert_path_exists("//SwitchStatNode")
@cython.test_fail_if_path_exists("//PrimaryCmpNode")
def m_list(int a):
"""
>>> m(2)
>>> m_list(2)
0
>>> m(5)
>>> m_list(5)
1
"""
cdef int result = a not in [1,2,3,4]
return result
@cython.test_assert_path_exists("//SwitchStatNode")
@cython.test_fail_if_path_exists("//PrimaryCmpNode")
def m_tuple(int a):
"""
>>> m_tuple(2)
0
>>> m_tuple(5)
1
"""
cdef int result = a not in (1,2,3,4)
return result
@cython.test_assert_path_exists("//SwitchStatNode")
@cython.test_fail_if_path_exists("//BoolBinopNode", "//PrimaryCmpNode")
def m_set(int a):
"""
>>> m_set(2)
0
>>> m_set(5)
1
"""
cdef int result = a not in {1,2,3,4}
return result
cdef bytes bytes_string = b'abcdefg'
@cython.test_assert_path_exists("//PrimaryCmpNode")
@cython.test_fail_if_path_exists("//SwitchStatNode", "//BoolBinopNode")
def m_bytes(char a):
"""
>>> m_bytes(ord('f'))
0
>>> m_bytes(ord('X'))
1
"""
cdef int result = a not in bytes_string
return result
@cython.test_assert_path_exists("//SwitchStatNode")
@cython.test_fail_if_path_exists("//BoolBinopNode", "//PrimaryCmpNode")
def m_bytes_literal(char a):
"""
>>> m_bytes_literal(ord('f'))
0
>>> m_bytes_literal(ord('X'))
1
"""
cdef int result = a not in b'abcdefg'
return result
cdef unicode unicode_string = u'abcdefg\u1234\uF8D2'
py_unicode_string = unicode_string
cdef unicode klingon_character = u'\uF8D2'
py_klingon_character = klingon_character
@cython.test_assert_path_exists("//PrimaryCmpNode")
@cython.test_fail_if_path_exists("//SwitchStatNode", "//BoolBinopNode")
def m_unicode(Py_UNICODE a, unicode unicode_string):
"""
>>> m_unicode(ord('f'), py_unicode_string)
0
>>> m_unicode(ord('X'), py_unicode_string)
1
>>> m_unicode(ord(py_klingon_character), py_unicode_string)
0
>>> 'f' in None
Traceback (most recent call last):
TypeError: argument of type 'NoneType' is not iterable
>>> m_unicode(ord('f'), None)
Traceback (most recent call last):
TypeError: argument of type 'NoneType' is not iterable
"""
cdef int result = a not in unicode_string
return result
@cython.test_assert_path_exists("//SwitchStatNode")
@cython.test_fail_if_path_exists("//BoolBinopNode", "//PrimaryCmpNode")
def m_unicode_literal(Py_UNICODE a):
"""
>>> m_unicode_literal(ord('f'))
0
>>> m_unicode_literal(ord('X'))
1
>>> m_unicode_literal(ord(py_klingon_character))
0
"""
cdef int result = a not in u'abcdefg\u1234\uF8D2'
return result
@cython.test_assert_path_exists("//SwitchStatNode", "//BoolBinopNode")
@cython.test_fail_if_path_exists("//PrimaryCmpNode")
def m_tuple_in_or_notin(int a):
"""
>>> m_tuple_in_or_notin(2)
0
>>> m_tuple_in_or_notin(3)
1
>>> m_tuple_in_or_notin(5)
1
"""
cdef int result = a not in (1,2,3,4) or a in (3,4)
return result
@cython.test_assert_path_exists("//SwitchStatNode", "//BoolBinopNode")
@cython.test_fail_if_path_exists("//PrimaryCmpNode")
def m_tuple_notin_or_notin(int a):
"""
>>> m_tuple_notin_or_notin(2)
1
>>> m_tuple_notin_or_notin(6)
1
>>> m_tuple_notin_or_notin(4)
0
"""
cdef int result = a not in (1,2,3,4) or a not in (4,5)
return result
@cython.test_assert_path_exists("//SwitchStatNode")
@cython.test_fail_if_path_exists("//BoolBinopNode", "//PrimaryCmpNode")
def m_tuple_notin_and_notin(int a):
"""
>>> m_tuple_notin_and_notin(2)
0
>>> m_tuple_notin_and_notin(6)
0
>>> m_tuple_notin_and_notin(5)
1
"""
cdef int result = a not in (1,2,3,4) and a not in (6,7)
return result
@cython.test_assert_path_exists("//SwitchStatNode", "//BoolBinopNode")
@cython.test_fail_if_path_exists("//PrimaryCmpNode")
def m_tuple_notin_and_notin_overlap(int a):
"""
>>> m_tuple_notin_and_notin_overlap(2)
0
>>> m_tuple_notin_and_notin_overlap(4)
0
>>> m_tuple_notin_and_notin_overlap(5)
1
"""
cdef int result = a not in (1,2,3,4) and a not in (3,4)
return result
@cython.test_assert_path_exists("//SwitchStatNode")
@cython.test_fail_if_path_exists("//BoolBinopNode", "//PrimaryCmpNode")
def conditional_int(int a):
"""
>>> conditional_int(1)
2
>>> conditional_int(0)
1
>>> conditional_int(5)
1
"""
return 1 if a not in (1,2,3,4) else 2
@cython.test_assert_path_exists("//SwitchStatNode")
@cython.test_fail_if_path_exists("//BoolBinopNode", "//PrimaryCmpNode")
def conditional_object(int a):
"""
>>> conditional_object(1)
'2'
>>> conditional_object(0)
1
>>> conditional_object(5)
1
"""
return 1 if a not in (1,2,3,4) else '2'
@cython.test_assert_path_exists("//SwitchStatNode")
@cython.test_fail_if_path_exists("//BoolBinopNode", "//PrimaryCmpNode")
def conditional_bytes(char a):
"""
>>> conditional_bytes(ord('a'))
'2'
>>> conditional_bytes(ord('X'))
1
>>> conditional_bytes(0)
1
"""
return 1 if a not in b'abc' else '2'
@cython.test_assert_path_exists("//SwitchStatNode")
@cython.test_fail_if_path_exists("//BoolBinopNode", "//PrimaryCmpNode")
def conditional_unicode(Py_UNICODE a):
"""
>>> conditional_unicode(ord('a'))
'2'
>>> conditional_unicode(ord('X'))
1
>>> conditional_unicode(0)
1
"""
return 1 if a not in u'abc' else '2'
@cython.test_assert_path_exists("//SwitchStatNode")
@cython.test_fail_if_path_exists("//BoolBinopNode", "//PrimaryCmpNode")
def conditional_none(int a):
"""
>>> conditional_none(1)
1
>>> conditional_none(0)
>>> conditional_none(5)
"""
return None if a not in {1,2,3,4} else 1
def n(a):
"""
>>> n('d *')
......
......@@ -104,3 +104,42 @@ def test_imports():
MyStruct3 = typedef(MyStruct[3])
MyStruct4 = my_typedef(MyStruct[4])
MyStruct5 = cy.typedef(MyStruct[5])
def test_declare_c_types(n):
"""
>>> test_declare_c_types(0)
>>> test_declare_c_types(1)
>>> test_declare_c_types(2)
"""
#
b00 = cython.declare(cython.bint, 0)
b01 = cython.declare(cython.bint, 1)
b02 = cython.declare(cython.bint, 2)
#
i00 = cython.declare(cython.uchar, n)
i01 = cython.declare(cython.char, n)
i02 = cython.declare(cython.schar, n)
i03 = cython.declare(cython.ushort, n)
i04 = cython.declare(cython.short, n)
i05 = cython.declare(cython.sshort, n)
i06 = cython.declare(cython.uint, n)
i07 = cython.declare(cython.int, n)
i08 = cython.declare(cython.sint, n)
i09 = cython.declare(cython.slong, n)
i10 = cython.declare(cython.long, n)
i11 = cython.declare(cython.ulong, n)
i12 = cython.declare(cython.slonglong, n)
i13 = cython.declare(cython.longlong, n)
i14 = cython.declare(cython.ulonglong, n)
i20 = cython.declare(cython.Py_ssize_t, n)
i21 = cython.declare(cython.size_t, n)
#
f00 = cython.declare(cython.float, n)
f01 = cython.declare(cython.double, n)
f02 = cython.declare(cython.longdouble, n)
#
#z00 = cython.declare(cython.complex, n+1j)
#z01 = cython.declare(cython.floatcomplex, n+1j)
#z02 = cython.declare(cython.doublecomplex, n+1j)
#z03 = cython.declare(cython.longdoublecomplex, n+1j)
# -*- coding: iso-8859-1 -*-
cdef Py_UNICODE char_ASCII = u'A'
cdef Py_UNICODE char_KLINGON = u'\uF8D2'
def compare_ASCII():
"""
>>> compare_ASCII()
True
False
False
"""
print(char_ASCII == u'A')
print(char_ASCII == u'B')
print(char_ASCII == u'\uF8D2')
def compare_KLINGON():
"""
>>> compare_ASCII()
True
False
False
"""
print(char_KLINGON == u'\uF8D2')
print(char_KLINGON == u'A')
print(char_KLINGON == u'B')
def index_literal(int i):
"""
>>> index_literal(0) == '1'
True
>>> index_literal(-5) == '1'
True
>>> index_literal(2) == '3'
True
>>> 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):
"""
>>> import sys
>>> unicode_cardinal(0)
0
>>> unicode_cardinal(1)
1
>>> unicode_cardinal(sys.maxunicode) == sys.maxunicode
True
>>> unicode_cardinal(-1) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
>>> unicode_cardinal(sys.maxunicode+1) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
"""
return i
__doc__ = u"""
>>> test(-2)
-2
>>> test(-1)
-1
>>> test(0)
0
>>> test(1)
1
>>> test(2)
2
>>> test(SSIZE_T_MAX) == SSIZE_T_MAX
True
>>> test(SSIZE_T_MIN) == SSIZE_T_MIN
True
>>> test(SSIZE_T_MAX+1) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
>>> test(SSIZE_T_MIN-1) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
>>> test(1<<128) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
>>> test(-(1<<128)) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
>>> a = A(1,2)
>>> a.a == 1
True
>>> a.b == 2
True
>>> a.foo(5)
5
>>> a.foo(1 << 180) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
"""
# XXX This should generate a warning !!!
cdef extern from *:
ctypedef long ssize_t
SSIZE_T_MAX = <ssize_t>((<size_t>-1)>>1)
SSIZE_T_MIN = (-SSIZE_T_MAX-1)
def test(ssize_t i):
return i
cdef class A:
cdef public ssize_t a
cdef readonly ssize_t b
def __init__(self, ssize_t a, object b):
self.a = a
self.b = b
cpdef ssize_t foo(self, ssize_t x):
cdef object o = x
return o
# -*- coding: utf-8 -*-
cimport cython
import sys
PY_VERSION = sys.version_info
text = u'ab jd sdflk as sa sadas asdas fsdf '
sep = u' '
multiline_text = u'''\
ab jd
sdflk as sa
sadas asdas fsdf '''
def print_all(l):
for s in l:
print(s)
# unicode.split(s, [sep, [maxsplit]])
@cython.test_assert_path_exists(
"//PythonCapiCallNode")
def split(unicode s):
"""
>>> print_all( text.split() )
ab
jd
sdflk
as
sa
sadas
asdas
fsdf
>>> print_all( split(text) )
ab
jd
sdflk
as
sa
sadas
asdas
fsdf
"""
return s.split()
@cython.test_assert_path_exists(
"//PythonCapiCallNode")
def split_sep(unicode s, sep):
"""
>>> print_all( text.split(sep) )
ab jd
sdflk as sa
sadas asdas fsdf
>>> print_all( split_sep(text, sep) )
ab jd
sdflk as sa
sadas asdas fsdf
"""
return s.split(sep)
@cython.test_fail_if_path_exists(
"//CoerceToPyTypeNode",
"//CastNode", "//TypecastNode")
@cython.test_assert_path_exists(
"//CoerceFromPyTypeNode",
"//PythonCapiCallNode")
def split_sep_max(unicode s, sep, max):
"""
>>> print_all( text.split(sep, 1) )
ab jd
sdflk as sa sadas asdas fsdf
>>> print_all( split_sep_max(text, sep, 1) )
ab jd
sdflk as sa sadas asdas fsdf
"""
return s.split(sep, max)
@cython.test_fail_if_path_exists(
"//CoerceToPyTypeNode", "//CoerceFromPyTypeNode",
"//CastNode", "//TypecastNode")
@cython.test_assert_path_exists(
"//PythonCapiCallNode")
def split_sep_max_int(unicode s, sep):
"""
>>> print_all( text.split(sep, 1) )
ab jd
sdflk as sa sadas asdas fsdf
>>> print_all( split_sep_max_int(text, sep) )
ab jd
sdflk as sa sadas asdas fsdf
"""
return s.split(sep, 1)
# unicode.splitlines(s, [keepends])
@cython.test_assert_path_exists(
"//PythonCapiCallNode")
def splitlines(unicode s):
"""
>>> len(multiline_text.splitlines())
3
>>> print_all( multiline_text.splitlines() )
ab jd
sdflk as sa
sadas asdas fsdf
>>> len(splitlines(multiline_text))
3
>>> print_all( splitlines(multiline_text) )
ab jd
sdflk as sa
sadas asdas fsdf
"""
return s.splitlines()
@cython.test_assert_path_exists(
"//PythonCapiCallNode")
def splitlines_keep(unicode s, keep):
"""
>>> len(multiline_text.splitlines(True))
3
>>> print_all( multiline_text.splitlines(True) )
ab jd
<BLANKLINE>
sdflk as sa
<BLANKLINE>
sadas asdas fsdf
>>> len(splitlines_keep(multiline_text, True))
3
>>> print_all( splitlines_keep(multiline_text, True) )
ab jd
<BLANKLINE>
sdflk as sa
<BLANKLINE>
sadas asdas fsdf
"""
return s.splitlines(keep)
@cython.test_fail_if_path_exists(
"//CoerceToPyTypeNode", "//CoerceFromPyTypeNode",
"//CastNode", "//TypecastNode")
@cython.test_assert_path_exists(
"//PythonCapiCallNode")
def splitlines_keep_bint(unicode s):
"""
>>> len(multiline_text.splitlines(True))
3
>>> print_all( multiline_text.splitlines(True) )
ab jd
<BLANKLINE>
sdflk as sa
<BLANKLINE>
sadas asdas fsdf
>>> print_all( multiline_text.splitlines(False) )
ab jd
sdflk as sa
sadas asdas fsdf
>>> len(splitlines_keep_bint(multiline_text))
7
>>> print_all( splitlines_keep_bint(multiline_text) )
ab jd
<BLANKLINE>
sdflk as sa
<BLANKLINE>
sadas asdas fsdf
--
ab jd
sdflk as sa
sadas asdas fsdf
"""
return s.splitlines(True) + ['--'] + s.splitlines(False)
# unicode.join(s, iterable)
pipe_sep = u'|'
@cython.test_fail_if_path_exists(
"//CoerceToPyTypeNode", "//CoerceFromPyTypeNode",
"//CastNode", "//TypecastNode")
@cython.test_assert_path_exists(
"//PythonCapiCallNode")
def join(unicode sep, l):
"""
>>> l = text.split()
>>> len(l)
8
>>> print( pipe_sep.join(l) )
ab|jd|sdflk|as|sa|sadas|asdas|fsdf
>>> print( join(pipe_sep, l) )
ab|jd|sdflk|as|sa|sadas|asdas|fsdf
"""
return sep.join(l)
@cython.test_fail_if_path_exists(
"//CoerceToPyTypeNode", "//CoerceFromPyTypeNode",
"//CastNode", "//TypecastNode", "//NoneCheckNode")
@cython.test_assert_path_exists(
"//PythonCapiCallNode")
def join_sep(l):
"""
>>> l = text.split()
>>> len(l)
8
>>> print( '|'.join(l) )
ab|jd|sdflk|as|sa|sadas|asdas|fsdf
>>> print( join_sep(l) )
ab|jd|sdflk|as|sa|sadas|asdas|fsdf
"""
return u'|'.join(l)
# unicode.startswith(s, prefix, [start, [end]])
@cython.test_fail_if_path_exists(
"//CoerceToPyTypeNode",
"//CoerceFromPyTypeNode",
"//CastNode", "//TypecastNode")
@cython.test_assert_path_exists(
"//PythonCapiCallNode")
def startswith(unicode s, sub):
"""
>>> text.startswith('ab ')
True
>>> startswith(text, 'ab ')
'MATCH'
>>> text.startswith('ab X')
False
>>> startswith(text, 'ab X')
'NO MATCH'
>>> PY_VERSION < (2,5) or text.startswith(('ab', 'ab '))
True
>>> startswith(text, ('ab', 'ab '))
'MATCH'
>>> PY_VERSION < (2,5) or not text.startswith((' ab', 'ab X'))
True
>>> startswith(text, (' ab', 'ab X'))
'NO MATCH'
"""
if s.startswith(sub):
return 'MATCH'
else:
return 'NO MATCH'
@cython.test_fail_if_path_exists(
"//CoerceToPyTypeNode",
"//CastNode", "//TypecastNode")
@cython.test_assert_path_exists(
"//CoerceFromPyTypeNode",
"//PythonCapiCallNode")
def startswith_start_end(unicode s, sub, start, end):
"""
>>> text.startswith('b ', 1, 5)
True
>>> startswith_start_end(text, 'b ', 1, 5)
'MATCH'
>>> text.startswith('b X', 1, 5)
False
>>> startswith_start_end(text, 'b X', 1, 5)
'NO MATCH'
"""
if s.startswith(sub, start, end):
return 'MATCH'
else:
return 'NO MATCH'
# unicode.endswith(s, prefix, [start, [end]])
@cython.test_fail_if_path_exists(
"//CoerceToPyTypeNode",
"//CoerceFromPyTypeNode",
"//CastNode", "//TypecastNode")
@cython.test_assert_path_exists(
"//PythonCapiCallNode")
def endswith(unicode s, sub):
"""
>>> text.endswith('fsdf ')
True
>>> endswith(text, 'fsdf ')
'MATCH'
>>> text.endswith('fsdf X')
False
>>> endswith(text, 'fsdf X')
'NO MATCH'
>>> PY_VERSION < (2,5) or text.endswith(('fsdf', 'fsdf '))
True
>>> endswith(text, ('fsdf', 'fsdf '))
'MATCH'
>>> PY_VERSION < (2,5) or not text.endswith(('fsdf', 'fsdf X'))
True
>>> endswith(text, ('fsdf', 'fsdf X'))
'NO MATCH'
"""
if s.endswith(sub):
return 'MATCH'
else:
return 'NO MATCH'
@cython.test_fail_if_path_exists(
"//CoerceToPyTypeNode",
"//CastNode", "//TypecastNode")
@cython.test_assert_path_exists(
"//CoerceFromPyTypeNode",
"//PythonCapiCallNode")
def endswith_start_end(unicode s, sub, start, end):
"""
>>> text.endswith('fsdf', 10, len(text)-1)
True
>>> endswith_start_end(text, 'fsdf', 10, len(text)-1)
'MATCH'
>>> text.endswith('fsdf ', 10, len(text)-1)
False
>>> endswith_start_end(text, 'fsdf ', 10, len(text)-1)
'NO MATCH'
>>> PY_VERSION < (2,5) or text.endswith(('fsd', 'fsdf'), 10, len(text)-1)
True
>>> endswith_start_end(text, ('fsd', 'fsdf'), 10, len(text)-1)
'MATCH'
>>> PY_VERSION < (2,5) or not text.endswith(('fsdf ', 'fsdf X'), 10, len(text)-1)
True
>>> endswith_start_end(text, ('fsdf ', 'fsdf X'), 10, len(text)-1)
'NO MATCH'
"""
if s.endswith(sub, start, end):
return 'MATCH'
else:
return 'NO MATCH'
# unicode.find(s, sub, [start, [end]])
@cython.test_fail_if_path_exists(
"//CoerceFromPyTypeNode",
"//CastNode", "//TypecastNode")
@cython.test_assert_path_exists(
"//CoerceToPyTypeNode",
"//PythonCapiCallNode")
def find(unicode s, substring):
"""
>>> text.find('sa')
16
>>> find(text, 'sa')
16
"""
cdef Py_ssize_t pos = s.find(substring)
return pos
@cython.test_fail_if_path_exists(
"//CastNode", "//TypecastNode")
@cython.test_assert_path_exists(
"//CoerceToPyTypeNode",
"//PythonCapiCallNode")
def find_start_end(unicode s, substring, start, end):
"""
>>> text.find('sa', 17, 25)
20
>>> find_start_end(text, 'sa', 17, 25)
20
"""
cdef Py_ssize_t pos = s.find(substring, start, end)
return pos
# unicode.rfind(s, sub, [start, [end]])
@cython.test_fail_if_path_exists(
"//CoerceFromPyTypeNode",
"//CastNode", "//TypecastNode")
@cython.test_assert_path_exists(
"//CoerceToPyTypeNode",
"//PythonCapiCallNode")
def rfind(unicode s, substring):
"""
>>> text.rfind('sa')
20
>>> rfind(text, 'sa')
20
"""
cdef Py_ssize_t pos = s.rfind(substring)
return pos
@cython.test_fail_if_path_exists(
"//CastNode", "//TypecastNode")
@cython.test_assert_path_exists(
"//CoerceToPyTypeNode",
"//PythonCapiCallNode")
def rfind_start_end(unicode s, substring, start, end):
"""
>>> text.rfind('sa', 14, 19)
16
>>> rfind_start_end(text, 'sa', 14, 19)
16
"""
cdef Py_ssize_t pos = s.rfind(substring, start, end)
return pos
# unicode.count(s, sub, [start, [end]])
@cython.test_fail_if_path_exists(
"//CoerceFromPyTypeNode",
"//CastNode", "//TypecastNode")
@cython.test_assert_path_exists(
"//CoerceToPyTypeNode",
"//PythonCapiCallNode")
def count(unicode s, substring):
"""
>>> text.count('sa')
2
>>> count(text, 'sa')
2
"""
cdef Py_ssize_t pos = s.count(substring)
return pos
@cython.test_fail_if_path_exists(
"//CastNode", "//TypecastNode")
@cython.test_assert_path_exists(
"//CoerceToPyTypeNode",
"//PythonCapiCallNode")
def count_start_end(unicode s, substring, start, end):
"""
>>> text.count('sa', 14, 21)
1
>>> text.count('sa', 14, 22)
2
>>> count_start_end(text, 'sa', 14, 21)
1
>>> count_start_end(text, 'sa', 14, 22)
2
"""
cdef Py_ssize_t pos = s.count(substring, start, end)
return pos
# unicode.replace(s, sub, repl, [maxcount])
@cython.test_fail_if_path_exists(
"//CoerceFromPyTypeNode",
"//CastNode", "//TypecastNode")
@cython.test_assert_path_exists(
"//PythonCapiCallNode")
def replace(unicode s, substring, repl):
"""
>>> print( text.replace('sa', 'SA') )
ab jd sdflk as SA SAdas asdas fsdf
>>> print( replace(text, 'sa', 'SA') )
ab jd sdflk as SA SAdas asdas fsdf
"""
return s.replace(substring, repl)
@cython.test_fail_if_path_exists(
"//CastNode", "//TypecastNode")
@cython.test_assert_path_exists(
"//CoerceFromPyTypeNode",
"//PythonCapiCallNode")
def replace_maxcount(unicode s, substring, repl, maxcount):
"""
>>> print( text.replace('sa', 'SA', 1) )
ab jd sdflk as SA sadas asdas fsdf
>>> print( replace_maxcount(text, 'sa', 'SA', 1) )
ab jd sdflk as SA sadas asdas fsdf
"""
return s.replace(substring, repl, maxcount)
import sys
if sys.version_info[0] >= 3:
__doc__ = u"""
>>> test_signed()
3 <class 'int'>
9 <class 'int'>
6 <class 'int'>
12 <class 'int'>
"""
else:
__doc__ = u"""
>>> test_signed()
3 <type 'int'>
9 <type 'long'>
6 <type 'long'>
12 <type 'long'>
"""
cdef int i = 1
cdef long l = 2
cdef unsigned int ui = 4
cdef unsigned long ul = 8
def test_signed():
print i + l, type(i+l)
print i + ul, type(i+ul)
print ui + l, type(ui+l)
print ui + ul, type(ui+ul)
def test_add():
"""
>>> test_add()
3
9
6
12
"""
print i + l
print i + ul
print ui + l
print ui + ul
def test_add_sshort_ulong(signed short a, unsigned long b):
"""
>>> test_add_sshort_ulong(1, 1) == 2
True
>>> test_add_sshort_ulong(-1, 1) == 0
True
>>> test_add_sshort_ulong(-2, 1) == -1
False
"""
return a + b
def test_add_ushort_slonglong(unsigned short a, signed long long b):
"""
>>> test_add_ushort_slonglong(1, 1) == 2
True
>>> test_add_ushort_slonglong(1, -1) == 0
True
>>> test_add_ushort_slonglong(1, -2) == -1
True
"""
return a + b
def test_add_slong_ulong(signed long a, unsigned long b):
"""
>>> test_add_slong_ulong(1, 1) == 2
True
>>> test_add_slong_ulong(-1, 1) == 0
True
>>> test_add_slong_ulong(-2, 1) == -1
False
"""
return a + b
from __future__ import with_statement
import sys
if sys.version_info < (2,5):
__doc__ = __doc__.replace(u"exit <type 'type'> <type 'MyException'>",
u"exit <type 'classobj'> <type 'instance'>")
def typename(t):
return u"<type '%s'>" % type(t).__name__
......
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