Commit 24c64823 authored by Stefan Behnel's avatar Stefan Behnel

merged in latest cython-devel

parents a8bdadbe 07226b17
...@@ -5389,7 +5389,7 @@ class BoolBinopNode(ExprNode): ...@@ -5389,7 +5389,7 @@ class BoolBinopNode(ExprNode):
def infer_type(self, env): def infer_type(self, env):
type1 = self.operand1.infer_type(env) type1 = self.operand1.infer_type(env)
type2 = self.operand2.infer_type(env) type2 = self.operand2.infer_type(env)
return PyrexTypes.spanning_type(type1, type2) return PyrexTypes.independent_spanning_type(type1, type2)
def calculate_constant_result(self): def calculate_constant_result(self):
if self.operator == 'and': if self.operator == 'and':
...@@ -5418,7 +5418,7 @@ class BoolBinopNode(ExprNode): ...@@ -5418,7 +5418,7 @@ class BoolBinopNode(ExprNode):
def analyse_types(self, env): def analyse_types(self, env):
self.operand1.analyse_types(env) self.operand1.analyse_types(env)
self.operand2.analyse_types(env) self.operand2.analyse_types(env)
self.type = PyrexTypes.spanning_type(self.operand1.type, self.operand2.type) self.type = PyrexTypes.independent_spanning_type(self.operand1.type, self.operand2.type)
self.operand1 = self.operand1.coerce_to(self.type, env) self.operand1 = self.operand1.coerce_to(self.type, env)
self.operand2 = self.operand2.coerce_to(self.type, env) self.operand2 = self.operand2.coerce_to(self.type, env)
...@@ -5492,8 +5492,8 @@ class CondExprNode(ExprNode): ...@@ -5492,8 +5492,8 @@ class CondExprNode(ExprNode):
return self.true_val.type_dependencies(env) + self.false_val.type_dependencies(env) return self.true_val.type_dependencies(env) + self.false_val.type_dependencies(env)
def infer_type(self, env): def infer_type(self, env):
return self.compute_result_type(self.true_val.infer_type(env), return PyrexTypes.independent_spanning_type(self.true_val.infer_type(env),
self.false_val.infer_type(env)) self.false_val.infer_type(env))
def calculate_constant_result(self): def calculate_constant_result(self):
if self.test.constant_result: if self.test.constant_result:
...@@ -5506,7 +5506,7 @@ class CondExprNode(ExprNode): ...@@ -5506,7 +5506,7 @@ class CondExprNode(ExprNode):
self.test = self.test.coerce_to_boolean(env) self.test = self.test.coerce_to_boolean(env)
self.true_val.analyse_types(env) self.true_val.analyse_types(env)
self.false_val.analyse_types(env) self.false_val.analyse_types(env)
self.type = self.compute_result_type(self.true_val.type, self.false_val.type) self.type = PyrexTypes.independent_spanning_type(self.true_val.type, self.false_val.type)
if self.true_val.type.is_pyobject or self.false_val.type.is_pyobject: if self.true_val.type.is_pyobject or self.false_val.type.is_pyobject:
self.true_val = self.true_val.coerce_to(self.type, env) self.true_val = self.true_val.coerce_to(self.type, env)
self.false_val = self.false_val.coerce_to(self.type, env) self.false_val = self.false_val.coerce_to(self.type, env)
...@@ -5514,24 +5514,6 @@ class CondExprNode(ExprNode): ...@@ -5514,24 +5514,6 @@ class CondExprNode(ExprNode):
if self.type == PyrexTypes.error_type: if self.type == PyrexTypes.error_type:
self.type_error() self.type_error()
def compute_result_type(self, type1, type2):
if type1 == type2:
return type1
elif type1.is_numeric and type2.is_numeric:
return PyrexTypes.widest_numeric_type(type1, type2)
elif type1.is_extension_type and type1.subtype_of_resolved_type(type2):
return type2
elif type2.is_extension_type and type2.subtype_of_resolved_type(type1):
return type1
elif type1.is_pyobject or type2.is_pyobject:
return py_object_type
elif type1.assignable_from(type2):
return type1
elif type2.assignable_from(type1):
return type2
else:
return PyrexTypes.error_type
def type_error(self): def type_error(self):
if not (self.true_val.type.is_error or self.false_val.type.is_error): if not (self.true_val.type.is_error or self.false_val.type.is_error):
error(self.pos, "Incompatable types in conditional expression (%s; %s)" % error(self.pos, "Incompatable types in conditional expression (%s; %s)" %
......
...@@ -1693,6 +1693,8 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform): ...@@ -1693,6 +1693,8 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
return node return node
_handle_simple_method_list_pop = _handle_simple_method_object_pop
PyList_Append_func_type = PyrexTypes.CFuncType( PyList_Append_func_type = PyrexTypes.CFuncType(
PyrexTypes.c_int_type, [ PyrexTypes.c_int_type, [
PyrexTypes.CFuncTypeArg("list", PyrexTypes.py_object_type, None), PyrexTypes.CFuncTypeArg("list", PyrexTypes.py_object_type, None),
...@@ -2423,7 +2425,7 @@ impl = """ ...@@ -2423,7 +2425,7 @@ impl = """
static CYTHON_INLINE Py_UNICODE __Pyx_PyUnicode_GetItemInt(PyObject* unicode, Py_ssize_t index, int check_bounds) { static CYTHON_INLINE Py_UNICODE __Pyx_PyUnicode_GetItemInt(PyObject* unicode, Py_ssize_t index, int check_bounds) {
if (check_bounds) { if (check_bounds) {
if (unlikely(index >= PyUnicode_GET_SIZE(unicode)) | if (unlikely(index >= PyUnicode_GET_SIZE(unicode)) |
unlikely(index < -PyUnicode_GET_SIZE(unicode))) { ((index < 0) & unlikely(index < -PyUnicode_GET_SIZE(unicode)))) {
PyErr_Format(PyExc_IndexError, "string index out of range"); PyErr_Format(PyExc_IndexError, "string index out of range");
return (Py_UNICODE)-1; return (Py_UNICODE)-1;
} }
...@@ -2444,7 +2446,7 @@ impl = """ ...@@ -2444,7 +2446,7 @@ impl = """
static CYTHON_INLINE char __Pyx_PyBytes_GetItemInt(PyObject* bytes, Py_ssize_t index, int check_bounds) { static CYTHON_INLINE char __Pyx_PyBytes_GetItemInt(PyObject* bytes, Py_ssize_t index, int check_bounds) {
if (check_bounds) { if (check_bounds) {
if (unlikely(index >= PyBytes_GET_SIZE(bytes)) | if (unlikely(index >= PyBytes_GET_SIZE(bytes)) |
unlikely(index < -PyBytes_GET_SIZE(bytes))) { ((index < 0) & unlikely(index < -PyBytes_GET_SIZE(bytes)))) {
PyErr_Format(PyExc_IndexError, "string index out of range"); PyErr_Format(PyExc_IndexError, "string index out of range");
return -1; return -1;
} }
...@@ -2524,6 +2526,24 @@ class ConstantFolding(Visitor.VisitorTransform, SkipDeclarations): ...@@ -2524,6 +2526,24 @@ class ConstantFolding(Visitor.VisitorTransform, SkipDeclarations):
self._calculate_const(node) self._calculate_const(node)
return node return node
def visit_BoolBinopNode(self, node):
self._calculate_const(node)
if node.constant_result is ExprNodes.not_a_constant:
return node
if not node.operand1.is_literal or not node.operand2.is_literal:
# We calculate other constants to make them available to
# the compiler, but we only aggregate constant nodes
# recursively, so non-const nodes are straight out.
return node
if node.constant_result == node.operand1.constant_result and node.operand1.is_literal:
return node.operand1
elif node.constant_result == node.operand2.constant_result and node.operand2.is_literal:
return node.operand2
else:
# FIXME: we could do more ...
return node
def visit_BinopNode(self, node): def visit_BinopNode(self, node):
self._calculate_const(node) self._calculate_const(node)
if node.constant_result is ExprNodes.not_a_constant: if node.constant_result is ExprNodes.not_a_constant:
...@@ -2566,7 +2586,10 @@ class ConstantFolding(Visitor.VisitorTransform, SkipDeclarations): ...@@ -2566,7 +2586,10 @@ class ConstantFolding(Visitor.VisitorTransform, SkipDeclarations):
new_node = target_class(pos=node.pos, type = widest_type) new_node = target_class(pos=node.pos, type = widest_type)
new_node.constant_result = node.constant_result new_node.constant_result = node.constant_result
new_node.value = str(node.constant_result) if isinstance(node, ExprNodes.BoolNode):
new_node.value = node.constant_result
else:
new_node.value = str(node.constant_result)
#new_node = new_node.coerce_to(node.type, self.current_scope) #new_node = new_node.coerce_to(node.type, self.current_scope)
return new_node return new_node
......
...@@ -2413,31 +2413,52 @@ def widest_numeric_type(type1, type2): ...@@ -2413,31 +2413,52 @@ def widest_numeric_type(type1, type2):
widest_type = type2 widest_type = type2
return widest_type return widest_type
def spanning_type(type1, type2): def independent_spanning_type(type1, type2):
# Return a type assignable from both type1 and type2. # Return a type assignable independently from both type1 and
if type1 is py_object_type or type2 is py_object_type: # type2, but do not require any interoperability between the two.
# For example, in "True * 2", it is safe to assume an integer
# result type (so spanning_type() will do the right thing),
# whereas "x = True or 2" must evaluate to a type that can hold
# both a boolean value and an integer, so this function works
# better.
if type1 == type2:
return type1
elif (type1 is c_bint_type or type2 is c_bint_type) and (type1.is_numeric and type2.is_numeric):
# special case: if one of the results is a bint and the other
# is another C integer, we must prevent returning a numeric
# type so that we do not loose the ability to coerce to a
# Python bool if we have to.
return py_object_type return py_object_type
elif type1 == type2: span_type = _spanning_type(type1, type2)
if span_type is None:
return PyrexTypes.error_type
return span_type
def spanning_type(type1, type2):
# Return a type assignable from both type1 and type2, or
# py_object_type if no better type is found. Assumes that the
# code that calls this will try a coercion afterwards, which will
# fail if the types cannot actually coerce to a py_object_type.
if type1 == type2:
return type1 return type1
elif type1.is_numeric and type2.is_numeric: elif type1 is py_object_type or type2 is py_object_type:
return py_object_type
span_type = _spanning_type(type1, type2)
if span_type is None:
return py_object_type
return span_type
def _spanning_type(type1, type2):
if type1.is_numeric and type2.is_numeric:
return widest_numeric_type(type1, type2) return widest_numeric_type(type1, type2)
elif type1.is_builtin_type and type1.name == 'float' and type2.is_numeric: elif type1.is_builtin_type and type1.name == 'float' and type2.is_numeric:
return widest_numeric_type(c_double_type, type2) return widest_numeric_type(c_double_type, type2)
elif type2.is_builtin_type and type2.name == 'float' and type1.is_numeric: elif type2.is_builtin_type and type2.name == 'float' and type1.is_numeric:
return widest_numeric_type(type1, c_double_type) return widest_numeric_type(type1, c_double_type)
elif type1.is_pyobject ^ type2.is_pyobject:
return py_object_type
elif type1.is_extension_type and type2.is_extension_type: elif type1.is_extension_type and type2.is_extension_type:
if type1.typeobj_is_imported() or type2.typeobj_is_imported(): return widest_extension_type(type1, type2)
return py_object_type elif type1.is_pyobject or type2.is_pyobject:
while True: return py_object_type
if type1.subtype_of(type2):
return type2
elif type2.subtype_of(type1):
return type1
type1, type2 = type1.base_type, type2.base_type
if type1 is None or type2 is None:
return py_object_type
elif type1.assignable_from(type2): elif type1.assignable_from(type2):
if type1.is_extension_type and type1.typeobj_is_imported(): if type1.is_extension_type and type1.typeobj_is_imported():
# external types are unsafe, so we use PyObject instead # external types are unsafe, so we use PyObject instead
...@@ -2449,8 +2470,20 @@ def spanning_type(type1, type2): ...@@ -2449,8 +2470,20 @@ def spanning_type(type1, type2):
return py_object_type return py_object_type
return type2 return type2
else: else:
return None
def widest_extension_type(type1, type2):
if type1.typeobj_is_imported() or type2.typeobj_is_imported():
return py_object_type return py_object_type
while True:
if type1.subtype_of(type2):
return type2
elif type2.subtype_of(type1):
return type1
type1, type2 = type1.base_type, type2.base_type
if type1 is None or type2 is None:
return py_object_type
def simple_c_type(signed, longness, name): def simple_c_type(signed, longness, name):
# Find type descriptor for simple type given name and modifiers. # Find type descriptor for simple type given name and modifiers.
# Returns None if arguments don't make sense. # Returns None if arguments don't make sense.
......
# http://www.opengroup.org/onlinepubs/009695399/basedefs/fcntl.h.html
cdef extern from "fcntl.h" nogil:
enum: F_DUPFD
enum: F_GETFD
enum: F_SETFD
enum: F_GETFL
enum: F_SETFL
enum: F_GETLK
enum: F_SETLK
enum: F_SETLKW
enum: F_GETOWN
enum: F_SETOWN
enum: FD_CLOEXEC
enum: F_RDLCK
enum: F_UNLCK
enum: F_WRLCK
enum: SEEK_SET
enum: SEEK_CUR
enum: SEEK_END
enum: O_CREAT
enum: O_EXCL
enum: O_NOCTTY
enum: O_TRUNC
enum: O_APPEND
enum: O_DSYNC
enum: O_NONBLOCK
enum: O_RSYNC
enum: O_SYNC
enum: O_ACCMODE # O_RDONLY|O_WRONLY|O_RDWR
enum: O_RDONLY
enum: O_WRONLY
enum: O_RDWR
enum: S_IFMT
enum: S_IFBLK
enum: S_IFCHR
enum: S_IFIFO
enum: S_IFREG
enum: S_IFDIR
enum: S_IFLNK
enum: S_IFSOCK
ctypedef int mode_t
ctypedef signed pid_t
ctypedef signed off_t
struct flock:
short l_type
short l_whence
off_t l_start
off_t l_len
pid_t l_pid
int creat(char *, mode_t)
int fcntl(int, int, ...)
int open(char *, int, ...)
#int open (char *, int, mode_t)
# http://www.opengroup.org/onlinepubs/009695399/basedefs/unistd.h.html
cdef extern from "unistd.h" nogil:
#:NULL
enum: R_OK
enum: W_OK
enum: X_OK
enum: F_OK
# confstr()
#_CS_PATH
#_CS_POSIX_*
enum: SEEK_SET
enum: SEEK_CUR
enum: SEEK_END
enum: F_LOCK
enum: F_TEST
enum: F_TLOCK
enum: F_ULOCK
# pathconf()
# _PC_*
# sysconf()
# _SC_*
enum: STDIN_FILENO #0
enum: STDOUT_FILENO #1
enum: STDERR_FILENO #2
#:ctypedef unsigned size_t
#:ctypedef signed ssize_t
ctypedef int uid_t
ctypedef int gid_t
ctypedef signed off_t
ctypedef signed pid_t
ctypedef unsigned useconds_t
ctypedef signed intptr_t
int access(char *, int)
unsigned alarm(unsigned)
int chdir(char *)
int chown(char *, uid_t, gid_t)
int close(int)
size_t confstr(int, char *, size_t)
char *crypt(char *, char *)
char *ctermid(char *)
int dup(int)
int dup2(int, int)
void encrypt(char[64], int)
int execl(char *, char *, ...)
int execle(char *, char *, ...)
int execlp(char *, char *, ...)
int execv(char *, char *[])
int execve(char *, char *[], char *[])
int execvp(char *, char *[])
void _exit(int)
int fchown(int, uid_t, gid_t)
int fchdir(int)
int fdatasync(int)
pid_t fork()
long fpathconf(int, int)
int fsync(int)
int ftruncate(int, off_t)
char *getcwd(char *, size_t)
gid_t getegid()
uid_t geteuid()
gid_t getgid()
int getgroups(int, gid_t [])
long gethostid()
int gethostname(char *, size_t)
char *getlogin()
int getlogin_r(char *, size_t)
int getopt(int, char * [], char *)
pid_t getpgid(pid_t)
pid_t getpgrp()
pid_t getpid()
pid_t getppid()
pid_t getsid(pid_t)
uid_t getuid()
char *getwd(char *)
int isatty(int)
int lchown(char *, uid_t, gid_t)
int link(char *, char *)
int lockf(int, int, off_t)
off_t lseek(int, off_t, int)
int nice(int)
long pathconf(char *, int)
int pause()
int pipe(int [2])
ssize_t pread(int, void *, size_t, off_t)
ssize_t pwrite(int, void *, size_t, off_t)
ssize_t read(int, void *, size_t)
ssize_t readlink(char *, char *, size_t)
int rmdir(char *)
int setegid(gid_t)
int seteuid(uid_t)
int setgid(gid_t)
int setpgid(pid_t, pid_t)
pid_t setpgrp()
int setregid(gid_t, gid_t)
int setreuid(uid_t, uid_t)
pid_t setsid()
int setuid(uid_t)
unsigned sleep(unsigned)
void swab(void *, void *, ssize_t)
int symlink(char *, char *)
void sync()
long sysconf(int)
pid_t tcgetpgrp(int)
int tcsetpgrp(int, pid_t)
int truncate(char *, off_t)
char *ttyname(int)
int ttyname_r(int, char *, size_t)
useconds_t ualarm(useconds_t, useconds_t)
int unlink(char *)
int usleep(useconds_t)
pid_t vfork()
ssize_t write(int, void *, size_t)
char *optarg
int optind
int opterr
int optopt
...@@ -35,7 +35,8 @@ TEST_RUN_DIRS = ['run', 'wrappers', 'pyregr'] ...@@ -35,7 +35,8 @@ TEST_RUN_DIRS = ['run', 'wrappers', 'pyregr']
# which should be excluded if the module is not present. # which should be excluded if the module is not present.
EXT_DEP_MODULES = { EXT_DEP_MODULES = {
'numpy' : re.compile('.*\.numpy_.*').match, 'numpy' : re.compile('.*\.numpy_.*').match,
'pstats' : re.compile('.*\.pstats_.*').match 'pstats' : re.compile('.*\.pstats_.*').match,
'posix' : re.compile('.*\.posix_.*').match,
} }
def get_numpy_include_dirs(): def get_numpy_include_dirs():
......
...@@ -10,6 +10,6 @@ cfunc_call_tuple_args_T408 ...@@ -10,6 +10,6 @@ cfunc_call_tuple_args_T408
cascaded_list_unpacking_T467 cascaded_list_unpacking_T467
compile.cpp_operators compile.cpp_operators
# Pyrex regression tests that don't current work: # CPython regression tests that don't current work:
pyregr.test_threadsignals pyregr.test_threadsignals
pyregr.test_module pyregr.test_module
...@@ -7,7 +7,7 @@ cimport libc.limits ...@@ -7,7 +7,7 @@ cimport libc.limits
cimport libc.locale cimport libc.locale
cimport libc.signal cimport libc.signal
cimport libc.stddef cimport libc.stddef
cimport libc.stdint #cimport libc.stdint # XXX MSVC
cimport libc.stdio cimport libc.stdio
cimport libc.stdlib cimport libc.stdlib
cimport libc.string cimport libc.string
...@@ -18,7 +18,7 @@ from libc cimport limits ...@@ -18,7 +18,7 @@ from libc cimport limits
from libc cimport locale from libc cimport locale
from libc cimport signal from libc cimport signal
from libc cimport stddef from libc cimport stddef
from libc cimport stdint #from libc cimport stdint # XXX MSVC
from libc cimport stdio from libc cimport stdio
from libc cimport stdlib from libc cimport stdlib
from libc cimport string from libc cimport string
...@@ -29,7 +29,7 @@ from libc.limits cimport * ...@@ -29,7 +29,7 @@ from libc.limits cimport *
from libc.locale cimport * from libc.locale cimport *
from libc.signal cimport * from libc.signal cimport *
from libc.stddef cimport * from libc.stddef cimport *
from libc.stdint cimport * #from libc.stdint cimport * # XXX MSVC
from libc.stdio cimport * from libc.stdio cimport *
from libc.stdlib cimport * from libc.stdlib cimport *
from libc.string cimport * from libc.string cimport *
......
cimport posix
cimport posix.unistd
from posix cimport unistd
from posix.unistd cimport *
cimport posix.fcntl
from posix cimport fcntl
from posix.fcntl cimport *
...@@ -52,3 +52,10 @@ def and2_no_result(a,b): ...@@ -52,3 +52,10 @@ def and2_no_result(a,b):
'b *' 'b *'
""" """
a and b a and b
def and2_literal():
"""
>>> and2_literal()
5
"""
return True and 5
cimport cython
@cython.test_fail_if_path_exists('//BoolBinopNode')
def or_literal_bint():
"""
>>> True or 5
True
>>> or_literal_bint()
True
"""
return True or 5
@cython.test_fail_if_path_exists('//BoolBinopNode')
def and_literal_bint():
"""
>>> 5 and True
True
>>> and_literal_bint()
True
"""
return 5 and True
@cython.test_fail_if_path_exists('//BoolBinopNode')
def False_and_True_or_0():
"""
>>> False and True or 0
0
>>> False_and_True_or_0()
0
"""
return False and True or 0
@cython.test_fail_if_path_exists('//BoolBinopNode')
def True_and_True_or_0():
"""
>>> True and True or 0
True
>>> True_and_True_or_0()
True
"""
return True and True or 0
def x_and_True_or_False(x):
"""
>>> x_and_True_or_False(0)
False
>>> x_and_True_or_False(1)
True
>>> x_and_True_or_False('abc')
True
>>> x_and_True_or_False([])
False
"""
return x and True or False
def x_and_True_or_0(x):
"""
>>> 0 and True or 0
0
>>> x_and_True_or_0(0)
0
>>> 1 and True or 0
True
>>> x_and_True_or_0(1)
True
>>> x_and_True_or_0('abc')
True
>>> x_and_True_or_0([])
0
"""
return x and True or 0
def x_and_True_or_1(x):
"""
>>> 0 and True or 1
1
>>> x_and_True_or_1(0)
1
>>> 1 and True or 1
True
>>> x_and_True_or_1(1)
True
>>> x_and_True_or_1('abc')
True
>>> x_and_True_or_1([])
1
"""
return x and True or 1
def x_and_1_or_False(x):
"""
>>> 0 and 1 or False
False
>>> x_and_1_or_False(0)
False
>>> 1 and 1 or False
1
>>> x_and_1_or_False(1)
1
>>> x_and_1_or_False('abc')
1
>>> x_and_1_or_False([])
False
"""
return x and 1 or False
cdef class Test:
"""
>>> t = Test(True)
>>> t.some_ro_bool
True
>>> t.some_public_bool
True
"""
cdef public bint some_public_bool
cdef readonly bint some_ro_bool
def __init__(self, bint boolval):
self.some_ro_bool = boolval
self.some_public_bool = boolval
import cython import cython
cdef extern from "complex_int_T446_fix.h":
pass
def test_arith(int complex a, int complex b): def test_arith(int complex a, int complex b):
""" """
>>> test_arith(4, 2) >>> test_arith(4, 2)
......
#if defined _MSC_VER && defined __cplusplus
#define CYTHON_CCOMPLEX 0
#endif
...@@ -32,6 +32,30 @@ def simple_pop(L): ...@@ -32,6 +32,30 @@ def simple_pop(L):
""" """
return L.pop() return L.pop()
@cython.test_assert_path_exists('//PythonCapiCallNode')
@cython.test_fail_if_path_exists('//SimpleCallNode/AttributeNode')
def simple_pop_typed(list L):
"""
>>> L = list(range(10))
>>> simple_pop_typed(L)
9
>>> simple_pop_typed(L)
8
>>> L
[0, 1, 2, 3, 4, 5, 6, 7]
>>> while L:
... _ = simple_pop_typed(L)
>>> L
[]
>>> simple_pop_typed(L)
Traceback (most recent call last):
...
IndexError: pop from empty list
"""
return L.pop()
@cython.test_assert_path_exists('//PythonCapiCallNode') @cython.test_assert_path_exists('//PythonCapiCallNode')
@cython.test_fail_if_path_exists('//SimpleCallNode/AttributeNode') @cython.test_fail_if_path_exists('//SimpleCallNode/AttributeNode')
def index_pop(L, int i): def index_pop(L, int i):
...@@ -68,6 +92,40 @@ def index_pop(L, int i): ...@@ -68,6 +92,40 @@ def index_pop(L, int i):
""" """
return L.pop(i) return L.pop(i)
@cython.test_assert_path_exists('//PythonCapiCallNode')
@cython.test_fail_if_path_exists('//SimpleCallNode/AttributeNode')
def index_pop_typed(list L, int i):
"""
>>> L = list(range(10))
>>> index_pop_typed(L, 2)
2
>>> index_pop_typed(L, -2)
8
>>> L
[0, 1, 3, 4, 5, 6, 7, 9]
>>> index_pop_typed(L, 100)
Traceback (most recent call last):
...
IndexError: pop index out of range
>>> index_pop_typed(L, -100)
Traceback (most recent call last):
...
IndexError: pop index out of range
>>> while L:
... _ = index_pop_typed(L, 0)
>>> L
[]
>>> index_pop_typed(L, 0)
Traceback (most recent call last):
...
IndexError: pop from empty list
"""
return L.pop(i)
@cython.test_fail_if_path_exists('//PythonCapiCallNode') @cython.test_fail_if_path_exists('//PythonCapiCallNode')
def crazy_pop(L): def crazy_pop(L):
""" """
......
...@@ -51,3 +51,10 @@ def or2_no_result(a,b): ...@@ -51,3 +51,10 @@ def or2_no_result(a,b):
'a *' 'a *'
""" """
a or b a or b
def or2_literal():
"""
>>> or2_literal()
5
"""
return False or 5
from libc.stdio cimport *
from posix.unistd cimport *
from posix.fcntl cimport *
cdef int noisy_function() except -1:
cdef int ret = 0
ret = printf(b"0123456789\n", 0)
assert ret == 11
ret = fflush(stdout)
assert ret == 0
ret = fprintf(stdout, b"0123456789\n", 0)
assert ret == 11
ret = fflush(stdout)
assert ret == 0
ret = write(STDOUT_FILENO, b"0123456789\n", 11)
assert ret == 11
return 0
def test_silent_stdout():
"""
>>> test_silent_stdout()
"""
cdef int ret
cdef int stdout_save, dev_null
stdout_save = dup(STDOUT_FILENO)
assert stdout_save != -1
dev_null = open(b"/dev/null", O_WRONLY, 0)
assert dev_null != -1
ret = dup2(dev_null, STDOUT_FILENO)
assert ret == STDOUT_FILENO
ret = close(dev_null)
assert ret == 0
try:
noisy_function()
finally:
ret = dup2(stdout_save, STDOUT_FILENO)
assert ret == STDOUT_FILENO
ret = close(stdout_save)
assert ret == 0
cdef class silent_fd:
cdef int fd_save, fd
def __cinit__(self, int fd=-1):
self.fd_save = -1
self.fd = STDOUT_FILENO
if fd != -1:
self.fd = fd
def __enter__(self):
cdef int ret = 0, dev_null = -1
assert self.fd_save == -1
dev_null = open(b"/dev/null", O_WRONLY, 0)
assert dev_null != -1
try:
self.fd_save = dup(self.fd)
assert self.fd_save != -1
try:
ret = dup2(dev_null, self.fd)
assert ret != -1
except:
ret = close(self.fd_save)
self.fd_save = -1
finally:
ret = close(dev_null)
def __exit__(self, t, v, tb):
cdef int ret = 0
if self.fd_save != -1:
ret = dup2(self.fd_save, self.fd)
assert ret == self.fd
ret = close(self.fd_save)
assert ret == 0
self.fd_save = -1
return None
def test_silent_stdout_ctxmanager():
"""
>> test_silent_stdout_ctxmanager()
"""
with silent_fd():
noisy_function()
try:
with silent_fd():
noisy_function()
raise RuntimeError
except RuntimeError:
pass
with silent_fd(STDOUT_FILENO):
noisy_function()
...@@ -46,12 +46,13 @@ Traceback (most recent call last): ...@@ -46,12 +46,13 @@ Traceback (most recent call last):
OverflowError: ... OverflowError: ...
""" """
# XXX This should generate a warning !!!
cdef extern from *: cdef extern from *:
ctypedef long ssize_t ctypedef long ssize_t # XXX This should generate a warning !!!
ssize_t PY_SSIZE_T_MAX
ssize_t PY_SSIZE_T_MIN
SSIZE_T_MAX = <ssize_t>((<size_t>-1)>>1) SSIZE_T_MAX = PY_SSIZE_T_MAX
SSIZE_T_MIN = (-SSIZE_T_MAX-1) SSIZE_T_MIN = PY_SSIZE_T_MIN
def test(ssize_t i): def test(ssize_t i):
return i return i
......
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