Author: Armin Rigo <[email protected]>
Branch: py3.5-fstring-pep498
Changeset: r89698:19d22e69d149
Date: 2017-01-22 23:07 +0100
http://bitbucket.org/pypy/pypy/changeset/19d22e69d149/
Log: conversions (!s, !r, !a)
diff --git a/pypy/interpreter/astcompiler/astbuilder.py
b/pypy/interpreter/astcompiler/astbuilder.py
--- a/pypy/interpreter/astcompiler/astbuilder.py
+++ b/pypy/interpreter/astcompiler/astbuilder.py
@@ -1249,18 +1249,26 @@
break # normal way out of this loop
# XXX forbid comment, but how?
else:
- raise self.error("f-string: unterminated '{' expression")
+ ch = u'\x00'
+ #
if nested_depth > 0:
- self.error("f-string: mismatched '(', '{' or '['")
+ self.error("f-string: mismatched '(', '{' or '['", atom_node)
+ end_expression = p - 1
if ch == u'!':
- XXX
+ if p + 1 < len(u):
+ conversion = ord(u[p])
+ ch = u[p + 1]
+ p += 2
+ if conversion not in (ord('s'), ord('r'), ord('a')):
+ self.error("f-string: invalid conversion character: "
+ "expected 's', 'r', or 'a'", atom_node)
if ch == u':':
XXX
- assert ch == u'}'
+ if ch != u'}':
+ self.error("f-string: expecting '}'", atom_node)
end_f_string = p
- p -= 1 # drop the final '}'
- assert p >= start
- expr = self._f_string_compile(u[start:p], atom_node)
+ assert end_expression >= start
+ expr = self._f_string_compile(u[start:end_expression], atom_node)
assert isinstance(expr, ast.Expression)
fval = ast.FormattedValue(expr.body, conversion, format_spec,
atom_node.get_lineno(),
@@ -1284,7 +1292,7 @@
atom_node)
start = pn + 1
else:
- self.error("f-string: unexpected '}'", atom_node)
+ self.error("f-string: single '}' is not allowed",
atom_node)
continue
self._f_constant_string(joined_pieces, u[start:p1], atom_node)
if p1 == len(u):
diff --git a/pypy/interpreter/astcompiler/codegen.py
b/pypy/interpreter/astcompiler/codegen.py
--- a/pypy/interpreter/astcompiler/codegen.py
+++ b/pypy/interpreter/astcompiler/codegen.py
@@ -1499,7 +1499,11 @@
def visit_FormattedValue(self, fmt):
fmt.value.walkabout(self)
- self.emit_op_arg(ops.FORMAT_VALUE, 0)
+ arg = 0
+ if fmt.conversion == ord('s'): arg = consts.FVC_STR
+ if fmt.conversion == ord('r'): arg = consts.FVC_REPR
+ if fmt.conversion == ord('a'): arg = consts.FVC_ASCII
+ self.emit_op_arg(ops.FORMAT_VALUE, arg)
class TopLevelCodeGenerator(PythonCodeGenerator):
diff --git a/pypy/interpreter/astcompiler/consts.py
b/pypy/interpreter/astcompiler/consts.py
--- a/pypy/interpreter/astcompiler/consts.py
+++ b/pypy/interpreter/astcompiler/consts.py
@@ -33,3 +33,12 @@
PyCF_IGNORE_COOKIE = 0x0800
PyCF_ACCEPT_NULL_BYTES = 0x10000000 # PyPy only, for compile()
PyCF_FOUND_ENCODING = 0x20000000 # PyPy only, for pytokenizer
+
+# Masks and values used by FORMAT_VALUE opcode
+FVC_MASK = 0x3
+FVC_NONE = 0x0
+FVC_STR = 0x1
+FVC_REPR = 0x2
+FVC_ASCII = 0x3
+FVS_MASK = 0x4
+FVS_HAVE_SPEC = 0x4
diff --git a/pypy/interpreter/astcompiler/test/test_compiler.py
b/pypy/interpreter/astcompiler/test/test_compiler.py
--- a/pypy/interpreter/astcompiler/test/test_compiler.py
+++ b/pypy/interpreter/astcompiler/test/test_compiler.py
@@ -1164,6 +1164,15 @@
def test_fstring(self):
yield self.st, """x = 42; z = f'ab{x}cd'""", 'z', 'ab42cd'
+ yield self.st, """z = f'{{'""", 'z', '{'
+ yield self.st, """z = f'}}'""", 'z', '}'
+ yield self.st, """z = f'x{{y'""", 'z', 'x{y'
+ yield self.st, """z = f'x}}y'""", 'z', 'x}y'
+
+ yield self.st, """x = 'hi'; z = f'{x}'""", 'z', 'hi'
+ yield self.st, """x = 'hi'; z = f'{x!s}'""", 'z', 'hi'
+ yield self.st, """x = 'hi'; z = f'{x!r}'""", 'z', "'hi'"
+ yield self.st, """x = 'hi'; z = f'{x!a}'""", 'z', "'hi'"
class AppTestCompiler:
diff --git a/pypy/interpreter/pyopcode.py b/pypy/interpreter/pyopcode.py
--- a/pypy/interpreter/pyopcode.py
+++ b/pypy/interpreter/pyopcode.py
@@ -1612,8 +1612,19 @@
self.pushvalue(w_awaitable)
def FORMAT_VALUE(self, oparg, next_instr):
+ from pypy.interpreter.astcompiler import consts
space = self.space
w_value = self.popvalue()
+ #
+ conversion = oparg & consts.FVC_MASK
+ if conversion == consts.FVC_STR:
+ w_value = space.str(w_value)
+ elif conversion == consts.FVC_REPR:
+ w_value = space.repr(w_value)
+ elif conversion == consts.FVC_ASCII:
+ from pypy.objspace.std.unicodeobject import ascii_from_object
+ w_value = ascii_from_object(space, w_value)
+ #
w_res = space.format(w_value, space.newunicode(u''))
self.pushvalue(w_res)
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit