Commit c9001d17 authored by Nick Coghlan's avatar Nick Coghlan

Don't crash when nonlocal is used at module level (fixes SF#1705365)

parent eb7381d1
...@@ -388,6 +388,12 @@ Misuse of the nonlocal statement can lead to a few unique syntax errors. ...@@ -388,6 +388,12 @@ Misuse of the nonlocal statement can lead to a few unique syntax errors.
... ...
SyntaxError: no binding for nonlocal 'x' found SyntaxError: no binding for nonlocal 'x' found
From SF bug #1705365
>>> nonlocal x
Traceback (most recent call last):
...
SyntaxError: nonlocal declaration not allowed at module level
TODO(jhylton): Figure out how to test SyntaxWarning with doctest. TODO(jhylton): Figure out how to test SyntaxWarning with doctest.
## >>> def f(x): ## >>> def f(x):
......
...@@ -337,8 +337,6 @@ PyST_GetScope(PySTEntryObject *ste, PyObject *name) ...@@ -337,8 +337,6 @@ PyST_GetScope(PySTEntryObject *ste, PyObject *name)
block, the name is treated as global until it is assigned to; then it block, the name is treated as global until it is assigned to; then it
is treated as a local. is treated as a local.
TODO(jhylton): Discuss nonlocal
The symbol table requires two passes to determine the scope of each name. The symbol table requires two passes to determine the scope of each name.
The first pass collects raw facts from the AST via the symtable_visit_* The first pass collects raw facts from the AST via the symtable_visit_*
functions: the name is a parameter here, the name is used but not defined functions: the name is a parameter here, the name is used but not defined
...@@ -348,8 +346,10 @@ PyST_GetScope(PySTEntryObject *ste, PyObject *name) ...@@ -348,8 +346,10 @@ PyST_GetScope(PySTEntryObject *ste, PyObject *name)
When a function is entered during the second pass, the parent passes When a function is entered during the second pass, the parent passes
the set of all name bindings visible to its children. These bindings the set of all name bindings visible to its children. These bindings
are used to determine if non-local variables are free or implicit globals. are used to determine if non-local variables are free or implicit globals.
After doing the local analysis, it analyzes each of its child blocks Names which are explicitly declared nonlocal must exist in this set of
using an updated set of name bindings. visible names - if they do not, a syntax error is raised. After doing
the local analysis, it analyzes each of its child blocks using an
updated set of name bindings.
The children update the free variable set. If a local variable is added to The children update the free variable set. If a local variable is added to
the free variable set by the child, the variable is marked as a cell. The the free variable set by the child, the variable is marked as a cell. The
...@@ -415,6 +415,11 @@ analyze_name(PySTEntryObject *ste, PyObject *scopes, PyObject *name, long flags, ...@@ -415,6 +415,11 @@ analyze_name(PySTEntryObject *ste, PyObject *scopes, PyObject *name, long flags,
PyString_AS_STRING(name)); PyString_AS_STRING(name));
return 0; return 0;
} }
if (!bound) {
PyErr_Format(PyExc_SyntaxError,
"nonlocal declaration not allowed at module level");
return 0;
}
if (!PySet_Contains(bound, name)) { if (!PySet_Contains(bound, name)) {
PyErr_Format(PyExc_SyntaxError, PyErr_Format(PyExc_SyntaxError,
"no binding for nonlocal '%s' found", "no binding for nonlocal '%s' found",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment