Skip to content

Commit 91faa31

Browse files
committed
handle lambda in f-string
1 parent 143524b commit 91faa31

File tree

3 files changed

+1411
-1332
lines changed

3 files changed

+1411
-1332
lines changed

Grammar/python.gram

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1140,6 +1140,8 @@ invalid_expression:
11401140
_PyPegen_check_legacy_stmt(p, a) ? NULL : p->tokens[p->mark-1]->level == 0 ? NULL :
11411141
RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "invalid syntax. Perhaps you forgot a comma?") }
11421142
| a=disjunction 'if' b=disjunction !('else'|':') { RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "expected 'else' after 'if' expression") }
1143+
| a='lambda' [lambda_params] b=':' &(FSTRING_MIDDLE | fstring_replacement_field) {
1144+
RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "f-string: lambda expressions are not allowed without parentheses") }
11431145

11441146
invalid_named_expression(memo):
11451147
| a=expression ':=' expression {
@@ -1362,7 +1364,6 @@ invalid_replacement_field:
13621364
| '{' a='!' { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "f-string: valid expression required before '!'") }
13631365
| '{' a=':' { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "f-string: valid expression required before ':'") }
13641366
| '{' a='}' { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "f-string: valid expression required before '}'") }
1365-
| '{' a='lambda' { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "f-string: lambda expression are not allowed without parentheses") }
13661367
| '{' !(yield_expr | star_expressions) { RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN("f-string: expecting a valid expression after '{'")}
13671368
| '{' (yield_expr | star_expressions) !('=' | '!' | ':' | '}') {
13681369
PyErr_Occurred() ? NULL : RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN("f-string: expecting '=', or '!', or ':', or '}'") }

Lib/test/test_fstring.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -929,11 +929,23 @@ def test_lambda(self):
929929
self.assertEqual(f'{(lambda y:x*y)("8"):10}', "88888 ")
930930

931931
# lambda doesn't work without parens, because the colon
932-
# makes the parser think it's a format_spec
932+
# makes the parser think it's a format_spec
933+
# emit warning if we can match a format_spec
933934
self.assertAllRaise(SyntaxError,
934-
"f-string: lambda expression are not allowed "
935+
"f-string: lambda expressions are not allowed "
935936
"without parentheses",
936937
["f'{lambda x:x}'",
938+
"f'{lambda :x}'",
939+
"f'{lambda *arg, :x}'",
940+
"f'{1, lambda:x}'",
941+
])
942+
943+
# but don't emit the paren warning in general cases
944+
self.assertAllRaise(SyntaxError,
945+
"f-string: expecting a valid expression after '{'",
946+
["f'{lambda x:}'",
947+
"f'{lambda :}'",
948+
"f'{+ lambda:None}'",
937949
])
938950

939951
def test_valid_prefixes(self):

0 commit comments

Comments
 (0)