summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>2002-12-23 16:35:23 (GMT)
committerGuido van Rossum <guido@python.org>2002-12-23 16:35:23 (GMT)
commit9c8a0866c924ef92221a2c6e55f1774ee6feb408 (patch)
treeeec872ba9e086e8e9f274befb10b0f93e413e84f
parenta4deda0d11b1369dcb74226094c95f86fe716cbc (diff)
downloadcpython-9c8a0866c924ef92221a2c6e55f1774ee6feb408.zip
cpython-9c8a0866c924ef92221a2c6e55f1774ee6feb408.tar.gz
cpython-9c8a0866c924ef92221a2c6e55f1774ee6feb408.tar.bz2
Add warning for assignment to None, True and False. This is patch
549213 by Jeremy (checking in for him since he's away and busy).
-rw-r--r--Misc/NEWS4
-rw-r--r--Python/compile.c126
2 files changed, 100 insertions, 30 deletions
diff --git a/Misc/NEWS b/Misc/NEWS
index 5cc62bf..8da277a 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -84,6 +84,10 @@ Type/class unification and new-style classes
Core and builtins
-----------------
+- Assignment to None has long been frowned upon. Now there's a
+ warning message when you do this. It also warns against assignment
+ to True or False.
+
- A frame object's f_lineno attribute can now be written to from a
trace function to change which line will execute next. A command to
exploit this from pdb has been added. [SF patch #643835]
diff --git a/Python/compile.c b/Python/compile.c
index c7ca534..8b1652d 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -575,6 +575,7 @@ block_pop(struct compiling *c, int type)
/* Prototype forward declarations */
static int issue_warning(const char *, const char *, int);
+static int symtable_warn(struct symtable *, char *);
static int com_init(struct compiling *, const char *);
static void com_free(struct compiling *);
static void com_push(struct compiling *, int);
@@ -1006,6 +1007,64 @@ none_assignment_check(struct compiling *c, char *name, int assigning)
return 0;
}
+static int num_literals = 3;
+static char *literal_names[] = {"None", "True", "False"};
+static PyObject *literals;
+
+static int
+init_literals(void)
+{
+ int i;
+
+ literals = PyDict_New();
+ if (literals == NULL)
+ return -1;
+ for (i = 0; i < num_literals; i++)
+ if (PyDict_SetItemString(literals, literal_names[i],
+ Py_None) < 0)
+ return -1;
+ return 0;
+}
+
+static int
+check_literal(PyObject *name, struct compiling *c, struct symtable *st)
+{
+ /* check for literal names that will become keywords in the future */
+ if (literals == NULL && init_literals() < 0)
+ return -1;
+ if (!PyString_Check(name))
+ return -1;
+ if (PyDict_GetItem(literals, name)) {
+ char buf[1024];
+ PyOS_snprintf(buf, sizeof(buf), "'%s' may become a keyword",
+ PyString_AS_STRING(name));
+ if (c && (issue_warning(buf, c->c_filename, c->c_lineno) < 0))
+ return -1;
+ if (st && (symtable_warn(st, buf) < 0))
+ return -1;
+ }
+ return 0;
+}
+
+static int
+check_literal_str(const char *name, struct compiling *c, struct symtable *st)
+{
+ int i;
+
+ for (i = 0; i < num_literals; i++)
+ if (strcmp(literal_names[i], name) == 0) {
+ char buf[1024];
+ PyOS_snprintf(buf, sizeof(buf),
+ "'%s' may become a keyword", name);
+ if (c &&
+ issue_warning(buf, c->c_filename, c->c_lineno) < 0)
+ return -1;
+ if (st && symtable_warn(st, buf) < 0)
+ return -1;
+ }
+ return 0;
+}
+
static void
com_addop_varname(struct compiling *c, int kind, char *name)
{
@@ -1063,6 +1122,14 @@ com_addop_varname(struct compiling *c, int kind, char *name)
}
Py_DECREF(v);
+ if (kind == VAR_STORE || kind == VAR_DELETE) {
+ if (check_literal(v, c, NULL) < 0) {
+ c->c_errors++;
+ i = 255;
+ goto done;
+ }
+ }
+
switch (kind) {
case VAR_LOAD:
switch (scope) {
@@ -1130,6 +1197,7 @@ com_addopname(struct compiling *c, int op, node *n)
/* XXX it is possible to write this code without the 1000
chars on the total length of dotted names, I just can't be
bothered right now */
+
if (TYPE(n) == STAR)
name = "*";
else if (TYPE(n) == dotted_name) {
@@ -1138,6 +1206,10 @@ com_addopname(struct compiling *c, int op, node *n)
name = buffer;
for (i = 0; i < NCH(n); i += 2) {
char *s = STR(CHILD(n, i));
+ if (check_literal_str(s, c, NULL) < 0) {
+ name = NULL;
+ break;
+ }
if (p + strlen(s) > buffer + (sizeof buffer) - 2) {
com_error(c, PyExc_MemoryError,
"dotted_name too long");
@@ -1153,6 +1225,8 @@ com_addopname(struct compiling *c, int op, node *n)
else {
REQ(n, NAME);
name = STR(n);
+ if (check_literal_str(name, c, NULL) < 0)
+ name = NULL;
}
com_addop_name(c, op, name);
}
@@ -2972,9 +3046,13 @@ com_import_stmt(struct compiling *c, node *n)
} else {
tup = PyTuple_New((NCH(n) - 2)/2);
for (i = 3; i < NCH(n); i += 2) {
+ char *s = STR(CHILD(CHILD(n, i), 0));
+ if (check_literal_str(s, c, NULL) < 0) {
+ c->c_errors++;
+ return;
+ }
PyTuple_SET_ITEM(tup, (i-3)/2,
- PyString_FromString(STR(
- CHILD(CHILD(n, i), 0))));
+ PyString_FromString(s));
}
}
com_addoparg(c, LOAD_CONST, com_addconst(c, tup));
@@ -3914,40 +3992,23 @@ com_fplist(struct compiling *c, node *n)
static void
com_arglist(struct compiling *c, node *n)
{
- int nch, i, narg;
+ int i;
int complex = 0;
- char nbuf[30];
REQ(n, varargslist);
/* varargslist:
(fpdef ['=' test] ',')* (fpdef ['=' test] | '*' .....) */
- nch = NCH(n);
- /* Enter all arguments in table of locals */
- for (i = 0, narg = 0; i < nch; i++) {
- node *ch = CHILD(n, i);
- node *fp;
- if (TYPE(ch) == STAR || TYPE(ch) == DOUBLESTAR)
- break;
- REQ(ch, fpdef); /* fpdef: NAME | '(' fplist ')' */
- fp = CHILD(ch, 0);
- if (TYPE(fp) != NAME) {
- PyOS_snprintf(nbuf, sizeof(nbuf), ".%d", i);
+ /* Check if the argument list includes nested tuples */
+ for (i = 0; i < NCH(n); i++)
+ if (TYPE(CHILD(n, i)) == LPAR) {
complex = 1;
- }
- narg++;
- /* all name updates handled by symtable */
- if (++i >= nch)
break;
- ch = CHILD(n, i);
- if (TYPE(ch) == EQUAL)
- i += 2;
- else
- REQ(ch, COMMA);
- }
+ }
+ /* If it does, generate code to unpack them. */
if (complex) {
/* Generate code for complex arguments only after
having counted the simple arguments */
int ilocal = 0;
- for (i = 0; i < nch; i++) {
+ for (i = 0; i < NCH(n); i++) {
node *ch = CHILD(n, i);
node *fp;
if (TYPE(ch) == STAR || TYPE(ch) == DOUBLESTAR)
@@ -3960,7 +4021,7 @@ com_arglist(struct compiling *c, node *n)
com_fpdef(c, ch);
}
ilocal++;
- if (++i >= nch)
+ if (++i >= NCH(n))
break;
ch = CHILD(n, i);
if (TYPE(ch) == EQUAL)
@@ -5359,7 +5420,7 @@ static void
symtable_params(struct symtable *st, node *n)
{
int i, complex = -1, ext = 0;
- node *c = NULL;
+ node *c = NULL, *ch = NULL;
if (TYPE(n) == parameters) {
n = CHILD(n, 1);
@@ -5376,9 +5437,14 @@ symtable_params(struct symtable *st, node *n)
if (TYPE(c) == test) {
continue;
}
- if (TYPE(CHILD(c, 0)) == NAME)
+ ch = CHILD(c, 0);
+ if (TYPE(ch) == NAME) {
+ if (check_literal_str(STR(ch), NULL, st) < 0) {
+ st->st_errors++;
+ return;
+ }
symtable_add_def(st, STR(CHILD(c, 0)), DEF_PARAM);
- else {
+ } else {
char nbuf[30];
PyOS_snprintf(nbuf, sizeof(nbuf), ".%d", i);
symtable_add_def(st, nbuf, DEF_PARAM);