From 862e4a6176d4a6d4436b56885693225a808f8ecf Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Wed, 12 Oct 2016 02:19:52 +0200 Subject: [PATCH] Add filters for the sub module dicts and module attributes dicts. --- jedi/api/completion.py | 12 ++++-------- jedi/evaluate/compiled/__init__.py | 14 +++++--------- jedi/evaluate/filters.py | 20 +++++++++++++++++++- jedi/evaluate/representation.py | 14 ++++++-------- 4 files changed, 34 insertions(+), 26 deletions(-) diff --git a/jedi/api/completion.py b/jedi/api/completion.py index 2c0c44db..eaddef9f 100644 --- a/jedi/api/completion.py +++ b/jedi/api/completion.py @@ -11,6 +11,7 @@ from jedi.api import keywords from jedi.evaluate import compiled from jedi.evaluate.helpers import call_of_leaf from jedi.evaluate.finder import global_names_dict_generator, filter_definition_names +from jedi.evaluate.filters import get_global_filters def get_call_signature_param_names(call_signatures): @@ -182,19 +183,14 @@ class Completion: scope = scope.get_parent_scope() scope = self._evaluator.wrap(scope) debug.dbg('global completion scope: %s', scope) - names_dicts = global_names_dict_generator( + filters = get_global_filters( self._evaluator, scope, self._position ) completion_names = [] - for names_dict, pos in names_dicts: - names = list(chain.from_iterable(names_dict.values())) - if not names: - continue - completion_names += filter_definition_names( - names, self._module.get_statement_for_position(self._position), pos - ) + for filter in filters: + completion_names += filter.values() return completion_names def _trailer_completions(self, atom_expr): diff --git a/jedi/evaluate/compiled/__init__.py b/jedi/evaluate/compiled/__init__.py index 46dabac6..eb5c97b7 100644 --- a/jedi/evaluate/compiled/__init__.py +++ b/jedi/evaluate/compiled/__init__.py @@ -353,22 +353,18 @@ class CompiledObjectFilter(AbstractFilter): return [self.name_class(self._evaluator, self._compiled_obj, name)] def values(self): - raise NotImplementedError obj = self._compiled_obj.obj - values = [] + names = [] for name in dir(obj): - try: - values.append(self[name]) - except KeyError: - # The dir function can be wrong. - pass + names += self.get(name) is_instance = self._is_instance or fake.is_class_instance(obj) # ``dir`` doesn't include the type names. if not inspect.ismodule(obj) and obj != type and not is_instance: - values += create(self._evaluator, type).names_dict.values() - return values + for filter in create(self._evaluator, type).get_filters(): + names += filter.values() + return names def dotted_from_fs_path(fs_path, sys_path): diff --git a/jedi/evaluate/filters.py b/jedi/evaluate/filters.py index c3e4ac91..b12398a1 100644 --- a/jedi/evaluate/filters.py +++ b/jedi/evaluate/filters.py @@ -44,7 +44,8 @@ class AbstractUsedNamesFilter(AbstractFilter): return list(self._filter(names)) def values(self): - return self._filter(self._used_names.values()) + names = [name for name_list in self._used_names.values() for name in name_list] + return self._filter(names) class ParserTreeFilter(AbstractUsedNamesFilter): @@ -105,6 +106,23 @@ class GlobalNameFilter(AbstractUsedNamesFilter): yield name +class DictFilter(AbstractFilter): + def __init__(self, dct, origin_scope=None): + super(DictFilter, self).__init__(origin_scope) + self._dct = dct + + def get(self, name): + try: + leaf_name = self._dct[str(name)] + except KeyError: + return [] + + return list(self._filter([leaf_name])) + + def values(self): + return self._filter(self._dct.values()) + + def get_global_filters(evaluator, context, until_position): """ Returns all filters in order of priority for name resolution. diff --git a/jedi/evaluate/representation.py b/jedi/evaluate/representation.py index b3fadeef..763f50a0 100644 --- a/jedi/evaluate/representation.py +++ b/jedi/evaluate/representation.py @@ -55,7 +55,8 @@ from jedi.evaluate import helpers from jedi.evaluate import param from jedi.evaluate import flow_analysis from jedi.evaluate import imports -from jedi.evaluate.filters import ParserTreeFilter, FunctionExecutionFilter, GlobalNameFilter +from jedi.evaluate.filters import ParserTreeFilter, FunctionExecutionFilter, \ + GlobalNameFilter, DictFilter class Executed(tree.Base): @@ -912,15 +913,12 @@ class ModuleWrapper(use_metaclass(CachedMetaClass, tree.Module, Wrapper)): def get_filters(self, search_global, until_position=None): yield ParserTreeFilter(self._evaluator, self._module, until_position) yield GlobalNameFilter(self._module) + yield DictFilter(self._sub_modules_dict()) + yield DictFilter(self._module_attributes_dict()) # TODO ''' - yield self._module_attributes_dict() - for star_module in self.star_imports(): yield star_module.names_dict - - yield dict((str(n), [GlobalName(n)]) for n in self.base.global_names) - yield self._sub_modules_dict() ''' # I'm not sure if the star import cache is really that effective anymore @@ -948,7 +946,7 @@ class ModuleWrapper(use_metaclass(CachedMetaClass, tree.Module, Wrapper)): names = ['__file__', '__package__', '__doc__', '__name__'] # All the additional module attributes are strings. - return dict((n, [helpers.LazyName(n, parent_callback, is_definition=True)]) + return dict((n, helpers.LazyName(n, parent_callback, is_definition=True)) for n in names) @property @@ -1049,7 +1047,7 @@ class ModuleWrapper(use_metaclass(CachedMetaClass, tree.Module, Wrapper)): # It's obviously a relative import to the current module. imp = helpers.FakeImport(fake_n, self, level=1) fake_n.parent = imp - names[name] = [fake_n] + names[name] = fake_n # TODO add something like this in the future, its cleaner than the # import hacks.