Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 17 additions & 4 deletions Doc/library/code.rst
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ build applications which provide an interactive interpreter prompt.
.. versionchanged:: 3.13
Added *local_exit* parameter.

.. function:: interact(banner=None, readfunc=None, local=None, exitmsg=None, local_exit=False)
.. function:: interact(banner=None, readfunc=None, local=None, exitmsg=None, local_exit=False, *, use_pyrepl=False)

Convenience function to run a read-eval-print loop. This creates a new
instance of :class:`InteractiveConsole` and sets *readfunc* to be used as
Expand All @@ -49,15 +49,19 @@ build applications which provide an interactive interpreter prompt.
use as the default namespace for the interpreter loop. If *local_exit* is provided,
it is passed to the :class:`InteractiveConsole` constructor. The :meth:`~InteractiveConsole.interact`
method of the instance is then run with *banner* and *exitmsg* passed as the
banner and exit message to use, if provided. The console object is discarded
after use.
banner and exit message to use, if provided. The *use_pyrepl* argument is
passed to :meth:`~InteractiveConsole.interact` to control whether to use the
pyrepl-based REPL. The console object is discarded after use.

.. versionchanged:: 3.6
Added *exitmsg* parameter.

.. versionchanged:: 3.13
Added *local_exit* parameter.

.. versionchanged:: next
Added *use_pyrepl* parameter.

.. function:: compile_command(source, filename="<input>", symbol="single")

This function is useful for programs that want to emulate Python's interpreter
Expand Down Expand Up @@ -153,7 +157,7 @@ The :class:`InteractiveConsole` class is a subclass of
interpreter objects as well as the following additions.


.. method:: InteractiveConsole.interact(banner=None, exitmsg=None)
.. method:: InteractiveConsole.interact(banner=None, exitmsg=None, *, use_pyrepl=False)

Closely emulate the interactive Python console. The optional *banner* argument
specify the banner to print before the first interaction; by default it prints a
Expand All @@ -165,12 +169,21 @@ interpreter objects as well as the following additions.
Pass the empty string to suppress the exit message. If *exitmsg* is not given or
``None``, a default message is printed.

The optional *use_pyrepl* argument controls whether to use the pyrepl-based REPL
when available. When ``True``, pyrepl is used. When ``False`` (the default),
the basic readline-based REPL is used. When ``None``, pyrepl is used
automatically if available and the :envvar:`PYTHON_BASIC_REPL` environment
variable is not set.
Comment on lines +174 to +176
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not make None behavior - default, and get rid of the use_pyrepl option? Users can override this by setting PYTHON_BASIC_REPL.

I presume, new option was chosen on ground backward-compatibility, but new REPL is an incompatible change by itself, this is just a continuation.

So, I think it's fine to remove added option, but please wait first feedback from core developers.


.. versionchanged:: 3.4
To suppress printing any banner, pass an empty string.

.. versionchanged:: 3.6
Print an exit message when exiting.

.. versionchanged:: next
Added *use_pyrepl* parameter.


.. method:: InteractiveConsole.push(line)

Expand Down
18 changes: 15 additions & 3 deletions Doc/whatsnew/3.15.rst
Original file line number Diff line number Diff line change
Expand Up @@ -722,6 +722,18 @@ calendar
(Contributed by Pål Grønås Drange in :gh:`140212`.)


code
----

* The :meth:`code.InteractiveConsole.interact` method and the :func:`code.interact`
function now support a *use_pyrepl* parameter to control whether to use the
pyrepl-based REPL. By default, *use_pyrepl* is ``False``, using the basic
readline-based REPL. When set to ``True``, pyrepl is used if available.
When set to ``None``, pyrepl is used automatically if available and the
:envvar:`PYTHON_BASIC_REPL` environment variable is not set.
(Contributed by Long Tan in :gh:`148261`.)


collections
-----------

Expand Down Expand Up @@ -830,9 +842,9 @@ http.server
is colored by default.
This can be controlled with :ref:`environment variables
<using-on-controlling-color>`.
(Contributed by Hugo van Kemenade in :gh:`146292`.)
(Contributed by Hugo van Kemenade in :gh:`146292`.)


Comment on lines +845 to +847
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is unrelated change, please revert.

inspect
-------

Expand Down
30 changes: 27 additions & 3 deletions Lib/code.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@


import builtins
import os
import sys
import traceback
from codeop import CommandCompiler, compile_command
Expand Down Expand Up @@ -201,7 +202,7 @@ def resetbuffer(self):
"""Reset the input buffer."""
self.buffer = []

def interact(self, banner=None, exitmsg=None):
def interact(self, banner=None, exitmsg=None, *, use_pyrepl=False):
"""Closely emulate the interactive Python console.

The optional banner argument specifies the banner to print
Expand All @@ -216,7 +217,29 @@ def interact(self, banner=None, exitmsg=None):
printing an exit message. If exitmsg is not given or None,
a default message is printed.

The use_pyrepl argument controls whether to use the pyrepl-based REPL
when available. When True, pyrepl is used. When False (the default),
the basic readline-based REPL is used. When None, pyrepl is used
automatically if available and the PYTHON_BASIC_REPL environment
variable is not set.

"""
if use_pyrepl is None:
use_pyrepl = not os.getenv('PYTHON_BASIC_REPL')

if use_pyrepl:
try:
from _pyrepl.main import CAN_USE_PYREPL
if CAN_USE_PYREPL:
from _pyrepl.simple_interact import (
run_multiline_interactive_console,
)
run_multiline_interactive_console(self)
return
except ImportError:
pass
# Fall through to basic REPL if pyrepl is unavailable

try:
sys.ps1
delete_ps1_after = False
Expand Down Expand Up @@ -355,7 +378,7 @@ def __call__(self, code=None):
raise SystemExit(code)


def interact(banner=None, readfunc=None, local=None, exitmsg=None, local_exit=False):
def interact(banner=None, readfunc=None, local=None, exitmsg=None, local_exit=False, *, use_pyrepl=False):
"""Closely emulate the interactive Python interpreter.

This is a backwards compatible interface to the InteractiveConsole
Expand All @@ -369,6 +392,7 @@ def interact(banner=None, readfunc=None, local=None, exitmsg=None, local_exit=Fa
local -- passed to InteractiveInterpreter.__init__()
exitmsg -- passed to InteractiveConsole.interact()
local_exit -- passed to InteractiveConsole.__init__()
use_pyrepl -- passed to InteractiveConsole.interact()

"""
console = InteractiveConsole(local, local_exit=local_exit)
Expand All @@ -379,7 +403,7 @@ def interact(banner=None, readfunc=None, local=None, exitmsg=None, local_exit=Fa
import readline # noqa: F401
except ImportError:
pass
console.interact(banner, exitmsg)
console.interact(banner, exitmsg, use_pyrepl=use_pyrepl)


if __name__ == "__main__":
Expand Down
Loading
Loading