From 8f306953dac9c7fd6fa6b900ac500962dc7d3fed Mon Sep 17 00:00:00 2001 From: Johannes Maria Frank Date: Thu, 26 Sep 2019 08:17:30 +0100 Subject: [PATCH 01/14] Added experimental substring and fuzzysearch --- jedi/api/completion.py | 18 +++++++++++++++++- test/test_api/test_completion.py | 15 +++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/jedi/api/completion.py b/jedi/api/completion.py index d5c9182b..7a3c9c88 100644 --- a/jedi/api/completion.py +++ b/jedi/api/completion.py @@ -27,6 +27,22 @@ def get_call_signature_param_names(call_signatures): Parameter.KEYWORD_ONLY): yield p._name +def start_match(string, like_name): + return string.startswith(like_name) + + +def substr_match(string, like_name): + return like_name in string + + +def fuzzy_match(string, like_name): + if len(like_name) <= 1: + return like_name in string + pos = string.find(like_name[0]) + if pos >= 0: + return fuzzy_match(string[pos + 1:], like_name[1:]) + return False + def filter_names(inference_state, completion_names, stack, like_name): comp_dct = {} @@ -37,7 +53,7 @@ def filter_names(inference_state, completion_names, stack, like_name): if settings.case_insensitive_completion: string = string.lower() - if string.startswith(like_name): + if fuzzy_match(string, like_name): new = classes.Completion( inference_state, name, diff --git a/test/test_api/test_completion.py b/test/test_api/test_completion.py index 1d3d092b..d0da4864 100644 --- a/test/test_api/test_completion.py +++ b/test/test_api/test_completion.py @@ -267,3 +267,18 @@ def test_file_path_completions(Script, file, code, column, expected): assert len(comps) > 100 # This is basically global completions. else: assert [c.complete for c in comps] == expected + +from jedi.api.completion import start_match, substr_match, fuzzy_match + +def test_start_match(): + assert start_match('Condition', 'C') + +def test_substr_match(): + assert substr_match('Condition', 'dit') + +def test_fuzzy_match(): + assert fuzzy_match('Condition', 'i') + assert not fuzzy_match('Condition', 'p') + assert fuzzy_match('Condition', 'ii') + assert not fuzzy_match('Condition', 'Ciito') + assert fuzzy_match('Condition', 'Cdiio') From 0bbc8d6e9a0d63346b276a07089546fa4bbd7908 Mon Sep 17 00:00:00 2001 From: Johannes Maria Frank Date: Thu, 26 Sep 2019 09:12:15 +0100 Subject: [PATCH 02/14] Added match_method parameter --- jedi/api/completion.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/jedi/api/completion.py b/jedi/api/completion.py index 7a3c9c88..8959efe2 100644 --- a/jedi/api/completion.py +++ b/jedi/api/completion.py @@ -44,7 +44,7 @@ def fuzzy_match(string, like_name): return False -def filter_names(inference_state, completion_names, stack, like_name): +def filter_names(inference_state, completion_names, stack, like_name, match_method): comp_dct = {} if settings.case_insensitive_completion: like_name = like_name.lower() @@ -53,7 +53,7 @@ def filter_names(inference_state, completion_names, stack, like_name): if settings.case_insensitive_completion: string = string.lower() - if fuzzy_match(string, like_name): + if match_method(string, like_name): new = classes.Completion( inference_state, name, @@ -100,7 +100,10 @@ class Completion: self._position = position[0], position[1] - len(self._like_name) self._call_signatures_callback = call_signatures_callback - def completions(self): + def completions(self, **kwargs): + return self._completions(**kwargs) + + def _completions(self, method=start_match): leaf = self._module_node.get_leaf_for_position(self._position, include_prefixes=True) string, start_leaf = _extract_string_while_in_string(leaf, self._position) if string is not None: @@ -115,7 +118,7 @@ class Completion: completion_names = self._get_value_completions(leaf) completions = filter_names(self._inference_state, completion_names, - self.stack, self._like_name) + self.stack, self._like_name, method) return sorted(completions, key=lambda x: (x.name.startswith('__'), x.name.startswith('_'), From 85278242c336fcf6712e179a7dfd0bef2090e786 Mon Sep 17 00:00:00 2001 From: Johannes Maria Frank Date: Wed, 2 Oct 2019 00:28:31 +0100 Subject: [PATCH 03/14] Switched to fuzzy boolean --- jedi/api/completion.py | 17 ++++++++--------- test/test_api/test_completion.py | 5 +---- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/jedi/api/completion.py b/jedi/api/completion.py index 8959efe2..bf4ec9ab 100644 --- a/jedi/api/completion.py +++ b/jedi/api/completion.py @@ -31,10 +31,6 @@ def start_match(string, like_name): return string.startswith(like_name) -def substr_match(string, like_name): - return like_name in string - - def fuzzy_match(string, like_name): if len(like_name) <= 1: return like_name in string @@ -44,7 +40,7 @@ def fuzzy_match(string, like_name): return False -def filter_names(inference_state, completion_names, stack, like_name, match_method): +def filter_names(inference_state, completion_names, stack, like_name, fuzzy): comp_dct = {} if settings.case_insensitive_completion: like_name = like_name.lower() @@ -52,8 +48,11 @@ def filter_names(inference_state, completion_names, stack, like_name, match_meth string = name.string_name if settings.case_insensitive_completion: string = string.lower() - - if match_method(string, like_name): + if fuzzy: + match = fuzzy_match(string, like_name) + else: + match = start_match(string, like_name) + if match: new = classes.Completion( inference_state, name, @@ -103,7 +102,7 @@ class Completion: def completions(self, **kwargs): return self._completions(**kwargs) - def _completions(self, method=start_match): + def _completions(self, fuzzy=False): leaf = self._module_node.get_leaf_for_position(self._position, include_prefixes=True) string, start_leaf = _extract_string_while_in_string(leaf, self._position) if string is not None: @@ -118,7 +117,7 @@ class Completion: completion_names = self._get_value_completions(leaf) completions = filter_names(self._inference_state, completion_names, - self.stack, self._like_name, method) + self.stack, self._like_name, fuzzy) return sorted(completions, key=lambda x: (x.name.startswith('__'), x.name.startswith('_'), diff --git a/test/test_api/test_completion.py b/test/test_api/test_completion.py index d0da4864..6b5735af 100644 --- a/test/test_api/test_completion.py +++ b/test/test_api/test_completion.py @@ -268,14 +268,11 @@ def test_file_path_completions(Script, file, code, column, expected): else: assert [c.complete for c in comps] == expected -from jedi.api.completion import start_match, substr_match, fuzzy_match +from jedi.api.completion import start_match, fuzzy_match def test_start_match(): assert start_match('Condition', 'C') -def test_substr_match(): - assert substr_match('Condition', 'dit') - def test_fuzzy_match(): assert fuzzy_match('Condition', 'i') assert not fuzzy_match('Condition', 'p') From 0b56bf8f0864fb7df5c9e832c8047764a1453207 Mon Sep 17 00:00:00 2001 From: Johannes Maria Frank Date: Fri, 4 Oct 2019 17:18:01 +0100 Subject: [PATCH 04/14] Added completions test with fuzzy=True --- jedi/api/__init__.py | 4 ++-- jedi/api/completion.py | 10 ++++++---- test/test_api/test_api.py | 7 +++++++ 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/jedi/api/__init__.py b/jedi/api/__init__.py index 94893a3d..0e505c9f 100644 --- a/jedi/api/__init__.py +++ b/jedi/api/__init__.py @@ -201,7 +201,7 @@ class Script(object): self._inference_state.environment, ) - def completions(self): + def completions(self, fuzzy=False): """ Return :class:`classes.Completion` objects. Those objects contain information about the completions, more than just names. @@ -214,7 +214,7 @@ class Script(object): self._inference_state, self._get_module_context(), self._code_lines, self._pos, self.call_signatures ) - return completion.completions() + return completion.completions(fuzzy) def goto_definitions(self, **kwargs): """ diff --git a/jedi/api/completion.py b/jedi/api/completion.py index bf4ec9ab..906a2149 100644 --- a/jedi/api/completion.py +++ b/jedi/api/completion.py @@ -85,7 +85,7 @@ def get_flow_scope_node(module_node, position): class Completion: def __init__(self, inference_state, module_context, code_lines, position, - call_signatures_callback): + call_signatures_callback, fuzzy=False): self._inference_state = inference_state self._module_context = module_context self._module_node = module_context.tree_node @@ -99,10 +99,12 @@ class Completion: self._position = position[0], position[1] - len(self._like_name) self._call_signatures_callback = call_signatures_callback - def completions(self, **kwargs): - return self._completions(**kwargs) + self._fuzzy = fuzzy - def _completions(self, fuzzy=False): + def completions(self, fuzzy=False, **kwargs): + return self._completions(fuzzy, **kwargs) + + def _completions(self, fuzzy): leaf = self._module_node.get_leaf_for_position(self._position, include_prefixes=True) string, start_leaf = _extract_string_while_in_string(leaf, self._position) if string is not None: diff --git a/test/test_api/test_api.py b/test/test_api/test_api.py index bfe305b6..0edd8613 100644 --- a/test/test_api/test_api.py +++ b/test/test_api/test_api.py @@ -304,3 +304,10 @@ def test_goto_follow_builtin_imports(Script): assert d.in_builtin_module() is True d, = s.goto_assignments(follow_imports=True, follow_builtin_imports=True) assert d.in_builtin_module() is True + + +def test_fuzzy_completion(Script): + script = Script('string = "hello"\nstring.upper') + assert ['isupper', 'upper'] == [comp.name + for comp in + script.completions(fuzzy=True)] From 48ffc5473abc3f6828fa5afe3d0859ad7e6e4d8e Mon Sep 17 00:00:00 2001 From: Johannes Maria Frank Date: Wed, 9 Oct 2019 10:37:46 +0200 Subject: [PATCH 05/14] Added test for math og --- test/test_api/test_api.py | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/test/test_api/test_api.py b/test/test_api/test_api.py index 0edd8613..dcba7496 100644 --- a/test/test_api/test_api.py +++ b/test/test_api/test_api.py @@ -23,8 +23,7 @@ def test_preload_modules(): # Filter the typeshed parser cache. typeshed_cache_count = sum( 1 for path in grammar_cache - if path is not None and path.startswith(typeshed.TYPESHED_PATH) - ) + if path is not None and path.startswith(typeshed.TYPESHED_PATH)) # +1 for None module (currently used) assert len(grammar_cache) - typeshed_cache_count == len(modules) + 1 for i in modules: @@ -35,7 +34,8 @@ def test_preload_modules(): try: preload_module('sys') - check_loaded() # compiled (c_builtin) modules shouldn't be in the cache. + check_loaded( + ) # compiled (c_builtin) modules shouldn't be in the cache. preload_module('types', 'token') check_loaded('types', 'token') finally: @@ -117,8 +117,9 @@ def test_completion_on_complex_literals(Script): # However this has been disabled again, because it apparently annoyed # users. So no completion after j without a space :) assert not Script('4j').completions() - assert ({c.name for c in Script('4j ').completions()} == - {'if', 'and', 'in', 'is', 'not', 'or'}) + assert ({c.name + for c in Script('4j ').completions() + } == {'if', 'and', 'in', 'is', 'not', 'or'}) def test_goto_assignments_on_non_name(Script, environment): @@ -167,7 +168,8 @@ def test_usage_description(Script): def test_get_line_code(Script): def get_line_code(source, line=None, **kwargs): - return Script(source, line=line).completions()[0].get_line_code(**kwargs) + return Script(source, + line=line).completions()[0].get_line_code(**kwargs) # On builtin assert get_line_code('') == '' @@ -244,8 +246,7 @@ def test_goto_definition_cursor(Script): " b):\n" " return\n" "A._something\n" - "A.different_line" - ) + "A.different_line") in_name = 2, 9 under_score = 2, 8 @@ -308,6 +309,8 @@ def test_goto_follow_builtin_imports(Script): def test_fuzzy_completion(Script): script = Script('string = "hello"\nstring.upper') - assert ['isupper', 'upper'] == [comp.name - for comp in - script.completions(fuzzy=True)] + assert ['isupper', + 'upper'] == [comp.name for comp in script.completions(fuzzy=True)] + script = Script('import math\nmath.og') + assert ['copysign', 'log', 'log10', 'log1p', + 'log2'] == [comp.name for comp in script.completions(fuzzy=True)] From a84087682d2697aea5399063ed0b3096842b63a4 Mon Sep 17 00:00:00 2001 From: Johannes Maria Frank Date: Thu, 10 Oct 2019 12:10:19 +0200 Subject: [PATCH 06/14] Adopted results for different python versions --- test/test_api/test_api.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/test/test_api/test_api.py b/test/test_api/test_api.py index dcba7496..25591cab 100644 --- a/test/test_api/test_api.py +++ b/test/test_api/test_api.py @@ -307,10 +307,23 @@ def test_goto_follow_builtin_imports(Script): assert d.in_builtin_module() is True -def test_fuzzy_completion(Script): +def test_str_fuzzy_completion(Script): script = Script('string = "hello"\nstring.upper') assert ['isupper', 'upper'] == [comp.name for comp in script.completions(fuzzy=True)] + + +@pytest.mark.skipif(sys.version_info < (3, 3), + reason="requires python3.3 or higher") +def test_math_fuzzy_completion(Script): + script = Script('import math\nmath.og') + assert ['copysign', 'log', 'log10', + 'log1p'] == [comp.name for comp in script.completions(fuzzy=True)] + + +@pytest.mark.skipif(sys.version_info >= (3, 3), + reason="requires python3.3 or higher") +def test_math_fuzzy_completion(Script): script = Script('import math\nmath.og') assert ['copysign', 'log', 'log10', 'log1p', 'log2'] == [comp.name for comp in script.completions(fuzzy=True)] From 1fa678e3fe93a40a1531476ccc690ae6f00bac5e Mon Sep 17 00:00:00 2001 From: Johannes Maria Frank Date: Thu, 10 Oct 2019 13:23:33 +0200 Subject: [PATCH 07/14] Corrected an error in the math fuzzy completion test --- test/test_api/test_api.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/test_api/test_api.py b/test/test_api/test_api.py index 25591cab..d5371c1f 100644 --- a/test/test_api/test_api.py +++ b/test/test_api/test_api.py @@ -317,13 +317,13 @@ def test_str_fuzzy_completion(Script): reason="requires python3.3 or higher") def test_math_fuzzy_completion(Script): script = Script('import math\nmath.og') - assert ['copysign', 'log', 'log10', - 'log1p'] == [comp.name for comp in script.completions(fuzzy=True)] + assert ['copysign', 'log', 'log10', 'log1p', + 'log2'] == [comp.name for comp in script.completions(fuzzy=True)] @pytest.mark.skipif(sys.version_info >= (3, 3), reason="requires python3.3 or higher") def test_math_fuzzy_completion(Script): script = Script('import math\nmath.og') - assert ['copysign', 'log', 'log10', 'log1p', - 'log2'] == [comp.name for comp in script.completions(fuzzy=True)] + assert ['copysign', 'log', 'log10', + 'log1p'] == [comp.name for comp in script.completions(fuzzy=True)] From d73f32745dd90b1687e5ea439fa04c1a6b5b51f1 Mon Sep 17 00:00:00 2001 From: Johannes Maria Frank Date: Thu, 10 Oct 2019 15:02:00 +0200 Subject: [PATCH 08/14] Fixed bug for python 2 --- test/test_api/test_api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_api/test_api.py b/test/test_api/test_api.py index d5371c1f..0bab3491 100644 --- a/test/test_api/test_api.py +++ b/test/test_api/test_api.py @@ -321,7 +321,7 @@ def test_math_fuzzy_completion(Script): 'log2'] == [comp.name for comp in script.completions(fuzzy=True)] -@pytest.mark.skipif(sys.version_info >= (3, 3), +@pytest.mark.skipif(sys.version_info > (2, 7), reason="requires python3.3 or higher") def test_math_fuzzy_completion(Script): script = Script('import math\nmath.og') From 2653752f9c94c73b23d69d22184275e5a4b2b748 Mon Sep 17 00:00:00 2001 From: Johannes Maria Frank Date: Mon, 21 Oct 2019 15:44:03 +0100 Subject: [PATCH 09/14] Corrected formatting --- test/test_api/test_api.py | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/test/test_api/test_api.py b/test/test_api/test_api.py index 0bab3491..a90c1a89 100644 --- a/test/test_api/test_api.py +++ b/test/test_api/test_api.py @@ -23,7 +23,8 @@ def test_preload_modules(): # Filter the typeshed parser cache. typeshed_cache_count = sum( 1 for path in grammar_cache - if path is not None and path.startswith(typeshed.TYPESHED_PATH)) + if path is not None and path.startswith(typeshed.TYPESHED_PATH) + ) # +1 for None module (currently used) assert len(grammar_cache) - typeshed_cache_count == len(modules) + 1 for i in modules: @@ -34,8 +35,7 @@ def test_preload_modules(): try: preload_module('sys') - check_loaded( - ) # compiled (c_builtin) modules shouldn't be in the cache. + check_loaded() # compiled (c_builtin) modules shouldn't be in the cache. preload_module('types', 'token') check_loaded('types', 'token') finally: @@ -117,9 +117,8 @@ def test_completion_on_complex_literals(Script): # However this has been disabled again, because it apparently annoyed # users. So no completion after j without a space :) assert not Script('4j').completions() - assert ({c.name - for c in Script('4j ').completions() - } == {'if', 'and', 'in', 'is', 'not', 'or'}) + assert ({c.name for c in Script('4j ').completions()} == + {'if', 'and', 'in', 'is', 'not', 'or'}) def test_goto_assignments_on_non_name(Script, environment): @@ -168,8 +167,7 @@ def test_usage_description(Script): def test_get_line_code(Script): def get_line_code(source, line=None, **kwargs): - return Script(source, - line=line).completions()[0].get_line_code(**kwargs) + return Script(source, line=line).completions()[0].get_line_code(**kwargs) # On builtin assert get_line_code('') == '' @@ -246,7 +244,8 @@ def test_goto_definition_cursor(Script): " b):\n" " return\n" "A._something\n" - "A.different_line") + "A.different_line" + ) in_name = 2, 9 under_score = 2, 8 @@ -307,7 +306,7 @@ def test_goto_follow_builtin_imports(Script): assert d.in_builtin_module() is True -def test_str_fuzzy_completion(Script): +def test_fuzzy_completion(Script): script = Script('string = "hello"\nstring.upper') assert ['isupper', 'upper'] == [comp.name for comp in script.completions(fuzzy=True)] @@ -326,4 +325,4 @@ def test_math_fuzzy_completion(Script): def test_math_fuzzy_completion(Script): script = Script('import math\nmath.og') assert ['copysign', 'log', 'log10', - 'log1p'] == [comp.name for comp in script.completions(fuzzy=True)] + 'log1p'] == [comp.name for comp in script.completions(fuzzy=True)] \ No newline at end of file From f7fae4dde71f9e23544049ab407ce5176c222755 Mon Sep 17 00:00:00 2001 From: Johannes Maria Frank Date: Tue, 22 Oct 2019 15:50:16 +0100 Subject: [PATCH 10/14] Added file fuzzy match and refactored --- jedi/api/__init__.py | 2 +- jedi/api/completion.py | 19 ++++--------------- jedi/api/file_name.py | 9 +++++++-- jedi/api/helpers.py | 13 +++++++++++++ jedi/api/replstartup.py | 2 +- jedi/utils.py | 4 ++-- test/test_api/test_api.py | 16 +++++++++++++++- test/test_api/test_completion.py | 2 +- 8 files changed, 44 insertions(+), 23 deletions(-) diff --git a/jedi/api/__init__.py b/jedi/api/__init__.py index 0e505c9f..4ab5c19c 100644 --- a/jedi/api/__init__.py +++ b/jedi/api/__init__.py @@ -201,7 +201,7 @@ class Script(object): self._inference_state.environment, ) - def completions(self, fuzzy=False): + def completions(self, fuzzy=True): """ Return :class:`classes.Completion` objects. Those objects contain information about the completions, more than just names. diff --git a/jedi/api/completion.py b/jedi/api/completion.py index 906a2149..d9ffda06 100644 --- a/jedi/api/completion.py +++ b/jedi/api/completion.py @@ -27,18 +27,6 @@ def get_call_signature_param_names(call_signatures): Parameter.KEYWORD_ONLY): yield p._name -def start_match(string, like_name): - return string.startswith(like_name) - - -def fuzzy_match(string, like_name): - if len(like_name) <= 1: - return like_name in string - pos = string.find(like_name[0]) - if pos >= 0: - return fuzzy_match(string[pos + 1:], like_name[1:]) - return False - def filter_names(inference_state, completion_names, stack, like_name, fuzzy): comp_dct = {} @@ -49,9 +37,9 @@ def filter_names(inference_state, completion_names, stack, like_name, fuzzy): if settings.case_insensitive_completion: string = string.lower() if fuzzy: - match = fuzzy_match(string, like_name) + match = helpers.fuzzy_match(string, like_name) else: - match = start_match(string, like_name) + match = helpers.start_match(string, like_name) if match: new = classes.Completion( inference_state, @@ -111,7 +99,8 @@ class Completion: completions = list(file_name_completions( self._inference_state, self._module_context, start_leaf, string, self._like_name, self._call_signatures_callback, - self._code_lines, self._original_position + self._code_lines, self._original_position, + fuzzy )) if completions: return completions diff --git a/jedi/api/file_name.py b/jedi/api/file_name.py index 5871fd90..04f90ba9 100644 --- a/jedi/api/file_name.py +++ b/jedi/api/file_name.py @@ -3,12 +3,13 @@ import os from jedi._compatibility import FileNotFoundError, force_unicode, scandir from jedi.inference.names import AbstractArbitraryName from jedi.api import classes +from jedi.api.helpers import fuzzy_match, start_match from jedi.inference.helpers import get_str_or_none from jedi.parser_utils import get_string_quote def file_name_completions(inference_state, module_context, start_leaf, string, - like_name, call_signatures_callback, code_lines, position): + like_name, call_signatures_callback, code_lines, position, fuzzy): # First we want to find out what can actually be changed as a name. like_name_length = len(os.path.basename(string) + like_name) @@ -37,7 +38,11 @@ def file_name_completions(inference_state, module_context, start_leaf, string, return for entry in listed: name = entry.name - if name.startswith(must_start_with): + if fuzzy: + match = fuzzy_match(name, must_start_with) + else: + match = start_match(name, must_start_with) + if match: if is_in_os_path_join or not entry.is_dir(): if start_leaf.type == 'string': quote = get_string_quote(start_leaf) diff --git a/jedi/api/helpers.py b/jedi/api/helpers.py index 236deb02..b59fee93 100644 --- a/jedi/api/helpers.py +++ b/jedi/api/helpers.py @@ -19,6 +19,19 @@ from jedi.cache import call_signature_time_cache CompletionParts = namedtuple('CompletionParts', ['path', 'has_dot', 'name']) +def start_match(string, like_name): + return string.startswith(like_name) + + +def fuzzy_match(string, like_name): + if len(like_name) <= 1: + return like_name in string + pos = string.find(like_name[0]) + if pos >= 0: + return fuzzy_match(string[pos + 1:], like_name[1:]) + return False + + def sorted_definitions(defs): # Note: `or ''` below is required because `module_path` could be return sorted(defs, key=lambda x: (x.module_path or '', x.line or 0, x.column or 0, x.name)) diff --git a/jedi/api/replstartup.py b/jedi/api/replstartup.py index 3ac84708..38aa8e6f 100644 --- a/jedi/api/replstartup.py +++ b/jedi/api/replstartup.py @@ -21,7 +21,7 @@ import jedi.utils from jedi import __version__ as __jedi_version__ print('REPL completion using Jedi %s' % __jedi_version__) -jedi.utils.setup_readline() +jedi.utils.setup_readline(fuzzy=False) del jedi diff --git a/jedi/utils.py b/jedi/utils.py index a5cf84b1..56b21d0c 100644 --- a/jedi/utils.py +++ b/jedi/utils.py @@ -17,7 +17,7 @@ from jedi import Interpreter READLINE_DEBUG = False -def setup_readline(namespace_module=__main__): +def setup_readline(namespace_module=__main__, fuzzy=False): """ Install Jedi completer to :mod:`readline`. @@ -83,7 +83,7 @@ def setup_readline(namespace_module=__main__): logging.debug("Start REPL completion: " + repr(text)) interpreter = Interpreter(text, [namespace_module.__dict__]) - completions = interpreter.completions() + completions = interpreter.completions(fuzzy=fuzzy) logging.debug("REPL completions: %s", completions) self.matches = [ diff --git a/test/test_api/test_api.py b/test/test_api/test_api.py index a90c1a89..c370be48 100644 --- a/test/test_api/test_api.py +++ b/test/test_api/test_api.py @@ -306,6 +306,18 @@ def test_goto_follow_builtin_imports(Script): assert d.in_builtin_module() is True +def test_file_fuzzy_completion(Script, tmp_path): + folder0 = tmp_path / "inference" + folder0.mkdir() + file0_path0 = folder0 / "sys_path.py" + file0_path0.write_text('\n') + file0_path1 = folder0 / "syntax_tree.py" + file0_path1.write_text('\n') + script = Script('"{}/yt'.format(folder0)) + assert ['sys_path.py"', + 'syntax_tree.py"' ] == [comp.name for comp in script.completions(fuzzy=True)] + + def test_fuzzy_completion(Script): script = Script('string = "hello"\nstring.upper') assert ['isupper', @@ -325,4 +337,6 @@ def test_math_fuzzy_completion(Script): def test_math_fuzzy_completion(Script): script = Script('import math\nmath.og') assert ['copysign', 'log', 'log10', - 'log1p'] == [comp.name for comp in script.completions(fuzzy=True)] \ No newline at end of file + 'log1p'] == [comp.name for comp in script.completions(fuzzy=True)] + + diff --git a/test/test_api/test_completion.py b/test/test_api/test_completion.py index 6b5735af..ab1af15b 100644 --- a/test/test_api/test_completion.py +++ b/test/test_api/test_completion.py @@ -268,7 +268,7 @@ def test_file_path_completions(Script, file, code, column, expected): else: assert [c.complete for c in comps] == expected -from jedi.api.completion import start_match, fuzzy_match +from jedi.api.helpers import start_match, fuzzy_match def test_start_match(): assert start_match('Condition', 'C') From f61d041830c34c27ceb20f81a1b9e75acb7fde87 Mon Sep 17 00:00:00 2001 From: Johannes Maria Frank Date: Tue, 22 Oct 2019 16:06:46 +0100 Subject: [PATCH 11/14] Switched back to fuzzy off as default --- jedi/api/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jedi/api/__init__.py b/jedi/api/__init__.py index 4ab5c19c..0e505c9f 100644 --- a/jedi/api/__init__.py +++ b/jedi/api/__init__.py @@ -201,7 +201,7 @@ class Script(object): self._inference_state.environment, ) - def completions(self, fuzzy=True): + def completions(self, fuzzy=False): """ Return :class:`classes.Completion` objects. Those objects contain information about the completions, more than just names. From d48816603e58049be91698d9df3e3ec2023ac2fd Mon Sep 17 00:00:00 2001 From: Johannes Maria Frank Date: Tue, 22 Oct 2019 16:34:47 +0100 Subject: [PATCH 12/14] Sorted scandir results to have completions ordered --- test/test_api/test_api.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test_api/test_api.py b/test/test_api/test_api.py index c370be48..b49a651d 100644 --- a/test/test_api/test_api.py +++ b/test/test_api/test_api.py @@ -314,8 +314,8 @@ def test_file_fuzzy_completion(Script, tmp_path): file0_path1 = folder0 / "syntax_tree.py" file0_path1.write_text('\n') script = Script('"{}/yt'.format(folder0)) - assert ['sys_path.py"', - 'syntax_tree.py"' ] == [comp.name for comp in script.completions(fuzzy=True)] + assert ['syntax_tree.py"', + 'sys_path.py"'] == [comp.name for comp in script.completions(fuzzy=True)] def test_fuzzy_completion(Script): From 2039ab9a3c0952db6777054d38ea1b9b4c07a97a Mon Sep 17 00:00:00 2001 From: Johannes Maria Frank Date: Tue, 22 Oct 2019 16:47:06 +0100 Subject: [PATCH 13/14] Fixed pytest fixtures for test_api --- test/test_api/test_api.py | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/test/test_api/test_api.py b/test/test_api/test_api.py index b49a651d..e6ab5506 100644 --- a/test/test_api/test_api.py +++ b/test/test_api/test_api.py @@ -306,18 +306,6 @@ def test_goto_follow_builtin_imports(Script): assert d.in_builtin_module() is True -def test_file_fuzzy_completion(Script, tmp_path): - folder0 = tmp_path / "inference" - folder0.mkdir() - file0_path0 = folder0 / "sys_path.py" - file0_path0.write_text('\n') - file0_path1 = folder0 / "syntax_tree.py" - file0_path1.write_text('\n') - script = Script('"{}/yt'.format(folder0)) - assert ['syntax_tree.py"', - 'sys_path.py"'] == [comp.name for comp in script.completions(fuzzy=True)] - - def test_fuzzy_completion(Script): script = Script('string = "hello"\nstring.upper') assert ['isupper', @@ -331,6 +319,19 @@ def test_math_fuzzy_completion(Script): assert ['copysign', 'log', 'log10', 'log1p', 'log2'] == [comp.name for comp in script.completions(fuzzy=True)] +@pytest.mark.skipif(sys.version_info < (3, 3), + reason="requires python3.3 or higher") +def test_file_fuzzy_completion(Script, tmp_path): + folder0 = tmp_path / "inference" + folder0.mkdir() + file0_path0 = folder0 / "sys_path.py" + file0_path0.write_text('\n') + file0_path1 = folder0 / "syntax_tree.py" + file0_path1.write_text('\n') + script = Script('"{}/yt'.format(folder0)) + assert ['syntax_tree.py"', + 'sys_path.py"'] == [comp.name for comp in script.completions(fuzzy=True)] + @pytest.mark.skipif(sys.version_info > (2, 7), reason="requires python3.3 or higher") @@ -339,4 +340,16 @@ def test_math_fuzzy_completion(Script): assert ['copysign', 'log', 'log10', 'log1p'] == [comp.name for comp in script.completions(fuzzy=True)] +@pytest.mark.skipif(sys.version_info > (2, 7), + reason="requires python3.3 or higher") +def test_file_fuzzy_completion(Script, tmp_path): + folder0 = tmp_path / u"inference" + folder0.mkdir() + file0_path0 = folder0 / u"sys_path.py" + file0_path0.write_text('\n') + file0_path1 = folder0 / u"syntax_tree.py" + file0_path1.write_text('\n') + script = Script('"{}/yt'.format(folder0)) + assert ['syntax_tree.py"', + 'sys_path.py"'] == [comp.name for comp in script.completions(fuzzy=True)] From 364a527fd9ed853c2616c84677aa49b411810f06 Mon Sep 17 00:00:00 2001 From: Johannes Maria Frank Date: Tue, 22 Oct 2019 16:49:35 +0100 Subject: [PATCH 14/14] Added missing sorted to scandir --- jedi/api/file_name.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jedi/api/file_name.py b/jedi/api/file_name.py index 04f90ba9..41db5a92 100644 --- a/jedi/api/file_name.py +++ b/jedi/api/file_name.py @@ -33,7 +33,7 @@ def file_name_completions(inference_state, module_context, start_leaf, string, string = to_be_added + string base_path = os.path.join(inference_state.project._path, string) try: - listed = scandir(base_path) + listed = sorted(scandir(base_path), key=lambda e:e.name) except FileNotFoundError: return for entry in listed: