From 4ceca541384429f9bf9a137c0aebb61070bc8071 Mon Sep 17 00:00:00 2001 From: muffinmad Date: Thu, 21 May 2020 17:31:44 +0300 Subject: [PATCH 1/9] Specify max-line-length for pycodestyle According to CONTRIBUTING.md it can be 100 --- tox.ini | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tox.ini b/tox.ini index dfa023c2..24da7c73 100644 --- a/tox.ini +++ b/tox.ini @@ -41,3 +41,5 @@ commands = commands = flake8 --extend-ignore F401 {posargs:jedi} deps = extras = qa +[pycodestyle] +max-line-length=100 From 741097827dc0be035b4dda76fcb36ab91caa7d8f Mon Sep 17 00:00:00 2001 From: muffinmad Date: Thu, 21 May 2020 17:37:25 +0300 Subject: [PATCH 2/9] Get references in the current module only --- jedi/api/__init__.py | 12 ++++---- jedi/inference/names.py | 10 +++---- jedi/inference/references.py | 48 +++++++++++++++++-------------- jedi/plugins/pytest.py | 4 +-- test/test_api/test_usages.py | 56 ++++++++++++++++++++++++++++++++++++ 5 files changed, 96 insertions(+), 34 deletions(-) diff --git a/jedi/api/__init__.py b/jedi/api/__init__.py index 7531598a..a4ec5363 100644 --- a/jedi/api/__init__.py +++ b/jedi/api/__init__.py @@ -505,21 +505,23 @@ class Script(object): quite hard to do for Jedi, if it is too complicated, Jedi will stop searching. - :param include_builtins: Default True, checks if a reference is a - builtin (e.g. ``sys``) and in that case does not return it. + :param include_builtins: Default ``True``. If ``False`` checks if a reference + is a builtin (e.g. ``sys``) and in that case does not return it. + :param all_scopes: Default ``True``. If ``False`` include references in + the current module only. :rtype: list of :class:`.Name` """ - def _references(include_builtins=True): + def _references(include_builtins=True, all_scopes=True): tree_name = self._module_node.get_name_of_position((line, column)) if tree_name is None: # Must be syntax return [] - names = find_references(self._get_module_context(), tree_name) + names = find_references(self._get_module_context(), tree_name, all_scopes) definitions = [classes.Name(self._inference_state, n) for n in names] - if not include_builtins: + if not (include_builtins and all_scopes): definitions = [d for d in definitions if not d.in_builtin_module()] return helpers.sorted_definitions(definitions) return _references(**kwargs) diff --git a/jedi/inference/names.py b/jedi/inference/names.py index ccf42d4c..bc6d494f 100644 --- a/jedi/inference/names.py +++ b/jedi/inference/names.py @@ -138,7 +138,7 @@ class AbstractTreeName(AbstractNameDefinition): return self.parent_context.get_value() # Might be None return None - def goto(self): + def goto(self, all_scopes=True): context = self.parent_context name = self.tree_name definition = name.get_definition(import_name_always=True) @@ -150,13 +150,13 @@ class AbstractTreeName(AbstractNameDefinition): is_simple_name = name.parent.type not in ('power', 'trailer') if is_simple_name: return [self] - elif type_ in ('import_from', 'import_name'): + elif all_scopes and type_ in ('import_from', 'import_name'): from jedi.inference.imports import goto_import module_names = goto_import(context, name) return module_names else: return [self] - else: + elif all_scopes: from jedi.inference.imports import follow_error_node_imports_if_possible values = follow_error_node_imports_if_possible(context, name) if values is not None: @@ -498,8 +498,8 @@ class _ActualTreeParamName(BaseTreeParamName): class AnonymousParamName(_ActualTreeParamName): @plugin_manager.decorate(name='goto_anonymous_param') - def goto(self): - return super(AnonymousParamName, self).goto() + def goto(self, **kwargs): + return super(AnonymousParamName, self).goto(**kwargs) @plugin_manager.decorate(name='infer_anonymous_param') def infer(self): diff --git a/jedi/inference/references.py b/jedi/inference/references.py index 5534db30..19a843f9 100644 --- a/jedi/inference/references.py +++ b/jedi/inference/references.py @@ -25,7 +25,7 @@ easily 100ms for bigger files. """ -def _resolve_names(definition_names, avoid_names=()): +def _resolve_names(definition_names, avoid_names=(), all_scopes=True): for name in definition_names: if name in avoid_names: # Avoiding recursions here, because goto on a module name lands @@ -37,7 +37,7 @@ def _resolve_names(definition_names, avoid_names=()): # names when importing something like `import foo.bar.baz`. yield name - if name.api_type == 'module': + if all_scopes and name.api_type == 'module': for n in _resolve_names(name.goto(), definition_names): yield n @@ -49,16 +49,17 @@ def _dictionarize(names): ) -def _find_defining_names(module_context, tree_name): - found_names = _find_names(module_context, tree_name) +def _find_defining_names(module_context, tree_name, all_scopes=True): + found_names = _find_names(module_context, tree_name, all_scopes=all_scopes) - for name in list(found_names): - # Convert from/to stubs, because those might also be usages. - found_names |= set(convert_names( - [name], - only_stubs=not name.get_root_context().is_stub(), - prefer_stub_to_compiled=False - )) + if all_scopes: + for name in list(found_names): + # Convert from/to stubs, because those might also be usages. + found_names |= set(convert_names( + [name], + only_stubs=not name.get_root_context().is_stub(), + prefer_stub_to_compiled=False + )) found_names |= set(_find_global_variables(found_names, tree_name.value)) for name in list(found_names): @@ -66,15 +67,15 @@ def _find_defining_names(module_context, tree_name): or name.tree_name.parent.type == 'trailer': continue found_names |= set(_add_names_in_same_context(name.parent_context, name.string_name)) - return set(_resolve_names(found_names)) + return set(_resolve_names(found_names, all_scopes=all_scopes)) -def _find_names(module_context, tree_name): +def _find_names(module_context, tree_name, all_scopes=True): name = module_context.create_name(tree_name) - found_names = set(name.goto()) + found_names = set(name.goto(all_scopes=all_scopes)) found_names.add(name) - return set(_resolve_names(found_names)) + return set(_resolve_names(found_names, all_scopes=all_scopes)) def _add_names_in_same_context(context, string_name): @@ -113,7 +114,7 @@ def _find_global_variables(names, search_name): yield n -def find_references(module_context, tree_name): +def find_references(module_context, tree_name, all_scopes=True): inf = module_context.inference_state search_name = tree_name.value @@ -121,17 +122,20 @@ def find_references(module_context, tree_name): # certain cases, we want both sides. try: inf.flow_analysis_enabled = False - found_names = _find_defining_names(module_context, tree_name) + found_names = _find_defining_names(module_context, tree_name, all_scopes=all_scopes) finally: inf.flow_analysis_enabled = True found_names_dct = _dictionarize(found_names) - module_contexts = set(d.get_root_context() for d in found_names) - module_contexts = [module_context] \ - + [m for m in module_contexts if m != module_context and m.tree_node is not None] + module_contexts = [module_context] + if all_scopes: + module_contexts.extend( + m for m in set(d.get_root_context() for d in found_names) + if m != module_context and m.tree_node is not None + ) # For param no search for other modules is necessary. - if any(n.api_type == 'param' for n in found_names): + if not all_scopes or any(n.api_type == 'param' for n in found_names): potential_modules = module_contexts else: potential_modules = get_module_contexts_containing_name( @@ -143,7 +147,7 @@ def find_references(module_context, tree_name): non_matching_reference_maps = {} for module_context in potential_modules: for name_leaf in module_context.tree_node.get_used_names().get(search_name, []): - new = _dictionarize(_find_names(module_context, name_leaf)) + new = _dictionarize(_find_names(module_context, name_leaf, all_scopes=all_scopes)) if any(tree_name in found_names_dct for tree_name in new): found_names_dct.update(new) for tree_name in new: diff --git a/jedi/plugins/pytest.py b/jedi/plugins/pytest.py index f9b04284..76754394 100644 --- a/jedi/plugins/pytest.py +++ b/jedi/plugins/pytest.py @@ -63,7 +63,7 @@ def infer_anonymous_param(func): def goto_anonymous_param(func): - def wrapper(param_name): + def wrapper(param_name, **kwargs): is_pytest_param, param_name_is_function_name = \ _is_a_pytest_param_and_inherited(param_name) if is_pytest_param: @@ -74,7 +74,7 @@ def goto_anonymous_param(func): ) if names: return names - return func(param_name) + return func(param_name, **kwargs) return wrapper diff --git a/test/test_api/test_usages.py b/test/test_api/test_usages.py index 188f893d..f7ef9c57 100644 --- a/test/test_api/test_usages.py +++ b/test/test_api/test_usages.py @@ -15,3 +15,59 @@ def test_exclude_builtin_modules(Script): places = get(include=False) assert places == [(1, 7), (2, 6)] + + +def test_references_scope(Script): + from jedi.api.project import Project + project = Project('', sys_path=[], smart_sys_path=False) + script = Script( + '''import sys +from collections import defaultdict + +print(sys.path) + +def foo(bar): + baz = defaultdict(int) + return baz + +def bar(foo): + baz = defaultdict(int) + return baz + +foo() +''', project=project) + + def r(*args): + return script.get_references(all_scopes=False, *args) + + print(script._code_lines) + sys_places = r(1, 7) + assert len(sys_places) == 2 + assert sys_places == r(4, 6) + + assert len(r(2, 5)) == 1 + + dd_places = r(2, 24) + assert len(dd_places) == 3 + assert dd_places == r(7, 10) + assert dd_places == r(11, 10) + + foo_places = r(6, 4) + assert len(foo_places) == 2 + assert foo_places == r(14, 0) + + baz_places = r(7, 4) + assert len(baz_places) == 2 + assert baz_places == r(8, 11) + + int_places = r(7, 22) + assert len(int_places) == 2 + assert int_places == r(11, 22) + + baz_places = r(11, 4) + assert len(baz_places) == 2 + assert baz_places == r(12, 11) + + script = Script('from datetime', project=project) + places = r(1, 5) + assert len(places) == 1 From 7459d67fee8f766cefb2c404a1437fb976b8b5bd Mon Sep 17 00:00:00 2001 From: muffinmad Date: Fri, 22 May 2020 13:24:39 +0300 Subject: [PATCH 3/9] Test local references in some other cases --- test/test_api/test_usages.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/test/test_api/test_usages.py b/test/test_api/test_usages.py index f7ef9c57..27d9d300 100644 --- a/test/test_api/test_usages.py +++ b/test/test_api/test_usages.py @@ -71,3 +71,22 @@ foo() script = Script('from datetime', project=project) places = r(1, 5) assert len(places) == 1 + + +def test_local_references_method_other_file(Script): + from jedi.api.project import Project + script = Script('''from datetime import datetime +d1 = datetime.now() +d2 = datetime.now() +''', project=Project('', sys_path=[], smart_sys_path=False)) + now_places = script.get_references(2, 14, all_scopes=False) + assert len(now_places) == 2 + assert now_places == script.get_references(3, 14, all_scopes=False) + + +def test_local_references_kwarg(Script): + from jedi.api.project import Project + script = Script('''from jedi import Script +Script(code='') +''', project=Project('', sys_path=[], smart_sys_path=False)) + assert len(script.get_references(2, 7, all_scopes=False)) == 1 From 1c342d36e53f88949222e95660470e872cc9b302 Mon Sep 17 00:00:00 2001 From: muffinmad Date: Sun, 24 May 2020 22:58:04 +0300 Subject: [PATCH 4/9] Don't goto while building found_names for the current file But goto for all non_matching_reference_maps items later --- jedi/inference/names.py | 4 ++++ jedi/inference/references.py | 17 +++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/jedi/inference/names.py b/jedi/inference/names.py index bc6d494f..6a75504a 100644 --- a/jedi/inference/names.py +++ b/jedi/inference/names.py @@ -166,6 +166,8 @@ class AbstractTreeName(AbstractNameDefinition): node_type = par.type if node_type == 'argument' and par.children[1] == '=' and par.children[0] == name: # Named param goto. + if not all_scopes: + return [self] trailer = par.parent if trailer.type == 'arglist': trailer = trailer.parent @@ -200,6 +202,8 @@ class AbstractTreeName(AbstractNameDefinition): ) if node_type == 'trailer' and par.children[0] == '.': + if not all_scopes: + return [self] values = infer_call_of_leaf(context, name, cut_own_trailer=True) return values.goto(name, name_context=context) else: diff --git a/jedi/inference/references.py b/jedi/inference/references.py index 19a843f9..ff52cb56 100644 --- a/jedi/inference/references.py +++ b/jedi/inference/references.py @@ -144,6 +144,11 @@ def find_references(module_context, tree_name, all_scopes=True): search_name, ) + gotos = set() + if not all_scopes: + for name in found_names_dct.values(): + gotos |= set(name.goto()) + non_matching_reference_maps = {} for module_context in potential_modules: for name_leaf in module_context.tree_node.get_used_names().get(search_name, []): @@ -162,6 +167,18 @@ def find_references(module_context, tree_name, all_scopes=True): else: for name in new: non_matching_reference_maps.setdefault(name, []).append(new) + + if not all_scopes: + def in_gotos(g): + for g_ in gotos: + if g.start_pos == g_.start_pos and g.get_root_context() == g_.get_root_context(): + return True + + for dct_list in non_matching_reference_maps.values(): + for dct in dct_list: + for k, v in dct.items(): + if any(in_gotos(g) for g in v.goto()): + found_names_dct[k] = v return found_names_dct.values() From f9bbccbc1316d4885a43973c125f8a27e06456c0 Mon Sep 17 00:00:00 2001 From: muffinmad Date: Wed, 3 Jun 2020 15:24:37 +0300 Subject: [PATCH 5/9] Pycodestyle configuration section moved to setup.cfg --- setup.cfg | 3 +++ tox.ini | 2 -- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/setup.cfg b/setup.cfg index dfc0c6d0..39633dc1 100644 --- a/setup.cfg +++ b/setup.cfg @@ -14,3 +14,6 @@ ignore = # Line break before binary operator W503, exclude = jedi/third_party/* .tox/* + +[pycodestyle] +max-line-length = 100 diff --git a/tox.ini b/tox.ini index 24da7c73..dfa023c2 100644 --- a/tox.ini +++ b/tox.ini @@ -41,5 +41,3 @@ commands = commands = flake8 --extend-ignore F401 {posargs:jedi} deps = extras = qa -[pycodestyle] -max-line-length=100 From 782dedd43960b68925bae54b86c4384aae8b26a3 Mon Sep 17 00:00:00 2001 From: muffinmad Date: Wed, 3 Jun 2020 16:35:28 +0300 Subject: [PATCH 6/9] Get references in the current module only --- jedi/api/__init__.py | 10 +++--- jedi/inference/names.py | 14 +++----- jedi/inference/references.py | 63 ++++++++++++++---------------------- jedi/plugins/pytest.py | 4 +-- test/test_api/test_usages.py | 8 ++--- 5 files changed, 40 insertions(+), 59 deletions(-) diff --git a/jedi/api/__init__.py b/jedi/api/__init__.py index a4ec5363..d2a6e4b6 100644 --- a/jedi/api/__init__.py +++ b/jedi/api/__init__.py @@ -505,23 +505,23 @@ class Script(object): quite hard to do for Jedi, if it is too complicated, Jedi will stop searching. - :param include_builtins: Default ``True``. If ``False`` checks if a reference + :param include_builtins: Default ``True``. If ``False``, checks if a reference is a builtin (e.g. ``sys``) and in that case does not return it. - :param all_scopes: Default ``True``. If ``False`` include references in + :param scope: Default ``'project'``. If ``'file'``, include references in the current module only. :rtype: list of :class:`.Name` """ - def _references(include_builtins=True, all_scopes=True): + def _references(include_builtins=True, scope='project'): tree_name = self._module_node.get_name_of_position((line, column)) if tree_name is None: # Must be syntax return [] - names = find_references(self._get_module_context(), tree_name, all_scopes) + names = find_references(self._get_module_context(), tree_name, scope == 'file') definitions = [classes.Name(self._inference_state, n) for n in names] - if not (include_builtins and all_scopes): + if not include_builtins or scope == 'file': definitions = [d for d in definitions if not d.in_builtin_module()] return helpers.sorted_definitions(definitions) return _references(**kwargs) diff --git a/jedi/inference/names.py b/jedi/inference/names.py index 6a75504a..ccf42d4c 100644 --- a/jedi/inference/names.py +++ b/jedi/inference/names.py @@ -138,7 +138,7 @@ class AbstractTreeName(AbstractNameDefinition): return self.parent_context.get_value() # Might be None return None - def goto(self, all_scopes=True): + def goto(self): context = self.parent_context name = self.tree_name definition = name.get_definition(import_name_always=True) @@ -150,13 +150,13 @@ class AbstractTreeName(AbstractNameDefinition): is_simple_name = name.parent.type not in ('power', 'trailer') if is_simple_name: return [self] - elif all_scopes and type_ in ('import_from', 'import_name'): + elif type_ in ('import_from', 'import_name'): from jedi.inference.imports import goto_import module_names = goto_import(context, name) return module_names else: return [self] - elif all_scopes: + else: from jedi.inference.imports import follow_error_node_imports_if_possible values = follow_error_node_imports_if_possible(context, name) if values is not None: @@ -166,8 +166,6 @@ class AbstractTreeName(AbstractNameDefinition): node_type = par.type if node_type == 'argument' and par.children[1] == '=' and par.children[0] == name: # Named param goto. - if not all_scopes: - return [self] trailer = par.parent if trailer.type == 'arglist': trailer = trailer.parent @@ -202,8 +200,6 @@ class AbstractTreeName(AbstractNameDefinition): ) if node_type == 'trailer' and par.children[0] == '.': - if not all_scopes: - return [self] values = infer_call_of_leaf(context, name, cut_own_trailer=True) return values.goto(name, name_context=context) else: @@ -502,8 +498,8 @@ class _ActualTreeParamName(BaseTreeParamName): class AnonymousParamName(_ActualTreeParamName): @plugin_manager.decorate(name='goto_anonymous_param') - def goto(self, **kwargs): - return super(AnonymousParamName, self).goto(**kwargs) + def goto(self): + return super(AnonymousParamName, self).goto() @plugin_manager.decorate(name='infer_anonymous_param') def infer(self): diff --git a/jedi/inference/references.py b/jedi/inference/references.py index ff52cb56..963a16d3 100644 --- a/jedi/inference/references.py +++ b/jedi/inference/references.py @@ -25,7 +25,7 @@ easily 100ms for bigger files. """ -def _resolve_names(definition_names, avoid_names=(), all_scopes=True): +def _resolve_names(definition_names, avoid_names=()): for name in definition_names: if name in avoid_names: # Avoiding recursions here, because goto on a module name lands @@ -37,7 +37,7 @@ def _resolve_names(definition_names, avoid_names=(), all_scopes=True): # names when importing something like `import foo.bar.baz`. yield name - if all_scopes and name.api_type == 'module': + if name.api_type == 'module': for n in _resolve_names(name.goto(), definition_names): yield n @@ -49,17 +49,16 @@ def _dictionarize(names): ) -def _find_defining_names(module_context, tree_name, all_scopes=True): - found_names = _find_names(module_context, tree_name, all_scopes=all_scopes) +def _find_defining_names(module_context, tree_name): + found_names = _find_names(module_context, tree_name) - if all_scopes: - for name in list(found_names): - # Convert from/to stubs, because those might also be usages. - found_names |= set(convert_names( - [name], - only_stubs=not name.get_root_context().is_stub(), - prefer_stub_to_compiled=False - )) + for name in list(found_names): + # Convert from/to stubs, because those might also be usages. + found_names |= set(convert_names( + [name], + only_stubs=not name.get_root_context().is_stub(), + prefer_stub_to_compiled=False + )) found_names |= set(_find_global_variables(found_names, tree_name.value)) for name in list(found_names): @@ -67,15 +66,15 @@ def _find_defining_names(module_context, tree_name, all_scopes=True): or name.tree_name.parent.type == 'trailer': continue found_names |= set(_add_names_in_same_context(name.parent_context, name.string_name)) - return set(_resolve_names(found_names, all_scopes=all_scopes)) + return set(_resolve_names(found_names)) -def _find_names(module_context, tree_name, all_scopes=True): +def _find_names(module_context, tree_name): name = module_context.create_name(tree_name) - found_names = set(name.goto(all_scopes=all_scopes)) + found_names = set(name.goto()) found_names.add(name) - return set(_resolve_names(found_names, all_scopes=all_scopes)) + return set(_resolve_names(found_names)) def _add_names_in_same_context(context, string_name): @@ -114,7 +113,7 @@ def _find_global_variables(names, search_name): yield n -def find_references(module_context, tree_name, all_scopes=True): +def find_references(module_context, tree_name, only_in_module=False): inf = module_context.inference_state search_name = tree_name.value @@ -122,20 +121,20 @@ def find_references(module_context, tree_name, all_scopes=True): # certain cases, we want both sides. try: inf.flow_analysis_enabled = False - found_names = _find_defining_names(module_context, tree_name, all_scopes=all_scopes) + found_names = _find_defining_names(module_context, tree_name) finally: inf.flow_analysis_enabled = True found_names_dct = _dictionarize(found_names) module_contexts = [module_context] - if all_scopes: + if not only_in_module: module_contexts.extend( m for m in set(d.get_root_context() for d in found_names) if m != module_context and m.tree_node is not None ) # For param no search for other modules is necessary. - if not all_scopes or any(n.api_type == 'param' for n in found_names): + if only_in_module or any(n.api_type == 'param' for n in found_names): potential_modules = module_contexts else: potential_modules = get_module_contexts_containing_name( @@ -144,15 +143,10 @@ def find_references(module_context, tree_name, all_scopes=True): search_name, ) - gotos = set() - if not all_scopes: - for name in found_names_dct.values(): - gotos |= set(name.goto()) - non_matching_reference_maps = {} for module_context in potential_modules: for name_leaf in module_context.tree_node.get_used_names().get(search_name, []): - new = _dictionarize(_find_names(module_context, name_leaf, all_scopes=all_scopes)) + new = _dictionarize(_find_names(module_context, name_leaf)) if any(tree_name in found_names_dct for tree_name in new): found_names_dct.update(new) for tree_name in new: @@ -167,19 +161,10 @@ def find_references(module_context, tree_name, all_scopes=True): else: for name in new: non_matching_reference_maps.setdefault(name, []).append(new) - - if not all_scopes: - def in_gotos(g): - for g_ in gotos: - if g.start_pos == g_.start_pos and g.get_root_context() == g_.get_root_context(): - return True - - for dct_list in non_matching_reference_maps.values(): - for dct in dct_list: - for k, v in dct.items(): - if any(in_gotos(g) for g in v.goto()): - found_names_dct[k] = v - return found_names_dct.values() + result = found_names_dct.values() + if only_in_module: + return [n for n in result if n.get_root_context() == module_context] + return result def _check_fs(inference_state, file_io, regex): diff --git a/jedi/plugins/pytest.py b/jedi/plugins/pytest.py index 76754394..f9b04284 100644 --- a/jedi/plugins/pytest.py +++ b/jedi/plugins/pytest.py @@ -63,7 +63,7 @@ def infer_anonymous_param(func): def goto_anonymous_param(func): - def wrapper(param_name, **kwargs): + def wrapper(param_name): is_pytest_param, param_name_is_function_name = \ _is_a_pytest_param_and_inherited(param_name) if is_pytest_param: @@ -74,7 +74,7 @@ def goto_anonymous_param(func): ) if names: return names - return func(param_name, **kwargs) + return func(param_name) return wrapper diff --git a/test/test_api/test_usages.py b/test/test_api/test_usages.py index 27d9d300..cef18fb8 100644 --- a/test/test_api/test_usages.py +++ b/test/test_api/test_usages.py @@ -38,7 +38,7 @@ foo() ''', project=project) def r(*args): - return script.get_references(all_scopes=False, *args) + return script.get_references(scope='file', *args) print(script._code_lines) sys_places = r(1, 7) @@ -79,9 +79,9 @@ def test_local_references_method_other_file(Script): d1 = datetime.now() d2 = datetime.now() ''', project=Project('', sys_path=[], smart_sys_path=False)) - now_places = script.get_references(2, 14, all_scopes=False) + now_places = script.get_references(2, 14, scope='file') assert len(now_places) == 2 - assert now_places == script.get_references(3, 14, all_scopes=False) + assert now_places == script.get_references(3, 14, scope='file') def test_local_references_kwarg(Script): @@ -89,4 +89,4 @@ def test_local_references_kwarg(Script): script = Script('''from jedi import Script Script(code='') ''', project=Project('', sys_path=[], smart_sys_path=False)) - assert len(script.get_references(2, 7, all_scopes=False)) == 1 + assert len(script.get_references(2, 7, scope='file')) == 1 From 8705149619bdcd574b46e5932a8cf561ab3dc3c9 Mon Sep 17 00:00:00 2001 From: muffinmad Date: Wed, 3 Jun 2020 17:20:23 +0300 Subject: [PATCH 7/9] Use pytest.mark.parametrize --- test/test_api/test_usages.py | 86 ++++++++++++------------------------ 1 file changed, 28 insertions(+), 58 deletions(-) diff --git a/test/test_api/test_usages.py b/test/test_api/test_usages.py index cef18fb8..69dff339 100644 --- a/test/test_api/test_usages.py +++ b/test/test_api/test_usages.py @@ -1,3 +1,6 @@ +import pytest + + def test_import_references(Script): s = Script("from .. import foo", path="foo.py") assert [usage.line for usage in s.get_references(line=1, column=18)] == [1] @@ -17,11 +20,26 @@ def test_exclude_builtin_modules(Script): assert places == [(1, 7), (2, 6)] -def test_references_scope(Script): - from jedi.api.project import Project - project = Project('', sys_path=[], smart_sys_path=False) - script = Script( - '''import sys +@pytest.mark.parametrize('code, places', [ + ('', [(1, 7), (4, 6)]), + ('', [(2, 5)]), + ('', [(2, 24), (7, 10), (11, 10)]), + ('', [(6, 4), (14, 0)]), + ('', [(7, 4), (8, 11)]), + ('', [(7, 22), (11, 22)]), + ('', [(11, 4), (12, 11)]), + ('from datetime', [(1, 5)]), + ('''from datetime import datetime +d1 = datetime.now() +d2 = datetime.now() +''', [(2, 14), (3, 14)]), + ('''from jedi import Script +Script(code='') +''', [(2, 7)]) +]) +def test_references_scope(Script, code, places): + if not code: + code = '''import sys from collections import defaultdict print(sys.path) @@ -35,58 +53,10 @@ def bar(foo): return baz foo() -''', project=project) - - def r(*args): - return script.get_references(scope='file', *args) - - print(script._code_lines) - sys_places = r(1, 7) - assert len(sys_places) == 2 - assert sys_places == r(4, 6) - - assert len(r(2, 5)) == 1 - - dd_places = r(2, 24) - assert len(dd_places) == 3 - assert dd_places == r(7, 10) - assert dd_places == r(11, 10) - - foo_places = r(6, 4) - assert len(foo_places) == 2 - assert foo_places == r(14, 0) - - baz_places = r(7, 4) - assert len(baz_places) == 2 - assert baz_places == r(8, 11) - - int_places = r(7, 22) - assert len(int_places) == 2 - assert int_places == r(11, 22) - - baz_places = r(11, 4) - assert len(baz_places) == 2 - assert baz_places == r(12, 11) - - script = Script('from datetime', project=project) - places = r(1, 5) - assert len(places) == 1 - - -def test_local_references_method_other_file(Script): +''' from jedi.api.project import Project - script = Script('''from datetime import datetime -d1 = datetime.now() -d2 = datetime.now() -''', project=Project('', sys_path=[], smart_sys_path=False)) - now_places = script.get_references(2, 14, scope='file') - assert len(now_places) == 2 - assert now_places == script.get_references(3, 14, scope='file') + project = Project('', sys_path=[], smart_sys_path=False) + script = Script(code, project=project) - -def test_local_references_kwarg(Script): - from jedi.api.project import Project - script = Script('''from jedi import Script -Script(code='') -''', project=Project('', sys_path=[], smart_sys_path=False)) - assert len(script.get_references(2, 7, scope='file')) == 1 + for place in places: + assert places == [(n.line, n.column) for n in script.get_references(scope='file', *place)] From 1e58f9a15ca29b032be473752a57bc62ba7e769f Mon Sep 17 00:00:00 2001 From: muffinmad Date: Fri, 5 Jun 2020 15:28:22 +0300 Subject: [PATCH 8/9] Test both named params are found --- test/test_api/test_usages.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/test_api/test_usages.py b/test/test_api/test_usages.py index 69dff339..fa4896d3 100644 --- a/test/test_api/test_usages.py +++ b/test/test_api/test_usages.py @@ -34,8 +34,9 @@ d1 = datetime.now() d2 = datetime.now() ''', [(2, 14), (3, 14)]), ('''from jedi import Script -Script(code='') -''', [(2, 7)]) +s1 = Script(code='') +s2 = Script(code='') +''', [(2, 12), (3, 12)]) ]) def test_references_scope(Script, code, places): if not code: From 404661f361e8f38a147406308cd48f0b4bed502b Mon Sep 17 00:00:00 2001 From: muffinmad Date: Fri, 5 Jun 2020 17:44:59 +0300 Subject: [PATCH 9/9] Replace Script by timedelta in the test --- test/test_api/test_usages.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/test_api/test_usages.py b/test/test_api/test_usages.py index fa4896d3..e3868333 100644 --- a/test/test_api/test_usages.py +++ b/test/test_api/test_usages.py @@ -33,10 +33,10 @@ def test_exclude_builtin_modules(Script): d1 = datetime.now() d2 = datetime.now() ''', [(2, 14), (3, 14)]), - ('''from jedi import Script -s1 = Script(code='') -s2 = Script(code='') -''', [(2, 12), (3, 12)]) + ('''from datetime import timedelta +t1 = timedelta(seconds=1) +t2 = timedelta(seconds=2) +''', [(2, 15), (3, 15)]) ]) def test_references_scope(Script, code, places): if not code: