summaryrefslogtreecommitdiffstats
path: root/Python/ceval.c
diff options
context:
space:
mode:
authorEric V. Smith <eric@trueblade.com>2015-11-03 17:45:05 (GMT)
committerEric V. Smith <eric@trueblade.com>2015-11-03 17:45:05 (GMT)
commita78c7954d549fba967a842143b4e3050ff488468 (patch)
tree26e0270948bb638d1b11dec80cfbc6397fdc2643 /Python/ceval.c
parent2753a096e0365bf93e1fd3a3e20735f598c14e91 (diff)
downloadcpython-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.c57
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();