Issue 25483: Add an opcode to make f-string formatting more robust.

This commit is contained in:
Eric V. Smith 2015-11-03 12:45:05 -05:00
parent 2753a096e0
commit a78c7954d5
8 changed files with 205 additions and 168 deletions

View file

@ -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();