mirror of
https://github.com/python/cpython.git
synced 2025-07-24 11:44:31 +00:00
Issue #27999: Make "global after use" a SyntaxError, and ditto for nonlocal.
Patch by Ivan Levkivskyi.
This commit is contained in:
parent
95e502e7a6
commit
6cff8744a0
4 changed files with 59 additions and 71 deletions
|
@ -903,11 +903,12 @@ block textually preceding that :keyword:`global` statement.
|
||||||
|
|
||||||
Names listed in a :keyword:`global` statement must not be defined as formal
|
Names listed in a :keyword:`global` statement must not be defined as formal
|
||||||
parameters or in a :keyword:`for` loop control target, :keyword:`class`
|
parameters or in a :keyword:`for` loop control target, :keyword:`class`
|
||||||
definition, function definition, or :keyword:`import` statement.
|
definition, function definition, :keyword:`import` statement, or variable
|
||||||
|
annotation.
|
||||||
|
|
||||||
.. impl-detail::
|
.. impl-detail::
|
||||||
|
|
||||||
The current implementation does not enforce the two restrictions, but
|
The current implementation does not enforce some of these restriction, but
|
||||||
programs should not abuse this freedom, as future implementations may enforce
|
programs should not abuse this freedom, as future implementations may enforce
|
||||||
them or silently change the meaning of the program.
|
them or silently change the meaning of the program.
|
||||||
|
|
||||||
|
|
|
@ -366,7 +366,23 @@ build. The number of blocks must be greater than CO_MAXBLOCKS. SF #1565514
|
||||||
...
|
...
|
||||||
SyntaxError: too many statically nested blocks
|
SyntaxError: too many statically nested blocks
|
||||||
|
|
||||||
Misuse of the nonlocal statement can lead to a few unique syntax errors.
|
Misuse of the nonlocal and global statement can lead to a few unique syntax errors.
|
||||||
|
|
||||||
|
>>> def f():
|
||||||
|
... x = 1
|
||||||
|
... global x
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
SyntaxError: name 'x' is assigned to before global declaration
|
||||||
|
|
||||||
|
>>> def f():
|
||||||
|
... x = 1
|
||||||
|
... def g():
|
||||||
|
... print(x)
|
||||||
|
... nonlocal x
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
SyntaxError: name 'x' is used prior to nonlocal declaration
|
||||||
|
|
||||||
>>> def f(x):
|
>>> def f(x):
|
||||||
... nonlocal x
|
... nonlocal x
|
||||||
|
|
|
@ -10,6 +10,9 @@ What's New in Python 3.6.0 beta 1
|
||||||
Core and Builtins
|
Core and Builtins
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
|
- Issue #27999: Make "global after use" a SyntaxError, and ditto for nonlocal.
|
||||||
|
Patch by Ivan Levkivskyi.
|
||||||
|
|
||||||
- Issue #28003: Implement PEP 525 -- Asynchronous Generators.
|
- Issue #28003: Implement PEP 525 -- Asynchronous Generators.
|
||||||
|
|
||||||
- Issue #27985: Implement PEP 526 -- Syntax for Variable Annotations.
|
- Issue #27985: Implement PEP 526 -- Syntax for Variable Annotations.
|
||||||
|
|
|
@ -6,16 +6,22 @@
|
||||||
|
|
||||||
/* error strings used for warnings */
|
/* error strings used for warnings */
|
||||||
#define GLOBAL_AFTER_ASSIGN \
|
#define GLOBAL_AFTER_ASSIGN \
|
||||||
"name '%.400s' is assigned to before global declaration"
|
"name '%U' is assigned to before global declaration"
|
||||||
|
|
||||||
#define NONLOCAL_AFTER_ASSIGN \
|
#define NONLOCAL_AFTER_ASSIGN \
|
||||||
"name '%.400s' is assigned to before nonlocal declaration"
|
"name '%U' is assigned to before nonlocal declaration"
|
||||||
|
|
||||||
#define GLOBAL_AFTER_USE \
|
#define GLOBAL_AFTER_USE \
|
||||||
"name '%.400s' is used prior to global declaration"
|
"name '%U' is used prior to global declaration"
|
||||||
|
|
||||||
#define NONLOCAL_AFTER_USE \
|
#define NONLOCAL_AFTER_USE \
|
||||||
"name '%.400s' is used prior to nonlocal declaration"
|
"name '%U' is used prior to nonlocal declaration"
|
||||||
|
|
||||||
|
#define GLOBAL_ANNOT \
|
||||||
|
"annotated name '%U' can't be global"
|
||||||
|
|
||||||
|
#define NONLOCAL_ANNOT \
|
||||||
|
"annotated name '%U' can't be nonlocal"
|
||||||
|
|
||||||
#define IMPORT_STAR_WARNING "import * only allowed at module level"
|
#define IMPORT_STAR_WARNING "import * only allowed at module level"
|
||||||
|
|
||||||
|
@ -161,7 +167,6 @@ PyTypeObject PySTEntry_Type = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static int symtable_analyze(struct symtable *st);
|
static int symtable_analyze(struct symtable *st);
|
||||||
static int symtable_warn(struct symtable *st, const char *msg, int lineno);
|
|
||||||
static int symtable_enter_block(struct symtable *st, identifier name,
|
static int symtable_enter_block(struct symtable *st, identifier name,
|
||||||
_Py_block_ty block, void *ast, int lineno,
|
_Py_block_ty block, void *ast, int lineno,
|
||||||
int col_offset);
|
int col_offset);
|
||||||
|
@ -907,27 +912,6 @@ symtable_analyze(struct symtable *st)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
symtable_warn(struct symtable *st, const char *msg, int lineno)
|
|
||||||
{
|
|
||||||
PyObject *message = PyUnicode_FromString(msg);
|
|
||||||
if (message == NULL)
|
|
||||||
return 0;
|
|
||||||
if (PyErr_WarnExplicitObject(PyExc_SyntaxWarning, message, st->st_filename,
|
|
||||||
lineno, NULL, NULL) < 0) {
|
|
||||||
Py_DECREF(message);
|
|
||||||
if (PyErr_ExceptionMatches(PyExc_SyntaxWarning)) {
|
|
||||||
PyErr_SetString(PyExc_SyntaxError, msg);
|
|
||||||
PyErr_SyntaxLocationObject(st->st_filename, st->st_cur->ste_lineno,
|
|
||||||
st->st_cur->ste_col_offset);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
Py_DECREF(message);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* symtable_enter_block() gets a reference via ste_new.
|
/* symtable_enter_block() gets a reference via ste_new.
|
||||||
This reference is released when the block is exited, via the DECREF
|
This reference is released when the block is exited, via the DECREF
|
||||||
in symtable_exit_block().
|
in symtable_exit_block().
|
||||||
|
@ -1212,9 +1196,8 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
|
||||||
if ((cur & (DEF_GLOBAL | DEF_NONLOCAL))
|
if ((cur & (DEF_GLOBAL | DEF_NONLOCAL))
|
||||||
&& s->v.AnnAssign.simple) {
|
&& s->v.AnnAssign.simple) {
|
||||||
PyErr_Format(PyExc_SyntaxError,
|
PyErr_Format(PyExc_SyntaxError,
|
||||||
"annotated name '%U' can't be %s",
|
cur & DEF_GLOBAL ? GLOBAL_ANNOT : NONLOCAL_ANNOT,
|
||||||
e_name->v.Name.id,
|
e_name->v.Name.id);
|
||||||
cur & DEF_GLOBAL ? "global" : "nonlocal");
|
|
||||||
PyErr_SyntaxLocationObject(st->st_filename,
|
PyErr_SyntaxLocationObject(st->st_filename,
|
||||||
s->lineno,
|
s->lineno,
|
||||||
s->col_offset);
|
s->col_offset);
|
||||||
|
@ -1297,31 +1280,24 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
|
||||||
long cur = symtable_lookup(st, name);
|
long cur = symtable_lookup(st, name);
|
||||||
if (cur < 0)
|
if (cur < 0)
|
||||||
VISIT_QUIT(st, 0);
|
VISIT_QUIT(st, 0);
|
||||||
if (cur & DEF_ANNOT) {
|
if (cur & (DEF_LOCAL | USE | DEF_ANNOT)) {
|
||||||
|
char* msg;
|
||||||
|
if (cur & DEF_ANNOT) {
|
||||||
|
msg = GLOBAL_ANNOT;
|
||||||
|
}
|
||||||
|
if (cur & DEF_LOCAL) {
|
||||||
|
msg = GLOBAL_AFTER_ASSIGN;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
msg = GLOBAL_AFTER_USE;
|
||||||
|
}
|
||||||
PyErr_Format(PyExc_SyntaxError,
|
PyErr_Format(PyExc_SyntaxError,
|
||||||
"annotated name '%U' can't be global",
|
msg, name);
|
||||||
name);
|
|
||||||
PyErr_SyntaxLocationObject(st->st_filename,
|
PyErr_SyntaxLocationObject(st->st_filename,
|
||||||
s->lineno,
|
s->lineno,
|
||||||
s->col_offset);
|
s->col_offset);
|
||||||
VISIT_QUIT(st, 0);
|
VISIT_QUIT(st, 0);
|
||||||
}
|
}
|
||||||
if (cur & (DEF_LOCAL | USE)) {
|
|
||||||
char buf[256];
|
|
||||||
char *c_name = _PyUnicode_AsString(name);
|
|
||||||
if (!c_name)
|
|
||||||
return 0;
|
|
||||||
if (cur & DEF_LOCAL)
|
|
||||||
PyOS_snprintf(buf, sizeof(buf),
|
|
||||||
GLOBAL_AFTER_ASSIGN,
|
|
||||||
c_name);
|
|
||||||
else
|
|
||||||
PyOS_snprintf(buf, sizeof(buf),
|
|
||||||
GLOBAL_AFTER_USE,
|
|
||||||
c_name);
|
|
||||||
if (!symtable_warn(st, buf, s->lineno))
|
|
||||||
VISIT_QUIT(st, 0);
|
|
||||||
}
|
|
||||||
if (!symtable_add_def(st, name, DEF_GLOBAL))
|
if (!symtable_add_def(st, name, DEF_GLOBAL))
|
||||||
VISIT_QUIT(st, 0);
|
VISIT_QUIT(st, 0);
|
||||||
if (!symtable_record_directive(st, name, s))
|
if (!symtable_record_directive(st, name, s))
|
||||||
|
@ -1337,31 +1313,23 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
|
||||||
long cur = symtable_lookup(st, name);
|
long cur = symtable_lookup(st, name);
|
||||||
if (cur < 0)
|
if (cur < 0)
|
||||||
VISIT_QUIT(st, 0);
|
VISIT_QUIT(st, 0);
|
||||||
if (cur & DEF_ANNOT) {
|
if (cur & (DEF_LOCAL | USE | DEF_ANNOT)) {
|
||||||
PyErr_Format(PyExc_SyntaxError,
|
char* msg;
|
||||||
"annotated name '%U' can't be nonlocal",
|
if (cur & DEF_ANNOT) {
|
||||||
name);
|
msg = NONLOCAL_ANNOT;
|
||||||
|
}
|
||||||
|
if (cur & DEF_LOCAL) {
|
||||||
|
msg = NONLOCAL_AFTER_ASSIGN;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
msg = NONLOCAL_AFTER_USE;
|
||||||
|
}
|
||||||
|
PyErr_Format(PyExc_SyntaxError, msg, name);
|
||||||
PyErr_SyntaxLocationObject(st->st_filename,
|
PyErr_SyntaxLocationObject(st->st_filename,
|
||||||
s->lineno,
|
s->lineno,
|
||||||
s->col_offset);
|
s->col_offset);
|
||||||
VISIT_QUIT(st, 0);
|
VISIT_QUIT(st, 0);
|
||||||
}
|
}
|
||||||
if (cur & (DEF_LOCAL | USE)) {
|
|
||||||
char buf[256];
|
|
||||||
char *c_name = _PyUnicode_AsString(name);
|
|
||||||
if (!c_name)
|
|
||||||
return 0;
|
|
||||||
if (cur & DEF_LOCAL)
|
|
||||||
PyOS_snprintf(buf, sizeof(buf),
|
|
||||||
NONLOCAL_AFTER_ASSIGN,
|
|
||||||
c_name);
|
|
||||||
else
|
|
||||||
PyOS_snprintf(buf, sizeof(buf),
|
|
||||||
NONLOCAL_AFTER_USE,
|
|
||||||
c_name);
|
|
||||||
if (!symtable_warn(st, buf, s->lineno))
|
|
||||||
VISIT_QUIT(st, 0);
|
|
||||||
}
|
|
||||||
if (!symtable_add_def(st, name, DEF_NONLOCAL))
|
if (!symtable_add_def(st, name, DEF_NONLOCAL))
|
||||||
VISIT_QUIT(st, 0);
|
VISIT_QUIT(st, 0);
|
||||||
if (!symtable_record_directive(st, name, s))
|
if (!symtable_record_directive(st, name, s))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue