Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commiteea45ea

Browse files
ambvpablogsalmdboom
authored
[3.13]gh-119842: Honor PyOS_InputHook in the new REPL (GH-119843) (GH-120066)
(cherry picked from commitd909519)Signed-off-by: Pablo Galindo <pablogsal@gmail.com>Co-authored-by: Pablo Galindo Salgado <Pablogsal@gmail.com>Co-authored-by: Michael Droettboom <mdboom@gmail.com>
1 parent93b95e9 commiteea45ea

File tree

8 files changed

+144
-11
lines changed

8 files changed

+144
-11
lines changed

‎Lib/_pyrepl/console.py‎

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333

3434
ifTYPE_CHECKING:
3535
fromtypingimportIO
36+
fromtypingimportCallable
3637

3738

3839
@dataclass
@@ -134,8 +135,15 @@ def getpending(self) -> Event:
134135
...
135136

136137
@abstractmethod
137-
defwait(self)->None:
138-
"""Wait for an event."""
138+
defwait(self,timeout:float|None)->bool:
139+
"""Wait for an event. The return value is True if an event is
140+
available, False if the timeout has been reached. If timeout is
141+
None, wait forever. The timeout is in milliseconds."""
142+
...
143+
144+
@property
145+
definput_hook(self)->Callable[[],int]|None:
146+
"""Returns the current input hook."""
139147
...
140148

141149
@abstractmethod

‎Lib/_pyrepl/reader.py‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -650,7 +650,15 @@ def handle1(self, block: bool = True) -> bool:
650650
self.dirty=True
651651

652652
whileTrue:
653-
event=self.console.get_event(block)
653+
input_hook=self.console.input_hook
654+
ifinput_hook:
655+
input_hook()
656+
# We use the same timeout as in readline.c: 100ms
657+
whilenotself.console.wait(100):
658+
input_hook()
659+
event=self.console.get_event(block=False)
660+
else:
661+
event=self.console.get_event(block)
654662
ifnotevent:# can only happen if we're not blocking
655663
returnFalse
656664

‎Lib/_pyrepl/unix_console.py‎

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -118,9 +118,12 @@ def __init__(self):
118118

119119
defregister(self,fd,flag):
120120
self.fd=fd
121-
122-
defpoll(self):# note: a 'timeout' argument would be *milliseconds*
123-
r,w,e=select.select([self.fd], [], [])
121+
# note: The 'timeout' argument is received as *milliseconds*
122+
defpoll(self,timeout:float|None=None)->list[int]:
123+
iftimeoutisNone:
124+
r,w,e=select.select([self.fd], [], [])
125+
else:
126+
r,w,e=select.select([self.fd], [], [],timeout/1000)
124127
returnr
125128

126129
poll=MinimalPoll# type: ignore[assignment]
@@ -385,11 +388,11 @@ def get_event(self, block: bool = True) -> Event | None:
385388
break
386389
returnself.event_queue.get()
387390

388-
defwait(self):
391+
defwait(self,timeout:float|None=None)->bool:
389392
"""
390393
Wait for events on the console.
391394
"""
392-
self.pollob.poll()
395+
returnbool(self.pollob.poll(timeout))
393396

394397
defset_cursor_vis(self,visible):
395398
"""
@@ -527,6 +530,15 @@ def clear(self):
527530
self.__posxy=0,0
528531
self.screen= []
529532

533+
@property
534+
definput_hook(self):
535+
try:
536+
importposix
537+
exceptImportError:
538+
returnNone
539+
ifposix._is_inputhook_installed():
540+
returnposix._inputhook
541+
530542
def__enable_bracketed_paste(self)->None:
531543
os.write(self.output_fd,b"\x1b[?2004h")
532544

‎Lib/_pyrepl/windows_console.py‎

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
frommultiprocessingimportValue
2424
importos
2525
importsys
26+
importtime
27+
importmsvcrt
2628

2729
fromabcimportABC,abstractmethod
2830
fromcollectionsimportdeque
@@ -202,6 +204,15 @@ def refresh(self, screen: list[str], c_xy: tuple[int, int]) -> None:
202204
self.screen=screen
203205
self.move_cursor(cx,cy)
204206

207+
@property
208+
definput_hook(self):
209+
try:
210+
importnt
211+
exceptImportError:
212+
returnNone
213+
ifnt._is_inputhook_installed():
214+
returnnt._inputhook
215+
205216
def__write_changed_line(
206217
self,y:int,oldline:str,newline:str,px_coord:int
207218
)->None:
@@ -460,9 +471,16 @@ def getpending(self) -> Event:
460471
processed."""
461472
returnEvent("key","",b"")
462473

463-
defwait(self)->None:
474+
defwait(self,timeout:float|None)->bool:
464475
"""Wait for an event."""
465-
raiseNotImplementedError("No wait support")
476+
# Poor man's Windows select loop
477+
start_time=time.time()
478+
whileTrue:
479+
ifmsvcrt.kbhit():# type: ignore[attr-defined]
480+
returnTrue
481+
iftimeoutandtime.time()-start_time>timeout:
482+
returnFalse
483+
time.sleep(0.01)
466484

467485
defrepaint(self)->None:
468486
raiseNotImplementedError("No repaint support")

‎Lib/test/test_pyrepl/test_reader.py‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22
importfunctools
33
importrlcompleter
44
fromunittestimportTestCase
5+
fromunittest.mockimportMagicMock,patch
56

67
from .supportimporthandle_all_events,handle_events_narrow_console,code_to_events,prepare_reader
8+
fromtest.supportimportimport_helper
79
from_pyrepl.consoleimportEvent
810
from_pyrepl.readerimportReader
911

@@ -179,6 +181,21 @@ def test_newline_within_block_trailing_whitespace(self):
179181
self.assert_screen_equals(reader,expected)
180182
self.assertTrue(reader.finished)
181183

184+
deftest_input_hook_is_called_if_set(self):
185+
input_hook=MagicMock()
186+
def_prepare_console(events):
187+
console=MagicMock()
188+
console.get_event.side_effect=events
189+
console.height=100
190+
console.width=80
191+
console.input_hook=input_hook
192+
returnconsole
193+
194+
events=code_to_events("a")
195+
reader,_=handle_all_events(events,prepare_console=_prepare_console)
196+
197+
self.assertEqual(len(input_hook.mock_calls),4)
198+
182199
deftest_keyboard_interrupt_clears_screen(self):
183200
namespace= {"itertools":itertools}
184201
code="import itertools\nitertools."
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Honor:c:func:`PyOS_InputHook` in the new REPL. Patch by Pablo Galindo

‎Modules/clinic/posixmodule.c.h‎

Lines changed: 37 additions & 1 deletion
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

‎Modules/posixmodule.c‎

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16784,6 +16784,37 @@ os__supports_virtual_terminal_impl(PyObject *module)
1678416784
}
1678516785
#endif
1678616786

16787+
/*[clinic input]
16788+
os._inputhook
16789+
16790+
Calls PyOS_CallInputHook droppong the GIL first
16791+
[clinic start generated code]*/
16792+
16793+
staticPyObject*
16794+
os__inputhook_impl(PyObject*module)
16795+
/*[clinic end generated code: output=525aca4ef3c6149f input=fc531701930d064f]*/
16796+
{
16797+
intresult=0;
16798+
if (PyOS_InputHook) {
16799+
Py_BEGIN_ALLOW_THREADS;
16800+
result=PyOS_InputHook();
16801+
Py_END_ALLOW_THREADS;
16802+
}
16803+
returnPyLong_FromLong(result);
16804+
}
16805+
16806+
/*[clinic input]
16807+
os._is_inputhook_installed
16808+
16809+
Checks if PyOS_CallInputHook is set
16810+
[clinic start generated code]*/
16811+
16812+
staticPyObject*
16813+
os__is_inputhook_installed_impl(PyObject*module)
16814+
/*[clinic end generated code: output=3b3eab4f672c689a input=ff177c9938dd76d8]*/
16815+
{
16816+
returnPyBool_FromLong(PyOS_InputHook!=NULL);
16817+
}
1678716818

1678816819
staticPyMethodDefposix_methods[]= {
1678916820

@@ -16997,6 +17028,8 @@ static PyMethodDef posix_methods[] = {
1699717028
OS__PATH_LEXISTS_METHODDEF
1699817029

1699917030
OS__SUPPORTS_VIRTUAL_TERMINAL_METHODDEF
17031+
OS__INPUTHOOK_METHODDEF
17032+
OS__IS_INPUTHOOK_INSTALLED_METHODDEF
1700017033
{NULL,NULL}/* Sentinel */
1700117034
};
1700217035

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp