]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Issue #27573 make the exit message configurable.
authorSteven D'Aprano <steve@pearwood.info>
Tue, 23 Aug 2016 15:42:15 +0000 (01:42 +1000)
committerSteven D'Aprano <steve@pearwood.info>
Tue, 23 Aug 2016 15:42:15 +0000 (01:42 +1000)
Doc/library/code.rst
Lib/code.py
Lib/test/test_code_module.py

index c573087af34089df6b1ccc67358ee02b5630a90b..4cce1fab349327ab0a898802951450efce85accf 100644 (file)
@@ -30,15 +30,19 @@ build applications which provide an interactive interpreter prompt.
    ``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
    instance of :class:`InteractiveConsole` and sets *readfunc* to be used as
    the :meth:`InteractiveConsole.raw_input` method, if provided.  If *local* is
    provided, it is passed to the :class:`InteractiveConsole` constructor for
    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
-   use, if provided.  The console object is discarded after use.
+   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.
+
+   .. versionchanged:: 3.6
+      Added *exitmsg* parameter.
 
 
 .. 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.
 
 
-.. method:: InteractiveConsole.interact(banner=None)
+.. method:: InteractiveConsole.interact(banner=None, exitmsg=None)
 
    Closely emulate the interactive Python console. The optional *banner* argument
    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
    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
       To suppress printing any banner, pass an empty string.
 
    .. versionchanged:: 3.6
-      Now prints a brief message when exiting.
+      Print an exit message when exiting.
 
 
 .. method:: InteractiveConsole.push(line)
index c8b72042e05692183cde7b4b6500f54376fb30ac..23295f4cf59610a39df6057695c8077a7498cc74 100644 (file)
@@ -186,7 +186,7 @@ class InteractiveConsole(InteractiveInterpreter):
         """Reset the input buffer."""
         self.buffer = []
 
-    def interact(self, banner=None):
+    def interact(self, banner=None, exitmsg=None):
         """Closely emulate the interactive Python console.
 
         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
         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:
             sys.ps1
@@ -230,7 +235,10 @@ class InteractiveConsole(InteractiveInterpreter):
                 self.write("\nKeyboardInterrupt\n")
                 self.resetbuffer()
                 more = 0
-        self.write('now exiting %s...\n' % self.__class__.__name__)
+        if exitmsg is None:
+            self.write('now exiting %s...\n' % self.__class__.__name__)
+        elif exitmsg != '':
+            self.write('%s\n' % exitmsg)
 
     def push(self, line):
         """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.
 
     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()
     readfunc -- if not None, replaces InteractiveConsole.raw_input()
     local -- passed to InteractiveInterpreter.__init__()
+    exitmsg -- passed to InteractiveConsole.interact()
 
     """
     console = InteractiveConsole(local)
@@ -290,7 +299,7 @@ def interact(banner=None, readfunc=None, local=None):
             import readline
         except ImportError:
             pass
-    console.interact(banner)
+    console.interact(banner, exitmsg)
 
 
 if __name__ == "__main__":
index 08ba3f370498013626a2670be6f8e91cd5e8ec37..1a8f6990dfb7ec707ad6875840ac2c02cfa48d11 100644 (file)
@@ -80,6 +80,7 @@ class TestInteractiveConsole(unittest.TestCase):
         self.assertEqual(len(self.stderr.method_calls), 2)
 
     def test_exit_msg(self):
+        # default exit message
         self.infunc.side_effect = EOFError('Finished')
         self.console.interact(banner='')
         self.assertEqual(len(self.stderr.method_calls), 2)
@@ -87,6 +88,25 @@ class TestInteractiveConsole(unittest.TestCase):
         expected = 'now exiting InteractiveConsole...\n'
         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):
         self.infunc.side_effect = ["raise ValueError('') from AttributeError",
                                     EOFError('Finished')]