Commit 22b2f077 authored by Stefan Behnel's avatar Stefan Behnel

fix lookup order in Python class scope

--HG--
extra : rebase_source : b3b465b8679fb04ed27193c61bb52c8fb1e6a082
parent 61f1b662
......@@ -1379,7 +1379,7 @@ class NameNode(AtomicExprNode):
def type_dependencies(self, env):
if self.entry is None:
self.entry = env.lookup(self.name)
self.entry = env.lookup_relative(self.name, self.pos)
if self.entry is not None and self.entry.type.is_unspecified:
return (self.entry,)
else:
......@@ -1387,7 +1387,7 @@ class NameNode(AtomicExprNode):
def infer_type(self, env):
if self.entry is None:
self.entry = env.lookup(self.name)
self.entry = env.lookup_relative(self.name, self.pos)
if self.entry is None:
return py_object_type
elif (self.entry.type.is_extension_type or self.entry.type.is_builtin_type) and \
......@@ -1440,7 +1440,7 @@ class NameNode(AtomicExprNode):
# Returns the module scope, or None.
entry = self.entry
if not entry:
entry = env.lookup(self.name)
entry = env.lookup_relative(self.name, self.pos)
if entry and entry.as_module:
return entry.as_module
return None
......@@ -1454,7 +1454,7 @@ class NameNode(AtomicExprNode):
return type
entry = self.entry
if not entry:
entry = env.lookup(self.name)
entry = env.lookup_relative(self.name, self.pos)
if entry and entry.is_type:
return entry.type
else:
......@@ -1465,7 +1465,7 @@ class NameNode(AtomicExprNode):
# Returns the extension type, or None.
entry = self.entry
if not entry:
entry = env.lookup(self.name)
entry = env.lookup_relative(self.name, self.pos)
if entry and entry.is_type and entry.type.is_extension_type:
return entry.type
else:
......@@ -1488,7 +1488,7 @@ class NameNode(AtomicExprNode):
def analyse_types(self, env):
self.initialized_check = env.directives['initializedcheck']
if self.entry is None:
self.entry = env.lookup(self.name)
self.entry = env.lookup_relative(self.name, self.pos)
if not self.entry:
self.entry = env.declare_builtin(self.name, self.pos)
if not self.entry:
......
......@@ -1215,7 +1215,7 @@ class EarlyReplaceBuiltinCalls(Visitor.EnvTransform):
if not function.is_name:
return False
env = self.current_env()
entry = env.lookup(function.name)
entry = env.lookup_relative(function.name, function.pos)
if entry is not env.builtin_scope().lookup_here(function.name):
return False
# if entry is None, it's at least an undeclared name, so likely builtin
......
......@@ -730,6 +730,10 @@ class Scope(object):
# Look up in this scope only, return None if not found.
return self.entries.get(name, None)
def lookup_relative(self, name, pos):
# Like lookup(): look up a name, relative to the current source position.
return self.lookup(name)
def lookup_target(self, name):
# Look up name in this scope only. Declare as Python
# variable if not found.
......@@ -1695,6 +1699,14 @@ class PyClassScope(ClassScope):
name = self.mangle_special_name(name)
return ClassScope.lookup_here(self, name)
def lookup_relative(self, name, pos):
entry = self.lookup_here(name)
if entry is not None and entry.pos[1:] <= pos[1:]:
return entry
if self.outer_scope:
return self.outer_scope.lookup_relative(name, pos)
return None
def declare_var(self, name, type, pos,
cname = None, visibility = 'private',
api = 0, in_pxd = 0, is_cdef = 0):
......
......@@ -78,3 +78,25 @@ def name_error_deleted():
"""
class X(object):
C = C
_set = set
def name_lookup_order():
"""
>>> Scope = name_lookup_order()
>>> Scope().set(2)
42
>>> Scope.test1 == _set()
True
>>> Scope.test2 == _set()
True
"""
class Scope(object):
test1 = set()
test2 = set()
def set(self, x):
return 42
return Scope
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