fstring_full_format_spec[ResultTokenWithMetadata*]:
| colon=':' spec=fstring_format_spec* { _PyPegen_setup_full_format_spec(p, colon, (asdl_expr_seq *) spec, EXTRA) }
fstring_format_spec[expr_ty]:
- | t=FSTRING_MIDDLE { _PyPegen_constant_from_token(p, t) }
+ | t=FSTRING_MIDDLE { _PyPegen_decoded_constant_from_token(p, t) }
| fstring_replacement_field
fstring[expr_ty]:
| a=FSTRING_START b=fstring_middle* c=FSTRING_END { _PyPegen_joined_str(p, a, (asdl_expr_seq*)b, c) }
"""f'{"s"!{"r"}}'""",
])
+ def test_custom_format_specifier(self):
+ class CustomFormat:
+ def __format__(self, format_spec):
+ return format_spec
+
+ self.assertEqual(f'{CustomFormat():\n}', '\n')
+ self.assertEqual(f'{CustomFormat():\u2603}', '☃')
+ with self.assertWarns(SyntaxWarning):
+ exec('f"{F():¯\_(ツ)_/¯}"', {'F': CustomFormat})
+
def test_side_effect_order(self):
class X:
def __init__(self):
--- /dev/null
+Do not escape with backslashes f-string format specifiers. Patch by Pablo
+Galindo
p->arena);
}
+expr_ty _PyPegen_decoded_constant_from_token(Parser* p, Token* tok) {
+ Py_ssize_t bsize;
+ char* bstr;
+ if (PyBytes_AsStringAndSize(tok->bytes, &bstr, &bsize) == -1) {
+ return NULL;
+ }
+ PyObject* str = _PyPegen_decode_string(p, 0, bstr, bsize, tok);
+ if (str == NULL) {
+ return NULL;
+ }
+ if (_PyArena_AddPyObject(p->arena, str) < 0) {
+ Py_DECREF(str);
+ return NULL;
+ }
+ return _PyAST_Constant(str, NULL, tok->lineno, tok->col_offset,
+ tok->end_lineno, tok->end_col_offset,
+ p->arena);
+}
+
expr_ty _PyPegen_constant_from_token(Parser* p, Token* tok) {
char* bstr = PyBytes_AsString(tok->bytes);
if (bstr == NULL) {
)
{
D(fprintf(stderr, "%*c+ fstring_format_spec[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "FSTRING_MIDDLE"));
- _res = _PyPegen_constant_from_token ( p , t );
+ _res = _PyPegen_decoded_constant_from_token ( p , t );
if (_res == NULL && PyErr_Occurred()) {
p->error_indicator = 1;
p->level--;
int lineno, int col_offset, int end_lineno,
int end_col_offset, PyArena *arena);
expr_ty _PyPegen_constant_from_token(Parser* p, Token* tok);
+expr_ty _PyPegen_decoded_constant_from_token(Parser* p, Token* tok);
expr_ty _PyPegen_constant_from_string(Parser* p, Token* tok);
expr_ty _PyPegen_concatenate_strings(Parser *p, asdl_expr_seq *, int, int, int, int, PyArena *);
expr_ty _PyPegen_FetchRawForm(Parser *p, int, int, int, int);