summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Peterson <benjamin@python.org>2008-06-08 22:52:37 (GMT)
committerBenjamin Peterson <benjamin@python.org>2008-06-08 22:52:37 (GMT)
commitd5efd2040642d08e64011fb6e81193002269aad4 (patch)
tree83d5030f13f6fd161e1dbe81cfa5c95125de1159
parentcbd78133fa68bd646bc0e77ea28cb73ed5a9c188 (diff)
downloadcpython-d5efd2040642d08e64011fb6e81193002269aad4.zip
cpython-d5efd2040642d08e64011fb6e81193002269aad4.tar.gz
cpython-d5efd2040642d08e64011fb6e81193002269aad4.tar.bz2
Warn about assigning to Py3k keywords (True and False)
-rw-r--r--Lib/test/test_py3kwarn.py49
-rw-r--r--Python/ast.c60
2 files changed, 76 insertions, 33 deletions
diff --git a/Lib/test/test_py3kwarn.py b/Lib/test/test_py3kwarn.py
index 617d996..18298fe 100644
--- a/Lib/test/test_py3kwarn.py
+++ b/Lib/test/test_py3kwarn.py
@@ -16,6 +16,55 @@ class TestPy3KWarnings(unittest.TestCase):
exec "`2`" in {}
self.assertWarning(None, w, expected)
+ def test_bool_assign(self):
+ # So we don't screw up our globals
+ def safe_exec(expr):
+ def f(**kwargs): pass
+ exec expr in {'f' : f}
+
+ 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)
+ with catch_warning() as w:
+ safe_exec("def f(True=43): pass")
+ self.assertWarning(None, w, expected)
+ with catch_warning() as w:
+ safe_exec("def f(False=None): pass")
+ self.assertWarning(None, w, expected)
+ with catch_warning() as w:
+ safe_exec("f(False=True)")
+ self.assertWarning(None, w, expected)
+ with catch_warning() as w:
+ safe_exec("f(True=1)")
+ 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:
diff --git a/Python/ast.c b/Python/ast.c
index ad78840..ab166e8 100644
--- a/Python/ast.c
+++ b/Python/ast.c
@@ -126,6 +126,17 @@ ast_warn(struct compiling *c, const node *n, char *msg)
return 1;
}
+static int
+forbidden_check(struct compiling *c, const node *n, const char *x)
+{
+ if (!strcmp(x, "None"))
+ return ast_error(n, "assignment to None");
+ if (Py_Py3kWarningFlag && !(strcmp(x, "True") && strcmp(x, "False")) &&
+ !ast_warn(c, n, "assignment to True or False is forbidden in 3.x"))
+ return 0;
+ return 1;
+}
+
/* num_stmts() returns number of contained statements.
Use this routine to determine how big a sequence is needed for
@@ -364,20 +375,18 @@ set_context(struct compiling *c, expr_ty e, expr_context_ty ctx, const node *n)
switch (e->kind) {
case Attribute_kind:
- if (ctx == Store &&
- !strcmp(PyBytes_AS_STRING(e->v.Attribute.attr), "None")) {
- return ast_error(n, "assignment to None");
- }
+ if (ctx == Store && !forbidden_check(c, n,
+ PyBytes_AS_STRING(e->v.Attribute.attr)))
+ return 0;
e->v.Attribute.ctx = ctx;
break;
case Subscript_kind:
e->v.Subscript.ctx = ctx;
break;
case Name_kind:
- if (ctx == Store &&
- !strcmp(PyBytes_AS_STRING(e->v.Name.id), "None")) {
- return ast_error(n, "assignment to None");
- }
+ if (ctx == Store && !forbidden_check(c, n,
+ PyBytes_AS_STRING(e->v.Name.id)))
+ return 0;
e->v.Name.ctx = ctx;
break;
case List_kind:
@@ -595,10 +604,8 @@ set_name:
/* fpdef_node is either a NAME or an fplist */
child = CHILD(fpdef_node, 0);
if (TYPE(child) == NAME) {
- if (!strcmp(STR(child), "None")) {
- ast_error(child, "assignment to None");
- return NULL;
- }
+ if (!forbidden_check(c, n, STR(child)))
+ return NULL;
arg = Name(NEW_IDENTIFIER(child), Store, LINENO(child),
child->n_col_offset, c->c_arena);
}
@@ -708,10 +715,8 @@ ast_for_arguments(struct compiling *c, const node *n)
}
if (TYPE(CHILD(ch, 0)) == NAME) {
expr_ty name;
- if (!strcmp(STR(CHILD(ch, 0)), "None")) {
- ast_error(CHILD(ch, 0), "assignment to None");
+ if (!forbidden_check(c, n, STR(CHILD(ch, 0))))
goto error;
- }
name = Name(NEW_IDENTIFIER(CHILD(ch, 0)),
Param, LINENO(ch), ch->n_col_offset,
c->c_arena);
@@ -723,18 +728,14 @@ ast_for_arguments(struct compiling *c, const node *n)
i += 2; /* the name and the comma */
break;
case STAR:
- if (!strcmp(STR(CHILD(n, i+1)), "None")) {
- ast_error(CHILD(n, i+1), "assignment to None");
+ if (!forbidden_check(c, CHILD(n, i+1), STR(CHILD(n, i+1))))
goto error;
- }
vararg = NEW_IDENTIFIER(CHILD(n, i+1));
i += 3;
break;
case DOUBLESTAR:
- if (!strcmp(STR(CHILD(n, i+1)), "None")) {
- ast_error(CHILD(n, i+1), "assignment to None");
+ if (!forbidden_check(c, CHILD(n, i+1), STR(CHILD(n, i+1))))
goto error;
- }
kwarg = NEW_IDENTIFIER(CHILD(n, i+1));
i += 3;
break;
@@ -857,10 +858,8 @@ ast_for_funcdef(struct compiling *c, const node *n, asdl_seq *decorator_seq)
name = NEW_IDENTIFIER(CHILD(n, name_i));
if (!name)
return NULL;
- else if (!strcmp(STR(CHILD(n, name_i)), "None")) {
- ast_error(CHILD(n, name_i), "assignment to None");
+ else if (!forbidden_check(c, CHILD(n, name_i), STR(CHILD(n, name_i))))
return NULL;
- }
args = ast_for_arguments(c, CHILD(n, name_i + 1));
if (!args)
return NULL;
@@ -1929,10 +1928,8 @@ ast_for_call(struct compiling *c, const node *n, expr_ty func)
return NULL;
}
key = e->v.Name.id;
- if (!strcmp(PyBytes_AS_STRING(key), "None")) {
- ast_error(CHILD(ch, 0), "assignment to None");
+ if (!forbidden_check(c, CHILD(ch, 0), PyBytes_AS_STRING(key)))
return NULL;
- }
e = ast_for_expr(c, CHILD(ch, 2));
if (!e)
return NULL;
@@ -2059,10 +2056,9 @@ ast_for_expr_stmt(struct compiling *c, const node *n)
return NULL;
case Name_kind: {
const char *var_name = PyBytes_AS_STRING(expr1->v.Name.id);
- if (var_name[0] == 'N' && !strcmp(var_name, "None")) {
- ast_error(ch, "assignment to None");
+ if ((var_name[0] == 'N' || var_name[0] == 'T' || var_name[0] == 'F') &&
+ !forbidden_check(c, ch, var_name))
return NULL;
- }
break;
}
case Attribute_kind:
@@ -3005,10 +3001,8 @@ ast_for_classdef(struct compiling *c, const node *n, asdl_seq *decorator_seq)
REQ(n, classdef);
- if (!strcmp(STR(CHILD(n, 1)), "None")) {
- ast_error(n, "assignment to None");
+ if (!forbidden_check(c, n, STR(CHILD(n, 1))))
return NULL;
- }
if (NCH(n) == 4) {
s = ast_for_suite(c, CHILD(n, 3));