Nick Coghlan added the comment:

Just to clarify, the problem here isn't to do with referencing the class name 
in particular, it's referencing *any* lexically scoped name from the class 
body, when a metaclass wants to inject that as variable name in the class 
namespace. Here's a case where it silently looks up the wrong value:

>>> class Meta(type): pass
... 
>>> def f():
...     outer = "lexically scoped"
...     class inner(metaclass=Meta):
...         print(outer)
... 
>>> f()
lexically scoped
>>> class Meta(type):
...     def __prepare__(*args):
...         return dict(outer="from metaclass")
... 
>>> f()
lexically scoped

That second one *should* say "from metaclass", but it doesn't because the 
LOAD_DEREF completely ignores the local namespace. You can get the same 
exception noted above by moving the assignment after the inner class definition:

>>> def g():
...     class inner(metaclass=Meta):
...         print(outer)
...     outer = "This causes an exception"
... 
>>> g()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in g
  File "<stdin>", line 3, in inner
NameError: free variable 'outer' referenced before assignment in enclosing 
scope                      

We simply missed the fact that PEP 3115 and the __prepare__ method mean that 
using LOAD_DEREF to resolve lexically scoped names in a nested class is now 
wrong. Instead, we need a new opcode that first tries the class namespace and 
only if that fails does it fall back to looking it up in the lexically scoped 
cell reference.

(I changed the affected versions, as even though this *is* a bug in all current 
Python 3 versions, there's no way we're going to change the behaviour of name 
resolution in a maintenance release)

----------
nosy: +ncoghlan
title: class construction name resolution broken in functions -> Conflict 
between lexical scoping and name injection in __prepare__
versions: +Python 3.4 -Python 3.2, Python 3.3

_______________________________________
Python tracker <rep...@bugs.python.org>
<http://bugs.python.org/issue17853>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to