Commit 416e3293 authored by Stefan Behnel's avatar Stefan Behnel

merged in latest cython-devel

parents ae714eac 04c2f16b
...@@ -17,3 +17,4 @@ af6f1bed8cd40a2edefb57d3eacbc9274a8788b4 0.11.2.rc1 ...@@ -17,3 +17,4 @@ af6f1bed8cd40a2edefb57d3eacbc9274a8788b4 0.11.2.rc1
15ad532e2127840ae09dfbe46ccc80ac8c562f99 0.11.2 15ad532e2127840ae09dfbe46ccc80ac8c562f99 0.11.2
eb00d00a73c13b6aa8b440fe07cd7acb52a060e8 0.11.3.rc0 eb00d00a73c13b6aa8b440fe07cd7acb52a060e8 0.11.3.rc0
7c695fe49fd6912f52d995fe512d66baacf90ee6 0.11.3 7c695fe49fd6912f52d995fe512d66baacf90ee6 0.11.3
4208042ceeae634f5c0999b8ab75f69faf46b6db 0.12.alpha0
...@@ -245,8 +245,9 @@ def put_acquire_arg_buffer(entry, code, pos): ...@@ -245,8 +245,9 @@ def put_acquire_arg_buffer(entry, code, pos):
# need to care about the buffer then. # need to care about the buffer then.
put_unpack_buffer_aux_into_scope(buffer_aux, entry.type.mode, code) put_unpack_buffer_aux_into_scope(buffer_aux, entry.type.mode, code)
def get_release_buffer_code(entry): def put_release_buffer_code(code, entry):
return "__Pyx_SafeReleaseBuffer(&%s)" % entry.buffer_aux.buffer_info_var.cname code.globalstate.use_utility_code(acquire_utility_code)
code.putln("__Pyx_SafeReleaseBuffer(&%s);" % entry.buffer_aux.buffer_info_var.cname)
def get_getbuffer_call(code, obj_cname, buffer_aux, buffer_type): def get_getbuffer_call(code, obj_cname, buffer_aux, buffer_type):
ndim = buffer_type.ndim ndim = buffer_type.ndim
......
...@@ -17,7 +17,6 @@ Options: ...@@ -17,7 +17,6 @@ Options:
-I, --include-dir <directory> Search for include files in named directory -I, --include-dir <directory> Search for include files in named directory
(multiply include directories are allowed). (multiply include directories are allowed).
-o, --output-file <filename> Specify name of generated C file -o, --output-file <filename> Specify name of generated C file
-r, --recursive Recursively find and compile dependencies
-t, --timestamps Only compile newer source files (implied with -r) -t, --timestamps Only compile newer source files (implied with -r)
-f, --force Compile all source files (overrides implied -t) -f, --force Compile all source files (overrides implied -t)
-q, --quiet Don't print module names in recursive mode -q, --quiet Don't print module names in recursive mode
...@@ -40,6 +39,10 @@ Options: ...@@ -40,6 +39,10 @@ Options:
-X, --directive <name>=<value>[,<name=value,...] Overrides a compiler directive -X, --directive <name>=<value>[,<name=value,...] Overrides a compiler directive
""" """
# The following is broken http://trac.cython.org/cython_trac/ticket/379
# -r, --recursive Recursively find and compile dependencies
#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
# --link Link .o file to produce extension module (implies -C) # --link Link .o file to produce extension module (implies -C)
......
...@@ -408,8 +408,10 @@ class GlobalState(object): ...@@ -408,8 +408,10 @@ class GlobalState(object):
code_layout = [ code_layout = [
'h_code', 'h_code',
'utility_code_proto_before_types', 'utility_code_proto_before_types',
'type_declarations', 'numeric_typedefs', # Let these detailed individual parts stay!,
'utility_code_proto', 'complex_type_declarations', # as the proper solution is to make a full DAG...
'type_declarations', # More coarse-grained blocks would simply hide
'utility_code_proto', # the ugliness, not fix it
'module_declarations', 'module_declarations',
'typeinfo', 'typeinfo',
'before_global_var', 'before_global_var',
......
...@@ -2572,7 +2572,7 @@ class SimpleCallNode(CallNode): ...@@ -2572,7 +2572,7 @@ class SimpleCallNode(CallNode):
for formal_arg, actual_arg in args[expected_nargs:actual_nargs]: for formal_arg, actual_arg in args[expected_nargs:actual_nargs]:
code.putln("%s.%s = %s;" % ( code.putln("%s.%s = %s;" % (
self.opt_arg_struct, self.opt_arg_struct,
formal_arg.name, func_type.opt_arg_cname(formal_arg.name),
actual_arg.result_as(formal_arg.type))) actual_arg.result_as(formal_arg.type)))
exc_checks = [] exc_checks = []
if self.type.is_pyobject: if self.type.is_pyobject:
...@@ -5601,6 +5601,7 @@ class CoercionNode(ExprNode): ...@@ -5601,6 +5601,7 @@ class CoercionNode(ExprNode):
# arg ExprNode node being coerced # arg ExprNode node being coerced
subexprs = ['arg'] subexprs = ['arg']
constant_result = not_a_constant
def __init__(self, arg): def __init__(self, arg):
self.pos = arg.pos self.pos = arg.pos
......
...@@ -658,8 +658,12 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -658,8 +658,12 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
def generate_typedef(self, entry, code): def generate_typedef(self, entry, code):
base_type = entry.type.typedef_base_type base_type = entry.type.typedef_base_type
code.putln("") if base_type.is_numeric:
code.putln("typedef %s;" % base_type.declaration_code(entry.cname)) writer = code.globalstate['numeric_typedefs']
else:
writer = code
writer.putln("")
writer.putln("typedef %s;" % base_type.declaration_code(entry.cname))
def sue_header_footer(self, type, kind, name): def sue_header_footer(self, type, kind, name):
if type.typedef_flag: if type.typedef_flag:
......
...@@ -1180,7 +1180,7 @@ class FuncDefNode(StatNode, BlockNode): ...@@ -1180,7 +1180,7 @@ class FuncDefNode(StatNode, BlockNode):
code.putln("{ PyObject *__pyx_type, *__pyx_value, *__pyx_tb;") code.putln("{ PyObject *__pyx_type, *__pyx_value, *__pyx_tb;")
code.putln("__Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);") code.putln("__Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);")
for entry in lenv.buffer_entries: for entry in lenv.buffer_entries:
code.putln("%s;" % Buffer.get_release_buffer_code(entry)) Buffer.put_release_buffer_code(code, entry)
#code.putln("%s = 0;" % entry.cname) #code.putln("%s = 0;" % entry.cname)
code.putln("__Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}") code.putln("__Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}")
...@@ -1222,7 +1222,7 @@ class FuncDefNode(StatNode, BlockNode): ...@@ -1222,7 +1222,7 @@ class FuncDefNode(StatNode, BlockNode):
code.put_label(code.return_label) code.put_label(code.return_label)
for entry in lenv.buffer_entries: for entry in lenv.buffer_entries:
if entry.used: if entry.used:
code.putln("%s;" % Buffer.get_release_buffer_code(entry)) Buffer.put_release_buffer_code(code, entry)
if is_getbuffer_slot: if is_getbuffer_slot:
self.getbuffer_normal_cleanup(code) self.getbuffer_normal_cleanup(code)
# ----- Return cleanup for both error and no-error return # ----- Return cleanup for both error and no-error return
...@@ -1519,13 +1519,11 @@ class CFuncDefNode(FuncDefNode): ...@@ -1519,13 +1519,11 @@ class CFuncDefNode(FuncDefNode):
code.putln('if (%s) {' % Naming.optional_args_cname) code.putln('if (%s) {' % Naming.optional_args_cname)
for arg in self.args: for arg in self.args:
if arg.default: if arg.default:
# FIXME: simple name prefixing doesn't work when
# argument name mangling is in place
code.putln('if (%s->%sn > %s) {' % (Naming.optional_args_cname, Naming.pyrex_prefix, i)) code.putln('if (%s->%sn > %s) {' % (Naming.optional_args_cname, Naming.pyrex_prefix, i))
declarator = arg.declarator declarator = arg.declarator
while not hasattr(declarator, 'name'): while not hasattr(declarator, 'name'):
declarator = declarator.base declarator = declarator.base
code.putln('%s = %s->%s;' % (arg.cname, Naming.optional_args_cname, declarator.name)) code.putln('%s = %s->%s;' % (arg.cname, Naming.optional_args_cname, self.type.opt_arg_cname(declarator.name)))
i += 1 i += 1
for _ in range(self.type.optional_arg_count): for _ in range(self.type.optional_arg_count):
code.putln('}') code.putln('}')
......
...@@ -7,6 +7,7 @@ import UtilNodes ...@@ -7,6 +7,7 @@ import UtilNodes
import TypeSlots import TypeSlots
import Symtab import Symtab
import Options import Options
import Naming
from Code import UtilityCode from Code import UtilityCode
from StringEncoding import EncodedString, BytesLiteral from StringEncoding import EncodedString, BytesLiteral
...@@ -755,7 +756,9 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform): ...@@ -755,7 +756,9 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
### cleanup to avoid redundant coercions to/from Python types ### cleanup to avoid redundant coercions to/from Python types
def visit_PyTypeTestNode(self, node): def _visit_PyTypeTestNode(self, node):
# disabled - appears to break assignments in some cases, and
# also drops a None check, which might still be required
"""Flatten redundant type checks after tree changes. """Flatten redundant type checks after tree changes.
""" """
old_arg = node.arg old_arg = node.arg
...@@ -832,6 +835,7 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform): ...@@ -832,6 +835,7 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
else: else:
return function_handler(node, arg_tuple) return function_handler(node, arg_tuple)
elif function.is_attribute: elif function.is_attribute:
attr_name = function.attribute
arg_list = arg_tuple.args arg_list = arg_tuple.args
self_arg = function.obj self_arg = function.obj
obj_type = self_arg.type obj_type = self_arg.type
...@@ -849,7 +853,12 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform): ...@@ -849,7 +853,12 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
else: else:
type_name = "object" # safety measure type_name = "object" # safety measure
method_handler = self._find_handler( method_handler = self._find_handler(
"method_%s_%s" % (type_name, function.attribute), kwargs) "method_%s_%s" % (type_name, attr_name), kwargs)
if method_handler is None:
if attr_name in TypeSlots.method_name_to_slot \
or attr_name == '__new__':
method_handler = self._find_handler(
"slot%s" % attr_name, kwargs)
if method_handler is None: if method_handler is None:
return node return node
if self_arg is not None: if self_arg is not None:
...@@ -1030,6 +1039,51 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform): ...@@ -1030,6 +1039,51 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
) )
return node return node
### special methods
Pyx_tp_new_func_type = PyrexTypes.CFuncType(
PyrexTypes.py_object_type, [
PyrexTypes.CFuncTypeArg("type", Builtin.type_type, None)
])
def _handle_simple_slot__new__(self, node, args, is_unbound_method):
"""Replace 'exttype.__new__(exttype)' by a call to exttype->tp_new()
"""
obj = node.function.obj
if not is_unbound_method or len(args) != 1:
return node
type_arg = args[0]
if not obj.is_name or not type_arg.is_name:
# play safe
return node
if obj.type != Builtin.type_type or type_arg.type != Builtin.type_type:
# not a known type, play safe
return node
if not type_arg.type_entry or not obj.type_entry:
if obj.name != type_arg.name:
return node
# otherwise, we know it's a type and we know it's the same
# type for both - that should do
elif type_arg.type_entry != obj.type_entry:
# different types - may or may not lead to an error at runtime
return node
# FIXME: we could potentially look up the actual tp_new C method
# of the extension type and call that instead of the generic slot
if not type_arg.type_entry:
# arbitrary variable, needs a None check for safety
type_arg = ExprNodes.NoneCheckNode(
type_arg, "PyExc_TypeError",
"object.__new__(X): X is not a type object (NoneType)")
return ExprNodes.PythonCapiCallNode(
node.pos, "__Pyx_tp_new", self.Pyx_tp_new_func_type,
args = [type_arg],
utility_code = tpnew_utility_code,
is_temp = node.is_temp
)
### methods of builtin types ### methods of builtin types
PyObject_Append_func_type = PyrexTypes.CFuncType( PyObject_Append_func_type = PyrexTypes.CFuncType(
...@@ -1050,6 +1104,40 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform): ...@@ -1050,6 +1104,40 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
utility_code = append_utility_code utility_code = append_utility_code
) )
PyObject_Pop_func_type = PyrexTypes.CFuncType(
PyrexTypes.py_object_type, [
PyrexTypes.CFuncTypeArg("list", PyrexTypes.py_object_type, None),
])
PyObject_PopIndex_func_type = PyrexTypes.CFuncType(
PyrexTypes.py_object_type, [
PyrexTypes.CFuncTypeArg("list", PyrexTypes.py_object_type, None),
PyrexTypes.CFuncTypeArg("index", PyrexTypes.c_long_type, None),
])
def _handle_simple_method_object_pop(self, node, args, is_unbound_method):
# X.pop([n]) is almost always referring to a list
if len(args) == 1:
return ExprNodes.PythonCapiCallNode(
node.pos, "__Pyx_PyObject_Pop", self.PyObject_Pop_func_type,
args = args,
is_temp = node.is_temp,
utility_code = pop_utility_code
)
elif len(args) == 2:
if isinstance(args[1], ExprNodes.CoerceToPyTypeNode) and args[1].arg.type.is_int:
original_type = args[1].arg.type
if PyrexTypes.widest_numeric_type(original_type, PyrexTypes.c_py_ssize_t_type) == PyrexTypes.c_py_ssize_t_type:
args[1] = args[1].arg
return ExprNodes.PythonCapiCallNode(
node.pos, "__Pyx_PyObject_PopIndex", self.PyObject_PopIndex_func_type,
args = args,
is_temp = node.is_temp,
utility_code = pop_index_utility_code
)
return node
PyList_Append_func_type = PyrexTypes.CFuncType( PyList_Append_func_type = PyrexTypes.CFuncType(
PyrexTypes.c_int_type, [ PyrexTypes.c_int_type, [
PyrexTypes.CFuncTypeArg("list", PyrexTypes.py_object_type, None), PyrexTypes.CFuncTypeArg("list", PyrexTypes.py_object_type, None),
...@@ -1306,6 +1394,76 @@ impl = "" ...@@ -1306,6 +1394,76 @@ impl = ""
) )
pop_utility_code = UtilityCode(
proto = """
static INLINE PyObject* __Pyx_PyObject_Pop(PyObject* L) {
if (likely(PyList_CheckExact(L))
/* Check that both the size is positive and no reallocation shrinking needs to be done. */
&& likely(PyList_GET_SIZE(L) > (((PyListObject*)L)->allocated >> 1))) {
Py_SIZE(L) -= 1;
return PyList_GET_ITEM(L, PyList_GET_SIZE(L));
}
else {
PyObject *r, *m;
m = __Pyx_GetAttrString(L, "pop");
if (!m) return NULL;
r = PyObject_CallObject(m, NULL);
Py_DECREF(m);
return r;
}
}
""",
impl = ""
)
pop_index_utility_code = UtilityCode(
proto = """
static PyObject* __Pyx_PyObject_PopIndex(PyObject* L, Py_ssize_t ix);
""",
impl = """
static PyObject* __Pyx_PyObject_PopIndex(PyObject* L, Py_ssize_t ix) {
PyObject *r, *m, *t, *py_ix;
if (likely(PyList_CheckExact(L))) {
Py_ssize_t size = PyList_GET_SIZE(L);
if (likely(size > (((PyListObject*)L)->allocated >> 1))) {
if (ix < 0) {
ix += size;
}
if (likely(0 <= ix && ix < size)) {
Py_ssize_t i;
PyObject* v = PyList_GET_ITEM(L, ix);
Py_SIZE(L) -= 1;
size -= 1;
for(i=ix; i<size; i++) {
PyList_SET_ITEM(L, i, PyList_GET_ITEM(L, i+1));
}
return v;
}
}
}
py_ix = t = NULL;
m = __Pyx_GetAttrString(L, "pop");
if (!m) goto bad;
py_ix = PyInt_FromSsize_t(ix);
if (!py_ix) goto bad;
t = PyTuple_New(1);
if (!t) goto bad;
PyTuple_SET_ITEM(t, 0, py_ix);
py_ix = NULL;
r = PyObject_CallObject(m, t);
Py_DECREF(m);
Py_DECREF(t);
return r;
bad:
Py_XDECREF(m);
Py_XDECREF(t);
Py_XDECREF(py_ix);
return NULL;
}
"""
)
pytype_utility_code = UtilityCode( pytype_utility_code = UtilityCode(
proto = """ proto = """
static INLINE PyObject* __Pyx_Type(PyObject* o) { static INLINE PyObject* __Pyx_Type(PyObject* o) {
...@@ -1317,6 +1475,16 @@ static INLINE PyObject* __Pyx_Type(PyObject* o) { ...@@ -1317,6 +1475,16 @@ static INLINE PyObject* __Pyx_Type(PyObject* o) {
) )
tpnew_utility_code = UtilityCode(
proto = """
static INLINE PyObject* __Pyx_tp_new(PyObject* type_obj) {
return (PyObject*) (((PyTypeObject*)(type_obj))->tp_new(
(PyTypeObject*)(type_obj), %(TUPLE)s, NULL));
}
""" % {'TUPLE' : Naming.empty_tuple}
)
class ConstantFolding(Visitor.VisitorTransform, SkipDeclarations): class ConstantFolding(Visitor.VisitorTransform, SkipDeclarations):
"""Calculate the result of constant expressions to store it in """Calculate the result of constant expressions to store it in
``expr_node.constant_result``, and replace trivial cases by their ``expr_node.constant_result``, and replace trivial cases by their
......
...@@ -871,6 +871,17 @@ class CComplexType(CNumericType): ...@@ -871,6 +871,17 @@ class CComplexType(CNumericType):
scope = None scope = None
def __init__(self, real_type): def __init__(self, real_type):
while real_type.is_typedef and not real_type.typedef_is_external:
real_type = real_type.typedef_base_type
if real_type.is_typedef and real_type.typedef_is_external:
# The below is not actually used: Coercions are currently disabled
# so that complex types of external types can not be created
self.funcsuffix = "_%s" % real_type.specalization_name()
elif hasattr(real_type, 'math_h_modifier'):
self.funcsuffix = real_type.math_h_modifier
else:
self.funcsuffix = "_%s" % real_type.specalization_name()
self.real_type = real_type self.real_type = real_type
CNumericType.__init__(self, real_type.rank + 0.5, real_type.signed) CNumericType.__init__(self, real_type.rank + 0.5, real_type.signed)
self.binops = {} self.binops = {}
...@@ -883,6 +894,12 @@ class CComplexType(CNumericType): ...@@ -883,6 +894,12 @@ class CComplexType(CNumericType):
else: else:
return False return False
def __ne__(self, other):
if isinstance(self, CComplexType) and isinstance(other, CComplexType):
return self.real_type != other.real_type
else:
return True
def __lt__(self, other): def __lt__(self, other):
if isinstance(self, CComplexType) and isinstance(other, CComplexType): if isinstance(self, CComplexType) and isinstance(other, CComplexType):
return self.real_type < other.real_type return self.real_type < other.real_type
...@@ -907,6 +924,14 @@ class CComplexType(CNumericType): ...@@ -907,6 +924,14 @@ class CComplexType(CNumericType):
real_type_name = real_type_name.replace('long__double','long_double') real_type_name = real_type_name.replace('long__double','long_double')
return Naming.type_prefix + real_type_name + "_complex" return Naming.type_prefix + real_type_name + "_complex"
def assignable_from(self, src_type):
# Temporary hack/feature disabling, see #441
if (not src_type.is_complex and src_type.is_numeric and src_type.is_typedef
and src_type.typedef_is_external):
return False
else:
return super(CComplexType, self).assignable_from(src_type)
def assignable_from_resolved_type(self, src_type): def assignable_from_resolved_type(self, src_type):
return (src_type.is_complex and self.real_type.assignable_from_resolved_type(src_type.real_type) return (src_type.is_complex and self.real_type.assignable_from_resolved_type(src_type.real_type)
or src_type.is_numeric and self.real_type.assignable_from_resolved_type(src_type) or src_type.is_numeric and self.real_type.assignable_from_resolved_type(src_type)
...@@ -927,7 +952,7 @@ class CComplexType(CNumericType): ...@@ -927,7 +952,7 @@ class CComplexType(CNumericType):
CFuncType(self, [CFuncTypeArg("self", self, None)]), CFuncType(self, [CFuncTypeArg("self", self, None)]),
pos=None, pos=None,
defining=1, defining=1,
cname="__Pyx_c_conj%s" % self.real_type.math_h_modifier) cname="__Pyx_c_conj%s" % self.funcsuffix)
return True return True
...@@ -943,7 +968,7 @@ class CComplexType(CNumericType): ...@@ -943,7 +968,7 @@ class CComplexType(CNumericType):
utility_code.specialize( utility_code.specialize(
self, self,
real_type = self.real_type.declaration_code(''), real_type = self.real_type.declaration_code(''),
m = self.real_type.math_h_modifier)) m = self.funcsuffix))
return True return True
def create_to_py_utility_code(self, env): def create_to_py_utility_code(self, env):
...@@ -960,7 +985,7 @@ class CComplexType(CNumericType): ...@@ -960,7 +985,7 @@ class CComplexType(CNumericType):
utility_code.specialize( utility_code.specialize(
self, self,
real_type = self.real_type.declaration_code(''), real_type = self.real_type.declaration_code(''),
m = self.real_type.math_h_modifier)) m = self.funcsuffix))
self.from_py_function = "__Pyx_PyComplex_As_" + self.specalization_name() self.from_py_function = "__Pyx_PyComplex_As_" + self.specalization_name()
return True return True
...@@ -971,8 +996,7 @@ class CComplexType(CNumericType): ...@@ -971,8 +996,7 @@ class CComplexType(CNumericType):
pass pass
try: try:
op_name = complex_ops[nargs, op] op_name = complex_ops[nargs, op]
modifier = self.real_type.math_h_modifier self.binops[nargs, op] = func_name = "__Pyx_c_%s%s" % (op_name, self.funcsuffix)
self.binops[nargs, op] = func_name = "__Pyx_c_%s%s" % (op_name, modifier)
return func_name return func_name
except KeyError: except KeyError:
return None return None
...@@ -1032,7 +1056,7 @@ proto=""" ...@@ -1032,7 +1056,7 @@ proto="""
""") """)
complex_type_utility_code = UtilityCode( complex_type_utility_code = UtilityCode(
proto_block='utility_code_proto_before_types', proto_block='complex_type_declarations',
proto=""" proto="""
#if CYTHON_CCOMPLEX #if CYTHON_CCOMPLEX
#ifdef __cplusplus #ifdef __cplusplus
...@@ -1113,7 +1137,7 @@ proto=""" ...@@ -1113,7 +1137,7 @@ proto="""
#define __Pyx_c_quot%(m)s(a, b) ((a)/(b)) #define __Pyx_c_quot%(m)s(a, b) ((a)/(b))
#define __Pyx_c_neg%(m)s(a) (-(a)) #define __Pyx_c_neg%(m)s(a) (-(a))
#ifdef __cplusplus #ifdef __cplusplus
#define __Pyx_c_is_zero%(m)s(z) ((z)==0.0) #define __Pyx_c_is_zero%(m)s(z) ((z)==(%(real_type)s)0)
#define __Pyx_c_conj%(m)s(z) (::std::conj(z)) #define __Pyx_c_conj%(m)s(z) (::std::conj(z))
/*#define __Pyx_c_abs%(m)s(z) (::std::abs(z))*/ /*#define __Pyx_c_abs%(m)s(z) (::std::abs(z))*/
#else #else
...@@ -1191,7 +1215,6 @@ impl=""" ...@@ -1191,7 +1215,6 @@ impl="""
#endif #endif
""") """)
class CArrayType(CType): class CArrayType(CType):
# base_type CType Element type # base_type CType Element type
# size integer or None Number of elements # size integer or None Number of elements
...@@ -1513,6 +1536,9 @@ class CFuncType(CType): ...@@ -1513,6 +1536,9 @@ class CFuncType(CType):
s = self.declaration_code("(*)", with_calling_convention=False) s = self.declaration_code("(*)", with_calling_convention=False)
return '(%s)' % s return '(%s)' % s
def opt_arg_cname(self, arg_name):
return self.op_arg_struct.base_type.scope.lookup(arg_name).cname
class CFuncTypeArg(object): class CFuncTypeArg(object):
# name string # name string
......
version = '0.11.3' version = '0.12.alpha0'
...@@ -16,7 +16,7 @@ include Demos/embed/* ...@@ -16,7 +16,7 @@ include Demos/embed/*
include Demos/freeze/* include Demos/freeze/*
include Demos/Setup.py include Demos/Setup.py
include Demos/Makefile* include Demos/Makefile*
include Tools/* recursive-include Tools *
recursive-include tests *.pyx *.pxd *.pxi *.py *.h *.BROKEN bugs.txt recursive-include tests *.pyx *.pxd *.pxi *.py *.h *.BROKEN bugs.txt
include runtests.py include runtests.py
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
import os import os
import sys import sys
import re import re
import gc
import codecs import codecs
import shutil import shutil
import unittest import unittest
...@@ -99,7 +100,7 @@ class ErrorWriter(object): ...@@ -99,7 +100,7 @@ class ErrorWriter(object):
class TestBuilder(object): class TestBuilder(object):
def __init__(self, rootdir, workdir, selectors, exclude_selectors, annotate, def __init__(self, rootdir, workdir, selectors, exclude_selectors, annotate,
cleanup_workdir, cleanup_sharedlibs, with_pyregr, cython_only, cleanup_workdir, cleanup_sharedlibs, with_pyregr, cython_only,
languages, test_bugs): languages, test_bugs, fork):
self.rootdir = rootdir self.rootdir = rootdir
self.workdir = workdir self.workdir = workdir
self.selectors = selectors self.selectors = selectors
...@@ -111,6 +112,7 @@ class TestBuilder(object): ...@@ -111,6 +112,7 @@ class TestBuilder(object):
self.cython_only = cython_only self.cython_only = cython_only
self.languages = languages self.languages = languages
self.test_bugs = test_bugs self.test_bugs = test_bugs
self.fork = fork
def build_suite(self): def build_suite(self):
suite = unittest.TestSuite() suite = unittest.TestSuite()
...@@ -192,12 +194,13 @@ class TestBuilder(object): ...@@ -192,12 +194,13 @@ class TestBuilder(object):
annotate=self.annotate, annotate=self.annotate,
cleanup_workdir=self.cleanup_workdir, cleanup_workdir=self.cleanup_workdir,
cleanup_sharedlibs=self.cleanup_sharedlibs, cleanup_sharedlibs=self.cleanup_sharedlibs,
cython_only=self.cython_only) cython_only=self.cython_only,
fork=self.fork)
class CythonCompileTestCase(unittest.TestCase): class CythonCompileTestCase(unittest.TestCase):
def __init__(self, directory, workdir, module, language='c', def __init__(self, directory, workdir, module, language='c',
expect_errors=False, annotate=False, cleanup_workdir=True, expect_errors=False, annotate=False, cleanup_workdir=True,
cleanup_sharedlibs=True, cython_only=False): cleanup_sharedlibs=True, cython_only=False, fork=True):
self.directory = directory self.directory = directory
self.workdir = workdir self.workdir = workdir
self.module = module self.module = module
...@@ -207,6 +210,7 @@ class CythonCompileTestCase(unittest.TestCase): ...@@ -207,6 +210,7 @@ class CythonCompileTestCase(unittest.TestCase):
self.cleanup_workdir = cleanup_workdir self.cleanup_workdir = cleanup_workdir
self.cleanup_sharedlibs = cleanup_sharedlibs self.cleanup_sharedlibs = cleanup_sharedlibs
self.cython_only = cython_only self.cython_only = cython_only
self.fork = fork
unittest.TestCase.__init__(self) unittest.TestCase.__init__(self)
def shortDescription(self): def shortDescription(self):
...@@ -391,8 +395,9 @@ class CythonRunTestCase(CythonCompileTestCase): ...@@ -391,8 +395,9 @@ class CythonRunTestCase(CythonCompileTestCase):
pass pass
def run_doctests(self, module_name, result): def run_doctests(self, module_name, result):
if sys.version_info[0] >= 3 or not hasattr(os, 'fork'): if sys.version_info[0] >= 3 or not hasattr(os, 'fork') or not self.fork:
doctest.DocTestSuite(module_name).run(result) doctest.DocTestSuite(module_name).run(result)
gc.collect()
return return
# fork to make sure we do not keep the tested module loaded # fork to make sure we do not keep the tested module loaded
...@@ -407,11 +412,13 @@ class CythonRunTestCase(CythonCompileTestCase): ...@@ -407,11 +412,13 @@ class CythonRunTestCase(CythonCompileTestCase):
partial_result = PartialTestResult(result) partial_result = PartialTestResult(result)
tests = doctest.DocTestSuite(module_name) tests = doctest.DocTestSuite(module_name)
tests.run(partial_result) tests.run(partial_result)
gc.collect()
except Exception: except Exception:
if tests is None: if tests is None:
# importing failed, try to fake a test class # importing failed, try to fake a test class
tests = _FakeClass( tests = _FakeClass(
failureException=None, failureException=None,
shortDescription = self.shortDescription,
**{module_name: None}) **{module_name: None})
partial_result.addError(tests, sys.exc_info()) partial_result.addError(tests, sys.exc_info())
result_code = 1 result_code = 1
...@@ -421,9 +428,13 @@ class CythonRunTestCase(CythonCompileTestCase): ...@@ -421,9 +428,13 @@ class CythonRunTestCase(CythonCompileTestCase):
except: pass except: pass
os._exit(result_code) os._exit(result_code)
cid, result_code = os.waitpid(child_id, 0)
if result_code in (0,1):
input = os.fdopen(input, 'rb') input = os.fdopen(input, 'rb')
try:
PartialTestResult.join_results(result, pickle.load(input)) PartialTestResult.join_results(result, pickle.load(input))
cid, result_code = os.waitpid(child_id, 0) finally:
input.close()
if result_code: if result_code:
raise Exception("Tests in module '%s' exited with status %d" % raise Exception("Tests in module '%s' exited with status %d" %
(module_name, result_code >> 8)) (module_name, result_code >> 8))
...@@ -663,6 +674,9 @@ if __name__ == '__main__': ...@@ -663,6 +674,9 @@ if __name__ == '__main__':
parser.add_option("--no-refnanny", dest="with_refnanny", parser.add_option("--no-refnanny", dest="with_refnanny",
action="store_false", default=True, action="store_false", default=True,
help="do not regression test reference counting") help="do not regression test reference counting")
parser.add_option("--no-fork", dest="fork",
action="store_false", default=True,
help="do not fork to run tests")
parser.add_option("--sys-pyregr", dest="system_pyregr", parser.add_option("--sys-pyregr", dest="system_pyregr",
action="store_true", default=False, action="store_true", default=False,
help="run the regression tests of the CPython installation") help="run the regression tests of the CPython installation")
...@@ -814,14 +828,16 @@ if __name__ == '__main__': ...@@ -814,14 +828,16 @@ if __name__ == '__main__':
filetests = TestBuilder(ROOTDIR, WORKDIR, selectors, exclude_selectors, filetests = TestBuilder(ROOTDIR, WORKDIR, selectors, exclude_selectors,
options.annotate_source, options.cleanup_workdir, options.annotate_source, options.cleanup_workdir,
options.cleanup_sharedlibs, options.pyregr, options.cleanup_sharedlibs, options.pyregr,
options.cython_only, languages, test_bugs) options.cython_only, languages, test_bugs,
options.fork)
test_suite.addTest(filetests.build_suite()) test_suite.addTest(filetests.build_suite())
if options.system_pyregr and languages: if options.system_pyregr and languages:
filetests = TestBuilder(ROOTDIR, WORKDIR, selectors, exclude_selectors, filetests = TestBuilder(ROOTDIR, WORKDIR, selectors, exclude_selectors,
options.annotate_source, options.cleanup_workdir, options.annotate_source, options.cleanup_workdir,
options.cleanup_sharedlibs, True, options.cleanup_sharedlibs, True,
options.cython_only, languages, test_bugs) options.cython_only, languages, test_bugs,
options.fork)
test_suite.addTest( test_suite.addTest(
filetests.handle_directory( filetests.handle_directory(
os.path.join(sys.prefix, 'lib', 'python'+sys.version[:3], 'test'), os.path.join(sys.prefix, 'lib', 'python'+sys.version[:3], 'test'),
......
...@@ -5,5 +5,4 @@ methodmangling_T5 ...@@ -5,5 +5,4 @@ methodmangling_T5
class_attribute_init_values_T18 class_attribute_init_values_T18
numpy_ValueError_T172 numpy_ValueError_T172
unsignedbehaviour_T184 unsignedbehaviour_T184
bad_c_struct_T252
missing_baseclass_in_predecl_T262 missing_baseclass_in_predecl_T262
def test():
cdef object[int] not_assigned_to
not_assigned_to[2] = 3
extern int generic_error(void);
extern int specified_error(void);
extern int dynamic_error(void);
cdef void raise_py_error():
pass
cdef extern from "cpp_exceptions.h":
cdef int generic_error() except +
cdef int specified_error() except +MemoryError
cdef int dynamic_error() except +raise_py_error
def test_it():
generic_error()
specified_error()
dynamic_error()
cdef cf(default=None): cdef cf(default=None):
return default return default
cpdef cpf(default=None): cpdef cpf(default=100):
""" """
>>> cpf() >>> cpf()
None 100
>>> cpf(1) >>> cpf(1)
1 1
>>> cpf(default=2) >>> cpf(default=2)
...@@ -13,10 +13,10 @@ cpdef cpf(default=None): ...@@ -13,10 +13,10 @@ cpdef cpf(default=None):
default = cf(default) default = cf(default)
return default return default
def pf(default=None): def pf(default=100):
""" """
>>> pf() >>> pf()
None 100
>>> pf(1) >>> pf(1)
1 1
>>> pf(default=2) >>> pf(default=2)
......
...@@ -31,12 +31,16 @@ True ...@@ -31,12 +31,16 @@ True
True True
>>> all([div_int_py(a,b) == a // b for a in range(-10, 10) for b in range(-10, 10) if b != 0]) >>> all([div_int_py(a,b) == a // b for a in range(-10, 10) for b in range(-10, 10) if b != 0])
True True
"""
>>> def simple_warn(msg, *args): print(msg) import warnings
>>> import warnings orig_showwarning = warnings.showwarning
>>> warnings.showwarning = simple_warn
true_py_functions = {}
exec "def simple_warn(msg, *args): print(msg)" in true_py_functions
simple_warn = true_py_functions['simple_warn']
del true_py_functions
"""
def _all(seq): def _all(seq):
for x in seq: for x in seq:
...@@ -100,9 +104,11 @@ def test_cdiv_cmod(short a, short b): ...@@ -100,9 +104,11 @@ def test_cdiv_cmod(short a, short b):
@cython.cdivision_warnings(True) @cython.cdivision_warnings(True)
def mod_int_c_warn(int a, int b): def mod_int_c_warn(int a, int b):
""" """
>>> warnings.showwarning = simple_warn
>>> mod_int_c_warn(-17, 10) >>> mod_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
-7 -7
>>> warnings.showwarning = orig_showwarning
""" """
return a % b return a % b
...@@ -110,9 +116,11 @@ def mod_int_c_warn(int a, int b): ...@@ -110,9 +116,11 @@ def mod_int_c_warn(int a, int b):
@cython.cdivision_warnings(True) @cython.cdivision_warnings(True)
def div_int_c_warn(int a, int b): def div_int_c_warn(int a, int b):
""" """
>>> warnings.showwarning = simple_warn
>>> 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
>>> warnings.showwarning = orig_showwarning
""" """
return a // b return a // b
...@@ -120,12 +128,14 @@ def div_int_c_warn(int a, int b): ...@@ -120,12 +128,14 @@ def div_int_c_warn(int a, int b):
@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):
""" """
>>> warnings.showwarning = simple_warn
>>> complex_expression(-150, 20, 19, -7) >>> complex_expression(-150, 20, 19, -7)
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) verbose_call(19)
division with oppositely signed operands, C and Python semantics differ division with oppositely signed operands, C and Python semantics differ
-2 -2
>>> warnings.showwarning = orig_showwarning
""" """
return (a // verbose_call(b)) % (verbose_call(c) // d) return (a // verbose_call(b)) % (verbose_call(c) // d)
......
import cython
def test_arith(int complex a, int complex b):
"""
>>> test_arith(4, 2)
((-4+0j), (6+0j), (2+0j), (8+0j), (2+0j))
>>> test_arith(6+9j, 3j)
((-6-9j), (6+12j), (6+6j), (-27+18j), (3-2j))
>>> test_arith(29+11j, 5+7j)
((-29-11j), (34+18j), (24+4j), (68+258j), (3-2j))
"""
return -a, a+b, a-b, a*b, a/b
@cython.cdivision(False)
def test_div_by_zero(long complex z):
"""
>>> test_div_by_zero(4j)
-25j
>>> test_div_by_zero(0)
Traceback (most recent call last):
...
ZeroDivisionError: float division
"""
return 100/z
def test_coercion(int a, long b, int complex c):
"""
>>> test_coercion(1, -2, 3-3j)
(1+0j)
(-2+0j)
(3-3j)
(5-6j)
"""
cdef double complex z
z = a; print z
z = b; print z
z = c; print z
return z + a + b + c
def test_conjugate(long complex z):
"""
>>> test_conjugate(2+3j)
(2-3j)
"""
return z.conjugate()
\ No newline at end of file
#cdef extern from "complex.h":
# pass
cimport cython cimport cython
def test_object_conversion(o): def test_object_conversion(o):
...@@ -23,21 +20,20 @@ def test_arithmetic(double complex z, double complex w): ...@@ -23,21 +20,20 @@ def test_arithmetic(double complex z, double complex w):
((6+12j), (-6-12j), (6+15j), (6+9j), (-36+18j), (4-2j)) ((6+12j), (-6-12j), (6+15j), (6+9j), (-36+18j), (4-2j))
>>> test_arithmetic(5-10j, 3+4j) >>> test_arithmetic(5-10j, 3+4j)
((5-10j), (-5+10j), (8-6j), (2-14j), (55-10j), (-1-2j)) ((5-10j), (-5+10j), (8-6j), (2-14j), (55-10j), (-1-2j))
## XXX this is not working
## >>> test_div_by_zero(4j)
## -0.25j
## >>> test_div_by_zero(0)
## Traceback (most recent call last):
## ...
## ZeroDivisionError: float division
""" """
return +z, -z, z+w, z-w, z*w, z/w return +z, -z, z+w, z-w, z*w, z/w
## XXX this is not working @cython.cdivision(False)
## @cython.cdivision(False) def test_div_by_zero(double complex z):
## def test_div_by_zero(double complex z): """
## return 1/z >>> test_div_by_zero(4j)
-0.25j
>>> test_div_by_zero(0)
Traceback (most recent call last):
...
ZeroDivisionError: float division
"""
return 1/z
def test_coercion(int a, float b, double c, float complex d, double complex e): def test_coercion(int a, float b, double c, float complex d, double complex e):
""" """
...@@ -127,13 +123,43 @@ def test_conjugate_double(double complex z): ...@@ -127,13 +123,43 @@ def test_conjugate_double(double complex z):
ctypedef double complex cdouble ctypedef double complex cdouble
def test_conjugate_typedef(cdouble z): def test_conjugate_typedef(cdouble z):
"""
>>> test_conjugate_typedef(2+3j)
(2-3j)
"""
return z.conjugate() return z.conjugate()
## cdef extern from "complex_numbers_T305.h":
## ctypedef double double_really_float "myfloat"
## ctypedef float float_really_double "mydouble"
## ctypedef float real_float "myfloat"
## ctypedef double real_double "mydouble"
## def test_conjugate_nosizeassumptions(double_really_float x,
## float_really_double y,
## real_float z, real_double w):
## """
## >>> test_conjugate_nosizeassumptions(1, 1, 1, 1)
## (-1j, -1j, -1j, -1j)
## >>> ["%.2f" % x.imag for x in test_conjugate_nosizeassumptions(2e300, 2e300, 2e300, 2e300)]
## ['-inf', '-2e+300', '-inf', '-2e+300']
## """
## cdef double complex I = 1j
## return ((x*I).conjugate(), (y*I).conjugate(), (z*I).conjugate(), (w*I).conjugate())
ctypedef double mydouble ctypedef double mydouble
def test_coerce_typedef_multiply(mydouble x, double complex z): def test_coerce_typedef_multiply(mydouble x, double complex z):
""" """
>>> test_coerce_typedef_multiply(3, 1j) >>> test_coerce_typedef_multiply(3, 1+1j)
(3j) (3+3j)
"""
return x * z
ctypedef int myint
def test_coerce_typedef_multiply_int(myint x, double complex z):
"""
>>> test_coerce_typedef_multiply_int(3, 1+1j)
(3+3j)
""" """
return x * z return x * z
......
cdef int raise_py_error() except *: cdef int raise_py_error() except *:
raise TypeError("custom") raise TypeError("custom")
cdef extern from "cpp_exceptions_helper.cpp": cdef extern from "cpp_exceptions_helper.h":
cdef int raise_int_raw "raise_int"(bint fire) except + cdef int raise_int_raw "raise_int"(bint fire) except +
cdef int raise_int_value "raise_int"(bint fire) except +ValueError cdef int raise_int_value "raise_int"(bint fire) except +ValueError
cdef int raise_int_custom "raise_int"(bint fire) except +raise_py_error cdef int raise_int_custom "raise_int"(bint fire) except +raise_py_error
......
import sys
if sys.version_info[0] >= 3:
__doc__ = __doc__.replace(u" u'", u" '").replace(u' u"', u' "')
def for_else(): def for_else():
""" """
>>> for_else() >>> for_else()
30 30
>>> print( u'*'.join(int_comp()) ) >>> print( int_comp() )
00*01*02 00*01*02
""" """
cdef int i, j=0, k=2 cdef int i, j=0, k=2
...@@ -18,5 +15,5 @@ def for_else(): ...@@ -18,5 +15,5 @@ def for_else():
def int_comp(): def int_comp():
cdef int i cdef int i
return tuple([ u"%02d" % i return u'*'.join(tuple([ u"%02d" % i
for i from 0 <= i < 3 ]) for i from 0 <= i < 3 ]))
__doc__ = u"""
>>> index_object(100, 100)
Traceback (most recent call last):
...
TypeError: 'int' object is unsubscriptable
"""
import sys import sys
if sys.version_info[0] >= 3: if sys.version_info[0] >= 3:
__doc__ = __doc__.replace(u'is unsubscriptable', u'is not subscriptable') __doc__ = __doc__.replace(u'is unsubscriptable', u'is not subscriptable')
elif sys.version_info < (2,5): elif sys.version_info < (2,5):
__doc__ = __doc__.replace(u"'int' object is unsubscriptable", u'unsubscriptable object') __doc__ = __doc__.replace(u"'int' object is unsubscriptable", u'unsubscriptable object')
def index_tuple(tuple t, int i): def index_tuple(tuple t, int i):
""" """
>>> index_tuple((1,1,2,3,5), 0) >>> index_tuple((1,1,2,3,5), 0)
...@@ -52,10 +60,6 @@ def index_object(object o, int i): ...@@ -52,10 +60,6 @@ def index_object(object o, int i):
Traceback (most recent call last): Traceback (most recent call last):
... ...
IndexError: string index out of range IndexError: string index out of range
>>> index_object(100, 100)
Traceback (most recent call last):
...
TypeError: 'int' object is unsubscriptable
""" """
return o[i] return o[i]
......
__doc__ = u"""
>>> c_longs()
(1, 1L, -1L, 18446744073709551615L)
>>> py_longs()
(1, 1L, 100000000000000000000000000000000L, -100000000000000000000000000000000L)
"""
import sys
if sys.version_info[0] >= 3:
__doc__ = __doc__.replace(u'L', u'')
import sys import sys
if sys.version_info[0] >= 3: if sys.version_info[0] >= 3:
__doc__ = __doc__.replace(u'L', u'') __doc__ = __doc__.replace(u'L', u'')
def c_longs(): def c_longs():
"""
>>> c_longs()
(1, 1L, -1L, 18446744073709551615L)
"""
cdef long a = 1L cdef long a = 1L
cdef unsigned long ua = 1UL cdef unsigned long ua = 1UL
cdef long long aa = 0xFFFFFFFFFFFFFFFFLL cdef long long aa = 0xFFFFFFFFFFFFFFFFLL
...@@ -16,8 +24,4 @@ def c_longs(): ...@@ -16,8 +24,4 @@ def c_longs():
return a, ua, aa, uaa return a, ua, aa, uaa
def py_longs(): def py_longs():
"""
>>> py_longs()
(1, 1L, 100000000000000000000000000000000L, -100000000000000000000000000000000L)
"""
return 1, 1L, 100000000000000000000000000000000, -100000000000000000000000000000000 return 1, 1L, 100000000000000000000000000000000, -100000000000000000000000000000000
import sys
if sys.version_info[0] >= 3:
__doc__ = __doc__.replace(u" u'", u" '")
class C: class C:
""" """
>>> C().xxx(5) >>> C().xxx(5)
5 5
>>> C().xxx() >>> C().xxx()
u'a b' 'a b'
>>> C().xxx(42) >>> C().xxx(42)
42 42
>>> C().xxx() >>> C().xxx()
u'a b' 'a b'
""" """
def xxx(self, p=u"a b"): def xxx(self, p="a b"):
return p return p
cimport cython
class A:
def pop(self, *args):
print args
return None
@cython.test_assert_path_exists('//PythonCapiCallNode')
@cython.test_fail_if_path_exists('//SimpleCallNode/AttributeNode')
def simple_pop(L):
"""
>>> L = range(10)
>>> simple_pop(L)
9
>>> simple_pop(L)
8
>>> L
[0, 1, 2, 3, 4, 5, 6, 7]
>>> while L:
... _ = simple_pop(L)
>>> L
[]
>>> simple_pop(L)
Traceback (most recent call last):
...
IndexError: pop from empty list
>>> simple_pop(A())
()
"""
return L.pop()
@cython.test_assert_path_exists('//PythonCapiCallNode')
@cython.test_fail_if_path_exists('//SimpleCallNode/AttributeNode')
def index_pop(L, int i):
"""
>>> L = range(10)
>>> index_pop(L, 2)
2
>>> index_pop(L, -2)
8
>>> L
[0, 1, 3, 4, 5, 6, 7, 9]
>>> index_pop(L, 100)
Traceback (most recent call last):
...
IndexError: pop index out of range
>>> index_pop(L, -100)
Traceback (most recent call last):
...
IndexError: pop index out of range
>>> while L:
... _ = index_pop(L, 0)
>>> L
[]
>>> index_pop(L, 0)
Traceback (most recent call last):
...
IndexError: pop from empty list
>>> index_pop(A(), 3)
(3,)
"""
return L.pop(i)
@cython.test_fail_if_path_exists('//PythonCapiCallNode')
def crazy_pop(L):
"""
>>> crazy_pop(range(10))
Traceback (most recent call last):
...
TypeError: pop() takes at most 1 argument (3 given)
>>> crazy_pop(A())
(1, 2, 3)
"""
return L.pop(1, 2, 3)
import sys
if sys.version_info[0] >= 3:
__doc__ = __doc__.replace(u" u'", u" '")
def f(): def f():
""" """
>>> f() >>> f()
>>> g >>> g
42 42
>>> x >>> x == 'spam'
u'spam' True
>>> y >>> y == 'eggs'
u'eggs' True
>>> z >>> z == 'spameggs'
u'spameggs' True
""" """
pass pass
......
import sys
if sys.version_info[0] >= 3:
__doc__ = __doc__.replace(u"u'", u"'")
import sys, types import sys, types
def test(obj): def test(obj):
""" """
>>> test(Exception(u'hi')) >>> test(Exception('hi'))
Raising: Exception(u'hi',) Raising: Exception('hi',)
Caught: Exception(u'hi',) Caught: Exception('hi',)
""" """
print u"Raising: %s%r" % (obj.__class__.__name__, obj.args) print u"Raising: %s%r" % (obj.__class__.__name__, obj.args)
try: try:
......
...@@ -20,7 +20,10 @@ __doc__ = u""" ...@@ -20,7 +20,10 @@ __doc__ = u"""
KeyError: 'f_noprof' KeyError: 'f_noprof'
>>> short_stats['f_raise'] >>> short_stats['f_raise']
100 100
>>> os.unlink(statsfile) >>> try:
... os.unlink(statsfile)
... except:
... pass
""" """
import sys import sys
......
__doc__ = u"""
>>> f(100)
101L
>>> g(3000000000)
3000000001L
"""
import sys import sys
if sys.version_info[0] >= 3: if sys.version_info[0] >= 3:
__doc__ = __doc__.replace(u"L", u"") __doc__ = __doc__.replace(u"L", u"")
def f(x): def f(x):
"""
>>> f(100)
101L
"""
cdef unsigned long long ull cdef unsigned long long ull
ull = x ull = x
return ull + 1 return ull + 1
def g(unsigned long x): def g(unsigned long x):
"""
>>> g(3000000000)
3000000001L
"""
return x + 1 return x + 1
cimport cython
cdef class MyType:
def __cinit__(self):
print "CINIT"
def __init__(self):
print "INIT"
cdef class MySubType(MyType):
def __cinit__(self):
print "CINIT(SUB)"
def __init__(self):
print "INIT"
class MyClass(object):
def __cinit__(self):
print "CINIT"
def __init__(self):
print "INIT"
class MyTypeSubClass(MyType):
def __cinit__(self):
# not called: Python class!
print "CINIT(PYSUB)"
def __init__(self):
print "INIT"
# only this can be safely optimised:
@cython.test_assert_path_exists('//PythonCapiCallNode')
@cython.test_fail_if_path_exists('//SimpleCallNode/AttributeNode')
def make_new():
"""
>>> isinstance(make_new(), MyType)
CINIT
True
"""
m = MyType.__new__(MyType)
return m
@cython.test_assert_path_exists('//PythonCapiCallNode')
@cython.test_fail_if_path_exists('//SimpleCallNode/AttributeNode')
def make_new_typed_target():
"""
>>> isinstance(make_new_typed_target(), MyType)
CINIT
True
"""
cdef MyType m
m = MyType.__new__(MyType)
return m
@cython.test_assert_path_exists('//PythonCapiCallNode')
@cython.test_fail_if_path_exists('//SimpleCallNode/AttributeNode')
def make_new_builtin():
"""
>>> isinstance(make_new_builtin(), tuple)
True
"""
m = dict.__new__(dict)
m = list.__new__(list)
m = tuple.__new__(tuple)
return m
@cython.test_assert_path_exists('//PythonCapiCallNode')
@cython.test_fail_if_path_exists('//SimpleCallNode/AttributeNode')
def make_new_none(type t=None):
"""
>>> isinstance(make_new_none(), MyType)
Traceback (most recent call last):
TypeError: object.__new__(X): X is not a type object (NoneType)
"""
m = t.__new__(t)
return m
# these cannot:
@cython.test_assert_path_exists('//SimpleCallNode/AttributeNode')
@cython.test_fail_if_path_exists('//PythonCapiCallNode')
def make_new_pyclass():
"""
>>> isinstance(make_new_pyclass(), MyTypeSubClass)
CINIT
True
"""
m = MyClass.__new__(MyClass)
m = MyTypeSubClass.__new__(MyTypeSubClass)
return m
@cython.test_assert_path_exists('//SimpleCallNode/AttributeNode')
@cython.test_fail_if_path_exists('//PythonCapiCallNode')
def make_new_args(type t1=None, type t2=None):
"""
>>> isinstance(make_new_args(), MyType)
CINIT
True
>>> isinstance(make_new_args(MyType), MyType)
CINIT
True
>>> isinstance(make_new_args(MyType, MyType), MyType)
CINIT
True
>>> isinstance(make_new_args(MyType, MySubType), MySubType)
Traceback (most recent call last):
TypeError: tp_new.MyType.__new__(tp_new.MySubType) is not safe, use tp_new.MySubType.__new__()
>>> isinstance(make_new_args(MySubType, MyType), MyType)
Traceback (most recent call last):
TypeError: tp_new.MySubType.__new__(tp_new.MyType): tp_new.MyType is not a subtype of tp_new.MySubType
"""
if t1 is None:
t1 = MyType
if t2 is None:
t2 = MyType
m = t1.__new__(t2)
return m
@cython.test_assert_path_exists('//SimpleCallNode/AttributeNode')
@cython.test_fail_if_path_exists('//PythonCapiCallNode')
def make_new_none_typed(tuple t=None):
"""
>>> isinstance(make_new_none(), MyType)
Traceback (most recent call last):
TypeError: object.__new__(X): X is not a type object (NoneType)
"""
m = t.__new__(t)
return m
@cython.test_assert_path_exists('//SimpleCallNode/AttributeNode')
@cython.test_fail_if_path_exists('//PythonCapiCallNode')
def make_new_untyped(t):
"""
>>> make_new_untyped(None)
Traceback (most recent call last):
TypeError: object.__new__(X): X is not a type object (NoneType)
"""
m = t.__new__(t)
return m
__doc__ = """
>>> readonly()
Traceback (most recent call last):
...
TypeError: readonly attribute
"""
import sys import sys
if sys.version_info[0] >= 3: if sys.version_info[0] >= 3:
__doc__ = __doc__.replace(u'TypeError:', u'AttributeError:') __doc__ = __doc__.replace(u'TypeError:', u'AttributeError:')
...@@ -53,11 +60,5 @@ def longdouble_access(): ...@@ -53,11 +60,5 @@ def longdouble_access():
def readonly(): def readonly():
"""
>>> readonly()
Traceback (most recent call last):
...
TypeError: readonly attribute
"""
c = MyClass() c = MyClass()
c.actual_double = 3 c.actual_double = 3
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