diff options
author | Christian Heimes <christian@cheimes.de> | 2012-09-30 13:51:39 (GMT) |
---|---|---|
committer | Christian Heimes <christian@cheimes.de> | 2012-09-30 13:51:39 (GMT) |
commit | 5c9a5895d4357ad33c42f6d996142ae3fb591ad9 (patch) | |
tree | 78a81a898fdb26a9c5119b437f3bf995b8afd15c | |
parent | 72c9946718004a13c895cc54a2b82e9a50fd4ef3 (diff) | |
parent | 2cac28b37ef1dfdfc90481cad780c1555c713b04 (diff) | |
download | cpython-5c9a5895d4357ad33c42f6d996142ae3fb591ad9.zip cpython-5c9a5895d4357ad33c42f6d996142ae3fb591ad9.tar.gz cpython-5c9a5895d4357ad33c42f6d996142ae3fb591ad9.tar.bz2 |
merge
-rw-r--r-- | Doc/library/subprocess.rst | 8 | ||||
-rw-r--r-- | Doc/tools/sphinxext/indexsidebar.html | 2 | ||||
-rw-r--r-- | Doc/tools/sphinxext/layout.html | 17 | ||||
-rw-r--r-- | Doc/tools/sphinxext/pyspecific.py | 40 | ||||
-rw-r--r-- | Doc/using/windows.rst | 2 | ||||
-rw-r--r-- | Doc/whatsnew/3.3.rst | 55 | ||||
-rw-r--r-- | Doc/whatsnew/index.rst | 8 | ||||
-rw-r--r-- | Doc/whatsnew/news.rst | 14 | ||||
-rw-r--r-- | Lib/bz2.py | 81 | ||||
-rw-r--r-- | Lib/test/test_subprocess.py | 123 | ||||
-rw-r--r-- | Misc/NEWS | 111 | ||||
-rw-r--r-- | Modules/_decimal/tests/bench.py | 9 |
12 files changed, 404 insertions, 66 deletions
diff --git a/Doc/library/subprocess.rst b/Doc/library/subprocess.rst index 042f8f4..3ecdf4b 100644 --- a/Doc/library/subprocess.rst +++ b/Doc/library/subprocess.rst @@ -484,10 +484,10 @@ functions. .. versionadded:: 3.2 The *pass_fds* parameter was added. - If *cwd* is not ``None``, the child's current directory will be changed to *cwd* - before it is executed. Note that this directory is not considered when - searching the executable, so you can't specify the program's path relative to - *cwd*. + If *cwd* is not ``None``, the function changes the working directory to + *cwd* before executing the child. In particular, the function looks for + *executable* (or for the first item in *args*) relative to *cwd* if the + executable path is a relative path. If *restore_signals* is True (the default) all signals that Python has set to SIG_IGN are restored to SIG_DFL in the child process before the exec. diff --git a/Doc/tools/sphinxext/indexsidebar.html b/Doc/tools/sphinxext/indexsidebar.html index 2018011..a0ec32f 100644 --- a/Doc/tools/sphinxext/indexsidebar.html +++ b/Doc/tools/sphinxext/indexsidebar.html @@ -3,7 +3,7 @@ <h3>Docs for other versions</h3> <ul> <li><a href="http://docs.python.org/2.7/">Python 2.7 (stable)</a></li> - <li><a href="http://docs.python.org/3.2/">Python 3.2 (stable)</a></li> + <li><a href="http://docs.python.org/3.4/">Python 3.4 (in development)</a></li> <li><a href="http://www.python.org/doc/versions/">Old versions</a></li> </ul> diff --git a/Doc/tools/sphinxext/layout.html b/Doc/tools/sphinxext/layout.html index db4a386..df728aa 100644 --- a/Doc/tools/sphinxext/layout.html +++ b/Doc/tools/sphinxext/layout.html @@ -8,6 +8,23 @@ {% block extrahead %} <link rel="shortcut icon" type="image/png" href="{{ pathto('_static/py.png', 1) }}" /> {% if not embedded %}<script type="text/javascript" src="{{ pathto('_static/copybutton.js', 1) }}"></script>{% endif %} + {% if pagename == 'whatsnew/news' %} + <script type="text/javascript"> + function dofilter() { + var el = document.getElementById('searchbox'); + var string = el.value.toLowerCase(); + var litags = document.getElementsByTagName('li') + for (var idx = 0; idx < litags.length; idx++) { + var li = litags[idx]; + if (li.innerHTML.toLowerCase().indexOf(string) >= 0) { + li.style.display = ''; + } else { + li.style.display = 'none'; + } + } + } + </script> + {% endif %} {{ super() }} {% endblock %} {% block footer %} diff --git a/Doc/tools/sphinxext/pyspecific.py b/Doc/tools/sphinxext/pyspecific.py index 9fa2d2a..9304461 100644 --- a/Doc/tools/sphinxext/pyspecific.py +++ b/Doc/tools/sphinxext/pyspecific.py @@ -145,6 +145,45 @@ class DeprecatedRemoved(Directive): return ret +# Support for including Misc/NEWS + +import re +import codecs +from docutils.statemachine import string2lines +from sphinx.util.nodes import nested_parse_with_titles + +issue_re = re.compile('Issue #([0-9]+)') + +class MiscNews(Directive): + has_content = False + required_arguments = 1 + optional_arguments = 0 + final_argument_whitespace = False + option_spec = {} + + def run(self): + fname = self.arguments[0] + source = self.state_machine.input_lines.source( + self.lineno - self.state_machine.input_offset - 1) + source_dir = path.dirname(path.abspath(source)) + try: + fp = codecs.open(path.join(source_dir, fname), encoding='utf-8') + try: + content = fp.read() + finally: + fp.close() + except Exception: + text = 'The NEWS file is not available.' + node = nodes.strong(text, text) + return [node] + content = issue_re.sub(r'`Issue #\1 <http://bugs.python.org/\1>`__', + content) + # remove first 3 lines as they are the main heading + lines = content.splitlines()[3:] + self.state_machine.insert_input(lines, fname) + return [] + + # Support for building "topic help" for pydoc pydoc_topic_labels = [ @@ -276,3 +315,4 @@ def setup(app): app.add_description_unit('2to3fixer', '2to3fixer', '%s (2to3 fixer)') app.add_directive_to_domain('py', 'decorator', PyDecoratorFunction) app.add_directive_to_domain('py', 'decoratormethod', PyDecoratorMethod) + app.add_directive('miscnews', MiscNews) diff --git a/Doc/using/windows.rst b/Doc/using/windows.rst index 51152df..5f01b77 100644 --- a/Doc/using/windows.rst +++ b/Doc/using/windows.rst @@ -132,6 +132,8 @@ Consult :command:`set /?` for details on this behaviour. Setting Environment variables, Louis J. Farrugia +.. _windows-path-mod: + Finding the Python executable ----------------------------- diff --git a/Doc/whatsnew/3.3.rst b/Doc/whatsnew/3.3.rst index 1943a06..8d434db 100644 --- a/Doc/whatsnew/3.3.rst +++ b/Doc/whatsnew/3.3.rst @@ -51,7 +51,7 @@ see the :source:`Misc/NEWS` file. .. seealso:: - :pep:`398` - Python 3.2 Release Schedule + :pep:`398` - Python 3.3 Release Schedule Summary -- Release highlights @@ -289,6 +289,43 @@ details). and Martin von Löwis. +.. _pep-397: + +PEP 397: Python Launcher for Windows +==================================== + +The Python 3.3 Windows installer now includes a ``py`` launcher application +that can be used to launch Python applications in a version independent +fashion. + +This launcher is invoked implicitly when double-clicking ``*.py`` files. +If only a single Python version is installed on the system, that version +will be used to run the file. If multiple versions are installed, the most +recent version is used by default, but this can be overridden by including +a Unix-style "shebang line" in the Python script. + +The launcher can also be used explicitly from the command line as the ``py`` +application. Running ``py`` follows the same version selection rules as +implicitly launching scripts, but a more specific version can be selected +by passing appropriate arguments (such as ``-3`` to request Python 3 when +Python 2 is also installed, or ``-2.6`` to specifclly request an earlier +Python version when a more recent version is installed). + +In addition to the launcher, the Windows installer now includes an +option to add the newly installed Python to the system PATH (contributed +by Brian Curtain in :issue:`3561`). + +.. seealso:: + + :pep:`397` - Python Launcher for Windows + PEP written by Mark Hammond and Martin v. Löwis; implementation by + Vinay Sajip. + + Launcher documentation: :ref:`launcher` + + Installer PATH modification: :ref:`windows-path-mod` + + .. _pep-3151: PEP 3151: Reworking the OS and IO exception hierarchy @@ -2102,6 +2139,22 @@ Porting Python code special case the standard import hooks so they are still supported even though they do not provide the non-standard ``iter_modules()`` method. +* A longstanding RFC-compliance bug (:issue:`1079`) in the parsing done by + :func:`email.header.decode_header` has been fixed. Code that uses the + standard idiom to convert encoded headers into unicode + (``str(make_header(decode_header(h))``) will see no change, but code that + looks at the individual tuples returned by decode_header will see that + whitespace that precedes or follows ``ASCII`` sections is now included in the + ``ASCII`` section. Code that builds headers using ``make_header`` should + also continue to work without change, since ``make_header`` continues to add + whitespace between ``ASCII`` and non-``ASCII`` sections if it is not already + present in the input strings. + +* :func:`email.utils.formataddr` now does the correct content transfer + encoding when passed non-``ASCII`` display names. Any code that depended on + the previous buggy behavior that preserved the non-``ASCII`` unicode in the + formatted output string will need to be changed. + Porting C code -------------- diff --git a/Doc/whatsnew/index.rst b/Doc/whatsnew/index.rst index c60818a..a06849b 100644 --- a/Doc/whatsnew/index.rst +++ b/Doc/whatsnew/index.rst @@ -23,3 +23,11 @@ anyone wishing to stay up-to-date after a new release. 2.2.rst 2.1.rst 2.0.rst + +The "Python News" is a HTML version of the file :source:`Misc/NEWS` which +contains *all* nontrivial changes to Python. + +.. toctree:: + :maxdepth: 1 + + news.rst diff --git a/Doc/whatsnew/news.rst b/Doc/whatsnew/news.rst new file mode 100644 index 0000000..2f81ed3 --- /dev/null +++ b/Doc/whatsnew/news.rst @@ -0,0 +1,14 @@ ++++++++++++ +Python News ++++++++++++ + +.. raw:: html + + <p> + Filter entries by content: + <input type="text" value="" id="searchbox" style="width: 50%" onchange="dofilter()"> + <input type="submit" value="Filter" onclick="dofilter()"> + </p> + +.. miscnews:: ../../Misc/NEWS + @@ -79,7 +79,8 @@ class BZ2File(io.BufferedIOBase): mode = "rb" mode_code = _MODE_READ self._decompressor = BZ2Decompressor() - self._buffer = None + self._buffer = b"" + self._buffer_offset = 0 elif mode in ("w", "wb"): mode = "wb" mode_code = _MODE_WRITE @@ -124,7 +125,8 @@ class BZ2File(io.BufferedIOBase): self._fp = None self._closefp = False self._mode = _MODE_CLOSED - self._buffer = None + self._buffer = b"" + self._buffer_offset = 0 @property def closed(self): @@ -174,16 +176,13 @@ class BZ2File(io.BufferedIOBase): # Fill the readahead buffer if it is empty. Returns False on EOF. def _fill_buffer(self): + if self._mode == _MODE_READ_EOF: + return False # Depending on the input data, our call to the decompressor may not # return any data. In this case, try again after reading another block. - while True: - if self._buffer: - return True - - if self._decompressor.unused_data: - rawblock = self._decompressor.unused_data - else: - rawblock = self._fp.read(_BUFFER_SIZE) + while self._buffer_offset == len(self._buffer): + rawblock = (self._decompressor.unused_data or + self._fp.read(_BUFFER_SIZE)) if not rawblock: if self._decompressor.eof: @@ -199,30 +198,48 @@ class BZ2File(io.BufferedIOBase): self._decompressor = BZ2Decompressor() self._buffer = self._decompressor.decompress(rawblock) + self._buffer_offset = 0 + return True # Read data until EOF. # If return_data is false, consume the data without returning it. def _read_all(self, return_data=True): + # The loop assumes that _buffer_offset is 0. Ensure that this is true. + self._buffer = self._buffer[self._buffer_offset:] + self._buffer_offset = 0 + blocks = [] while self._fill_buffer(): if return_data: blocks.append(self._buffer) self._pos += len(self._buffer) - self._buffer = None + self._buffer = b"" if return_data: return b"".join(blocks) # Read a block of up to n bytes. # If return_data is false, consume the data without returning it. def _read_block(self, n, return_data=True): + # If we have enough data buffered, return immediately. + end = self._buffer_offset + n + if end <= len(self._buffer): + data = self._buffer[self._buffer_offset : end] + self._buffer_offset = end + self._pos += len(data) + return data if return_data else None + + # The loop assumes that _buffer_offset is 0. Ensure that this is true. + self._buffer = self._buffer[self._buffer_offset:] + self._buffer_offset = 0 + blocks = [] while n > 0 and self._fill_buffer(): if n < len(self._buffer): data = self._buffer[:n] - self._buffer = self._buffer[n:] + self._buffer_offset = n else: data = self._buffer - self._buffer = None + self._buffer = b"" if return_data: blocks.append(data) self._pos += len(data) @@ -238,9 +255,9 @@ class BZ2File(io.BufferedIOBase): """ with self._lock: self._check_can_read() - if self._mode == _MODE_READ_EOF or not self._fill_buffer(): + if not self._fill_buffer(): return b"" - return self._buffer + return self._buffer[self._buffer_offset:] def read(self, size=-1): """Read up to size uncompressed bytes from the file. @@ -250,7 +267,7 @@ class BZ2File(io.BufferedIOBase): """ with self._lock: self._check_can_read() - if self._mode == _MODE_READ_EOF or size == 0: + if size == 0: return b"" elif size < 0: return self._read_all() @@ -268,15 +285,19 @@ class BZ2File(io.BufferedIOBase): # In this case we make multiple reads, to avoid returning b"". with self._lock: self._check_can_read() - if (size == 0 or self._mode == _MODE_READ_EOF or - not self._fill_buffer()): + if (size == 0 or + # Only call _fill_buffer() if the buffer is actually empty. + # This gives a significant speedup if *size* is small. + (self._buffer_offset == len(self._buffer) and not self._fill_buffer())): return b"" - if 0 < size < len(self._buffer): - data = self._buffer[:size] - self._buffer = self._buffer[size:] + if size > 0: + data = self._buffer[self._buffer_offset : + self._buffer_offset + size] + self._buffer_offset += len(data) else: - data = self._buffer - self._buffer = None + data = self._buffer[self._buffer_offset:] + self._buffer = b"" + self._buffer_offset = 0 self._pos += len(data) return data @@ -299,6 +320,14 @@ class BZ2File(io.BufferedIOBase): raise TypeError("Integer argument expected") size = size.__index__() with self._lock: + # Shortcut for the common case - the whole line is in the buffer. + if size < 0: + end = self._buffer.find(b"\n", self._buffer_offset) + 1 + if end > 0: + line = self._buffer[self._buffer_offset : end] + self._buffer_offset = end + self._pos += len(line) + return line return io.BufferedIOBase.readline(self, size) def readlines(self, size=-1): @@ -345,7 +374,8 @@ class BZ2File(io.BufferedIOBase): self._mode = _MODE_READ self._pos = 0 self._decompressor = BZ2Decompressor() - self._buffer = None + self._buffer = b"" + self._buffer_offset = 0 def seek(self, offset, whence=0): """Change the file position. @@ -385,8 +415,7 @@ class BZ2File(io.BufferedIOBase): offset -= self._pos # Read and discard data until we reach the desired position. - if self._mode != _MODE_READ_EOF: - self._read_block(offset, return_data=False) + self._read_block(offset, return_data=False) return self._pos diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py index 2420772..24924f6 100644 --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -1,4 +1,5 @@ import unittest +from test import script_helper from test import support import subprocess import sys @@ -191,15 +192,101 @@ class ProcessTestCase(BaseTestCase): p.wait() self.assertEqual(p.stderr, None) + # For use in the test_cwd* tests below. + def _normalize_cwd(self, cwd): + # Normalize an expected cwd (for Tru64 support). + # We can't use os.path.realpath since it doesn't expand Tru64 {memb} + # strings. See bug #1063571. + original_cwd = os.getcwd() + os.chdir(cwd) + cwd = os.getcwd() + os.chdir(original_cwd) + return cwd + + # For use in the test_cwd* tests below. + def _split_python_path(self): + # Return normalized (python_dir, python_base). + python_path = os.path.realpath(sys.executable) + return os.path.split(python_path) + + # For use in the test_cwd* tests below. + def _assert_cwd(self, expected_cwd, python_arg, **kwargs): + # Invoke Python via Popen, and assert that (1) the call succeeds, + # and that (2) the current working directory of the child process + # matches *expected_cwd*. + p = subprocess.Popen([python_arg, "-c", + "import os, sys; " + "sys.stdout.write(os.getcwd()); " + "sys.exit(47)"], + stdout=subprocess.PIPE, + **kwargs) + self.addCleanup(p.stdout.close) + p.wait() + self.assertEqual(47, p.returncode) + normcase = os.path.normcase + self.assertEqual(normcase(expected_cwd), + normcase(p.stdout.read().decode("utf-8"))) + + def test_cwd(self): + # Check that cwd changes the cwd for the child process. + temp_dir = tempfile.gettempdir() + temp_dir = self._normalize_cwd(temp_dir) + self._assert_cwd(temp_dir, sys.executable, cwd=temp_dir) + + def test_cwd_with_relative_arg(self): + # Check that Popen looks for args[0] relative to cwd if args[0] + # is relative. + python_dir, python_base = self._split_python_path() + rel_python = os.path.join(os.curdir, python_base) + with support.temp_cwd() as wrong_dir: + # Before calling with the correct cwd, confirm that the call fails + # without cwd and with the wrong cwd. + self.assertRaises(FileNotFoundError, subprocess.Popen, + [rel_python]) + self.assertRaises(FileNotFoundError, subprocess.Popen, + [rel_python], cwd=wrong_dir) + python_dir = self._normalize_cwd(python_dir) + self._assert_cwd(python_dir, rel_python, cwd=python_dir) + + def test_cwd_with_relative_executable(self): + # Check that Popen looks for executable relative to cwd if executable + # is relative (and that executable takes precedence over args[0]). + python_dir, python_base = self._split_python_path() + rel_python = os.path.join(os.curdir, python_base) + doesntexist = "somethingyoudonthave" + with support.temp_cwd() as wrong_dir: + # Before calling with the correct cwd, confirm that the call fails + # without cwd and with the wrong cwd. + self.assertRaises(FileNotFoundError, subprocess.Popen, + [doesntexist], executable=rel_python) + self.assertRaises(FileNotFoundError, subprocess.Popen, + [doesntexist], executable=rel_python, + cwd=wrong_dir) + python_dir = self._normalize_cwd(python_dir) + self._assert_cwd(python_dir, doesntexist, executable=rel_python, + cwd=python_dir) + + def test_cwd_with_absolute_arg(self): + # Check that Popen can find the executable when the cwd is wrong + # if args[0] is an absolute path. + python_dir, python_base = self._split_python_path() + abs_python = os.path.join(python_dir, python_base) + rel_python = os.path.join(os.curdir, python_base) + with script_helper.temp_dir() as wrong_dir: + # Before calling with an absolute path, confirm that using a + # relative path fails. + self.assertRaises(FileNotFoundError, subprocess.Popen, + [rel_python], cwd=wrong_dir) + wrong_dir = self._normalize_cwd(wrong_dir) + self._assert_cwd(wrong_dir, abs_python, cwd=wrong_dir) + @unittest.skipIf(sys.base_prefix != sys.prefix, 'Test is not venv-compatible') def test_executable_with_cwd(self): - python_dir = os.path.dirname(os.path.realpath(sys.executable)) - p = subprocess.Popen(["somethingyoudonthave", "-c", - "import sys; sys.exit(47)"], - executable=sys.executable, cwd=python_dir) - p.wait() - self.assertEqual(p.returncode, 47) + python_dir, python_base = self._split_python_path() + python_dir = self._normalize_cwd(python_dir) + self._assert_cwd(python_dir, "somethingyoudonthave", + executable=sys.executable, cwd=python_dir) @unittest.skipIf(sys.base_prefix != sys.prefix, 'Test is not venv-compatible') @@ -208,11 +295,7 @@ class ProcessTestCase(BaseTestCase): def test_executable_without_cwd(self): # For a normal installation, it should work without 'cwd' # argument. For test runs in the build directory, see #7774. - p = subprocess.Popen(["somethingyoudonthave", "-c", - "import sys; sys.exit(47)"], - executable=sys.executable) - p.wait() - self.assertEqual(p.returncode, 47) + self._assert_cwd('', "somethingyoudonthave", executable=sys.executable) def test_stdin_pipe(self): # stdin redirection @@ -369,24 +452,6 @@ class ProcessTestCase(BaseTestCase): p.wait() self.assertEqual(p.stdin, None) - def test_cwd(self): - tmpdir = tempfile.gettempdir() - # We cannot use os.path.realpath to canonicalize the path, - # since it doesn't expand Tru64 {memb} strings. See bug 1063571. - cwd = os.getcwd() - os.chdir(tmpdir) - tmpdir = os.getcwd() - os.chdir(cwd) - p = subprocess.Popen([sys.executable, "-c", - 'import sys,os;' - 'sys.stdout.write(os.getcwd())'], - stdout=subprocess.PIPE, - cwd=tmpdir) - self.addCleanup(p.stdout.close) - normcase = os.path.normcase - self.assertEqual(normcase(p.stdout.read().decode("utf-8")), - normcase(tmpdir)) - def test_env(self): newenv = os.environ.copy() newenv["FRUIT"] = "orange" @@ -10,13 +10,117 @@ What's New in Python 3.3.1? Core and Builtins ----------------- +- Issue #15379: Fix passing of non-BMP characters as integers for the charmap + decoder (already working as unicode strings). Patch by Serhiy Storchaka. + +- Issue #15144: Fix possible integer overflow when handling pointers as + integer values, by using Py_uintptr_t instead of size_t. Patch by + Serhiy Storchaka. + +- Issue #15965: Explicitly cast AT_FDCWD as (int). Required on Solaris 10 + (which defines AT_FDCWD as 0xffd19553), harmless on other platforms. + +- Issue #15839: Convert SystemErrors in super() to RuntimeErrors. + +- Issue #15846: Fix SystemError which happened when using ast.parse in an + exception handler on code with syntax errors. + +- Issue #15801: Make sure mappings passed to '%' formatting are actually + subscriptable. + + Library ------- +- Issue #16034: Fix performance regressions in the new BZ2File implementation. + Initial patch by Serhiy Storchaka. + - Issue #15756: subprocess.poll() now properly handles errno.ECHILD to return a returncode of 0 when the child has already exited or cannot be waited on. +- Issue #15323: improve failure message of Mock.assert_called_once_with + +- Issue #16064: unittest -m claims executable is "python", not "python3" + +- Issue #12376: Pass on parameters in TextTestResult.__init__ super call + +- Issue #15222: Insert blank line after each message in mbox mailboxes + +- Issue #16013: Fix CSV Reader parsing issue with ending quote characters. + Patch by Serhiy Storchaka. + +- Issue #15421: Fix an OverflowError in Calendar.itermonthdates() after + datetime.MAXYEAR. Patch by Cédric Krier. + +- Issue #15970: xml.etree.ElementTree now serializes correctly the empty HTML + elements 'meta' and 'param'. + +- Issue #15842: The SocketIO.{readable,writable,seekable} methods now + raise ValueError when the file-like object is closed. Patch by Alessandro + Moura. + +- Issue #15876: Fix a refleak in the curses module: window.encoding. + +- Issue #15881: Fixed atexit hook in multiprocessing. Original patch + by Chris McDonough. + +- Issue #15841: The readable(), writable() and seekable() methods of BytesIO + and StringIO objects now raise ValueError when the object has been closed. + Patch by Alessandro Moura. + +- Issue #15447: Use subprocess.DEVNULL in webbrowser, instead of opening + os.devnull explicitly and leaving it open. + +- Issue #15509: webbrowser.UnixBrowser no longer passes empty arguments to + Popen when %action substitutions produce empty strings. + +- Issues #12776, #11839: call argparse type function (specified by add_argument) + only once. Before, the type function was called twice in the case where the + default was specified and the argument was given as well. This was especially + problematic for the FileType type, as a default file would always be opened, + even if a file argument was specified on the command line. + +- Issue #15906: Fix a regression in argparse caused by the preceding change, + when action='append', type='str' and default=[]. + +Tests +----- + +- Issue #15304: Fix warning message when os.chdir() fails inside + test.support.temp_cwd(). Patch by Chris Jerdonek. + +- Issue #15802: Fix test logic in TestMaildir.test_create_tmp. Patch + by Serhiy Storchaka. + +- Issue #15557: Added a test suite for the webbrowser module, thanks + to Anton Barkovsky. + +Build +----- + +- Issue #15819: Make sure we can build Python out-of-tree from a readonly + source directory. (Somewhat related to Issue #9860.) + +Documentation +------------- + +- Issue #15533: Clarify docs and add tests for subprocess.Popen()'s cwd + argument. + +- Issue #16036: Improve documentation of built-in int()'s signature and + arguments. + +- Issue #15935: Clarification of argparse docs, re: add_argument() type and + default arguments. Patch contributed by Chris Jerdonek. + +- Issue #11964: Document a change in v3.2 to the behavior of the indent + parameter of json encoding operations. + +Tools/Demos +----------- + + What's New in Python 3.3.0? =========================== @@ -560,9 +664,10 @@ Tools/Demos - Issue #12605: The gdb hooks for debugging CPython (within Tools/gdb) have been enhanced to show information on more C frames relevant to CPython within the "py-bt" and "py-bt-full" commands: - * C frames that are waiting on the GIL - * C frames that are garbage-collecting - * C frames that are due to the invocation of a PyCFunction + + * C frames that are waiting on the GIL + * C frames that are garbage-collecting + * C frames that are due to the invocation of a PyCFunction Documentation ------------- diff --git a/Modules/_decimal/tests/bench.py b/Modules/_decimal/tests/bench.py index 7ab6b44..7e4a210 100644 --- a/Modules/_decimal/tests/bench.py +++ b/Modules/_decimal/tests/bench.py @@ -18,8 +18,13 @@ except ImportError: C = import_fresh_module('decimal', fresh=['_decimal']) P = import_fresh_module('decimal', blocked=['_decimal']) - -# Pi function from the decimal.py documentation +# +# NOTE: This is the pi function from the decimal documentation, modified +# for benchmarking purposes. Since floats do not have a context, the higher +# intermediate precision from the original is NOT used, so the modified +# algorithm only gives an approximation to the correctly rounded result. +# For serious use, refer to the documentation or the appropriate literature. +# def pi_float(): """native float""" lasts, t, s, n, na, d, da = 0, 3.0, 3, 1, 0, 0, 24 |