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

Skip to content

Commit d9c8702

Browse files
committed
point errors related to nonlocals and globals to the statement declaring them (closes #10189)
1 parent a889d80 commit d9c8702

3 files changed

Lines changed: 53 additions & 8 deletions

File tree

Include/symtable.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ typedef struct _symtable_entry {
3939
PyObject *ste_name; /* string: name of current block */
4040
PyObject *ste_varnames; /* list of function parameters */
4141
PyObject *ste_children; /* list of child blocks */
42+
PyObject *ste_directives;/* locations of global and nonlocal statements */
4243
_Py_block_ty ste_type; /* module, class, or function */
4344
int ste_unoptimized; /* false if namespace is optimized */
4445
int ste_nested; /* true if block is nested */

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ What's New in Python 3.4.0 Alpha 1?
1010
Core and Builtins
1111
-----------------
1212

13+
- Issue #10189: Improve the error reporting of SyntaxErrors related to global
14+
and nonlocal statements.
15+
1316
- Issue #16086: PyTypeObject.tp_flags and PyType_Spec.flags are now unsigned
1417
(unsigned long and unsigned int) to avoid an undefined behaviour with
1518
Py_TPFLAGS_TYPE_SUBCLASS ((1 << 31). PyType_GetFlags() result type is

Python/symtable.c

Lines changed: 49 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ ste_new(struct symtable *st, identifier name, _Py_block_ty block,
5656
if (ste->ste_children == NULL)
5757
goto fail;
5858

59+
ste->ste_directives = NULL;
60+
5961
ste->ste_type = block;
6062
ste->ste_unoptimized = 0;
6163
ste->ste_nested = 0;
@@ -102,6 +104,7 @@ ste_dealloc(PySTEntryObject *ste)
102104
Py_XDECREF(ste->ste_symbols);
103105
Py_XDECREF(ste->ste_varnames);
104106
Py_XDECREF(ste->ste_children);
107+
Py_XDECREF(ste->ste_directives);
105108
PyObject_Del(ste);
106109
}
107110

@@ -319,6 +322,24 @@ PyST_GetScope(PySTEntryObject *ste, PyObject *name)
319322
return (PyLong_AS_LONG(v) >> SCOPE_OFFSET) & SCOPE_MASK;
320323
}
321324

325+
static int
326+
error_at_directive(PySTEntryObject *ste, PyObject *name)
327+
{
328+
Py_ssize_t i;
329+
PyObject *data;
330+
assert(ste->ste_directives);
331+
for (i = 0; ; i++) {
332+
data = PyList_GET_ITEM(ste->ste_directives, i);
333+
assert(PyTuple_CheckExact(data));
334+
if (PyTuple_GET_ITEM(data, 0) == name)
335+
break;
336+
}
337+
PyErr_SyntaxLocationEx(ste->ste_table->st_filename,
338+
PyLong_AsLong(PyTuple_GET_ITEM(data, 1)),
339+
PyLong_AsLong(PyTuple_GET_ITEM(data, 2)));
340+
return 0;
341+
}
342+
322343

323344
/* Analyze raw symbol information to determine scope of each name.
324345
@@ -393,16 +414,13 @@ analyze_name(PySTEntryObject *ste, PyObject *scopes, PyObject *name, long flags,
393414
PyErr_Format(PyExc_SyntaxError,
394415
"name '%U' is parameter and global",
395416
name);
396-
PyErr_SyntaxLocationEx(ste->ste_table->st_filename,
397-
ste->ste_lineno, ste->ste_col_offset);
398-
399-
return 0;
417+
return error_at_directive(ste, name);
400418
}
401419
if (flags & DEF_NONLOCAL) {
402420
PyErr_Format(PyExc_SyntaxError,
403421
"name '%U' is nonlocal and global",
404422
name);
405-
return 0;
423+
return error_at_directive(ste, name);
406424
}
407425
SET_SCOPE(scopes, name, GLOBAL_EXPLICIT);
408426
if (PySet_Add(global, name) < 0)
@@ -416,19 +434,19 @@ analyze_name(PySTEntryObject *ste, PyObject *scopes, PyObject *name, long flags,
416434
PyErr_Format(PyExc_SyntaxError,
417435
"name '%U' is parameter and nonlocal",
418436
name);
419-
return 0;
437+
return error_at_directive(ste, name);
420438
}
421439
if (!bound) {
422440
PyErr_Format(PyExc_SyntaxError,
423441
"nonlocal declaration not allowed at module level");
424-
return 0;
442+
return error_at_directive(ste, name);
425443
}
426444
if (!PySet_Contains(bound, name)) {
427445
PyErr_Format(PyExc_SyntaxError,
428446
"no binding for nonlocal '%U' found",
429447
name);
430448

431-
return 0;
449+
return error_at_directive(ste, name);
432450
}
433451
SET_SCOPE(scopes, name, FREE);
434452
ste->ste_free = 1;
@@ -1068,6 +1086,25 @@ symtable_new_tmpname(struct symtable *st)
10681086
}
10691087

10701088

1089+
static int
1090+
symtable_record_directive(struct symtable *st, identifier name, stmt_ty s)
1091+
{
1092+
PyObject *data;
1093+
int res;
1094+
if (!st->st_cur->ste_directives) {
1095+
st->st_cur->ste_directives = PyList_New(0);
1096+
if (!st->st_cur->ste_directives)
1097+
return 0;
1098+
}
1099+
data = Py_BuildValue("(Oii)", name, s->lineno, s->col_offset);
1100+
if (!data)
1101+
return 0;
1102+
res = PyList_Append(st->st_cur->ste_directives, data);
1103+
Py_DECREF(data);
1104+
return res == 0;
1105+
}
1106+
1107+
10711108
static int
10721109
symtable_visit_stmt(struct symtable *st, stmt_ty s)
10731110
{
@@ -1223,6 +1260,8 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
12231260
}
12241261
if (!symtable_add_def(st, name, DEF_GLOBAL))
12251262
return 0;
1263+
if (!symtable_record_directive(st, name, s))
1264+
return 0;
12261265
}
12271266
break;
12281267
}
@@ -1252,6 +1291,8 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
12521291
}
12531292
if (!symtable_add_def(st, name, DEF_NONLOCAL))
12541293
return 0;
1294+
if (!symtable_record_directive(st, name, s))
1295+
return 0;
12551296
}
12561297
break;
12571298
}

0 commit comments

Comments
 (0)