Index: Python/ast.c =================================================================== --- Python/ast.c (revision 62663) +++ Python/ast.c (working copy) @@ -113,6 +113,19 @@ PyErr_Restore(type, value, tback); } +static int +ast_warn(struct compiling *c, const node *n, PyObject *kind, char *msg) +{ + if (PyErr_WarnExplicit(kind, msg, c->c_filename, LINENO(n), + NULL, NULL) < 0) { + /* if -Werr, change it to a SyntaxError */ + if (PyErr_Occurred() && PyErr_ExceptionMatches(kind)) + ast_error(n, msg); + return -1; + } + return 0; +} + /* num_stmts() returns number of contained statements. Use this routine to determine how big a sequence is needed for @@ -351,9 +364,18 @@ switch (e->kind) { case Attribute_kind: - if (ctx == Store && - !strcmp(PyString_AS_STRING(e->v.Attribute.attr), "None")) { - return ast_error(n, "assignment to None"); + if (ctx == Store) { + char *attr = PyString_AS_STRING(e->v.Attribute.attr); + if (!strcmp(attr, "None")) { + return ast_error(n, "assignment to None"); + } + if (Py_Py3kWarningFlag && + !(strcmp(attr, "True") && strcmp(attr, "False")) && + ast_warn(c, n, PyExc_DeprecationWarning, + "Assignment to True or False is forbidden in 3.x.") + < 0) { + return 0; + } } e->v.Attribute.ctx = ctx; break; @@ -361,9 +383,18 @@ e->v.Subscript.ctx = ctx; break; case Name_kind: - if (ctx == Store && - !strcmp(PyString_AS_STRING(e->v.Name.id), "None")) { + if (ctx == Store) { + char *id = PyString_AS_STRING(e->v.Name.id); + if (!strcmp(id, "None")) { return ast_error(n, "assignment to None"); + } + if (Py_Py3kWarningFlag && + !(strcmp(id, "True") && strcmp(id, "False")) && + ast_warn(c, n, PyExc_DeprecationWarning, + "Assignment to True or False is forbidden in 3.x.") + < 0) { + return 0; + } } e->v.Name.ctx = ctx; break; @@ -585,7 +616,14 @@ if (!strcmp(STR(child), "None")) { ast_error(child, "assignment to None"); return NULL; - } + } + if (Py_Py3kWarningFlag && + !(strcmp(STR(child), "True") && strcmp(STR(child), "False")) && + ast_warn(c, n, PyExc_DeprecationWarning, + "Assignment to True or False is forbidden in 3.x.") + < 0) { + return NULL; + } arg = Name(NEW_IDENTIFIER(child), Store, LINENO(child), child->n_col_offset, c->c_arena); } @@ -699,6 +737,14 @@ ast_error(CHILD(ch, 0), "assignment to None"); goto error; } + if (Py_Py3kWarningFlag && + !(strcmp(STR(CHILD(ch, 0)), "True") && + strcmp(STR(CHILD(ch, 0)), "False")) && + ast_warn(c, n, PyExc_DeprecationWarning, + "Assignment to True or False is forbidden in 3.x.") + < 0) { + goto error; + } name = Name(NEW_IDENTIFIER(CHILD(ch, 0)), Param, LINENO(ch), ch->n_col_offset, c->c_arena); @@ -714,6 +760,14 @@ ast_error(CHILD(n, i+1), "assignment to None"); goto error; } + if (Py_Py3kWarningFlag && + !(strcmp(STR(CHILD(n, i+1)), "True") && + strcmp(STR(CHILD(n, i+1)), "False")) && + ast_warn(c, n, PyExc_DeprecationWarning, + "Assignment to True or False is forbidden in 3.x.") + < 0) { + goto error; + } vararg = NEW_IDENTIFIER(CHILD(n, i+1)); i += 3; break; @@ -722,6 +776,14 @@ ast_error(CHILD(n, i+1), "assignment to None"); goto error; } + if (Py_Py3kWarningFlag && + !(strcmp(STR(CHILD(n, i+1)), "True") && + strcmp(STR(CHILD(n, i+1)), "False")) && + ast_warn(c, n, PyExc_DeprecationWarning, + "Assignment to True or False is forbidden in 3.x.") + < 0) { + goto error; + } kwarg = NEW_IDENTIFIER(CHILD(n, i+1)); i += 3; break; @@ -848,6 +910,14 @@ ast_error(CHILD(n, name_i), "assignment to None"); return NULL; } + else if (Py_Py3kWarningFlag && + !(strcmp(STR(CHILD(n, name_i)), "True") && + strcmp(STR(CHILD(n, name_i)), "False")) && + ast_warn(c, n, PyExc_DeprecationWarning, + "Assignment to True or False is forbidden in 3.x.") + < 0) { + return NULL; + } args = ast_for_arguments(c, CHILD(n, name_i + 1)); if (!args) return NULL; @@ -1363,14 +1433,11 @@ } case BACKQUOTE: { /* repr */ expr_ty expression; - if (Py_Py3kWarningFlag) { - if (PyErr_WarnExplicit(PyExc_DeprecationWarning, - "backquote not supported in 3.x; use repr()", - c->c_filename, LINENO(n), - NULL, NULL)) { - return NULL; - } - } + if (Py_Py3kWarningFlag && + ast_warn(c, n, PyExc_DeprecationWarning, + "backquote not supported in 3.x; use repr()") + < 0) + return NULL; expression = ast_for_testlist(c, CHILD(n, 1)); if (!expression) return NULL; @@ -1925,6 +1992,14 @@ ast_error(CHILD(ch, 0), "assignment to None"); return NULL; } + if (Py_Py3kWarningFlag && + !(strcmp(PyString_AS_STRING(key), "True") && + strcmp(PyString_AS_STRING(key), "False")) && + ast_warn(c, n, PyExc_DeprecationWarning, + "Assignment to True or False is forbidden in 3.x.") + < 0) { + return NULL; + } e = ast_for_expr(c, CHILD(ch, 2)); if (!e) return NULL; @@ -2055,6 +2130,15 @@ ast_error(ch, "assignment to None"); return NULL; } + if (Py_Py3kWarningFlag) { + if (!(strcmp(var_name, "True") && + strcmp(var_name, "False")) && + ast_warn(c, n, PyExc_DeprecationWarning, + "Assignment to True or False is forbidden in 3.x.") + < 0) { + return NULL; + } + } break; } case Attribute_kind: @@ -3001,6 +3085,14 @@ ast_error(n, "assignment to None"); return NULL; } + if (Py_Py3kWarningFlag && + !(strcmp(STR(CHILD(n, 1)), "True") && + strcmp(STR(CHILD(n, 1)), "False")) && + ast_warn(c, n, PyExc_DeprecationWarning, + "Assignment to True or False is forbidden in 3.x.") + < 0) { + return NULL; + } if (NCH(n) == 4) { s = ast_for_suite(c, CHILD(n, 3)); @@ -3365,4 +3457,4 @@ onError: Py_XDECREF(v); return NULL; -} +} \ No newline at end of file Index: Lib/test/test_py3kwarn.py =================================================================== --- Lib/test/test_py3kwarn.py (revision 62663) +++ Lib/test/test_py3kwarn.py (working copy) @@ -10,6 +10,41 @@ class TestPy3KWarnings(unittest.TestCase): + def test_bool_assign(self): + # So we don't screw up our globals + def safe_exec(expr): + exec expr in {} + + expected = "Assignment to True or False is forbidden in 3.x." + with catch_warning() as w: + safe_exec("True = False") + self.assertWarning(None, w, expected) + with catch_warning() as w: + safe_exec("False = True") + self.assertWarning(None, w, expected) + with catch_warning() as w: + try: + safe_exec("obj.False = True") + except NameError: pass + self.assertWarning(None, w, expected) + with catch_warning() as w: + try: + safe_exec("obj.True = False") + except NameError: pass + self.assertWarning(None, w, expected) + with catch_warning() as w: + safe_exec("def False(): pass") + self.assertWarning(None, w, expected) + with catch_warning() as w: + safe_exec("def True(): pass") + self.assertWarning(None, w, expected) + with catch_warning() as w: + safe_exec("class False: pass") + self.assertWarning(None, w, expected) + with catch_warning() as w: + safe_exec("class True: pass") + self.assertWarning(None, w, expected) + def test_type_inequality_comparisons(self): expected = 'type inequality comparisons not supported in 3.x' with catch_warning() as w: