aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Lib/_pyrepl
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/_pyrepl')
-rw-r--r--Lib/_pyrepl/_module_completer.py8
-rw-r--r--Lib/_pyrepl/base_eventqueue.py6
-rw-r--r--Lib/_pyrepl/commands.py8
-rw-r--r--Lib/_pyrepl/main.py11
-rw-r--r--Lib/_pyrepl/readline.py6
-rw-r--r--Lib/_pyrepl/windows_console.py26
6 files changed, 38 insertions, 27 deletions
diff --git a/Lib/_pyrepl/_module_completer.py b/Lib/_pyrepl/_module_completer.py
index 9aafb55090e..1e9462a4215 100644
--- a/Lib/_pyrepl/_module_completer.py
+++ b/Lib/_pyrepl/_module_completer.py
@@ -17,8 +17,8 @@ if TYPE_CHECKING:
def make_default_module_completer() -> ModuleCompleter:
- # Inside pyrepl, __package__ is set to '_pyrepl'
- return ModuleCompleter(namespace={'__package__': '_pyrepl'})
+ # Inside pyrepl, __package__ is set to None by default
+ return ModuleCompleter(namespace={'__package__': None})
class ModuleCompleter:
@@ -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:
diff --git a/Lib/_pyrepl/base_eventqueue.py b/Lib/_pyrepl/base_eventqueue.py
index 842599bd187..0589a0f437e 100644
--- a/Lib/_pyrepl/base_eventqueue.py
+++ b/Lib/_pyrepl/base_eventqueue.py
@@ -87,7 +87,7 @@ class BaseEventQueue:
if isinstance(k, dict):
self.keymap = k
else:
- self.insert(Event('key', k, self.flush_buf()))
+ self.insert(Event('key', k, bytes(self.flush_buf())))
self.keymap = self.compiled_keymap
elif self.buf and self.buf[0] == 27: # escape
@@ -96,7 +96,7 @@ class BaseEventQueue:
# the docstring in keymap.py
trace('unrecognized escape sequence, propagating...')
self.keymap = self.compiled_keymap
- self.insert(Event('key', '\033', bytearray(b'\033')))
+ self.insert(Event('key', '\033', b'\033'))
for _c in self.flush_buf()[1:]:
self.push(_c)
@@ -106,5 +106,5 @@ class BaseEventQueue:
except UnicodeError:
return
else:
- self.insert(Event('key', decoded, self.flush_buf()))
+ self.insert(Event('key', decoded, bytes(self.flush_buf())))
self.keymap = self.compiled_keymap
diff --git a/Lib/_pyrepl/commands.py b/Lib/_pyrepl/commands.py
index 2354fbb2ec2..50c824995d8 100644
--- a/Lib/_pyrepl/commands.py
+++ b/Lib/_pyrepl/commands.py
@@ -370,6 +370,13 @@ class self_insert(EditCommand):
r = self.reader
text = self.event * r.get_arg()
r.insert(text)
+ if r.paste_mode:
+ data = ""
+ ev = r.console.getpending()
+ data += ev.data
+ if data:
+ r.insert(data)
+ r.last_refresh_cache.invalidated = True
class insert_nl(EditCommand):
@@ -484,7 +491,6 @@ class perform_bracketed_paste(Command):
data = ""
start = time.time()
while done not in data:
- self.reader.console.wait(100)
ev = self.reader.console.getpending()
data += ev.data
trace(
diff --git a/Lib/_pyrepl/main.py b/Lib/_pyrepl/main.py
index a6f824dcc4a..447eb1e551e 100644
--- a/Lib/_pyrepl/main.py
+++ b/Lib/_pyrepl/main.py
@@ -1,6 +1,7 @@
import errno
import os
import sys
+import types
CAN_USE_PYREPL: bool
@@ -29,12 +30,10 @@ def interactive_console(mainmodule=None, quiet=False, pythonstartup=False):
print(FAIL_REASON, file=sys.stderr)
return sys._baserepl()
- if mainmodule:
- namespace = mainmodule.__dict__
- else:
- import __main__
- namespace = __main__.__dict__
- namespace.pop("__pyrepl_interactive_console", None)
+ if not mainmodule:
+ mainmodule = types.ModuleType("__main__")
+
+ namespace = mainmodule.__dict__
# sys._baserepl() above does this internally, we do it here
startup_path = os.getenv("PYTHONSTARTUP")
diff --git a/Lib/_pyrepl/readline.py b/Lib/_pyrepl/readline.py
index 560a9db1921..9560ae779ab 100644
--- a/Lib/_pyrepl/readline.py
+++ b/Lib/_pyrepl/readline.py
@@ -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)
@@ -606,6 +607,7 @@ def _setup(namespace: Mapping[str, Any]) -> None:
# set up namespace in rlcompleter, which requires it to be a bona fide dict
if not isinstance(namespace, dict):
namespace = dict(namespace)
+ _wrapper.config.module_completer = ModuleCompleter(namespace)
_wrapper.config.readline_completer = RLCompleter(namespace).complete
# this is not really what readline.c does. Better than nothing I guess
diff --git a/Lib/_pyrepl/windows_console.py b/Lib/_pyrepl/windows_console.py
index 95749198b3b..c56dcd6d7dd 100644
--- a/Lib/_pyrepl/windows_console.py
+++ b/Lib/_pyrepl/windows_console.py
@@ -419,10 +419,7 @@ class WindowsConsole(Console):
return info.srWindow.Bottom # type: ignore[no-any-return]
- def _read_input(self, block: bool = True) -> INPUT_RECORD | None:
- if not block and not self.wait(timeout=0):
- return None
-
+ def _read_input(self) -> INPUT_RECORD | None:
rec = INPUT_RECORD()
read = DWORD()
if not ReadConsoleInput(InHandle, rec, 1, read):
@@ -431,14 +428,10 @@ class WindowsConsole(Console):
return rec
def _read_input_bulk(
- self, block: bool, n: int
+ self, n: int
) -> tuple[ctypes.Array[INPUT_RECORD], int]:
rec = (n * INPUT_RECORD)()
read = DWORD()
-
- if not block and not self.wait(timeout=0):
- return rec, 0
-
if not ReadConsoleInput(InHandle, rec, n, read):
raise WinError(GetLastError())
@@ -449,8 +442,11 @@ class WindowsConsole(Console):
and there is no event pending, otherwise waits for the
completion of an event."""
+ if not block and not self.wait(timeout=0):
+ return None
+
while self.event_queue.empty():
- rec = self._read_input(block)
+ rec = self._read_input()
if rec is None:
return None
@@ -551,12 +547,20 @@ class WindowsConsole(Console):
if e2:
e.data += e2.data
- recs, rec_count = self._read_input_bulk(False, 1024)
+ recs, rec_count = self._read_input_bulk(1024)
for i in range(rec_count):
rec = recs[i]
+ # In case of a legacy console, we do not only receive a keydown
+ # event, but also a keyup event - and for uppercase letters
+ # an additional SHIFT_PRESSED event.
if rec and rec.EventType == KEY_EVENT:
key_event = rec.Event.KeyEvent
+ if not key_event.bKeyDown:
+ continue
ch = key_event.uChar.UnicodeChar
+ if ch == "\x00":
+ # ignore SHIFT_PRESSED and special keys
+ continue
if ch == "\r":
ch += "\n"
e.data += ch