Commit dae30554 authored by Stefan Behnel's avatar Stefan Behnel

merge

parents 7d5d84ac 098f56b9
...@@ -11,3 +11,5 @@ cdf889c30e7a7053de20bae3a578dad09ebcbdf5 0.10.3 ...@@ -11,3 +11,5 @@ cdf889c30e7a7053de20bae3a578dad09ebcbdf5 0.10.3
a4abf0156540db4d3ebaa95712b65811c43c5acb 0.11-beta a4abf0156540db4d3ebaa95712b65811c43c5acb 0.11-beta
838a6b7cae62e01dc0ce663cccab1f93f649fdbd 0.11.rc 838a6b7cae62e01dc0ce663cccab1f93f649fdbd 0.11.rc
4497f635d5fdbd38ebb841be4869fbfa2bbfdbb6 0.11.1.alpha 4497f635d5fdbd38ebb841be4869fbfa2bbfdbb6 0.11.1.alpha
7bc36a0f81723117a19f92ffde1676a0884fef65 0.11.1.beta
6454db601984145f38e28d34176fca8a3a22329c 0.11.1
...@@ -165,6 +165,7 @@ impl = """ ...@@ -165,6 +165,7 @@ impl = """
static PyObject* __Pyx_PyRun(PyObject* o, PyObject* globals, PyObject* locals) { static PyObject* __Pyx_PyRun(PyObject* o, PyObject* globals, PyObject* locals) {
PyObject* result; PyObject* result;
PyObject* s = 0; PyObject* s = 0;
char *code = 0;
if (!locals && !globals) { if (!locals && !globals) {
globals = PyModule_GetDict(%s);""" % Naming.module_cname + """ globals = PyModule_GetDict(%s);""" % Naming.module_cname + """
...@@ -192,13 +193,12 @@ static PyObject* __Pyx_PyRun(PyObject* o, PyObject* globals, PyObject* locals) { ...@@ -192,13 +193,12 @@ static PyObject* __Pyx_PyRun(PyObject* o, PyObject* globals, PyObject* locals) {
goto bad; goto bad;
} }
result = PyRun_String(
#if PY_MAJOR_VERSION >= 3 #if PY_MAJOR_VERSION >= 3
PyBytes_AS_STRING(o), code = PyBytes_AS_STRING(o);
#else #else
PyString_AS_STRING(o), code = PyString_AS_STRING(o);
#endif #endif
Py_file_input, globals, locals); result = PyRun_String(code, Py_file_input, globals, locals);
Py_XDECREF(s); Py_XDECREF(s);
return result; return result;
......
...@@ -38,8 +38,9 @@ Options: ...@@ -38,8 +38,9 @@ Options:
-a, --annotate Produce a colorized HTML version of the source. -a, --annotate Produce a colorized HTML version of the source.
--line-directives Produce #line directives pointing to the .pyx source --line-directives Produce #line directives pointing to the .pyx source
--cplus Output a c++ rather than c file. --cplus Output a c++ rather than c file.
-X, --directive <name>=<value>[,<name=value,...] Overrides a compiler directive --directive <name>=<value>[,<name=value,...] Overrides a compiler directive
""" """
#The following experimental options are supported only on MacOSX: #The following experimental options are supported only on MacOSX:
# -C, --compile Compile generated .c file to .o file # -C, --compile Compile generated .c file to .o file
# -X, --link Link .o file to produce extension module (implies -C) # -X, --link Link .o file to produce extension module (implies -C)
...@@ -80,6 +81,10 @@ def parse_command_line(args): ...@@ -80,6 +81,10 @@ def parse_command_line(args):
elif option in ("-C", "--compile"): elif option in ("-C", "--compile"):
options.c_only = 0 options.c_only = 0
elif option in ("-X", "--link"): elif option in ("-X", "--link"):
if option == "-X":
print >>sys.stderr, "Deprecation warning: The -X command line switch will be changed to a"
print >>sys.stderr, "shorthand for --directive in Cython 0.12. Please use --link instead."
print >>sys.stderr
options.c_only = 0 options.c_only = 0
options.obj_only = 0 options.obj_only = 0
elif option in ("-+", "--cplus"): elif option in ("-+", "--cplus"):
......
...@@ -2021,7 +2021,7 @@ class SliceIndexNode(ExprNode): ...@@ -2021,7 +2021,7 @@ class SliceIndexNode(ExprNode):
check = stop check = stop
if check: if check:
code.putln("if (unlikely((%s) != %d)) {" % (check, target_size)) code.putln("if (unlikely((%s) != %d)) {" % (check, target_size))
code.putln('PyErr_Format(PyExc_ValueError, "Assignment to slice of wrong length, expected %%d, got %%d", %d, (%s));' % ( code.putln('PyErr_Format(PyExc_ValueError, "Assignment to slice of wrong length, expected %%"PY_FORMAT_SIZE_T"d, got %%"PY_FORMAT_SIZE_T"d", (Py_ssize_t)%d, (Py_ssize_t)(%s));' % (
target_size, check)) target_size, check))
code.putln(code.error_goto(self.pos)) code.putln(code.error_goto(self.pos))
code.putln("}") code.putln("}")
...@@ -4277,12 +4277,24 @@ class DivNode(NumBinopNode): ...@@ -4277,12 +4277,24 @@ class DivNode(NumBinopNode):
cdivision = None cdivision = None
cdivision_warnings = False cdivision_warnings = False
zerodivision_check = None
def analyse_types(self, env): def analyse_types(self, env):
NumBinopNode.analyse_types(self, env) NumBinopNode.analyse_types(self, env)
if not self.type.is_pyobject and env.directives['cdivision_warnings']: if not self.type.is_pyobject:
self.operand1 = self.operand1.coerce_to_simple(env) self.zerodivision_check = self.cdivision is None and not env.directives['cdivision']
self.operand2 = self.operand2.coerce_to_simple(env) if self.zerodivision_check or env.directives['cdivision_warnings']:
# Need to check ahead of time to warn or raise zero division error
self.operand1 = self.operand1.coerce_to_simple(env)
self.operand2 = self.operand2.coerce_to_simple(env)
if env.nogil:
error(self.pos, "Pythonic division not allowed without gil, consider using cython.cdivision(True)")
def zero_division_message(self):
if self.type.is_int:
return "integer division or modulo by zero"
else:
return "float division"
def generate_evaluation_code(self, code): def generate_evaluation_code(self, code):
if not self.type.is_pyobject: if not self.type.is_pyobject:
...@@ -4293,18 +4305,33 @@ class DivNode(NumBinopNode): ...@@ -4293,18 +4305,33 @@ class DivNode(NumBinopNode):
if not self.cdivision: if not self.cdivision:
code.globalstate.use_utility_code(div_int_utility_code.specialize(self.type)) code.globalstate.use_utility_code(div_int_utility_code.specialize(self.type))
NumBinopNode.generate_evaluation_code(self, code) NumBinopNode.generate_evaluation_code(self, code)
if not self.type.is_pyobject and code.globalstate.directives['cdivision_warnings']: self.generate_div_warning_code(code)
self.generate_div_warning_code(code)
def generate_div_warning_code(self, code): def generate_div_warning_code(self, code):
code.globalstate.use_utility_code(cdivision_warning_utility_code) if not self.type.is_pyobject:
code.putln("if ((%s < 0) ^ (%s < 0)) {" % ( if self.zerodivision_check:
self.operand1.result(), code.putln("if (unlikely(%s == 0)) {" % self.operand2.result())
self.operand2.result())) code.putln('PyErr_Format(PyExc_ZeroDivisionError, "%s");' % self.zero_division_message())
code.putln(code.set_error_info(self.pos)); code.putln(code.error_goto(self.pos))
code.put("if (__Pyx_cdivision_warning()) ") code.putln("}")
code.put_goto(code.error_label) if self.type.is_int and self.type.signed and self.operator != '%':
code.putln("}") code.globalstate.use_utility_code(division_overflow_test_code)
code.putln("else if (sizeof(%s) == sizeof(long) && unlikely(%s == -1) && unlikely(UNARY_NEG_WOULD_OVERFLOW(%s))) {" % (
self.type.declaration_code(''),
self.operand2.result(),
self.operand1.result()))
code.putln('PyErr_Format(PyExc_OverflowError, "value too large to perform division");')
code.putln(code.error_goto(self.pos))
code.putln("}")
if code.globalstate.directives['cdivision_warnings']:
code.globalstate.use_utility_code(cdivision_warning_utility_code)
code.putln("if ((%s < 0) ^ (%s < 0)) {" % (
self.operand1.result(),
self.operand2.result()))
code.putln(code.set_error_info(self.pos));
code.put("if (__Pyx_cdivision_warning()) ")
code.put_goto(code.error_label)
code.putln("}")
def calculate_result_code(self): def calculate_result_code(self):
if self.type.is_float and self.operator == '//': if self.type.is_float and self.operator == '//':
...@@ -4330,6 +4357,12 @@ class ModNode(DivNode): ...@@ -4330,6 +4357,12 @@ class ModNode(DivNode):
or self.operand2.type.is_string or self.operand2.type.is_string
or NumBinopNode.is_py_operation(self)) or NumBinopNode.is_py_operation(self))
def zero_division_message(self):
if self.type.is_int:
return "integer division or modulo by zero"
else:
return "float divmod()"
def generate_evaluation_code(self, code): def generate_evaluation_code(self, code):
if not self.type.is_pyobject: if not self.type.is_pyobject:
if self.cdivision is None: if self.cdivision is None:
...@@ -4341,8 +4374,7 @@ class ModNode(DivNode): ...@@ -4341,8 +4374,7 @@ class ModNode(DivNode):
code.globalstate.use_utility_code( code.globalstate.use_utility_code(
mod_float_utility_code.specialize(self.type, math_h_modifier=self.type.math_h_modifier)) mod_float_utility_code.specialize(self.type, math_h_modifier=self.type.math_h_modifier))
NumBinopNode.generate_evaluation_code(self, code) NumBinopNode.generate_evaluation_code(self, code)
if not self.type.is_pyobject and code.globalstate.directives['cdivision_warnings']: self.generate_div_warning_code(code)
self.generate_div_warning_code(code)
def calculate_result_code(self): def calculate_result_code(self):
if self.cdivision: if self.cdivision:
...@@ -5762,3 +5794,10 @@ static int __Pyx_cdivision_warning(void) { ...@@ -5762,3 +5794,10 @@ static int __Pyx_cdivision_warning(void) {
'MODULENAME': Naming.modulename_cname, 'MODULENAME': Naming.modulename_cname,
'LINENO': Naming.lineno_cname, 'LINENO': Naming.lineno_cname,
}) })
# from intobject.c
division_overflow_test_code = UtilityCode(
proto="""
#define UNARY_NEG_WOULD_OVERFLOW(x) \
(((x) < 0) & ((unsigned long)(x) == 0-(unsigned long)(x)))
""")
...@@ -417,6 +417,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -417,6 +417,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln(" typedef int Py_ssize_t;") code.putln(" typedef int Py_ssize_t;")
code.putln(" #define PY_SSIZE_T_MAX INT_MAX") code.putln(" #define PY_SSIZE_T_MAX INT_MAX")
code.putln(" #define PY_SSIZE_T_MIN INT_MIN") code.putln(" #define PY_SSIZE_T_MIN INT_MIN")
code.putln(" #define PY_FORMAT_SIZE_T \"\"")
code.putln(" #define PyInt_FromSsize_t(z) PyInt_FromLong(z)") code.putln(" #define PyInt_FromSsize_t(z) PyInt_FromLong(z)")
code.putln(" #define PyInt_AsSsize_t(o) PyInt_AsLong(o)") code.putln(" #define PyInt_AsSsize_t(o) PyInt_AsLong(o)")
code.putln(" #define PyNumber_Index(o) PyNumber_Int(o)") code.putln(" #define PyNumber_Index(o) PyNumber_Int(o)")
...@@ -549,6 +550,12 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -549,6 +550,12 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
env.use_utility_code(streq_utility_code) env.use_utility_code(streq_utility_code)
# XXX this is a mess
for utility_code in PyrexTypes.c_int_from_py_function.specialize_list:
env.use_utility_code(utility_code)
for utility_code in PyrexTypes.c_long_from_py_function.specialize_list:
env.use_utility_code(utility_code)
def generate_extern_c_macro_definition(self, code): def generate_extern_c_macro_definition(self, code):
name = Naming.extern_c_macro name = Naming.extern_c_macro
code.putln("#ifdef __cplusplus") code.putln("#ifdef __cplusplus")
...@@ -1948,10 +1955,14 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -1948,10 +1955,14 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
if weakref_entry: if weakref_entry:
if weakref_entry.type is py_object_type: if weakref_entry.type is py_object_type:
tp_weaklistoffset = "%s.tp_weaklistoffset" % typeobj_cname tp_weaklistoffset = "%s.tp_weaklistoffset" % typeobj_cname
code.putln("if (%s == 0) %s = offsetof(struct %s, %s);" % ( if type.typedef_flag:
objstruct = type.objstruct_cname
else:
objstruct = "struct %s" % type.objstruct_cname
code.putln("if (%s == 0) %s = offsetof(%s, %s);" % (
tp_weaklistoffset, tp_weaklistoffset,
tp_weaklistoffset, tp_weaklistoffset,
type.objstruct_cname, objstruct,
weakref_entry.cname)) weakref_entry.cname))
else: else:
error(weakref_entry.pos, "__weakref__ slot must be of type 'object'") error(weakref_entry.pos, "__weakref__ slot must be of type 'object'")
......
...@@ -891,12 +891,13 @@ class CEnumDefNode(StatNode): ...@@ -891,12 +891,13 @@ class CEnumDefNode(StatNode):
temp, temp,
item.cname, item.cname,
code.error_goto_if_null(temp, item.pos))) code.error_goto_if_null(temp, item.pos)))
code.put_gotref(temp)
code.putln('if (__Pyx_SetAttrString(%s, "%s", %s) < 0) %s' % ( code.putln('if (__Pyx_SetAttrString(%s, "%s", %s) < 0) %s' % (
Naming.module_cname, Naming.module_cname,
item.name, item.name,
temp, temp,
code.error_goto(item.pos))) code.error_goto(item.pos)))
code.putln("%s = 0;" % temp) code.put_decref_clear(temp, PyrexTypes.py_object_type)
code.funcstate.release_temp(temp) code.funcstate.release_temp(temp)
...@@ -984,6 +985,7 @@ class FuncDefNode(StatNode, BlockNode): ...@@ -984,6 +985,7 @@ class FuncDefNode(StatNode, BlockNode):
if type.is_cfunction: if type.is_cfunction:
lenv.nogil = type.nogil and not type.with_gil lenv.nogil = type.nogil and not type.with_gil
self.local_scope = lenv self.local_scope = lenv
lenv.directives = env.directives
return lenv return lenv
def generate_function_definitions(self, env, code): def generate_function_definitions(self, env, code):
...@@ -1257,9 +1259,7 @@ class CFuncDefNode(FuncDefNode): ...@@ -1257,9 +1259,7 @@ class CFuncDefNode(FuncDefNode):
return self.entry.name return self.entry.name
def analyse_declarations(self, env): def analyse_declarations(self, env):
if 'locals' in env.directives and env.directives['locals']: directive_locals = self.directive_locals = env.directives['locals']
self.directive_locals = env.directives['locals']
directive_locals = self.directive_locals
base_type = self.base_type.analyse(env) base_type = self.base_type.analyse(env)
# The 2 here is because we need both function and argument names. # The 2 here is because we need both function and argument names.
name_declarator, type = self.declarator.analyse(base_type, env, nonempty = 2 * (self.body is not None)) name_declarator, type = self.declarator.analyse(base_type, env, nonempty = 2 * (self.body is not None))
...@@ -1606,11 +1606,7 @@ class DefNode(FuncDefNode): ...@@ -1606,11 +1606,7 @@ class DefNode(FuncDefNode):
directive_locals = getattr(cfunc, 'directive_locals', {})) directive_locals = getattr(cfunc, 'directive_locals', {}))
def analyse_declarations(self, env): def analyse_declarations(self, env):
if 'locals' in env.directives: directive_locals = self.directive_locals = env.directives['locals']
directive_locals = env.directives['locals']
else:
directive_locals = {}
self.directive_locals = directive_locals
for arg in self.args: for arg in self.args:
if hasattr(arg, 'name'): if hasattr(arg, 'name'):
type = arg.type type = arg.type
...@@ -2524,6 +2520,7 @@ class PyClassDefNode(ClassDefNode): ...@@ -2524,6 +2520,7 @@ class PyClassDefNode(ClassDefNode):
def analyse_declarations(self, env): def analyse_declarations(self, env):
self.target.analyse_target_declaration(env) self.target.analyse_target_declaration(env)
cenv = self.create_scope(env) cenv = self.create_scope(env)
cenv.directives = env.directives
cenv.class_obj_cname = self.target.entry.cname cenv.class_obj_cname = self.target.entry.cname
self.body.analyse_declarations(cenv) self.body.analyse_declarations(cenv)
...@@ -2660,6 +2657,8 @@ class CClassDefNode(ClassDefNode): ...@@ -2660,6 +2657,8 @@ class CClassDefNode(ClassDefNode):
if home_scope is not env and self.visibility == 'extern': if home_scope is not env and self.visibility == 'extern':
env.add_imported_entry(self.class_name, self.entry, pos) env.add_imported_entry(self.class_name, self.entry, pos)
scope = self.entry.type.scope scope = self.entry.type.scope
if scope is not None:
scope.directives = env.directives
if self.doc and Options.docstrings: if self.doc and Options.docstrings:
scope.doc = embed_position(self.pos, self.doc) scope.doc = embed_position(self.pos, self.doc)
...@@ -2705,6 +2704,7 @@ class PropertyNode(StatNode): ...@@ -2705,6 +2704,7 @@ class PropertyNode(StatNode):
def analyse_declarations(self, env): def analyse_declarations(self, env):
entry = env.declare_property(self.name, self.doc, self.pos) entry = env.declare_property(self.name, self.doc, self.pos)
if entry: if entry:
entry.scope.directives = env.directives
self.body.analyse_declarations(entry.scope) self.body.analyse_declarations(entry.scope)
def analyse_expressions(self, env): def analyse_expressions(self, env):
...@@ -3874,12 +3874,28 @@ class ForFromStatNode(LoopNode, StatNode): ...@@ -3874,12 +3874,28 @@ class ForFromStatNode(LoopNode, StatNode):
self.body.generate_execution_code(code) self.body.generate_execution_code(code)
code.put_label(code.continue_label) code.put_label(code.continue_label)
if self.py_loopvar_node: if self.py_loopvar_node:
# Reassign py variable to loop var here. # This mess is to make for..from loops with python targets behave
# (For consistancy, should rarely come up in practice.) # exactly like those with C targets with regards to re-assignment
# of the loop variable.
import ExprNodes import ExprNodes
from_py_node = ExprNodes.CoerceFromPyTypeNode(self.loopvar_node.type, self.target, None) if self.target.entry.is_pyglobal:
# We know target is a NameNode, this is the only ugly case.
target_node = ExprNodes.PyTempNode(self.target.pos, None)
target_node.result_code = code.funcstate.allocate_temp(py_object_type, False)
code.putln("%s = __Pyx_GetName(%s, %s); %s" % (
target_node.result_code,
Naming.module_cname,
self.target.entry.interned_cname,
code.error_goto_if_null(target_node.result_code, self.target.pos)))
code.put_gotref(target_node.result_code)
else:
target_node = self.target
from_py_node = ExprNodes.CoerceFromPyTypeNode(self.loopvar_node.type, target_node, None)
from_py_node.temp_code = loopvar_name from_py_node.temp_code = loopvar_name
from_py_node.generate_result_code(code) from_py_node.generate_result_code(code)
if self.target.entry.is_pyglobal:
code.put_decref_clear(target_node.result_code, py_object_type)
code.funcstate.release_temp(target_node.result_code)
code.putln("}") code.putln("}")
if self.py_loopvar_node: if self.py_loopvar_node:
# This is potentially wasteful, but we don't want the semantics to # This is potentially wasteful, but we don't want the semantics to
......
...@@ -332,13 +332,20 @@ class InterpretCompilerDirectives(CythonTransform, SkipDeclarations): ...@@ -332,13 +332,20 @@ class InterpretCompilerDirectives(CythonTransform, SkipDeclarations):
def __init__(self, context, compilation_option_overrides): def __init__(self, context, compilation_option_overrides):
super(InterpretCompilerDirectives, self).__init__(context) super(InterpretCompilerDirectives, self).__init__(context)
self.compilation_option_overrides = compilation_option_overrides self.compilation_option_overrides = {}
for key, value in compilation_option_overrides.iteritems():
self.compilation_option_overrides[unicode(key)] = value
self.cython_module_names = set() self.cython_module_names = set()
self.option_names = {} self.option_names = {}
# Set up processing and handle the cython: comments. # Set up processing and handle the cython: comments.
def visit_ModuleNode(self, node): def visit_ModuleNode(self, node):
options = copy.copy(Options.option_defaults) options = copy.copy(Options.option_defaults)
for key, value in self.compilation_option_overrides.iteritems():
if key in node.option_comments and node.option_comments[key] != value:
warning(node.pos, "Compiler directive differs between environment and file header; this will change "
"in Cython 0.12. See http://article.gmane.org/gmane.comp.python.cython.devel/5233", 2)
break
options.update(node.option_comments) options.update(node.option_comments)
options.update(self.compilation_option_overrides) options.update(self.compilation_option_overrides)
self.options = options self.options = options
...@@ -659,7 +666,6 @@ class DecoratorTransform(CythonTransform, SkipDeclarations): ...@@ -659,7 +666,6 @@ class DecoratorTransform(CythonTransform, SkipDeclarations):
return [func_node, reassignment] return [func_node, reassignment]
ERR_DEC_AFTER = "cdef variable '%s' declared after it is used"
class AnalyseDeclarationsTransform(CythonTransform): class AnalyseDeclarationsTransform(CythonTransform):
basic_property = TreeFragment(u""" basic_property = TreeFragment(u"""
...@@ -673,22 +679,22 @@ property NAME: ...@@ -673,22 +679,22 @@ property NAME:
def __call__(self, root): def __call__(self, root):
self.env_stack = [root.scope] self.env_stack = [root.scope]
# needed to determine if a cdef var is declared after it's used. # needed to determine if a cdef var is declared after it's used.
self.local_scope_stack = [] self.seen_vars_stack = []
return super(AnalyseDeclarationsTransform, self).__call__(root) return super(AnalyseDeclarationsTransform, self).__call__(root)
def visit_NameNode(self, node): def visit_NameNode(self, node):
self.local_scope_stack[-1].add(node.name) self.seen_vars_stack[-1].add(node.name)
return node return node
def visit_ModuleNode(self, node): def visit_ModuleNode(self, node):
self.local_scope_stack.append(set()) self.seen_vars_stack.append(set())
node.analyse_declarations(self.env_stack[-1]) node.analyse_declarations(self.env_stack[-1])
self.visitchildren(node) self.visitchildren(node)
self.local_scope_stack.pop() self.seen_vars_stack.pop()
return node return node
def visit_FuncDefNode(self, node): def visit_FuncDefNode(self, node):
self.local_scope_stack.append(set()) self.seen_vars_stack.append(set())
lenv = node.create_local_scope(self.env_stack[-1]) lenv = node.create_local_scope(self.env_stack[-1])
node.body.analyse_control_flow(lenv) # this will be totally refactored node.body.analyse_control_flow(lenv) # this will be totally refactored
node.declare_arguments(lenv) node.declare_arguments(lenv)
...@@ -703,7 +709,7 @@ property NAME: ...@@ -703,7 +709,7 @@ property NAME:
self.env_stack.append(lenv) self.env_stack.append(lenv)
self.visitchildren(node) self.visitchildren(node)
self.env_stack.pop() self.env_stack.pop()
self.local_scope_stack.pop() self.seen_vars_stack.pop()
return node return node
# Some nodes are no longer needed after declaration # Some nodes are no longer needed after declaration
...@@ -728,9 +734,10 @@ property NAME: ...@@ -728,9 +734,10 @@ property NAME:
return None return None
def visit_CNameDeclaratorNode(self, node): def visit_CNameDeclaratorNode(self, node):
if node.name in self.local_scope_stack[-1]: if node.name in self.seen_vars_stack[-1]:
# cdef variable declared after it's used. entry = self.env_stack[-1].lookup(node.name)
error(node.pos, ERR_DEC_AFTER % node.name) if entry is None or entry.visibility != 'extern':
warning(node.pos, "cdef variable '%s' declared after it is used" % node.name, 2)
self.visitchildren(node) self.visitchildren(node)
return node return node
......
...@@ -228,6 +228,11 @@ class BufferType(BaseType): ...@@ -228,6 +228,11 @@ class BufferType(BaseType):
def __repr__(self): def __repr__(self):
return "<BufferType %r>" % self.base 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): class PyObjectType(PyrexType):
# #
...@@ -487,57 +492,123 @@ class CNumericType(CType): ...@@ -487,57 +492,123 @@ class CNumericType(CType):
return self.base_declaration_code(base, entity_code) return self.base_declaration_code(base, entity_code)
int_conversion_list = {}
type_conversion_functions = ""
type_conversion_predeclarations = "" type_conversion_predeclarations = ""
type_conversion_functions = ""
c_int_from_py_function = UtilityCode(
proto="""
static INLINE %(type)s __Pyx_PyInt_As%(SignWord)s%(TypeName)s(PyObject *);
""",
impl="""
static INLINE %(type)s __Pyx_PyInt_As%(SignWord)s%(TypeName)s(PyObject* x) {
if (sizeof(%(type)s) < sizeof(long)) {
long val = __Pyx_PyInt_AsLong(x);
if (unlikely(val != (long)(%(type)s)val)) {
if (unlikely(val == -1 && PyErr_Occurred()))
return (%(type)s)-1;""" + \
"%(IntValSignTest)s" + \
"""
PyErr_SetString(PyExc_OverflowError,
"value too large to convert to %(type)s");
return (%(type)s)-1;
}
return (%(type)s)val;
}
return (%(type)s)__Pyx_PyInt_As%(SignWord)sLong(x);
}
""")
intval_signtest = """
if (unlikely(%(var)s < 0)) {
PyErr_SetString(PyExc_OverflowError,
"can't convert negative value to %(type)s");
return (%(type)s)-1;
}"""
c_long_from_py_function = UtilityCode(
proto="""
static INLINE %(type)s __Pyx_PyInt_As%(SignWord)s%(TypeName)s(PyObject *);
""",
impl="""
static INLINE %(type)s __Pyx_PyInt_As%(SignWord)s%(TypeName)s(PyObject* x) {
#if PY_VERSION_HEX < 0x03000000
if (likely(PyInt_CheckExact(x) || PyInt_Check(x))) {
long val = PyInt_AS_LONG(x);""" + \
"%(IntValSignTest)s" + \
"""
return (%(type)s)val;
} else
#endif
if (likely(PyLong_CheckExact(x) || PyLong_Check(x))) {""" +\
"%(PyLongSignTest)s" + \
"""
return %(PyLongConvert)s(x);
} else {
%(type)s val;
PyObject *tmp = __Pyx_PyNumber_Int(x);
if (!tmp) return (%(type)s)-1;
val = __Pyx_PyInt_As%(SignWord)s%(TypeName)s(tmp);
Py_DECREF(tmp);
return val;
}
}
""")
pylong_signtest = """
if (unlikely(Py_SIZE(%(var)s) < 0)) {
PyErr_SetString(PyExc_OverflowError,
"can't convert negative value to %(type)s");
return (%(type)s)-1;
}"""
class CIntType(CNumericType): class CIntType(CNumericType):
is_int = 1 is_int = 1
typedef_flag = 0 typedef_flag = 0
to_py_function = "PyInt_FromLong" to_py_function = "PyInt_FromLong"
from_py_function = "__pyx_PyInt_AsLong" from_py_function = "__Pyx_PyInt_AsInt"
exception_value = -1 exception_value = -1
def __init__(self, rank, signed, pymemberdef_typecode = None, is_returncode = 0): def __init__(self, rank, signed, pymemberdef_typecode = None, is_returncode = 0):
CNumericType.__init__(self, rank, signed, pymemberdef_typecode) CNumericType.__init__(self, rank, signed, pymemberdef_typecode)
self.is_returncode = is_returncode self.is_returncode = is_returncode
if self.from_py_function == '__pyx_PyInt_AsLong': if self.from_py_function == "__Pyx_PyInt_AsInt":
self.from_py_function = self.get_type_conversion() self.from_py_function = self.get_type_conversion()
def get_type_conversion(self): def get_type_conversion(self):
# error on overflow ctype = self.declaration_code('')
c_type = self.sign_and_name() bits = ctype.split(" ", 1)
c_name = c_type.replace(' ', '_'); if len(bits) == 1:
func_name = "__pyx_PyInt_%s" % c_name; sign_word, type_name = "", bits[0]
if func_name not in int_conversion_list: else:
# no env to add utility code to sign_word, type_name = bits
global type_conversion_predeclarations, type_conversion_functions type_name = type_name.replace("PY_LONG_LONG","long long")
if self.signed: SignWord = sign_word.title()
neg_test = "" TypeName = type_name.title().replace(" ", "")
else: data = {'IntValSignTest' : "",
neg_test = " || (long_val < 0)" 'PyLongSignTest' : "",
type_conversion_predeclarations += """ 'PyLongConvert' : "",
static INLINE %(c_type)s %(func_name)s(PyObject* x);""" % {'c_type': c_type, 'c_name': c_name, 'func_name': func_name } }
type_conversion_functions += """ if not self.signed:
static INLINE %(c_type)s %(func_name)s(PyObject* x) { data['IntValSignTest'] = intval_signtest % {'var':"val", 'type':ctype}
if (sizeof(%(c_type)s) < sizeof(long)) { data['PyLongSignTest'] = pylong_signtest % {'var':"x", 'type':ctype}
long long_val = __pyx_PyInt_AsLong(x); if "Long" in TypeName:
%(c_type)s val = (%(c_type)s)long_val; data['PyLongConvert'] = \
if (unlikely((val != long_val) %(neg_test)s)) { "PyLong_As" + SignWord.replace("Signed", "") + TypeName
PyErr_SetString(PyExc_OverflowError, "value too large to convert to %(c_type)s"); # the replaces below are just for generating well indented C code
return (%(c_type)s)-1; data['IntValSignTest'] = "\n".join(
} [ln.replace(" "*4, "", 1) for ln in data['IntValSignTest'].split('\n')]
return val; )
} utility_code = c_long_from_py_function
else { else:
return __pyx_PyInt_AsLong(x); utility_code = c_int_from_py_function
} utility_code.specialize(self,
} SignWord=SignWord,
""" % {'c_type': c_type, 'c_name': c_name, 'func_name': func_name, 'neg_test': neg_test } TypeName=TypeName,
int_conversion_list[func_name] = True **data)
func_name = "__Pyx_PyInt_As%s%s" % (SignWord, TypeName)
return func_name return func_name
def assignable_from_resolved_type(self, src_type): def assignable_from_resolved_type(self, src_type):
return src_type.is_int or src_type.is_enum or src_type is error_type return src_type.is_int or src_type.is_enum or src_type is error_type
...@@ -551,40 +622,44 @@ class CBIntType(CIntType): ...@@ -551,40 +622,44 @@ class CBIntType(CIntType):
class CAnonEnumType(CIntType): class CAnonEnumType(CIntType):
is_enum = 1 is_enum = 1
def sign_and_name(self):
return 'int'
class CUIntType(CIntType): class CUIntType(CIntType):
to_py_function = "PyLong_FromUnsignedLong" to_py_function = "PyLong_FromUnsignedLong"
from_py_function = "PyInt_AsUnsignedLongMask"
exception_value = -1 exception_value = -1
class CLongType(CIntType):
to_py_function = "PyInt_FromLong"
class CULongType(CUIntType): class CULongType(CUIntType):
to_py_function = "PyLong_FromUnsignedLong" to_py_function = "PyLong_FromUnsignedLong"
from_py_function = "PyInt_AsUnsignedLongMask"
class CLongLongType(CIntType): class CLongLongType(CIntType):
is_longlong = 1 is_longlong = 1
to_py_function = "PyLong_FromLongLong" to_py_function = "PyLong_FromLongLong"
from_py_function = "__pyx_PyInt_AsLongLong"
class CULongLongType(CUIntType): class CULongLongType(CUIntType):
is_longlong = 1 is_longlong = 1
to_py_function = "PyLong_FromUnsignedLongLong" to_py_function = "PyLong_FromUnsignedLongLong"
from_py_function = "__pyx_PyInt_AsUnsignedLongLong"
class CPySSizeTType(CIntType): class CPySSizeTType(CIntType):
to_py_function = "PyInt_FromSsize_t" to_py_function = "PyInt_FromSsize_t"
from_py_function = "__pyx_PyIndex_AsSsize_t" from_py_function = "__Pyx_PyIndex_AsSsize_t"
def sign_and_name(self): def sign_and_name(self):
return rank_to_type_name[self.rank] return rank_to_type_name[self.rank]
...@@ -592,8 +667,8 @@ class CPySSizeTType(CIntType): ...@@ -592,8 +667,8 @@ class CPySSizeTType(CIntType):
class CSizeTType(CUIntType): class CSizeTType(CUIntType):
to_py_function = "__pyx_PyInt_FromSize_t" to_py_function = "__Pyx_PyInt_FromSize_t"
from_py_function = "__pyx_PyInt_AsSize_t" from_py_function = "__Pyx_PyInt_AsSize_t"
def sign_and_name(self): def sign_and_name(self):
return rank_to_type_name[self.rank] return rank_to_type_name[self.rank]
...@@ -1185,14 +1260,14 @@ c_ulonglong_type = CULongLongType(6, 0, "T_ULONGLONG") ...@@ -1185,14 +1260,14 @@ c_ulonglong_type = CULongLongType(6, 0, "T_ULONGLONG")
c_char_type = CIntType(0, 1, "T_CHAR") c_char_type = CIntType(0, 1, "T_CHAR")
c_short_type = CIntType(1, 1, "T_SHORT") c_short_type = CIntType(1, 1, "T_SHORT")
c_int_type = CIntType(2, 1, "T_INT") c_int_type = CIntType(2, 1, "T_INT")
c_long_type = CIntType(3, 1, "T_LONG") c_long_type = CLongType(3, 1, "T_LONG")
c_longlong_type = CLongLongType(6, 1, "T_LONGLONG") c_longlong_type = CLongLongType(6, 1, "T_LONGLONG")
c_bint_type = CBIntType(2, 1, "T_INT") c_bint_type = CBIntType(2, 1, "T_INT")
c_schar_type = CIntType(0, 2, "T_CHAR") c_schar_type = CIntType(0, 2, "T_CHAR")
c_sshort_type = CIntType(1, 2, "T_SHORT") c_sshort_type = CIntType(1, 2, "T_SHORT")
c_sint_type = CIntType(2, 2, "T_INT") c_sint_type = CIntType(2, 2, "T_INT")
c_slong_type = CIntType(3, 2, "T_LONG") c_slong_type = CLongType(3, 2, "T_LONG")
c_slonglong_type = CLongLongType(6, 2, "T_LONGLONG") c_slonglong_type = CLongLongType(6, 2, "T_LONGLONG")
c_py_ssize_t_type = CPySSizeTType(4, 2, "T_PYSSIZET") c_py_ssize_t_type = CPySSizeTType(4, 2, "T_PYSSIZET")
...@@ -1224,23 +1299,23 @@ unspecified_type = UnspecifiedType() ...@@ -1224,23 +1299,23 @@ unspecified_type = UnspecifiedType()
sign_and_rank_to_type = { sign_and_rank_to_type = {
#(signed, rank) #(signed, rank)
(0, 0): c_uchar_type, (0, 0): c_uchar_type,
(0, 1): c_ushort_type, (0, 1): c_ushort_type,
(0, 2): c_uint_type, (0, 2): c_uint_type,
(0, 3): c_ulong_type, (0, 3): c_ulong_type,
(0, 6): c_ulonglong_type, (0, 6): c_ulonglong_type,
(1, 0): c_char_type, (1, 0): c_char_type,
(1, 1): c_short_type, (1, 1): c_short_type,
(1, 2): c_int_type, (1, 2): c_int_type,
(1, 3): c_long_type, (1, 3): c_long_type,
(1, 6): c_longlong_type, (1, 6): c_longlong_type,
(2, 0): c_schar_type, (2, 0): c_schar_type,
(2, 1): c_sshort_type, (2, 1): c_sshort_type,
(2, 2): c_sint_type, (2, 2): c_sint_type,
(2, 3): c_slong_type, (2, 3): c_slong_type,
(2, 6): c_slonglong_type, (2, 6): c_slonglong_type,
(0, 4): c_py_ssize_t_type, (0, 4): c_py_ssize_t_type,
(1, 4): c_py_ssize_t_type, (1, 4): c_py_ssize_t_type,
...@@ -1249,36 +1324,36 @@ sign_and_rank_to_type = { ...@@ -1249,36 +1324,36 @@ sign_and_rank_to_type = {
(1, 5): c_size_t_type, (1, 5): c_size_t_type,
(2, 5): c_size_t_type, (2, 5): c_size_t_type,
(1, 7): c_float_type, (1, 7): c_float_type,
(1, 8): c_double_type, (1, 8): c_double_type,
(1, 9): c_longdouble_type, (1, 9): c_longdouble_type,
# In case we're mixing unsigned ints and floats... # In case we're mixing unsigned ints and floats...
(0, 7): c_float_type, (0, 7): c_float_type,
(0, 8): c_double_type, (0, 8): c_double_type,
(0, 9): c_longdouble_type, (0, 9): c_longdouble_type,
} }
modifiers_and_name_to_type = { modifiers_and_name_to_type = {
#(signed, longness, name) #(signed, longness, name)
(0, 0, "char"): c_uchar_type, (0, 0, "char"): c_uchar_type,
(0, -1, "int"): c_ushort_type, (0, -1, "int"): c_ushort_type,
(0, 0, "int"): c_uint_type, (0, 0, "int"): c_uint_type,
(0, 1, "int"): c_ulong_type, (0, 1, "int"): c_ulong_type,
(0, 2, "int"): c_ulonglong_type, (0, 2, "int"): c_ulonglong_type,
(1, 0, "void"): c_void_type, (1, 0, "void"): c_void_type,
(1, 0, "char"): c_char_type, (1, 0, "char"): c_char_type,
(1, -1, "int"): c_short_type, (1, -1, "int"): c_short_type,
(1, 0, "int"): c_int_type, (1, 0, "int"): c_int_type,
(1, 1, "int"): c_long_type, (1, 1, "int"): c_long_type,
(1, 2, "int"): c_longlong_type, (1, 2, "int"): c_longlong_type,
(1, 0, "float"): c_float_type, (1, 0, "float"): c_float_type,
(1, 0, "double"): c_double_type, (1, 0, "double"): c_double_type,
(1, 1, "double"): c_longdouble_type, (1, 1, "double"): c_longdouble_type,
(1, 0, "object"): py_object_type, (1, 0, "object"): py_object_type,
(1, 0, "bint"): c_bint_type, (1, 0, "bint"): c_bint_type,
(2, 0, "char"): c_schar_type, (2, 0, "char"): c_schar_type,
(2, -1, "int"): c_sshort_type, (2, -1, "int"): c_sshort_type,
(2, 0, "int"): c_sint_type, (2, 0, "int"): c_sint_type,
(2, 1, "int"): c_slong_type, (2, 1, "int"): c_slong_type,
(2, 2, "int"): c_slonglong_type, (2, 2, "int"): c_slonglong_type,
...@@ -1358,12 +1433,6 @@ def Node_to_type(node, env): ...@@ -1358,12 +1433,6 @@ def Node_to_type(node, env):
else: else:
error(node.pos, "Bad type") error(node.pos, "Bad type")
def public_decl(base, dll_linkage):
if dll_linkage:
return "%s(%s)" % (dll_linkage, base)
else:
return base
def same_type(type1, type2): def same_type(type1, type2):
return type1.same_as(type2) return type1.same_as(type2)
...@@ -1396,9 +1465,8 @@ type_conversion_predeclarations = """ ...@@ -1396,9 +1465,8 @@ type_conversion_predeclarations = """
#endif #endif
#define __Pyx_PyBool_FromLong(b) ((b) ? (Py_INCREF(Py_True), Py_True) : (Py_INCREF(Py_False), Py_False)) #define __Pyx_PyBool_FromLong(b) ((b) ? (Py_INCREF(Py_True), Py_True) : (Py_INCREF(Py_False), Py_False))
static INLINE int __Pyx_PyObject_IsTrue(PyObject* x); static INLINE int __Pyx_PyObject_IsTrue(PyObject*);
static INLINE PY_LONG_LONG __pyx_PyInt_AsLongLong(PyObject* x); static INLINE PyObject* __Pyx_PyNumber_Int(PyObject* x);
static INLINE unsigned PY_LONG_LONG __pyx_PyInt_AsUnsignedLongLong(PyObject* x);
#if !defined(T_PYSSIZET) #if !defined(T_PYSSIZET)
#if PY_VERSION_HEX < 0x02050000 #if PY_VERSION_HEX < 0x02050000
...@@ -1428,18 +1496,70 @@ static INLINE unsigned PY_LONG_LONG __pyx_PyInt_AsUnsignedLongLong(PyObject* x); ...@@ -1428,18 +1496,70 @@ static INLINE unsigned PY_LONG_LONG __pyx_PyInt_AsUnsignedLongLong(PyObject* x);
#endif #endif
#endif #endif
static INLINE Py_ssize_t __pyx_PyIndex_AsSsize_t(PyObject* b); static INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject*);
static INLINE PyObject * __pyx_PyInt_FromSize_t(size_t); static INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t);
static INLINE size_t __pyx_PyInt_AsSize_t(PyObject*); static INLINE size_t __Pyx_PyInt_AsSize_t(PyObject*);
#define __pyx_PyInt_AsLong(x) (PyInt_CheckExact(x) ? PyInt_AS_LONG(x) : PyInt_AsLong(x))
#define __pyx_PyFloat_AsDouble(x) (PyFloat_CheckExact(x) ? PyFloat_AS_DOUBLE(x) : PyFloat_AsDouble(x)) #define __pyx_PyFloat_AsDouble(x) (PyFloat_CheckExact(x) ? PyFloat_AS_DOUBLE(x) : PyFloat_AsDouble(x))
""" + type_conversion_predeclarations """ + type_conversion_predeclarations
type_conversion_functions = """ type_conversion_functions = """
/* Type Conversion Functions */ /* Type Conversion Functions */
static INLINE Py_ssize_t __pyx_PyIndex_AsSsize_t(PyObject* b) { static INLINE int __Pyx_PyObject_IsTrue(PyObject* x) {
if (x == Py_True) return 1;
else if ((x == Py_False) | (x == Py_None)) return 0;
else return PyObject_IsTrue(x);
}
static INLINE PyObject* __Pyx_PyNumber_Int(PyObject* x) {
PyNumberMethods *m;
const char *name = NULL;
PyObject *res = NULL;
#if PY_VERSION_HEX < 0x03000000
if (PyInt_Check(x) || PyLong_Check(x))
#else
if (PyLong_Check(x))
#endif
return Py_INCREF(x), x;
m = Py_TYPE(x)->tp_as_number;
#if PY_VERSION_HEX < 0x03000000
if (m && m->nb_long) {
name = "long";
res = PyNumber_Long(x);
}
else if (m && m->nb_int) {
name = "int";
res = PyNumber_Int(x);
}
#else
if (m && m->nb_int) {
name = "int";
res = PyNumber_Long(x);
}
#endif
if (res) {
#if PY_VERSION_HEX < 0x03000000
if (!PyInt_Check(res) && !PyLong_Check(res)) {
#else
if (!PyLong_Check(res)) {
#endif
PyErr_Format(PyExc_TypeError,
"__%s__ returned non-%s (type %.200s)",
name, name, Py_TYPE(res)->tp_name);
Py_DECREF(res);
return NULL;
}
}
else if (!PyErr_Occurred()) {
PyErr_SetString(PyExc_TypeError,
"an integer is required");
}
return res;
}
static INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject* b) {
Py_ssize_t ival; Py_ssize_t ival;
PyObject* x = PyNumber_Index(b); PyObject* x = PyNumber_Index(b);
if (!x) return -1; if (!x) return -1;
...@@ -1448,7 +1568,7 @@ static INLINE Py_ssize_t __pyx_PyIndex_AsSsize_t(PyObject* b) { ...@@ -1448,7 +1568,7 @@ static INLINE Py_ssize_t __pyx_PyIndex_AsSsize_t(PyObject* b) {
return ival; return ival;
} }
static INLINE PyObject * __pyx_PyInt_FromSize_t(size_t ival) { static INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t ival) {
#if PY_VERSION_HEX < 0x02050000 #if PY_VERSION_HEX < 0x02050000
if (ival <= LONG_MAX) if (ival <= LONG_MAX)
return PyInt_FromLong((long)ival); return PyInt_FromLong((long)ival);
...@@ -1462,74 +1582,16 @@ static INLINE PyObject * __pyx_PyInt_FromSize_t(size_t ival) { ...@@ -1462,74 +1582,16 @@ static INLINE PyObject * __pyx_PyInt_FromSize_t(size_t ival) {
#endif #endif
} }
static INLINE size_t __pyx_PyInt_AsSize_t(PyObject* b) { static INLINE size_t __Pyx_PyInt_AsSize_t(PyObject* x) {
unsigned PY_LONG_LONG val = __pyx_PyInt_AsUnsignedLongLong(b); unsigned PY_LONG_LONG val = __Pyx_PyInt_AsUnsignedLongLong(x);
if (unlikely(val == (unsigned PY_LONG_LONG)-1 && PyErr_Occurred())) { if (unlikely(val == (unsigned PY_LONG_LONG)-1 && PyErr_Occurred())) {
return (size_t)-1; return (size_t)-1;
} else if (unlikely(val != (unsigned PY_LONG_LONG)(size_t)val)) { } else if (unlikely(val != (unsigned PY_LONG_LONG)(size_t)val)) {
PyErr_SetString(PyExc_OverflowError, "value too large to convert to size_t"); PyErr_SetString(PyExc_OverflowError,
"value too large to convert to size_t");
return (size_t)-1; return (size_t)-1;
} }
return val; return (size_t)val;
}
static INLINE int __Pyx_PyObject_IsTrue(PyObject* x) {
if (x == Py_True) return 1;
else if ((x == Py_False) | (x == Py_None)) return 0;
else return PyObject_IsTrue(x);
}
static INLINE PY_LONG_LONG __pyx_PyInt_AsLongLong(PyObject* x) {
#if PY_VERSION_HEX < 0x03000000
if (PyInt_CheckExact(x)) {
return PyInt_AS_LONG(x);
}
else
#endif
if (PyLong_CheckExact(x)) {
return PyLong_AsLongLong(x);
}
else {
PY_LONG_LONG val;
#if PY_VERSION_HEX < 0x03000000
PyObject* tmp = PyNumber_Int(x); if (!tmp) return (PY_LONG_LONG)-1;
val = __pyx_PyInt_AsLongLong(tmp);
#else
PyObject* tmp = PyNumber_Long(x); if (!tmp) return (PY_LONG_LONG)-1;
val = PyLong_AsLongLong(tmp);
#endif
Py_DECREF(tmp);
return val;
}
}
static INLINE unsigned PY_LONG_LONG __pyx_PyInt_AsUnsignedLongLong(PyObject* x) {
#if PY_VERSION_HEX < 0x03000000
if (PyInt_CheckExact(x)) {
long val = PyInt_AS_LONG(x);
if (unlikely(val < 0)) {
PyErr_SetString(PyExc_OverflowError, "can't convert negative value to unsigned long long");
return (unsigned PY_LONG_LONG)-1;
}
return val;
}
else
#endif
if (PyLong_CheckExact(x)) {
return PyLong_AsUnsignedLongLong(x);
}
else {
unsigned PY_LONG_LONG val;
#if PY_VERSION_HEX < 0x03000000
PyObject* tmp = PyNumber_Int(x); if (!tmp) return (PY_LONG_LONG)-1;
val = __pyx_PyInt_AsUnsignedLongLong(tmp);
#else
PyObject* tmp = PyNumber_Long(x); if (!tmp) return (PY_LONG_LONG)-1;
val = PyLong_AsUnsignedLongLong(tmp);
#endif
Py_DECREF(tmp);
return val;
}
} }
""" + type_conversion_functions """ + type_conversion_functions
...@@ -48,6 +48,7 @@ def hash_source_file(path): ...@@ -48,6 +48,7 @@ def hash_source_file(path):
from hashlib import md5 as new_md5 from hashlib import md5 as new_md5
except ImportError: except ImportError:
from md5 import new as new_md5 from md5 import new as new_md5
f = None
try: try:
try: try:
f = open(path, "rU") f = open(path, "rU")
...@@ -56,7 +57,8 @@ def hash_source_file(path): ...@@ -56,7 +57,8 @@ def hash_source_file(path):
print("Unable to hash scanner source file (%s)" % e) print("Unable to hash scanner source file (%s)" % e)
return "" return ""
finally: finally:
f.close() if f:
f.close()
# Normalise spaces/tabs. We don't know what sort of # Normalise spaces/tabs. We don't know what sort of
# space-tab substitution the file may have been # space-tab substitution the file may have been
# through, so we replace all spans of spaces and # through, so we replace all spans of spaces and
......
...@@ -208,7 +208,6 @@ class Scope(object): ...@@ -208,7 +208,6 @@ class Scope(object):
scope_prefix = "" scope_prefix = ""
in_cinclude = 0 in_cinclude = 0
nogil = 0 nogil = 0
directives = {}
def __init__(self, name, outer_scope, parent_scope): def __init__(self, name, outer_scope, parent_scope):
# The outer_scope is the next scope in the lookup chain. # The outer_scope is the next scope in the lookup chain.
......
version = '0.11.1.alpha' version = '0.11.1'
cdef extern from "stdio.h": cdef extern from "stdio.h" nogil:
ctypedef struct FILE ctypedef struct FILE
int printf(char *format, ...) nogil int printf(char *format, ...)
int fprintf(FILE *stream, char *format, ...) nogil int fprintf(FILE *stream, char *format, ...)
int sprintf(char *str, char *format, ...) nogil int sprintf(char *str, char *format, ...)
FILE *fopen(char *path, char *mode) nogil FILE *fopen(char *path, char *mode)
int fclose(FILE *strea) nogil int fclose(FILE *strea)
cdef FILE *stdout cdef FILE *stdout
int scanf(char *format, ...) nogil int scanf(char *format, ...)
cdef extern from "stdlib.h": cdef extern from "stdlib.h" nogil:
void free(void *ptr) nogil void free(void *ptr)
void *malloc(size_t size) nogil void *malloc(size_t size)
void *realloc(void *ptr, size_t size) nogil void *realloc(void *ptr, size_t size)
size_t strlen(char *s) nogil size_t strlen(char *s)
char *strcpy(char *dest, char *src) nogil char *strcpy(char *dest, char *src)
...@@ -105,6 +105,7 @@ class UtilityCode(object): ...@@ -105,6 +105,7 @@ class UtilityCode(object):
self.cleanup = cleanup self.cleanup = cleanup
self.requires = requires self.requires = requires
self._cache = {} self._cache = {}
self.specialize_list = []
def write_init_code(self, writer, pos): def write_init_code(self, writer, pos):
if not self.init: if not self.init:
...@@ -141,4 +142,5 @@ class UtilityCode(object): ...@@ -141,4 +142,5 @@ class UtilityCode(object):
none_or_sub(self.init, data), none_or_sub(self.init, data),
none_or_sub(self.cleanup, data), none_or_sub(self.cleanup, data),
requires) requires)
self.specialize_list.append(s)
return s return s
...@@ -10,7 +10,7 @@ from distutils.command.build_ext import build_ext as _build_ext ...@@ -10,7 +10,7 @@ from distutils.command.build_ext import build_ext as _build_ext
distutils_distro = Distribution() distutils_distro = Distribution()
TEST_DIRS = ['compile', 'errors', 'run', 'pyregr'] TEST_DIRS = ['compile', 'errors', 'run', 'pyregr']
TEST_RUN_DIRS = ['run', 'pyregr', 'bugs'] TEST_RUN_DIRS = ['run', 'pyregr']
# Lists external modules, and a matcher matching tests # Lists external modules, and a matcher matching tests
# which should be excluded if the module is not present. # which should be excluded if the module is not present.
...@@ -91,8 +91,6 @@ class TestBuilder(object): ...@@ -91,8 +91,6 @@ class TestBuilder(object):
def build_suite(self): def build_suite(self):
suite = unittest.TestSuite() suite = unittest.TestSuite()
test_dirs = TEST_DIRS test_dirs = TEST_DIRS
if self.test_bugs and 'bugs' not in test_dirs:
test_dirs.append('bugs')
filenames = os.listdir(self.rootdir) filenames = os.listdir(self.rootdir)
filenames.sort() filenames.sort()
for filename in filenames: for filename in filenames:
...@@ -147,6 +145,9 @@ class TestBuilder(object): ...@@ -147,6 +145,9 @@ class TestBuilder(object):
languages = self.languages[:1] languages = self.languages[:1]
else: else:
languages = self.languages languages = self.languages
if 'cpp' in module and 'c' in languages:
languages = list(languages)
languages.remove('c')
tests = [ self.build_test(test_class, path, workdir, module, tests = [ self.build_test(test_class, path, workdir, module,
language, expect_errors) language, expect_errors)
for language in languages ] for language in languages ]
...@@ -463,6 +464,18 @@ class VersionDependencyExcluder: ...@@ -463,6 +464,18 @@ class VersionDependencyExcluder:
return True return True
return False return False
class FileListExcluder:
def __init__(self, list_file):
self.excludes = {}
for line in open(list_file).readlines():
line = line.strip()
if line and line[0] != '#':
self.excludes[line.split()[0]] = True
def __call__(self, testname):
return testname.split('.')[-1] in self.excludes
if __name__ == '__main__': if __name__ == '__main__':
from optparse import OptionParser from optparse import OptionParser
parser = OptionParser() parser = OptionParser()
...@@ -580,7 +593,7 @@ if __name__ == '__main__': ...@@ -580,7 +593,7 @@ if __name__ == '__main__':
if options.tickets: if options.tickets:
for ticket_number in options.tickets: for ticket_number in options.tickets:
test_bugs = True test_bugs = True
cmd_args.append('bugs.*T%s$' % ticket_number) cmd_args.append('.*T%s$' % ticket_number)
if not test_bugs: if not test_bugs:
for selector in cmd_args: for selector in cmd_args:
if selector.startswith('bugs'): if selector.startswith('bugs'):
...@@ -600,6 +613,9 @@ if __name__ == '__main__': ...@@ -600,6 +613,9 @@ if __name__ == '__main__':
if options.exclude: if options.exclude:
exclude_selectors += [ re.compile(r, re.I|re.U).search for r in options.exclude ] exclude_selectors += [ re.compile(r, re.I|re.U).search for r in options.exclude ]
if not test_bugs:
exclude_selectors += [ FileListExcluder("tests/bugs.txt") ]
languages = [] languages = []
if options.use_c: if options.use_c:
......
# This file contains tests corresponding to of unresolved bugs,
# which will be skipped in the normal testing run.
methodmangling_T5
class_attribute_init_values_T18
return_outside_function_T135
builtin_types_none_T166
numpy_ValueError_T172
unsignedbehaviour_T184
funcexc_iter_T228
pxd_override_T230
ext_instance_type_T232
large_consts_T237
bad_c_struct_T252
missing_baseclass_in_predecl_T262
ifelseexpr_T267
cdef_setitem_T284
extern int generic_error(void);
extern int specified_error(void);
extern int dynamic_error(void);
cdef void raise_py_error(): cdef void raise_py_error():
pass pass
cdef extern from "foo.h": cdef extern from "cpp_exceptions.h":
cdef int generic_error() except + cdef int generic_error() except +
cdef int specified_error() except +MemoryError cdef int specified_error() except +MemoryError
cdef int dynamic_error() except +raise_py_error cdef int dynamic_error() except +raise_py_error
......
__doc__ = u"""
"""
cdef class A:
cdef __weakref__
ctypedef public class B [type B_Type, object BObject]:
cdef __weakref__
cdef public class C [type C_Type, object CObject]:
cdef __weakref__
...@@ -49,8 +49,8 @@ cdef int *baz ...@@ -49,8 +49,8 @@ cdef int *baz
print var[0][0] print var[0][0]
cdef unsigned long long var[100][100] cdef unsigned long long var[100][100]
# in 0.11.1 these are warnings
_ERRORS = u""" FUTURE_ERRORS = u"""
4:13: cdef variable 's' declared after it is used 4:13: cdef variable 's' declared after it is used
4:16: cdef variable 'vv' declared after it is used 4:16: cdef variable 'vv' declared after it is used
9:14: cdef variable 'i' declared after it is used 9:14: cdef variable 'i' declared after it is used
...@@ -63,3 +63,12 @@ _ERRORS = u""" ...@@ -63,3 +63,12 @@ _ERRORS = u"""
47:10: cdef variable 'baz' declared after it is used 47:10: cdef variable 'baz' declared after it is used
50:24: cdef variable 'var' declared after it is used 50:24: cdef variable 'var' declared after it is used
""" """
syntax error
_ERRORS = u"""
40:17: cdef variable 't' declared after it is used
47:10: cdef variable 'baz' declared after it is used
50:24: cdef variable 'var' declared after it is used
67:7: Syntax error in simple statement list
"""
__doc__ = u""
# -------------------------------------------------------------------
CHAR_MAX = <char>((<unsigned char>-1)>>1)
CHAR_MIN = (-CHAR_MAX-1)
def test_char(char x):
u"""
>>> test_char(CHAR_MIN-1) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
>>> test_char(CHAR_MIN) == CHAR_MIN
True
>>> test_char(-1)
-1
>>> test_char(0)
0
>>> test_char(1)
1
>>> test_char(CHAR_MAX) == CHAR_MAX
True
>>> test_char(CHAR_MAX+1) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
"""
return x
def test_add_char(x, y):
u"""
>>> test_add_char(CHAR_MIN, -1) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
>>> test_add_char(CHAR_MIN, 0) == CHAR_MIN
True
>>> test_add_char(CHAR_MIN, 1) == CHAR_MIN+1
True
>>> test_add_char(CHAR_MAX, -1) == CHAR_MAX-1
True
>>> test_add_char(CHAR_MAX, 0) == CHAR_MAX
True
>>> test_add_char(CHAR_MAX, 1) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
"""
cdef char r = x + y
return r
SCHAR_MAX = <signed char>((<unsigned char>-1)>>1)
SCHAR_MIN = (-SCHAR_MAX-1)
def test_schar(signed char x):
u"""
>>> test_schar(-129) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
>>> test_schar(-128)
-128
>>> test_schar(0)
0
>>> test_schar(127)
127
>>> test_schar(128) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
"""
return x
def test_add_schar(x, y):
u"""
>>> test_add_schar(SCHAR_MIN, -1) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
>>> test_add_schar(SCHAR_MIN, 0) == SCHAR_MIN
True
>>> test_add_schar(SCHAR_MIN, 1) == SCHAR_MIN+1
True
>>> test_add_schar(SCHAR_MAX, -1) == SCHAR_MAX-1
True
>>> test_add_schar(SCHAR_MAX, 0) == SCHAR_MAX
True
>>> test_add_schar(SCHAR_MAX, 1) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
"""
cdef signed char r = x + y
return r
UCHAR_MAX = <unsigned char>((<unsigned char>-1))
def test_uchar(unsigned char x):
u"""
>>> test_uchar(-1) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
>>> test_uchar(0)
0
>>> test_uchar(1)
1
>>> test_uchar(UCHAR_MAX) == UCHAR_MAX
True
>>> test_uchar(UCHAR_MAX+1) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
"""
return x
def test_add_uchar(x, y):
u"""
>>> test_add_uchar(UCHAR_MAX, 0) == UCHAR_MAX
True
>>> test_add_uchar(UCHAR_MAX, 1) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
"""
cdef unsigned char r = x + y
return r
# -------------------------------------------------------------------
SHORT_MAX = <short>((<unsigned short>-1)>>1)
SHORT_MIN = (-SHORT_MAX-1)
def test_short(short x):
u"""
>>> test_short(SHORT_MIN-1) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
>>> test_short(SHORT_MIN) == SHORT_MIN
True
>>> test_short(-1)
-1
>>> test_short(0)
0
>>> test_short(1)
1
>>> test_short(SHORT_MAX) == SHORT_MAX
True
>>> test_short(SHORT_MAX+1) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
"""
return x
def test_add_short(x, y):
u"""
>>> test_add_short(SHORT_MIN, -1) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
>>> test_add_short(SHORT_MIN, 0) == SHORT_MIN
True
>>> test_add_short(SHORT_MIN, 1) == SHORT_MIN+1
True
>>> test_add_short(SHORT_MAX, -1) == SHORT_MAX-1
True
>>> test_add_short(SHORT_MAX, 0) == SHORT_MAX
True
>>> test_add_short(SHORT_MAX, 1) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
"""
cdef short r = x + y
return r
SSHORT_MAX = <signed short>((<unsigned short>-1)>>1)
SSHORT_MIN = (-SSHORT_MAX-1)
def test_sshort(short x):
u"""
>>> test_sshort(SSHORT_MIN-1) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
>>> test_sshort(SSHORT_MIN) == SSHORT_MIN
True
>>> test_sshort(-1)
-1
>>> test_sshort(0)
0
>>> test_sshort(1)
1
>>> test_sshort(SSHORT_MAX) == SSHORT_MAX
True
>>> test_short(SSHORT_MAX+1) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
"""
return x
def test_add_sshort(x, y):
u"""
>>> test_add_sshort(SSHORT_MIN, -1) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
>>> test_add_sshort(SSHORT_MIN, 0) == SSHORT_MIN
True
>>> test_add_sshort(SSHORT_MIN, 1) == SSHORT_MIN+1
True
>>> test_add_sshort(SSHORT_MAX, -1) == SSHORT_MAX-1
True
>>> test_add_sshort(SSHORT_MAX, 0) == SSHORT_MAX
True
>>> test_add_sshort(SSHORT_MAX, 1) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
"""
cdef signed short r = x + y
return r
USHORT_MAX = <unsigned short>((<unsigned short>-1))
def test_ushort(unsigned short x):
u"""
>>> test_ushort(-1) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
>>> test_ushort(0)
0
>>> test_ushort(1)
1
>>> test_ushort(USHORT_MAX) == USHORT_MAX
True
>>> test_ushort(USHORT_MAX+1) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
"""
return x
def test_add_ushort(x, y):
u"""
>>> test_add_ushort(USHORT_MAX, 0) == USHORT_MAX
True
>>> test_add_ushort(USHORT_MAX, 1) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
"""
cdef unsigned short r = x + y
return r
# -------------------------------------------------------------------
INT_MAX = <int>((<unsigned int>-1)>>1)
INT_MIN = (-INT_MAX-1)
def test_int(int x):
u"""
>>> test_int(INT_MIN-1) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
>>> test_int(INT_MIN) == INT_MIN
True
>>> test_int(-1)
-1
>>> test_int(0)
0
>>> test_int(1)
1
>>> test_int(INT_MAX) == INT_MAX
True
>>> test_int(INT_MAX+1) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
"""
return x
def test_add_int(x, y):
u"""
>>> test_add_int(INT_MIN, -1) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
>>> test_add_int(INT_MIN, 0) == INT_MIN
True
>>> test_add_int(INT_MIN, 1) == INT_MIN+1
True
>>> test_add_int(INT_MAX, -1) == INT_MAX-1
True
>>> test_add_int(INT_MAX, 0) == INT_MAX
True
>>> test_add_int(INT_MAX, 1) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
"""
cdef int r = x + y
return r
SINT_MAX = <signed int>((<unsigned int>-1)>>1)
SINT_MIN = (-SINT_MAX-1)
def test_sint(int x):
u"""
>>> test_sint(SINT_MIN-1) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
>>> test_sint(SINT_MIN) == SINT_MIN
True
>>> test_sint(-1)
-1
>>> test_sint(0)
0
>>> test_sint(1)
1
>>> test_sint(SINT_MAX) == SINT_MAX
True
>>> test_sint(SINT_MAX+1) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
"""
return x
def test_add_sint(x, y):
u"""
>>> test_add_sint(SINT_MIN, -1) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
>>> test_add_sint(SINT_MIN, 0) == SINT_MIN
True
>>> test_add_sint(SINT_MIN, 1) == SINT_MIN+1
True
>>> test_add_sint(SINT_MAX, -1) == SINT_MAX-1
True
>>> test_add_sint(SINT_MAX, 0) == SINT_MAX
True
>>> test_add_sint(SINT_MAX, 1) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
"""
cdef signed int r = x + y
return r
UINT_MAX = <unsigned int>(<unsigned int>-1)
def test_uint(unsigned int x):
u"""
>>> test_uint(-1) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
>>> print(test_uint(0))
0
>>> print(test_uint(1))
1
>>> test_uint(UINT_MAX) == UINT_MAX
True
>>> test_uint(UINT_MAX+1) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
"""
return x
def test_add_uint(x, y):
u"""
>>> test_add_uint(UINT_MAX, 0) == UINT_MAX
True
>>> test_add_uint(UINT_MAX, 1) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
"""
cdef unsigned int r = x + y
return r
# -------------------------------------------------------------------
LONG_MAX = <long>((<unsigned long>-1)>>1)
LONG_MIN = (-LONG_MAX-1)
def test_long(long x):
u"""
>>> test_long(LONG_MIN-1) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
>>> test_long(LONG_MIN) == LONG_MIN
True
>>> test_long(-1)
-1
>>> test_long(0)
0
>>> test_long(1)
1
>>> test_long(LONG_MAX) == LONG_MAX
True
>>> test_long(LONG_MAX+1) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
"""
return x
def test_add_long(x, y):
u"""
>>> test_add_long(LONG_MIN, -1) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
>>> test_add_long(LONG_MIN, 0) == LONG_MIN
True
>>> test_add_long(LONG_MIN, 1) == LONG_MIN+1
True
>>> test_add_long(LONG_MAX, -1) == LONG_MAX-1
True
>>> test_add_long(LONG_MAX, 0) == LONG_MAX
True
>>> test_add_long(LONG_MAX, 1) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
"""
cdef long r = x + y
return r
SLONG_MAX = <signed long>((<unsigned long>-1)>>1)
SLONG_MIN = (-SLONG_MAX-1)
def test_slong(long x):
u"""
>>> test_slong(SLONG_MIN-1) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
>>> test_slong(SLONG_MIN) == SLONG_MIN
True
>>> test_slong(-1)
-1
>>> test_slong(0)
0
>>> test_slong(1)
1
>>> test_slong(SLONG_MAX) == SLONG_MAX
True
>>> test_slong(SLONG_MAX+1) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
"""
return x
def test_add_slong(x, y):
u"""
>>> test_add_slong(SLONG_MIN, -1) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
>>> test_add_slong(SLONG_MIN, 0) == SLONG_MIN
True
>>> test_add_slong(SLONG_MIN, 1) == SLONG_MIN+1
True
>>> test_add_slong(SLONG_MAX, -1) == SLONG_MAX-1
True
>>> test_add_slong(SLONG_MAX, 0) == SLONG_MAX
True
>>> test_add_slong(SLONG_MAX, 1) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
"""
cdef signed long r = x + y
return r
ULONG_MAX = <unsigned long>(<unsigned long>-1)
def test_ulong(unsigned long x):
u"""
>>> test_ulong(-1) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
>>> print(test_ulong(0))
0
>>> print(test_ulong(1))
1
>>> test_ulong(ULONG_MAX) == ULONG_MAX
True
>>> test_ulong(ULONG_MAX+1) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
"""
return x
def test_add_ulong(x, y):
u"""
>>> test_add_ulong(ULONG_MAX, 0) == ULONG_MAX
True
>>> test_add_ulong(ULONG_MAX, 1) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
"""
cdef unsigned long r = x + y
return r
# -------------------------------------------------------------------
LONGLONG_MAX = <long long>((<unsigned long long>-1)>>1)
LONGLONG_MIN = (-LONGLONG_MAX-1)
def test_longlong(long long x):
u"""
>>> test_longlong(LONGLONG_MIN-1) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
>>> test_longlong(LONGLONG_MIN) == LONGLONG_MIN
True
>>> print(test_longlong(-1))
-1
>>> print(test_longlong(0))
0
>>> print(test_longlong(1))
1
>>> test_longlong(LONGLONG_MAX) == LONGLONG_MAX
True
>>> test_longlong(LONGLONG_MAX+1) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
"""
return x
def test_add_longlong(x, y):
u"""
>>> test_add_longlong(LONGLONG_MIN, -1) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
>>> test_add_longlong(LONGLONG_MIN, 0) == LONGLONG_MIN
True
>>> test_add_longlong(LONGLONG_MIN, 1) == LONGLONG_MIN+1
True
>>> test_add_longlong(LONGLONG_MAX, -1) == LONGLONG_MAX-1
True
>>> test_add_longlong(LONGLONG_MAX, 0) == LONGLONG_MAX
True
>>> test_add_longlong(LONGLONG_MAX, 1) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
"""
cdef long long r = x + y
return r
SLONGLONG_MAX = <signed long long>((<unsigned long long>-1)>>1)
SLONGLONG_MIN = (-SLONGLONG_MAX-1)
def test_slonglong(long long x):
u"""
>>> test_slonglong(SLONGLONG_MIN-1) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
>>> test_slonglong(SLONGLONG_MIN) == SLONGLONG_MIN
True
>>> print(test_slonglong(-1))
-1
>>> print(test_slonglong(0))
0
>>> print(test_slonglong(1))
1
>>> test_slonglong(SLONGLONG_MAX) == SLONGLONG_MAX
True
>>> test_slonglong(SLONGLONG_MAX+1) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
"""
return x
def test_add_slonglong(x, y):
u"""
>>> test_add_slonglong(SLONGLONG_MIN, -1) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
>>> test_add_slonglong(SLONGLONG_MIN, 0) == SLONGLONG_MIN
True
>>> test_add_slonglong(SLONGLONG_MIN, 1) == SLONGLONG_MIN+1
True
>>> test_add_slonglong(SLONGLONG_MAX, -1) == SLONGLONG_MAX-1
True
>>> test_add_slonglong(SLONGLONG_MAX, 0) == SLONGLONG_MAX
True
>>> test_add_slonglong(SLONGLONG_MAX, 1) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
"""
cdef signed long long r = x + y
return r
ULONGLONG_MAX = <unsigned long long>(<unsigned long long>-1)
def test_ulonglong(unsigned long long x):
u"""
>>> test_ulonglong(-1) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
>>> print(test_ulonglong(0))
0
>>> print(test_ulonglong(1))
1
>>> test_ulonglong(ULONGLONG_MAX) == ULONGLONG_MAX
True
>>> test_ulonglong(ULONGLONG_MAX+1) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
"""
return x
def test_add_ulonglong(x, y):
u"""
>>> test_add_ulonglong(ULONGLONG_MAX, 0) == ULONGLONG_MAX
True
>>> test_add_ulonglong(ULONGLONG_MAX, 1) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
OverflowError: ...
"""
cdef unsigned long long r = x + y
return r
# -------------------------------------------------------------------
import sys
class MyInt(object):
def __init__(self, value):
self.value = value
def __int__(self):
print(u"MyInt.__int__()")
return self.value
class MyBadInt(MyInt):
def __int__(self):
return u"%s" % self.value
def test_convert_pyint(x):
u"""
>>> test_convert_pyint(None)
Traceback (most recent call last):
...
TypeError: an integer is required
>>> test_convert_pyint("123")
Traceback (most recent call last):
...
TypeError: an integer is required
>>> test_convert_pyint(MyBadInt(0)) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
TypeError: ... returned non-... (type ...)
>>> test_convert_pyint(False) == 0
True
>>> test_convert_pyint(True) == 1
True
>>> test_convert_pyint(3.14) == 3
True
>>> test_convert_pyint(MyInt(LONG_MIN)) == LONG_MIN
MyInt.__int__()
True
>>> test_convert_pyint(MyInt(0)) == 0
MyInt.__int__()
True
>>> test_convert_pyint(MyInt(LONG_MAX)) == LONG_MAX
MyInt.__int__()
True
"""
cdef long r = x
return r
class MyLong(object):
def __init__(self, value):
self.value = value
def __int__(self): # Python 3
return self.__long__()
def __long__(self):
print(u"MyInt.__long__()")
return self.value
class MyBadLong(MyLong):
def __long__(self):
return u"%s" % self.value
def test_convert_pylong(x):
u"""
>>> test_convert_pylong(None)
Traceback (most recent call last):
...
TypeError: an integer is required
>>> test_convert_pylong("123")
Traceback (most recent call last):
...
TypeError: an integer is required
>>> test_convert_pylong(MyBadLong(0)) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
TypeError: ... returned non-... (type ...)
>>> test_convert_pylong(False) == 0
True
>>> test_convert_pylong(True) == 1
True
>>> test_convert_pylong(3.14) == 3
True
>>> test_convert_pylong(MyLong(LONGLONG_MIN)) == LONGLONG_MIN
MyInt.__long__()
True
>>> test_convert_pylong(MyLong(0)) == 0
MyInt.__long__()
True
>>> test_convert_pylong(MyLong(LONGLONG_MAX)) == LONGLONG_MAX
MyInt.__long__()
True
"""
cdef long long r = x
return r
# -------------------------------------------------------------------
__doc__ = u"".join([
f.__doc__ for f in (
#
test_char, test_add_char,
test_schar, test_add_schar,
test_uchar, test_add_uchar,
#
test_short, test_add_short,
test_sshort, test_add_sshort,
test_ushort, test_add_ushort,
#
test_int, test_add_int,
test_sint, test_add_sint,
test_uint, test_add_uint,
#
test_long, test_add_long,
test_slong, test_add_slong,
test_ulong, test_add_ulong,
#
test_longlong, test_add_longlong,
test_slonglong, test_add_slonglong,
test_ulonglong, test_add_ulonglong,
#
test_convert_pyint,
test_convert_pylong,
)
])
# -------------------------------------------------------------------
__doc__ = u'''
>>> no_cdef()
>>> with_cdef()
'''
def no_cdef():
lst = range(11)
ob = 10L
lst[ob] = -10
dd = {}
dd[ob] = -10
def with_cdef():
cdef list lst = range(11)
ob = 10L
lst[ob] = -10
cdef dict dd = {}
dd[ob] = -10
...@@ -42,12 +42,36 @@ division with oppositely signed operands, C and Python semantics differ ...@@ -42,12 +42,36 @@ division with oppositely signed operands, C and Python semantics differ
>>> div_int_c_warn(-17, 10) >>> div_int_c_warn(-17, 10)
division with oppositely signed operands, C and Python semantics differ division with oppositely signed operands, C and Python semantics differ
-1 -1
>>> complex_expression(-150, 20, 20, -7) >>> complex_expression(-150, 20, 19, -7)
verbose_call(-150)
division with oppositely signed operands, C and Python semantics differ
verbose_call(20) verbose_call(20)
division with oppositely signed operands, C and Python semantics differ division with oppositely signed operands, C and Python semantics differ
verbose_call(19)
division with oppositely signed operands, C and Python semantics differ
-2 -2
>>> mod_div_zero_int(25, 10, 2)
verbose_call(5)
2
>>> mod_div_zero_int(25, 10, 0)
verbose_call(5)
'integer division or modulo by zero'
>>> mod_div_zero_int(25, 0, 0)
'integer division or modulo by zero'
>>> mod_div_zero_float(25, 10, 2)
2.5
>>> mod_div_zero_float(25, 10, 0)
'float division'
>>> mod_div_zero_float(25, 0, 0)
'float divmod()'
>>> import sys
>>> py_div_long(-5, -1)
5
>>> py_div_long(-sys.maxint-1, -1)
Traceback (most recent call last):
...
OverflowError: value too large to perform division
""" """
cimport cython cimport cython
...@@ -109,8 +133,29 @@ def div_int_c_warn(int a, int b): ...@@ -109,8 +133,29 @@ def div_int_c_warn(int a, int b):
@cython.cdivision(False) @cython.cdivision(False)
@cython.cdivision_warnings(True) @cython.cdivision_warnings(True)
def complex_expression(int a, int b, int c, int d): def complex_expression(int a, int b, int c, int d):
return (verbose_call(a) // b) % (verbose_call(c) // d) return (a // verbose_call(b)) % (verbose_call(c) // d)
cdef int verbose_call(int x): cdef int verbose_call(int x):
print "verbose_call(%s)" % x print "verbose_call(%s)" % x
return x return x
# These may segfault with cdivision
@cython.cdivision(False)
def mod_div_zero_int(int a, int b, int c):
try:
return verbose_call(a % b) / c
except ZeroDivisionError, ex:
return ex.message
@cython.cdivision(False)
def mod_div_zero_float(float a, float b, float c):
try:
return (a % b) / c
except ZeroDivisionError, ex:
return ex.message
@cython.cdivision(False)
def py_div_long(long a, long b):
return a / b
__doc__ = """# no unicode string, not tested in Python3! __doc__ = u"""
#>>> a #>>> a
#Traceback (most recent call last): #Traceback (most recent call last):
#NameError: name 'a' is not defined #NameError: name 'a' is not defined
...@@ -10,32 +10,32 @@ __doc__ = """# no unicode string, not tested in Python3! ...@@ -10,32 +10,32 @@ __doc__ = """# no unicode string, not tested in Python3!
>>> d = {} >>> d = {}
>>> test_dict_scope2(d) >>> test_dict_scope2(d)
>>> print d['b'] >>> d['b']
2 2
>>> d1 = {} >>> d1 = {}
>>> test_dict_scope3(d1, d1) >>> test_dict_scope3(d1, d1)
>>> print d1['b'] >>> d1['b']
2 2
>>> d1, d2 = {}, {} >>> d1, d2 = {}, {}
>>> test_dict_scope3(d1, d2) >>> test_dict_scope3(d1, d2)
>>> print d1.get('b'), d2.get('b') >>> (d1.get('b'), d2.get('b'))
None 2 (None, 2)
>>> d1, d2 = {}, {} >>> d1, d2 = {}, {}
>>> test_dict_scope3(d1, d2) >>> test_dict_scope3(d1, d2)
>>> print d1.get('b'), d2.get('b') >>> (d1.get('b'), d2.get('b'))
None 2 (None, 2)
>>> d1, d2 = dict(a=11), dict(c=5) >>> d1, d2 = dict(a=11), dict(c=5)
>>> test_dict_scope_ref(d1, d2) >>> test_dict_scope_ref(d1, d2)
>>> print d1.get('b'), d2.get('b') >>> (d1.get('b'), d2.get('b'))
None 16 (None, 16)
>>> d = dict(a=11, c=5) >>> d = dict(a=11, c=5)
>>> test_dict_scope_ref(d, d) >>> test_dict_scope_ref(d, d)
>>> print d['b'] >>> d['b']
16 16
>>> d = dict(seq = [1,2,3,4]) >>> d = dict(seq = [1,2,3,4])
...@@ -57,22 +57,22 @@ NameError: name 'a' is not defined ...@@ -57,22 +57,22 @@ NameError: name 'a' is not defined
def test_dict_scope1(): def test_dict_scope1():
cdef dict d = {} cdef dict d = {}
exec "b=1+1" in d exec u"b=1+1" in d
return d['b'] return d[u'b']
def test_dict_scope2(d): def test_dict_scope2(d):
exec "b=1+1" in d exec u"b=1+1" in d
def test_dict_scope3(d1, d2): def test_dict_scope3(d1, d2):
exec "b=1+1" in d1, d2 exec u"b=1+1" in d1, d2
def test_dict_scope_ref(d1, d2): def test_dict_scope_ref(d1, d2):
exec "b=a+c" in d1, d2 exec u"b=a+c" in d1, d2
def test_def(d, varref): def test_def(d, varref):
exec """ exec u"""
def test(): def test():
for x in %s: for x in %s:
yield x+1 yield x+1
""" % varref in d """ % varref in d
return d['test'] return d[u'test']
...@@ -46,6 +46,12 @@ at 1 ...@@ -46,6 +46,12 @@ at 1
at 3 at 3
at 7 at 7
15 15
>>> for_from_py_global_target_reassignment(10, 2)
at 0
at 1
at 3
at 7
15
>>> for_in_target_reassignment(10, 2) >>> for_in_target_reassignment(10, 2)
at 0 at 0
at 1 at 1
...@@ -112,6 +118,13 @@ def for_from_py_target_reassignment(int bound, int factor): ...@@ -112,6 +118,13 @@ def for_from_py_target_reassignment(int bound, int factor):
i *= factor i *= factor
return i return i
def for_from_py_global_target_reassignment(int bound, int factor):
global g_var
for g_var from 0 <= g_var < bound:
print "at", g_var
g_var *= factor
return g_var
def for_in_target_reassignment(int bound, int factor): def for_in_target_reassignment(int bound, int factor):
cdef int i = 100 cdef int i = 100
for i in range(bound): for i in range(bound):
......
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