gh-69605: Disable PyREPL module autocomplete fallback on regular completion (gh-134181)

Co-authored-by: Loïc Simon <loic.simon@napta.io>
This commit is contained in:
Loïc Simon 2025-05-26 01:05:08 +02:00 committed by GitHub
parent a32ea45699
commit 0e3bc962c6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 27 additions and 12 deletions

View file

@ -42,11 +42,11 @@ class ModuleCompleter:
self._global_cache: list[pkgutil.ModuleInfo] = []
self._curr_sys_path: list[str] = sys.path[:]
def get_completions(self, line: str) -> list[str]:
def get_completions(self, line: str) -> list[str] | None:
"""Return the next possible import completions for 'line'."""
result = ImportParser(line).parse()
if not result:
return []
return None
try:
return self.complete(*result)
except Exception:

View file

@ -134,7 +134,8 @@ class ReadlineAlikeReader(historical_reader.HistoricalReader, CompletingReader):
return "".join(b[p + 1 : self.pos])
def get_completions(self, stem: str) -> list[str]:
if module_completions := self.get_module_completions():
module_completions = self.get_module_completions()
if module_completions is not None:
return module_completions
if len(stem) == 0 and self.more_lines is not None:
b = self.buffer
@ -165,7 +166,7 @@ class ReadlineAlikeReader(historical_reader.HistoricalReader, CompletingReader):
result.sort()
return result
def get_module_completions(self) -> list[str]:
def get_module_completions(self) -> list[str] | None:
line = self.get_line()
return self.config.module_completer.get_completions(line)

View file

@ -918,7 +918,14 @@ class TestPyReplCompleter(TestCase):
class TestPyReplModuleCompleter(TestCase):
def setUp(self):
import importlib
# Make iter_modules() search only the standard library.
# This makes the test more reliable in case there are
# other user packages/scripts on PYTHONPATH which can
# interfere with the completions.
lib_path = os.path.dirname(importlib.__path__[0])
self._saved_sys_path = sys.path
sys.path = [lib_path]
def tearDown(self):
sys.path = self._saved_sys_path
@ -932,14 +939,6 @@ class TestPyReplModuleCompleter(TestCase):
return reader
def test_import_completions(self):
import importlib
# Make iter_modules() search only the standard library.
# This makes the test more reliable in case there are
# other user packages/scripts on PYTHONPATH which can
# intefere with the completions.
lib_path = os.path.dirname(importlib.__path__[0])
sys.path = [lib_path]
cases = (
("import path\t\n", "import pathlib"),
("import importlib.\t\tres\t\n", "import importlib.resources"),
@ -1052,6 +1051,19 @@ class TestPyReplModuleCompleter(TestCase):
output = reader.readline()
self.assertEqual(output, expected)
def test_no_fallback_on_regular_completion(self):
cases = (
("import pri\t\n", "import pri"),
("from pri\t\n", "from pri"),
("from typing import Na\t\n", "from typing import Na"),
)
for code, expected in cases:
with self.subTest(code=code):
events = code_to_events(code)
reader = self.prepare_reader(events, namespace={})
output = reader.readline()
self.assertEqual(output, expected)
def test_get_path_and_prefix(self):
cases = (
('', ('', '')),

View file

@ -0,0 +1,2 @@
When auto-completing an import in the :term:`REPL`, finding no candidates
now issues no suggestion, rather than suggestions from the current namespace.