Issue #27573 make the exit message configurable.
This commit is contained in:
parent
f4d28d4385
commit
6877ed3560
|
@ -30,15 +30,19 @@ build applications which provide an interactive interpreter prompt.
|
||||||
``sys.ps1`` and ``sys.ps2``, and input buffering.
|
``sys.ps1`` and ``sys.ps2``, and input buffering.
|
||||||
|
|
||||||
|
|
||||||
.. function:: interact(banner=None, readfunc=None, local=None)
|
.. function:: interact(banner=None, readfunc=None, local=None, exitmsg=None)
|
||||||
|
|
||||||
Convenience function to run a read-eval-print loop. This creates a new
|
Convenience function to run a read-eval-print loop. This creates a new
|
||||||
instance of :class:`InteractiveConsole` and sets *readfunc* to be used as
|
instance of :class:`InteractiveConsole` and sets *readfunc* to be used as
|
||||||
the :meth:`InteractiveConsole.raw_input` method, if provided. If *local* is
|
the :meth:`InteractiveConsole.raw_input` method, if provided. If *local* is
|
||||||
provided, it is passed to the :class:`InteractiveConsole` constructor for
|
provided, it is passed to the :class:`InteractiveConsole` constructor for
|
||||||
use as the default namespace for the interpreter loop. The :meth:`interact`
|
use as the default namespace for the interpreter loop. The :meth:`interact`
|
||||||
method of the instance is then run with *banner* passed as the banner to
|
method of the instance is then run with *banner* and *exitmsg* passed as the
|
||||||
use, if provided. The console object is discarded after use.
|
banner and exit message to use, if provided. The console object is discarded
|
||||||
|
after use.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.6
|
||||||
|
Added *exitmsg* parameter.
|
||||||
|
|
||||||
|
|
||||||
.. function:: compile_command(source, filename="<input>", symbol="single")
|
.. function:: compile_command(source, filename="<input>", symbol="single")
|
||||||
|
@ -136,7 +140,7 @@ The :class:`InteractiveConsole` class is a subclass of
|
||||||
interpreter objects as well as the following additions.
|
interpreter objects as well as the following additions.
|
||||||
|
|
||||||
|
|
||||||
.. method:: InteractiveConsole.interact(banner=None)
|
.. method:: InteractiveConsole.interact(banner=None, exitmsg=None)
|
||||||
|
|
||||||
Closely emulate the interactive Python console. The optional *banner* argument
|
Closely emulate the interactive Python console. The optional *banner* argument
|
||||||
specify the banner to print before the first interaction; by default it prints a
|
specify the banner to print before the first interaction; by default it prints a
|
||||||
|
@ -144,11 +148,15 @@ interpreter objects as well as the following additions.
|
||||||
by the class name of the console object in parentheses (so as not to confuse
|
by the class name of the console object in parentheses (so as not to confuse
|
||||||
this with the real interpreter -- since it's so close!).
|
this with the real interpreter -- since it's so close!).
|
||||||
|
|
||||||
|
The optional *exitmsg* argument specifies an exit message printed when exiting.
|
||||||
|
Pass the empty string to suppress the exit message. If *exitmsg* is not given or
|
||||||
|
None, a default message is printed.
|
||||||
|
|
||||||
.. versionchanged:: 3.4
|
.. versionchanged:: 3.4
|
||||||
To suppress printing any banner, pass an empty string.
|
To suppress printing any banner, pass an empty string.
|
||||||
|
|
||||||
.. versionchanged:: 3.6
|
.. versionchanged:: 3.6
|
||||||
Now prints a brief message when exiting.
|
Print an exit message when exiting.
|
||||||
|
|
||||||
|
|
||||||
.. method:: InteractiveConsole.push(line)
|
.. method:: InteractiveConsole.push(line)
|
||||||
|
|
15
Lib/code.py
15
Lib/code.py
|
@ -186,7 +186,7 @@ class InteractiveConsole(InteractiveInterpreter):
|
||||||
"""Reset the input buffer."""
|
"""Reset the input buffer."""
|
||||||
self.buffer = []
|
self.buffer = []
|
||||||
|
|
||||||
def interact(self, banner=None):
|
def interact(self, banner=None, exitmsg=None):
|
||||||
"""Closely emulate the interactive Python console.
|
"""Closely emulate the interactive Python console.
|
||||||
|
|
||||||
The optional banner argument specifies the banner to print
|
The optional banner argument specifies the banner to print
|
||||||
|
@ -196,6 +196,11 @@ class InteractiveConsole(InteractiveInterpreter):
|
||||||
to confuse this with the real interpreter -- since it's so
|
to confuse this with the real interpreter -- since it's so
|
||||||
close!).
|
close!).
|
||||||
|
|
||||||
|
The optional exitmsg argument specifies the exit message
|
||||||
|
printed when exiting. Pass the empty string to suppress
|
||||||
|
printing an exit message. If exitmsg is not given or None,
|
||||||
|
a default message is printed.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
sys.ps1
|
sys.ps1
|
||||||
|
@ -230,7 +235,10 @@ class InteractiveConsole(InteractiveInterpreter):
|
||||||
self.write("\nKeyboardInterrupt\n")
|
self.write("\nKeyboardInterrupt\n")
|
||||||
self.resetbuffer()
|
self.resetbuffer()
|
||||||
more = 0
|
more = 0
|
||||||
|
if exitmsg is None:
|
||||||
self.write('now exiting %s...\n' % self.__class__.__name__)
|
self.write('now exiting %s...\n' % self.__class__.__name__)
|
||||||
|
elif exitmsg != '':
|
||||||
|
self.write('%s\n' % exitmsg)
|
||||||
|
|
||||||
def push(self, line):
|
def push(self, line):
|
||||||
"""Push a line to the interpreter.
|
"""Push a line to the interpreter.
|
||||||
|
@ -268,7 +276,7 @@ class InteractiveConsole(InteractiveInterpreter):
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def interact(banner=None, readfunc=None, local=None):
|
def interact(banner=None, readfunc=None, local=None, exitmsg=None):
|
||||||
"""Closely emulate the interactive Python interpreter.
|
"""Closely emulate the interactive Python interpreter.
|
||||||
|
|
||||||
This is a backwards compatible interface to the InteractiveConsole
|
This is a backwards compatible interface to the InteractiveConsole
|
||||||
|
@ -280,6 +288,7 @@ def interact(banner=None, readfunc=None, local=None):
|
||||||
banner -- passed to InteractiveConsole.interact()
|
banner -- passed to InteractiveConsole.interact()
|
||||||
readfunc -- if not None, replaces InteractiveConsole.raw_input()
|
readfunc -- if not None, replaces InteractiveConsole.raw_input()
|
||||||
local -- passed to InteractiveInterpreter.__init__()
|
local -- passed to InteractiveInterpreter.__init__()
|
||||||
|
exitmsg -- passed to InteractiveConsole.interact()
|
||||||
|
|
||||||
"""
|
"""
|
||||||
console = InteractiveConsole(local)
|
console = InteractiveConsole(local)
|
||||||
|
@ -290,7 +299,7 @@ def interact(banner=None, readfunc=None, local=None):
|
||||||
import readline
|
import readline
|
||||||
except ImportError:
|
except ImportError:
|
||||||
pass
|
pass
|
||||||
console.interact(banner)
|
console.interact(banner, exitmsg)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
|
@ -80,6 +80,7 @@ class TestInteractiveConsole(unittest.TestCase):
|
||||||
self.assertEqual(len(self.stderr.method_calls), 2)
|
self.assertEqual(len(self.stderr.method_calls), 2)
|
||||||
|
|
||||||
def test_exit_msg(self):
|
def test_exit_msg(self):
|
||||||
|
# default exit message
|
||||||
self.infunc.side_effect = EOFError('Finished')
|
self.infunc.side_effect = EOFError('Finished')
|
||||||
self.console.interact(banner='')
|
self.console.interact(banner='')
|
||||||
self.assertEqual(len(self.stderr.method_calls), 2)
|
self.assertEqual(len(self.stderr.method_calls), 2)
|
||||||
|
@ -87,6 +88,25 @@ class TestInteractiveConsole(unittest.TestCase):
|
||||||
expected = 'now exiting InteractiveConsole...\n'
|
expected = 'now exiting InteractiveConsole...\n'
|
||||||
self.assertEqual(err_msg, ['write', (expected,), {}])
|
self.assertEqual(err_msg, ['write', (expected,), {}])
|
||||||
|
|
||||||
|
# no exit message
|
||||||
|
self.stderr.reset_mock()
|
||||||
|
self.infunc.side_effect = EOFError('Finished')
|
||||||
|
self.console.interact(banner='', exitmsg='')
|
||||||
|
self.assertEqual(len(self.stderr.method_calls), 1)
|
||||||
|
|
||||||
|
# custom exit message
|
||||||
|
self.stderr.reset_mock()
|
||||||
|
message = (
|
||||||
|
'bye! \N{GREEK SMALL LETTER ZETA}\N{CYRILLIC SMALL LETTER ZHE}'
|
||||||
|
)
|
||||||
|
self.infunc.side_effect = EOFError('Finished')
|
||||||
|
self.console.interact(banner='', exitmsg=message)
|
||||||
|
self.assertEqual(len(self.stderr.method_calls), 2)
|
||||||
|
err_msg = self.stderr.method_calls[1]
|
||||||
|
expected = message + '\n'
|
||||||
|
self.assertEqual(err_msg, ['write', (expected,), {}])
|
||||||
|
|
||||||
|
|
||||||
def test_cause_tb(self):
|
def test_cause_tb(self):
|
||||||
self.infunc.side_effect = ["raise ValueError('') from AttributeError",
|
self.infunc.side_effect = ["raise ValueError('') from AttributeError",
|
||||||
EOFError('Finished')]
|
EOFError('Finished')]
|
||||||
|
|
Loading…
Reference in New Issue