Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 9c8a086

Browse files
committed
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).
1 parent a4deda0 commit 9c8a086

2 files changed

Lines changed: 100 additions & 30 deletions

File tree

Misc/NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,10 @@ Type/class unification and new-style classes
8484
Core and builtins
8585
-----------------
8686

87+
- Assignment to None has long been frowned upon. Now there's a
88+
warning message when you do this. It also warns against assignment
89+
to True or False.
90+
8791
- A frame object's f_lineno attribute can now be written to from a
8892
trace function to change which line will execute next. A command to
8993
exploit this from pdb has been added. [SF patch #643835]

Python/compile.c

Lines changed: 96 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -575,6 +575,7 @@ block_pop(struct compiling *c, int type)
575575
/* Prototype forward declarations */
576576

577577
static int issue_warning(const char *, const char *, int);
578+
static int symtable_warn(struct symtable *, char *);
578579
static int com_init(struct compiling *, const char *);
579580
static void com_free(struct compiling *);
580581
static void com_push(struct compiling *, int);
@@ -1006,6 +1007,64 @@ none_assignment_check(struct compiling *c, char *name, int assigning)
10061007
return 0;
10071008
}
10081009

1010+
static int num_literals = 3;
1011+
static char *literal_names[] = {"None", "True", "False"};
1012+
static PyObject *literals;
1013+
1014+
static int
1015+
init_literals(void)
1016+
{
1017+
int i;
1018+
1019+
literals = PyDict_New();
1020+
if (literals == NULL)
1021+
return -1;
1022+
for (i = 0; i < num_literals; i++)
1023+
if (PyDict_SetItemString(literals, literal_names[i],
1024+
Py_None) < 0)
1025+
return -1;
1026+
return 0;
1027+
}
1028+
1029+
static int
1030+
check_literal(PyObject *name, struct compiling *c, struct symtable *st)
1031+
{
1032+
/* check for literal names that will become keywords in the future */
1033+
if (literals == NULL && init_literals() < 0)
1034+
return -1;
1035+
if (!PyString_Check(name))
1036+
return -1;
1037+
if (PyDict_GetItem(literals, name)) {
1038+
char buf[1024];
1039+
PyOS_snprintf(buf, sizeof(buf), "'%s' may become a keyword",
1040+
PyString_AS_STRING(name));
1041+
if (c && (issue_warning(buf, c->c_filename, c->c_lineno) < 0))
1042+
return -1;
1043+
if (st && (symtable_warn(st, buf) < 0))
1044+
return -1;
1045+
}
1046+
return 0;
1047+
}
1048+
1049+
static int
1050+
check_literal_str(const char *name, struct compiling *c, struct symtable *st)
1051+
{
1052+
int i;
1053+
1054+
for (i = 0; i < num_literals; i++)
1055+
if (strcmp(literal_names[i], name) == 0) {
1056+
char buf[1024];
1057+
PyOS_snprintf(buf, sizeof(buf),
1058+
"'%s' may become a keyword", name);
1059+
if (c &&
1060+
issue_warning(buf, c->c_filename, c->c_lineno) < 0)
1061+
return -1;
1062+
if (st && symtable_warn(st, buf) < 0)
1063+
return -1;
1064+
}
1065+
return 0;
1066+
}
1067+
10091068
static void
10101069
com_addop_varname(struct compiling *c, int kind, char *name)
10111070
{
@@ -1063,6 +1122,14 @@ com_addop_varname(struct compiling *c, int kind, char *name)
10631122
}
10641123
Py_DECREF(v);
10651124

1125+
if (kind == VAR_STORE || kind == VAR_DELETE) {
1126+
if (check_literal(v, c, NULL) < 0) {
1127+
c->c_errors++;
1128+
i = 255;
1129+
goto done;
1130+
}
1131+
}
1132+
10661133
switch (kind) {
10671134
case VAR_LOAD:
10681135
switch (scope) {
@@ -1130,6 +1197,7 @@ com_addopname(struct compiling *c, int op, node *n)
11301197
/* XXX it is possible to write this code without the 1000
11311198
chars on the total length of dotted names, I just can't be
11321199
bothered right now */
1200+
11331201
if (TYPE(n) == STAR)
11341202
name = "*";
11351203
else if (TYPE(n) == dotted_name) {
@@ -1138,6 +1206,10 @@ com_addopname(struct compiling *c, int op, node *n)
11381206
name = buffer;
11391207
for (i = 0; i < NCH(n); i += 2) {
11401208
char *s = STR(CHILD(n, i));
1209+
if (check_literal_str(s, c, NULL) < 0) {
1210+
name = NULL;
1211+
break;
1212+
}
11411213
if (p + strlen(s) > buffer + (sizeof buffer) - 2) {
11421214
com_error(c, PyExc_MemoryError,
11431215
"dotted_name too long");
@@ -1153,6 +1225,8 @@ com_addopname(struct compiling *c, int op, node *n)
11531225
else {
11541226
REQ(n, NAME);
11551227
name = STR(n);
1228+
if (check_literal_str(name, c, NULL) < 0)
1229+
name = NULL;
11561230
}
11571231
com_addop_name(c, op, name);
11581232
}
@@ -2972,9 +3046,13 @@ com_import_stmt(struct compiling *c, node *n)
29723046
} else {
29733047
tup = PyTuple_New((NCH(n) - 2)/2);
29743048
for (i = 3; i < NCH(n); i += 2) {
3049+
char *s = STR(CHILD(CHILD(n, i), 0));
3050+
if (check_literal_str(s, c, NULL) < 0) {
3051+
c->c_errors++;
3052+
return;
3053+
}
29753054
PyTuple_SET_ITEM(tup, (i-3)/2,
2976-
PyString_FromString(STR(
2977-
CHILD(CHILD(n, i), 0))));
3055+
PyString_FromString(s));
29783056
}
29793057
}
29803058
com_addoparg(c, LOAD_CONST, com_addconst(c, tup));
@@ -3914,40 +3992,23 @@ com_fplist(struct compiling *c, node *n)
39143992
static void
39153993
com_arglist(struct compiling *c, node *n)
39163994
{
3917-
int nch, i, narg;
3995+
int i;
39183996
int complex = 0;
3919-
char nbuf[30];
39203997
REQ(n, varargslist);
39213998
/* varargslist:
39223999
(fpdef ['=' test] ',')* (fpdef ['=' test] | '*' .....) */
3923-
nch = NCH(n);
3924-
/* Enter all arguments in table of locals */
3925-
for (i = 0, narg = 0; i < nch; i++) {
3926-
node *ch = CHILD(n, i);
3927-
node *fp;
3928-
if (TYPE(ch) == STAR || TYPE(ch) == DOUBLESTAR)
3929-
break;
3930-
REQ(ch, fpdef); /* fpdef: NAME | '(' fplist ')' */
3931-
fp = CHILD(ch, 0);
3932-
if (TYPE(fp) != NAME) {
3933-
PyOS_snprintf(nbuf, sizeof(nbuf), ".%d", i);
4000+
/* Check if the argument list includes nested tuples */
4001+
for (i = 0; i < NCH(n); i++)
4002+
if (TYPE(CHILD(n, i)) == LPAR) {
39344003
complex = 1;
3935-
}
3936-
narg++;
3937-
/* all name updates handled by symtable */
3938-
if (++i >= nch)
39394004
break;
3940-
ch = CHILD(n, i);
3941-
if (TYPE(ch) == EQUAL)
3942-
i += 2;
3943-
else
3944-
REQ(ch, COMMA);
3945-
}
4005+
}
4006+
/* If it does, generate code to unpack them. */
39464007
if (complex) {
39474008
/* Generate code for complex arguments only after
39484009
having counted the simple arguments */
39494010
int ilocal = 0;
3950-
for (i = 0; i < nch; i++) {
4011+
for (i = 0; i < NCH(n); i++) {
39514012
node *ch = CHILD(n, i);
39524013
node *fp;
39534014
if (TYPE(ch) == STAR || TYPE(ch) == DOUBLESTAR)
@@ -3960,7 +4021,7 @@ com_arglist(struct compiling *c, node *n)
39604021
com_fpdef(c, ch);
39614022
}
39624023
ilocal++;
3963-
if (++i >= nch)
4024+
if (++i >= NCH(n))
39644025
break;
39654026
ch = CHILD(n, i);
39664027
if (TYPE(ch) == EQUAL)
@@ -5359,7 +5420,7 @@ static void
53595420
symtable_params(struct symtable *st, node *n)
53605421
{
53615422
int i, complex = -1, ext = 0;
5362-
node *c = NULL;
5423+
node *c = NULL, *ch = NULL;
53635424

53645425
if (TYPE(n) == parameters) {
53655426
n = CHILD(n, 1);
@@ -5376,9 +5437,14 @@ symtable_params(struct symtable *st, node *n)
53765437
if (TYPE(c) == test) {
53775438
continue;
53785439
}
5379-
if (TYPE(CHILD(c, 0)) == NAME)
5440+
ch = CHILD(c, 0);
5441+
if (TYPE(ch) == NAME) {
5442+
if (check_literal_str(STR(ch), NULL, st) < 0) {
5443+
st->st_errors++;
5444+
return;
5445+
}
53805446
symtable_add_def(st, STR(CHILD(c, 0)), DEF_PARAM);
5381-
else {
5447+
} else {
53825448
char nbuf[30];
53835449
PyOS_snprintf(nbuf, sizeof(nbuf), ".%d", i);
53845450
symtable_add_def(st, nbuf, DEF_PARAM);

0 commit comments

Comments
 (0)