Commit 86d1bd4a authored by Vitja Makarov's avatar Vitja Makarov

Merge remote branch 'upstream/master'

Conflicts:
	Cython/Compiler/Nodes.py
parents bb8cd827 9f2c79e1
...@@ -151,7 +151,7 @@ def cython_inline(code, ...@@ -151,7 +151,7 @@ def cython_inline(code,
if m.groups()[0] == 'numpy': if m.groups()[0] == 'numpy':
import numpy import numpy
c_include_dirs.append(numpy.get_include()) c_include_dirs.append(numpy.get_include())
cflags.append('-Wno-unused') # cflags.append('-Wno-unused')
module_body, func_body = extract_func_code(code) module_body, func_body = extract_func_code(code)
params = ', '.join(['%s %s' % a for a in arg_sigs]) params = ', '.join(['%s %s' % a for a in arg_sigs])
module_code = """ module_code = """
......
...@@ -366,7 +366,7 @@ builtin_function_table = [ ...@@ -366,7 +366,7 @@ builtin_function_table = [
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", "PyObject_HasAttr"),
BuiltinFunction('hash', "O", "l", "PyObject_Hash"), BuiltinFunction('hash', "O", "h", "PyObject_Hash"),
#('hex', "", "", ""), #('hex', "", "", ""),
#('id', "", "", ""), #('id', "", "", ""),
#('input', "", "", ""), #('input', "", "", ""),
...@@ -503,6 +503,7 @@ builtin_structs_table = [ ...@@ -503,6 +503,7 @@ builtin_structs_table = [
("shape", PyrexTypes.c_py_ssize_t_ptr_type), ("shape", PyrexTypes.c_py_ssize_t_ptr_type),
("strides", PyrexTypes.c_py_ssize_t_ptr_type), ("strides", PyrexTypes.c_py_ssize_t_ptr_type),
("suboffsets", PyrexTypes.c_py_ssize_t_ptr_type), ("suboffsets", PyrexTypes.c_py_ssize_t_ptr_type),
("smalltable", PyrexTypes.CArrayType(PyrexTypes.c_py_ssize_t_type, 2)),
("internal", PyrexTypes.c_void_ptr_type), ("internal", PyrexTypes.c_void_ptr_type),
]), ]),
('Py_complex', 'Py_complex', ('Py_complex', 'Py_complex',
......
...@@ -2073,14 +2073,17 @@ class IndexNode(ExprNode): ...@@ -2073,14 +2073,17 @@ class IndexNode(ExprNode):
if index_type and index_type.is_int or isinstance(self.index, (IntNode, LongNode)): if index_type and index_type.is_int or isinstance(self.index, (IntNode, LongNode)):
# indexing! # indexing!
if base_type is unicode_type: if base_type is unicode_type:
# Py_UNICODE will automatically coerce to a unicode string # Py_UCS4 will automatically coerce to a unicode string
# if required, so this is safe. We only infer Py_UNICODE # if required, so this is safe. We only infer Py_UCS4
# when the index is a C integer type. Otherwise, we may # when the index is a C integer type. Otherwise, we may
# need to use normal Python item access, in which case # need to use normal Python item access, in which case
# it's faster to return the one-char unicode string than # it's faster to return the one-char unicode string than
# to receive it, throw it away, and potentially rebuild it # to receive it, throw it away, and potentially rebuild it
# on a subsequent PyObject coercion. # on a subsequent PyObject coercion.
return PyrexTypes.c_py_unicode_type return PyrexTypes.c_py_ucs4_type
elif base_type is str_type:
# always returns str - Py2: bytes, Py3: unicode
return base_type
elif isinstance(self.base, BytesNode): elif isinstance(self.base, BytesNode):
#if env.global_scope().context.language_level >= 3: #if env.global_scope().context.language_level >= 3:
# # infering 'char' can be made to work in Python 3 mode # # infering 'char' can be made to work in Python 3 mode
...@@ -2091,8 +2094,8 @@ class IndexNode(ExprNode): ...@@ -2091,8 +2094,8 @@ class IndexNode(ExprNode):
return base_type.base_type return base_type.base_type
# may be slicing or indexing, we don't know # may be slicing or indexing, we don't know
if base_type is unicode_type: if base_type in (unicode_type, str_type):
# this type always returns its own type on Python indexing/slicing # these types always returns their own type on Python indexing/slicing
return base_type return base_type
else: else:
# TODO: Handle buffers (hopefully without too much redundancy). # TODO: Handle buffers (hopefully without too much redundancy).
...@@ -2200,7 +2203,7 @@ class IndexNode(ExprNode): ...@@ -2200,7 +2203,7 @@ class IndexNode(ExprNode):
if self.index.type.is_int and base_type is unicode_type: if self.index.type.is_int and base_type is unicode_type:
# Py_UNICODE/Py_UCS4 will automatically coerce to a unicode string # Py_UNICODE/Py_UCS4 will automatically coerce to a unicode string
# if required, so this is fast and safe # if required, so this is fast and safe
self.type = PyrexTypes.c_py_unicode_type self.type = PyrexTypes.c_py_ucs4_type
elif is_slice and base_type in (bytes_type, str_type, unicode_type, list_type, tuple_type): elif is_slice and base_type in (bytes_type, str_type, unicode_type, list_type, tuple_type):
self.type = base_type self.type = base_type
else: else:
...@@ -6721,11 +6724,43 @@ static CYTHON_INLINE int __Pyx_UnicodeContains(PyObject* unicode, Py_UNICODE cha ...@@ -6721,11 +6724,43 @@ static CYTHON_INLINE int __Pyx_UnicodeContains(PyObject* unicode, Py_UNICODE cha
""", """,
impl=""" impl="""
static CYTHON_INLINE int __Pyx_UnicodeContains(PyObject* unicode, Py_UNICODE character) { static CYTHON_INLINE int __Pyx_UnicodeContains(PyObject* unicode, Py_UNICODE character) {
Py_UNICODE* pos;
const Py_ssize_t length = PyUnicode_GET_SIZE(unicode); const Py_ssize_t length = PyUnicode_GET_SIZE(unicode);
Py_UNICODE* char_start = PyUnicode_AS_UNICODE(unicode); Py_UNICODE* char_start = PyUnicode_AS_UNICODE(unicode);
for (pos=char_start; pos < char_start+length; pos++) {
if (unlikely(character == pos[0])) return 1;
}
return 0;
}
""")
py_ucs4_in_unicode_utility_code = UtilityCode(
proto="""
static CYTHON_INLINE int __Pyx_UnicodeContainsUCS4(PyObject* unicode, Py_UCS4 character); /*proto*/
""",
# additionally handles surrogate pairs in 16bit Unicode builds
impl="""
static CYTHON_INLINE int __Pyx_UnicodeContainsUCS4(PyObject* unicode, Py_UCS4 character) {
Py_UNICODE* pos; Py_UNICODE* pos;
Py_UNICODE uchar;
const Py_ssize_t length = PyUnicode_GET_SIZE(unicode);
Py_UNICODE* char_start = PyUnicode_AS_UNICODE(unicode);
#if Py_UNICODE_SIZE == 2
if (unlikely(character > 65535)) {
Py_UNICODE high_val, low_val;
high_val = (Py_UNICODE) (0xD800 | (((character - 0x10000) >> 10) & ((1<<10)-1)));
low_val = (Py_UNICODE) (0xDC00 | ( (character - 0x10000) & ((1<<10)-1)));
for (pos=char_start; pos < char_start+length-1; pos++) {
if (unlikely(high_val == pos[0]) & unlikely(low_val == pos[1])) return 1;
}
return 0;
}
#endif
uchar = (Py_UNICODE) character;
for (pos=char_start; pos < char_start+length; pos++) { for (pos=char_start; pos < char_start+length; pos++) {
if (character == pos[0]) return 1; if (unlikely(uchar == pos[0])) return 1;
} }
return 0; return 0;
} }
...@@ -6823,7 +6858,12 @@ class PrimaryCmpNode(ExprNode, CmpNode): ...@@ -6823,7 +6858,12 @@ class PrimaryCmpNode(ExprNode, CmpNode):
error(self.pos, "Cascading comparison not yet supported for 'int_val in string'.") error(self.pos, "Cascading comparison not yet supported for 'int_val in string'.")
return return
if self.operand2.type is unicode_type: if self.operand2.type is unicode_type:
env.use_utility_code(pyunicode_in_unicode_utility_code) self.uchar_test_type = PyrexTypes.widest_numeric_type(
self.operand1.type, PyrexTypes.c_py_unicode_type)
if self.uchar_test_type is PyrexTypes.c_py_unicode_type:
env.use_utility_code(pyunicode_in_unicode_utility_code)
else:
env.use_utility_code(py_ucs4_in_unicode_utility_code)
else: else:
if self.operand1.type is PyrexTypes.c_uchar_type: if self.operand1.type is PyrexTypes.c_uchar_type:
self.operand1 = self.operand1.coerce_to(PyrexTypes.c_char_type, env) self.operand1 = self.operand1.coerce_to(PyrexTypes.c_char_type, env)
...@@ -6913,10 +6953,13 @@ class PrimaryCmpNode(ExprNode, CmpNode): ...@@ -6913,10 +6953,13 @@ class PrimaryCmpNode(ExprNode, CmpNode):
self.operand1.result(), self.operand1.result(),
self.operand2.result()) self.operand2.result())
elif self.is_c_string_contains(): elif self.is_c_string_contains():
if self.operand2.type is bytes_type: if self.operand2.type is unicode_type:
method = "__Pyx_BytesContains" if self.uchar_test_type is PyrexTypes.c_py_unicode_type:
method = "__Pyx_UnicodeContains"
else:
method = "__Pyx_UnicodeContainsUCS4"
else: else:
method = "__Pyx_UnicodeContains" method = "__Pyx_BytesContains"
if self.operator == "not_in": if self.operator == "not_in":
negation = "!" negation = "!"
else: else:
......
...@@ -610,6 +610,15 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -610,6 +610,15 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
#define PyBoolObject PyLongObject #define PyBoolObject PyLongObject
#endif #endif
#if PY_VERSION_HEX < 0x03020000
typedef long Py_hash_t;
#define __Pyx_PyInt_FromHash_t PyInt_FromLong
#define __Pyx_PyInt_AsHash_t PyInt_AsLong
#else
#define __Pyx_PyInt_FromHash_t PyInt_FromSsize_t
#define __Pyx_PyInt_AsHash_t PyInt_AsSsize_t
#endif
""") """)
code.put(""" code.put("""
......
...@@ -2654,7 +2654,7 @@ class DefNode(FuncDefNode): ...@@ -2654,7 +2654,7 @@ class DefNode(FuncDefNode):
max_positional_args, Naming.args_cname)) max_positional_args, Naming.args_cname))
code.putln("if (unlikely(!%s)) {" % self.star_arg.entry.cname) code.putln("if (unlikely(!%s)) {" % self.star_arg.entry.cname)
if self.starstar_arg: if self.starstar_arg:
code.put_decref(self.starstar_arg.entry.cname, py_object_type) code.put_decref_clear(self.starstar_arg.entry.cname, py_object_type)
if self.needs_closure: if self.needs_closure:
code.put_decref(Naming.cur_scope_cname, self.local_scope.scope_class.type) code.put_decref(Naming.cur_scope_cname, self.local_scope.scope_class.type)
code.put_finish_refcount_context() code.put_finish_refcount_context()
...@@ -5308,7 +5308,7 @@ class GILStatNode(TryFinallyStatNode): ...@@ -5308,7 +5308,7 @@ class GILStatNode(TryFinallyStatNode):
code.putln("#endif") code.putln("#endif")
else: else:
code.putln("#ifdef WITH_THREAD") code.putln("#ifdef WITH_THREAD")
code.putln("PyThreadState *_save;") code.putln("PyThreadState *_save = NULL;")
code.putln("#endif") code.putln("#endif")
code.putln("Py_UNBLOCK_THREADS") code.putln("Py_UNBLOCK_THREADS")
TryFinallyStatNode.generate_execution_code(self, code) TryFinallyStatNode.generate_execution_code(self, code)
......
...@@ -2184,7 +2184,7 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform): ...@@ -2184,7 +2184,7 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
PyUnicode_uchar_predicate_func_type = PyrexTypes.CFuncType( PyUnicode_uchar_predicate_func_type = PyrexTypes.CFuncType(
PyrexTypes.c_bint_type, [ PyrexTypes.c_bint_type, [
PyrexTypes.CFuncTypeArg("uchar", PyrexTypes.c_py_unicode_type, None), PyrexTypes.CFuncTypeArg("uchar", PyrexTypes.c_py_ucs4_type, None),
]) ])
def _inject_unicode_predicate(self, node, args, is_unbound_method): def _inject_unicode_predicate(self, node, args, is_unbound_method):
...@@ -2222,8 +2222,8 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform): ...@@ -2222,8 +2222,8 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
_handle_simple_method_unicode_isupper = _inject_unicode_predicate _handle_simple_method_unicode_isupper = _inject_unicode_predicate
PyUnicode_uchar_conversion_func_type = PyrexTypes.CFuncType( PyUnicode_uchar_conversion_func_type = PyrexTypes.CFuncType(
PyrexTypes.c_py_unicode_type, [ PyrexTypes.c_py_ucs4_type, [
PyrexTypes.CFuncTypeArg("uchar", PyrexTypes.c_py_unicode_type, None), PyrexTypes.CFuncTypeArg("uchar", PyrexTypes.c_py_ucs4_type, None),
]) ])
def _inject_unicode_character_conversion(self, node, args, is_unbound_method): def _inject_unicode_character_conversion(self, node, args, is_unbound_method):
...@@ -2703,10 +2703,18 @@ py_unicode_istitle_utility_code = UtilityCode( ...@@ -2703,10 +2703,18 @@ py_unicode_istitle_utility_code = UtilityCode(
# Py_UNICODE_ISTITLE() doesn't match unicode.istitle() as the latter # Py_UNICODE_ISTITLE() doesn't match unicode.istitle() as the latter
# additionally allows character that comply with Py_UNICODE_ISUPPER() # additionally allows character that comply with Py_UNICODE_ISUPPER()
proto = ''' proto = '''
#if PY_VERSION_HEX < 0x030200A2
static CYTHON_INLINE int __Pyx_Py_UNICODE_ISTITLE(Py_UNICODE uchar); /* proto */ static CYTHON_INLINE int __Pyx_Py_UNICODE_ISTITLE(Py_UNICODE uchar); /* proto */
#else
static CYTHON_INLINE int __Pyx_Py_UNICODE_ISTITLE(Py_UCS4 uchar); /* proto */
#endif
''', ''',
impl = ''' impl = '''
#if PY_VERSION_HEX < 0x030200A2
static CYTHON_INLINE int __Pyx_Py_UNICODE_ISTITLE(Py_UNICODE uchar) { static CYTHON_INLINE int __Pyx_Py_UNICODE_ISTITLE(Py_UNICODE uchar) {
#else
static CYTHON_INLINE int __Pyx_Py_UNICODE_ISTITLE(Py_UCS4 uchar) {
#endif
return Py_UNICODE_ISTITLE(uchar) || Py_UNICODE_ISUPPER(uchar); return Py_UNICODE_ISTITLE(uchar) || Py_UNICODE_ISUPPER(uchar);
} }
''') ''')
......
...@@ -965,7 +965,7 @@ static CYTHON_INLINE Py_UCS4 __Pyx_PyObject_AsPy_UCS4(PyObject* x) { ...@@ -965,7 +965,7 @@ static CYTHON_INLINE Py_UCS4 __Pyx_PyObject_AsPy_UCS4(PyObject* x) {
if (high_val >= 0xD800 && high_val <= 0xDBFF) { if (high_val >= 0xD800 && high_val <= 0xDBFF) {
Py_UCS4 low_val = PyUnicode_AS_UNICODE(x)[1]; Py_UCS4 low_val = PyUnicode_AS_UNICODE(x)[1];
if (low_val >= 0xDC00 && low_val <= 0xDFFF) { if (low_val >= 0xDC00 && low_val <= 0xDFFF) {
return 0x10000 | ((high_val & ((1<<10)-1)) << 10) | (low_val & ((1<<10)-1)); return 0x10000 + (((high_val & ((1<<10)-1)) << 10) | (low_val & ((1<<10)-1)));
} }
} }
} }
...@@ -1056,6 +1056,14 @@ static CYTHON_INLINE Py_UNICODE __Pyx_PyObject_AsPy_UNICODE(PyObject* x) { ...@@ -1056,6 +1056,14 @@ static CYTHON_INLINE Py_UNICODE __Pyx_PyObject_AsPy_UNICODE(PyObject* x) {
''') ''')
class CPyHashTType(CIntType):
to_py_function = "__Pyx_PyInt_FromHash_t"
from_py_function = "__Pyx_PyInt_AsHash_t"
def sign_and_name(self):
return "Py_hash_t"
class CPySSizeTType(CIntType): class CPySSizeTType(CIntType):
to_py_function = "PyInt_FromSsize_t" to_py_function = "PyInt_FromSsize_t"
...@@ -1522,7 +1530,7 @@ class CArrayType(CType): ...@@ -1522,7 +1530,7 @@ class CArrayType(CType):
def __init__(self, base_type, size): def __init__(self, base_type, size):
self.base_type = base_type self.base_type = base_type
self.size = size self.size = size
if base_type is c_char_type: if base_type in (c_char_type, c_uchar_type, c_schar_type):
self.is_string = 1 self.is_string = 1
def __repr__(self): def __repr__(self):
...@@ -2381,6 +2389,7 @@ c_returncode_type = CReturnCodeType(RANK_INT) ...@@ -2381,6 +2389,7 @@ c_returncode_type = CReturnCodeType(RANK_INT)
c_bint_type = CBIntType(RANK_INT) c_bint_type = CBIntType(RANK_INT)
c_py_unicode_type = CPyUnicodeIntType(RANK_INT-0.5, UNSIGNED) c_py_unicode_type = CPyUnicodeIntType(RANK_INT-0.5, UNSIGNED)
c_py_ucs4_type = CPyUCS4IntType(RANK_LONG-0.5, UNSIGNED) c_py_ucs4_type = CPyUCS4IntType(RANK_LONG-0.5, UNSIGNED)
c_py_hash_t_type = CPyHashTType(RANK_LONG+0.5, SIGNED)
c_py_ssize_t_type = CPySSizeTType(RANK_LONG+0.5, SIGNED) c_py_ssize_t_type = CPySSizeTType(RANK_LONG+0.5, SIGNED)
c_ssize_t_type = CSSizeTType(RANK_LONG+0.5, SIGNED) c_ssize_t_type = CSSizeTType(RANK_LONG+0.5, SIGNED)
c_size_t_type = CSizeTType(RANK_LONG+0.5, UNSIGNED) c_size_t_type = CSizeTType(RANK_LONG+0.5, UNSIGNED)
...@@ -2443,6 +2452,7 @@ modifiers_and_name_to_type = { ...@@ -2443,6 +2452,7 @@ modifiers_and_name_to_type = {
(1, 0, "bint"): c_bint_type, (1, 0, "bint"): c_bint_type,
(0, 0, "Py_UNICODE"): c_py_unicode_type, (0, 0, "Py_UNICODE"): c_py_unicode_type,
(0, 0, "Py_UCS4"): c_py_ucs4_type, (0, 0, "Py_UCS4"): c_py_ucs4_type,
(2, 0, "Py_hash_t"): c_py_hash_t_type,
(2, 0, "Py_ssize_t"): c_py_ssize_t_type, (2, 0, "Py_ssize_t"): c_py_ssize_t_type,
(2, 0, "ssize_t") : c_ssize_t_type, (2, 0, "ssize_t") : c_ssize_t_type,
(0, 0, "size_t") : c_size_t_type, (0, 0, "size_t") : c_size_t_type,
...@@ -2692,6 +2702,8 @@ def parse_basic_type(name): ...@@ -2692,6 +2702,8 @@ def parse_basic_type(name):
signed = 0 signed = 0
elif name == 'Py_UCS4': elif name == 'Py_UCS4':
signed = 0 signed = 0
elif name == 'Py_hash_t':
signed = 2
elif name == 'Py_ssize_t': elif name == 'Py_ssize_t':
signed = 2 signed = 2
elif name == 'ssize_t': elif name == 'ssize_t':
......
...@@ -32,6 +32,7 @@ class Signature(object): ...@@ -32,6 +32,7 @@ class Signature(object):
# 'b' bint # 'b' bint
# 'I' int * # 'I' int *
# 'l' long # 'l' long
# 'h' Py_hash_t
# 'z' Py_ssize_t # 'z' Py_ssize_t
# 'Z' Py_ssize_t * # 'Z' Py_ssize_t *
# 's' char * # 's' char *
...@@ -52,6 +53,7 @@ class Signature(object): ...@@ -52,6 +53,7 @@ class Signature(object):
'b': PyrexTypes.c_bint_type, 'b': PyrexTypes.c_bint_type,
'I': PyrexTypes.c_int_ptr_type, 'I': PyrexTypes.c_int_ptr_type,
'l': PyrexTypes.c_long_type, 'l': PyrexTypes.c_long_type,
'h': PyrexTypes.c_py_hash_t_type,
'z': PyrexTypes.c_py_ssize_t_type, 'z': PyrexTypes.c_py_ssize_t_type,
'Z': PyrexTypes.c_py_ssize_t_ptr_type, 'Z': PyrexTypes.c_py_ssize_t_ptr_type,
's': PyrexTypes.c_char_ptr_type, 's': PyrexTypes.c_char_ptr_type,
...@@ -69,6 +71,7 @@ class Signature(object): ...@@ -69,6 +71,7 @@ class Signature(object):
'b': "-1", 'b': "-1",
'l': "-1", 'l': "-1",
'r': "-1", 'r': "-1",
'h': "-1",
'z': "-1", 'z': "-1",
} }
...@@ -534,7 +537,7 @@ setattrofunc = Signature("TOO", 'r') # typedef int (*setattrofunc)(PyObjec ...@@ -534,7 +537,7 @@ setattrofunc = Signature("TOO", 'r') # typedef int (*setattrofunc)(PyObjec
delattrofunc = Signature("TO", 'r') delattrofunc = Signature("TO", 'r')
cmpfunc = Signature("TO", "i") # typedef int (*cmpfunc)(PyObject *, PyObject *); cmpfunc = Signature("TO", "i") # typedef int (*cmpfunc)(PyObject *, PyObject *);
reprfunc = Signature("T", "O") # typedef PyObject *(*reprfunc)(PyObject *); reprfunc = Signature("T", "O") # typedef PyObject *(*reprfunc)(PyObject *);
hashfunc = Signature("T", "l") # typedef long (*hashfunc)(PyObject *); hashfunc = Signature("T", "h") # typedef Py_hash_t (*hashfunc)(PyObject *);
# typedef PyObject *(*richcmpfunc) (PyObject *, PyObject *, int); # typedef PyObject *(*richcmpfunc) (PyObject *, PyObject *, int);
richcmpfunc = Signature("OOi", "O") # typedef PyObject *(*richcmpfunc) (PyObject *, PyObject *, int); richcmpfunc = Signature("OOi", "O") # typedef PyObject *(*richcmpfunc) (PyObject *, PyObject *, int);
getiterfunc = Signature("T", "O") # typedef PyObject *(*getiterfunc) (PyObject *); getiterfunc = Signature("T", "O") # typedef PyObject *(*getiterfunc) (PyObject *);
......
from __future__ import with_statement
import os import os
import re import re
import sys import sys
import uuid
import shutil import shutil
import warnings import warnings
import textwrap import textwrap
import unittest import unittest
import tempfile import tempfile
import subprocess import subprocess
import distutils.core #import distutils.core
from distutils import sysconfig #from distutils import sysconfig
from distutils import ccompiler from distutils import ccompiler
import runtests import runtests
...@@ -22,8 +20,12 @@ from Cython.Debugger import Cygdb as cygdb ...@@ -22,8 +20,12 @@ from Cython.Debugger import Cygdb as cygdb
root = os.path.dirname(os.path.abspath(__file__)) root = os.path.dirname(os.path.abspath(__file__))
codefile = os.path.join(root, 'codefile') codefile = os.path.join(root, 'codefile')
cfuncs_file = os.path.join(root, 'cfuncs.c') cfuncs_file = os.path.join(root, 'cfuncs.c')
with open(codefile) as f:
source_to_lineno = dict((line.strip(), i + 1) for i, line in enumerate(f)) f = open(codefile)
try:
source_to_lineno = dict([ (line.strip(), i + 1) for i, line in enumerate(f) ])
finally:
f.close()
# Cython.Distutils.__init__ imports build_ext from build_ext which means we # Cython.Distutils.__init__ imports build_ext from build_ext which means we
# can't access the module anymore. Get it from sys.modules instead. # can't access the module anymore. Get it from sys.modules instead.
...@@ -205,8 +207,11 @@ class GdbDebuggerTestCase(DebuggerTestCase): ...@@ -205,8 +207,11 @@ class GdbDebuggerTestCase(DebuggerTestCase):
self.gdb_command_file = cygdb.make_command_file(self.tempdir, self.gdb_command_file = cygdb.make_command_file(self.tempdir,
prefix_code) prefix_code)
with open(self.gdb_command_file, 'a') as f: f = open(self.gdb_command_file, 'a')
try:
f.write(code) f.write(code)
finally:
f.close()
args = ['gdb', '-batch', '-x', self.gdb_command_file, '-n', '--args', args = ['gdb', '-batch', '-x', self.gdb_command_file, '-n', '--args',
sys.executable, '-c', 'import codefile'] sys.executable, '-c', 'import codefile']
......
__version__ = "0.14.1rc3" __version__ = "0.14.1+"
# Void cython.* directives (for case insensitive operating systems). # Void cython.* directives (for case insensitive operating systems).
from Cython.Shadow import * from Cython.Shadow import *
...@@ -6,6 +6,7 @@ import re ...@@ -6,6 +6,7 @@ import re
import gc import gc
import codecs import codecs
import shutil import shutil
import time
import unittest import unittest
import doctest import doctest
import operator import operator
...@@ -97,7 +98,7 @@ KEEP_2X_FILES = [ ...@@ -97,7 +98,7 @@ KEEP_2X_FILES = [
os.path.join('Cython', 'Debugger', 'libpython.py'), os.path.join('Cython', 'Debugger', 'libpython.py'),
] ]
COMPILER = None
INCLUDE_DIRS = [ d for d in os.getenv('INCLUDE', '').split(os.pathsep) if d ] INCLUDE_DIRS = [ d for d in os.getenv('INCLUDE', '').split(os.pathsep) if d ]
CFLAGS = os.getenv('CFLAGS', '').split() CFLAGS = os.getenv('CFLAGS', '').split()
...@@ -177,7 +178,8 @@ class TestBuilder(object): ...@@ -177,7 +178,8 @@ class TestBuilder(object):
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'] and sys.version_info[0] < 3:
# Non-Windows makefile, can't run Cython under Py3. # Non-Windows makefile, can't run Cython under Py3.
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")]:
suite.addTest(unittest.makeSuite(EmbedTest)) suite.addTest(unittest.makeSuite(EmbedTest))
return suite return suite
...@@ -194,7 +196,10 @@ class TestBuilder(object): ...@@ -194,7 +196,10 @@ class TestBuilder(object):
if context == "build" and filename.endswith(".srctree"): if context == "build" and 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
suite.addTest(EndToEndTest(filename, workdir, self.cleanup_workdir)) if self.exclude_selectors:
if [1 for match in self.exclude_selectors if match(filename)]:
continue
suite.addTest(EndToEndTest(os.path.join(path, filename), workdir, self.cleanup_workdir))
continue continue
if not (filename.endswith(".pyx") or filename.endswith(".py")): if not (filename.endswith(".pyx") or filename.endswith(".py")):
continue continue
...@@ -409,20 +414,24 @@ class CythonCompileTestCase(unittest.TestCase): ...@@ -409,20 +414,24 @@ class CythonCompileTestCase(unittest.TestCase):
if incdir: if incdir:
build_extension.include_dirs.append(incdir) build_extension.include_dirs.append(incdir)
build_extension.finalize_options() build_extension.finalize_options()
if COMPILER:
build_extension.compiler = COMPILER
ext_include_dirs = [] ext_include_dirs = []
for match, get_additional_include_dirs in EXT_DEP_INCLUDES: for match, get_additional_include_dirs in EXT_DEP_INCLUDES:
if match(module): if match(module):
ext_include_dirs += get_additional_include_dirs() ext_include_dirs += get_additional_include_dirs()
self.copy_related_files(test_directory, workdir, module) ext_compile_flags = CFLAGS[:]
if build_extension.compiler == 'mingw32':
ext_compile_flags.append('-Wno-format')
if extra_extension_args is None: if extra_extension_args is None:
extra_extension_args = {} extra_extension_args = {}
self.copy_related_files(test_directory, workdir, module)
extension = Extension( extension = Extension(
module, module,
sources = self.find_source_files(workdir, module), sources = self.find_source_files(workdir, module),
include_dirs = ext_include_dirs, include_dirs = ext_include_dirs,
extra_compile_args = CFLAGS, extra_compile_args = ext_compile_flags,
**extra_extension_args **extra_extension_args
) )
if self.language == 'cpp': if self.language == 'cpp':
...@@ -709,8 +718,7 @@ def collect_unittests(path, module_prefix, suite, selectors): ...@@ -709,8 +718,7 @@ def collect_unittests(path, module_prefix, suite, selectors):
if include_debugger: if include_debugger:
skipped_dirs = [] skipped_dirs = []
else: else:
cython_dir = os.path.dirname(os.path.abspath(__file__)) skipped_dirs = ['Cython' + os.path.sep + 'Debugger' + os.path.sep]
skipped_dirs = [os.path.join(cython_dir, 'Cython', 'Debugger')]
for dirpath, dirnames, filenames in os.walk(path): for dirpath, dirnames, filenames in os.walk(path):
if dirpath != path and "__init__.py" not in filenames: if dirpath != path and "__init__.py" not in filenames:
...@@ -786,8 +794,9 @@ class EndToEndTest(unittest.TestCase): ...@@ -786,8 +794,9 @@ class EndToEndTest(unittest.TestCase):
cython_root = os.path.dirname(os.path.abspath(__file__)) cython_root = os.path.dirname(os.path.abspath(__file__))
def __init__(self, treefile, workdir, cleanup_workdir=True): def __init__(self, treefile, workdir, cleanup_workdir=True):
self.name = os.path.splitext(os.path.basename(treefile))[0]
self.treefile = treefile self.treefile = treefile
self.workdir = os.path.join(workdir, os.path.splitext(treefile)[0]) self.workdir = os.path.join(workdir, self.name)
self.cleanup_workdir = cleanup_workdir self.cleanup_workdir = cleanup_workdir
cython_syspath = self.cython_root cython_syspath = self.cython_root
for path in sys.path[::-1]: for path in sys.path[::-1]:
...@@ -800,12 +809,11 @@ class EndToEndTest(unittest.TestCase): ...@@ -800,12 +809,11 @@ class EndToEndTest(unittest.TestCase):
unittest.TestCase.__init__(self) unittest.TestCase.__init__(self)
def shortDescription(self): def shortDescription(self):
return "End-to-end %s" % self.treefile return "End-to-end %s" % self.name
def setUp(self): def setUp(self):
from Cython.TestUtils import unpack_source_tree from Cython.TestUtils import unpack_source_tree
_, self.commands = unpack_source_tree( _, self.commands = unpack_source_tree(self.treefile, self.workdir)
os.path.join('tests', 'build', self.treefile), self.workdir)
self.old_dir = os.getcwd() self.old_dir = os.getcwd()
os.chdir(self.workdir) os.chdir(self.workdir)
if self.workdir not in sys.path: if self.workdir not in sys.path:
...@@ -813,7 +821,13 @@ class EndToEndTest(unittest.TestCase): ...@@ -813,7 +821,13 @@ class EndToEndTest(unittest.TestCase):
def tearDown(self): def tearDown(self):
if self.cleanup_workdir: if self.cleanup_workdir:
shutil.rmtree(self.workdir) for trial in range(5):
try:
shutil.rmtree(self.workdir)
except OSError:
time.sleep(0.1)
else:
break
os.chdir(self.old_dir) os.chdir(self.old_dir)
def runTest(self): def runTest(self):
...@@ -1006,6 +1020,8 @@ def main(): ...@@ -1006,6 +1020,8 @@ def main():
parser.add_option("--no-cython", dest="with_cython", parser.add_option("--no-cython", dest="with_cython",
action="store_false", default=True, action="store_false", default=True,
help="do not run the Cython compiler, only the C compiler") help="do not run the Cython compiler, only the C compiler")
parser.add_option("--compiler", dest="compiler", default=None,
help="C compiler type")
parser.add_option("--no-c", dest="use_c", parser.add_option("--no-c", dest="use_c",
action="store_false", default=True, action="store_false", default=True,
help="do not test C compilation") help="do not test C compilation")
...@@ -1123,7 +1139,7 @@ def main(): ...@@ -1123,7 +1139,7 @@ def main():
# RUN ALL TESTS! # RUN ALL TESTS!
UNITTEST_MODULE = "Cython" UNITTEST_MODULE = "Cython"
UNITTEST_ROOT = os.path.join(os.getcwd(), UNITTEST_MODULE) UNITTEST_ROOT = os.path.join(os.path.dirname(__file__), UNITTEST_MODULE)
if WITH_CYTHON: if WITH_CYTHON:
if os.path.exists(WORKDIR): if os.path.exists(WORKDIR):
for path in os.listdir(WORKDIR): for path in os.listdir(WORKDIR):
...@@ -1189,6 +1205,9 @@ def main(): ...@@ -1189,6 +1205,9 @@ def main():
if sys.platform in ['win32', 'cygwin'] and sys.version_info < (2,6): if sys.platform in ['win32', 'cygwin'] and sys.version_info < (2,6):
exclude_selectors += [ lambda x: x == "run.specialfloat" ] exclude_selectors += [ lambda x: x == "run.specialfloat" ]
global COMPILER
if options.compiler:
COMPILER = options.compiler
languages = [] languages = []
if options.use_c: if options.use_c:
languages.append('c') languages.append('c')
......
...@@ -272,8 +272,8 @@ setup( ...@@ -272,8 +272,8 @@ setup(
name = 'Cython', name = 'Cython',
version = version, version = version,
url = 'http://www.cython.org', url = 'http://www.cython.org',
author = 'Greg Ewing, Robert Bradshaw, Stefan Behnel, Dag Seljebotn, et al.', author = 'Robert Bradshaw, Stefan Behnel, Dag Seljebotn, Greg Ewing, et al.',
author_email = 'cython-dev@codespeak.net', author_email = 'cython-devel@python.org',
description = "The Cython compiler for writing C extensions for the Python language.", description = "The Cython compiler for writing C extensions for the Python language.",
long_description = """\ long_description = """\
The Cython language makes writing C extensions for the Python language as The Cython language makes writing C extensions for the Python language as
......
...@@ -8,9 +8,14 @@ PYTHON -c "import a" ...@@ -8,9 +8,14 @@ PYTHON -c "import a"
from Cython.Build.Dependencies import cythonize from Cython.Build.Dependencies import cythonize
from distutils.core import setup from distutils.core import setup
import sys
if sys.platform == 'win32':
MATH_LIBS = []
else:
MATH_LIBS = ['m']
setup( setup(
ext_modules = cythonize("*.pyx", aliases={'MATH_LIBS': ['m']}), ext_modules = cythonize("*.pyx", aliases={'MATH_LIBS': MATH_LIBS}),
) )
######## my_lib.pxd ######## ######## my_lib.pxd ########
......
cdef extern int a "c_a", b "c_b" cdef extern from "cnamespec.h":
int a "c_a", b "c_b"
cdef struct foo "c_foo": cdef struct foo "c_foo":
int i "c_i" int i "c_i"
......
...@@ -2,13 +2,13 @@ ...@@ -2,13 +2,13 @@
extern "C" { extern "C" {
#endif #endif
extern DL_EXPORT(void) e1(void); extern DL_EXPORT(void) e1(void);
extern DL_EXPORT(void *) e2(void); extern DL_EXPORT(int*) e2(void);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
void e1(void) {return;} void e1(void) {return;}
void *e2(void) {return 0;} int* e2(void) {return 0;}
......
...@@ -7,9 +7,10 @@ cdef void f(): ...@@ -7,9 +7,10 @@ cdef void f():
cdef int (*h)() cdef int (*h)()
h = <int ()()>f # this is an error h = <int ()()>f # this is an error
h = <int (*)()>f # this is OK h = <int (*)()>f # this is OK
_ERRORS = u""" _ERRORS = u"""
1:19: Array element cannot be a function 1:19: Array element cannot be a function
2:18: Function cannot return an array
3:18: Function cannot return a function 3:18: Function cannot return a function
8:10: Function cannot return a function 8:10: Function cannot return a function
8:5: Cannot cast to a function type 8:5: Cannot cast to a function type
......
def outer(int x, *args, **kwargs):
"""
>>> inner = outer(1, 2, a=3)
>>> inner()
(1, (2,), {'a': 3})
>>> inner = outer('abc', 2, a=3)
Traceback (most recent call last):
TypeError: an integer is required
"""
def inner():
return x, args, kwargs
return inner
...@@ -195,3 +195,25 @@ def index_and_in(): ...@@ -195,3 +195,25 @@ def index_and_in():
for i in range(1,9): for i in range(1,9):
if u'abcdefgh'[-i] in u'abCDefGh': if u'abcdefgh'[-i] in u'abCDefGh':
print i print i
# special test for narrow builds
high_uchar = u'\U00012345'
high_ustring0 = u'\U00012345\U00012346abc'
high_ustring1 = u'\U00012346\U00012345abc'
high_ustring_end = u'\U00012346abc\U00012344\U00012345'
high_ustring_no = u'\U00012346\U00012346abc'
def uchar_in(Py_UCS4 uchar, unicode ustring):
"""
>>> uchar_in(high_uchar, high_ustring0)
True
>>> uchar_in(high_uchar, high_ustring1)
True
>>> uchar_in(high_uchar, high_ustring_end)
True
>>> uchar_in(high_uchar, high_ustring_no)
False
"""
assert uchar == 0x12345, ('%X' % uchar)
return uchar in ustring
...@@ -94,15 +94,15 @@ def indexing(): ...@@ -94,15 +94,15 @@ def indexing():
b = b"abc" b = b"abc"
assert typeof(b) == "bytes object", typeof(b) assert typeof(b) == "bytes object", typeof(b)
b1 = b[1] b1 = b[1]
assert typeof(b1) == "Python object", typeof(b1) assert typeof(b1) == "Python object", typeof(b1) # Py2: bytes, Py3: int
u = u"xyz" u = u"xyz"
assert typeof(u) == "unicode object", typeof(u) assert typeof(u) == "unicode object", typeof(u)
u1 = u[1] u1 = u[1]
assert typeof(u1) == "Py_UNICODE", typeof(u1) assert typeof(u1) == "Py_UCS4", typeof(u1)
s = "xyz" s = "xyz"
assert typeof(s) == "str object", typeof(s) assert typeof(s) == "str object", typeof(s)
s1 = s[1] s1 = s[1]
assert typeof(s1) == "Python object", typeof(s1) assert typeof(s1) == "str object", typeof(s1)
L = [1,2,3] L = [1,2,3]
assert typeof(L) == "list object", typeof(L) assert typeof(L) == "list object", typeof(L)
L1 = L[1] L1 = L[1]
...@@ -296,6 +296,7 @@ def loop_over_bytes(): ...@@ -296,6 +296,7 @@ def loop_over_bytes():
Python object Python object
""" """
cdef bytes bytes_string = b'abcdefg' cdef bytes bytes_string = b'abcdefg'
# bytes in Py2, int in Py3
for c in bytes_string: for c in bytes_string:
pass pass
return typeof(c) return typeof(c)
...@@ -303,9 +304,10 @@ def loop_over_bytes(): ...@@ -303,9 +304,10 @@ def loop_over_bytes():
def loop_over_str(): def loop_over_str():
""" """
>>> print( loop_over_str() ) >>> print( loop_over_str() )
Python object str object
""" """
cdef str string = 'abcdefg' cdef str string = 'abcdefg'
# str (bytes) in Py2, str (unicode) in Py3
for c in string: for c in string:
pass pass
return typeof(c) return typeof(c)
...@@ -313,9 +315,10 @@ def loop_over_str(): ...@@ -313,9 +315,10 @@ def loop_over_str():
def loop_over_unicode(): def loop_over_unicode():
""" """
>>> print( loop_over_unicode() ) >>> print( loop_over_unicode() )
Py_UNICODE Py_UCS4
""" """
cdef unicode ustring = u'abcdefg' cdef unicode ustring = u'abcdefg'
# Py_UCS4 can represent any Unicode character
for uchar in ustring: for uchar in ustring:
pass pass
return typeof(uchar) return typeof(uchar)
......
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