Author: Carl Friedrich Bolz-Tereick <[email protected]>
Branch: py3.7
Changeset: r98454:1758bd2014d8
Date: 2020-01-06 13:47 +0100
http://bitbucket.org/pypy/pypy/changeset/1758bd2014d8/
Log: fstring support
diff --git a/pypy/interpreter/astcompiler/test/test_unparse.py
b/pypy/interpreter/astcompiler/test/test_unparse.py
--- a/pypy/interpreter/astcompiler/test/test_unparse.py
+++ b/pypy/interpreter/astcompiler/test/test_unparse.py
@@ -154,6 +154,17 @@
self.check('lambda **foo: 1')
self.check('lambda a, **b: 45')
+ def test_fstrings(self):
+ #self.check('f"abc"', '"abc"')
+ self.check("f'{{{a}'", "f'{{{a}'")
+ self.check("f'{{{a}'", "f'{{{a}'")
+ self.check("f'{x+1!a}'", "f'{x + 1!a}'")
+ self.check("f'{x+1:x}'", "f'{x + 1:x}'")
+ self.check("f'some f-string with {a} {few():.2f}
{formatted.values!r}'")
+ self.check('''f"{f'{nested} inner'} outer"''')
+ self.check("f'space between opening braces: { {a for a in (1, 2,
3)}}'")
+ self.check("f'{(lambda x: x)}'")
+ self.check("f'{(None if a else lambda x: x)}'")
class TestAstUnparseAnnotations(object):
def setup_class(cls):
diff --git a/pypy/interpreter/astcompiler/unparse.py
b/pypy/interpreter/astcompiler/unparse.py
--- a/pypy/interpreter/astcompiler/unparse.py
+++ b/pypy/interpreter/astcompiler/unparse.py
@@ -23,6 +23,7 @@
PRIORITY_AWAIT = 15 # 'await'
PRIORITY_ATOM = 16
+
class Parenthesizer(object):
def __init__(self, visitor, priority):
self.visitor = visitor
@@ -40,16 +41,10 @@
if level > self.priority:
visitor.append_ascii(")")
-
-
-class UnparseVisitor(ast.ASTVisitor):
+class Utf8BuilderVisitor(ast.ASTVisitor):
def __init__(self, space):
self.space = space
self.builder = Utf8StringBuilder()
- self.level = PRIORITY_TEST
-
- def maybe_parenthesize(self, priority):
- return Parenthesizer(self, priority)
def append_w_str(self, w_s):
s, l = self.space.utf8_len_w(w_s)
@@ -61,6 +56,15 @@
def append_utf8(self, s):
self.builder.append(s)
+
+class UnparseVisitor(Utf8BuilderVisitor):
+ def __init__(self, space, startlevel=PRIORITY_TEST):
+ Utf8BuilderVisitor.__init__(self, space)
+ self.level = startlevel
+
+ def maybe_parenthesize(self, priority):
+ return Parenthesizer(self, priority)
+
def append_expr(self, node, priority=PRIORITY_TEST):
level = self.level
self.level = priority
@@ -175,7 +179,7 @@
self.append_expr(node.left, priority + right_associative)
self.append_ascii(op)
self.append_expr(node.right, priority + (not right_associative))
-
+
def visit_BoolOp(self, node):
if node.op == ast.And:
op = " and "
@@ -448,14 +452,66 @@
self.append_ascii(': ')
self.append_expr(node.body)
+ def visit_JoinedStr(self, node):
+ # mess
+ subvisitor = FstringVisitor(self.space)
+ for i, elt in enumerate(node.values):
+ elt.walkabout(subvisitor)
+ s = subvisitor.builder.build()
+ l = subvisitor.builder.getlength()
+ self.append_ascii("f")
+ self.append_w_str(self.space.repr(self.space.newutf8(s, l)))
-def unparse(space, ast):
- visitor = UnparseVisitor(space)
+
+class FstringVisitor(Utf8BuilderVisitor):
+
+ def default_visitor(self, node):
+ raise OperationError(self.space.w_SystemError,
+ self.space.newtext("expression type not supported yet:" +
str(node)))
+
+ def visit_Str(self, node):
+ s, l = self.space.utf8_len_w(node.s)
+ s = s.replace("{", "{{")
+ s = s.replace("}", "}}")
+ self.append_utf8(s)
+
+ def visit_FormattedValue(self, node):
+ outer_brace = "{"
+ s = unparse(self.space, node.value, PRIORITY_TEST + 1)
+ if s.startswith("{"):
+ outer_brace = "{ "
+ self.append_ascii(outer_brace)
+ self.append_utf8(s)
+ conversion = node.conversion
+ if conversion >= 0:
+ if conversion == ord('a'):
+ conversion = '!a'
+ elif conversion == ord('r'):
+ conversion = '!r'
+ elif conversion == ord('s'):
+ conversion = '!s'
+ else:
+ raise oefmt(self.space.w_SystemError,
+ "unknown f-string conversion kind %s", chr(conversion))
+ self.append_ascii(conversion)
+
+ if node.format_spec:
+ self.append_ascii(":")
+ node.format_spec.walkabout(self)
+ self.append_ascii("}")
+
+ def visit_JoinedStr(self, node):
+ for i, elt in enumerate(node.values):
+ elt.walkabout(self)
+
+
+def unparse(space, ast, level=PRIORITY_TEST):
+ visitor = UnparseVisitor(space, level)
ast.walkabout(visitor)
return visitor.builder.build()
-def w_unparse(space, ast):
- visitor = UnparseVisitor(space)
+def w_unparse(space, ast, level=PRIORITY_TEST):
+ visitor = UnparseVisitor(space, level)
ast.walkabout(visitor)
return space.newutf8(visitor.builder.build(), visitor.builder.getlength())
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit