diff options
author | Eric V. Smith <eric@trueblade.com> | 2015-11-03 17:45:05 (GMT) |
---|---|---|
committer | Eric V. Smith <eric@trueblade.com> | 2015-11-03 17:45:05 (GMT) |
commit | a78c7954d549fba967a842143b4e3050ff488468 (patch) | |
tree | 26e0270948bb638d1b11dec80cfbc6397fdc2643 /Python/ceval.c | |
parent | 2753a096e0365bf93e1fd3a3e20735f598c14e91 (diff) | |
download | cpython-a78c7954d549fba967a842143b4e3050ff488468.zip cpython-a78c7954d549fba967a842143b4e3050ff488468.tar.gz cpython-a78c7954d549fba967a842143b4e3050ff488468.tar.bz2 |
Issue 25483: Add an opcode to make f-string formatting more robust.
Diffstat (limited to 'Python/ceval.c')
-rw-r--r-- | Python/ceval.c | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/Python/ceval.c b/Python/ceval.c index f9e8ef8..60db703 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -3363,6 +3363,63 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) DISPATCH(); } + TARGET(FORMAT_VALUE) { + /* Handles f-string value formatting. */ + PyObject *result; + PyObject *fmt_spec; + PyObject *value; + PyObject *(*conv_fn)(PyObject *); + int which_conversion = oparg & FVC_MASK; + int have_fmt_spec = (oparg & FVS_MASK) == FVS_HAVE_SPEC; + + fmt_spec = have_fmt_spec ? POP() : NULL; + value = TOP(); + + /* See if any conversion is specified. */ + switch (which_conversion) { + case FVC_STR: conv_fn = PyObject_Str; break; + case FVC_REPR: conv_fn = PyObject_Repr; break; + case FVC_ASCII: conv_fn = PyObject_ASCII; break; + + /* Must be 0 (meaning no conversion), since only four + values are allowed by (oparg & FVC_MASK). */ + default: conv_fn = NULL; break; + } + + /* If there's a conversion function, call it and replace + value with that result. Otherwise, just use value, + without conversion. */ + if (conv_fn) { + result = conv_fn(value); + Py_DECREF(value); + if (!result) { + Py_XDECREF(fmt_spec); + goto error; + } + value = result; + } + + /* If value is a unicode object, and there's no fmt_spec, + then we know the result of format(value) is value + itself. In that case, skip calling format(). I plan to + move this optimization in to PyObject_Format() + itself. */ + if (PyUnicode_CheckExact(value) && fmt_spec == NULL) { + /* Do nothing, just transfer ownership to result. */ + result = value; + } else { + /* Actually call format(). */ + result = PyObject_Format(value, fmt_spec); + Py_DECREF(value); + Py_XDECREF(fmt_spec); + if (!result) + goto error; + } + + SET_TOP(result); + DISPATCH(); + } + TARGET(EXTENDED_ARG) { opcode = NEXTOP(); oparg = oparg<<16 | NEXTARG(); |