Commit c26fb663 authored by Robert Bradshaw's avatar Robert Bradshaw

Merge branch 'master' of github.com:cython/cython

parents aae6c5c9 85562685
...@@ -50,6 +50,9 @@ Bugs fixed ...@@ -50,6 +50,9 @@ Bugs fixed
* abs(signed int) now returns a signed rather than unsigned int. * abs(signed int) now returns a signed rather than unsigned int.
(Github issue #1837) (Github issue #1837)
* Compile time evaluations of (partially) constant f-strings could show incorrect
results.
Other changes Other changes
------------- -------------
......
...@@ -3126,7 +3126,7 @@ class FormattedValueNode(ExprNode): ...@@ -3126,7 +3126,7 @@ class FormattedValueNode(ExprNode):
self.format_spec = self.format_spec.analyse_types(env).coerce_to_pyobject(env) self.format_spec = self.format_spec.analyse_types(env).coerce_to_pyobject(env)
if self.c_format_spec is None: if self.c_format_spec is None:
self.value = self.value.coerce_to_pyobject(env) self.value = self.value.coerce_to_pyobject(env)
if not self.format_spec and not self.conversion_char: if not self.format_spec and (not self.conversion_char or self.conversion_char == 's'):
if self.value.type is unicode_type and not self.value.may_be_none(): if self.value.type is unicode_type and not self.value.may_be_none():
# value is definitely a unicode string and we don't format it any special # value is definitely a unicode string and we don't format it any special
return self.value return self.value
......
...@@ -3959,10 +3959,21 @@ class ConstantFolding(Visitor.VisitorTransform, SkipDeclarations): ...@@ -3959,10 +3959,21 @@ class ConstantFolding(Visitor.VisitorTransform, SkipDeclarations):
def visit_FormattedValueNode(self, node): def visit_FormattedValueNode(self, node):
self.visitchildren(node) self.visitchildren(node)
conversion_char = node.conversion_char or 's'
if isinstance(node.format_spec, ExprNodes.UnicodeNode) and not node.format_spec.value: if isinstance(node.format_spec, ExprNodes.UnicodeNode) and not node.format_spec.value:
node.format_spec = None node.format_spec = None
if node.format_spec is None and node.conversion_char is None and isinstance(node.value, ExprNodes.UnicodeNode): if node.format_spec is None and isinstance(node.value, ExprNodes.IntNode):
return node.value value = EncodedString(node.value.value)
if value.isdigit():
return ExprNodes.UnicodeNode(node.value.pos, value=value, constant_result=value)
if node.format_spec is None and conversion_char == 's':
value = None
if isinstance(node.value, ExprNodes.UnicodeNode):
value = node.value.value
elif isinstance(node.value, ExprNodes.StringNode):
value = node.value.unicode_value
if value is not None:
return ExprNodes.UnicodeNode(node.value.pos, value=value, constant_result=value)
return node return node
def visit_JoinedStrNode(self, node): def visit_JoinedStrNode(self, node):
...@@ -3980,7 +3991,8 @@ class ConstantFolding(Visitor.VisitorTransform, SkipDeclarations): ...@@ -3980,7 +3991,8 @@ class ConstantFolding(Visitor.VisitorTransform, SkipDeclarations):
substrings = list(substrings) substrings = list(substrings)
unode = substrings[0] unode = substrings[0]
if len(substrings) > 1: if len(substrings) > 1:
unode.value = EncodedString(u''.join(value.value for value in substrings)) value = EncodedString(u''.join(value.value for value in substrings))
unode = ExprNodes.UnicodeNode(unode.pos, value=value, constant_result=value)
# ignore empty Unicode strings # ignore empty Unicode strings
if unode.value: if unode.value:
values.append(unode) values.append(unode)
...@@ -3988,7 +4000,8 @@ class ConstantFolding(Visitor.VisitorTransform, SkipDeclarations): ...@@ -3988,7 +4000,8 @@ class ConstantFolding(Visitor.VisitorTransform, SkipDeclarations):
values.extend(substrings) values.extend(substrings)
if not values: if not values:
node = ExprNodes.UnicodeNode(node.pos, value=EncodedString('')) value = EncodedString('')
node = ExprNodes.UnicodeNode(node.pos, value=value, constant_result=value)
elif len(values) == 1: elif len(values) == 1:
node = values[0] node = values[0]
elif len(values) == 2: elif len(values) == 2:
......
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
# Cython specific PEP 498 tests in addition to test_fstring.pyx from CPython # Cython specific PEP 498 tests in addition to test_fstring.pyx from CPython
#### ####
cimport cython
import sys import sys
IS_PYPY = hasattr(sys, 'pypy_version_info') IS_PYPY = hasattr(sys, 'pypy_version_info')
...@@ -18,13 +20,39 @@ max_long = LONG_MAX ...@@ -18,13 +20,39 @@ max_long = LONG_MAX
min_long = LONG_MIN min_long = LONG_MIN
@cython.test_fail_if_path_exists(
"//FormattedValueNode",
"//JoinedStrNode",
"//AddNode",
)
def escaping(): def escaping():
""" """
>>> escaping() >>> escaping()
""" """
assert f'{{{{{"abc"}}}}}{{}}{{' == '{{abc}}{}{' assert f'{{{{{"abc"}}}}}{{}}{{' == '{{abc}}{}{'
s = f'{{{{{"abc"}}}}}{{}}{{'
assert s == '{{abc}}{}{', s
assert f'\x7b}}' == '{}' assert f'\x7b}}' == '{}'
s = f'\x7b}}'
assert s == '{}', s
assert f'{"{{}}"}' == '{{}}' assert f'{"{{}}"}' == '{{}}'
s = f'{"{{}}"}'
assert s == '{{}}', s
@cython.test_fail_if_path_exists(
"//FormattedValueNode",
"//JoinedStrNode",
"//AddNode",
)
def nested_constant():
"""
>>> print(nested_constant())
xyabc123321
"""
return f"""{f'''xy{f"abc{123}{'321'}"!s}'''}"""
def format2(ab, cd): def format2(ab, cd):
......
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