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
*.pyc
*.swp
*.pyo
__pycache__
Cython/Compiler/*.c
Cython/Plex/*.c
Cython/Runtime/refnanny.c
Cython/Compiler/Lexicon.pickle
BUILD/
build/
dist/
.gitrev
.coverage
*~
*.orig
*.rej
*.dep
*.swp
*~
tags
TAGS
import os, tempfile
from Cython.Shadow import inline
from Cython.Build.Inline import safe_type
from Cython.TestUtils import CythonTest
......@@ -13,23 +14,31 @@ test_kwds = dict(force=True, quiet=True)
global_value = 100
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):
self.assertEquals(inline("return 1+2", **test_kwds), 3)
self.assertEquals(inline("return 1+2", **self.test_kwds), 3)
def test_types(self):
self.assertEquals(inline("""
cimport cython
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):
a = 1
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):
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:
......@@ -38,4 +47,4 @@ class TestInline(CythonTest):
a = numpy.ndarray((10, 20))
a[0,0] = 10
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):
html_filename = os.path.splitext(target_filename)[0] + ".html"
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"""
<head>
......
......@@ -527,8 +527,7 @@ def use_py2_buffer_functions(env):
#if PY_MAJOR_VERSION < 3
static int __Pyx_GetBuffer(PyObject *obj, Py_buffer *view, int flags) {
#if PY_VERSION_HEX >= 0x02060000
if (Py_TYPE(obj)->tp_flags & Py_TPFLAGS_HAVE_NEWBUFFER)
return PyObject_GetBuffer(obj, view, flags);
if (PyObject_CheckBuffer(obj)) return PyObject_GetBuffer(obj, view, flags);
#endif
""")
if len(types) > 0:
......@@ -548,11 +547,15 @@ def use_py2_buffer_functions(env):
static void __Pyx_ReleaseBuffer(Py_buffer *view) {
PyObject* obj = view->obj;
if (obj) {
#if PY_VERSION_HEX >= 0x02060000
if (PyObject_CheckBuffer(obj)) {PyBuffer_Release(view); return;}
#endif
""")
if len(types) > 0:
clause = "if"
for t, get, release in types:
if release:
code += " "
code += "%s (PyObject_TypeCheck(obj, %s)) %s(obj, view);" % (clause, t, release)
clause = "else if"
code += dedent("""
......@@ -1114,6 +1117,11 @@ static const char* __Pyx_BufFmt_CheckString(__Pyx_BufFmt_Context* ctx, const cha
ctx->new_count = 1;
got_Z = 0;
break;
case ':':
++ts;
while(*ts != ':') ++ts;
++ts;
break;
default:
{
ctx->new_count = __Pyx_BufFmt_ParseNumber(&ts);
......
......@@ -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(
proto = """
#if PY_VERSION_HEX < 0x02040000
......@@ -365,7 +384,8 @@ builtin_function_table = [
utility_code = getattr3_utility_code),
BuiltinFunction('getattr3', "OOO", "O", "__Pyx_GetAttr3", "getattr",
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"),
#('hex', "", "", ""),
#('id', "", "", ""),
......
......@@ -34,7 +34,7 @@ Options:
-a, --annotate Produce a colorized HTML version of the source.
--line-directives Produce #line directives pointing to the .pyx source
--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.
-3 Compile based on Python-3 syntax and code semantics.
--fast-fail Abort the compilation on the first error
......@@ -84,8 +84,12 @@ def parse_command_line(args):
options.use_listing_file = 1
elif option in ("-+", "--cplus"):
options.cplus = 1
elif option == "--embed":
Options.embed = True
elif option.startswith("--embed"):
ix = option.find('=')
if ix == -1:
Options.embed = "main"
else:
Options.embed = option[ix+1:]
elif option.startswith("-I"):
options.include_path.append(get_param(option))
elif option == "--include-dir":
......
......@@ -371,7 +371,7 @@ class ExprNode(Node):
def nonlocally_immutable(self):
# Returns whether this variable is a safe reference, i.e.
# 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 ------------------
......@@ -1483,6 +1483,8 @@ class NameNode(AtomicExprNode):
return 1
def nonlocally_immutable(self):
if ExprNode.nonlocally_immutable(self):
return True
entry = self.entry
return entry and (entry.is_local or entry.is_arg) and not entry.in_closure
......@@ -1681,20 +1683,22 @@ class NameNode(AtomicExprNode):
def generate_deletion_code(self, code):
if self.entry is None:
return # There was an error earlier
if not self.entry.is_pyglobal:
error(self.pos, "Deletion of local or C global name not supported")
return
if self.entry.is_pyclass_attr:
elif self.entry.is_pyglobal:
code.put_error_if_neg(self.pos,
'__Pyx_DelAttrString(%s, "%s")' % (
Naming.module_cname,
self.entry.name))
elif self.entry.is_pyclass_attr:
namespace = self.entry.scope.namespace_cname
code.put_error_if_neg(self.pos,
'PyMapping_DelItemString(%s, "%s")' % (
namespace,
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:
code.put_error_if_neg(self.pos,
'__Pyx_DelAttrString(%s, "%s")' % (
Naming.module_cname,
self.entry.name))
error(self.pos, "Deletion of C names not supported")
def annotate(self, code):
if hasattr(self, 'is_called') and self.is_called:
......@@ -3043,10 +3047,11 @@ class SimpleCallNode(CallNode):
if i == 0 and self.self is not None:
continue # self is ok
arg = self.args[i]
if arg.is_name and arg.entry and (
(arg.entry.is_local and not arg.entry.in_closure)
or arg.entry.type.is_cfunction):
# local variables and C functions are safe
if arg.nonlocally_immutable():
# locals, C functions, unassignable types are safe.
pass
elif arg.type.is_cpp_class:
# Assignment has side effects, avoid.
pass
elif env.nogil and arg.type.is_pyobject:
# 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
compile-time values.
"""
import sys
from Nodes import *
from ExprNodes import *
from Errors import CompileError
......@@ -44,6 +45,10 @@ def interpret_compiletime_options(optlist, optdict, type_env=None, type_args=())
else:
raise CompileError(node.pos, "Type not allowed here.")
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)
if optlist:
......@@ -52,6 +57,7 @@ def interpret_compiletime_options(optlist, optdict, type_env=None, type_args=())
assert isinstance(optdict, DictNode)
new_optdict = {}
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
return (optlist, new_optdict)
......@@ -2,7 +2,7 @@
# Cython Top Level
#
import os, sys, re
import os, sys, re, codecs
if sys.version_info[:2] < (2, 3):
sys.stderr.write("Sorry, Cython requires Python 2.3 or later\n")
sys.exit(1)
......@@ -607,6 +607,14 @@ def run_pipeline(source, options, full_module_name = None):
# Set up result object
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
if source_ext.lower() == '.py':
pipeline = context.create_py_pipeline(options, result)
......@@ -826,7 +834,7 @@ default_options = dict(
errors_to_stderr = 1,
cplus = 0,
output_file = None,
annotate = False,
annotate = None,
generate_pxi = 0,
working_path = "",
recursive = 0,
......
......@@ -272,7 +272,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code = globalstate['before_global_var']
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("/* Implementation of %s */" % env.qualified_name)
......@@ -1744,7 +1744,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln("#endif")
code.putln("{")
tempdecl_code = code.insertion_point()
code.putln("#if CYTHON_REFNANNY")
code.putln("void* __pyx_refnanny = NULL;")
code.putln("__Pyx_RefNanny = __Pyx_RefNannyImportAPI(\"refnanny\");")
......@@ -1757,6 +1757,9 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln("__pyx_refnanny = __Pyx_RefNanny->SetupContext(\"%s\", __LINE__, __FILE__);"% header3)
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 = 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):
def generate_main_method(self, env, code):
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):
if env.doc:
......@@ -2648,9 +2660,9 @@ impl = """
#endif
#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)
int wmain(int argc, wchar_t **argv) {
int %(wmain_method)s(int argc, wchar_t **argv) {
#else
static int __Pyx_main(int argc, wchar_t **argv) {
#endif
......@@ -2667,9 +2679,13 @@ static int __Pyx_main(int argc, wchar_t **argv) {
m = fpgetmask();
fpsetmask(m & ~FP_X_OFL);
#endif
Py_SetProgramName(argv[0]);
if (argc) {
Py_SetProgramName(argv[0]);
}
Py_Initialize();
PySys_SetArgv(argc, argv);
if (argc) {
PySys_SetArgv(argc, argv);
}
%(module_is_main)s = 1;
#if PY_MAJOR_VERSION < 3
init%(module_name)s();
......@@ -2796,33 +2812,38 @@ oom:
}
int
main(int argc, char **argv)
%(main_method)s(int argc, char **argv)
{
wchar_t **argv_copy = (wchar_t **)malloc(sizeof(wchar_t*)*argc);
/* We need a second copies, as Python might modify the first one. */
wchar_t **argv_copy2 = (wchar_t **)malloc(sizeof(wchar_t*)*argc);
int i, res;
char *oldloc;
if (!argv_copy || !argv_copy2) {
fprintf(stderr, "out of memory\\n");
return 1;
}
oldloc = strdup(setlocale(LC_ALL, NULL));
setlocale(LC_ALL, "");
for (i = 0; i < argc; i++) {
argv_copy2[i] = argv_copy[i] = __Pyx_char2wchar(argv[i]);
if (!argv_copy[i])
return 1;
}
setlocale(LC_ALL, oldloc);
free(oldloc);
res = __Pyx_main(argc, argv_copy);
for (i = 0; i < argc; i++) {
free(argv_copy2[i]);
}
free(argv_copy);
free(argv_copy2);
return res;
if (!argc) {
return __Pyx_main(0, NULL);
}
else {
wchar_t **argv_copy = (wchar_t **)malloc(sizeof(wchar_t*)*argc);
/* We need a second copies, as Python might modify the first one. */
wchar_t **argv_copy2 = (wchar_t **)malloc(sizeof(wchar_t*)*argc);
int i, res;
char *oldloc;
if (!argv_copy || !argv_copy2) {
fprintf(stderr, "out of memory\\n");
return 1;
}
oldloc = strdup(setlocale(LC_ALL, NULL));
setlocale(LC_ALL, "");
for (i = 0; i < argc; i++) {
argv_copy2[i] = argv_copy[i] = __Pyx_char2wchar(argv[i]);
if (!argv_copy[i])
return 1;
}
setlocale(LC_ALL, oldloc);
free(oldloc);
res = __Pyx_main(argc, argv_copy);
for (i = 0; i < argc; i++) {
free(argv_copy2[i]);
}
free(argv_copy);
free(argv_copy2);
return res;
}
}
#endif
""")
......@@ -2834,3 +2855,26 @@ packed_struct_utility_code = UtilityCode(proto="""
#define __Pyx_PACKED
#endif
""", 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):
self.entry = env.declare_cpp_class(
self.name, scope, self.pos,
self.cname, base_class_types, visibility = self.visibility, templates = template_types)
if self.entry is None:
return
self.entry.is_cpp_class = 1
if self.attributes is not None:
if self.in_pxd and not env.in_cinclude:
......
......@@ -44,9 +44,10 @@ lookup_module_cpdef = 0
init_local_none = 1
# 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.
embed = False
embed = None
# Disables function redefinition, allowing all functions to be declared at
# module creation time. For legacy code only.
......
......@@ -449,7 +449,8 @@ class Scope(object):
visibility = visibility, defining = scope is not None)
else:
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:
warning(pos, "'%s' already defined (ignoring second definition)" % name, 0)
else:
......
......@@ -121,6 +121,12 @@ class MarkAssignments(CythonTransform):
self.visitchildren(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):
# It may be possible to integrate this with the above for
......
......@@ -3,7 +3,7 @@
cdef extern from *:
ctypedef char const_char "const char"
cdef extern from "locale.h":
cdef extern from "locale.h" nogil:
struct lconv:
char *decimal_point
......
cdef extern from "math.h":
cdef extern from "math.h" nogil:
enum: M_E
enum: M_LOG2E
......@@ -29,9 +29,57 @@ cdef extern from "math.h":
double asinh(double x)
double atanh(double x)
double hypot(double x, double y)
double exp(double x)
double exp2(double x)
double expm1(double x)
double log(double x)
double logb(double x)
double log2(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 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
# numpy.int corresponds to 'l' and numpy.long to 'q'
ctypedef npy_long int_t
ctypedef npy_longlong long_t
ctypedef npy_intp intp_t
ctypedef npy_uintp uintp_t
ctypedef npy_longlong longlong_t
ctypedef npy_ulong uint_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 double_t
......
......@@ -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())")
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'))")
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'))")
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
SYSLIBS= $(shell $(PYTHON) -c "import distutils.sysconfig; print(distutils.sysconfig.get_config_var('SYSLIBS'))")
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
$(CC) -c $^ -I$(INCDIR)
CYTHON=../../cython.py
embedded.c: embedded.pyx
@$(PYTHON) ../../cython.py --embed embedded.pyx
@$(PYTHON) $(CYTHON) --embed embedded.pyx
all: embedded
......
import sys
if open(sys.argv[1]).read() != open(sys.argv[2]).read():
print "Files differ"
sys.exit(1)
else:
print "Files identical"
f1 = open(sys.argv[1])
f2 = open(sys.argv[2])
try:
if f1.read() != f2.read():
print ("Files differ")
sys.exit(1)
else:
print ("Files identical")
finally:
f1.close()
f2.close()
......@@ -9,9 +9,12 @@ local:
.git: REV := $(shell cat .gitrev)
.git: TMPDIR := $(shell mktemp -d tmprepo.XXXXXX)
.git:
rm -rf $(TMPDIR)
git clone $(REPO) $(TMPDIR)
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
rm -rf $(TMPDIR)
......
......@@ -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
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
make repo
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
threading = None
WITH_CYTHON = True
CY3_DIR = None
from distutils.dist import Distribution
from distutils.core import Extension
......@@ -176,8 +177,8 @@ class TestBuilder(object):
continue
suite.addTest(
self.handle_directory(path, filename))
if sys.platform not in ['win32'] and sys.version_info[0] < 3:
# Non-Windows makefile, can't run Cython under Py3.
if sys.platform not in ['win32']:
# Non-Windows makefile.
if [1 for selector in self.selectors if selector("embedded")] \
and not [1 for selector in self.exclude_selectors if selector("embedded")]:
suite.addTest(unittest.makeSuite(EmbedTest))
......@@ -193,7 +194,7 @@ class TestBuilder(object):
filenames = os.listdir(path)
filenames.sort()
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) ]:
continue
if self.exclude_selectors:
......@@ -892,8 +893,12 @@ class EmbedTest(unittest.TestCase):
if not os.path.isdir(libdir) or libname not in os.listdir(libdir):
# report the error for the original directory
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(
"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:
os.remove('make.output')
except OSError:
......@@ -967,6 +972,7 @@ def refactor_for_py3(distdir, cy3_dir):
recursive-include Cython *.py *.pyx *.pxd
recursive-include Cython/Debugger/Tests *
include runtests.py
include cython.py
''')
sys.path.insert(0, cy3_dir)
......@@ -1105,7 +1111,8 @@ def main():
for name in cy_modules:
del sys.modules[name]
# 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):
refactor_for_py3(DISTDIR, 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):
Traceback (most recent call last):
...
OverflowError: ...
>>> if CHAR_MIN < 0:
... assert test_char(-1) == -1
>>> test_char(CHAR_MIN) == CHAR_MIN
True
>>> test_char(-1)
-1
>>> test_char(0)
0
>>> 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):
while a.attr:
del 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():
0
"""
cdef char key = -1
d = {-1:0}
if <char>-1 < 0:
d = {-1:0}
else:
d = {255:0}
return d[key]
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:
Write to slices
>>> b = a.copy()
>>> put_range_long_1d(b[:, 3])
>>> print b
>>> print (b)
[[0 1 2 0 4]
[5 6 7 1 9]]
>>> put_range_long_1d(b[::-1, 3])
>>> print b
>>> print (b)
[[0 1 2 1 4]
[5 6 7 0 9]]
>>> a = np.zeros(9, dtype='l')
>>> put_range_long_1d(a[1::3])
>>> print a
>>> print (a)
[0 0 0 0 1 0 0 2 0]
Write to picked subarrays. This should NOT change the original
array as picking creates a new mutable copy.
>>> a = np.zeros(10, dtype='l').reshape(2, 5)
>>> 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]]
......@@ -103,18 +103,18 @@ try:
0 1 2 3
4 5 6 7
8 9 10 11
>>> test_c_contig(f_arr)
>>> test_c_contig(f_arr) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
ValueError: ndarray is not C contiguous
>>> test_f_contig(c_arr)
ValueError: ndarray is not C...contiguous
>>> test_f_contig(c_arr) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
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):
...
ValueError: ndarray is not C contiguous
ValueError: ndarray is not C...contiguous
>>> test_dtype('b', inc1_byte)
>>> test_dtype('B', inc1_ubyte)
......@@ -137,7 +137,7 @@ try:
>>> test_dtype('G', inc1_clongdouble_struct)
>>> 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.double, inc1_double_t)
>>> test_dtype(np.intp, inc1_intp_t)
......@@ -150,10 +150,10 @@ try:
Endian tests:
>>> 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):
...
ValueError: Non-native byte order not supported
ValueError: ...
......@@ -181,15 +181,15 @@ try:
array([(22, 23)],
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):
...
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):
...
ValueError: Buffer dtype mismatch; next field is at offset 1 but 4 expected
ValueError: ...
>>> test_good_cast()
......@@ -235,17 +235,17 @@ def ndarray_str(arr):
return unicode(arr).replace(u'\n\n', u'\n<_BLANKLINE_>\n')
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[0, 2], buf[0, 0], buf[1, 4], buf[1, 0]
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 buf[0, 1, 2], buf[0, 0, 0], buf[1, 1, 1], buf[1, 0, 0]
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[0], buf[1], buf[2]
......@@ -262,12 +262,12 @@ def put_range_long_1d(np.ndarray[long] arr):
arr[i] = value
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
for i in range(arr.shape[0]):
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
for i in range(arr.shape[0]):
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):
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_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_double_t(np.ndarray[np.double_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):
"G", np.clongdouble):
if sizeof(double) == sizeof(long double): # MSVC
return
if dtype in (b'F', b'D', b'G'):
if dtype in ('F', 'D', 'G'):
a = np.array([0, 10+10j], dtype=dtype)
inc1(a)
if a[1] != (11 + 11j): print u"failed!", a[1]
......@@ -344,7 +345,7 @@ cdef struct DoubleInt:
def test_recordarray():
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
rec = arr[0]
if rec.x != 5: print u"failed"
......@@ -384,13 +385,13 @@ def test_bad_nested_dtypes():
def test_good_cast():
# 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]
return -100 == <int>data
def test_bad_cast():
# 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:
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