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