diff options
-rw-r--r-- | Doc/library/io.rst | 14 | ||||
-rw-r--r-- | Doc/library/stdtypes.rst | 8 | ||||
-rw-r--r-- | Doc/library/symtable.rst | 4 | ||||
-rw-r--r-- | Doc/library/timeit.rst | 5 | ||||
-rw-r--r-- | Lib/email/mime/nonmultipart.py | 4 | ||||
-rwxr-xr-x | Lib/pydoc.py | 7 | ||||
-rw-r--r-- | Lib/test/test_coding.py | 12 | ||||
-rw-r--r-- | Lib/test/test_extcall.py | 18 | ||||
-rw-r--r-- | Lib/test/test_pydoc.py | 42 | ||||
-rw-r--r-- | Lib/xml/sax/expatreader.py | 6 | ||||
-rw-r--r-- | Misc/ACKS | 1 | ||||
-rw-r--r-- | Modules/_ssl.c | 2 | ||||
-rw-r--r-- | Modules/_struct.c | 2 | ||||
-rw-r--r-- | Objects/funcobject.c | 21 | ||||
-rw-r--r-- | Parser/tokenizer.c | 5 | ||||
-rw-r--r-- | Python/compile.c | 12 |
16 files changed, 123 insertions, 40 deletions
diff --git a/Doc/library/io.rst b/Doc/library/io.rst index 5866113..71d3f67 100644 --- a/Doc/library/io.rst +++ b/Doc/library/io.rst @@ -359,9 +359,15 @@ I/O Base Classes implementation, but wrap one like :class:`BufferedWriter` and :class:`BufferedReader`. - :class:`BufferedIOBase` provides or overrides these methods in addition to + :class:`BufferedIOBase` provides or overrides these members in addition to those from :class:`IOBase`: + .. attribute:: raw + + The underlying raw stream (a :class:`RawIOBase` instance) that + :class:`BufferedIOBase` deals with. This is not part of the + :class:`BufferedIOBase` API and may not exist on some implementations. + .. method:: detach() Separate the underlying raw stream from the buffer and return it. @@ -607,6 +613,12 @@ Text I/O A string, a tuple of strings, or ``None``, indicating the newlines translated so far. + .. attribute:: buffer + + The underlying binary buffer (a :class:`BufferedIOBase` instance) that + :class:`TextIOBase` deals with. This is not part of the + :class:`TextIOBase` API and may not exist on some implementations. + .. method:: detach() Separate the underlying buffer from the :class:`TextIOBase` and return it. diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index bd02b37..1ccc457 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -583,10 +583,18 @@ Once an iterator's :meth:`__next__` method raises :exc:`StopIteration`, it must continue to do so on subsequent calls. Implementations that do not obey this property are deemed broken. + +.. _generator-types: + +Generator Types +--------------- + Python's :term:`generator`\s provide a convenient way to implement the iterator protocol. If a container object's :meth:`__iter__` method is implemented as a generator, it will automatically return an iterator object (technically, a generator object) supplying the :meth:`__iter__` and :meth:`__next__` methods. +More information about generators can be found in :ref:`the documentation for +the yield expression <yieldexpr>`. .. _typesseq: diff --git a/Doc/library/symtable.rst b/Doc/library/symtable.rst index 9ea3f01..9aafd4e 100644 --- a/Doc/library/symtable.rst +++ b/Doc/library/symtable.rst @@ -144,6 +144,10 @@ Examining Symbol Tables Return ``True`` if the symbol is global. + .. method:: is_declared_global() + + Return ``True`` if the symbol is declared global with a global statement. + .. method:: is_local() Return ``True`` if the symbol is local to its block. diff --git a/Doc/library/timeit.rst b/Doc/library/timeit.rst index 495ac81..a85fa3e 100644 --- a/Doc/library/timeit.rst +++ b/Doc/library/timeit.rst @@ -24,8 +24,9 @@ The module defines the following public class: The constructor takes a statement to be timed, an additional statement used for setup, and a timer function. Both statements default to ``'pass'``; the timer - function is platform-dependent (see the module doc string). The statements may - contain newlines, as long as they don't contain multi-line string literals. + function is platform-dependent (see the module doc string). *stmt* and *setup* + may also contain multiple statements separated by ``;`` or newlines, as long as + they don't contain multi-line string literals. To measure the execution time of the first statement, use the :meth:`timeit` method. The :meth:`repeat` method is a convenience to call :meth:`timeit` diff --git a/Lib/email/mime/nonmultipart.py b/Lib/email/mime/nonmultipart.py index dd280b5..fc3b9eb 100644 --- a/Lib/email/mime/nonmultipart.py +++ b/Lib/email/mime/nonmultipart.py @@ -14,13 +14,9 @@ from email.mime.base import MIMEBase class MIMENonMultipart(MIMEBase): """Base class for MIME multipart/* type messages.""" - __pychecker__ = 'unusednames=payload' - def attach(self, payload): # The public API prohibits attaching multiple subparts to MIMEBase # derived subtypes since none of them are, by definition, of content # type multipart/* raise errors.MultipartConversionError( 'Cannot attach additional subparts to non-multipart/*') - - del __pychecker__ diff --git a/Lib/pydoc.py b/Lib/pydoc.py index 6475dec..fe439c2 100755 --- a/Lib/pydoc.py +++ b/Lib/pydoc.py @@ -54,6 +54,7 @@ Richard Chamberlain, for the first implementation of textdoc. import sys, imp, os, re, inspect, builtins, pkgutil from reprlib import Repr +from traceback import extract_tb as _extract_tb try: from collections import deque except ImportError: @@ -292,9 +293,9 @@ def safeimport(path, forceload=0, cache={}): elif exc is SyntaxError: # A SyntaxError occurred before we could execute the module. raise ErrorDuringImport(value.filename, info) - elif exc is ImportError and \ - str(value).lower().split()[:2] == ['no', 'module']: - # The module was not found. + elif exc is ImportError and _extract_tb(tb)[-1][2]=='safeimport': + # The import error occurred directly in this function, + # which means there is no such module in the path. return None else: # Some other error occurred during the importing process. diff --git a/Lib/test/test_coding.py b/Lib/test/test_coding.py index 51873b4..9d368c5 100644 --- a/Lib/test/test_coding.py +++ b/Lib/test/test_coding.py @@ -49,6 +49,18 @@ class CodingTest(unittest.TestCase): unlink(TESTFN+".pyc") sys.path.pop(0) + def test_error_from_string(self): + # See http://bugs.python.org/issue6289 + input = "# coding: ascii\n\N{SNOWMAN}".encode('utf-8') + try: + compile(input, "<string>", "exec") + except SyntaxError as e: + expected = "'ascii' codec can't decode byte 0xe2 in position 16: " \ + "ordinal not in range(128)" + self.assertTrue(str(e).startswith(expected)) + else: + self.fail("didn't raise") + def test_main(): test.support.run_unittest(CodingTest) diff --git a/Lib/test/test_extcall.py b/Lib/test/test_extcall.py index 7ed0e2e..f1fff0a 100644 --- a/Lib/test/test_extcall.py +++ b/Lib/test/test_extcall.py @@ -243,6 +243,24 @@ TypeError if te dictionary is not empty ... TypeError: id() takes no keyword arguments +A corner case of keyword dictionary items being deleted during +the function call setup. See <http://bugs.python.org/issue2016>. + + >>> class Name(str): + ... def __eq__(self, other): + ... try: + ... del x[self] + ... except KeyError: + ... pass + ... return str.__eq__(self, other) + ... def __hash__(self): + ... return str.__hash__(self) + + >>> x = {Name("a"):1, Name("b"):2} + >>> def f(a, b): + ... print(a,b) + >>> f(**x) + 1 2 """ from test import support diff --git a/Lib/test/test_pydoc.py b/Lib/test/test_pydoc.py index 03b3539..00a2ada 100644 --- a/Lib/test/test_pydoc.py +++ b/Lib/test/test_pydoc.py @@ -1,5 +1,6 @@ import sys import os +import os.path import difflib import subprocess import re @@ -7,6 +8,8 @@ import pydoc import inspect import unittest import test.support +from contextlib import contextmanager +from test.support import TESTFN, forget, rmtree, EnvironmentVarGuard from test import pydoc_mod @@ -183,6 +186,9 @@ war</tt></dd></dl> # output pattern for missing module missing_pattern = "no Python documentation found for '%s'" +# output pattern for module with bad imports +badimport_pattern = "problem in %s - ImportError: No module named %s" + def run_pydoc(module_name, *args): """ Runs pydoc on the specified module. Returns the stripped @@ -254,6 +260,42 @@ class PyDocDocTest(unittest.TestCase): self.assertEqual(expected, result, "documentation for missing module found") + def test_badimport(self): + # This tests the fix for issue 5230, where if pydoc found the module + # but the module had an internal import error pydoc would report no doc + # found. + modname = 'testmod_xyzzy' + testpairs = ( + ('i_am_not_here', 'i_am_not_here'), + ('test.i_am_not_here_either', 'i_am_not_here_either'), + ('test.i_am_not_here.neither_am_i', 'i_am_not_here.neither_am_i'), + ('i_am_not_here.{}'.format(modname), 'i_am_not_here.{}'.format(modname)), + ('test.{}'.format(modname), modname), + ) + + @contextmanager + def newdirinpath(dir): + os.mkdir(dir) + sys.path.insert(0, dir) + yield + sys.path.pop(0) + rmtree(dir) + + with newdirinpath(TESTFN), EnvironmentVarGuard() as env: + env['PYTHONPATH'] = TESTFN + fullmodname = os.path.join(TESTFN, modname) + sourcefn = fullmodname + os.extsep + "py" + for importstring, expectedinmsg in testpairs: + f = open(sourcefn, 'w') + f.write("import {}\n".format(importstring)) + f.close() + try: + result = run_pydoc(modname).decode("ascii") + finally: + forget(modname) + expected = badimport_pattern % (modname, expectedinmsg) + self.assertEqual(expected, result) + def test_input_strip(self): missing_module = " test.i_am_not_here " result = str(run_pydoc(missing_module), 'ascii') diff --git a/Lib/xml/sax/expatreader.py b/Lib/xml/sax/expatreader.py index 26b05c3..c9fc894 100644 --- a/Lib/xml/sax/expatreader.py +++ b/Lib/xml/sax/expatreader.py @@ -407,8 +407,8 @@ def create_parser(*args, **kwargs): # --- if __name__ == "__main__": - import xml.sax + import xml.sax.saxutils p = create_parser() - p.setContentHandler(xml.sax.XMLGenerator()) + p.setContentHandler(xml.sax.saxutils.XMLGenerator()) p.setErrorHandler(xml.sax.ErrorHandler()) - p.parse("../../../hamlet.xml") + p.parse("http://www.ibiblio.org/xml/examples/shakespeare/hamlet.xml") @@ -482,6 +482,7 @@ Andrew McNamara Craig McPheeters Lambert Meertens Bill van Melle +Lucas Prado Melo Luke Mewburn Mike Meyer Steven Miale diff --git a/Modules/_ssl.c b/Modules/_ssl.c index b400057..906138d 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -658,7 +658,7 @@ _get_peer_alt_names (X509 *certificate) { char buf[2048]; char *vptr; int len; - const unsigned char *p; + unsigned char *p; if (certificate == NULL) return peer_alt_names; diff --git a/Modules/_struct.c b/Modules/_struct.c index 83f5685..27d596c 100644 --- a/Modules/_struct.c +++ b/Modules/_struct.c @@ -132,6 +132,7 @@ get_long(PyObject *v, long *p) /* Same, but handling unsigned long */ +#ifndef PY_STRUCT_OVERFLOW_MASKING static int get_ulong(PyObject *v, unsigned long *p) { @@ -152,6 +153,7 @@ get_ulong(PyObject *v, unsigned long *p) *p = x; return 0; } +#endif /* PY_STRUCT_OVERFLOW_MASKING */ #ifdef HAVE_LONG_LONG diff --git a/Objects/funcobject.c b/Objects/funcobject.c index acd662c..1456810 100644 --- a/Objects/funcobject.c +++ b/Objects/funcobject.c @@ -593,13 +593,14 @@ function_call(PyObject *func, PyObject *arg, PyObject *kw) { PyObject *result; PyObject *argdefs; + PyObject *kwtuple = NULL; PyObject **d, **k; Py_ssize_t nk, nd; argdefs = PyFunction_GET_DEFAULTS(func); if (argdefs != NULL && PyTuple_Check(argdefs)) { d = &PyTuple_GET_ITEM((PyTupleObject *)argdefs, 0); - nd = PyTuple_Size(argdefs); + nd = PyTuple_GET_SIZE(argdefs); } else { d = NULL; @@ -609,16 +610,17 @@ function_call(PyObject *func, PyObject *arg, PyObject *kw) if (kw != NULL && PyDict_Check(kw)) { Py_ssize_t pos, i; nk = PyDict_Size(kw); - k = PyMem_NEW(PyObject *, 2*nk); - if (k == NULL) { - PyErr_NoMemory(); + kwtuple = PyTuple_New(2*nk); + if (kwtuple == NULL) return NULL; - } + k = &PyTuple_GET_ITEM(kwtuple, 0); pos = i = 0; - while (PyDict_Next(kw, &pos, &k[i], &k[i+1])) + while (PyDict_Next(kw, &pos, &k[i], &k[i+1])) { + Py_INCREF(k[i]); + Py_INCREF(k[i+1]); i += 2; + } nk = i/2; - /* XXX This is broken if the caller deletes dict items! */ } else { k = NULL; @@ -628,13 +630,12 @@ function_call(PyObject *func, PyObject *arg, PyObject *kw) result = PyEval_EvalCodeEx( (PyCodeObject *)PyFunction_GET_CODE(func), PyFunction_GET_GLOBALS(func), (PyObject *)NULL, - &PyTuple_GET_ITEM(arg, 0), PyTuple_Size(arg), + &PyTuple_GET_ITEM(arg, 0), PyTuple_GET_SIZE(arg), k, nk, d, nd, PyFunction_GET_KW_DEFAULTS(func), PyFunction_GET_CLOSURE(func)); - if (k != NULL) - PyMem_DEL(k); + Py_XDECREF(kwtuple); return result; } diff --git a/Parser/tokenizer.c b/Parser/tokenizer.c index 15e8185..cc142a7 100644 --- a/Parser/tokenizer.c +++ b/Parser/tokenizer.c @@ -682,11 +682,8 @@ decode_str(const char *str, struct tok_state *tok) if (tok->enc != NULL) { assert(utf8 == NULL); utf8 = translate_into_utf8(str, tok->enc); - if (utf8 == NULL) { - PyErr_Format(PyExc_SyntaxError, - "unknown encoding: %s", tok->enc); + if (utf8 == NULL) return error_ret(tok); - } str = PyBytes_AS_STRING(utf8); } assert(tok->decoding_buffer == NULL); diff --git a/Python/compile.c b/Python/compile.c index c78949d..11d7c33 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -551,18 +551,6 @@ compiler_exit_scope(struct compiler *c) } -/* Allocate a new "anonymous" local variable. - Used by list comprehensions and with statements. -*/ - -static PyObject * -compiler_new_tmpname(struct compiler *c) -{ - char tmpname[256]; - PyOS_snprintf(tmpname, sizeof(tmpname), "_[%d]", ++c->u->u_tmpname); - return PyUnicode_FromString(tmpname); -} - /* Allocate a new block and return a pointer to it. Returns NULL on error. */ |