summaryrefslogtreecommitdiffstats
path: root/Python/ceval.c
diff options
context:
space:
mode:
Diffstat (limited to 'Python/ceval.c')
-rw-r--r--Python/ceval.c607
1 files changed, 344 insertions, 263 deletions
diff --git a/Python/ceval.c b/Python/ceval.c
index f0ea7c9..6d49363 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -749,6 +749,9 @@ enum why_code {
WHY_SILENCED = 0x0080 /* Exception silenced by 'with' */
};
+static void save_exc_state(PyThreadState *, PyFrameObject *);
+static void swap_exc_state(PyThreadState *, PyFrameObject *);
+static void restore_and_clear_exc_state(PyThreadState *, PyFrameObject *);
static enum why_code do_raise(PyObject *, PyObject *);
static int unpack_iterable(PyObject *, int, int, PyObject **);
@@ -817,10 +820,6 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
unsigned char *first_instr;
PyObject *names;
PyObject *consts;
-#if defined(Py_DEBUG) || defined(LLTRACE)
- /* Make it easier to find out where we are with a debugger */
- char *filename;
-#endif
/* Computed GOTOs, or
the-optimization-commonly-but-improperly-known-as-"threaded code"
@@ -1114,59 +1113,8 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
Py_XDECREF(traceback); \
}
-#define SAVE_EXC_STATE() \
- { \
- PyObject *type, *value, *traceback; \
- Py_XINCREF(tstate->exc_type); \
- Py_XINCREF(tstate->exc_value); \
- Py_XINCREF(tstate->exc_traceback); \
- type = f->f_exc_type; \
- value = f->f_exc_value; \
- traceback = f->f_exc_traceback; \
- f->f_exc_type = tstate->exc_type; \
- f->f_exc_value = tstate->exc_value; \
- f->f_exc_traceback = tstate->exc_traceback; \
- Py_XDECREF(type); \
- Py_XDECREF(value); \
- Py_XDECREF(traceback); \
- }
-
-#define SWAP_EXC_STATE() \
- { \
- PyObject *tmp; \
- tmp = tstate->exc_type; \
- tstate->exc_type = f->f_exc_type; \
- f->f_exc_type = tmp; \
- tmp = tstate->exc_value; \
- tstate->exc_value = f->f_exc_value; \
- f->f_exc_value = tmp; \
- tmp = tstate->exc_traceback; \
- tstate->exc_traceback = f->f_exc_traceback; \
- f->f_exc_traceback = tmp; \
- }
-
-#define RESTORE_AND_CLEAR_EXC_STATE() \
- { \
- PyObject *type, *value, *tb; \
- type = tstate->exc_type; \
- value = tstate->exc_value; \
- tb = tstate->exc_traceback; \
- tstate->exc_type = f->f_exc_type; \
- tstate->exc_value = f->f_exc_value; \
- tstate->exc_traceback = f->f_exc_traceback; \
- f->f_exc_type = NULL; \
- f->f_exc_value = NULL; \
- f->f_exc_traceback = NULL; \
- Py_XDECREF(type); \
- Py_XDECREF(value); \
- Py_XDECREF(tb); \
- }
-
/* Start of code */
- if (f == NULL)
- return NULL;
-
/* push frame */
if (Py_EnterRecursiveCall(""))
return NULL;
@@ -1240,28 +1188,15 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
/* We were in an except handler when we left,
restore the exception state which was put aside
(see YIELD_VALUE). */
- SWAP_EXC_STATE();
- }
- else {
- SAVE_EXC_STATE();
+ swap_exc_state(tstate, f);
}
+ else
+ save_exc_state(tstate, f);
}
#ifdef LLTRACE
lltrace = PyDict_GetItemString(f->f_globals, "__lltrace__") != NULL;
#endif
-#if defined(Py_DEBUG) || defined(LLTRACE)
- {
- PyObject *error_type, *error_value, *error_traceback;
- PyErr_Fetch(&error_type, &error_value, &error_traceback);
- filename = _PyUnicode_AsString(co->co_filename);
- if (filename == NULL && tstate->overflowed) {
- /* maximum recursion depth exceeded */
- goto exit_eval_frame;
- }
- PyErr_Restore(error_type, error_value, error_traceback);
- }
-#endif
why = WHY_NOT;
err = 0;
@@ -2725,7 +2660,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
Py_DECREF(*pfunc);
*pfunc = self;
na++;
- n++;
+ /* n++; */
} else
Py_INCREF(func);
sp = stack_pointer;
@@ -3049,9 +2984,9 @@ fast_yield:
break;
if (i == f->f_iblock)
/* We did not create this exception. */
- RESTORE_AND_CLEAR_EXC_STATE()
+ restore_and_clear_exc_state(tstate, f);
else
- SWAP_EXC_STATE()
+ swap_exc_state(tstate, f);
}
if (tstate->use_tracing) {
@@ -3081,7 +3016,7 @@ fast_yield:
PyTrace_RETURN, retval)) {
Py_XDECREF(retval);
retval = NULL;
- why = WHY_EXCEPTION;
+ /* why = WHY_EXCEPTION; */
}
}
}
@@ -3094,6 +3029,154 @@ exit_eval_frame:
return retval;
}
+static void
+format_missing(const char *kind, PyCodeObject *co, PyObject *names)
+{
+ int err;
+ Py_ssize_t len = PyList_GET_SIZE(names);
+ PyObject *name_str, *comma, *tail, *tmp;
+
+ assert(PyList_CheckExact(names));
+ assert(len >= 1);
+ /* Deal with the joys of natural language. */
+ switch (len) {
+ case 1:
+ name_str = PyList_GET_ITEM(names, 0);
+ Py_INCREF(name_str);
+ break;
+ case 2:
+ name_str = PyUnicode_FromFormat("%U and %U",
+ PyList_GET_ITEM(names, len - 2),
+ PyList_GET_ITEM(names, len - 1));
+ break;
+ default:
+ tail = PyUnicode_FromFormat(", %U, and %U",
+ PyList_GET_ITEM(names, len - 2),
+ PyList_GET_ITEM(names, len - 1));
+ /* Chop off the last two objects in the list. This shouldn't actually
+ fail, but we can't be too careful. */
+ err = PyList_SetSlice(names, len - 2, len, NULL);
+ if (err == -1) {
+ Py_DECREF(tail);
+ return;
+ }
+ /* Stitch everything up into a nice comma-separated list. */
+ comma = PyUnicode_FromString(", ");
+ if (comma == NULL) {
+ Py_DECREF(tail);
+ return;
+ }
+ tmp = PyUnicode_Join(comma, names);
+ Py_DECREF(comma);
+ if (tmp == NULL) {
+ Py_DECREF(tail);
+ return;
+ }
+ name_str = PyUnicode_Concat(tmp, tail);
+ Py_DECREF(tmp);
+ Py_DECREF(tail);
+ break;
+ }
+ if (name_str == NULL)
+ return;
+ PyErr_Format(PyExc_TypeError,
+ "%U() missing %i required %s argument%s: %U",
+ co->co_name,
+ len,
+ kind,
+ len == 1 ? "" : "s",
+ name_str);
+ Py_DECREF(name_str);
+}
+
+static void
+missing_arguments(PyCodeObject *co, int missing, int defcount,
+ PyObject **fastlocals)
+{
+ int i, j = 0;
+ int start, end;
+ int positional = defcount != -1;
+ const char *kind = positional ? "positional" : "keyword-only";
+ PyObject *missing_names;
+
+ /* Compute the names of the arguments that are missing. */
+ missing_names = PyList_New(missing);
+ if (missing_names == NULL)
+ return;
+ if (positional) {
+ start = 0;
+ end = co->co_argcount - defcount;
+ }
+ else {
+ start = co->co_argcount;
+ end = start + co->co_kwonlyargcount;
+ }
+ for (i = start; i < end; i++) {
+ if (GETLOCAL(i) == NULL) {
+ PyObject *raw = PyTuple_GET_ITEM(co->co_varnames, i);
+ PyObject *name = PyObject_Repr(raw);
+ if (name == NULL) {
+ Py_DECREF(missing_names);
+ return;
+ }
+ PyList_SET_ITEM(missing_names, j++, name);
+ }
+ }
+ assert(j == missing);
+ format_missing(kind, co, missing_names);
+ Py_DECREF(missing_names);
+}
+
+static void
+too_many_positional(PyCodeObject *co, int given, int defcount, PyObject **fastlocals)
+{
+ int plural;
+ int kwonly_given = 0;
+ int i;
+ PyObject *sig, *kwonly_sig;
+
+ assert((co->co_flags & CO_VARARGS) == 0);
+ /* Count missing keyword-only args. */
+ for (i = co->co_argcount; i < co->co_argcount + co->co_kwonlyargcount; i++)
+ if (GETLOCAL(i) != NULL)
+ kwonly_given++;
+ if (defcount) {
+ int atleast = co->co_argcount - defcount;
+ plural = 1;
+ sig = PyUnicode_FromFormat("from %d to %d", atleast, co->co_argcount);
+ }
+ else {
+ plural = co->co_argcount != 1;
+ sig = PyUnicode_FromFormat("%d", co->co_argcount);
+ }
+ if (sig == NULL)
+ return;
+ if (kwonly_given) {
+ const char *format = " positional argument%s (and %d keyword-only argument%s)";
+ kwonly_sig = PyUnicode_FromFormat(format, given != 1 ? "s" : "", kwonly_given,
+ kwonly_given != 1 ? "s" : "");
+ if (kwonly_sig == NULL) {
+ Py_DECREF(sig);
+ return;
+ }
+ }
+ else {
+ /* This will not fail. */
+ kwonly_sig = PyUnicode_FromString("");
+ assert(kwonly_sig != NULL);
+ }
+ PyErr_Format(PyExc_TypeError,
+ "%U() takes %U positional argument%s but %d%U %s given",
+ co->co_name,
+ sig,
+ plural ? "s" : "",
+ given,
+ kwonly_sig,
+ given == 1 && !kwonly_given ? "was" : "were");
+ Py_DECREF(sig);
+ Py_DECREF(kwonly_sig);
+}
+
/* This is gonna seem *real weird*, but if you put some other code between
PyEval_EvalFrame() and PyEval_EvalCodeEx() you will need to adjust
the test in the if statements in Misc/gdbinit (pystack and pystackv). */
@@ -3110,6 +3193,9 @@ PyEval_EvalCodeEx(PyObject *_co, PyObject *globals, PyObject *locals,
PyThreadState *tstate = PyThreadState_GET();
PyObject *x, *u;
int total_args = co->co_argcount + co->co_kwonlyargcount;
+ int i;
+ int n = argcount;
+ PyObject *kwdict = NULL;
if (globals == NULL) {
PyErr_SetString(PyExc_SystemError,
@@ -3126,212 +3212,153 @@ PyEval_EvalCodeEx(PyObject *_co, PyObject *globals, PyObject *locals,
fastlocals = f->f_localsplus;
freevars = f->f_localsplus + co->co_nlocals;
- if (total_args || co->co_flags & (CO_VARARGS | CO_VARKEYWORDS)) {
- int i;
- int n = argcount;
- PyObject *kwdict = NULL;
- if (co->co_flags & CO_VARKEYWORDS) {
- kwdict = PyDict_New();
- if (kwdict == NULL)
- goto fail;
- i = total_args;
- if (co->co_flags & CO_VARARGS)
- i++;
- SETLOCAL(i, kwdict);
- }
- if (argcount > co->co_argcount) {
- if (!(co->co_flags & CO_VARARGS)) {
- PyErr_Format(PyExc_TypeError,
- "%U() takes %s %d "
- "positional argument%s (%d given)",
- co->co_name,
- defcount ? "at most" : "exactly",
- co->co_argcount,
- co->co_argcount == 1 ? "" : "s",
- argcount + kwcount);
- goto fail;
- }
- n = co->co_argcount;
- }
- for (i = 0; i < n; i++) {
+ /* Parse arguments. */
+ if (co->co_flags & CO_VARKEYWORDS) {
+ kwdict = PyDict_New();
+ if (kwdict == NULL)
+ goto fail;
+ i = total_args;
+ if (co->co_flags & CO_VARARGS)
+ i++;
+ SETLOCAL(i, kwdict);
+ }
+ if (argcount > co->co_argcount)
+ n = co->co_argcount;
+ for (i = 0; i < n; i++) {
+ x = args[i];
+ Py_INCREF(x);
+ SETLOCAL(i, x);
+ }
+ if (co->co_flags & CO_VARARGS) {
+ u = PyTuple_New(argcount - n);
+ if (u == NULL)
+ goto fail;
+ SETLOCAL(total_args, u);
+ for (i = n; i < argcount; i++) {
x = args[i];
Py_INCREF(x);
- SETLOCAL(i, x);
+ PyTuple_SET_ITEM(u, i-n, x);
}
- if (co->co_flags & CO_VARARGS) {
- u = PyTuple_New(argcount - n);
- if (u == NULL)
- goto fail;
- SETLOCAL(total_args, u);
- for (i = n; i < argcount; i++) {
- x = args[i];
- Py_INCREF(x);
- PyTuple_SET_ITEM(u, i-n, x);
- }
+ }
+ for (i = 0; i < kwcount; i++) {
+ PyObject **co_varnames;
+ PyObject *keyword = kws[2*i];
+ PyObject *value = kws[2*i + 1];
+ int j;
+ if (keyword == NULL || !PyUnicode_Check(keyword)) {
+ PyErr_Format(PyExc_TypeError,
+ "%U() keywords must be strings",
+ co->co_name);
+ goto fail;
}
- for (i = 0; i < kwcount; i++) {
- PyObject **co_varnames;
- PyObject *keyword = kws[2*i];
- PyObject *value = kws[2*i + 1];
- int j;
- if (keyword == NULL || !PyUnicode_Check(keyword)) {
- PyErr_Format(PyExc_TypeError,
- "%U() keywords must be strings",
- co->co_name);
- goto fail;
- }
- /* Speed hack: do raw pointer compares. As names are
- normally interned this should almost always hit. */
- co_varnames = ((PyTupleObject *)(co->co_varnames))->ob_item;
- for (j = 0; j < total_args; j++) {
- PyObject *nm = co_varnames[j];
- if (nm == keyword)
- goto kw_found;
- }
- /* Slow fallback, just in case */
- for (j = 0; j < total_args; j++) {
- PyObject *nm = co_varnames[j];
- int cmp = PyObject_RichCompareBool(
- keyword, nm, Py_EQ);
- if (cmp > 0)
- goto kw_found;
- else if (cmp < 0)
- goto fail;
- }
- if (j >= total_args && kwdict == NULL) {
- PyErr_Format(PyExc_TypeError,
- "%U() got an unexpected "
- "keyword argument '%S'",
- co->co_name,
- keyword);
+ /* Speed hack: do raw pointer compares. As names are
+ normally interned this should almost always hit. */
+ co_varnames = ((PyTupleObject *)(co->co_varnames))->ob_item;
+ for (j = 0; j < total_args; j++) {
+ PyObject *nm = co_varnames[j];
+ if (nm == keyword)
+ goto kw_found;
+ }
+ /* Slow fallback, just in case */
+ for (j = 0; j < total_args; j++) {
+ PyObject *nm = co_varnames[j];
+ int cmp = PyObject_RichCompareBool(
+ keyword, nm, Py_EQ);
+ if (cmp > 0)
+ goto kw_found;
+ else if (cmp < 0)
goto fail;
- }
- PyDict_SetItem(kwdict, keyword, value);
- continue;
- kw_found:
- if (GETLOCAL(j) != NULL) {
- PyErr_Format(PyExc_TypeError,
+ }
+ if (j >= total_args && kwdict == NULL) {
+ PyErr_Format(PyExc_TypeError,
+ "%U() got an unexpected "
+ "keyword argument '%S'",
+ co->co_name,
+ keyword);
+ goto fail;
+ }
+ PyDict_SetItem(kwdict, keyword, value);
+ continue;
+ kw_found:
+ if (GETLOCAL(j) != NULL) {
+ PyErr_Format(PyExc_TypeError,
"%U() got multiple "
- "values for keyword "
- "argument '%S'",
+ "values for argument '%S'",
co->co_name,
keyword);
- goto fail;
- }
- Py_INCREF(value);
- SETLOCAL(j, value);
+ goto fail;
}
- if (co->co_kwonlyargcount > 0) {
- for (i = co->co_argcount; i < total_args; i++) {
- PyObject *name;
- if (GETLOCAL(i) != NULL)
- continue;
- name = PyTuple_GET_ITEM(co->co_varnames, i);
- if (kwdefs != NULL) {
- PyObject *def = PyDict_GetItem(kwdefs, name);
- if (def) {
- Py_INCREF(def);
- SETLOCAL(i, def);
- continue;
- }
- }
- PyErr_Format(PyExc_TypeError,
- "%U() needs keyword-only argument %S",
- co->co_name, name);
- goto fail;
- }
+ Py_INCREF(value);
+ SETLOCAL(j, value);
+ }
+ if (argcount > co->co_argcount && !(co->co_flags & CO_VARARGS)) {
+ too_many_positional(co, argcount, defcount, fastlocals);
+ goto fail;
+ }
+ if (argcount < co->co_argcount) {
+ int m = co->co_argcount - defcount;
+ int missing = 0;
+ for (i = argcount; i < m; i++)
+ if (GETLOCAL(i) == NULL)
+ missing++;
+ if (missing) {
+ missing_arguments(co, missing, defcount, fastlocals);
+ goto fail;
}
- if (argcount < co->co_argcount) {
- int m = co->co_argcount - defcount;
- for (i = argcount; i < m; i++) {
- if (GETLOCAL(i) == NULL) {
- int j, given = 0;
- for (j = 0; j < co->co_argcount; j++)
- if (GETLOCAL(j))
- given++;
- PyErr_Format(PyExc_TypeError,
- "%U() takes %s %d "
- "argument%s "
- "(%d given)",
- co->co_name,
- ((co->co_flags & CO_VARARGS) ||
- defcount) ? "at least"
- : "exactly",
- m, m == 1 ? "" : "s", given);
- goto fail;
- }
+ if (n > m)
+ i = n - m;
+ else
+ i = 0;
+ for (; i < defcount; i++) {
+ if (GETLOCAL(m+i) == NULL) {
+ PyObject *def = defs[i];
+ Py_INCREF(def);
+ SETLOCAL(m+i, def);
}
- if (n > m)
- i = n - m;
- else
- i = 0;
- for (; i < defcount; i++) {
- if (GETLOCAL(m+i) == NULL) {
- PyObject *def = defs[i];
+ }
+ }
+ if (co->co_kwonlyargcount > 0) {
+ int missing = 0;
+ for (i = co->co_argcount; i < total_args; i++) {
+ PyObject *name;
+ if (GETLOCAL(i) != NULL)
+ continue;
+ name = PyTuple_GET_ITEM(co->co_varnames, i);
+ if (kwdefs != NULL) {
+ PyObject *def = PyDict_GetItem(kwdefs, name);
+ if (def) {
Py_INCREF(def);
- SETLOCAL(m+i, def);
+ SETLOCAL(i, def);
+ continue;
}
}
+ missing++;
+ }
+ if (missing) {
+ missing_arguments(co, missing, -1, fastlocals);
+ goto fail;
}
}
- else if (argcount > 0 || kwcount > 0) {
- PyErr_Format(PyExc_TypeError,
- "%U() takes no arguments (%d given)",
- co->co_name,
- argcount + kwcount);
- goto fail;
- }
+
/* Allocate and initialize storage for cell vars, and copy free
- vars into frame. This isn't too efficient right now. */
- if (PyTuple_GET_SIZE(co->co_cellvars)) {
- int i, j, nargs, found;
- Py_UNICODE *cellname, *argname;
+ vars into frame. */
+ for (i = 0; i < PyTuple_GET_SIZE(co->co_cellvars); ++i) {
PyObject *c;
-
- nargs = total_args;
- if (co->co_flags & CO_VARARGS)
- nargs++;
- if (co->co_flags & CO_VARKEYWORDS)
- nargs++;
-
- /* Initialize each cell var, taking into account
- cell vars that are initialized from arguments.
-
- Should arrange for the compiler to put cellvars
- that are arguments at the beginning of the cellvars
- list so that we can march over it more efficiently?
- */
- for (i = 0; i < PyTuple_GET_SIZE(co->co_cellvars); ++i) {
- cellname = PyUnicode_AS_UNICODE(
- PyTuple_GET_ITEM(co->co_cellvars, i));
- found = 0;
- for (j = 0; j < nargs; j++) {
- argname = PyUnicode_AS_UNICODE(
- PyTuple_GET_ITEM(co->co_varnames, j));
- if (Py_UNICODE_strcmp(cellname, argname) == 0) {
- c = PyCell_New(GETLOCAL(j));
- if (c == NULL)
- goto fail;
- GETLOCAL(co->co_nlocals + i) = c;
- found = 1;
- break;
- }
- }
- if (found == 0) {
- c = PyCell_New(NULL);
- if (c == NULL)
- goto fail;
- SETLOCAL(co->co_nlocals + i, c);
- }
- }
+ int arg;
+ /* Possibly account for the cell variable being an argument. */
+ if (co->co_cell2arg != NULL &&
+ (arg = co->co_cell2arg[i]) != CO_CELL_NOT_AN_ARG)
+ c = PyCell_New(GETLOCAL(arg));
+ else
+ c = PyCell_New(NULL);
+ if (c == NULL)
+ goto fail;
+ SETLOCAL(co->co_nlocals + i, c);
}
- if (PyTuple_GET_SIZE(co->co_freevars)) {
- int i;
- for (i = 0; i < PyTuple_GET_SIZE(co->co_freevars); ++i) {
- PyObject *o = PyTuple_GET_ITEM(closure, i);
- Py_INCREF(o);
- freevars[PyTuple_GET_SIZE(co->co_cellvars) + i] = o;
- }
+ for (i = 0; i < PyTuple_GET_SIZE(co->co_freevars); ++i) {
+ PyObject *o = PyTuple_GET_ITEM(closure, i);
+ Py_INCREF(o);
+ freevars[PyTuple_GET_SIZE(co->co_cellvars) + i] = o;
}
if (co->co_flags & CO_GENERATOR) {
@@ -3377,6 +3404,60 @@ special_lookup(PyObject *o, char *meth, PyObject **cache)
}
+/* These 3 functions deal with the exception state of generators. */
+
+static void
+save_exc_state(PyThreadState *tstate, PyFrameObject *f)
+{
+ PyObject *type, *value, *traceback;
+ Py_XINCREF(tstate->exc_type);
+ Py_XINCREF(tstate->exc_value);
+ Py_XINCREF(tstate->exc_traceback);
+ type = f->f_exc_type;
+ value = f->f_exc_value;
+ traceback = f->f_exc_traceback;
+ f->f_exc_type = tstate->exc_type;
+ f->f_exc_value = tstate->exc_value;
+ f->f_exc_traceback = tstate->exc_traceback;
+ Py_XDECREF(type);
+ Py_XDECREF(value);
+ Py_XDECREF(traceback);
+}
+
+static void
+swap_exc_state(PyThreadState *tstate, PyFrameObject *f)
+{
+ PyObject *tmp;
+ tmp = tstate->exc_type;
+ tstate->exc_type = f->f_exc_type;
+ f->f_exc_type = tmp;
+ tmp = tstate->exc_value;
+ tstate->exc_value = f->f_exc_value;
+ f->f_exc_value = tmp;
+ tmp = tstate->exc_traceback;
+ tstate->exc_traceback = f->f_exc_traceback;
+ f->f_exc_traceback = tmp;
+}
+
+static void
+restore_and_clear_exc_state(PyThreadState *tstate, PyFrameObject *f)
+{
+ PyObject *type, *value, *tb;
+ type = tstate->exc_type;
+ value = tstate->exc_value;
+ tb = tstate->exc_traceback;
+ tstate->exc_type = f->f_exc_type;
+ tstate->exc_value = f->f_exc_value;
+ tstate->exc_traceback = f->f_exc_traceback;
+ f->f_exc_type = NULL;
+ f->f_exc_value = NULL;
+ f->f_exc_traceback = NULL;
+ Py_XDECREF(type);
+ Py_XDECREF(value);
+ Py_XDECREF(tb);
+}
+
+
/* Logic for the raise statement (too complicated for inlining).
This *consumes* a reference count to each of its arguments. */
static enum why_code
@@ -4192,7 +4273,7 @@ ext_do_call(PyObject *func, PyObject ***pp_stack, int flags, int na, int nk)
if (PyErr_ExceptionMatches(PyExc_TypeError)) {
PyErr_Format(PyExc_TypeError,
"%.200s%.200s argument after * "
- "must be a sequence, not %200s",
+ "must be a sequence, not %.200s",
PyEval_GetFuncName(func),
PyEval_GetFuncDesc(func),
stararg->ob_type->tp_name);