private variables are not accessible anymore, but still completeable - fixes and tests for #56

This commit is contained in:
David Halter
2012-11-22 23:50:26 +01:00
parent 7d38fc6513
commit 936f7f9fd5
4 changed files with 38 additions and 9 deletions

View File

@@ -502,7 +502,7 @@ class Execution(Executable):
for name in names:
key = name.var_args.get_only_subelement()
stmts += follow_path(iter([key]), obj)
stmts += follow_path(iter([key]), obj, self.base)
return stmts
if self.base.isinstance(Class):
@@ -1480,10 +1480,10 @@ def follow_call_path(path, scope, position):
# Reset the position, when imports where stripped.
position = None
return follow_paths(path, result, position=position)
return follow_paths(path, result, scope, position=position)
def follow_paths(path, results, position=None):
def follow_paths(path, results, call_scope, position=None):
"""
In each result, `path` must be followed. Copies the path iterator.
"""
@@ -1495,7 +1495,7 @@ def follow_paths(path, results, position=None):
iter_paths = [path]
for i, r in enumerate(results):
fp = follow_path(iter_paths[i], r, position=position)
fp = follow_path(iter_paths[i], r, call_scope, position=position)
if fp is not None:
results_new += fp
else:
@@ -1504,7 +1504,7 @@ def follow_paths(path, results, position=None):
return results_new
def follow_path(path, scope, position=None):
def follow_path(path, scope, call_scope, position=None):
"""
Uses a generator and tries to complete the path, e.g.
>>> foo.bar.baz
@@ -1540,9 +1540,24 @@ def follow_path(path, scope, position=None):
else:
# TODO Check magic class methods and return them also.
# This is the typical lookup while chaining things.
if filter_private_variable(scope, call_scope, current):
return []
result = imports.strip_imports(get_scopes_for_name(scope, current,
position=position))
return follow_paths(path, set(result), position=position)
return follow_paths(path, set(result), call_scope, position=position)
def filter_private_variable(scope, call_scope, var_name):
if isinstance(var_name, (str, unicode)) \
and var_name.startswith('__') and isinstance(scope, Instance):
#print 'a', scope, var_name, call_scope
s = call_scope.get_parent_until((parsing.Class, Instance), include_current=True)
if s != scope and s != scope.base.base:
#print s, scope, call_scope.parent()
return True
return False
def goto(stmt, call_path=None):
if call_path is None:

View File

@@ -157,6 +157,7 @@ class ImportPath(parsing.Base):
scopes += itertools.chain.from_iterable(
remove_star_imports(s) for s in scopes)
# follow the rest of the import (not FS -> classes, functions)
if len(rest) > 1 or rest and self.is_like_search:
scopes = []
elif rest:
@@ -166,7 +167,7 @@ class ImportPath(parsing.Base):
for s in scopes)
else:
scopes = itertools.chain.from_iterable(
evaluate.follow_path(iter(rest), s)
evaluate.follow_path(iter(rest), s, s)
for s in scopes)
scopes = list(scopes)

View File

@@ -253,5 +253,5 @@ tuple({1})[0]
tuple((1,))[0]
# implementation detail for lists, should not be visible
##? []
#? []
list().__iterable

View File

@@ -510,3 +510,16 @@ Wrapper(Base()).ret(3)
#? int()
Wrapper2(Base()).ret(3)
# -----------------
# private vars
# -----------------
class PrivateVar():
def __init__(self):
self.__var = 1
#? int()
self.__var
#? []
PrivateVar().__var
#?
PrivateVar().__var