Commit 20fe9ab6 authored by Dag Sverre Seljebotn's avatar Dag Sverre Seljebotn

Big merge of -devel

parents 082156ee afb437d5
......@@ -13,3 +13,4 @@ a4abf0156540db4d3ebaa95712b65811c43c5acb 0.11-beta
4497f635d5fdbd38ebb841be4869fbfa2bbfdbb6 0.11.1.alpha
7bc36a0f81723117a19f92ffde1676a0884fef65 0.11.1.beta
6454db601984145f38e28d34176fca8a3a22329c 0.11.1
af6f1bed8cd40a2edefb57d3eacbc9274a8788b4 0.11.2.rc1
This diff is collapsed.
......@@ -50,6 +50,7 @@ builtin_function_table = [
#('round', "", "", ""),
('setattr', "OOO", "r", "PyObject_SetAttr"),
#('sum', "", "", ""),
('type', "O", "O", "PyObject_Type"),
#('unichr', "", "", ""),
#('unicode', "", "", ""),
#('vars', "", "", ""),
......
......@@ -153,5 +153,9 @@ def parse_command_line(args):
sys.exit(1)
if len(sources) == 0 and not options.show_version:
bad_usage()
if Options.embed and len(sources) > 1:
sys.stderr.write(
"cython: Only one source file allowed when using -embed\n")
sys.exit(1)
return options, sources
This diff is collapsed.
This diff is collapsed.
......@@ -125,6 +125,7 @@ class Context(object):
_check_c_declarations,
AnalyseExpressionsTransform(self),
OptimizeBuiltinCalls(),
ConstantFolding(),
IterationTransform(),
SwitchTransform(),
FinalOptimizePhase(self),
......
......@@ -100,6 +100,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
if h_types or h_vars or h_funcs or h_extension_types:
result.h_file = replace_suffix(result.c_file, ".h")
h_code = Code.CCodeWriter()
Code.GlobalState(h_code)
if options.generate_pxi:
result.i_file = replace_suffix(result.c_file, ".pxi")
i_code = Code.PyrexCodeWriter(result.i_file)
......@@ -161,6 +162,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
if api_funcs or has_api_extension_types:
result.api_file = replace_suffix(result.c_file, "_api.h")
h_code = Code.CCodeWriter()
Code.GlobalState(h_code)
name = self.api_name(env)
guard = Naming.api_guard_prefix + name
h_code.put_h_guard(guard)
......@@ -237,23 +239,31 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
def generate_c_code(self, env, options, result):
modules = self.referenced_modules
if Options.annotate or options.annotate:
code = Annotate.AnnotationCCodeWriter()
emit_linenums = False
rootwriter = Annotate.AnnotationCCodeWriter()
else:
code = Code.CCodeWriter(emit_linenums=options.emit_linenums)
h_code = code.insertion_point()
emit_linenums = options.emit_linenums
rootwriter = Code.CCodeWriter(emit_linenums=emit_linenums)
globalstate = Code.GlobalState(rootwriter, emit_linenums)
globalstate.initialize_main_c_code()
h_code = globalstate['h_code']
self.generate_module_preamble(env, modules, h_code)
code.globalstate.module_pos = self.pos
code.globalstate.directives = self.directives
globalstate.module_pos = self.pos
globalstate.directives = self.directives
code.globalstate.use_utility_code(refcount_utility_code)
globalstate.use_utility_code(refcount_utility_code)
code = globalstate['before_global_var']
code.putln('#define __Pyx_MODULE_NAME "%s"' % self.full_module_name)
code.putln("int %s%s = %s;" % (Naming.module_is_main, self.full_module_name.replace('.', '__'), int(Options.embed)))
code.putln("")
code.putln("/* Implementation of %s */" % env.qualified_name)
code.globalstate.insert_global_var_declarations_into(code)
code = globalstate['all_the_rest']
self.generate_cached_builtins_decls(env, code)
self.body.generate_function_definitions(env, code)
......@@ -270,20 +280,21 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
if Options.embed:
self.generate_main_method(env, code)
self.generate_filename_table(code)
self.generate_utility_functions(env, code, h_code)
self.generate_declarations_for_modules(env, modules, h_code)
self.generate_declarations_for_modules(env, modules, globalstate)
h_code.write('\n')
code.globalstate.close_global_decls()
for codetup, name in env.utility_code_list:
globalstate.use_utility_code(codetup, name)
globalstate.finalize_main_c_code()
f = open_new_file(result.c_file)
code.copyto(f)
rootwriter.copyto(f)
f.close()
result.c_file_generated = 1
if Options.annotate or options.annotate:
self.annotate(code)
code.save_annotation(result.main_source_file, result.c_file)
self.annotate(rootwriter)
rootwriter.save_annotation(result.main_source_file, result.c_file)
def find_referenced_modules(self, env, module_list, modules_seen):
if env not in modules_seen:
......@@ -381,18 +392,20 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
self.generate_exttype_vtable_struct(entry, code)
self.generate_exttype_vtabptr_declaration(entry, code)
def generate_declarations_for_modules(self, env, modules, code):
code.putln("")
code.putln("/* Type declarations */")
def generate_declarations_for_modules(self, env, modules, globalstate):
typecode = globalstate['type_declarations']
typecode.putln("")
typecode.putln("/* Type declarations */")
vtab_list, vtabslot_list = self.sort_type_hierarchy(modules, env)
self.generate_type_definitions(
env, modules, vtab_list, vtabslot_list, code)
env, modules, vtab_list, vtabslot_list, typecode)
modulecode = globalstate['module_declarations']
for module in modules:
defined_here = module is env
code.putln("/* Module declarations from %s */" %
modulecode.putln("/* Module declarations from %s */" %
module.qualified_name.encode("ASCII", "ignore"))
self.generate_global_declarations(module, code, defined_here)
self.generate_cfunction_predeclarations(module, code, defined_here)
self.generate_global_declarations(module, modulecode, defined_here)
self.generate_cfunction_predeclarations(module, modulecode, defined_here)
def generate_module_preamble(self, env, cimported_modules, code):
code.putln('/* Generated by Cython %s on %s */' % (
......@@ -508,6 +521,9 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln(" #ifndef __cdecl")
code.putln(" #define __cdecl")
code.putln(" #endif")
code.putln(" #ifndef __fastcall")
code.putln(" #define __fastcall")
code.putln(" #endif")
code.putln("#else")
code.putln(" #define _USE_MATH_DEFINES")
code.putln("#endif")
......@@ -534,6 +550,11 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln("#include <math.h>")
code.putln("#define %s" % Naming.api_guard_prefix + self.api_name(env))
self.generate_includes(env, cimported_modules, code)
if env.directives['c99_complex']:
code.putln("#ifndef _Complex_I")
code.putln("#include <complex.h>")
code.putln("#endif")
code.putln("#define __PYX_USE_C99_COMPLEX defined(_Complex_I)")
code.putln('')
code.put(Nodes.utility_function_predeclarations)
code.put(PyrexTypes.type_conversion_predeclarations)
......@@ -1805,14 +1826,17 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
env.module_cname,
Naming.builtins_cname,
code.error_goto(self.pos)))
if Options.embed:
__main__name = code.globalstate.get_py_string_const(
EncodedString("__main__"), identifier=True)
code.putln(
'if (__Pyx_SetAttrString(%s, "__name__", %s) < 0) %s;' % (
env.module_cname,
__main__name.cname,
code.error_goto(self.pos)))
__main__name = code.globalstate.get_py_string_const(
EncodedString("__main__"), identifier=True)
code.putln("if (%s%s) {" % (Naming.module_is_main, self.full_module_name.replace('.', '__')))
code.putln(
'if (__Pyx_SetAttrString(%s, "__name__", %s) < 0) %s;' % (
env.module_cname,
__main__name.cname,
code.error_goto(self.pos)))
code.putln("}")
if Options.pre_import is not None:
code.putln(
'%s = PyImport_AddModule(__Pyx_NAMESTR("%s"));' % (
......@@ -2040,22 +2064,6 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
"%s = &%s;" % (
type.typeptr_cname, type.typeobj_cname))
def generate_utility_functions(self, env, code, h_code):
for codetup, name in env.utility_code_list:
code.globalstate.use_utility_code(codetup, name)
code.globalstate.put_utility_code_protos(h_code)
code.putln("")
code.putln("/* Runtime support code */")
code.putln("")
code.putln("static void %s(void) {" % Naming.fileinit_cname)
code.putln("%s = %s;" %
(Naming.filetable_cname, Naming.filenames_cname))
code.putln("}")
code.globalstate.put_utility_code_defs(code)
code.put(PyrexTypes.type_conversion_functions)
code.putln("")
#------------------------------------------------------------------------------------
#
# Runtime support code
......@@ -2460,7 +2468,11 @@ static __Pyx_RefnannyAPIStruct *__Pyx_Refnanny = NULL;
main_method = UtilityCode(
impl = """
#if PY_MAJOR_VERSION < 3 || (!defined(WIN32) && !defined(MS_WINDOWS))
int main(int argc, char** argv) {
#else
int wmain(int argc, wchar_t **argv) {
#endif
int r = 0;
PyObject* m = NULL;
Py_SetProgramName(argv[0]);
......
......@@ -44,6 +44,7 @@ vtabptr_prefix = pyrex_prefix + "vtabptr_"
vtabstruct_prefix = pyrex_prefix + "vtabstruct_"
opt_arg_prefix = pyrex_prefix + "opt_args_"
convert_func_prefix = pyrex_prefix + "convert_"
module_is_main = pyrex_prefix + "module_is_main_"
args_cname = pyrex_prefix + "args"
pykwdlist_cname = pyrex_prefix + "pyargnames"
......
......@@ -569,6 +569,13 @@ class CFuncDeclaratorNode(CDeclaratorNode):
nogil = self.nogil, with_gil = self.with_gil, is_overridable = self.overridable)
if self.optional_arg_count:
func_type.op_arg_struct = PyrexTypes.c_ptr_type(self.op_args_struct.type)
callspec = env.directives['callspec']
if callspec:
current = func_type.calling_convention
if current and current != callspec:
error(self.pos, "cannot have both '%s' and '%s' "
"calling conventions" % (current, callspec))
func_type.calling_convention = callspec
return self.base.analyse(func_type, env)
......@@ -650,6 +657,7 @@ class CSimpleBaseTypeNode(CBaseTypeNode):
# is_basic_c_type boolean
# signed boolean
# longness integer
# complex boolean
# is_self_arg boolean Is self argument of C method
child_attrs = []
......@@ -690,6 +698,11 @@ class CSimpleBaseTypeNode(CBaseTypeNode):
self.arg_name = self.name
else:
error(self.pos, "'%s' is not a type identifier" % self.name)
if self.complex:
if not type.is_numeric or type.is_complex:
error(self.pos, "can only complexify c numeric types")
type = PyrexTypes.CComplexType(type)
type.create_declaration_utility_code(env)
if type:
return type
else:
......@@ -763,15 +776,26 @@ class CVarDefNode(StatNode):
dest_scope = env
self.dest_scope = dest_scope
base_type = self.base_type.analyse(env)
need_property = False
if (dest_scope.is_c_class_scope
and self.visibility == 'public'
and base_type.is_pyobject
and (base_type.is_builtin_type or base_type.is_extension_type)):
self.need_properties = []
and self.visibility == 'public'
and base_type.is_pyobject
and (base_type.is_builtin_type or base_type.is_extension_type)):
# If the field is settable and extension type, then the CPython mechanism does
# not do enough type-checking for us.
need_property = True
elif (base_type.is_typedef and base_type.typedef_is_external
and (self.visibility in ('public', 'readonly'))):
# If the field is an external typedef, we cannot be sure about the type,
# so do conversion ourself rather than rely on the CPython mechanism (through
# a property; made in AnalyseDeclarationsTransform).
need_property = True
if need_property:
visibility = 'private'
self.need_properties = []
else:
need_property = False
visibility = self.visibility
for declarator in self.declarators:
......@@ -1867,6 +1891,10 @@ class DefNode(FuncDefNode):
has_star_or_kw_args = self.star_arg is not None \
or self.starstar_arg is not None or has_kwonly_args
for arg in self.args:
if not arg.type.is_pyobject and arg.type.from_py_function is None:
arg.type.create_from_py_utility_code(env)
if not self.signature_has_generic_args():
if has_star_or_kw_args:
error(self.pos, "This method cannot have * or keyword arguments")
......@@ -3069,10 +3097,10 @@ class InPlaceAssignmentNode(AssignmentNode):
if c_op == "//":
c_op = "/"
elif c_op == "**":
if self.lhs.type.is_int and self.rhs.type.is_int:
error(self.pos, "** with two C int types is ambiguous")
else:
error(self.pos, "No C inplace power operator")
error(self.pos, "No C inplace power operator")
elif self.lhs.type.is_complex and not code.globalstate.directives['c99_complex']:
error(self.pos, "Inplace operators not implemented for complex types.")
# have to do assignment directly to avoid side-effects
if isinstance(self.lhs, ExprNodes.IndexNode) and self.lhs.is_buffer_access:
self.lhs.generate_buffer_setitem_code(self.rhs, code, c_op)
......
......@@ -54,7 +54,7 @@ c_line_in_traceback = 1
embed = False
# Declare pragmas
# Declare compiler directives
option_defaults = {
'boundscheck' : True,
'nonecheck' : False,
......@@ -64,6 +64,9 @@ option_defaults = {
'cdivision': True, # Will be False in 0.12
'cdivision_warnings': False,
'always_allow_keywords': False,
'wraparound' : True,
'c99_complex' : False, # Don't use macro wrappers for complex arith, not sure what to name this...
'callspec' : "",
}
# Override types possibilities above, if needed
......@@ -94,6 +97,11 @@ def parse_option_value(name, value):
if value == "True": return True
elif value == "False": return False
else: raise ValueError("%s directive must be set to True or False" % name)
elif type is int:
try:
return int(value)
except ValueError:
raise ValueError("%s directive must be set to an integer" % name)
else:
assert False
......
......@@ -435,6 +435,11 @@ class InterpretCompilerDirectives(CythonTransform, SkipDeclarations):
raise PostParseError(dec.function.pos,
'The %s option takes one compile-time boolean argument' % optname)
return (optname, args[0].value)
elif optiontype is str:
if kwds is not None or len(args) != 1 or not isinstance(args[0], StringNode):
raise PostParseError(dec.function.pos,
'The %s option takes one compile-time string argument' % optname)
return (optname, args[0].value)
elif optiontype is dict:
if len(args) != 0:
raise PostParseError(dec.function.pos,
......@@ -589,62 +594,6 @@ class WithTransform(CythonTransform, SkipDeclarations):
return node
class ComprehensionTransform(VisitorTransform):
"""Prevent the target of list/set/dict comprehensions from leaking by
moving it into a temp variable. This mimics the behaviour of all
comprehensions in Py3 and of generator expressions in Py2.x.
This must run before the IterationTransform, which might replace
for-loops with while-loops. We only handle for-loops here.
"""
def visit_ModuleNode(self, node):
self.comprehension_targets = {}
self.visitchildren(node)
return node
visit_Node = VisitorTransform.recurse_to_children
def visit_ComprehensionNode(self, node):
if type(node.loop) not in (Nodes.ForInStatNode,
Nodes.ForFromStatNode):
# this should not happen!
self.visitchildren(node)
return node
outer_comprehension_targets = self.comprehension_targets
self.comprehension_targets = outer_comprehension_targets.copy()
# find all NameNodes in the loop target
target_name_collector = NameNodeCollector()
target_name_collector.visit(node.loop.target)
targets = target_name_collector.name_nodes
# create a temp variable for each target name
temps = []
for target in targets:
handle = TempHandle(target.type)
temps.append(handle)
self.comprehension_targets[target.entry.cname] = handle.ref(node.pos)
# replace name references in the loop code by their temp node
self.visitchildren(node, ['loop'])
loop = node.loop
if type(loop) is Nodes.ForFromStatNode and loop.target.type.is_numeric:
loop.loopvar_node = loop.target
node.loop = TempsBlockNode(node.pos, body=node.loop, temps=temps)
self.comprehension_targets = outer_comprehension_targets
return node
def visit_NameNode(self, node):
if node.entry:
replacement = self.comprehension_targets.get(node.entry.cname)
if replacement is not None:
return replacement
return node
class DecoratorTransform(CythonTransform, SkipDeclarations):
def visit_DefNode(self, func_node):
......@@ -676,6 +625,12 @@ property NAME:
ATTR = value
""", level='c_class')
readonly_property = TreeFragment(u"""
property NAME:
def __get__(self):
return ATTR
""", level='c_class')
def __call__(self, root):
self.env_stack = [root.scope]
# needed to determine if a cdef var is declared after it's used.
......@@ -752,7 +707,7 @@ property NAME:
# mechanism for them.
stats = []
for entry in node.need_properties:
property = self.create_Property(entry)
property = self.create_Property(entry, node.visibility == 'readonly')
property.analyse_declarations(node.dest_scope)
self.visit(property)
stats.append(property)
......@@ -760,8 +715,12 @@ property NAME:
else:
return None
def create_Property(self, entry):
property = self.basic_property.substitute({
def create_Property(self, entry, readonly):
if readonly:
template = self.readonly_property
else:
template = self.basic_property
property = template.substitute({
u"ATTR": AttributeNode(pos=entry.pos,
obj=NameNode(pos=entry.pos, name="self"),
attribute=entry.name),
......
......@@ -1753,7 +1753,7 @@ def p_calling_convention(s):
else:
return ""
calling_convention_words = ("__stdcall", "__cdecl")
calling_convention_words = ("__stdcall", "__cdecl", "__fastcall")
def p_c_complex_base_type(s):
# s.sy == '('
......@@ -1770,6 +1770,7 @@ def p_c_simple_base_type(s, self_flag, nonempty):
is_basic = 0
signed = 1
longness = 0
complex = 0
module_path = []
pos = s.position()
if not s.sy == 'IDENT':
......@@ -1788,6 +1789,9 @@ def p_c_simple_base_type(s, self_flag, nonempty):
s.next()
else:
name = 'int'
if s.sy == 'IDENT' and s.systring == 'complex':
complex = 1
s.next()
elif looking_at_dotted_name(s):
#print "p_c_simple_base_type: looking_at_type_name at", s.position()
name = s.systring
......@@ -1816,7 +1820,8 @@ def p_c_simple_base_type(s, self_flag, nonempty):
type_node = Nodes.CSimpleBaseTypeNode(pos,
name = name, module_path = module_path,
is_basic_c_type = is_basic, signed = signed,
longness = longness, is_self_arg = self_flag)
complex = complex, longness = longness,
is_self_arg = self_flag)
# Treat trailing [] on type as buffer access if it appears in a context
......@@ -2561,7 +2566,7 @@ def p_code(s, level=None):
repr(s.sy), repr(s.systring)))
return body
COMPILER_DIRECTIVE_COMMENT_RE = re.compile(r"^#\s*cython:\s*([a-z_]+)\s*=(.*)$")
COMPILER_DIRECTIVE_COMMENT_RE = re.compile(r"^#\s*cython:\s*(\w+)\s*=(.*)$")
def p_compiler_directive_comments(s):
result = {}
......@@ -2571,10 +2576,10 @@ def p_compiler_directive_comments(s):
name = m.group(1)
try:
value = Options.parse_option_value(str(name), str(m.group(2).strip()))
if value is not None: # can be False!
result[name] = value
except ValueError, e:
s.error(e.args[0], fatal=False)
if value is not None: # can be False!
result[name] = value
s.next()
return result
......
This diff is collapsed.
......@@ -335,7 +335,7 @@ class Scope(object):
cname = name
else:
cname = self.mangle(Naming.type_prefix, name)
type = PyrexTypes.CTypedefType(cname, base_type)
type = PyrexTypes.CTypedefType(cname, base_type, (visibility == 'extern'))
entry = self.declare_type(name, type, pos, cname, visibility)
type.qualified_name = entry.qualified_name
return entry
......
......@@ -154,7 +154,14 @@ class SlotDescriptor(object):
code.putln("#if PY_MAJOR_VERSION >= 3")
if flag:
code.putln("#if (PY_MAJOR_VERSION >= 3) || (Py_TPFLAGS_DEFAULT & %s)" % flag)
if py3k == '<RESERVED>':
code.putln("#if PY_MAJOR_VERSION >= 3")
code.putln("0, /*reserved*/")
code.putln("#else")
code.putln("%s, /*%s*/" % (value, self.slot_name))
if py3k == '<RESERVED>':
code.putln("#endif")
if flag or (not py3k or not py2) or self.ifdef:
code.putln("#endif")
......@@ -212,10 +219,13 @@ class MethodSlot(SlotDescriptor):
def slot_code(self, scope):
entry = scope.lookup_here(self.method_name)
if entry:
if entry and entry.func_cname:
return entry.func_cname
else:
return "0"
if self.default is not None:
entry = scope.lookup_here(self.default)
if entry and entry.func_cname:
return entry.func_cname
return "0"
class InternalMethodSlot(SlotDescriptor):
......@@ -557,8 +567,8 @@ PyNumberMethods = (
MethodSlot(binaryfunc, "nb_xor", "__xor__"),
MethodSlot(binaryfunc, "nb_or", "__or__"),
EmptySlot("nb_coerce", py3k = False),
MethodSlot(unaryfunc, "nb_int", "__int__"),
MethodSlot(unaryfunc, "nb_long", "__long__"),
MethodSlot(unaryfunc, "nb_int", "__int__", default="__long__"),
MethodSlot(unaryfunc, "nb_long", "__long__", default="__int__", py3k = "<RESERVED>"),
MethodSlot(unaryfunc, "nb_float", "__float__"),
MethodSlot(unaryfunc, "nb_oct", "__oct__", py3k = False),
MethodSlot(unaryfunc, "nb_hex", "__hex__", py3k = False),
......
version = '0.11.1'
version = '0.11.2.rc1'
This diff is collapsed.
cdef extern int f()
cdef extern int f1()
cdef extern int __stdcall g()
cdef extern int __cdecl f2()
cdef extern int __cdecl h()
cdef extern int __stdcall f3()
cdef extern int (__stdcall *p)()
cdef extern int __fastcall f4()
cdef extern int (*p1)()
cdef extern int (__cdecl *p2)()
cdef extern int (__stdcall *p3)()
cdef extern int (__fastcall *p4)()
p1 = f1
p2 = f2
p3 = f3
p4 = f4
......@@ -4,7 +4,11 @@ cdef void foo(obj):
cdef int *p2
i1 = p1 # error
p2 = obj # error
obj = p2 # error
_ERRORS = u"""
5:16: Cannot assign type 'char *' to 'int'
6:17: Cannot convert Python object to 'int *'
8:17: Cannot convert 'int *' to Python object
"""
cimport cython
@cython.callspec("")
cdef void h1(): pass
@cython.callspec("__cdecl")
cdef void __cdecl h2(): pass
@cython.callspec("__stdcall")
cdef void __stdcall h3(): pass
@cython.callspec("__fastcall")
cdef void __fastcall h4(): pass
@cython.callspec("__cdecl")
cdef void __stdcall h5(): pass # fail
@cython.callspec("__cdecl")
cdef void __fastcall h6(): pass # fail
cdef void (*p1)()
cdef void (__cdecl *p2)()
cdef void (__stdcall *p3)()
cdef void (__fastcall *p4)()
p1 = h1
p2 = h2
p3 = h3
p4 = h4
#p1 = h2 # fail
#p1 = h3 # fail
#p1 = h4 # fail
#p2 = h1 # fail
#p2 = h3 # fail
#p2 = h4 # fail
_ERRORS = u"""
16:22: cannot have both '__stdcall' and '__cdecl' calling conventions
19:23: cannot have both '__fastcall' and '__cdecl' calling conventions
"""
#31:14: Cannot assign type 'void (__cdecl )(void)' to 'void (*)(void)'
#32:14: Cannot assign type 'void (__stdcall )(void)' to 'void (*)(void)'
#33:14: Cannot assign type 'void (__fastcall )(void)' to 'void (*)(void)'
#35:14: Cannot assign type 'void (void)' to 'void (__cdecl *)(void)'
#36:14: Cannot assign type 'void (__stdcall )(void)' to 'void (__cdecl *)(void)'
#37:14: Cannot assign type 'void (__fastcall )(void)' to 'void (__cdecl *)(void)'
cdef object blarg
def foo(obj):
cdef int *p
p = <int *>blarg # okay
p = <int *>(foo + blarg) # error - temporary
cdef void *p
p = <void *>blarg # ok
p = <void *>(obj + blarg) # error - temporary
_ERRORS = u"""
6:5: Casting temporary Python object to non-numeric non-Python type
"""
......@@ -25,7 +25,7 @@ cdef object m():
i = 42
obj = None
17L
7j
<object>7j
help
`"Hello"`
import fred
......@@ -85,7 +85,7 @@ _ERRORS = u"""
15: 5: Calling gil-requiring function not allowed without gil
24: 9: Calling gil-requiring function not allowed without gil
26:12: Assignment of Python object not allowed without gil
28: 8: Constructing complex number not allowed without gil
28:16: Constructing complex number not allowed without gil
29:12: Accessing Python global or builtin not allowed without gil
30: 8: Backquote expression not allowed without gil
31:15: Assignment of Python object not allowed without gil
......
a = 3
cdef void* allowed = <void*>a
cdef double* disallowed = <double*>a
_ERRORS = u"""
5:26: Python objects cannot be casted to pointers of primitive types
"""
......@@ -341,60 +341,6 @@ def explicitly_release_buffer():
x = None
print "After release"
#
# Format strings
#
@testcase
def alignment_string(object[int] buf):
"""
>>> alignment_string(IntMockBuffer(None, [1,2], format="@i"))
2
>>> alignment_string(IntMockBuffer(None, [1,2], format="@i@@"))
2
>>> alignment_string(IntMockBuffer(None, [1,2], format=">i"))
Traceback (most recent call last):
...
ValueError: Buffer acquisition error: Only native byte order, size and alignment supported.
>>> alignment_string(IntMockBuffer(None, [1,2], format="<i"))
Traceback (most recent call last):
...
ValueError: Buffer acquisition error: Only native byte order, size and alignment supported.
>>> alignment_string(IntMockBuffer(None, [1,2], format="=i"))
Traceback (most recent call last):
...
ValueError: Buffer acquisition error: Only native byte order, size and alignment supported.
>>> alignment_string(IntMockBuffer(None, [1,2], format="!i"))
Traceback (most recent call last):
...
ValueError: Buffer acquisition error: Only native byte order, size and alignment supported.
"""
print buf[1]
@testcase
def wrong_string(object[int] buf):
"""
>>> wrong_string(IntMockBuffer(None, [1,2], format="if"))
Traceback (most recent call last):
...
ValueError: Buffer dtype mismatch (expected end, got float)
>>> wrong_string(IntMockBuffer(None, [1,2], format="$$"))
Traceback (most recent call last):
...
ValueError: Buffer dtype mismatch (expected int, got unparseable format string)
"""
print buf[1]
@testcase
def int_and_long_are_same():
"""
>>> int_and_long_are_same()
"""
cdef object[int] intarr
cdef object[long] longarr
if sizeof(int) == sizeof(long):
intarr = IntMockBuffer(None, [1,2], format='l')
longarr = IntMockBuffer(None, [1,2])
#
# Getting items and index bounds checking
#
......@@ -532,38 +478,25 @@ def no_negative_indices(object[int, negative_indices=False] buf, int idx):
"""
return buf[idx]
#
# Buffer type mismatch examples. Varying the type and access
# method simultaneously, the odds of an interaction is virtually
# zero.
#
@testcase
def fmtst1(buf):
@cython.wraparound(False)
def wraparound_directive(object[int] buf, int pos_idx, int neg_idx):
"""
>>> fmtst1(IntMockBuffer("A", range(3)))
Traceback (most recent call last):
...
ValueError: Buffer dtype mismatch (expected float, got int)
"""
cdef object[float] a = buf
@testcase
def fmtst2(object[int] buf):
"""
>>> fmtst2(FloatMockBuffer("A", range(3)))
Again, the most interesting thing here is to inspect the C source.
>>> A = IntMockBuffer(None, range(4))
>>> wraparound_directive(A, 2, -1)
5
>>> wraparound_directive(A, -1, 2)
Traceback (most recent call last):
...
ValueError: Buffer dtype mismatch (expected int, got float)
IndexError: Out of bounds on buffer access (axis 0)
"""
cdef int byneg
with cython.wraparound(True):
byneg = buf[neg_idx]
return buf[pos_idx] + byneg
@testcase
def ndim1(object[int, ndim=2] buf):
"""
>>> ndim1(IntMockBuffer("A", range(3)))
Traceback (most recent call last):
...
ValueError: Buffer has wrong number of dimensions (expected 2, got 1)
"""
#
# Test which flags are passed.
......@@ -860,8 +793,7 @@ def printbuf_td_cy_int(object[td_cy_int] buf, shape):
>>> printbuf_td_cy_int(ShortMockBuffer(None, range(3)), (3,))
Traceback (most recent call last):
...
ValueError: Buffer dtype mismatch (expected bufaccess.td_cy_int, got short)
ValueError: Buffer dtype mismatch, expected 'bufaccess.td_cy_int' but got 'short'
"""
cdef int i
for i in range(shape[0]):
......@@ -876,7 +808,7 @@ def printbuf_td_h_short(object[td_h_short] buf, shape):
>>> printbuf_td_h_short(IntMockBuffer(None, range(3)), (3,))
Traceback (most recent call last):
...
ValueError: Buffer dtype mismatch (expected bufaccess.td_h_short, got int)
ValueError: Buffer dtype mismatch, expected 'bufaccess.td_h_short' but got 'int'
"""
cdef int i
for i in range(shape[0]):
......@@ -891,7 +823,7 @@ def printbuf_td_h_cy_short(object[td_h_cy_short] buf, shape):
>>> printbuf_td_h_cy_short(IntMockBuffer(None, range(3)), (3,))
Traceback (most recent call last):
...
ValueError: Buffer dtype mismatch (expected bufaccess.td_h_cy_short, got int)
ValueError: Buffer dtype mismatch, expected 'bufaccess.td_h_cy_short' but got 'int'
"""
cdef int i
for i in range(shape[0]):
......@@ -906,7 +838,7 @@ def printbuf_td_h_ushort(object[td_h_ushort] buf, shape):
>>> printbuf_td_h_ushort(ShortMockBuffer(None, range(3)), (3,))
Traceback (most recent call last):
...
ValueError: Buffer dtype mismatch (expected bufaccess.td_h_ushort, got short)
ValueError: Buffer dtype mismatch, expected 'bufaccess.td_h_ushort' but got 'short'
"""
cdef int i
for i in range(shape[0]):
......@@ -921,7 +853,7 @@ def printbuf_td_h_double(object[td_h_double] buf, shape):
>>> printbuf_td_h_double(FloatMockBuffer(None, [0.25, 1, 3.125]), (3,))
Traceback (most recent call last):
...
ValueError: Buffer dtype mismatch (expected bufaccess.td_h_double, got float)
ValueError: Buffer dtype mismatch, expected 'bufaccess.td_h_double' but got 'float'
"""
cdef int i
for i in range(shape[0]):
......@@ -1033,7 +965,7 @@ def buffer_cast_fails(object[char, cast=True] buf):
>>> buffer_cast_fails(IntMockBuffer(None, [0]))
Traceback (most recent call last):
...
ValueError: Attempted cast of buffer to datatype of different size.
ValueError: Item size of buffer (4 bytes) does not match size of 'char' (1 byte)
"""
return buf[0]
......@@ -1366,48 +1298,31 @@ cdef class NestedStructMockBuffer(MockBuffer):
@testcase
def basic_struct(object[MyStruct] buf):
"""
See also buffmt.pyx
>>> basic_struct(MyStructMockBuffer(None, [(1, 2, 3, 4, 5)]))
1 2 3 4 5
>>> basic_struct(MyStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="bbqii"))
1 2 3 4 5
>>> basic_struct(MyStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="23bqii"))
Traceback (most recent call last):
...
ValueError: Buffer dtype mismatch (expected long long, got char)
>>> basic_struct(MyStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="i"))
Traceback (most recent call last):
...
ValueError: Buffer dtype mismatch (expected char, got int)
"""
print buf[0].a, buf[0].b, buf[0].c, buf[0].d, buf[0].e
@testcase
def nested_struct(object[NestedStruct] buf):
"""
See also buffmt.pyx
>>> nested_struct(NestedStructMockBuffer(None, [(1, 2, 3, 4, 5)]))
1 2 3 4 5
>>> nested_struct(NestedStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="T{ii}T{2i}i"))
1 2 3 4 5
>>> nested_struct(NestedStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="iiiii"))
Traceback (most recent call last):
...
ValueError: Buffer dtype mismatch (expected SmallStruct, got int)
>>> nested_struct(NestedStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="T{iii}T{ii}i"))
Traceback (most recent call last):
...
ValueError: Buffer dtype mismatch (expected end of SmallStruct struct, got int)
"""
print buf[0].x.a, buf[0].x.b, buf[0].y.a, buf[0].y.b, buf[0].z
cdef struct LongComplex:
long double real
long double imag
cdef struct MixedComplex:
long double real
float imag
cdef class LongComplexMockBuffer(MockBuffer):
cdef int write(self, char* buf, object value) except -1:
cdef LongComplex* s
......@@ -1418,24 +1333,33 @@ cdef class LongComplexMockBuffer(MockBuffer):
cdef get_itemsize(self): return sizeof(LongComplex)
cdef get_default_format(self): return b"Zg"
#cdef extern from "complex.h":
# pass
@testcase
def complex_struct_dtype(object[LongComplex] buf):
def complex_dtype(object[long double complex] buf):
"""
Note that the format string is "Zg" rather than "2g"...
>>> complex_struct_dtype(LongComplexMockBuffer(None, [(0, -1)]))
0.0 -1.0
>>> complex_dtype(LongComplexMockBuffer(None, [(0, -1)]))
-1j
"""
print buf[0].real, buf[0].imag
print buf[0]
@testcase
def mixed_complex_struct_dtype(object[MixedComplex] buf):
def complex_inplace(object[long double complex] buf):
"""
Triggering a specific execution path for this case.
>>> mixed_complex_struct_dtype(LongComplexMockBuffer(None, [(0, -1)]))
Traceback (most recent call last):
...
ValueError: Cannot store complex number in 'MixedComplex' as 'long double' differs from 'float' in size.
>>> complex_inplace(LongComplexMockBuffer(None, [(0, -1)]))
(1+1j)
"""
buf[0] = buf[0] + 1 + 2j
print buf[0]
@testcase
def complex_struct_dtype(object[LongComplex] buf):
"""
Note that the format string is "Zg" rather than "2g", yet a struct
is accessed.
>>> complex_struct_dtype(LongComplexMockBuffer(None, [(0, -1)]))
0.0 -1.0
"""
print buf[0].real, buf[0].imag
......@@ -1448,7 +1372,7 @@ def complex_struct_inplace(object[LongComplex] buf):
buf[0].real += 1
buf[0].imag += 2
print buf[0].real, buf[0].imag
#
# Nogil
#
......
from __future__ import unicode_literals
# Tests buffer format string parsing.
__test__ = {}
def testcase(func):
__test__[func.__name__] = func.__doc__
return func
cimport stdlib
def little_endian():
cdef unsigned int n = 1
return (<unsigned char*>&n)[0] != 0
if little_endian():
current_endian = '<'
other_endian = '>'
else:
current_endian = '>'
other_endian = '<'
cdef struct align_of_float_helper:
char ch
float d
cdef struct align_of_int_helper:
char ch
int i
float_align = sizeof(align_of_float_helper) - sizeof(float)
int_align = sizeof(align_of_int_helper) - sizeof(int)
if float_align != 4 or sizeof(float) != 4:
raise RuntimeError("Alignment or size of float is %d on this system, please report to cython-dev for a testcase fix" % float_align)
if int_align != 4 or sizeof(int) != 4:
raise RuntimeError("Alignment or size of int is %d on this system, please report to cython-dev for a testcase fix" % int_align)
cdef class MockBuffer:
cdef Py_ssize_t zero
cdef Py_ssize_t minusone
cdef object format
cdef object itemsize
def __init__(self, format, itemsize):
self.format = unicode(format).encode(u"ASCII")
self.itemsize = itemsize
self.zero = 0
self.minusone = -1
def __getbuffer__(self, Py_buffer* info, int flags):
info.buf = NULL
info.strides = &self.zero
info.suboffsets = &self.minusone
info.shape = &self.zero
info.ndim = 1
info.format = self.format
info.itemsize = self.itemsize
@testcase
def _int(fmt):
"""
>>> _int("i")
>>> _int("b")
Traceback (most recent call last):
...
ValueError: Buffer dtype mismatch, expected 'int' but got 'char'
>>> _int("if")
Traceback (most recent call last):
...
ValueError: Buffer dtype mismatch, expected end but got 'float'
>>> _int("$$")
Traceback (most recent call last):
...
ValueError: Does not understand character buffer dtype format string ('$')
"""
cdef object[int] buf = MockBuffer(fmt, sizeof(int))
@testcase
def _ulong(fmt):
"""
>>> _ulong("L")
"""
cdef object[unsigned long] buf = MockBuffer(fmt, sizeof(unsigned long))
@testcase
def wrongsize():
"""
>>> wrongsize()
Traceback (most recent call last):
...
ValueError: Item size of buffer (1 byte) does not match size of 'float' (4 bytes)
"""
cdef object[float] buf = MockBuffer("f", 1)
@testcase
def _obj(fmt):
"""
>>> _obj("O")
>>> _obj("i")
Traceback (most recent call last):
...
ValueError: Buffer dtype mismatch, expected 'Python object' but got 'int'
"""
cdef object[object] buf = MockBuffer(fmt, sizeof(void*))
cdef struct ComplexFloat:
float real
float imag
ctypedef struct Char3Int:
char a
int b
int c
int d
cdef struct CharIntCFloat:
char a
int b
ComplexFloat c
float d
cdef struct UnpackedStruct1:
char a
int b
ComplexFloat c
float c2
Char3Int d
ctypedef struct UnpackedStruct2:
CharIntCFloat a
Char3Int b
ctypedef struct UnpackedStruct3:
CharIntCFloat a
char b
int c, d, e
cdef struct UnpackedStruct4:
char a
int b
ComplexFloat c
float c2
char d
int e, f, g
@testcase
def char3int(fmt):
"""
>>> char3int("ciii")
>>> char3int("c1i1i1i")
>>> char3int("c3i")
>>> char3int("ci2i")
#TODO > char3int("c@i@2i")
Extra pad bytes (assuming int size is 4 or more)
>>> char3int("cxiii")
>>> char3int("c3xiii")
>>> char3int("cxxxiii")
Standard alignment (assming int size is 4)
>>> char3int("=c3xiii")
>>> char3int("=ciii")
Traceback (most recent call last):
...
ValueError: Buffer dtype mismatch; next field is at offset 1 but 4 expected
#TODO char3int("=cxxx@iii")
Error:
>>> char3int("cii")
Traceback (most recent call last):
...
ValueError: Buffer dtype mismatch, expected 'int' but got end in 'Char3Int.d'
"""
obj = MockBuffer(fmt, sizeof(Char3Int))
cdef object[Char3Int, ndim=1] buf = obj
@testcase
def unpacked_struct(fmt):
"""
Native formats:
>>> unpacked_struct("biZffbiii")
>>> unpacked_struct("@bi3fb3i")
>>> unpacked_struct("@biZffbi2i")
>>> unpacked_struct("biZffT{biii}")
>>> unpacked_struct("bT{ifffb2i}i")
>>> unpacked_struct("biZffb3T{i}")
>>> unpacked_struct("T{b}T{T{iZffT{bi}}}2T{T{i}}")
"""
assert (sizeof(UnpackedStruct1) == sizeof(UnpackedStruct2)
== sizeof(UnpackedStruct3) == sizeof(UnpackedStruct4))
obj = MockBuffer(fmt, sizeof(UnpackedStruct1))
cdef object[UnpackedStruct1, ndim=1] buf1 = obj
cdef object[UnpackedStruct2, ndim=1] buf2 = obj
cdef object[UnpackedStruct3, ndim=1] buf3 = obj
cdef object[UnpackedStruct4, ndim=1] buf4 = obj
cdef struct ComplexTest:
ComplexFloat a, b, c
@testcase
def complex_test(fmt):
"""
>>> complex_test("ZfZfZf")
>>> complex_test("3Zf")
>>> complex_test("6f")
>>> complex_test("3T{Zf}")
>>> complex_test("fZfZff")
Traceback (most recent call last):
...
ValueError: Buffer dtype mismatch, expected 'float' but got 'complex float' in 'ComplexFloat.imag'
"""
obj = MockBuffer(fmt, sizeof(ComplexTest))
cdef object[ComplexTest] buf1 = obj
@testcase
def alignment_string(fmt, exc=None):
"""
>>> alignment_string("@i")
>>> alignment_string("%si" % current_endian)
>>> alignment_string("%si" % other_endian, "X-endian buffer not supported on X-endian compiler")
>>> alignment_string("=i")
"""
cdef object[int] buf
try:
buf = MockBuffer(fmt, sizeof(int))
except ValueError, e:
msg = unicode(e).replace("Big", "X").replace("Little", "X").replace("big", "X").replace("little", "X")
if msg != exc:
print msg
print " is not equal to"
print exc
return
if exc:
print "fail"
@testcase
def int_and_long_are_same():
"""
>>> int_and_long_are_same()
"""
cdef object[int] intarr
cdef object[long] longarr
if sizeof(int) == sizeof(long):
intarr = MockBuffer("l", sizeof(int))
longarr = MockBuffer("i", sizeof(int))
cdef struct MixedComplex:
double real
float imag
@testcase
def mixed_complex_struct():
"""
Triggering a specific execution path for this case.
>>> mixed_complex_struct()
Traceback (most recent call last):
...
ValueError: Buffer dtype mismatch, expected 'double' but got 'complex double' in 'MixedComplex.real'
"""
cdef object[MixedComplex] buf = MockBuffer("Zd",
sizeof(MixedComplex))
cdef packed struct PackedSubStruct:
char x
int y
cdef packed struct PackedStruct:
char a
int b
PackedSubStruct sub
@testcase
def packed_struct(fmt):
"""
Assuming int is four bytes:
>>> packed_struct("^cici")
>>> packed_struct("=cibi")
>>> packed_struct("^c@i^ci")
Traceback (most recent call last):
...
ValueError: Buffer packing mode currently only allowed at beginning of format string (this is a defect)
However aligned access won't work:
>>> packed_struct("@cici")
Traceback (most recent call last):
...
ValueError: Buffer dtype mismatch; next field is at offset 4 but 1 expected
"""
cdef object[PackedStruct] buf = MockBuffer(fmt, sizeof(PackedStruct))
# TODO: empty struct
# TODO: Incomplete structs
# TODO: mixed structs
......@@ -666,6 +666,17 @@ class MyBadInt(MyInt):
def __int__(self):
return u"%s" % self.value
class MyInt2:
def __init__(self, value):
self.value = value
def __int__(self):
print(u"MyInt.__int__()")
return self.value
class MyBadInt2(MyInt2):
def __int__(self):
return u"%s" % self.value
def test_convert_pyint(x):
u"""
>>> test_convert_pyint(None)
......
__doc__ = u'''
>>> no_cdef()
>>> with_cdef()
<<<<<<< local
>>> test_list(range(11), -2, None)
=======
>>> test_list(list(range(11)), -2, None)
>>>>>>> other
[0, 1, 2, 3, 4, 5, 6, 7, 8, None, 10]
<<<<<<< local
>>> test_list(range(11), "invalid index", None)
=======
>>> test_list(list(range(11)), "invalid index", None) #doctest: +ELLIPSIS
>>>>>>> other
Traceback (most recent call last):
...
TypeError: list indices must be integers, not str
TypeError: list indices must be integers...
'''
def no_cdef():
lst = range(11)
lst = list(range(11))
ob = 10L
lst[ob] = -10
dd = {}
dd[ob] = -10
def with_cdef():
cdef list lst = range(11)
cdef list lst = list(range(11))
ob = 10L
lst[ob] = -10
cdef dict dd = {}
......
......@@ -14,11 +14,11 @@ cdef char* s = 'abcdef'
def global_c_and_s():
pys = s
print c
print pys.decode('ASCII')
print (pys.decode(u'ASCII'))
def local_c_and_s():
cdef char c = 'b'
cdef char* s = 'bcdefg'
pys = s
print c
print pys.decode('ASCII')
print (pys.decode(u'ASCII'))
__doc__ = u"""
>>> test_object_conversion(2)
((2+0j), (2+0j))
>>> test_object_conversion(2j - 0.5)
((-0.5+2j), (-0.5+2j))
>>> test_arithmetic(2j, 4j)
(-2j, 6j, -2j, (-8+0j), (0.5+0j))
>>> test_arithmetic(6+12j, 3j)
((-6-12j), (6+15j), (6+9j), (-36+18j), (4-2j))
>>> test_arithmetic(5-10j, 3+4j)
((-5+10j), (8-6j), (2-14j), (55-10j), (-1-2j))
>>> test_div_by_zero(4j)
-0.25j
>>> test_div_by_zero(0)
Traceback (most recent call last):
...
ZeroDivisionError: float division
>>> test_coercion(1, 1.5, 2.5, 4+1j, 10j)
(1+0j)
(1.5+0j)
(2.5+0j)
(4+1j)
10j
(9+21j)
>>> test_compare(3, 3)
(True, False)
>>> test_compare(3j, 3j)
(True, False)
>>> test_compare(3j, 4j)
(False, True)
>>> test_compare(3, 4)
(False, True)
>>> test_compare_coerce(3, 4)
(False, True)
>>> test_compare_coerce(4+1j, 4)
(False, True)
>>> test_compare_coerce(4, 4)
(True, False)
>>> test_literal()
(5j, (1-2.5j))
>>> test_real_imag(1-3j)
(1.0, -3.0)
>>> test_real_imag(5)
(5.0, 0.0)
>>> test_real_imag(1.5j)
(0.0, 1.5)
>>> test_real_imag_assignment(1, 2)
(1+2j)
>>> test_real_imag_assignment(1.5, -3.5)
(1.5-3.5j)
"""
#cdef extern from "complex.h":
# pass
cimport cython
def test_object_conversion(o):
cdef float complex a = o
cdef double complex z = o
return (a, z)
def test_arithmetic(double complex z, double complex w):
return -z, z+w, z-w, z*w, z/w
@cython.cdivision(False)
def test_div_by_zero(double complex z):
return 1/z
def test_coercion(int a, float b, double c, float complex d, double complex e):
cdef double complex z
z = a; print z
z = b; print z
z = c; print z
z = d; print z
z = e; print z
return z + a + b + c + d + e
def test_compare(double complex a, double complex b):
return a == b, a != b
def test_compare_coerce(double complex a, int b):
return a == b, a != b
def test_literal():
return 5j, 1-2.5j
def test_real_imag(double complex z):
return z.real, z.imag
def test_real_imag_assignment(object a, double b):
cdef double complex z
z.real = a
z.imag = b
return z
typedef double DoubleTypedef;
......@@ -32,29 +32,29 @@ __doc__ = u"""
def double_target(a, b):
cdef double x
for x from a <= x < b:
print "at", x
print u"at", x
return x
def double_step(a, b, dx):
cdef double x
for x from a <= x < b by dx:
print "at", x
print u"at", x
return x
def double_step_typed(a, b, double dx):
cdef double x
for x from a <= x < b by dx:
print "at", x
print u"at", x
return x
def double_step_py_target(a, b, double dx):
cdef object x
for x from a <= x < b by dx:
print "at", x
print u"at", x
return x
def int_step_py_target(a, b, int dx):
cdef object x
for x from a <= x < b by dx:
print "at", x
print u"at", x
return x
......@@ -2,6 +2,17 @@
cimport numpy as np
def little_endian():
cdef int endian_detector = 1
return (<char*>&endian_detector)[0] != 0
if little_endian():
my_endian = '<'
other_endian = '>'
else:
my_endian = '>'
other_endian = '<'
try:
import numpy as np
__doc__ = u"""
......@@ -111,6 +122,7 @@ try:
>>> test_dtype('I', inc1_uint)
>>> test_dtype('l', inc1_long)
>>> test_dtype('L', inc1_ulong)
>>> test_dtype('f', inc1_float)
>>> test_dtype('d', inc1_double)
>>> test_dtype('g', inc1_longdouble)
......@@ -118,6 +130,9 @@ try:
>>> test_dtype('F', inc1_cfloat) # numpy format codes differ from buffer ones here
>>> test_dtype('D', inc1_cdouble)
>>> test_dtype('G', inc1_clongdouble)
>>> test_dtype('F', inc1_cfloat_struct)
>>> test_dtype('D', inc1_cdouble_struct)
>>> test_dtype('G', inc1_clongdouble_struct)
>>> test_dtype(np.int, inc1_int_t)
>>> test_dtype(np.long, inc1_long_t)
......@@ -129,34 +144,62 @@ try:
>>> test_dtype(np.int32, inc1_int32_t)
>>> test_dtype(np.float64, inc1_float64_t)
Endian tests:
>>> test_dtype('%si' % my_endian, inc1_int)
>>> test_dtype('%si' % other_endian, inc1_int)
Traceback (most recent call last):
...
ValueError: Non-native byte order not supported
>>> test_recordarray()
>>> test_nested_dtypes(np.zeros((3,), dtype=np.dtype([\
>>> print(test_nested_dtypes(np.zeros((3,), dtype=np.dtype([\
('a', np.dtype('i,i')),\
('b', np.dtype('i,i'))\
])))
]))))
array([((0, 0), (0, 0)), ((1, 2), (1, 4)), ((1, 2), (1, 4))],
dtype=[('a', [('f0', '<i4'), ('f1', '<i4')]), ('b', [('f0', '<i4'), ('f1', '<i4')])])
dtype=[('a', [('f0', '!i4'), ('f1', '!i4')]), ('b', [('f0', '!i4'), ('f1', '!i4')])])
>>> test_nested_dtypes(np.zeros((3,), dtype=np.dtype([\
>>> print(test_nested_dtypes(np.zeros((3,), dtype=np.dtype([\
('a', np.dtype('i,f')),\
('b', np.dtype('i,i'))\
])))
]))))
Traceback (most recent call last):
...
ValueError: Buffer dtype mismatch, expected 'int' but got 'float' in 'DoubleInt.y'
>>> print(test_packed_align(np.zeros((1,), dtype=np.dtype('b,i', align=False))))
array([(22, 23)],
dtype=[('f0', '|i1'), ('f1', '!i4')])
>>> print(test_unpacked_align(np.zeros((1,), dtype=np.dtype('b,i', align=True))))
array([(22, 23)],
dtype=[('f0', '|i1'), ('', '|V3'), ('f1', '!i4')])
>>> print(test_packed_align(np.zeros((1,), dtype=np.dtype('b,i', align=True))))
Traceback (most recent call last):
...
ValueError: Buffer dtype mismatch; next field is at offset 4 but 1 expected
>>> print(test_unpacked_align(np.zeros((1,), dtype=np.dtype('b,i', align=False))))
Traceback (most recent call last):
...
ValueError: Buffer dtype mismatch (expected int, got float)
ValueError: Buffer dtype mismatch; next field is at offset 1 but 4 expected
>>> test_good_cast()
True
>>> test_bad_cast()
Traceback (most recent call last):
...
ValueError: Attempted cast of buffer to datatype of different size.
ValueError: Item size of buffer (1 byte) does not match size of 'int' (4 bytes)
"""
except:
__doc__ = u""
def ndarray_str(arr):
u"""
Since Py2.3 doctest don't support <BLANKLINE>, manually replace blank lines
......@@ -218,15 +261,19 @@ def inc1_float(np.ndarray[float] arr): arr[1] += 1
def inc1_double(np.ndarray[double] arr): arr[1] += 1
def inc1_longdouble(np.ndarray[long double] arr): arr[1] += 1
def inc1_cfloat(np.ndarray[np.cfloat_t] arr):
def inc1_cfloat(np.ndarray[float complex] arr): arr[1] = arr[1] + 1 + 1j
def inc1_cdouble(np.ndarray[double complex] arr): arr[1] = (arr[1] + 1) + 1j
def inc1_clongdouble(np.ndarray[long double complex] arr): arr[1] = arr[1] + (1 + 1j)
def inc1_cfloat_struct(np.ndarray[np.cfloat_t] arr):
arr[1].real += 1
arr[1].imag += 1
def inc1_cdouble(np.ndarray[np.cdouble_t] arr):
def inc1_cdouble_struct(np.ndarray[np.cdouble_t] arr):
arr[1].real += 1
arr[1].imag += 1
def inc1_clongdouble(np.ndarray[np.clongdouble_t] arr):
def inc1_clongdouble_struct(np.ndarray[np.clongdouble_t] arr):
cdef long double x
x = arr[1].real + 1
arr[1].real = x
......@@ -297,7 +344,7 @@ def test_nested_dtypes(obj):
arr[1].b.x = arr[0].a.y + 1
arr[1].b.y = 4
arr[2] = arr[1]
return arr
return repr(arr).replace('<', '!').replace('>', '!')
def test_bad_nested_dtypes():
cdef object[BadNestedStruct] arr
......@@ -310,4 +357,22 @@ def test_good_cast():
def test_bad_cast():
# This should raise an exception
cdef np.ndarray[long, cast=True] arr = np.array([1], dtype=b'b')
cdef np.ndarray[int, cast=True] arr = np.array([1], dtype=b'b')
cdef packed struct PackedStruct:
char a
int b
cdef struct UnpackedStruct:
char a
int b
def test_packed_align(np.ndarray[PackedStruct] arr):
arr[0].a = 22
arr[0].b = 23
return repr(arr).replace('<', '!').replace('>', '!')
def test_unpacked_align(np.ndarray[UnpackedStruct] arr):
arr[0].a = 22
arr[0].b = 23
return repr(arr).replace('<', '!').replace('>', '!')
# Ensure casting still works to void*
"""
>>> o = f()
>>> print(o[0])
teststring
>>> print(o[1])
teststring
"""
cdef extern from *:
ctypedef void PyObject
def f():
cdef void* p1
cdef PyObject* p2
a = u"teststring"
p1 = <void*>a
p2 = <PyObject*>a
return (<object>p1, <object>p2)
......@@ -74,66 +74,66 @@ at 4
5
"""
cdef int get_bound(int m):
print "get_bound(%s)"%m
print u"get_bound(%s)"%m
return m
def for_from_range(a, b):
cdef int i = 100
print "range(%s)" % a
print u"range(%s)" % a
for i in range(a):
print "at", i
print "range(%s, %s)" % (a, b)
print u"at", i
print u"range(%s, %s)" % (a, b)
for i in range(a, b):
print "at", i
print "range(%s, %s, %s)" % (a, b, 2)
print u"at", i
print u"range(%s, %s, %s)" % (a, b, 2)
for i in range(a, b, 2):
print "at", i
print u"at", i
return i
def for_from_bound_reassignment(int bound, int fake_bound):
cdef int i = 100
for i from 0 <= i < bound:
print "at", i
print u"at", i
bound = fake_bound
return i
def for_from_step_reassignment(int bound, int step, int fake_step):
cdef int i = 100
for i from 0 <= i < bound by step:
print "at", i
print u"at", i
step = fake_step
return i
def for_from_target_reassignment(int bound, int factor):
cdef int i = 100
for i from 0 <= i < bound:
print "at", i
print u"at", i
i *= factor
return i
def for_from_py_target_reassignment(int bound, int factor):
cdef object i
for i from 0 <= i < bound:
print "at", i
print u"at", i
i *= factor
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
print u"at", g_var
g_var *= factor
return g_var
def for_in_target_reassignment(int bound, int factor):
cdef int i = 100
for i in range(bound):
print "at", i
print u"at", i
i *= factor
return i
def test_func(int n):
cdef int i = 100
for i from 0 <= i < get_bound(n):
print "at", i
print u"at", i
return i
__doc__ = u"""
>>> print( "%d" % Int() )
2
>>> print( "%d" % Long() )
3
>>> print( "%d" % IntLongA() )
2
>>> print( "%d" % IntLongB() )
2
>>> print( "%d" % IntLongC() )
3
>>> getint( Int() )
2
>>> getint( Long() )
3
>>> getint( IntLongA() )
2
>>> getint( IntLongB() )
2
>>> getint( IntLongC() )
3
>>> getlong( Int() )
2
>>> getlong( Long() )
3
>>> getlong( IntLongA() )
2
>>> getlong( IntLongB() )
2
>>> getlong( IntLongC() )
3
"""
def getint(int i):
return i
def getlong(long long i):
return <int>i
cdef class Int:
def __int__(self):
return 2
cdef class Long:
def __long__(self):
return 3
cdef class IntLongA:
def __int__(self):
return 2
def __long__(self):
return 3
cdef class IntLongB:
def __int__(self):
return 2
__long__ = __int__
cdef class IntLongC:
def __long__(self):
return 3
__int__ = __long__
......@@ -22,10 +22,10 @@ __doc__ = u"""
>>> slice_list_assign(l2, dict(zip(l,l)))
[1, 1, 2, 3, 4, 4]
>>> slice_charp('abcdefg')
'bc'
>>> slice_charp_repeat('abcdefg')
'cd'
>>> print("%s" % slice_charp('abcdefg'))
bc
>>> print("%s" % slice_charp_repeat('abcdefg'))
cd
"""
def slice_list(list l):
......@@ -51,12 +51,14 @@ def slice_list_assign(list l, value):
return l
def slice_charp(str py_string):
def slice_charp(py_string_arg):
cdef str py_string = py_string_arg.encode(u'ASCII')
cdef char* s = py_string
return s[1:3]
return s[1:3].decode(u'ASCII')
def slice_charp_repeat(str py_string):
def slice_charp_repeat(py_string_arg):
cdef str py_string = py_string_arg.encode(u'ASCII')
cdef char* s = py_string
cdef str slice_val = s[1:6]
s = slice_val
return s[1:3]
return s[1:3].decode(u'ASCII')
"""
>>> f()
42.0 42.0 42.0
>>> readonly()
Traceback (most recent call last):
...
AttributeError: attribute 'var_nf' of 'typedfieldbug_T303.MyClass' objects is not writable
"""
cdef extern from "external_defs.h":
ctypedef float DoubleTypedef
cdef class MyClass:
cdef readonly:
double var_d
DoubleTypedef var_nf
cdef public:
DoubleTypedef var_mutable
def __init__(self):
self.var_d = 42.0
self.var_nf = 42.0
self.var_mutable = 1
def f():
c = MyClass()
c.var_mutable = 42.0
print c.var_d, c.var_nf, c.var_mutable
def readonly():
c = MyClass()
c.var_nf = 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