diff --git a/Python/compile.c b/Python/compile.c index c3ffaae8ce..926e175894 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -175,6 +175,7 @@ static int compiler_addop_o(struct compiler *, int, PyObject *, PyObject *); static int compiler_addop_i(struct compiler *, int, Py_ssize_t); static int compiler_addop_j(struct compiler *, int, basicblock *, int); static int compiler_error(struct compiler *, const char *); +static int compiler_warning(struct compiler *, PyObject *); static int compiler_nameop(struct compiler *, identifier, expr_context_ty); static PyCodeObject *compiler_mod(struct compiler *, mod_ty); @@ -3033,15 +3034,9 @@ compiler_assert(struct compiler *c, stmt_ty s) asdl_seq_LEN(s->v.Assert.test->v.Tuple.elts) > 0) { msg = PyUnicode_FromString("assertion is always true, " "perhaps remove parentheses?"); - if (msg == NULL) - return 0; - if (PyErr_WarnExplicitObject(PyExc_SyntaxWarning, msg, - c->c_filename, c->u->u_lineno, - NULL, NULL) == -1) { - Py_DECREF(msg); + if (!compiler_warning(c, msg)) { return 0; } - Py_DECREF(msg); } end = compiler_new_block(c); if (end == NULL) @@ -3634,6 +3629,133 @@ compiler_compare(struct compiler *c, expr_ty e) return 1; } +static int +chech_caller(struct compiler *c, expr_ty e) +{ + const char *type; + PyObject *msg; + + switch (e->kind) { + case Tuple_kind: + type = "tuple"; + break; + case List_kind: + case ListComp_kind: + type = "list"; + break; + case Dict_kind: + case DictComp_kind: + type = "dict"; + break; + case Set_kind: + case SetComp_kind: + type = "set"; + break; + case GeneratorExp_kind: + type = "generator"; + break; + case JoinedStr_kind: + case FormattedValue_kind: + type = "str"; + break; + default: + if (is_const(e)) { + PyObject *v = get_const_value(e); + type = v->ob_type->tp_name; + } + else { + return 1; + } + } + msg = PyUnicode_FromFormat("'%.200s' object is not callable, " + "perhaps missed a comma?", + type); + return compiler_warning(c, msg); +} + +static int +chech_subscripter(struct compiler *c, expr_ty e) +{ + const char *type; + PyObject *msg; + + switch (e->kind) { + case Set_kind: + case SetComp_kind: + type = "set"; + break; + case GeneratorExp_kind: + type = "generator"; + break; + case Lambda_kind: + type = "function"; + break; + default: + if (is_const(e)) { + PyObject *v = get_const_value(e); + if (v == Py_None || v == Py_Ellipsis || + PyLong_Check(v) || PyFloat_Check(v) || PyComplex_Check(v) || + PyAnySet_Check(v)) + { + type = v->ob_type->tp_name; + } + else { + return 1; + } + } + else { + return 1; + } + } + msg = PyUnicode_FromFormat("'%.200s' object is not subscriptable, " + "perhaps missed a comma?", + type); + return compiler_warning(c, msg); +} + +static int +chech_index(struct compiler *c, expr_ty e, slice_ty s) +{ + const char *type; + PyObject *msg; + + if (s->kind != ExtSlice_kind) { + return 1; + } + + switch (e->kind) { + case Tuple_kind: + type = "tuple"; + break; + case List_kind: + case ListComp_kind: + type = "list"; + break; + case JoinedStr_kind: + case FormattedValue_kind: + type = "str"; + break; + default: + if (is_const(e)) { + PyObject *v = get_const_value(e); + if (PyUnicode_Check(v) || PyBytes_Check(v) || PyTuple_Check(v)) { + type = v->ob_type->tp_name; + } + else { + return 1; + } + } + else { + return 1; + } + } + msg = PyUnicode_FromFormat("%.200s indices must be integers or slices, " + "not tuple, " + "perhaps missed a comma?", + type); + return compiler_warning(c, msg); +} + static int maybe_optimize_method_call(struct compiler *c, expr_ty e) { @@ -3669,7 +3791,9 @@ compiler_call(struct compiler *c, expr_ty e) { if (maybe_optimize_method_call(c, e) > 0) return 1; - + if (!chech_caller(c, e->v.Call.func)) { + return 0; + } VISIT(c, expr, e->v.Call.func); return compiler_call_helper(c, 0, e->v.Call.args, @@ -4620,6 +4744,12 @@ compiler_visit_expr(struct compiler *c, expr_ty e) VISIT_SLICE(c, e->v.Subscript.slice, AugLoad); break; case Load: + if (!chech_subscripter(c, e->v.Subscript.value)) { + return 0; + } + if (!chech_index(c, e->v.Subscript.value, e->v.Subscript.slice)) { + return 0; + } VISIT(c, expr, e->v.Subscript.value); VISIT_SLICE(c, e->v.Subscript.slice, Load); break; @@ -4885,6 +5015,29 @@ compiler_error(struct compiler *c, const char *errstr) return 0; } +static int +compiler_warning(struct compiler *c, PyObject *msg) +{ + if (msg == NULL) + return 0; + if (PyErr_WarnExplicitObject(PyExc_SyntaxWarning, msg, + c->c_filename, c->u->u_lineno, + NULL, NULL) == -1) + { + if (PyErr_ExceptionMatches(PyExc_SyntaxWarning)) { + /* Replace the SyntaxWarning exception with a SyntaxError + to get a more accurate error report */ + PyErr_Clear(); + assert(PyUnicode_AsUTF8(msg) != NULL); + compiler_error(c, PyUnicode_AsUTF8(msg)); + } + Py_DECREF(msg); + return 0; + } + Py_DECREF(msg); + return 1; +} + static int compiler_handle_subscr(struct compiler *c, const char *kind, expr_context_ty ctx)