Commit 5a1d2cb6 authored by Dag Sverre Seljebotn's avatar Dag Sverre Seljebotn

merge

parents 2cb09abc c5366434
...@@ -3,9 +3,7 @@ from Cython.Compiler.Nodes import DefNode, CFuncDefNode ...@@ -3,9 +3,7 @@ from Cython.Compiler.Nodes import DefNode, CFuncDefNode
from Cython.Compiler.Errors import CompileError from Cython.Compiler.Errors import CompileError
from Cython.Compiler.StringEncoding import EncodedString from Cython.Compiler.StringEncoding import EncodedString
from Cython.Compiler import Options from Cython.Compiler import Options
from Cython.Compiler import PyrexTypes from Cython.Compiler import PyrexTypes, ExprNodes
class EmbedSignature(CythonTransform): class EmbedSignature(CythonTransform):
...@@ -16,15 +14,26 @@ class EmbedSignature(CythonTransform): ...@@ -16,15 +14,26 @@ class EmbedSignature(CythonTransform):
self.class_node = None self.class_node = None
def _fmt_arg_defv(self, arg): def _fmt_arg_defv(self, arg):
if not arg.default: default_val = arg.default
if not default_val:
return None return None
try: try:
denv = self.denv # XXX denv = self.denv # XXX
ctval = arg.default.compile_time_value(self.denv) ctval = default_val.compile_time_value(self.denv)
return '%r' % ctval repr_val = '%r' % ctval
if isinstance(default_val, ExprNodes.UnicodeNode):
if repr_val[:1] != 'u':
return u'u%s' % repr_val
elif isinstance(default_val, ExprNodes.BytesNode):
if repr_val[:1] != 'b':
return u'b%s' % repr_val
elif isinstance(default_val, ExprNodes.StringNode):
if repr_val[:1] in ('u', 'b'):
repr_val[1:]
return repr_val
except Exception: except Exception:
try: try:
return arg.default.name # XXX return default_val.name # XXX
except AttributeError: except AttributeError:
return '<???>' return '<???>'
......
...@@ -747,8 +747,9 @@ class GlobalState(object): ...@@ -747,8 +747,9 @@ class GlobalState(object):
u'*/', u'*[inserted by cython to avoid comment closer]/' u'*/', u'*[inserted by cython to avoid comment closer]/'
).replace( ).replace(
u'/*', u'/[inserted by cython to avoid comment start]*' u'/*', u'/[inserted by cython to avoid comment start]*'
).encode('ASCII', 'replace').decode('ASCII') )
for line in source_desc.get_lines()] for line in source_desc.get_lines(encoding='ASCII',
error_handling='ignore')]
if len(F) == 0: F.append(u'') if len(F) == 0: F.append(u'')
self.input_file_contents[source_desc] = F self.input_file_contents[source_desc] = F
return F return F
......
...@@ -13,7 +13,8 @@ import Nodes ...@@ -13,7 +13,8 @@ import Nodes
from Nodes import Node from Nodes import Node
import PyrexTypes import PyrexTypes
from PyrexTypes import py_object_type, c_long_type, typecast, error_type, unspecified_type from PyrexTypes import py_object_type, c_long_type, typecast, error_type, unspecified_type
from Builtin import list_type, tuple_type, set_type, dict_type, unicode_type, bytes_type, type_type from Builtin import list_type, tuple_type, set_type, dict_type, \
unicode_type, str_type, bytes_type, type_type
import Builtin import Builtin
import Symtab import Symtab
import Options import Options
...@@ -821,6 +822,9 @@ class BytesNode(ConstNode): ...@@ -821,6 +822,9 @@ class BytesNode(ConstNode):
if isinstance(sizeof_node, SizeofTypeNode): if isinstance(sizeof_node, SizeofTypeNode):
return sizeof_node.arg_type return sizeof_node.arg_type
def can_coerce_to_char_literal(self):
return len(self.value) == 1
def coerce_to(self, dst_type, env): def coerce_to(self, dst_type, env):
if dst_type == PyrexTypes.c_char_ptr_type: if dst_type == PyrexTypes.c_char_ptr_type:
self.type = PyrexTypes.c_char_ptr_type self.type = PyrexTypes.c_char_ptr_type
...@@ -830,7 +834,7 @@ class BytesNode(ConstNode): ...@@ -830,7 +834,7 @@ class BytesNode(ConstNode):
return CastNode(self, PyrexTypes.c_uchar_ptr_type) return CastNode(self, PyrexTypes.c_uchar_ptr_type)
if dst_type.is_int: if dst_type.is_int:
if len(self.value) > 1: if not self.can_coerce_to_char_literal():
error(self.pos, "Only single-character strings can be coerced into ints.") error(self.pos, "Only single-character strings can be coerced into ints.")
return self return self
return CharNode(self.pos, value=self.value) return CharNode(self.pos, value=self.value)
...@@ -905,11 +909,11 @@ class StringNode(PyConstNode): ...@@ -905,11 +909,11 @@ class StringNode(PyConstNode):
# value BytesLiteral or EncodedString # value BytesLiteral or EncodedString
# is_identifier boolean # is_identifier boolean
type = Builtin.str_type type = str_type
is_identifier = False is_identifier = False
def coerce_to(self, dst_type, env): def coerce_to(self, dst_type, env):
if dst_type is not py_object_type and dst_type is not Builtin.str_type: if dst_type is not py_object_type and dst_type is not str_type:
# if dst_type is Builtin.bytes_type: # if dst_type is Builtin.bytes_type:
# # special case: bytes = 'str literal' # # special case: bytes = 'str literal'
# return BytesNode(self.pos, value=self.value) # return BytesNode(self.pos, value=self.value)
...@@ -927,6 +931,9 @@ class StringNode(PyConstNode): ...@@ -927,6 +931,9 @@ class StringNode(PyConstNode):
return self return self
def can_coerce_to_char_literal(self):
return not self.is_identifier and len(self.value) == 1
def generate_evaluation_code(self, code): def generate_evaluation_code(self, code):
self.result_code = code.get_py_string_const( self.result_code = code.get_py_string_const(
self.value, identifier=self.is_identifier, is_str=True) self.value, identifier=self.is_identifier, is_str=True)
...@@ -2668,7 +2675,7 @@ class GeneralCallNode(CallNode): ...@@ -2668,7 +2675,7 @@ class GeneralCallNode(CallNode):
self.type = error_type self.type = error_type
return error_type return error_type
if hasattr(self.function, 'entry') and not self.function.entry.as_variable: if hasattr(self.function, 'entry') and not self.function.entry.as_variable:
error(self.pos, "Keyword arguments not allowed in cdef functions.") error(self.pos, "Keyword and starred arguments not allowed in cdef functions.")
else: else:
self.function = self.function.coerce_to_pyobject(env) self.function = self.function.coerce_to_pyobject(env)
self.positional_args = \ self.positional_args = \
...@@ -5065,6 +5072,80 @@ class CmpNode(object): ...@@ -5065,6 +5072,80 @@ class CmpNode(object):
result = result and cascade.compile_time_value(operand2, denv) result = result and cascade.compile_time_value(operand2, denv)
return result return result
def find_common_int_type(self, env, op, operand1, operand2):
# type1 != type2 and at least one of the types is not a C int
type1 = operand1.type
type2 = operand2.type
type1_can_be_int = False
type2_can_be_int = False
if isinstance(operand1, (StringNode, BytesNode)) \
and operand1.can_coerce_to_char_literal():
type1_can_be_int = True
if isinstance(operand2, (StringNode, BytesNode)) \
and operand2.can_coerce_to_char_literal():
type2_can_be_int = True
if type1.is_int:
if type2_can_be_int:
return type1
elif type2.is_int:
if type1_can_be_int:
return type2
elif type1_can_be_int:
if type2_can_be_int:
return PyrexTypes.c_uchar_type
return None
def find_common_type(self, env, op, operand1, common_type=None):
operand2 = self.operand2
type1 = operand1.type
type2 = operand2.type
new_common_type = None
if type1 == str_type and (type2.is_string or type2 in (bytes_type, unicode_type)) or \
type2 == str_type and (type1.is_string or type1 in (bytes_type, unicode_type)):
error(self.pos, "Comparisons between bytes/unicode and str are not portable to Python 3")
elif operand1.type.is_complex or operand2.type.is_complex:
if op not in ('==', '!='):
error(self.pos, "complex types unordered")
if operand1.type.is_pyobject:
new_common_type = operand1.type
elif operand2.type.is_pyobject:
new_common_type = operand2.type
else:
new_common_type = PyrexTypes.widest_numeric_type(type1, type2)
elif common_type is None or not common_type.is_pyobject:
if not type1.is_int or not type2.is_int:
new_common_type = self.find_common_int_type(env, op, operand1, operand2)
if new_common_type is None:
new_common_type = PyrexTypes.spanning_type(operand1.type, operand2.type)
if common_type is None:
common_type = new_common_type
else:
# we could do a lot better by splitting the comparison
# into a non-Python part and a Python part, but this is
# safer for now
common_type = PyrexTypes.spanning_type(common_type, new_common_type)
if self.cascade:
common_type = self.cascade.find_common_type(env, self.operator, operand2, common_type)
return common_type
def coerce_operands_to(self, dst_type, env):
operand2 = self.operand2
if operand2.type != dst_type:
self.operand2 = operand2.coerce_to(dst_type, env)
if self.cascade:
self.cascade.coerce_operands_to(dst_type, env)
def is_python_comparison(self): def is_python_comparison(self):
return (self.has_python_operands() return (self.has_python_operands()
or (self.cascade and self.cascade.is_python_comparison()) or (self.cascade and self.cascade.is_python_comparison())
...@@ -5075,13 +5156,7 @@ class CmpNode(object): ...@@ -5075,13 +5156,7 @@ class CmpNode(object):
or (self.cascade and self.cascade.is_python_result())) or (self.cascade and self.cascade.is_python_result()))
def check_types(self, env, operand1, op, operand2): def check_types(self, env, operand1, op, operand2):
if operand1.type.is_complex or operand2.type.is_complex: if not self.types_okay(operand1, op, operand2):
if op not in ('==', '!='):
error(self.pos, "complex types unordered")
common_type = PyrexTypes.widest_numeric_type(operand1.type, operand2.type)
self.operand1 = operand1.coerce_to(common_type, env)
self.operand2 = operand2.coerce_to(common_type, env)
elif not self.types_okay(operand1, op, operand2):
error(self.pos, "Invalid types for '%s' (%s, %s)" % error(self.pos, "Invalid types for '%s' (%s, %s)" %
(self.operator, operand1.type, operand2.type)) (self.operator, operand1.type, operand2.type))
...@@ -5224,12 +5299,14 @@ class PrimaryCmpNode(ExprNode, CmpNode): ...@@ -5224,12 +5299,14 @@ class PrimaryCmpNode(ExprNode, CmpNode):
self.operand1.analyse_types(env) self.operand1.analyse_types(env)
self.operand2.analyse_types(env) self.operand2.analyse_types(env)
if self.cascade: if self.cascade:
self.cascade.analyse_types(env, self.operand2) self.cascade.analyse_types(env)
self.is_pycmp = self.is_python_comparison()
if self.is_pycmp: common_type = self.find_common_type(env, self.operator, self.operand1)
self.coerce_operands_to_pyobjects(env) self.is_pycmp = common_type.is_pyobject
if self.has_int_operands(): if self.operand1.type != common_type:
self.coerce_chars_to_ints(env) self.operand1 = self.operand1.coerce_to(common_type, env)
self.coerce_operands_to(common_type, env)
if self.cascade: if self.cascade:
self.operand2 = self.operand2.coerce_to_simple(env) self.operand2 = self.operand2.coerce_to_simple(env)
self.cascade.coerce_cascaded_operands_to_temp(env) self.cascade.coerce_cascaded_operands_to_temp(env)
...@@ -5260,19 +5337,6 @@ class PrimaryCmpNode(ExprNode, CmpNode): ...@@ -5260,19 +5337,6 @@ class PrimaryCmpNode(ExprNode, CmpNode):
self.operand2 = self.operand2.coerce_to_pyobject(env) self.operand2 = self.operand2.coerce_to_pyobject(env)
if self.cascade: if self.cascade:
self.cascade.coerce_operands_to_pyobjects(env) self.cascade.coerce_operands_to_pyobjects(env)
def has_int_operands(self):
return (self.operand1.type.is_int or self.operand2.type.is_int) \
or (self.cascade and self.cascade.has_int_operands())
def coerce_chars_to_ints(self, env):
# coerce literal single-char strings to c chars
if self.operand1.type.is_string and isinstance(self.operand1, BytesNode):
self.operand1 = self.operand1.coerce_to(PyrexTypes.c_uchar_type, env)
if self.operand2.type.is_string and isinstance(self.operand2, BytesNode):
self.operand2 = self.operand2.coerce_to(PyrexTypes.c_uchar_type, env)
if self.cascade:
self.cascade.coerce_chars_to_ints(env)
def check_const(self): def check_const(self):
self.operand1.check_const() self.operand1.check_const()
...@@ -5353,10 +5417,10 @@ class CascadedCmpNode(Node, CmpNode): ...@@ -5353,10 +5417,10 @@ class CascadedCmpNode(Node, CmpNode):
def type_dependencies(self, env): def type_dependencies(self, env):
return () return ()
def analyse_types(self, env, operand1): def analyse_types(self, env):
self.operand2.analyse_types(env) self.operand2.analyse_types(env)
if self.cascade: if self.cascade:
self.cascade.analyse_types(env, self.operand2) self.cascade.analyse_types(env)
def check_operand_types(self, env, operand1): def check_operand_types(self, env, operand1):
self.check_types(env, self.check_types(env,
...@@ -5372,13 +5436,6 @@ class CascadedCmpNode(Node, CmpNode): ...@@ -5372,13 +5436,6 @@ class CascadedCmpNode(Node, CmpNode):
if self.cascade: if self.cascade:
self.cascade.coerce_operands_to_pyobjects(env) self.cascade.coerce_operands_to_pyobjects(env)
def has_int_operands(self):
return self.operand2.type.is_int
def coerce_chars_to_ints(self, env):
if self.operand2.type.is_string and isinstance(self.operand2, BytesNode):
self.operand2 = self.operand2.coerce_to(PyrexTypes.c_uchar_type, env)
def coerce_cascaded_operands_to_temp(self, env): def coerce_cascaded_operands_to_temp(self, env):
if self.cascade: if self.cascade:
#self.operand2 = self.operand2.coerce_to_temp(env) #CTT #self.operand2 = self.operand2.coerce_to_temp(env) #CTT
......
...@@ -3459,7 +3459,6 @@ class RaiseStatNode(StatNode): ...@@ -3459,7 +3459,6 @@ class RaiseStatNode(StatNode):
self.exc_tb.analyse_types(env) self.exc_tb.analyse_types(env)
self.exc_tb = self.exc_tb.coerce_to_pyobject(env) self.exc_tb = self.exc_tb.coerce_to_pyobject(env)
env.use_utility_code(raise_utility_code) env.use_utility_code(raise_utility_code)
env.use_utility_code(restore_exception_utility_code)
nogil_check = Node.gil_error nogil_check = Node.gil_error
gil_message = "Raising exception" gil_message = "Raising exception"
...@@ -3506,7 +3505,6 @@ class ReraiseStatNode(StatNode): ...@@ -3506,7 +3505,6 @@ class ReraiseStatNode(StatNode):
child_attrs = [] child_attrs = []
def analyse_expressions(self, env): def analyse_expressions(self, env):
env.use_utility_code(raise_utility_code)
env.use_utility_code(restore_exception_utility_code) env.use_utility_code(restore_exception_utility_code)
nogil_check = Node.gil_error nogil_check = Node.gil_error
...@@ -3515,7 +3513,12 @@ class ReraiseStatNode(StatNode): ...@@ -3515,7 +3513,12 @@ class ReraiseStatNode(StatNode):
def generate_execution_code(self, code): def generate_execution_code(self, code):
vars = code.funcstate.exc_vars vars = code.funcstate.exc_vars
if vars: if vars:
code.putln("__Pyx_Raise(%s, %s, %s);" % tuple(vars)) for varname in vars:
code.put_giveref(varname)
code.putln("__Pyx_ErrRestore(%s, %s, %s);" % tuple(vars))
for varname in vars:
code.put("%s = 0; " % varname)
code.putln()
code.putln(code.error_goto(self.pos)) code.putln(code.error_goto(self.pos))
else: else:
error(self.pos, "Reraise not inside except clause") error(self.pos, "Reraise not inside except clause")
...@@ -4125,8 +4128,9 @@ class TryExceptStatNode(StatNode): ...@@ -4125,8 +4128,9 @@ class TryExceptStatNode(StatNode):
code.put_goto(try_end_label) code.put_goto(try_end_label)
if code.label_used(try_return_label): if code.label_used(try_return_label):
code.put_label(try_return_label) code.put_label(try_return_label)
for var in Naming.exc_save_vars: for var in Naming.exc_save_vars: code.put_xgiveref(var)
code.put_xdecref_clear(var, py_object_type) code.putln("__Pyx_ExceptionReset(%s);" %
', '.join(Naming.exc_save_vars))
code.put_goto(old_return_label) code.put_goto(old_return_label)
code.put_label(our_error_label) code.put_label(our_error_label)
for temp_name, type in temps_to_clean_up: for temp_name, type in temps_to_clean_up:
...@@ -4920,13 +4924,57 @@ requires=[printing_utility_code]) ...@@ -4920,13 +4924,57 @@ requires=[printing_utility_code])
#------------------------------------------------------------------------------------ #------------------------------------------------------------------------------------
# The following function is based on do_raise() from ceval.c. # Exception raising code
#
# Exceptions are raised by __Pyx_Raise() and stored as plain
# type/value/tb in PyThreadState->curexc_*. When being caught by an
# 'except' statement, curexc_* is moved over to exc_* by
# __Pyx_GetException()
restore_exception_utility_code = UtilityCode(
proto = """
static INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
static INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
""",
impl = """
static INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb) {
PyObject *tmp_type, *tmp_value, *tmp_tb;
PyThreadState *tstate = PyThreadState_GET();
tmp_type = tstate->curexc_type;
tmp_value = tstate->curexc_value;
tmp_tb = tstate->curexc_traceback;
tstate->curexc_type = type;
tstate->curexc_value = value;
tstate->curexc_traceback = tb;
Py_XDECREF(tmp_type);
Py_XDECREF(tmp_value);
Py_XDECREF(tmp_tb);
}
static INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb) {
PyThreadState *tstate = PyThreadState_GET();
*type = tstate->curexc_type;
*value = tstate->curexc_value;
*tb = tstate->curexc_traceback;
tstate->curexc_type = 0;
tstate->curexc_value = 0;
tstate->curexc_traceback = 0;
}
""")
# The following function is based on do_raise() from ceval.c. There
# are separate versions for Python2 and Python3 as exception handling
# has changed quite a lot between the two versions.
raise_utility_code = UtilityCode( raise_utility_code = UtilityCode(
proto = """ proto = """
static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb); /*proto*/ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
""", """,
impl = """ impl = """
#if PY_MAJOR_VERSION < 3
static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb) { static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb) {
Py_XINCREF(type); Py_XINCREF(type);
Py_XINCREF(value); Py_XINCREF(value);
...@@ -4982,6 +5030,7 @@ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb) { ...@@ -4982,6 +5030,7 @@ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb) {
} }
#endif #endif
} }
__Pyx_ErrRestore(type, value, tb); __Pyx_ErrRestore(type, value, tb);
return; return;
raise_error: raise_error:
...@@ -4990,6 +5039,166 @@ raise_error: ...@@ -4990,6 +5039,166 @@ raise_error:
Py_XDECREF(tb); Py_XDECREF(tb);
return; return;
} }
#else // Python 3+
static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb) {
if (tb == Py_None) {
tb = 0;
} else if (tb && !PyTraceBack_Check(tb)) {
PyErr_SetString(PyExc_TypeError,
"raise: arg 3 must be a traceback or None");
goto bad;
}
if (value == Py_None)
value = 0;
if (PyExceptionInstance_Check(type)) {
if (value) {
PyErr_SetString(PyExc_TypeError,
"instance exception may not have a separate value");
goto bad;
}
value = type;
type = (PyObject*) Py_TYPE(value);
} else if (!PyExceptionClass_Check(type)) {
PyErr_SetString(PyExc_TypeError,
"raise: exception class must be a subclass of BaseException");
goto bad;
}
PyErr_SetObject(type, value);
if (tb) {
PyThreadState *tstate = PyThreadState_GET();
PyObject* tmp_tb = tstate->curexc_traceback;
if (tb != tmp_tb) {
Py_INCREF(tb);
tstate->curexc_traceback = tb;
Py_XDECREF(tmp_tb);
}
}
bad:
return;
}
#endif
""",
requires=[restore_exception_utility_code])
#------------------------------------------------------------------------------------
get_exception_utility_code = UtilityCode(
proto = """
static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
""",
impl = """
static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb) {
PyObject *local_type, *local_value, *local_tb;
PyObject *tmp_type, *tmp_value, *tmp_tb;
PyThreadState *tstate = PyThreadState_GET();
local_type = tstate->curexc_type;
local_value = tstate->curexc_value;
local_tb = tstate->curexc_traceback;
tstate->curexc_type = 0;
tstate->curexc_value = 0;
tstate->curexc_traceback = 0;
PyErr_NormalizeException(&local_type, &local_value, &local_tb);
if (unlikely(tstate->curexc_type))
goto bad;
#if PY_MAJOR_VERSION >= 3
if (unlikely(PyException_SetTraceback(local_value, local_tb) < 0))
goto bad;
#endif
*type = local_type;
*value = local_value;
*tb = local_tb;
Py_INCREF(local_type);
Py_INCREF(local_value);
Py_INCREF(local_tb);
tmp_type = tstate->exc_type;
tmp_value = tstate->exc_value;
tmp_tb = tstate->exc_traceback;
tstate->exc_type = local_type;
tstate->exc_value = local_value;
tstate->exc_traceback = local_tb;
/* Make sure tstate is in a consistent state when we XDECREF
these objects (XDECREF may run arbitrary code). */
Py_XDECREF(tmp_type);
Py_XDECREF(tmp_value);
Py_XDECREF(tmp_tb);
return 0;
bad:
*type = 0;
*value = 0;
*tb = 0;
Py_XDECREF(local_type);
Py_XDECREF(local_value);
Py_XDECREF(local_tb);
return -1;
}
""")
#------------------------------------------------------------------------------------
get_exception_tuple_utility_code = UtilityCode(proto="""
static PyObject *__Pyx_GetExceptionTuple(void); /*proto*/
""",
# I doubt that calling __Pyx_GetException() here is correct as it moves
# the exception from tstate->curexc_* to tstate->exc_*, which prevents
# exception handlers later on from receiving it.
impl = """
static PyObject *__Pyx_GetExceptionTuple(void) {
PyObject *type = NULL, *value = NULL, *tb = NULL;
if (__Pyx_GetException(&type, &value, &tb) == 0) {
PyObject* exc_info = PyTuple_New(3);
if (exc_info) {
Py_INCREF(type);
Py_INCREF(value);
Py_INCREF(tb);
PyTuple_SET_ITEM(exc_info, 0, type);
PyTuple_SET_ITEM(exc_info, 1, value);
PyTuple_SET_ITEM(exc_info, 2, tb);
return exc_info;
}
}
return NULL;
}
""",
requires=[get_exception_utility_code])
#------------------------------------------------------------------------------------
reset_exception_utility_code = UtilityCode(
proto = """
static INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
""",
impl = """
static INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb) {
PyThreadState *tstate = PyThreadState_GET();
*type = tstate->exc_type;
*value = tstate->exc_value;
*tb = tstate->exc_traceback;
Py_XINCREF(*type);
Py_XINCREF(*value);
Py_XINCREF(*tb);
}
static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb) {
PyObject *tmp_type, *tmp_value, *tmp_tb;
PyThreadState *tstate = PyThreadState_GET();
tmp_type = tstate->exc_type;
tmp_value = tstate->exc_value;
tmp_tb = tstate->exc_traceback;
tstate->exc_type = type;
tstate->exc_value = value;
tstate->exc_traceback = tb;
Py_XDECREF(tmp_type);
Py_XDECREF(tmp_value);
Py_XDECREF(tmp_tb);
}
""") """)
#------------------------------------------------------------------------------------ #------------------------------------------------------------------------------------
...@@ -5339,57 +5548,6 @@ bad: ...@@ -5339,57 +5548,6 @@ bad:
'EMPTY_BYTES' : Naming.empty_bytes, 'EMPTY_BYTES' : Naming.empty_bytes,
}) })
restore_exception_utility_code = UtilityCode(
proto = """
static INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
static INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
""",
impl = """
static INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb) {
PyObject *tmp_type, *tmp_value, *tmp_tb;
PyThreadState *tstate = PyThreadState_GET();
#if PY_MAJOR_VERSION >= 3
/* Note: this is a temporary work-around to prevent crashes in Python 3.0 */
if ((tstate->exc_type != NULL) & (tstate->exc_type != Py_None)) {
tmp_type = tstate->exc_type;
tmp_value = tstate->exc_value;
tmp_tb = tstate->exc_traceback;
PyErr_NormalizeException(&type, &value, &tb);
PyErr_NormalizeException(&tmp_type, &tmp_value, &tmp_tb);
tstate->exc_type = 0;
tstate->exc_value = 0;
tstate->exc_traceback = 0;
PyException_SetContext(value, tmp_value);
Py_DECREF(tmp_type);
Py_XDECREF(tmp_tb);
}
#endif
tmp_type = tstate->curexc_type;
tmp_value = tstate->curexc_value;
tmp_tb = tstate->curexc_traceback;
tstate->curexc_type = type;
tstate->curexc_value = value;
tstate->curexc_traceback = tb;
Py_XDECREF(tmp_type);
Py_XDECREF(tmp_value);
Py_XDECREF(tmp_tb);
}
static INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb) {
PyThreadState *tstate = PyThreadState_GET();
*type = tstate->curexc_type;
*value = tstate->curexc_value;
*tb = tstate->curexc_traceback;
tstate->curexc_type = 0;
tstate->curexc_value = 0;
tstate->curexc_traceback = 0;
}
""")
#------------------------------------------------------------------------------------ #------------------------------------------------------------------------------------
unraisable_exception_utility_code = UtilityCode( unraisable_exception_utility_code = UtilityCode(
...@@ -5508,107 +5666,6 @@ static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) { ...@@ -5508,107 +5666,6 @@ static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) {
#------------------------------------------------------------------------------------ #------------------------------------------------------------------------------------
get_exception_utility_code = UtilityCode(
proto = """
static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
""",
impl = """
static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb) {
PyObject *tmp_type, *tmp_value, *tmp_tb;
PyThreadState *tstate = PyThreadState_GET();
*type = tstate->curexc_type;
*value = tstate->curexc_value;
*tb = tstate->curexc_traceback;
tstate->curexc_type = 0;
tstate->curexc_value = 0;
tstate->curexc_traceback = 0;
PyErr_NormalizeException(type, value, tb);
if (PyErr_Occurred())
goto bad;
Py_INCREF(*type);
Py_INCREF(*value);
Py_INCREF(*tb);
tmp_type = tstate->exc_type;
tmp_value = tstate->exc_value;
tmp_tb = tstate->exc_traceback;
tstate->exc_type = *type;
tstate->exc_value = *value;
tstate->exc_traceback = *tb;
/* Make sure tstate is in a consistent state when we XDECREF
these objects (XDECREF may run arbitrary code). */
Py_XDECREF(tmp_type);
Py_XDECREF(tmp_value);
Py_XDECREF(tmp_tb);
return 0;
bad:
Py_XDECREF(*type);
Py_XDECREF(*value);
Py_XDECREF(*tb);
return -1;
}
""")
#------------------------------------------------------------------------------------
get_exception_tuple_utility_code = UtilityCode(proto="""
static PyObject *__Pyx_GetExceptionTuple(void); /*proto*/
""",
impl = """
static PyObject *__Pyx_GetExceptionTuple(void) {
PyObject *type = NULL, *value = NULL, *tb = NULL;
if (__Pyx_GetException(&type, &value, &tb) == 0) {
PyObject* exc_info = PyTuple_New(3);
if (exc_info) {
Py_INCREF(type);
Py_INCREF(value);
Py_INCREF(tb);
PyTuple_SET_ITEM(exc_info, 0, type);
PyTuple_SET_ITEM(exc_info, 1, value);
PyTuple_SET_ITEM(exc_info, 2, tb);
return exc_info;
}
}
return NULL;
}
""",
requires=[get_exception_utility_code])
#------------------------------------------------------------------------------------
reset_exception_utility_code = UtilityCode(
proto = """
static INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
""",
impl = """
static INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb) {
PyThreadState *tstate = PyThreadState_GET();
*type = tstate->exc_type;
*value = tstate->exc_value;
*tb = tstate->exc_traceback;
Py_XINCREF(*type);
Py_XINCREF(*value);
Py_XINCREF(*tb);
}
static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb) {
PyObject *tmp_type, *tmp_value, *tmp_tb;
PyThreadState *tstate = PyThreadState_GET();
tmp_type = tstate->exc_type;
tmp_value = tstate->exc_value;
tmp_tb = tstate->exc_traceback;
tstate->exc_type = type;
tstate->exc_value = value;
tstate->exc_traceback = tb;
Py_XDECREF(tmp_type);
Py_XDECREF(tmp_value);
Py_XDECREF(tmp_tb);
}
""")
#------------------------------------------------------------------------------------
force_init_threads_utility_code = UtilityCode( force_init_threads_utility_code = UtilityCode(
proto=""" proto="""
#ifndef __PYX_FORCE_INIT_THREADS #ifndef __PYX_FORCE_INIT_THREADS
......
...@@ -9,6 +9,7 @@ import os ...@@ -9,6 +9,7 @@ import os
import platform import platform
import stat import stat
import sys import sys
import codecs
from time import time from time import time
import cython import cython
...@@ -279,8 +280,12 @@ class FileSourceDescriptor(SourceDescriptor): ...@@ -279,8 +280,12 @@ class FileSourceDescriptor(SourceDescriptor):
self.filename = filename self.filename = filename
self._cmp_name = filename self._cmp_name = filename
def get_lines(self): def get_lines(self, encoding=None, error_handling=None):
return Utils.open_source_file(self.filename) if not encoding:
return Utils.open_source_file(self.filename)
else:
return codecs.open(self.filename, "rU", encoding=encoding,
errors=error_handling)
def get_description(self): def get_description(self):
return self.filename return self.filename
...@@ -307,9 +312,13 @@ class StringSourceDescriptor(SourceDescriptor): ...@@ -307,9 +312,13 @@ class StringSourceDescriptor(SourceDescriptor):
self.codelines = [x + "\n" for x in code.split("\n")] self.codelines = [x + "\n" for x in code.split("\n")]
self._cmp_name = name self._cmp_name = name
def get_lines(self): def get_lines(self, encoding=None, error_handling=None):
return self.codelines if not encoding:
return self.codelines
else:
return [ line.encode(encoding, error_handling).decode(encoding)
for line in self.codelines ]
def get_description(self): def get_description(self):
return self.name return self.name
......
...@@ -25,23 +25,85 @@ cdef extern from "Python.h": ...@@ -25,23 +25,85 @@ cdef extern from "Python.h":
PyBUF_WRITE, PyBUF_WRITE,
PyBUF_SHADOW PyBUF_SHADOW
int PyObject_CheckBuffer(object obj) bint PyObject_CheckBuffer(object obj)
int PyObject_GetBuffer(object obj, Py_buffer *view, int flags) # Return 1 if obj supports the buffer interface otherwise 0.
void PyObject_ReleaseBuffer(object obj, Py_buffer *view)
int PyObject_GetBuffer(object obj, Py_buffer *view, int flags) except -1
# Export obj into a Py_buffer, view. These arguments must never be
# NULL. The flags argument is a bit field indicating what kind of
# buffer the caller is prepared to deal with and therefore what
# kind of buffer the exporter is allowed to return. The buffer
# interface allows for complicated memory sharing possibilities,
# but some caller may not be able to handle all the complexity but
# may want to see if the exporter will let them take a simpler
# view to its memory.
# Some exporters may not be able to share memory in every possible
# way and may need to raise errors to signal to some consumers
# that something is just not possible. These errors should be a
# BufferError unless there is another error that is actually
# causing the problem. The exporter can use flags information to
# simplify how much of the Py_buffer structure is filled in with
# non-default values and/or raise an error if the object can’t
# support a simpler view of its memory.
# 0 is returned on success and -1 on error.
void PyBuffer_Release(object obj, object view)
# Release the buffer view over obj. This should be called when the
# buffer is no longer being used as it may free memory from it.
void* PyBuffer_GetPointer(Py_buffer *view, Py_ssize_t *indices) void* PyBuffer_GetPointer(Py_buffer *view, Py_ssize_t *indices)
# ??
int PyBuffer_SizeFromFormat(char *) # actually const char int PyBuffer_SizeFromFormat(char *) # actually const char
# Return the implied ~Py_buffer.itemsize from the struct-stype
# ~Py_buffer.format
int PyBuffer_ToContiguous(void *buf, Py_buffer *view, Py_ssize_t len, char fort) int PyBuffer_ToContiguous(void *buf, Py_buffer *view, Py_ssize_t len, char fort)
# ??
int PyBuffer_FromContiguous(Py_buffer *view, void *buf, Py_ssize_t len, char fort) int PyBuffer_FromContiguous(Py_buffer *view, void *buf, Py_ssize_t len, char fort)
# ??
int PyObject_CopyToObject(object obj, void *buf, Py_ssize_t len, char fortran) except -1
# Copy len bytes of data pointed to by the contiguous chunk of
# memory pointed to by buf into the buffer exported by obj. The
# buffer must of course be writable. Return 0 on success and
# return -1 and raise an error on failure. If the object does not
# have a writable buffer, then an error is raised. If fortran is
# 'F', then if the object is multi-dimensional, then the data will
# be copied into the array in Fortran-style (first dimension
# varies the fastest). If fortran is 'C', then the data will be
# copied into the array in C-style (last dimension varies the
# fastest). If fortran is 'A', then it does not matter and the
# copy will be made in whatever way is more efficient.
int PyObject_CopyData(object dest, object src) int PyObject_CopyData(object dest, object src)
int PyBuffer_IsContiguous(Py_buffer *view, char fort) # Copy the data from the src buffer to the buffer of destination
bint PyBuffer_IsContiguous(Py_buffer *view, char fort)
# Return 1 if the memory defined by the view is C-style (fortran
# is 'C') or Fortran-style (fortran is 'F') contiguous or either
# one (fortran is 'A'). Return 0 otherwise.
void PyBuffer_FillContiguousStrides(int ndims, void PyBuffer_FillContiguousStrides(int ndims,
Py_ssize_t *shape, Py_ssize_t *shape,
Py_ssize_t *strides, Py_ssize_t *strides,
int itemsize, int itemsize,
char fort) char fort)
# Fill the strides array with byte-strides of a contiguous
# (Fortran-style if fort is 'F' or C-style otherwise) array of the
# given shape with the given number of bytes per element.
int PyBuffer_FillInfo(Py_buffer *view, void *buf, int PyBuffer_FillInfo(Py_buffer *view, void *buf,
Py_ssize_t len, int readonly, Py_ssize_t len, int readonly,
int flags) int flags) except -1
# Fill in a buffer-info structure, view, correctly for an exporter
# that can only share a contiguous chunk of memory of “unsigned
# bytes” of the given length. Return 0 on success and -1 (with
# raising an error) on error.
object PyObject_Format(object obj, object PyObject_Format(object obj, object format_spec)
object format_spec) # Takes an arbitrary object and returns the result of calling
# obj.__format__(format_spec).
...@@ -5,7 +5,6 @@ methodmangling_T5 ...@@ -5,7 +5,6 @@ methodmangling_T5
class_attribute_init_values_T18 class_attribute_init_values_T18
numpy_ValueError_T172 numpy_ValueError_T172
unsignedbehaviour_T184 unsignedbehaviour_T184
funcexc_iter_T228
bad_c_struct_T252 bad_c_struct_T252
missing_baseclass_in_predecl_T262 missing_baseclass_in_predecl_T262
extended_unpacking_T409 extended_unpacking_T409
...@@ -14,6 +14,6 @@ a.some_method(1, 2) ...@@ -14,6 +14,6 @@ a.some_method(1, 2)
a.some_method(1, y=2) a.some_method(1, y=2)
_ERRORS = u""" _ERRORS = u"""
9:13: Keyword arguments not allowed in cdef functions. 9:13: Keyword and starred arguments not allowed in cdef functions.
14:13: Keyword arguments not allowed in cdef functions. 14:13: Keyword and starred arguments not allowed in cdef functions.
""" """
...@@ -116,9 +116,7 @@ _ERRORS = u""" ...@@ -116,9 +116,7 @@ _ERRORS = u"""
39: 9: Constructing Python tuple not allowed without gil 39: 9: Constructing Python tuple not allowed without gil
40: 8: Constructing Python list not allowed without gil 40: 8: Constructing Python list not allowed without gil
41: 8: Constructing Python dict not allowed without gil 41: 8: Constructing Python dict not allowed without gil
42:12: Creating temporary Python reference not allowed without gil
42:12: Truth-testing Python object not allowed without gil 42:12: Truth-testing Python object not allowed without gil
42:17: Creating temporary Python reference not allowed without gil
43:13: Python type test not allowed without gil 43:13: Python type test not allowed without gil
45:10: Operation not allowed without gil 45:10: Operation not allowed without gil
46:8: Operation not allowed without gil 46:8: Operation not allowed without gil
......
__doc__ = u""" __doc__ = u"""
__getattribute__ and __getattr__ special methods for a single class. __getattribute__ and __getattr__ special methods for a single class.
"""
cdef class just_getattribute:
"""
>>> a = just_getattribute() >>> a = just_getattribute()
>>> a.bar >>> a.bar
'bar' 'bar'
>>> a.invalid >>> a.invalid
Traceback (most recent call last): Traceback (most recent call last):
AttributeError AttributeError
"""
def __getattribute__(self,n):
if n == 'bar':
return n
else:
raise AttributeError
cdef class just_getattr:
"""
>>> a = just_getattr() >>> a = just_getattr()
>>> a.foo >>> a.foo
10 10
...@@ -16,25 +27,7 @@ __getattribute__ and __getattr__ special methods for a single class. ...@@ -16,25 +27,7 @@ __getattribute__ and __getattr__ special methods for a single class.
>>> a.invalid >>> a.invalid
Traceback (most recent call last): Traceback (most recent call last):
AttributeError AttributeError
"""
>>> a = both()
>>> a.foo
10
>>> a.bar
'bar'
>>> a.invalid
Traceback (most recent call last):
AttributeError
"""
cdef class just_getattribute:
def __getattribute__(self,n):
if n == 'bar':
return n
else:
raise AttributeError
cdef class just_getattr:
cdef readonly int foo cdef readonly int foo
def __init__(self): def __init__(self):
self.foo = 10 self.foo = 10
...@@ -45,6 +38,16 @@ cdef class just_getattr: ...@@ -45,6 +38,16 @@ cdef class just_getattr:
raise AttributeError raise AttributeError
cdef class both: cdef class both:
"""
>>> a = both()
>>> a.foo
10
>>> a.bar
'bar'
>>> a.invalid
Traceback (most recent call last):
AttributeError
"""
cdef readonly int foo cdef readonly int foo
def __init__(self): def __init__(self):
self.foo = 10 self.foo = 10
......
__doc__ = u"""
>>> test_int(0)
False
>>> test_int(1)
True
>>> test_short(0)
False
>>> test_short(1)
True
>>> test_Py_ssize_t(0)
False
>>> test_Py_ssize_t(1)
True
>>> test_ptr()
False
>>> test_ptr2()
2
>>> test_attr_int(TestExtInt(0))
False
>>> test_attr_int(TestExtInt(1))
True
>>> test_attr_ptr(TestExtPtr(0))
False
>>> test_attr_ptr(TestExtPtr(1))
True
"""
def test_ptr():
cdef void* p = NULL
if p:
return True
else:
return False
def test_ptr2():
cdef char* p1 = NULL
cdef char* p2 = NULL
p1 += 1
if p1 and p2:
return 1
elif p1 or p2:
return 2
else:
return 3
def test_int(int i):
if i:
return True
else:
return False
def test_short(short i):
if i:
return True
else:
return False
def test_Py_ssize_t(Py_ssize_t i):
if i:
return True
else:
return False
cdef class TestExtInt:
cdef int i
def __init__(self, i): self.i = i
def test_attr_int(TestExtInt e):
if e.i:
return True
else:
return False
cdef class TestExtPtr:
cdef void* p
def __init__(self, int i): self.p = <void*>i
def test_attr_ptr(TestExtPtr e):
if e.p:
return True
else:
return False
...@@ -137,10 +137,6 @@ __doc__ = ur""" ...@@ -137,10 +137,6 @@ __doc__ = ur"""
""" """
import sys
if sys.version_info[0] >= 3:
__doc__ = __doc__.replace(u"u'spam'", u"'spam'")
cdef class Ext: cdef class Ext:
def __init__(self, a, b, c=None): def __init__(self, a, b, c=None):
......
__doc__ = u""" __doc__ = u"""
>>> test_modify() >>> test_modify()
0 1 2 3 4 0
1
2
3
4
<BLANKLINE>
(4, 0) (4, 0)
>>> test_fix() >>> test_fix()
0 1 2 3 4 0
1
2
3
4
<BLANKLINE>
4 4
>>> test_break() >>> test_break()
0 1 2 0
1
2
<BLANKLINE>
(2, 0) (2, 0)
>>> test_return() >>> test_return()
0 1 2 0
1
2
(2, 0) (2, 0)
""" """
...@@ -20,7 +35,7 @@ cimport cython ...@@ -20,7 +35,7 @@ cimport cython
def test_modify(): def test_modify():
cdef int i, n = 5 cdef int i, n = 5
for i in range(n): for i in range(n):
print i, print i
n = 0 n = 0
print print
return i,n return i,n
...@@ -30,7 +45,7 @@ def test_modify(): ...@@ -30,7 +45,7 @@ def test_modify():
def test_fix(): def test_fix():
cdef int i cdef int i
for i in range(5): for i in range(5):
print i, print i
print print
return i return i
...@@ -39,10 +54,12 @@ def test_fix(): ...@@ -39,10 +54,12 @@ def test_fix():
def test_break(): def test_break():
cdef int i, n = 5 cdef int i, n = 5
for i in range(n): for i in range(n):
print i, print i
n = 0 n = 0
if i == 2: if i == 2:
break break
else:
print "FAILED!"
print print
return i,n return i,n
...@@ -51,7 +68,7 @@ def test_break(): ...@@ -51,7 +68,7 @@ def test_break():
def test_return(): def test_return():
cdef int i, n = 5 cdef int i, n = 5
for i in range(n): for i in range(n):
print i, print i
n = 0 n = 0
if i == 2: if i == 2:
return i,n return i,n
......
...@@ -45,6 +45,8 @@ True ...@@ -45,6 +45,8 @@ True
""" """
import sys import sys
if sys.version_info[0] < 3:
sys.exc_clear()
cdef class cy_iterator(object): cdef class cy_iterator(object):
def __iter__(self): def __iter__(self):
......
...@@ -11,6 +11,8 @@ __doc__ = u""" ...@@ -11,6 +11,8 @@ __doc__ = u"""
""" """
import sys import sys
if sys.version_info[0] < 3:
sys.exc_clear()
def foo(): def foo():
try: try:
......
import sys
def reraise(f, exc):
"""
>>> def f(exc): raise exc
>>> reraise(f, TypeError)
Traceback (most recent call last):
TypeError
>>> def f(exc): raise exc('hiho')
>>> reraise(f, TypeError)
Traceback (most recent call last):
TypeError: hiho
"""
try:
f(exc)
except:
assert sys.exc_info()[0] is exc, str(sys.exc_info()[1])
raise
def reraise_original(f, exc, raise_catch):
"""
>>> def f(exc): raise exc
>>> def raise_catch_py():
... try: raise ValueError
... except: pass
>>> reraise_original(f, TypeError, raise_catch_py)
Traceback (most recent call last):
TypeError
>>> reraise_original(f, TypeError, raise_catch_cy)
Traceback (most recent call last):
TypeError
>>> reraise_original(f, TypeError, raise_catch_cy_non_empty)
Traceback (most recent call last):
TypeError
"""
try:
f(exc)
except:
raise_catch()
assert sys.exc_info()[0] is exc, str(sys.exc_info()[1])
raise
def raise_catch_cy():
try: raise ValueError
except: pass
def raise_catch_cy_non_empty():
try: raise ValueError
except:
a = 1+1
__doc__ = u""" __doc__ = u"""
>>> py_x = br'\\\\' >>> b == br'\\\\'
>>> assert x == py_x True
>>> s == r'\\\\'
True
>>> u == ur'\\\\'
True
""" """
import sys import sys
if sys.version_info[0] < 3: if sys.version_info[0] < 3:
__doc__ = __doc__.replace(u" br'", u" r'") __doc__ = __doc__.replace(u" br'", u" r'")
else:
__doc__ = __doc__.replace(u" ur'", u" r'")
x = r'\\' b = br'\\'
s = r'\\'
u = ur'\\'
__doc__ = u""" __doc__ = u"""
>>> x = X() >>> x = X()
>>> x.slots >>> x.slots
[b''] ['']
""" """
import sys
if sys.version_info[0] < 3:
__doc__ = __doc__.replace(u"b'", u"'")
class X: class X:
slots = ["", ] slots = ["", ]
__doc__ = u""" __doc__ = u"""
>>> test_str(1) >>> test_str(1)
b'b' 'b'
>>> test_unicode_ascii(2) >>> test_unicode_ascii(2)
u'c' u'c'
...@@ -10,14 +10,14 @@ __doc__ = u""" ...@@ -10,14 +10,14 @@ __doc__ = u"""
>>> test_int_list(2) >>> test_int_list(2)
3 3
>>> test_str_list(1) >>> test_str_list(1)
b'bcd' 'bcd'
>>> test_int_tuple(2) >>> test_int_tuple(2)
3 3
>>> test_str_tuple(0) >>> test_str_tuple(0)
b'a' 'a'
>>> test_mix_tuple(1) >>> test_mix_tuple(1)
b'abc' 'abc'
>>> test_mix_tuple(0) >>> test_mix_tuple(0)
1 1
""" """
...@@ -30,10 +30,7 @@ else: ...@@ -30,10 +30,7 @@ else:
__doc__ = __doc__.replace(u" b'", u" '") __doc__ = __doc__.replace(u" b'", u" '")
def test_str(n): def test_str(n):
if IS_PY3: return "abcd"[n]
return bytes(["abcd"[n]])
else:
return "abcd"[n]
def test_unicode_ascii(n): def test_unicode_ascii(n):
return u"abcd"[n] return u"abcd"[n]
......
__doc__ = """# disabled in Py3
import sys
if sys.version_info[0] < 3:
__doc__ = u"""
>>> test(0) >>> test(0)
0L 0L
>>> test(1) >>> test(1)
1L 1L
>>> import sys
>>> sys.maxint + 1 > sys.maxint >>> sys.maxint + 1 > sys.maxint
True True
>>> type(sys.maxint * 2 + 1) is long >>> type(sys.maxint * 2 + 1) is long
...@@ -19,7 +22,16 @@ __doc__ = """# disabled in Py3 ...@@ -19,7 +22,16 @@ __doc__ = """# disabled in Py3
True True
>>> test(256 ** unsigned_long_size() - 1) > sys.maxint >>> test(256 ** unsigned_long_size() - 1) > sys.maxint
True True
""" """
else:
__doc__ = u"""
>>> test(0)
0
>>> test(1)
1
>>> test(256 ** unsigned_long_size() - 1) > 0
True
"""
def test(k): def test(k):
cdef unsigned long m cdef unsigned long m
......
__doc__ = u"""
>>> test_eq()
True
True
True
True
>>> test_cascaded_eq()
True
True
True
True
True
True
True
True
>>> test_cascaded_ineq()
True
True
True
True
True
True
True
True
>>> test_long_ineq()
True
>>> test_long_ineq_py()
True
True
"""
cdef int i = 'x'
cdef char c = 'x'
cdef char* s = 'x'
def test_eq():
print i == 'x'
print i == c'x'
print c == 'x'
print c == c'x'
# print s == 'x' # error
# print s == c'x' # error
def test_cascaded_eq():
print 'x' == i == 'x'
print 'x' == i == c'x'
print c'x' == i == 'x'
print c'x' == i == c'x'
print 'x' == c == 'x'
print 'x' == c == c'x'
print c'x' == c == 'x'
print c'x' == c == c'x'
def test_cascaded_ineq():
print 'a' <= i <= 'z'
print 'a' <= i <= c'z'
print c'a' <= i <= 'z'
print c'a' <= i <= c'z'
print 'a' <= c <= 'z'
print 'a' <= c <= c'z'
print c'a' <= c <= 'z'
print c'a' <= c <= c'z'
def test_long_ineq():
print 'a' < 'b' < 'c' < 'd' < c < 'y' < 'z'
def test_long_ineq_py():
print 'abcdef' < 'b' < 'c' < 'd' < 'y' < 'z'
print 'a' < 'b' < 'cde' < 'd' < 'y' < 'z'
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
__doc__ = r""" __doc__ = br"""
>>> sa >>> sa
b'abc' 'abc'
>>> ua >>> ua
u'abc' u'abc'
>>> b >>> b
...@@ -19,7 +19,7 @@ __doc__ = r""" ...@@ -19,7 +19,7 @@ __doc__ = r"""
u'S\xf8k ik\xfc\xd6\xe4abc' u'S\xf8k ik\xfc\xd6\xe4abc'
>>> null >>> null
u'\x00' u'\x00'
""".decode(u"ASCII") + """ """.decode("ASCII") + b"""
>>> len(sa) >>> len(sa)
3 3
>>> len(ua) >>> len(ua)
...@@ -38,7 +38,7 @@ __doc__ = r""" ...@@ -38,7 +38,7 @@ __doc__ = r"""
12 12
>>> len(null) >>> len(null)
1 1
""".decode(u"ASCII") + u""" """.decode("ASCII") + u"""
>>> ua == u'abc' >>> ua == u'abc'
True True
>>> b == u'123' >>> b == u'123'
......
...@@ -6,9 +6,9 @@ ...@@ -6,9 +6,9 @@
# This file is written in UTF-8, but it has no encoding declaration, # This file is written in UTF-8, but it has no encoding declaration,
# so it just defaults to UTF-8 (PEP 3120). # so it just defaults to UTF-8 (PEP 3120).
__doc__ = r""" __doc__ = br"""
>>> sa >>> sa
b'abc' 'abc'
>>> ua >>> ua
u'abc' u'abc'
>>> b >>> b
...@@ -25,7 +25,7 @@ __doc__ = r""" ...@@ -25,7 +25,7 @@ __doc__ = r"""
u'S\xf8k ik\xfc\xd6\xe4abc' u'S\xf8k ik\xfc\xd6\xe4abc'
>>> null >>> null
u'\x00' u'\x00'
""".decode(u"ASCII") + """ """.decode("ASCII") + b"""
>>> len(sa) >>> len(sa)
3 3
>>> len(ua) >>> len(ua)
...@@ -44,7 +44,7 @@ __doc__ = r""" ...@@ -44,7 +44,7 @@ __doc__ = r"""
12 12
>>> len(null) >>> len(null)
1 1
""".decode(u"ASCII") + u""" """.decode("ASCII") + u"""
>>> ua == u'abc' >>> ua == u'abc'
True True
>>> b == u'123' >>> b == u'123'
......
# -*- coding: latin-1 -*- # -*- coding: latin-1 -*-
__doc__ = r""" __doc__ = br"""
>>> sa >>> sa
b'abc' 'abc'
>>> ua >>> ua
u'abc' u'abc'
>>> b >>> b
...@@ -19,7 +19,7 @@ __doc__ = r""" ...@@ -19,7 +19,7 @@ __doc__ = r"""
u'S\xf8k ik\xfc\xd6\xe4abc' u'S\xf8k ik\xfc\xd6\xe4abc'
>>> null >>> null
u'\x00' u'\x00'
""".decode(u"ASCII") + """ """.decode("ASCII") + b"""
>>> len(sa) >>> len(sa)
3 3
>>> len(ua) >>> len(ua)
...@@ -38,7 +38,7 @@ __doc__ = r""" ...@@ -38,7 +38,7 @@ __doc__ = r"""
12 12
>>> len(null) >>> len(null)
1 1
""".decode(u"ASCII") + u""" """.decode("ASCII") + u"""
>>> ua == u'abc' >>> ua == u'abc'
True True
>>> b == u'123' >>> b == u'123'
......
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