Filtering private variables seems to be working now at least in the evaluation engine.

This commit is contained in:
Dave Halter
2015-01-02 01:49:10 +01:00
parent 8157dd2da8
commit 36819b3241
2 changed files with 28 additions and 19 deletions

View File

@@ -205,7 +205,7 @@ class Script(object):
if settings.case_insensitive_completion \
and n.lower().startswith(like.lower()) \
or n.startswith(like):
if not filter_private_variable(s, user_stmt or self._parser.user_scope(), n):
if True: # TODO reinstate! not filter_private_variable(s, user_stmt or self._parser.user_scope(), n):
if isinstance(c.parent, (pr.Function, pr.Class)):
# TODO I think this is a hack. It should be an
# er.Function/er.Class before that.

View File

@@ -73,8 +73,9 @@ class NameFinder(object):
return scope.param_by_name(str(el))
return el
search_str = str(self.name_str)
try:
names = names_dict[str(self.name_str)]
names = names_dict[search_str]
except KeyError:
return []
@@ -84,6 +85,13 @@ class NameFinder(object):
if isinstance(scope, (pr.CompFor, pr.Lambda)):
return names
# Private name mangling (compile.c) disallows access on names
# preceeded by two underscores `__` if used outside of the class. Names
# that also end with two underscores (e.g. __id__) are not affected.
if search_str.startswith('__') and not search_str.endswith('__'):
if filter_private_variable(scope, self.name_str):
return []
if not (isinstance(scope, er.FunctionExecution)
and isinstance(scope.base, er.LambdaWrapper)):
names = pr.filter_after_position(names, position)
@@ -485,12 +493,17 @@ def global_names_dict_generator(evaluator, scope, position):
"""
For global lookups.
"""
in_func = False
while scope is not None:
for names_dict in scope.names_dicts():
yield names_dict, position
if scope.type == 'funcdef':
# The position should be reset if the current scope is a function.
position = None
if not (scope.type == 'classdef' and in_func):
# Names in methods cannot be resolved within the class.
for names_dict in scope.names_dicts():
yield names_dict, position
if scope.type == 'funcdef':
# The position should be reset if the current scope is a function.
in_func = True
position = None
scope = er.wrap(evaluator, scope.get_parent_scope())
# Add builtins to the global scope.
@@ -606,15 +619,11 @@ def check_tuple_assignments(types, name):
return types
def filter_private_variable(scope, call_scope, var_name):
"""private variables begin with a double underline `__`"""
if isinstance(scope, er.Instance) and var_name.startswith('__') and not var_name.endswith('__'):
s = call_scope.get_parent_until((pr.Class, er.Instance, compiled.CompiledObject))
if s != scope:
if isinstance(scope.base, compiled.CompiledObject):
if s != scope.base:
return True
else:
if s != scope.base.base:
return True
return False
def filter_private_variable(scope, search_name):
"""Check if a variable is defined inside the same class or outside."""
instance = scope.get_parent_scope()
coming_from = search_name
while coming_from is not None and not isinstance(coming_from, pr.Class):
coming_from = coming_from.get_parent_scope()
return isinstance(instance, er.Instance) and instance.base.base != coming_from