From 6877ed3560aef64391657f634cbe00d16023201a Mon Sep 17 00:00:00 2001 From: Steven D'Aprano Date: Wed, 24 Aug 2016 01:42:15 +1000 Subject: Issue #27573 make the exit message configurable. --- Doc/library/code.rst | 18 +++++++++++++----- Lib/code.py | 17 +++++++++++++---- Lib/test/test_code_module.py | 20 ++++++++++++++++++++ 3 files changed, 46 insertions(+), 9 deletions(-) diff --git a/Doc/library/code.rst b/Doc/library/code.rst index c573087..4cce1fa 100644 --- a/Doc/library/code.rst +++ b/Doc/library/code.rst @@ -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="", 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) diff --git a/Lib/code.py b/Lib/code.py index c8b7204..23295f4 100644 --- a/Lib/code.py +++ b/Lib/code.py @@ -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__": diff --git a/Lib/test/test_code_module.py b/Lib/test/test_code_module.py index 08ba3f3..1a8f699 100644 --- a/Lib/test/test_code_module.py +++ b/Lib/test/test_code_module.py @@ -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')] -- cgit v0.12 From 228731879a55cb501f8af9935a17a83102323d34 Mon Sep 17 00:00:00 2001 From: Steven D'Aprano Date: Wed, 24 Aug 2016 02:34:25 +1000 Subject: Add documentation for geometric and harmonic means. --- Doc/library/statistics.rst | 58 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/Doc/library/statistics.rst b/Doc/library/statistics.rst index ea3d7da..d62d55a 100644 --- a/Doc/library/statistics.rst +++ b/Doc/library/statistics.rst @@ -39,6 +39,8 @@ or sample. ======================= ============================================= :func:`mean` Arithmetic mean ("average") of data. +:func:`geometric_mean` Geometric mean of data. +:func:`harmonic_mean` Harmonic mean of data. :func:`median` Median (middle value) of data. :func:`median_low` Low median of data. :func:`median_high` High median of data. @@ -111,6 +113,62 @@ However, for reading convenience, most of the examples show sorted sequences. ``mean(data)`` is equivalent to calculating the true population mean μ. +.. function:: geometric_mean(data) + + Return the geometric mean of *data*, a sequence or iterator of + real-valued numbers. + + The geometric mean is the *n*-th root of the product of *n* data points. + It is a type of average, a measure of the central location of the data. + + The geometric mean is appropriate when averaging quantities which + are multiplied together rather than added, for example growth rates. + Suppose an investment grows by 10% in the first year, falls by 5% in + the second, then grows by 12% in the third, what is the average rate + of growth over the three years? + + .. doctest:: + + >>> geometric_mean([1.10, 0.95, 1.12]) + 1.0538483123382172 + + giving an average growth of 5.385%. Using the arithmetic mean will + give approximately 5.667%, which is too high. + + :exc:``StatisticsError`` is raised if *data* is empty, or any + element is less than zero. + + +.. function:: harmonic_mean(data) + + Return the harmonic mean of *data*, a sequence or iterator of + real-valued numbers. + + The harmonic mean, sometimes called the subcontrary mean, is the + reciprocal of the arithmetic :func:``mean`` of the reciprocals of the + data. For example, the harmonic mean of three values *a*, *b* and *c* + will be equivalent to ``3/(1/a + 1/b + 1/c)``. + + The harmonic mean is a type of average, a measure of the central + location of the data. It is often appropriate when averaging quantities + which are rates or ratios, for example speeds. For example: + + Suppose an investor purchases an equal value of shares in each of + three companies, with P/E (price/earning) ratios of 2.5, 3 and 10. + What is the average P/E ratio for the investor's portfolio? + + .. doctest:: + + >>> harmonic_mean([2.5, 3, 10]) # For an equal investment portfolio. + 3.6 + + Using the arithmetic mean would give an average of about 5.167, which + is too high. + + :exc:``StatisticsError`` is raised if *data* is empty, or any element + is less than zero. + + .. function:: median(data) Return the median (middle value) of numeric data, using the common "mean of -- cgit v0.12 From 0a21c729ebaca9e2e929a1e04c7404c5349aa1f4 Mon Sep 17 00:00:00 2001 From: Steven D'Aprano Date: Wed, 24 Aug 2016 02:40:03 +1000 Subject: Re-licence statistics.py under the standard Python licence. --- Lib/statistics.py | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/Lib/statistics.py b/Lib/statistics.py index f4b49b5..17e471b 100644 --- a/Lib/statistics.py +++ b/Lib/statistics.py @@ -1,20 +1,3 @@ -## Module statistics.py -## -## Copyright (c) 2013 Steven D'Aprano . -## -## Licensed under the Apache License, Version 2.0 (the "License"); -## you may not use this file except in compliance with the License. -## You may obtain a copy of the License at -## -## http://www.apache.org/licenses/LICENSE-2.0 -## -## Unless required by applicable law or agreed to in writing, software -## distributed under the License is distributed on an "AS IS" BASIS, -## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -## See the License for the specific language governing permissions and -## limitations under the License. - - """ Basic statistics module. -- cgit v0.12