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): ...@@ -5673,6 +5673,7 @@ class SequenceNode(ExprNode):
is_sequence_constructor = 1 is_sequence_constructor = 1
unpacked_items = None unpacked_items = None
mult_factor = None mult_factor = None
slow = False # trade speed for code size (e.g. use PyTuple_Pack())
def compile_time_value_list(self, denv): def compile_time_value_list(self, denv):
return [arg.compile_time_value(denv) for arg in self.args] return [arg.compile_time_value(denv) for arg in self.args]
...@@ -5754,7 +5755,7 @@ class SequenceNode(ExprNode): ...@@ -5754,7 +5755,7 @@ class SequenceNode(ExprNode):
else: else:
size_factor = ' * ((%s<0) ? 0:%s)' % (c_mult, c_mult) 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 # use PyTuple_Pack() to avoid generating huge amounts of one-time code
code.putln('%s = PyTuple_Pack(%d, %s); %s' % ( code.putln('%s = PyTuple_Pack(%d, %s); %s' % (
target, target,
......
...@@ -5222,6 +5222,12 @@ class AssertStatNode(StatNode): ...@@ -5222,6 +5222,12 @@ class AssertStatNode(StatNode):
self.cond = self.cond.analyse_boolean_expression(env) self.cond = self.cond.analyse_boolean_expression(env)
if self.value: if self.value:
value = self.value.analyse_types(env) value = self.value.analyse_types(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) self.value = value.coerce_to_pyobject(env)
return self return self
......
# mode: run
cimport cython
def f(a, b, int i): def f(a, b, int i):
""" """
>>> f(1, 2, 1) >>> f(1, 2, 1)
...@@ -15,11 +19,62 @@ def f(a, b, int i): ...@@ -15,11 +19,62 @@ def f(a, b, int i):
assert a+b assert a+b
assert i assert i
@cython.test_assert_path_exists(
'//AssertStatNode',
'//AssertStatNode//TupleNode')
def g(a, b): def g(a, b):
""" """
>>> g(1, "works") >>> g(1, "works")
>>> g(0, "fails") >>> g(0, "fails")
Traceback (most recent call last): Traceback (most recent call last):
AssertionError: fails AssertionError: fails
>>> g(0, (1, 2))
Traceback (most recent call last):
AssertionError: (1, 2)
""" """
assert a, b 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