summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Include/opcode.h1
-rw-r--r--Include/symtable.h1
-rw-r--r--Lib/test/test_line_tracing.py (renamed from Lib/test/test_trace.py)0
-rw-r--r--Lib/test/test_scope.py8
-rw-r--r--Objects/typeobject.c1
-rw-r--r--Python/ceval.c16
-rw-r--r--Python/compile.c4
-rw-r--r--Python/symtable.c11
8 files changed, 31 insertions, 11 deletions
diff --git a/Include/opcode.h b/Include/opcode.h
index 7ffa359..facadc2 100644
--- a/Include/opcode.h
+++ b/Include/opcode.h
@@ -123,6 +123,7 @@ extern "C" {
#define LOAD_CLOSURE 135 /* Load free variable from closure */
#define LOAD_DEREF 136 /* Load and dereference from closure cell */
#define STORE_DEREF 137 /* Store into cell */
+#define LOAD_NAME_LOCAL_ONLY 138
/* The next 3 opcodes must be contiguous and satisfy
(CALL_FUNCTION_VAR - CALL_FUNCTION) & 3 == 1 */
diff --git a/Include/symtable.h b/Include/symtable.h
index d5ef96f..22075f0 100644
--- a/Include/symtable.h
+++ b/Include/symtable.h
@@ -88,6 +88,7 @@ PyAPI_FUNC(void) PySymtable_Free(struct symtable *);
#define GLOBAL_IMPLICIT 3
#define FREE 4
#define CELL 5
+#define LOCAL_ONLY 6
/* The following two names are used for the ste_unoptimized bit field */
#define OPT_IMPORT_STAR 1
diff --git a/Lib/test/test_trace.py b/Lib/test/test_line_tracing.py
index 43134e9..43134e9 100644
--- a/Lib/test/test_trace.py
+++ b/Lib/test/test_line_tracing.py
diff --git a/Lib/test/test_scope.py b/Lib/test/test_scope.py
index 643dcbc..1961e6e 100644
--- a/Lib/test/test_scope.py
+++ b/Lib/test/test_scope.py
@@ -690,6 +690,14 @@ result2 = h()
h = g()
self.assertEqual(h(), 3)
+ def testLocalClosureShadowing(self):
+ exec("""
+x = 4
+def f(x):
+ class C:
+ x = x
+raises(NameError, f, 3)""", {"raises" : self.assertRaises})
+
def test_main():
run_unittest(ScopeTests)
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 268a924..505ca68 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -6094,6 +6094,7 @@ supercheck(PyTypeObject *type, PyObject *obj)
PyErr_SetString(PyExc_TypeError,
"super(type, obj): "
"obj must be an instance or subtype of type");
+ printf("%s\n", type->tp_name);
return NULL;
}
diff --git a/Python/ceval.c b/Python/ceval.c
index 2d4b16a..368ad69 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -2052,6 +2052,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
break;
TARGET(LOAD_NAME)
+ TARGET(LOAD_NAME_LOCAL_ONLY)
w = GETITEM(names, oparg);
if ((v = f->f_locals) == NULL) {
PyErr_Format(PyExc_SystemError,
@@ -2073,15 +2074,14 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
}
}
if (x == NULL) {
- x = PyDict_GetItem(f->f_globals, w);
+ if (opcode != LOAD_NAME_LOCAL_ONLY) {
+ x = PyDict_GetItem(f->f_globals, w);
+ if (x == NULL)
+ x = PyDict_GetItem(f->f_builtins, w);
+ }
if (x == NULL) {
- x = PyDict_GetItem(f->f_builtins, w);
- if (x == NULL) {
- format_exc_check_arg(
- PyExc_NameError,
- NAME_ERROR_MSG, w);
- break;
- }
+ format_exc_check_arg(PyExc_NameError, NAME_ERROR_MSG, w);
+ break;
}
Py_INCREF(x);
}
diff --git a/Python/compile.c b/Python/compile.c
index aae0339..83c9e02 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -787,6 +787,7 @@ opcode_stack_effect(int opcode, int oparg)
case LOAD_CONST:
return 1;
case LOAD_NAME:
+ case LOAD_NAME_LOCAL_ONLY:
return 1;
case BUILD_TUPLE:
case BUILD_LIST:
@@ -2481,6 +2482,7 @@ compiler_nameop(struct compiler *c, identifier name, expr_context_ty ctx)
optype = OP_DEREF;
break;
case LOCAL:
+ case LOCAL_ONLY:
if (c->u->u_ste->ste_type == FunctionBlock)
optype = OP_FAST;
break;
@@ -2556,7 +2558,7 @@ compiler_nameop(struct compiler *c, identifier name, expr_context_ty ctx)
break;
case OP_NAME:
switch (ctx) {
- case Load: op = LOAD_NAME; break;
+ case Load: op = (scope == LOCAL_ONLY) ? LOAD_NAME_LOCAL_ONLY : LOAD_NAME; break;
case Store: op = STORE_NAME; break;
case Del: op = DELETE_NAME; break;
case AugLoad:
diff --git a/Python/symtable.c b/Python/symtable.c
index 55c9f47..37bdf2a 100644
--- a/Python/symtable.c
+++ b/Python/symtable.c
@@ -432,7 +432,14 @@ analyze_name(PySTEntryObject *ste, PyObject *scopes, PyObject *name, long flags,
return PySet_Add(free, name) >= 0;
}
if (flags & DEF_BOUND) {
- SET_SCOPE(scopes, name, LOCAL);
+ if (ste->ste_type == ClassBlock &&
+ !(flags & DEF_PARAM) &&
+ bound && PySet_Contains(bound, name)) {
+ SET_SCOPE(scopes, name, LOCAL_ONLY);
+ }
+ else {
+ SET_SCOPE(scopes, name, LOCAL);
+ }
if (PySet_Add(local, name) < 0)
return 0;
if (PySet_Discard(global, name) < 0)
@@ -489,7 +496,7 @@ analyze_cells(PyObject *scopes, PyObject *free, const char *restricted)
long scope;
assert(PyLong_Check(v));
scope = PyLong_AS_LONG(v);
- if (scope != LOCAL)
+ if (scope != LOCAL && scope != LOCAL_ONLY)
continue;
if (!PySet_Contains(free, name))
continue;