Commit be65922f authored by Stefan Behnel's avatar Stefan Behnel

implement Python corner case of passing a tuple as assert message

parent 461b8932
......@@ -5673,6 +5673,7 @@ class SequenceNode(ExprNode):
is_sequence_constructor = 1
unpacked_items = None
mult_factor = None
slow = False # trade speed for code size (e.g. use PyTuple_Pack())
def compile_time_value_list(self, denv):
return [arg.compile_time_value(denv) for arg in self.args]
......@@ -5754,7 +5755,7 @@ class SequenceNode(ExprNode):
else:
size_factor = ' * ((%s<0) ? 0:%s)' % (c_mult, c_mult)
if self.type is Builtin.tuple_type and self.is_literal and not c_mult:
if self.type is Builtin.tuple_type and (self.is_literal or self.slow) and not c_mult:
# use PyTuple_Pack() to avoid generating huge amounts of one-time code
code.putln('%s = PyTuple_Pack(%d, %s); %s' % (
target,
......
......@@ -5222,7 +5222,13 @@ class AssertStatNode(StatNode):
self.cond = self.cond.analyse_boolean_expression(env)
if self.value:
value = self.value.analyse_types(env)
self.value = value.coerce_to_pyobject(env)
if value.type is Builtin.tuple_type or not value.type.is_builtin_type:
# prevent tuple values from being interpreted as argument value tuples
from ExprNodes import TupleNode
value = TupleNode(value.pos, args=[value], slow=True)
self.value = value.analyse_types(env, skip_children=True)
else:
self.value = value.coerce_to_pyobject(env)
return self
nogil_check = Node.gil_error
......
# mode: run
cimport cython
def f(a, b, int i):
"""
>>> f(1, 2, 1)
......@@ -15,11 +19,62 @@ def f(a, b, int i):
assert a+b
assert i
@cython.test_assert_path_exists(
'//AssertStatNode',
'//AssertStatNode//TupleNode')
def g(a, b):
"""
>>> g(1, "works")
>>> g(0, "fails")
Traceback (most recent call last):
AssertionError: fails
>>> g(0, (1, 2))
Traceback (most recent call last):
AssertionError: (1, 2)
"""
assert a, b
@cython.test_assert_path_exists(
'//AssertStatNode',
'//AssertStatNode//TupleNode')
def g(a, b):
"""
>>> g(1, "works")
>>> g(0, "fails")
Traceback (most recent call last):
AssertionError: fails
>>> g(0, (1, 2))
Traceback (most recent call last):
AssertionError: (1, 2)
"""
assert a, b
@cython.test_assert_path_exists(
'//AssertStatNode',
'//AssertStatNode//TupleNode',
'//AssertStatNode//TupleNode//TupleNode')
def assert_with_tuple_arg(a):
"""
>>> assert_with_tuple_arg(True)
>>> assert_with_tuple_arg(False)
Traceback (most recent call last):
AssertionError: (1, 2)
"""
assert a, (1, 2)
@cython.test_assert_path_exists(
'//AssertStatNode')
@cython.test_fail_if_path_exists(
'//AssertStatNode//TupleNode')
def assert_with_str_arg(a):
"""
>>> assert_with_str_arg(True)
>>> assert_with_str_arg(False)
Traceback (most recent call last):
AssertionError: abc
"""
assert a, 'abc'
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