From a4fdc716b09250fddff8c4130f54e8cf2a194012 Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Thu, 15 Dec 2016 01:07:44 +0100 Subject: [PATCH] Improve a doctest. --- jedi/evaluate/filters.py | 49 +++++++++++++++++++++++++++++++++++++ jedi/evaluate/finder.py | 51 --------------------------------------- jedi/evaluate/instance.py | 3 +++ jedi/evaluate/param.py | 1 + 4 files changed, 53 insertions(+), 51 deletions(-) diff --git a/jedi/evaluate/filters.py b/jedi/evaluate/filters.py index 57afb4bd..4b07a417 100644 --- a/jedi/evaluate/filters.py +++ b/jedi/evaluate/filters.py @@ -164,6 +164,9 @@ class AbstractUsedNamesFilter(AbstractFilter): return self._convert_names(name for name_list in self._used_names.values() for name in self._filter(name_list)) + def __repr__(self): + return '<%s: %s>' % (self.__class__.__name__, self.context) + class ParserTreeFilter(AbstractUsedNamesFilter): def __init__(self, evaluator, context, parser_scope, until_position=None, origin_scope=None): @@ -257,6 +260,52 @@ class DictFilter(AbstractFilter): def get_global_filters(evaluator, context, until_position, origin_scope): """ Returns all filters in order of priority for name resolution. + + For global name lookups. The filters will handle name resolution + themselves, but here we gather possible filters downwards. + + >>> from jedi._compatibility import u, no_unicode_pprint + >>> from jedi import Script + >>> script = Script(u(''' + ... x = ['a', 'b', 'c'] + ... def func(): + ... y = None + ... ''')) + >>> module_node = script._get_module_node() + >>> scope = module_node.subscopes[0] + >>> scope + + >>> context = script._get_module().create_context(scope) + >>> filters = list(get_global_filters(context.evaluator, context, (4, 0), None)) + + First we get the names names from the function scope. + + >>> no_unicode_pprint(filters[0]) + >> + >>> sorted(str(n) for n in filters[0].values()) + ['', ''] + >>> filters[0]._until_position + (4, 0) + + Then it yields the names from one level "lower". In this example, this is + the module scope. As a side note, you can see, that the position in the + filter is now None, because typically the whole module is loaded before the + function is called. + + >>> filters[1].values() # global names -> there are none in our example. + [] + >>> list(filters[2].values()) # package modules -> Also empty. + [] + >>> sorted(name.string_name for name in filters[3].values()) # Module attributes + ['__doc__', '__file__', '__name__', '__package__'] + >>> print(filters[1]._until_position) + None + + Finally, it yields the builtin filter, if `include_builtin` is + true (default). + + >>> filters[4].values() #doctest: +ELLIPSIS + [, ...] """ from jedi.evaluate.representation import FunctionExecutionContext while context is not None: diff --git a/jedi/evaluate/finder.py b/jedi/evaluate/finder.py index dc378133..c3321e5c 100644 --- a/jedi/evaluate/finder.py +++ b/jedi/evaluate/finder.py @@ -585,57 +585,6 @@ def _check_isinstance_type(context, element, search_name): def global_names_dict_generator(evaluator, scope, position): - """ - For global name lookups. Yields tuples of (names_dict, position). If the - position is None, the position does not matter anymore in that scope. - - This function is used to include names from outer scopes. For example, when - the current scope is function: - - >>> from jedi._compatibility import u, no_unicode_pprint - >>> from jedi.parser import ParserWithRecovery, load_grammar - >>> parser = ParserWithRecovery(load_grammar(), u(''' - ... x = ['a', 'b', 'c'] - ... def func(): - ... y = None - ... ''')) - >>> scope = parser.module.subscopes[0] - >>> scope - - - `global_names_dict_generator` is a generator. First it yields names from - most inner scope. - - >>> from jedi.evaluate import Evaluator - >>> evaluator = Evaluator(load_grammar()) - >>> scope = evaluator.wrap(scope) - >>> pairs = list(global_names_dict_generator(evaluator, scope, (4, 0))) - >>> no_unicode_pprint(pairs[0]) - ({'func': [], 'y': []}, (4, 0)) - - Then it yields the names from one level "lower". In this example, this - is the most outer scope. As you can see, the position in the tuple is now - None, because typically the whole module is loaded before the function is - called. - - >>> no_unicode_pprint(pairs[1]) - ({'func': [], 'x': []}, None) - - After that we have a few underscore names that are part of the module. - - >>> sorted(pairs[2][0].keys()) - ['__doc__', '__file__', '__name__', '__package__'] - >>> pairs[3] # global names -> there are none in our example. - ({}, None) - >>> pairs[4] # package modules -> Also none. - ({}, None) - - Finally, it yields names from builtin, if `include_builtin` is - true (default). - - >>> pairs[5][0].values() #doctest: +ELLIPSIS - [[], ...] - """ in_func = False while scope is not None: if not (scope.type == 'classdef' and in_func): diff --git a/jedi/evaluate/instance.py b/jedi/evaluate/instance.py index 02099cd6..d03a66e4 100644 --- a/jedi/evaluate/instance.py +++ b/jedi/evaluate/instance.py @@ -434,6 +434,9 @@ class InstanceVarArgs(object): def get_calling_nodes(self): return self._get_var_args().get_calling_nodes() + def __getattr__(self, name): + return getattr(self._var_args, name) + class InstanceFunctionExecution(er.FunctionExecutionContext): def __init__(self, instance, parent_context, function_context, var_args): diff --git a/jedi/evaluate/param.py b/jedi/evaluate/param.py index a8d4eff1..b53d138a 100644 --- a/jedi/evaluate/param.py +++ b/jedi/evaluate/param.py @@ -186,6 +186,7 @@ class TreeArguments(AbstractArguments): if param.var_args is None: break arguments = param.var_args + break return [arguments.argument_node or arguments.trailer]