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

Commite5c7216

Browse files
zvynambv
andauthored
gh-121790: Fix interactive console initialization (#121793)
Co-authored-by: Łukasz Langa <lukasz@langa.pl>
1 parentd23be39 commite5c7216

File tree

6 files changed

+85
-42
lines changed

6 files changed

+85
-42
lines changed

‎Lib/_pyrepl/main.py‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323

2424
definteractive_console(mainmodule=None,quiet=False,pythonstartup=False):
2525
ifnotCAN_USE_PYREPL:
26-
ifnotos.environ.get('PYTHON_BASIC_REPL',None)andFAIL_REASON:
26+
ifnotos.getenv('PYTHON_BASIC_REPL')andFAIL_REASON:
2727
from .traceimporttrace
2828
trace(FAIL_REASON)
2929
print(FAIL_REASON,file=sys.stderr)
@@ -51,5 +51,7 @@ def interactive_console(mainmodule=None, quiet=False, pythonstartup=False):
5151
ifnothasattr(sys,"ps2"):
5252
sys.ps2="... "
5353

54+
from .consoleimportInteractiveColoredConsole
5455
from .simple_interactimportrun_multiline_interactive_console
55-
run_multiline_interactive_console(namespace)
56+
console=InteractiveColoredConsole(namespace,filename="<stdin>")
57+
run_multiline_interactive_console(console)

‎Lib/_pyrepl/readline.py‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858
TYPE_CHECKING=False
5959

6060
ifTYPE_CHECKING:
61-
fromtypingimportAny
61+
fromtypingimportAny,Mapping
6262

6363

6464
MoreLinesCallable=Callable[[str],bool]
@@ -559,7 +559,7 @@ def stub(*args: object, **kwds: object) -> None:
559559
# ____________________________________________________________
560560

561561

562-
def_setup(namespace:dict[str,Any])->None:
562+
def_setup(namespace:Mapping[str,Any])->None:
563563
globalraw_input
564564
ifraw_inputisnotNone:
565565
return# don't run _setup twice
@@ -575,7 +575,9 @@ def _setup(namespace: dict[str, Any]) -> None:
575575
_wrapper.f_in=f_in
576576
_wrapper.f_out=f_out
577577

578-
# set up namespace in rlcompleter
578+
# set up namespace in rlcompleter, which requires it to be a bona fide dict
579+
ifnotisinstance(namespace,dict):
580+
namespace=dict(namespace)
579581
_wrapper.config.readline_completer=RLCompleter(namespace).complete
580582

581583
# this is not really what readline.c does. Better than nothing I guess

‎Lib/_pyrepl/simple_interact.py‎

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,9 @@
2727

2828
import_sitebuiltins
2929
importlinecache
30-
importbuiltins
3130
importsys
3231
importcode
33-
fromtypesimportModuleType
3432

35-
from .consoleimportInteractiveColoredConsole
3633
from .readlineimport_get_reader,multiline_input
3734

3835
TYPE_CHECKING=False
@@ -82,17 +79,12 @@ def _clear_screen():
8279

8380

8481
defrun_multiline_interactive_console(
85-
namespace:dict[str,Any],
82+
console:code.InteractiveConsole,
83+
*,
8684
future_flags:int=0,
87-
console:code.InteractiveConsole|None=None,
8885
)->None:
8986
from .readlineimport_setup
90-
_setup(namespace)
91-
92-
ifconsoleisNone:
93-
console=InteractiveColoredConsole(
94-
namespace,filename="<stdin>"
95-
)
87+
_setup(console.locals)
9688
iffuture_flags:
9789
console.compile.compiler.flags|=future_flags
9890

‎Lib/asyncio/__main__.py‎

Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -97,30 +97,16 @@ def run(self):
9797
exec(startup_code,console.locals)
9898

9999
ps1=getattr(sys,"ps1",">>> ")
100-
ifcan_colorize():
100+
ifcan_colorize()andCAN_USE_PYREPL:
101101
ps1=f"{ANSIColors.BOLD_MAGENTA}{ps1}{ANSIColors.RESET}"
102102
console.write(f"{ps1}import asyncio\n")
103103

104-
try:
105-
importerrno
106-
ifos.getenv("PYTHON_BASIC_REPL"):
107-
raiseRuntimeError("user environment requested basic REPL")
108-
ifnotos.isatty(sys.stdin.fileno()):
109-
return_code=errno.ENOTTY
110-
raiseOSError(return_code,"tty required","stdin")
111-
112-
# This import will fail on operating systems with no termios.
104+
ifCAN_USE_PYREPL:
113105
from_pyrepl.simple_interactimport (
114-
check,
115106
run_multiline_interactive_console,
116107
)
117-
iferr:=check():
118-
raiseRuntimeError(err)
119-
exceptExceptionase:
120-
console.interact(banner="",exitmsg="")
121-
else:
122108
try:
123-
run_multiline_interactive_console(console=console)
109+
run_multiline_interactive_console(console)
124110
exceptSystemExit:
125111
# expected via the `exit` and `quit` commands
126112
pass
@@ -129,6 +115,8 @@ def run(self):
129115
console.showtraceback()
130116
console.write("Internal error, ")
131117
return_code=1
118+
else:
119+
console.interact(banner="",exitmsg="")
132120
finally:
133121
warnings.filterwarnings(
134122
'ignore',
@@ -139,7 +127,10 @@ def run(self):
139127

140128

141129
if__name__=='__main__':
142-
CAN_USE_PYREPL=True
130+
ifos.getenv('PYTHON_BASIC_REPL'):
131+
CAN_USE_PYREPL=False
132+
else:
133+
from_pyrepl.mainimportCAN_USE_PYREPL
143134

144135
return_code=0
145136
loop=asyncio.new_event_loop()

‎Lib/site.py‎

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -517,10 +517,7 @@ def register_readline():
517517
pass
518518

519519
ifreadline.get_current_history_length()==0:
520-
try:
521-
from_pyrepl.mainimportCAN_USE_PYREPL
522-
exceptImportError:
523-
CAN_USE_PYREPL=False
520+
from_pyrepl.mainimportCAN_USE_PYREPL
524521
# If no history was loaded, default to .python_history,
525522
# or PYTHON_HISTORY.
526523
# The guard is necessary to avoid doubling history size at

‎Lib/test/test_repl.py‎

Lines changed: 63 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,27 @@
11
"""Test the interactive interpreter."""
22

33
importos
4+
importselect
45
importsubprocess
56
importsys
67
importunittest
78
fromtextwrapimportdedent
89
fromtestimportsupport
9-
fromtest.supportimportcpython_only,has_subprocess_support,SuppressCrashReport
10-
fromtest.support.script_helperimportassert_python_failure,kill_python,assert_python_ok
10+
fromtest.supportimport (
11+
cpython_only,
12+
has_subprocess_support,
13+
os_helper,
14+
SuppressCrashReport,
15+
SHORT_TIMEOUT,
16+
)
17+
fromtest.support.script_helperimportkill_python
1118
fromtest.support.import_helperimportimport_module
1219

20+
try:
21+
importpty
22+
exceptImportError:
23+
pty=None
24+
1325

1426
ifnothas_subprocess_support:
1527
raiseunittest.SkipTest("test module requires subprocess")
@@ -195,9 +207,56 @@ def bar(x):
195207
expected="(30, None, [\'def foo(x):\\n\',\' return x + 1\\n\',\'\\n\'],\'<stdin>\')"
196208
self.assertIn(expected,output,expected)
197209

198-
deftest_asyncio_repl_no_tty_fails(self):
199-
assertassert_python_failure("-m","asyncio")
210+
deftest_asyncio_repl_reaches_python_startup_script(self):
211+
withos_helper.temp_dir()astmpdir:
212+
script=os.path.join(tmpdir,"pythonstartup.py")
213+
withopen(script,"w")asf:
214+
f.write("print('pythonstartup done!')"+os.linesep)
215+
f.write("exit(0)"+os.linesep)
216+
217+
env=os.environ.copy()
218+
env["PYTHONSTARTUP"]=script
219+
subprocess.check_call(
220+
[sys.executable,"-m","asyncio"],
221+
stdout=subprocess.PIPE,
222+
stderr=subprocess.PIPE,
223+
env=env,
224+
timeout=SHORT_TIMEOUT,
225+
)
226+
227+
@unittest.skipUnless(pty,"requires pty")
228+
deftest_asyncio_repl_is_ok(self):
229+
m,s=pty.openpty()
230+
cmd= [sys.executable,"-m","asyncio"]
231+
proc=subprocess.Popen(
232+
cmd,
233+
stdin=s,
234+
stdout=s,
235+
stderr=s,
236+
text=True,
237+
close_fds=True,
238+
env=os.environ,
239+
)
240+
os.close(s)
241+
os.write(m,b"await asyncio.sleep(0)\n")
242+
os.write(m,b"exit()\n")
243+
output= []
244+
whileselect.select([m], [], [],SHORT_TIMEOUT)[0]:
245+
try:
246+
data=os.read(m,1024).decode("utf-8")
247+
ifnotdata:
248+
break
249+
exceptOSError:
250+
break
251+
output.append(data)
252+
os.close(m)
253+
try:
254+
exit_code=proc.wait(timeout=SHORT_TIMEOUT)
255+
exceptsubprocess.TimeoutExpired:
256+
proc.kill()
257+
exit_code=proc.wait()
200258

259+
self.assertEqual(exit_code,0)
201260

202261
classTestInteractiveModeSyntaxErrors(unittest.TestCase):
203262

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp