Commit 0adcf7c2 authored by Vitja Makarov's avatar Vitja Makarov

Merge remote branch 'upstream/master'

parents 3cae35ea 0c87bea0
*.pyc
*.pyo
__pycache__
Cython/Compiler/*.c
Cython/Plex/*.c
Cython/Runtime/refnanny.c
BUILD/
build/
dist/
.gitrev
.coverage
*.orig
*.rej
*.dep
*.swp
*~
tags
TAGS
syntax: glob syntax: glob
*.pyc *.pyc
*.swp *.pyo
__pycache__
Cython/Compiler/*.c
Cython/Plex/*.c
Cython/Runtime/refnanny.c
Cython/Compiler/Lexicon.pickle
BUILD/ BUILD/
build/ build/
dist/ dist/
.gitrev
.coverage .coverage
*~
*.orig *.orig
*.rej *.rej
*.dep *.dep
*.swp
*~
tags tags
TAGS
import os, tempfile
from Cython.Shadow import inline from Cython.Shadow import inline
from Cython.Build.Inline import safe_type from Cython.Build.Inline import safe_type
from Cython.TestUtils import CythonTest from Cython.TestUtils import CythonTest
...@@ -13,23 +14,31 @@ test_kwds = dict(force=True, quiet=True) ...@@ -13,23 +14,31 @@ test_kwds = dict(force=True, quiet=True)
global_value = 100 global_value = 100
class TestInline(CythonTest): class TestInline(CythonTest):
def setUp(self):
CythonTest.setUp(self)
self.test_kwds = dict(test_kwds)
if os.path.isdir('BUILD'):
lib_dir = os.path.join('BUILD','inline')
else:
lib_dir = tempfile.mkdtemp(prefix='cython_inline_')
self.test_kwds['lib_dir'] = lib_dir
def test_simple(self): def test_simple(self):
self.assertEquals(inline("return 1+2", **test_kwds), 3) self.assertEquals(inline("return 1+2", **self.test_kwds), 3)
def test_types(self): def test_types(self):
self.assertEquals(inline(""" self.assertEquals(inline("""
cimport cython cimport cython
return cython.typeof(a), cython.typeof(b) return cython.typeof(a), cython.typeof(b)
""", a=1.0, b=[], **test_kwds), ('double', 'list object')) """, a=1.0, b=[], **self.test_kwds), ('double', 'list object'))
def test_locals(self): def test_locals(self):
a = 1 a = 1
b = 2 b = 2
self.assertEquals(inline("return a+b", **test_kwds), 3) self.assertEquals(inline("return a+b", **self.test_kwds), 3)
def test_globals(self): def test_globals(self):
self.assertEquals(inline("return global_value + 1", **test_kwds), global_value + 1) self.assertEquals(inline("return global_value + 1", **self.test_kwds), global_value + 1)
if has_numpy: if has_numpy:
...@@ -38,4 +47,4 @@ class TestInline(CythonTest): ...@@ -38,4 +47,4 @@ class TestInline(CythonTest):
a = numpy.ndarray((10, 20)) a = numpy.ndarray((10, 20))
a[0,0] = 10 a[0,0] = 10
self.assertEquals(safe_type(a), 'numpy.ndarray[numpy.float64_t, ndim=2]') self.assertEquals(safe_type(a), 'numpy.ndarray[numpy.float64_t, ndim=2]')
self.assertEquals(inline("return a[0,0]", a=a, **test_kwds), 10.0) self.assertEquals(inline("return a[0,0]", a=a, **self.test_kwds), 10.0)
...@@ -86,6 +86,7 @@ class AnnotationCCodeWriter(CCodeWriter): ...@@ -86,6 +86,7 @@ class AnnotationCCodeWriter(CCodeWriter):
html_filename = os.path.splitext(target_filename)[0] + ".html" html_filename = os.path.splitext(target_filename)[0] + ".html"
f = codecs.open(html_filename, "w", encoding="UTF-8") f = codecs.open(html_filename, "w", encoding="UTF-8")
f.write(u'<!-- Generated by Cython %s on %s -->\n' % (Version.version, time.asctime()))
f.write(u'<html>\n') f.write(u'<html>\n')
f.write(u""" f.write(u"""
<head> <head>
......
...@@ -527,8 +527,7 @@ def use_py2_buffer_functions(env): ...@@ -527,8 +527,7 @@ def use_py2_buffer_functions(env):
#if PY_MAJOR_VERSION < 3 #if PY_MAJOR_VERSION < 3
static int __Pyx_GetBuffer(PyObject *obj, Py_buffer *view, int flags) { static int __Pyx_GetBuffer(PyObject *obj, Py_buffer *view, int flags) {
#if PY_VERSION_HEX >= 0x02060000 #if PY_VERSION_HEX >= 0x02060000
if (Py_TYPE(obj)->tp_flags & Py_TPFLAGS_HAVE_NEWBUFFER) if (PyObject_CheckBuffer(obj)) return PyObject_GetBuffer(obj, view, flags);
return PyObject_GetBuffer(obj, view, flags);
#endif #endif
""") """)
if len(types) > 0: if len(types) > 0:
...@@ -548,11 +547,15 @@ def use_py2_buffer_functions(env): ...@@ -548,11 +547,15 @@ def use_py2_buffer_functions(env):
static void __Pyx_ReleaseBuffer(Py_buffer *view) { static void __Pyx_ReleaseBuffer(Py_buffer *view) {
PyObject* obj = view->obj; PyObject* obj = view->obj;
if (obj) { if (obj) {
#if PY_VERSION_HEX >= 0x02060000
if (PyObject_CheckBuffer(obj)) {PyBuffer_Release(view); return;}
#endif
""") """)
if len(types) > 0: if len(types) > 0:
clause = "if" clause = "if"
for t, get, release in types: for t, get, release in types:
if release: if release:
code += " "
code += "%s (PyObject_TypeCheck(obj, %s)) %s(obj, view);" % (clause, t, release) code += "%s (PyObject_TypeCheck(obj, %s)) %s(obj, view);" % (clause, t, release)
clause = "else if" clause = "else if"
code += dedent(""" code += dedent("""
...@@ -1114,6 +1117,11 @@ static const char* __Pyx_BufFmt_CheckString(__Pyx_BufFmt_Context* ctx, const cha ...@@ -1114,6 +1117,11 @@ static const char* __Pyx_BufFmt_CheckString(__Pyx_BufFmt_Context* ctx, const cha
ctx->new_count = 1; ctx->new_count = 1;
got_Z = 0; got_Z = 0;
break; break;
case ':':
++ts;
while(*ts != ':') ++ts;
++ts;
break;
default: default:
{ {
ctx->new_count = __Pyx_BufFmt_ParseNumber(&ts); ctx->new_count = __Pyx_BufFmt_ParseNumber(&ts);
......
...@@ -76,6 +76,25 @@ bad: ...@@ -76,6 +76,25 @@ bad:
} }
""") """)
hasattr_utility_code = UtilityCode(
proto = """
static CYTHON_INLINE int __Pyx_HasAttr(PyObject *, PyObject *); /*proto*/
""",
impl = """
static CYTHON_INLINE int __Pyx_HasAttr(PyObject *o, PyObject *n) {
PyObject *v = PyObject_GetAttr(o, n);
if (v) {
Py_DECREF(v);
return 1;
}
if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
PyErr_Clear();
return 0;
}
return -1;
}
""")
pyexec_utility_code = UtilityCode( pyexec_utility_code = UtilityCode(
proto = """ proto = """
#if PY_VERSION_HEX < 0x02040000 #if PY_VERSION_HEX < 0x02040000
...@@ -365,7 +384,8 @@ builtin_function_table = [ ...@@ -365,7 +384,8 @@ builtin_function_table = [
utility_code = getattr3_utility_code), utility_code = getattr3_utility_code),
BuiltinFunction('getattr3', "OOO", "O", "__Pyx_GetAttr3", "getattr", BuiltinFunction('getattr3', "OOO", "O", "__Pyx_GetAttr3", "getattr",
utility_code = getattr3_utility_code), # Pyrex compatibility utility_code = getattr3_utility_code), # Pyrex compatibility
BuiltinFunction('hasattr', "OO", "b", "PyObject_HasAttr"), BuiltinFunction('hasattr', "OO", "b", "__Pyx_HasAttr",
utility_code = hasattr_utility_code),
BuiltinFunction('hash', "O", "h", "PyObject_Hash"), BuiltinFunction('hash', "O", "h", "PyObject_Hash"),
#('hex', "", "", ""), #('hex', "", "", ""),
#('id', "", "", ""), #('id', "", "", ""),
......
...@@ -34,7 +34,7 @@ Options: ...@@ -34,7 +34,7 @@ Options:
-a, --annotate Produce a colorized HTML version of the source. -a, --annotate Produce a colorized HTML version of the source.
--line-directives Produce #line directives pointing to the .pyx source --line-directives Produce #line directives pointing to the .pyx source
--cplus Output a C++ rather than C file. --cplus Output a C++ rather than C file.
--embed Generate a main() function that embeds the Python interpreter. --embed[=<method_name>] Generate a main() function that embeds the Python interpreter.
-2 Compile based on Python-2 syntax and code semantics. -2 Compile based on Python-2 syntax and code semantics.
-3 Compile based on Python-3 syntax and code semantics. -3 Compile based on Python-3 syntax and code semantics.
--fast-fail Abort the compilation on the first error --fast-fail Abort the compilation on the first error
...@@ -84,8 +84,12 @@ def parse_command_line(args): ...@@ -84,8 +84,12 @@ def parse_command_line(args):
options.use_listing_file = 1 options.use_listing_file = 1
elif option in ("-+", "--cplus"): elif option in ("-+", "--cplus"):
options.cplus = 1 options.cplus = 1
elif option == "--embed": elif option.startswith("--embed"):
Options.embed = True ix = option.find('=')
if ix == -1:
Options.embed = "main"
else:
Options.embed = option[ix+1:]
elif option.startswith("-I"): elif option.startswith("-I"):
options.include_path.append(get_param(option)) options.include_path.append(get_param(option))
elif option == "--include-dir": elif option == "--include-dir":
......
...@@ -371,7 +371,7 @@ class ExprNode(Node): ...@@ -371,7 +371,7 @@ class ExprNode(Node):
def nonlocally_immutable(self): def nonlocally_immutable(self):
# Returns whether this variable is a safe reference, i.e. # Returns whether this variable is a safe reference, i.e.
# can't be modified as part of globals or closures. # can't be modified as part of globals or closures.
return self.is_temp return self.is_temp or self.type.is_array or self.type.is_cfunction
# --------------- Type Analysis ------------------ # --------------- Type Analysis ------------------
...@@ -1483,6 +1483,8 @@ class NameNode(AtomicExprNode): ...@@ -1483,6 +1483,8 @@ class NameNode(AtomicExprNode):
return 1 return 1
def nonlocally_immutable(self): def nonlocally_immutable(self):
if ExprNode.nonlocally_immutable(self):
return True
entry = self.entry entry = self.entry
return entry and (entry.is_local or entry.is_arg) and not entry.in_closure return entry and (entry.is_local or entry.is_arg) and not entry.in_closure
...@@ -1681,20 +1683,22 @@ class NameNode(AtomicExprNode): ...@@ -1681,20 +1683,22 @@ class NameNode(AtomicExprNode):
def generate_deletion_code(self, code): def generate_deletion_code(self, code):
if self.entry is None: if self.entry is None:
return # There was an error earlier return # There was an error earlier
if not self.entry.is_pyglobal: elif self.entry.is_pyglobal:
error(self.pos, "Deletion of local or C global name not supported") code.put_error_if_neg(self.pos,
return '__Pyx_DelAttrString(%s, "%s")' % (
if self.entry.is_pyclass_attr: Naming.module_cname,
self.entry.name))
elif self.entry.is_pyclass_attr:
namespace = self.entry.scope.namespace_cname namespace = self.entry.scope.namespace_cname
code.put_error_if_neg(self.pos, code.put_error_if_neg(self.pos,
'PyMapping_DelItemString(%s, "%s")' % ( 'PyMapping_DelItemString(%s, "%s")' % (
namespace, namespace,
self.entry.name)) self.entry.name))
elif self.entry.type.is_pyobject:
# Fake it until we can do it for real...
self.generate_assignment_code(NoneNode(self.pos), code)
else: else:
code.put_error_if_neg(self.pos, error(self.pos, "Deletion of C names not supported")
'__Pyx_DelAttrString(%s, "%s")' % (
Naming.module_cname,
self.entry.name))
def annotate(self, code): def annotate(self, code):
if hasattr(self, 'is_called') and self.is_called: if hasattr(self, 'is_called') and self.is_called:
...@@ -3043,10 +3047,11 @@ class SimpleCallNode(CallNode): ...@@ -3043,10 +3047,11 @@ class SimpleCallNode(CallNode):
if i == 0 and self.self is not None: if i == 0 and self.self is not None:
continue # self is ok continue # self is ok
arg = self.args[i] arg = self.args[i]
if arg.is_name and arg.entry and ( if arg.nonlocally_immutable():
(arg.entry.is_local and not arg.entry.in_closure) # locals, C functions, unassignable types are safe.
or arg.entry.type.is_cfunction): pass
# local variables and C functions are safe elif arg.type.is_cpp_class:
# Assignment has side effects, avoid.
pass pass
elif env.nogil and arg.type.is_pyobject: elif env.nogil and arg.type.is_pyobject:
# can't copy a Python reference into a temp in nogil # can't copy a Python reference into a temp in nogil
......
...@@ -6,6 +6,7 @@ For now this only covers parse tree to value conversion of ...@@ -6,6 +6,7 @@ For now this only covers parse tree to value conversion of
compile-time values. compile-time values.
""" """
import sys
from Nodes import * from Nodes import *
from ExprNodes import * from ExprNodes import *
from Errors import CompileError from Errors import CompileError
...@@ -44,6 +45,10 @@ def interpret_compiletime_options(optlist, optdict, type_env=None, type_args=()) ...@@ -44,6 +45,10 @@ def interpret_compiletime_options(optlist, optdict, type_env=None, type_args=())
else: else:
raise CompileError(node.pos, "Type not allowed here.") raise CompileError(node.pos, "Type not allowed here.")
else: else:
if (sys.version_info[0] >=3 and
isinstance(node, StringNode) and
node.unicode_value is not None):
return (node.unicode_value, node.pos)
return (node.compile_time_value(empty_scope), node.pos) return (node.compile_time_value(empty_scope), node.pos)
if optlist: if optlist:
...@@ -52,6 +57,7 @@ def interpret_compiletime_options(optlist, optdict, type_env=None, type_args=()) ...@@ -52,6 +57,7 @@ def interpret_compiletime_options(optlist, optdict, type_env=None, type_args=())
assert isinstance(optdict, DictNode) assert isinstance(optdict, DictNode)
new_optdict = {} new_optdict = {}
for item in optdict.key_value_pairs: for item in optdict.key_value_pairs:
new_optdict[item.key.value] = interpret(item.value, item.key.value) new_key, dummy = interpret(item.key, None)
new_optdict[new_key] = interpret(item.value, item.key.value)
optdict = new_optdict optdict = new_optdict
return (optlist, new_optdict) return (optlist, new_optdict)
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
# Cython Top Level # Cython Top Level
# #
import os, sys, re import os, sys, re, codecs
if sys.version_info[:2] < (2, 3): if sys.version_info[:2] < (2, 3):
sys.stderr.write("Sorry, Cython requires Python 2.3 or later\n") sys.stderr.write("Sorry, Cython requires Python 2.3 or later\n")
sys.exit(1) sys.exit(1)
...@@ -607,6 +607,14 @@ def run_pipeline(source, options, full_module_name = None): ...@@ -607,6 +607,14 @@ def run_pipeline(source, options, full_module_name = None):
# Set up result object # Set up result object
result = create_default_resultobj(source, options) result = create_default_resultobj(source, options)
if options.annotate is None:
# By default, decide based on whether an html file already exists.
html_filename = os.path.splitext(result.c_file)[0] + ".html"
if os.path.exists(html_filename):
line = codecs.open(html_filename, "r", encoding="UTF-8").readline()
if line.startswith(u'<!-- Generated by Cython'):
options.annotate = True
# Get pipeline # Get pipeline
if source_ext.lower() == '.py': if source_ext.lower() == '.py':
pipeline = context.create_py_pipeline(options, result) pipeline = context.create_py_pipeline(options, result)
...@@ -826,7 +834,7 @@ default_options = dict( ...@@ -826,7 +834,7 @@ default_options = dict(
errors_to_stderr = 1, errors_to_stderr = 1,
cplus = 0, cplus = 0,
output_file = None, output_file = None,
annotate = False, annotate = None,
generate_pxi = 0, generate_pxi = 0,
working_path = "", working_path = "",
recursive = 0, recursive = 0,
......
...@@ -272,7 +272,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -272,7 +272,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code = globalstate['before_global_var'] code = globalstate['before_global_var']
code.putln('#define __Pyx_MODULE_NAME "%s"' % self.full_module_name) code.putln('#define __Pyx_MODULE_NAME "%s"' % self.full_module_name)
code.putln("static int %s%s = 0;" % (Naming.module_is_main, self.full_module_name.replace('.', '__'))) code.putln("int %s%s = 0;" % (Naming.module_is_main, self.full_module_name.replace('.', '__')))
code.putln("") code.putln("")
code.putln("/* Implementation of %s */" % env.qualified_name) code.putln("/* Implementation of %s */" % env.qualified_name)
...@@ -1757,6 +1757,9 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -1757,6 +1757,9 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln("__pyx_refnanny = __Pyx_RefNanny->SetupContext(\"%s\", __LINE__, __FILE__);"% header3) code.putln("__pyx_refnanny = __Pyx_RefNanny->SetupContext(\"%s\", __LINE__, __FILE__);"% header3)
code.putln("#endif") code.putln("#endif")
env.use_utility_code(check_binary_version_utility_code)
code.putln("if ( __Pyx_check_binary_version() < 0) %s" % code.error_goto(self.pos))
code.putln("%s = PyTuple_New(0); %s" % (Naming.empty_tuple, code.error_goto_if_null(Naming.empty_tuple, self.pos))); code.putln("%s = PyTuple_New(0); %s" % (Naming.empty_tuple, code.error_goto_if_null(Naming.empty_tuple, self.pos)));
code.putln("%s = PyBytes_FromStringAndSize(\"\", 0); %s" % (Naming.empty_bytes, code.error_goto_if_null(Naming.empty_bytes, self.pos))); code.putln("%s = PyBytes_FromStringAndSize(\"\", 0); %s" % (Naming.empty_bytes, code.error_goto_if_null(Naming.empty_bytes, self.pos)));
...@@ -1897,7 +1900,16 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -1897,7 +1900,16 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
def generate_main_method(self, env, code): def generate_main_method(self, env, code):
module_is_main = "%s%s" % (Naming.module_is_main, self.full_module_name.replace('.', '__')) module_is_main = "%s%s" % (Naming.module_is_main, self.full_module_name.replace('.', '__'))
code.globalstate.use_utility_code(main_method.specialize(module_name=env.module_name, module_is_main=module_is_main)) if Options.embed == "main":
wmain = "wmain"
else:
wmain = Options.embed
code.globalstate.use_utility_code(
main_method.specialize(
module_name = env.module_name,
module_is_main = module_is_main,
main_method = Options.embed,
wmain_method = wmain))
def generate_pymoduledef_struct(self, env, code): def generate_pymoduledef_struct(self, env, code):
if env.doc: if env.doc:
...@@ -2648,9 +2660,9 @@ impl = """ ...@@ -2648,9 +2660,9 @@ impl = """
#endif #endif
#if PY_MAJOR_VERSION < 3 #if PY_MAJOR_VERSION < 3
int main(int argc, char** argv) { int %(main_method)s(int argc, char** argv) {
#elif defined(WIN32) || defined(MS_WINDOWS) #elif defined(WIN32) || defined(MS_WINDOWS)
int wmain(int argc, wchar_t **argv) { int %(wmain_method)s(int argc, wchar_t **argv) {
#else #else
static int __Pyx_main(int argc, wchar_t **argv) { static int __Pyx_main(int argc, wchar_t **argv) {
#endif #endif
...@@ -2667,9 +2679,13 @@ static int __Pyx_main(int argc, wchar_t **argv) { ...@@ -2667,9 +2679,13 @@ static int __Pyx_main(int argc, wchar_t **argv) {
m = fpgetmask(); m = fpgetmask();
fpsetmask(m & ~FP_X_OFL); fpsetmask(m & ~FP_X_OFL);
#endif #endif
if (argc) {
Py_SetProgramName(argv[0]); Py_SetProgramName(argv[0]);
}
Py_Initialize(); Py_Initialize();
if (argc) {
PySys_SetArgv(argc, argv); PySys_SetArgv(argc, argv);
}
%(module_is_main)s = 1; %(module_is_main)s = 1;
#if PY_MAJOR_VERSION < 3 #if PY_MAJOR_VERSION < 3
init%(module_name)s(); init%(module_name)s();
...@@ -2796,8 +2812,12 @@ oom: ...@@ -2796,8 +2812,12 @@ oom:
} }
int int
main(int argc, char **argv) %(main_method)s(int argc, char **argv)
{ {
if (!argc) {
return __Pyx_main(0, NULL);
}
else {
wchar_t **argv_copy = (wchar_t **)malloc(sizeof(wchar_t*)*argc); wchar_t **argv_copy = (wchar_t **)malloc(sizeof(wchar_t*)*argc);
/* We need a second copies, as Python might modify the first one. */ /* We need a second copies, as Python might modify the first one. */
wchar_t **argv_copy2 = (wchar_t **)malloc(sizeof(wchar_t*)*argc); wchar_t **argv_copy2 = (wchar_t **)malloc(sizeof(wchar_t*)*argc);
...@@ -2823,6 +2843,7 @@ main(int argc, char **argv) ...@@ -2823,6 +2843,7 @@ main(int argc, char **argv)
free(argv_copy); free(argv_copy);
free(argv_copy2); free(argv_copy2);
return res; return res;
}
} }
#endif #endif
""") """)
...@@ -2834,3 +2855,26 @@ packed_struct_utility_code = UtilityCode(proto=""" ...@@ -2834,3 +2855,26 @@ packed_struct_utility_code = UtilityCode(proto="""
#define __Pyx_PACKED #define __Pyx_PACKED
#endif #endif
""", impl="", proto_block='utility_code_proto_before_types') """, impl="", proto_block='utility_code_proto_before_types')
check_binary_version_utility_code = UtilityCode(proto="""
static int __Pyx_check_binary_version(void);
""", impl="""
static int __Pyx_check_binary_version(void) {
char ctversion[4], rtversion[4];
PyOS_snprintf(ctversion, 4, "%d.%d", PY_MAJOR_VERSION, PY_MINOR_VERSION);
PyOS_snprintf(rtversion, 4, "%s", Py_GetVersion());
if (ctversion[0] != rtversion[0] || ctversion[2] != rtversion[2]) {
char message[200];
PyOS_snprintf(message, sizeof(message),
"compiletime version %s of module '%.100s' "
"does not match runtime version %s",
ctversion, __Pyx_MODULE_NAME, rtversion);
#if PY_VERSION_HEX < 0x02050000
return PyErr_Warn(NULL, message);
#else
return PyErr_WarnEx(NULL, message, 1);
#endif
}
return 0;
}
""")
...@@ -1057,6 +1057,8 @@ class CppClassNode(CStructOrUnionDefNode): ...@@ -1057,6 +1057,8 @@ class CppClassNode(CStructOrUnionDefNode):
self.entry = env.declare_cpp_class( self.entry = env.declare_cpp_class(
self.name, scope, self.pos, self.name, scope, self.pos,
self.cname, base_class_types, visibility = self.visibility, templates = template_types) self.cname, base_class_types, visibility = self.visibility, templates = template_types)
if self.entry is None:
return
self.entry.is_cpp_class = 1 self.entry.is_cpp_class = 1
if self.attributes is not None: if self.attributes is not None:
if self.in_pxd and not env.in_cinclude: if self.in_pxd and not env.in_cinclude:
......
...@@ -44,9 +44,10 @@ lookup_module_cpdef = 0 ...@@ -44,9 +44,10 @@ lookup_module_cpdef = 0
init_local_none = 1 init_local_none = 1
# Whether or not to embed the Python interpreter, for use in making a # Whether or not to embed the Python interpreter, for use in making a
# standalone executable. This will provide a main() method which simply # standalone executable or calling from external libraries.
# This will provide a method which initalizes the interpreter and
# executes the body of this module. # executes the body of this module.
embed = False embed = None
# Disables function redefinition, allowing all functions to be declared at # Disables function redefinition, allowing all functions to be declared at
# module creation time. For legacy code only. # module creation time. For legacy code only.
......
...@@ -449,7 +449,8 @@ class Scope(object): ...@@ -449,7 +449,8 @@ class Scope(object):
visibility = visibility, defining = scope is not None) visibility = visibility, defining = scope is not None)
else: else:
if not (entry.is_type and entry.type.is_cpp_class): if not (entry.is_type and entry.type.is_cpp_class):
warning(pos, "'%s' redeclared " % name, 0) error(pos, "'%s' redeclared " % name)
return None
elif scope and entry.type.scope: elif scope and entry.type.scope:
warning(pos, "'%s' already defined (ignoring second definition)" % name, 0) warning(pos, "'%s' already defined (ignoring second definition)" % name, 0)
else: else:
......
...@@ -121,6 +121,12 @@ class MarkAssignments(CythonTransform): ...@@ -121,6 +121,12 @@ class MarkAssignments(CythonTransform):
self.visitchildren(node) self.visitchildren(node)
return node return node
def visit_DelStatNode(self, node):
for arg in node.args:
self.mark_assignment(arg, arg)
self.visitchildren(node)
return node
class MarkOverflowingArithmetic(CythonTransform): class MarkOverflowingArithmetic(CythonTransform):
# It may be possible to integrate this with the above for # It may be possible to integrate this with the above for
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
cdef extern from *: cdef extern from *:
ctypedef char const_char "const char" ctypedef char const_char "const char"
cdef extern from "locale.h": cdef extern from "locale.h" nogil:
struct lconv: struct lconv:
char *decimal_point char *decimal_point
......
cdef extern from "math.h": cdef extern from "math.h" nogil:
enum: M_E enum: M_E
enum: M_LOG2E enum: M_LOG2E
...@@ -29,9 +29,57 @@ cdef extern from "math.h": ...@@ -29,9 +29,57 @@ cdef extern from "math.h":
double asinh(double x) double asinh(double x)
double atanh(double x) double atanh(double x)
double hypot(double x, double y)
double exp(double x) double exp(double x)
double exp2(double x)
double expm1(double x)
double log(double x) double log(double x)
double logb(double x)
double log2(double x)
double log10(double x) double log10(double x)
double log1p(double x)
int ilogb(double x)
double lgamma(double x)
double tgamma(double x)
double frexp(double x, double* exponent)
double ldexp(double x, double exponent)
double modf(double x, double* iptr)
double fmod(double x, double y)
double remainder(double x, double y)
double remquo(double x, double y, int *quot)
double pow(double x, double y) double pow(double x, double y)
double sqrt(double x) double sqrt(double x)
double cbrt(double x)
double fabs(double x)
double ceil(double x)
double floor(double x)
double trunc(double x)
double rint(double x)
double round(double x)
double nearbyint(double x)
double nextafter(double, double)
double nexttoward(double, long double)
long long llrint(double)
long lrint(double)
long long llround(double)
long lround(double)
double copysign(double, double)
double erf(double)
double erfc(double)
double fdim(double x, double y)
double fma(double x, double y)
double fmax(double x, double y)
double fmin(double x, double y)
double scalbln(double x, long n)
double scalbn(double x, int n)
double nan(char*) # const char*
...@@ -737,11 +737,14 @@ ctypedef double complex complex128_t ...@@ -737,11 +737,14 @@ ctypedef double complex complex128_t
# numpy.int corresponds to 'l' and numpy.long to 'q' # numpy.int corresponds to 'l' and numpy.long to 'q'
ctypedef npy_long int_t ctypedef npy_long int_t
ctypedef npy_longlong long_t ctypedef npy_longlong long_t
ctypedef npy_intp intp_t ctypedef npy_longlong longlong_t
ctypedef npy_uintp uintp_t
ctypedef npy_ulong uint_t ctypedef npy_ulong uint_t
ctypedef npy_ulonglong ulong_t ctypedef npy_ulonglong ulong_t
ctypedef npy_ulonglong ulonglong_t
ctypedef npy_intp intp_t
ctypedef npy_uintp uintp_t
ctypedef npy_double float_t ctypedef npy_double float_t
ctypedef npy_double double_t ctypedef npy_double double_t
......
...@@ -5,7 +5,7 @@ PYVERSION=$(shell $(PYTHON) -c "import sys; print(sys.version[:3])") ...@@ -5,7 +5,7 @@ PYVERSION=$(shell $(PYTHON) -c "import sys; print(sys.version[:3])")
INCDIR=$(shell $(PYTHON) -c "from distutils import sysconfig; print(sysconfig.get_python_inc())") INCDIR=$(shell $(PYTHON) -c "from distutils import sysconfig; print(sysconfig.get_python_inc())")
LIBDIR1=$(shell $(PYTHON) -c "from distutils import sysconfig; print(sysconfig.get_config_var('LIBDIR'))") LIBDIR1=$(shell $(PYTHON) -c "from distutils import sysconfig; print(sysconfig.get_config_var('LIBDIR'))")
LIBDIR2=$(shell $(PYTHON) -c "from distutils import sysconfig; print(sysconfig.get_config_var('LIBPL'))") LIBDIR2=$(shell $(PYTHON) -c "from distutils import sysconfig; print(sysconfig.get_config_var('LIBPL'))")
STATIC_PYLIB=$(shell $(PYTHON) -c "from distutils import sysconfig; print(sysconfig.get_config_var('LIBRARY'))") PYLIB=$(shell $(PYTHON) -c "from distutils import sysconfig; print(sysconfig.get_config_var('LIBRARY')[3:-2])")
CC=$(shell $(PYTHON) -c "import distutils.sysconfig; print(distutils.sysconfig.get_config_var('CC'))") CC=$(shell $(PYTHON) -c "import distutils.sysconfig; print(distutils.sysconfig.get_config_var('CC'))")
LINKCC=$(shell $(PYTHON) -c "import distutils.sysconfig; print(distutils.sysconfig.get_config_var('LINKCC'))") LINKCC=$(shell $(PYTHON) -c "import distutils.sysconfig; print(distutils.sysconfig.get_config_var('LINKCC'))")
...@@ -14,13 +14,14 @@ LIBS=$(shell $(PYTHON) -c "import distutils.sysconfig; print(distutils.sysconfig ...@@ -14,13 +14,14 @@ LIBS=$(shell $(PYTHON) -c "import distutils.sysconfig; print(distutils.sysconfig
SYSLIBS= $(shell $(PYTHON) -c "import distutils.sysconfig; print(distutils.sysconfig.get_config_var('SYSLIBS'))") SYSLIBS= $(shell $(PYTHON) -c "import distutils.sysconfig; print(distutils.sysconfig.get_config_var('SYSLIBS'))")
embedded: embedded.o embedded: embedded.o
$(LINKCC) -o $@ $^ $(LIBDIR1)/$(STATIC_PYLIB) $(LINKFORSHARED) -L$(LIBDIR1) -L$(LIBDIR2) $(LIBS) $(SYSLIBS) $(LINKCC) -o $@ $^ -L$(LIBDIR1) -L$(LIBDIR2) -l$(PYLIB) $(LIBS) $(SYSLIBS) $(LINKFORSHARED)
embedded.o: embedded.c embedded.o: embedded.c
$(CC) -c $^ -I$(INCDIR) $(CC) -c $^ -I$(INCDIR)
CYTHON=../../cython.py
embedded.c: embedded.pyx embedded.c: embedded.pyx
@$(PYTHON) ../../cython.py --embed embedded.pyx @$(PYTHON) $(CYTHON) --embed embedded.pyx
all: embedded all: embedded
......
import sys import sys
if open(sys.argv[1]).read() != open(sys.argv[2]).read(): f1 = open(sys.argv[1])
print "Files differ" f2 = open(sys.argv[2])
try:
if f1.read() != f2.read():
print ("Files differ")
sys.exit(1) sys.exit(1)
else: else:
print "Files identical" print ("Files identical")
finally:
f1.close()
f2.close()
...@@ -9,9 +9,12 @@ local: ...@@ -9,9 +9,12 @@ local:
.git: REV := $(shell cat .gitrev) .git: REV := $(shell cat .gitrev)
.git: TMPDIR := $(shell mktemp -d tmprepo.XXXXXX) .git: TMPDIR := $(shell mktemp -d tmprepo.XXXXXX)
.git: .git:
rm -rf $(TMPDIR)
git clone $(REPO) $(TMPDIR) git clone $(REPO) $(TMPDIR)
cd $(TMPDIR); git checkout -b working $(REV) cd $(TMPDIR); git checkout -b working $(REV)
mv $(TMPDIR)/{.git,.hgtags,.hgignore} . mv $(TMPDIR)/.hgtags .
mv $(TMPDIR)/.hgignore .
mv $(TMPDIR)/.git .
mv $(TMPDIR)/Doc/s5 Doc/s5 mv $(TMPDIR)/Doc/s5 Doc/s5
rm -rf $(TMPDIR) rm -rf $(TMPDIR)
......
...@@ -26,16 +26,16 @@ See LICENSE.txt. ...@@ -26,16 +26,16 @@ See LICENSE.txt.
-------------------------- --------------------------
Note that Cython used to ship the Mercurial (hg) repository in its source Note that Cython used to ship the full version control repository in its source
distribution, but no longer does so due to space constraints. To get the distribution, but no longer does so due to space constraints. To get the
full source history, make sure you have hg installed, then step into the full source history, make sure you have git installed, then step into the
base directory of the Cython source distribution and type base directory of the Cython source distribution and type
make repo make repo
Alternatively, check out the latest developer repository from Alternatively, check out the latest developer repository from
http://hg.cython.org/cython-devel https://github.com/cython/cython
......
...@@ -28,6 +28,7 @@ except ImportError: # No threads, no problems ...@@ -28,6 +28,7 @@ except ImportError: # No threads, no problems
threading = None threading = None
WITH_CYTHON = True WITH_CYTHON = True
CY3_DIR = None
from distutils.dist import Distribution from distutils.dist import Distribution
from distutils.core import Extension from distutils.core import Extension
...@@ -176,8 +177,8 @@ class TestBuilder(object): ...@@ -176,8 +177,8 @@ class TestBuilder(object):
continue continue
suite.addTest( suite.addTest(
self.handle_directory(path, filename)) self.handle_directory(path, filename))
if sys.platform not in ['win32'] and sys.version_info[0] < 3: if sys.platform not in ['win32']:
# Non-Windows makefile, can't run Cython under Py3. # Non-Windows makefile.
if [1 for selector in self.selectors if selector("embedded")] \ if [1 for selector in self.selectors if selector("embedded")] \
and not [1 for selector in self.exclude_selectors if selector("embedded")]: and not [1 for selector in self.exclude_selectors if selector("embedded")]:
suite.addTest(unittest.makeSuite(EmbedTest)) suite.addTest(unittest.makeSuite(EmbedTest))
...@@ -193,7 +194,7 @@ class TestBuilder(object): ...@@ -193,7 +194,7 @@ class TestBuilder(object):
filenames = os.listdir(path) filenames = os.listdir(path)
filenames.sort() filenames.sort()
for filename in filenames: for filename in filenames:
if context == "build" and filename.endswith(".srctree"): if filename.endswith(".srctree"):
if not [ 1 for match in self.selectors if match(filename) ]: if not [ 1 for match in self.selectors if match(filename) ]:
continue continue
if self.exclude_selectors: if self.exclude_selectors:
...@@ -892,8 +893,12 @@ class EmbedTest(unittest.TestCase): ...@@ -892,8 +893,12 @@ class EmbedTest(unittest.TestCase):
if not os.path.isdir(libdir) or libname not in os.listdir(libdir): if not os.path.isdir(libdir) or libname not in os.listdir(libdir):
# report the error for the original directory # report the error for the original directory
libdir = sysconfig.get_config_var('LIBDIR') libdir = sysconfig.get_config_var('LIBDIR')
cython = 'cython.py'
if sys.version_info[0] >=3:
cython = os.path.join(CY3_DIR, cython)
cython = os.path.abspath(os.path.join('..', '..', cython))
self.assert_(os.system( self.assert_(os.system(
"make PYTHON='%s' LIBDIR1='%s' test > make.output" % (sys.executable, libdir)) == 0) "make PYTHON='%s' CYTHON='%s' LIBDIR1='%s' test > make.output" % (sys.executable, cython, libdir)) == 0)
try: try:
os.remove('make.output') os.remove('make.output')
except OSError: except OSError:
...@@ -967,6 +972,7 @@ def refactor_for_py3(distdir, cy3_dir): ...@@ -967,6 +972,7 @@ def refactor_for_py3(distdir, cy3_dir):
recursive-include Cython *.py *.pyx *.pxd recursive-include Cython *.py *.pyx *.pxd
recursive-include Cython/Debugger/Tests * recursive-include Cython/Debugger/Tests *
include runtests.py include runtests.py
include cython.py
''') ''')
sys.path.insert(0, cy3_dir) sys.path.insert(0, cy3_dir)
...@@ -1105,7 +1111,8 @@ def main(): ...@@ -1105,7 +1111,8 @@ def main():
for name in cy_modules: for name in cy_modules:
del sys.modules[name] del sys.modules[name]
# hasn't been refactored yet - do it now # hasn't been refactored yet - do it now
cy3_dir = os.path.join(WORKDIR, 'Cy3') global CY3_DIR
CY3_DIR = cy3_dir = os.path.join(WORKDIR, 'Cy3')
if sys.version_info >= (3,1): if sys.version_info >= (3,1):
refactor_for_py3(DISTDIR, cy3_dir) refactor_for_py3(DISTDIR, cy3_dir)
elif os.path.isdir(cy3_dir): elif os.path.isdir(cy3_dir):
......
# Errors reported during code generation.
cdef int i
def f(a):
del a # error: deletion of local name not supported
del i # error: deletion of local name not supported
_ERRORS = u"""
6:52: Deletion of local or C global name not supported
7:52: Deletion of local or C global name not supported
"""
...@@ -93,10 +93,10 @@ def test_char(char x): ...@@ -93,10 +93,10 @@ def test_char(char x):
Traceback (most recent call last): Traceback (most recent call last):
... ...
OverflowError: ... OverflowError: ...
>>> if CHAR_MIN < 0:
... assert test_char(-1) == -1
>>> test_char(CHAR_MIN) == CHAR_MIN >>> test_char(CHAR_MIN) == CHAR_MIN
True True
>>> test_char(-1)
-1
>>> test_char(0) >>> test_char(0)
0 0
>>> test_char(1) >>> test_char(1)
......
PYTHON setup.py build_ext --inplace
PYTHON -c "import a"
######## setup.py ########
from Cython.Build import cythonize
from distutils.core import setup
setup(
ext_modules = cythonize("*.pyx"),
)
######## other.pxd ########
cdef class A:
pass
cdef int foo(int)
######## other.pyx ########
cdef class A:
pass
cdef int foo(int a):
return a**2
######## a.pyx ########
from other cimport A, foo
print A, foo(10)
cimport other
print other.A, other.foo(10)
...@@ -80,3 +80,10 @@ def del_temp_slice(a): ...@@ -80,3 +80,10 @@ def del_temp_slice(a):
while a.attr: while a.attr:
del a.attr[:] del a.attr[:]
return a.attr return a.attr
def del_local(a):
"""
>>> del_local(object())
"""
del a
assert a is None # Until we have unbound locals...
...@@ -4,7 +4,10 @@ def test_get_char_neg(): ...@@ -4,7 +4,10 @@ def test_get_char_neg():
0 0
""" """
cdef char key = -1 cdef char key = -1
if <char>-1 < 0:
d = {-1:0} d = {-1:0}
else:
d = {255:0}
return d[key] return d[key]
def test_get_char_zero(): def test_get_char_zero():
""" """
......
class Foo:
@property
def foo(self):
return None
@property
def bar(self):
raise AttributeError
@property
def baz(self):
return int(1)/int(0)
def wrap_hasattr(obj, name):
"""
>>> wrap_hasattr(None, "abc")
False
>>> wrap_hasattr(list, "append")
True
>>> wrap_hasattr(Foo(), "foo")
True
>>> wrap_hasattr(Foo(), "spam")
False
>>> wrap_hasattr(Foo(), "bar")
False
>>> wrap_hasattr(Foo(), "baz") #doctest: +ELLIPSIS
Traceback (most recent call last):
...
ZeroDivisionError: ...
"""
return hasattr(obj, name)
...@@ -72,23 +72,23 @@ try: ...@@ -72,23 +72,23 @@ try:
Write to slices Write to slices
>>> b = a.copy() >>> b = a.copy()
>>> put_range_long_1d(b[:, 3]) >>> put_range_long_1d(b[:, 3])
>>> print b >>> print (b)
[[0 1 2 0 4] [[0 1 2 0 4]
[5 6 7 1 9]] [5 6 7 1 9]]
>>> put_range_long_1d(b[::-1, 3]) >>> put_range_long_1d(b[::-1, 3])
>>> print b >>> print (b)
[[0 1 2 1 4] [[0 1 2 1 4]
[5 6 7 0 9]] [5 6 7 0 9]]
>>> a = np.zeros(9, dtype='l') >>> a = np.zeros(9, dtype='l')
>>> put_range_long_1d(a[1::3]) >>> put_range_long_1d(a[1::3])
>>> print a >>> print (a)
[0 0 0 0 1 0 0 2 0] [0 0 0 0 1 0 0 2 0]
Write to picked subarrays. This should NOT change the original Write to picked subarrays. This should NOT change the original
array as picking creates a new mutable copy. array as picking creates a new mutable copy.
>>> a = np.zeros(10, dtype='l').reshape(2, 5) >>> a = np.zeros(10, dtype='l').reshape(2, 5)
>>> put_range_long_1d(a[[0, 0, 1, 1, 0], [0, 1, 2, 4, 3]]) >>> put_range_long_1d(a[[0, 0, 1, 1, 0], [0, 1, 2, 4, 3]])
>>> print a >>> print (a)
[[0 0 0 0 0] [[0 0 0 0 0]
[0 0 0 0 0]] [0 0 0 0 0]]
...@@ -103,18 +103,18 @@ try: ...@@ -103,18 +103,18 @@ try:
0 1 2 3 0 1 2 3
4 5 6 7 4 5 6 7
8 9 10 11 8 9 10 11
>>> test_c_contig(f_arr) >>> test_c_contig(f_arr) #doctest: +ELLIPSIS
Traceback (most recent call last): Traceback (most recent call last):
... ...
ValueError: ndarray is not C contiguous ValueError: ndarray is not C...contiguous
>>> test_f_contig(c_arr) >>> test_f_contig(c_arr) #doctest: +ELLIPSIS
Traceback (most recent call last): Traceback (most recent call last):
... ...
ValueError: ndarray is not Fortran contiguous ValueError: ndarray is not Fortran contiguous
>>> test_c_contig(c_arr[::2,::2]) >>> test_c_contig(c_arr[::2,::2]) #doctest: +ELLIPSIS
Traceback (most recent call last): Traceback (most recent call last):
... ...
ValueError: ndarray is not C contiguous ValueError: ndarray is not C...contiguous
>>> test_dtype('b', inc1_byte) >>> test_dtype('b', inc1_byte)
>>> test_dtype('B', inc1_ubyte) >>> test_dtype('B', inc1_ubyte)
...@@ -137,7 +137,7 @@ try: ...@@ -137,7 +137,7 @@ try:
>>> test_dtype('G', inc1_clongdouble_struct) >>> test_dtype('G', inc1_clongdouble_struct)
>>> test_dtype(np.int, inc1_int_t) >>> test_dtype(np.int, inc1_int_t)
>>> test_dtype(np.long, inc1_long_t) >>> test_dtype(np.longlong, inc1_longlong_t)
>>> test_dtype(np.float, inc1_float_t) >>> test_dtype(np.float, inc1_float_t)
>>> test_dtype(np.double, inc1_double_t) >>> test_dtype(np.double, inc1_double_t)
>>> test_dtype(np.intp, inc1_intp_t) >>> test_dtype(np.intp, inc1_intp_t)
...@@ -150,10 +150,10 @@ try: ...@@ -150,10 +150,10 @@ try:
Endian tests: Endian tests:
>>> test_dtype('%si' % my_endian, inc1_int) >>> test_dtype('%si' % my_endian, inc1_int)
>>> test_dtype('%si' % other_endian, inc1_int) >>> test_dtype('%si' % other_endian, inc1_int) #doctest: +ELLIPSIS
Traceback (most recent call last): Traceback (most recent call last):
... ...
ValueError: Non-native byte order not supported ValueError: ...
...@@ -181,15 +181,15 @@ try: ...@@ -181,15 +181,15 @@ try:
array([(22, 23)], array([(22, 23)],
dtype=[('f0', '|i1'), ('', '|V3'), ('f1', '!i4')]) dtype=[('f0', '|i1'), ('', '|V3'), ('f1', '!i4')])
>>> print(test_packed_align(np.zeros((1,), dtype=np.dtype('b,i', align=True)))) >>> print(test_packed_align(np.zeros((1,), dtype=np.dtype('b,i', align=True)))) #doctest: +ELLIPSIS
Traceback (most recent call last): Traceback (most recent call last):
... ...
ValueError: Buffer dtype mismatch; next field is at offset 4 but 1 expected ValueError: ...
>>> print(test_unpacked_align(np.zeros((1,), dtype=np.dtype('b,i', align=False)))) >>> print(test_unpacked_align(np.zeros((1,), dtype=np.dtype('b,i', align=False)))) #doctest: +ELLIPSIS
Traceback (most recent call last): Traceback (most recent call last):
... ...
ValueError: Buffer dtype mismatch; next field is at offset 1 but 4 expected ValueError: ...
>>> test_good_cast() >>> test_good_cast()
...@@ -235,17 +235,17 @@ def ndarray_str(arr): ...@@ -235,17 +235,17 @@ def ndarray_str(arr):
return unicode(arr).replace(u'\n\n', u'\n<_BLANKLINE_>\n') return unicode(arr).replace(u'\n\n', u'\n<_BLANKLINE_>\n')
def basic(): def basic():
cdef object[int, ndim=2] buf = np.arange(10, dtype=b'i').reshape((2, 5)) cdef object[int, ndim=2] buf = np.arange(10, dtype='i').reshape((2, 5))
print buf print buf
print buf[0, 2], buf[0, 0], buf[1, 4], buf[1, 0] print buf[0, 2], buf[0, 0], buf[1, 4], buf[1, 0]
def three_dim(): def three_dim():
cdef object[double, ndim=3] buf = np.arange(24, dtype=b'd').reshape((3,2,4)) cdef object[double, ndim=3] buf = np.arange(24, dtype='d').reshape((3,2,4))
print ndarray_str(buf) print ndarray_str(buf)
print buf[0, 1, 2], buf[0, 0, 0], buf[1, 1, 1], buf[1, 0, 0] print buf[0, 1, 2], buf[0, 0, 0], buf[1, 1, 1], buf[1, 0, 0]
def obj_array(): def obj_array():
cdef object[object, ndim=1] buf = np.array([b"a", 1, {}]) cdef object[object, ndim=1] buf = np.array(["a", 1, {}])
print buf print buf
print buf[0], buf[1], buf[2] print buf[0], buf[1], buf[2]
...@@ -262,12 +262,12 @@ def put_range_long_1d(np.ndarray[long] arr): ...@@ -262,12 +262,12 @@ def put_range_long_1d(np.ndarray[long] arr):
arr[i] = value arr[i] = value
value += 1 value += 1
def test_c_contig(np.ndarray[int, ndim=2, mode=b'c'] arr): def test_c_contig(np.ndarray[int, ndim=2, mode='c'] arr):
cdef int i, j cdef int i, j
for i in range(arr.shape[0]): for i in range(arr.shape[0]):
print u" ".join([unicode(arr[i, j]) for j in range(arr.shape[1])]) print u" ".join([unicode(arr[i, j]) for j in range(arr.shape[1])])
def test_f_contig(np.ndarray[int, ndim=2, mode=b'fortran'] arr): def test_f_contig(np.ndarray[int, ndim=2, mode='fortran'] arr):
cdef int i, j cdef int i, j
for i in range(arr.shape[0]): for i in range(arr.shape[0]):
print u" ".join([unicode(arr[i, j]) for j in range(arr.shape[1])]) print u" ".join([unicode(arr[i, j]) for j in range(arr.shape[1])])
...@@ -314,6 +314,7 @@ def inc1_object(np.ndarray[object] arr): ...@@ -314,6 +314,7 @@ def inc1_object(np.ndarray[object] arr):
def inc1_int_t(np.ndarray[np.int_t] arr): arr[1] += 1 def inc1_int_t(np.ndarray[np.int_t] arr): arr[1] += 1
def inc1_long_t(np.ndarray[np.long_t] arr): arr[1] += 1 def inc1_long_t(np.ndarray[np.long_t] arr): arr[1] += 1
def inc1_longlong_t(np.ndarray[np.longlong_t] arr): arr[1] += 1
def inc1_float_t(np.ndarray[np.float_t] arr): arr[1] += 1 def inc1_float_t(np.ndarray[np.float_t] arr): arr[1] += 1
def inc1_double_t(np.ndarray[np.double_t] arr): arr[1] += 1 def inc1_double_t(np.ndarray[np.double_t] arr): arr[1] += 1
def inc1_longdouble_t(np.ndarray[np.longdouble_t] arr): arr[1] += 1 def inc1_longdouble_t(np.ndarray[np.longdouble_t] arr): arr[1] += 1
...@@ -330,7 +331,7 @@ def test_dtype(dtype, inc1): ...@@ -330,7 +331,7 @@ def test_dtype(dtype, inc1):
"G", np.clongdouble): "G", np.clongdouble):
if sizeof(double) == sizeof(long double): # MSVC if sizeof(double) == sizeof(long double): # MSVC
return return
if dtype in (b'F', b'D', b'G'): if dtype in ('F', 'D', 'G'):
a = np.array([0, 10+10j], dtype=dtype) a = np.array([0, 10+10j], dtype=dtype)
inc1(a) inc1(a)
if a[1] != (11 + 11j): print u"failed!", a[1] if a[1] != (11 + 11j): print u"failed!", a[1]
...@@ -344,7 +345,7 @@ cdef struct DoubleInt: ...@@ -344,7 +345,7 @@ cdef struct DoubleInt:
def test_recordarray(): def test_recordarray():
cdef object[DoubleInt] arr cdef object[DoubleInt] arr
arr = np.array([(5,5), (4, 6)], dtype=np.dtype(b'i,i')) arr = np.array([(5,5), (4, 6)], dtype=np.dtype('i,i'))
cdef DoubleInt rec cdef DoubleInt rec
rec = arr[0] rec = arr[0]
if rec.x != 5: print u"failed" if rec.x != 5: print u"failed"
...@@ -384,13 +385,13 @@ def test_bad_nested_dtypes(): ...@@ -384,13 +385,13 @@ def test_bad_nested_dtypes():
def test_good_cast(): def test_good_cast():
# Check that a signed int can round-trip through casted unsigned int access # Check that a signed int can round-trip through casted unsigned int access
cdef np.ndarray[unsigned int, cast=True] arr = np.array([-100], dtype=b'i') cdef np.ndarray[unsigned int, cast=True] arr = np.array([-100], dtype='i')
cdef unsigned int data = arr[0] cdef unsigned int data = arr[0]
return -100 == <int>data return -100 == <int>data
def test_bad_cast(): def test_bad_cast():
# This should raise an exception # This should raise an exception
cdef np.ndarray[int, cast=True] arr = np.array([1], dtype=b'b') cdef np.ndarray[int, cast=True] arr = np.array([1], dtype='b')
cdef packed struct PackedStruct: cdef packed struct PackedStruct:
char a char a
......
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