From f57455f0adfc4b6cd686755e847f97a42db6bed2 Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Tue, 1 Nov 2016 23:38:06 +0100 Subject: [PATCH] Deprecate Evaluator.wrap. --- jedi/api/__init__.py | 41 ++++++++++++++++-------------- jedi/api/completion.py | 25 ++++++++++--------- jedi/evaluate/__init__.py | 44 ++++++++++++++++++--------------- jedi/evaluate/representation.py | 23 +++++++++-------- test/run.py | 6 ++--- 5 files changed, 74 insertions(+), 65 deletions(-) diff --git a/jedi/api/__init__.py b/jedi/api/__init__.py index fd2695ca..e075cfc7 100644 --- a/jedi/api/__init__.py +++ b/jedi/api/__init__.py @@ -132,15 +132,19 @@ class Script(object): debug.speed('init') @cache.memoize_method - def _get_module(self): + def _get_module_node(self): cache.invalidate_star_import_cache(self._path) parser = FastParser(self._grammar, self._source, self.path) save_parser(self.path, parser, pickling=False) - module = self._evaluator.wrap(parser.module, parent_context=None) - imports.add_module(self._evaluator, unicode(module.name), module) return parser.module + @cache.memoize_method + def _get_module(self): + module = er.ModuleContext(self._evaluator, self._get_module_node()) + imports.add_module(self._evaluator, unicode(module.name), module) + return module + @property def source_path(self): """ @@ -183,13 +187,14 @@ class Script(object): :rtype: list of :class:`classes.Definition` """ - leaf = self._get_module().name_for_position(self._pos) + module_node = self._get_module_node() + leaf = module_node.name_for_position(self._pos) if leaf is None: - leaf = self._get_module().get_leaf_for_position(self._pos) + leaf = module_node.get_leaf_for_position(self._pos) if leaf is None: return [] - context = self._evaluator.create_context(leaf) + context = self._evaluator.create_context(self._get_module(), leaf) definitions = helpers.evaluate_goto_definition(self._evaluator, context, leaf) names = [s.name for s in definitions] @@ -229,7 +234,7 @@ class Script(object): """ Used for goto_assignments and usages. """ - name = self._get_module().name_for_position(self._pos) + name = self._get_module_node().name_for_position(self._pos) if name is None: return [] return list(self._evaluator.goto(name)) @@ -248,7 +253,8 @@ class Script(object): temp, settings.dynamic_flow_information = \ settings.dynamic_flow_information, False try: - user_stmt = self._get_module().get_statement_for_position(self._pos) + module_node = self._get_module_node() + user_stmt = module_node.get_statement_for_position(self._pos) definitions = self._goto() if not definitions and isinstance(user_stmt, tree.Import): # For not defined imports (goto doesn't find something, we take @@ -270,7 +276,7 @@ class Script(object): definitions) module = set([d.get_parent_until() for d in definitions]) - module.add(self._get_module()) + module.add(module_node) names = usages.usages(self._evaluator, definitions, module) for d in set(definitions): @@ -297,7 +303,7 @@ class Script(object): :rtype: list of :class:`classes.CallSignature` """ call_signature_details = \ - helpers.get_call_signature_details(self._get_module(), self._pos) + helpers.get_call_signature_details(self._get_module_node(), self._pos) if call_signature_details is None: return [] @@ -320,9 +326,10 @@ class Script(object): def _analysis(self): self._evaluator.is_analysis = True - self._evaluator.analysis_modules = [self._get_module()] + module_node = self._get_module_node() + self._evaluator.analysis_modules = [module_node] try: - for node in self._get_module().nodes_to_execute(): + for node in module_node.nodes_to_execute(): if node.type in ('funcdef', 'classdef'): if node.type == 'classdef': continue @@ -387,11 +394,9 @@ class Interpreter(Script): super(Interpreter, self).__init__(source, **kwds) self.namespaces = namespaces - parser_module = super(Interpreter, self)._get_module() - self._module = interpreter.MixedModule(self._evaluator, parser_module, self.namespaces) - - def _get_module(self): - return self._module + def _get_module_node(self): + parser_module = super(Interpreter, self)._get_module_node() + return interpreter.MixedModule(self._evaluator, parser_module, self.namespaces) def defined_names(source, path=None, encoding='utf-8'): @@ -437,7 +442,7 @@ def names(source=None, path=None, encoding='utf-8', all_scopes=False, # Set line/column to a random position, because they don't matter. script = Script(source, line=1, column=0, path=path, encoding=encoding) defs = [classes.Definition(script._evaluator, name_part) - for name_part in get_module_names(script._get_module(), all_scopes)] + for name_part in get_module_names(script._get_module().module_node, all_scopes)] return sorted(filter(def_ref_filter, defs), key=lambda x: (x.line, x.column)) diff --git a/jedi/api/completion.py b/jedi/api/completion.py index 108f6283..f4704974 100644 --- a/jedi/api/completion.py +++ b/jedi/api/completion.py @@ -47,11 +47,11 @@ def filter_names(evaluator, completion_names, stack, like_name): yield new -def get_user_scope(module, position): +def get_user_scope(module_context, position): """ Returns the scope in which the user resides. This includes flows. """ - user_stmt = module.get_statement_for_position(position) + user_stmt = module_context.module_node.get_statement_for_position(position) if user_stmt is None: def scan(scope): for s in scope.children: @@ -62,20 +62,20 @@ def get_user_scope(module, position): return scan(s) return None - return scan(module) or module + return scan(module) or module_context else: return user_stmt.get_parent_scope(include_flows=True) class Completion: - def __init__(self, evaluator, module_node, code_lines, position, call_signatures_method): + def __init__(self, evaluator, module, code_lines, position, call_signatures_method): self._evaluator = evaluator - self._module_node = module_node - self._module = evaluator.wrap(module_node, parent_context=None) + self._module_context = module + self._module_node = module.module_node self._code_lines = code_lines # The first step of completions is to get the name - self._like_name = helpers.get_on_completion_name(module_node, code_lines, position) + self._like_name = helpers.get_on_completion_name(self._module_node, code_lines, position) # The actual cursor position is not what we need to calculate # everything. We want the start of the name we're on. self._position = position[0], position[1] - len(self._like_name) @@ -172,10 +172,10 @@ class Completion: yield keywords.keyword(self._evaluator, k).name def _global_completions(self): - scope = get_user_scope(self._module_node, self._position) + scope = get_user_scope(self._module_context, self._position) if not scope.is_scope(): # Might be a flow (if/while/etc). scope = scope.get_parent_scope() - scope = self._evaluator.create_context(scope) + scope = self._evaluator.create_context(self._module_context, scope) debug.dbg('global completion scope: %s', scope) filters = get_global_filters( self._evaluator, @@ -189,8 +189,9 @@ class Completion: return completion_names def _trailer_completions(self, atom_expr): - user_scope = get_user_scope(self._module_node, self._position) - contexts = self._evaluator.eval_element(self._evaluator.create_context(atom_expr), atom_expr) + user_scope = get_user_scope(self._module_context, self._position) + evaluation_context = self._evaluator.create_context(self._module_context, atom_expr) + contexts = self._evaluator.eval_element(evaluation_context, atom_expr) completion_names = [] debug.dbg('trailer completion contexts: %s', contexts) for context in contexts: @@ -215,7 +216,7 @@ class Completion: def _get_importer_names(self, names, level=0, only_modules=True): names = [str(n) for n in names] - i = imports.Importer(self._evaluator, names, self._module, level) + i = imports.Importer(self._evaluator, names, self._module_context, level) return i.completion_names(self._evaluator, only_modules=only_modules) def _get_class_context_completions(self, is_function=True): diff --git a/jedi/evaluate/__init__.py b/jedi/evaluate/__init__.py index 418da7ed..a709a496 100644 --- a/jedi/evaluate/__init__.py +++ b/jedi/evaluate/__init__.py @@ -110,19 +110,6 @@ class Evaluator(object): self.recursion_detector = recursion.RecursionDetector(self) self.execution_recursion_detector = recursion.ExecutionRecursionDetector(self) - def wrap(self, element, parent_context): - if element.type == 'classdef': - return er.ClassContext(self, element, parent_context) - elif element.type == 'funcdef': - return er.AnonymousFunctionExecution(self, parent_context, element) - elif element.type == 'lambda': - return er.LambdaWrapper(self, element) - elif element.type == 'file_input': - return er.ModuleContext(self, element) - else: - raise DeprecationWarning - return element - def find_types(self, context, name_str, position=None, search_global=False, is_goto=False): """ @@ -515,16 +502,33 @@ class Evaluator(object): return self.find_types(scope, name, stmt.start_pos, search_global=True, is_goto=True) - def create_context(self, node): - def from_scope(scope): + def wrap(self, element, parent_context): + raise DeprecationWarning + if element.type == 'classdef': + return er.ClassContext(self, element, parent_context) + elif element.type == 'lambda': + return er.LambdaWrapper(self, element) + elif element.type == 'file_input': + return er.ModuleContext(self, element) + else: + raise DeprecationWarning + return element + + def create_context(self, module_context, node): + def from_scope_node(scope_node): parent_context = None - parent_scope = scope.get_parent_scope() + parent_scope = scope_node.get_parent_scope() if parent_scope is not None: - parent_context = from_scope(parent_scope) + parent_context = from_scope_node(parent_scope) + if scope_node == module_context.module_node: + return module_context + elif scope_node.type == 'funcdef': + return er.AnonymousFunctionExecution(self, parent_context, scope_node) + raise DeprecationWarning return self.wrap(scope, parent_context=parent_context) if node.is_scope(): - scope = node + scope_node = node else: - scope = node.get_parent_scope() - return from_scope(scope) + scope_node = node.get_parent_scope() + return from_scope_node(scope_node) diff --git a/jedi/evaluate/representation.py b/jedi/evaluate/representation.py index 36533d96..8666be0c 100644 --- a/jedi/evaluate/representation.py +++ b/jedi/evaluate/representation.py @@ -734,10 +734,9 @@ class GlobalName(helpers.FakeName): class ModuleContext(use_metaclass(CachedMetaClass, context.TreeContext, Wrapper)): parent_context = None - def __init__(self, evaluator, module, parent_module=None): - self._evaluator = evaluator - self.base = self._module = module - self._parent_module = parent_module + def __init__(self, evaluator, module_node): + super(ModuleContext, self).__init__(evaluator, parent_context=None) + self.module_node = module_node self.path = None def names_dicts(self, search_global): @@ -754,11 +753,11 @@ class ModuleContext(use_metaclass(CachedMetaClass, context.TreeContext, Wrapper) yield ParserTreeFilter( self._evaluator, self, - self._module, + self.module_node, until_position, origin_scope=origin_scope ) - yield GlobalNameFilter(self, self._module) + yield GlobalNameFilter(self, self.module_node) yield DictFilter(self._sub_modules_dict()) yield DictFilter(self._module_attributes_dict()) # TODO @@ -774,7 +773,7 @@ class ModuleContext(use_metaclass(CachedMetaClass, context.TreeContext, Wrapper) @memoize_default([]) def star_imports(self): modules = [] - for i in self.base.imports: + for i in self.module_node.imports: if i.is_star_import(): name = i.star_import_name() new = imports.ImportWrapper(self._evaluator, name).follow() @@ -798,7 +797,7 @@ class ModuleContext(use_metaclass(CachedMetaClass, context.TreeContext, Wrapper) @property @memoize_default() def name(self): - return ContextName(self, self.base.name) + return ContextName(self, self.module_node.name) def _get_init_directory(self): """ @@ -824,10 +823,10 @@ class ModuleContext(use_metaclass(CachedMetaClass, context.TreeContext, Wrapper) """ In contrast to Python's __file__ can be None. """ - if self._module.path is None: + if self.module_node.path is None: return None - return os.path.abspath(self._module.path) + return os.path.abspath(self.module_node.path) def py__package__(self): if self._get_init_directory() is None: @@ -884,7 +883,7 @@ class ModuleContext(use_metaclass(CachedMetaClass, context.TreeContext, Wrapper) Lists modules in the directory of this module (if this module is a package). """ - path = self._module.path + path = self.module_node.path names = {} if path is not None and path.endswith(os.path.sep + '__init__.py'): mods = pkgutil.iter_modules([os.path.dirname(path)]) @@ -909,4 +908,4 @@ class ModuleContext(use_metaclass(CachedMetaClass, context.TreeContext, Wrapper) return compiled.get_special_object(self._evaluator, 'MODULE_CLASS') def __repr__(self): - return "<%s: %s>" % (type(self).__name__, self._module) + return "<%s: %s>" % (type(self).__name__, self.module_node) diff --git a/test/run.py b/test/run.py index b41bf757..d89bba61 100755 --- a/test/run.py +++ b/test/run.py @@ -122,6 +122,7 @@ from jedi import debug from jedi._compatibility import unicode, is_py3 from jedi.parser import Parser, load_grammar from jedi.api.classes import Definition +from jedi.evaluate.representation import ModuleContext TEST_COMPLETIONS = 0 @@ -189,13 +190,12 @@ class IntegrationTestCase(object): parser = Parser(load_grammar(), string, start_symbol='eval_input') parser.get_root_node().move(self.line_nr) element = parser.get_parsed_node() - module = script._get_module() + module_context = script._get_module() # TODO remove element.parent = jedi.api.completion.get_user_scope( - module, + module_context, (self.line_nr, self.column) ) - module_context = evaluator.wrap(module, parent_context=None) results = evaluator.eval_element(module_context, element) if not results: raise Exception('Could not resolve %s on line %s'