summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Doc/library/io.rst14
-rw-r--r--Doc/library/stdtypes.rst8
-rw-r--r--Doc/library/symtable.rst4
-rw-r--r--Doc/library/timeit.rst5
-rw-r--r--Lib/email/mime/nonmultipart.py4
-rwxr-xr-xLib/pydoc.py7
-rw-r--r--Lib/test/test_coding.py12
-rw-r--r--Lib/test/test_extcall.py18
-rw-r--r--Lib/test/test_pydoc.py42
-rw-r--r--Lib/xml/sax/expatreader.py6
-rw-r--r--Misc/ACKS1
-rw-r--r--Modules/_ssl.c2
-rw-r--r--Modules/_struct.c2
-rw-r--r--Objects/funcobject.c21
-rw-r--r--Parser/tokenizer.c5
-rw-r--r--Python/compile.c12
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")
diff --git a/Misc/ACKS b/Misc/ACKS
index 4d58f95..0fa88ed 100644
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -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.
*/