From ed512a4d0969a93402e3d4245540dff24b0dce4c Mon Sep 17 00:00:00 2001 From: Kristjan Valur Jonsson Date: Fri, 21 Dec 2012 10:32:57 +0000 Subject: [PATCH 01/38] ctypes: DECREF error_object _after_ re-acquiring GIL --- Modules/_ctypes/callproc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c index ef3e97408c0..23825a7110d 100644 --- a/Modules/_ctypes/callproc.c +++ b/Modules/_ctypes/callproc.c @@ -844,11 +844,11 @@ static int _call_function_pointer(int flags, space[0] = errno; errno = temp; } - Py_XDECREF(error_object); #ifdef WITH_THREAD if ((flags & FUNCFLAG_PYTHONAPI) == 0) Py_BLOCK_THREADS #endif + Py_XDECREF(error_object); #ifdef MS_WIN32 #ifndef DONT_USE_SEH if (dwExceptionCode) { From 9a772e5e8f1c85ca875329d8bb09098c1874d610 Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Sat, 22 Dec 2012 10:43:06 +0100 Subject: [PATCH 02/38] Fix indentation. --- Doc/library/imp.rst | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Doc/library/imp.rst b/Doc/library/imp.rst index 04bc6f58775..8f98d652d85 100644 --- a/Doc/library/imp.rst +++ b/Doc/library/imp.rst @@ -239,14 +239,14 @@ around for backward compatibility: .. impl-detail:: - The import internals identify extension modules by filename, so doing - ``foo = load_dynamic("foo", "mod.so")`` and - ``bar = load_dynamic("bar", "mod.so")`` will result in both foo and bar - referring to the same module, regardless of whether or not - ``mod.so`` exports an ``initbar`` function. On systems which - support them, symlinks can be used to import multiple modules from - the same shared library, as each reference to the module will use - a different file name. + The import internals identify extension modules by filename, so doing + ``foo = load_dynamic("foo", "mod.so")`` and + ``bar = load_dynamic("bar", "mod.so")`` will result in both foo and bar + referring to the same module, regardless of whether or not + ``mod.so`` exports an ``initbar`` function. On systems which + support them, symlinks can be used to import multiple modules from + the same shared library, as each reference to the module will use + a different file name. .. function:: load_source(name, pathname[, file]) From 8e1e8165a32da4934449df7dffac82c26b6ab101 Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Sat, 22 Dec 2012 10:44:11 +0100 Subject: [PATCH 03/38] Add missing label. --- Doc/using/windows.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Doc/using/windows.rst b/Doc/using/windows.rst index 978440c20bf..b49ba7ba92c 100644 --- a/Doc/using/windows.rst +++ b/Doc/using/windows.rst @@ -84,6 +84,8 @@ In order to run Python flawlessly, you might have to change certain environment settings in Windows. +.. _setting-envvars: + Excursus: Setting environment variables --------------------------------------- From cddcafaf6b11f4da66fdccba20a777ccb55b800b Mon Sep 17 00:00:00 2001 From: Andrew Svetlov Date: Sun, 23 Dec 2012 12:44:04 +0200 Subject: [PATCH 04/38] Issue #16045: add more unit tests for built-in int() Patch by Chris Jerdonek. --- Lib/test/test_builtin.py | 2 ++ Lib/test/test_int.py | 54 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py index 1d35a6afe57..d75c44afbba 100644 --- a/Lib/test/test_builtin.py +++ b/Lib/test/test_builtin.py @@ -680,6 +680,8 @@ class BuiltinTest(unittest.TestCase): # Test input() later, together with raw_input + # test_int(): see test_int.py for int() tests. + def test_intern(self): self.assertRaises(TypeError, intern) # This fails if the test is run twice with a constant string, diff --git a/Lib/test/test_int.py b/Lib/test/test_int.py index fa46212d9b1..88627017e5b 100644 --- a/Lib/test/test_int.py +++ b/Lib/test/test_int.py @@ -1,6 +1,7 @@ import sys import unittest +from test import test_support from test.test_support import run_unittest, have_unicode import math @@ -315,6 +316,59 @@ class IntTestCases(unittest.TestCase): self.assertEqual(int(float(2**54+10)), 2**54+8) self.assertEqual(int(float(2**54+11)), 2**54+12) + def test_no_args(self): + self.assertEquals(int(), 0) + + def test_keyword_args(self): + # Test invoking int() using keyword arguments. + self.assertEquals(int(x=1.2), 1) + self.assertEquals(int('100', base=2), 4) + self.assertEquals(int(x='100', base=2), 4) + + def test_valid_non_numeric_input_types_for_x(self): + # Test possible valid non-numeric types for x, including subclasses + # of the allowed built-in types. + class CustomStr(str): pass + values = ['100', CustomStr('100')] + + if have_unicode: + class CustomUnicode(unicode): pass + values += [unicode('100'), CustomUnicode(unicode('100'))] + + for x in values: + msg = 'x has value %s and type %s' % (x, type(x).__name__) + try: + self.assertEquals(int(x), 100, msg=msg) + self.assertEquals(int(x, 2), 4, msg=msg) + except TypeError, err: + raise AssertionError('For %s got TypeError: %s' % + (type(x).__name__, err)) + + def test_error_on_string_float_for_x(self): + self.assertRaises(ValueError, int, '1.2') + + def test_error_on_bytearray_for_x(self): + self.assertRaises(TypeError, int, bytearray('100'), 2) + + def test_error_on_invalid_int_bases(self): + for base in [-1, 1, 1000]: + self.assertRaises(ValueError, int, '100', base) + + def test_error_on_string_base(self): + self.assertRaises(TypeError, int, 100, base='foo') + # Include the following because in contrast CPython raises no error + # for bad integer bases when x is not given. + self.assertRaises(TypeError, int, base='foo') + + # For example, PyPy 1.9.0 raised TypeError for these cases because it + # expects x to be a string if base is given. + @test_support.cpython_only + def test_int_base_without_x_returns_0(self): + self.assertEquals(int(base=6), 0) + # Even invalid bases don't raise an exception. + self.assertEquals(int(base=1), 0) + self.assertEquals(int(base=1000), 0) + def test_intconversion(self): # Test __int__() class ClassicMissingMethods: From f8a6b005fdd1b150ae41699de556951a0d3ee26b Mon Sep 17 00:00:00 2001 From: Senthil Kumaran Date: Sun, 23 Dec 2012 09:00:47 -0800 Subject: [PATCH 05/38] Fix Issue15701 - HTTPError info method call raises AttributeError. Fix that to return headers correctly --- Lib/test/test_urllib2.py | 34 +++++++++++++++++++++++++--------- Lib/urllib2.py | 3 +++ Misc/NEWS | 2 ++ 3 files changed, 30 insertions(+), 9 deletions(-) diff --git a/Lib/test/test_urllib2.py b/Lib/test/test_urllib2.py index 12263b381dc..eac995001e8 100644 --- a/Lib/test/test_urllib2.py +++ b/Lib/test/test_urllib2.py @@ -1336,16 +1336,32 @@ class RequestTests(unittest.TestCase): req = Request(url) self.assertEqual(req.get_full_url(), url) -def test_HTTPError_interface(): - """ - Issue 13211 reveals that HTTPError didn't implement the URLError - interface even though HTTPError is a subclass of URLError. + def test_HTTPError_interface(self): + """ + Issue 13211 reveals that HTTPError didn't implement the URLError + interface even though HTTPError is a subclass of URLError. - >>> err = urllib2.HTTPError(msg='something bad happened', url=None, code=None, hdrs=None, fp=None) - >>> assert hasattr(err, 'reason') - >>> err.reason - 'something bad happened' - """ + >>> err = urllib2.HTTPError(msg='something bad happened', url=None, code=None, hdrs=None, fp=None) + >>> assert hasattr(err, 'reason') + >>> err.reason + 'something bad happened' + """ + + def test_HTTPError_interface_call(self): + """ + Issue 15701= - HTTPError interface has info method available from URLError. + """ + err = urllib2.HTTPError(msg='something bad happened', url=None, + code=None, hdrs='Content-Length:42', fp=None) + self.assertTrue(hasattr(err, 'reason')) + assert hasattr(err, 'reason') + assert hasattr(err, 'info') + assert callable(err.info) + try: + err.info() + except AttributeError: + self.fail("err.info() failed") + self.assertEqual(err.info(), "Content-Length:42") def test_main(verbose=None): from test import test_urllib2 diff --git a/Lib/urllib2.py b/Lib/urllib2.py index ebf58119d6a..aadeb7371eb 100644 --- a/Lib/urllib2.py +++ b/Lib/urllib2.py @@ -173,6 +173,9 @@ class HTTPError(URLError, addinfourl): def reason(self): return self.msg + def info(self): + return self.hdrs + # copied from cookielib.py _cut_port_re = re.compile(r":\d+$") def request_host(request): diff --git a/Misc/NEWS b/Misc/NEWS index babe8383a27..c0172572a7f 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -165,6 +165,8 @@ Library - Issue #16597: In buffered and text IO, call close() on the underlying stream if invoking flush() fails. +- Issue #15701: Fix HTTPError info method call to return the headers information. + - Issue #16646: ftplib.FTP.makeport() might lose socket error details. (patch by Serhiy Storchaka) From 1c6c90fc73bc779da80982aaf0c17644c6017fa5 Mon Sep 17 00:00:00 2001 From: Andrew Svetlov Date: Sun, 23 Dec 2012 20:09:01 +0200 Subject: [PATCH 06/38] Issue #16443: Add docstrings to regular expression match objects. Patch by Anton Kasyanov. --- Misc/ACKS | 1 + Misc/NEWS | 3 +++ Modules/_sre.c | 58 ++++++++++++++++++++++++++++++++++++++++++-------- 3 files changed, 53 insertions(+), 9 deletions(-) diff --git a/Misc/ACKS b/Misc/ACKS index ea7bea588ae..cfe7462437a 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -499,6 +499,7 @@ Tamito Kajiyama Peter van Kampen Jacob Kaplan-Moss Piotr Kasprzyk +Anton Kasyanov Lou Kates Hiroaki Kawai Sebastien Keim diff --git a/Misc/NEWS b/Misc/NEWS index c0172572a7f..e8e318df4e5 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -160,6 +160,9 @@ Core and Builtins Library ------- +- Issue #16443: Add docstrings to regular expression match objects. + Patch by Anton Kasyanov. + - Issue #8853: Allow port to be of type long for socket.getaddrinfo(). - Issue #16597: In buffered and text IO, call close() on the underlying stream diff --git a/Modules/_sre.c b/Modules/_sre.c index a5a6b1e8024..16e0303a276 100644 --- a/Modules/_sre.c +++ b/Modules/_sre.c @@ -3545,14 +3545,54 @@ match_deepcopy(MatchObject* self, PyObject* memo) #endif } -static struct PyMethodDef match_methods[] = { - {"group", (PyCFunction) match_group, METH_VARARGS}, - {"start", (PyCFunction) match_start, METH_VARARGS}, - {"end", (PyCFunction) match_end, METH_VARARGS}, - {"span", (PyCFunction) match_span, METH_VARARGS}, - {"groups", (PyCFunction) match_groups, METH_VARARGS|METH_KEYWORDS}, - {"groupdict", (PyCFunction) match_groupdict, METH_VARARGS|METH_KEYWORDS}, - {"expand", (PyCFunction) match_expand, METH_O}, +PyDoc_STRVAR(match_doc, +"The result of re.match() and re.search().\n\ +Match objects always have a boolean value of True."); + +PyDoc_STRVAR(match_group_doc, +"group([group1, ...]) -> str or tuple.\n\ + Return subgroup(s) of the match by indices or names.\n\ + For 0 returns the entire match."); + +PyDoc_STRVAR(match_start_doc, +"start([group=0]) -> int.\n\ + Return index of the start of the substring matched by group."); + +PyDoc_STRVAR(match_end_doc, +"end([group=0]) -> int.\n\ + Return index of the end of the substring matched by group."); + +PyDoc_STRVAR(match_span_doc, +"span([group]) -> tuple.\n\ + For MatchObject m, return the 2-tuple (m.start(group), m.end(group))."); + +PyDoc_STRVAR(match_groups_doc, +"groups([default=None]) -> tuple.\n\ + Return a tuple containing all the subgroups of the match, from 1.\n\ + The default argument is used for groups\n\ + that did not participate in the match"); + +PyDoc_STRVAR(match_groupdict_doc, +"groupdict([default=None]) -> dict.\n\ + Return a dictionary containing all the named subgroups of the match,\n\ + keyed by the subgroup name. The default argument is used for groups\n\ + that did not participate in the match"); + +PyDoc_STRVAR(match_expand_doc, +"expand(template) -> str.\n\ + Return the string obtained by doing backslash substitution\n\ + on the string template, as done by the sub() method."); + +static PyMethodDef match_methods[] = { + {"group", (PyCFunction) match_group, METH_VARARGS, match_group_doc}, + {"start", (PyCFunction) match_start, METH_VARARGS, match_start_doc}, + {"end", (PyCFunction) match_end, METH_VARARGS, match_end_doc}, + {"span", (PyCFunction) match_span, METH_VARARGS, match_span_doc}, + {"groups", (PyCFunction) match_groups, METH_VARARGS|METH_KEYWORDS, + match_groups_doc}, + {"groupdict", (PyCFunction) match_groupdict, METH_VARARGS|METH_KEYWORDS, + match_groupdict_doc}, + {"expand", (PyCFunction) match_expand, METH_O, match_expand_doc}, {"__copy__", (PyCFunction) match_copy, METH_NOARGS}, {"__deepcopy__", (PyCFunction) match_deepcopy, METH_O}, {NULL, NULL} @@ -3632,7 +3672,7 @@ static PyTypeObject Match_Type = { 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, - 0, /* tp_doc */ + match_doc, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ From d8590ff209369f45a5ed417c79ce255a33f70a1d Mon Sep 17 00:00:00 2001 From: Andrew Svetlov Date: Mon, 24 Dec 2012 13:17:59 +0200 Subject: [PATCH 07/38] Issue #16511: Use default IDLE width and height if config param is not valid. Patch Serhiy Storchaka. --- Lib/idlelib/EditorWindow.py | 10 ++++--- Lib/idlelib/FormatParagraph.py | 3 +- Lib/idlelib/configDialog.py | 11 +++++--- Lib/idlelib/configHandler.py | 51 ++++++++++++++++++++++------------ 4 files changed, 48 insertions(+), 27 deletions(-) diff --git a/Lib/idlelib/EditorWindow.py b/Lib/idlelib/EditorWindow.py index 241bd38ff9c..efd3c54d9a3 100644 --- a/Lib/idlelib/EditorWindow.py +++ b/Lib/idlelib/EditorWindow.py @@ -172,13 +172,13 @@ class EditorWindow(object): 'recent-files.lst') self.text_frame = text_frame = Frame(top) self.vbar = vbar = Scrollbar(text_frame, name='vbar') - self.width = idleConf.GetOption('main','EditorWindow','width') + self.width = idleConf.GetOption('main','EditorWindow','width', type='int') text_options = { 'name': 'text', 'padx': 5, 'wrap': 'none', 'width': self.width, - 'height': idleConf.GetOption('main', 'EditorWindow', 'height')} + 'height': idleConf.GetOption('main', 'EditorWindow', 'height', type='int')} if TkVersion >= 8.5: # Starting with tk 8.5 we have to set the new tabstyle option # to 'wordprocessor' to achieve the same display of tabs as in @@ -255,7 +255,8 @@ class EditorWindow(object): if idleConf.GetOption('main', 'EditorWindow', 'font-bold', type='bool'): fontWeight='bold' text.config(font=(idleConf.GetOption('main', 'EditorWindow', 'font'), - idleConf.GetOption('main', 'EditorWindow', 'font-size'), + idleConf.GetOption('main', 'EditorWindow', + 'font-size', type='int'), fontWeight)) text_frame.pack(side=LEFT, fill=BOTH, expand=1) text.pack(side=TOP, fill=BOTH, expand=1) @@ -763,7 +764,8 @@ class EditorWindow(object): if idleConf.GetOption('main','EditorWindow','font-bold',type='bool'): fontWeight='bold' self.text.config(font=(idleConf.GetOption('main','EditorWindow','font'), - idleConf.GetOption('main','EditorWindow','font-size'), + idleConf.GetOption('main','EditorWindow','font-size', + type='int'), fontWeight)) def RemoveKeybindings(self): diff --git a/Lib/idlelib/FormatParagraph.py b/Lib/idlelib/FormatParagraph.py index 6a5f9b5dd59..557d8a9e0d7 100644 --- a/Lib/idlelib/FormatParagraph.py +++ b/Lib/idlelib/FormatParagraph.py @@ -32,7 +32,8 @@ class FormatParagraph: self.editwin = None def format_paragraph_event(self, event): - maxformatwidth = int(idleConf.GetOption('main','FormatParagraph','paragraph')) + maxformatwidth = int(idleConf.GetOption('main','FormatParagraph', + 'paragraph', type='int')) text = self.editwin.text first, last = self.editwin.get_selection_indices() if first and last: diff --git a/Lib/idlelib/configDialog.py b/Lib/idlelib/configDialog.py index 9884d5e5a2e..b707fc3ddb4 100644 --- a/Lib/idlelib/configDialog.py +++ b/Lib/idlelib/configDialog.py @@ -947,7 +947,7 @@ class ConfigDialog(Toplevel): self.listFontName.select_anchor(currentFontIndex) ##font size dropdown fontSize=idleConf.GetOption('main','EditorWindow','font-size', - default='10') + type='int', default='10') self.optMenuFontSize.SetMenu(('7','8','9','10','11','12','13','14', '16','18','20','22'),fontSize ) ##fontWeight @@ -1033,10 +1033,13 @@ class ConfigDialog(Toplevel): self.autoSave.set(idleConf.GetOption('main', 'General', 'autosave', default=0, type='bool')) #initial window size - self.winWidth.set(idleConf.GetOption('main','EditorWindow','width')) - self.winHeight.set(idleConf.GetOption('main','EditorWindow','height')) + self.winWidth.set(idleConf.GetOption('main','EditorWindow','width', + type='int')) + self.winHeight.set(idleConf.GetOption('main','EditorWindow','height', + type='int')) #initial paragraph reformat size - self.paraWidth.set(idleConf.GetOption('main','FormatParagraph','paragraph')) + self.paraWidth.set(idleConf.GetOption('main','FormatParagraph','paragraph', + type='int')) # default source encoding self.encoding.set(idleConf.GetOption('main', 'EditorWindow', 'encoding', default='none')) diff --git a/Lib/idlelib/configHandler.py b/Lib/idlelib/configHandler.py index dd13a0e7334..ce28d0836d6 100644 --- a/Lib/idlelib/configHandler.py +++ b/Lib/idlelib/configHandler.py @@ -237,24 +237,39 @@ class IdleConf: printed to stderr. """ - if self.userCfg[configType].has_option(section,option): - return self.userCfg[configType].Get(section, option, - type=type, raw=raw) - elif self.defaultCfg[configType].has_option(section,option): - return self.defaultCfg[configType].Get(section, option, - type=type, raw=raw) - else: #returning default, print warning - if warn_on_default: - warning = ('\n Warning: configHandler.py - IdleConf.GetOption -\n' - ' problem retrieving configuration option %r\n' - ' from section %r.\n' - ' returning default value: %r\n' % - (option, section, default)) - try: - sys.stderr.write(warning) - except IOError: - pass - return default + try: + if self.userCfg[configType].has_option(section,option): + return self.userCfg[configType].Get(section, option, + type=type, raw=raw) + except ValueError: + warning = ('\n Warning: configHandler.py - IdleConf.GetOption -\n' + ' invalid %r value for configuration option %r\n' + ' from section %r: %r\n' % + (type, option, section, + self.userCfg[configType].Get(section, option, + raw=raw))) + try: + sys.stderr.write(warning) + except IOError: + pass + try: + if self.defaultCfg[configType].has_option(section,option): + return self.defaultCfg[configType].Get(section, option, + type=type, raw=raw) + except ValueError: + pass + #returning default, print warning + if warn_on_default: + warning = ('\n Warning: configHandler.py - IdleConf.GetOption -\n' + ' problem retrieving configuration option %r\n' + ' from section %r.\n' + ' returning default value: %r\n' % + (option, section, default)) + try: + sys.stderr.write(warning) + except IOError: + pass + return default def SetOption(self, configType, section, option, value): """In user's config file, set section's option to value. From 9fade768c89e3fbb497ac2851fbf540c3f054757 Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Mon, 24 Dec 2012 16:33:18 +0000 Subject: [PATCH 08/38] Issue #13863: fix incorrect .pyc timestamps on Windows / NTFS (apparently due to buggy fstat) --- Lib/test/test_import.py | 41 ++++++++++++++++++++++++++++++++ Misc/NEWS | 4 ++++ Python/import.c | 52 ++++++++++++++++++++++++++++++++++++----- 3 files changed, 91 insertions(+), 6 deletions(-) diff --git a/Lib/test/test_import.py b/Lib/test/test_import.py index edd18694b9c..ea50d34626a 100644 --- a/Lib/test/test_import.py +++ b/Lib/test/test_import.py @@ -5,6 +5,7 @@ import os import py_compile import random import stat +import struct import sys import unittest import textwrap @@ -350,6 +351,46 @@ class ImportTests(unittest.TestCase): del sys.path[0] remove_files(TESTFN) + def test_pyc_mtime(self): + # Test for issue #13863: .pyc timestamp sometimes incorrect on Windows. + sys.path.insert(0, os.curdir) + try: + # Jan 1, 2012; Jul 1, 2012. + mtimes = 1325376000, 1341100800 + + # Different names to avoid running into import caching. + tails = "spam", "eggs" + for mtime, tail in zip(mtimes, tails): + module = TESTFN + tail + source = module + ".py" + compiled = source + ('c' if __debug__ else 'o') + + # Create a new Python file with the given mtime. + with open(source, 'w') as f: + f.write("# Just testing\nx=1, 2, 3\n") + os.utime(source, (mtime, mtime)) + + # Generate the .pyc/o file; if it couldn't be created + # for some reason, skip the test. + m = __import__(module) + if not os.path.exists(compiled): + unlink(source) + self.skipTest("Couldn't create .pyc/.pyo file.") + + # Actual modification time of .py file. + mtime1 = int(os.stat(source).st_mtime) & 0xffffffff + + # mtime that was encoded in the .pyc file. + with open(compiled, 'rb') as f: + mtime2 = struct.unpack('st_mtime; #ifdef MS_WINDOWS /* since Windows uses different permissions */ mode_t mode = srcstat->st_mode & ~S_IEXEC; /* Issue #6074: We ensure user write access, so we can delete it later @@ -993,6 +992,38 @@ update_compiled_module(PyCodeObject *co, char *pathname) return 1; } +#ifdef MS_WINDOWS + +/* Seconds between 1.1.1601 and 1.1.1970 */ +static __int64 secs_between_epochs = 11644473600; + +/* Get mtime from file pointer. */ + +static time_t +win32_mtime(FILE *fp, char *pathname) +{ + __int64 filetime; + HANDLE fh; + BY_HANDLE_FILE_INFORMATION file_information; + + fh = (HANDLE)_get_osfhandle(fileno(fp)); + if (fh == INVALID_HANDLE_VALUE || + !GetFileInformationByHandle(fh, &file_information)) { + PyErr_Format(PyExc_RuntimeError, + "unable to get file status from '%s'", + pathname); + return -1; + } + /* filetime represents the number of 100ns intervals since + 1.1.1601 (UTC). Convert to seconds since 1.1.1970 (UTC). */ + filetime = (__int64)file_information.ftLastWriteTime.dwHighDateTime << 32 | + file_information.ftLastWriteTime.dwLowDateTime; + return filetime / 10000000 - secs_between_epochs; +} + +#endif /* #ifdef MS_WINDOWS */ + + /* Load a source module from a given file and return its module object WITH INCREMENTED REFERENCE COUNT. If there's a matching byte-compiled file, use that instead. */ @@ -1006,6 +1037,7 @@ load_source_module(char *name, char *pathname, FILE *fp) char *cpathname; PyCodeObject *co = NULL; PyObject *m; + time_t mtime; if (fstat(fileno(fp), &st) != 0) { PyErr_Format(PyExc_RuntimeError, @@ -1013,13 +1045,21 @@ load_source_module(char *name, char *pathname, FILE *fp) pathname); return NULL; } - if (sizeof st.st_mtime > 4) { + +#ifdef MS_WINDOWS + mtime = win32_mtime(fp, pathname); + if (mtime == (time_t)-1 && PyErr_Occurred()) + return NULL; +#else + mtime = st.st_mtime; +#endif + if (sizeof mtime > 4) { /* Python's .pyc timestamp handling presumes that the timestamp fits in 4 bytes. Since the code only does an equality comparison, ordering is not important and we can safely ignore the higher bits (collisions are extremely unlikely). */ - st.st_mtime &= 0xFFFFFFFF; + mtime &= 0xFFFFFFFF; } buf = PyMem_MALLOC(MAXPATHLEN+1); if (buf == NULL) { @@ -1028,7 +1068,7 @@ load_source_module(char *name, char *pathname, FILE *fp) cpathname = make_compiled_pathname(pathname, buf, (size_t)MAXPATHLEN + 1); if (cpathname != NULL && - (fpc = check_compiled_module(pathname, st.st_mtime, cpathname))) { + (fpc = check_compiled_module(pathname, mtime, cpathname))) { co = read_compiled_module(cpathname, fpc); fclose(fpc); if (co == NULL) @@ -1053,7 +1093,7 @@ load_source_module(char *name, char *pathname, FILE *fp) if (b < 0) goto error_exit; if (!b) - write_compiled_module(co, cpathname, &st); + write_compiled_module(co, cpathname, &st, mtime); } } m = PyImport_ExecCodeModuleEx(name, (PyObject *)co, pathname); From 332562f44790556cdd4cb909a3a90052a12a6fc0 Mon Sep 17 00:00:00 2001 From: Andrew Svetlov Date: Mon, 24 Dec 2012 20:09:27 +0200 Subject: [PATCH 09/38] Keep ref to ECHILD in local scope (#16650) --- Lib/subprocess.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/subprocess.py b/Lib/subprocess.py index 104d6ec4d5a..19a51889ea1 100644 --- a/Lib/subprocess.py +++ b/Lib/subprocess.py @@ -1292,7 +1292,7 @@ class Popen(object): def _internal_poll(self, _deadstate=None, _waitpid=os.waitpid, - _WNOHANG=os.WNOHANG, _os_error=os.error): + _WNOHANG=os.WNOHANG, _os_error=os.error, _ECHILD=errno.ECHILD): """Check if child process has terminated. Returns returncode attribute. @@ -1308,7 +1308,7 @@ class Popen(object): except _os_error as e: if _deadstate is not None: self.returncode = _deadstate - if e.errno == errno.ECHILD: + if e.errno == _ECHILD: # This happens if SIGCLD is set to be ignored or # waiting for child processes has otherwise been # disabled for our process. This child is dead, we From 1974baadc62a6c95db9c96fa482377df98ce36cc Mon Sep 17 00:00:00 2001 From: Senthil Kumaran Date: Mon, 24 Dec 2012 13:56:54 -0800 Subject: [PATCH 10/38] Fix issue16713 - tel url parsing with params --- Lib/test/test_urlparse.py | 33 +++++++++++++++++++++++++++++++++ Lib/urlparse.py | 2 +- Misc/NEWS | 2 ++ 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_urlparse.py b/Lib/test/test_urlparse.py index 3f316d385c3..72ebfaa0896 100644 --- a/Lib/test/test_urlparse.py +++ b/Lib/test/test_urlparse.py @@ -446,10 +446,43 @@ class UrlParseTestCase(unittest.TestCase): p1 = urlparse.urlsplit('tel:+31-641044153') self.assertEqual(p1.scheme, 'tel') self.assertEqual(p1.path, '+31-641044153') + p2 = urlparse.urlsplit('tel:+31641044153') self.assertEqual(p2.scheme, 'tel') self.assertEqual(p2.path, '+31641044153') + # Assert for urlparse + p1 = urlparse.urlparse('tel:+31-641044153') + self.assertEqual(p1.scheme, 'tel') + self.assertEqual(p1.path, '+31-641044153') + + p2 = urlparse.urlparse('tel:+31641044153') + self.assertEqual(p2.scheme, 'tel') + self.assertEqual(p2.path, '+31641044153') + + + def test_telurl_params(self): + p1 = urlparse.urlparse('tel:123-4;phone-context=+1-650-516') + self.assertEqual(p1.scheme, 'tel') + self.assertEqual(p1.path, '123-4') + self.assertEqual(p1.params, 'phone-context=+1-650-516') + + p1 = urlparse.urlparse('tel:+1-201-555-0123') + self.assertEqual(p1.scheme, 'tel') + self.assertEqual(p1.path, '+1-201-555-0123') + self.assertEqual(p1.params, '') + + p1 = urlparse.urlparse('tel:7042;phone-context=example.com') + self.assertEqual(p1.scheme, 'tel') + self.assertEqual(p1.path, '7042') + self.assertEqual(p1.params, 'phone-context=example.com') + + p1 = urlparse.urlparse('tel:863-1234;phone-context=+1-914-555') + self.assertEqual(p1.scheme, 'tel') + self.assertEqual(p1.path, '863-1234') + self.assertEqual(p1.params, 'phone-context=+1-914-555') + + def test_attributes_bad_port(self): """Check handling of non-integer ports.""" p = urlparse.urlsplit("http://www.example.net:foo") diff --git a/Lib/urlparse.py b/Lib/urlparse.py index abc53c616a8..f370ce3bdcc 100644 --- a/Lib/urlparse.py +++ b/Lib/urlparse.py @@ -42,7 +42,7 @@ uses_netloc = ['ftp', 'http', 'gopher', 'nntp', 'telnet', 'svn', 'svn+ssh', 'sftp','nfs','git', 'git+ssh'] uses_params = ['ftp', 'hdl', 'prospero', 'http', 'imap', 'https', 'shttp', 'rtsp', 'rtspu', 'sip', 'sips', - 'mms', '', 'sftp'] + 'mms', '', 'sftp', 'tel'] # These are not actually used anymore, but should stay for backwards # compatibility. (They are undocumented, but have a public-looking name.) diff --git a/Misc/NEWS b/Misc/NEWS index 923c6300f9c..58a637455b7 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -164,6 +164,8 @@ Core and Builtins Library ------- +- Issue #16713: Fix the parsing of tel url with params using urlparse module. + - Issue #16443: Add docstrings to regular expression match objects. Patch by Anton Kasyanov. From 94704fc25bd7653c78f01bcb78413a1e516e9e2b Mon Sep 17 00:00:00 2001 From: Ezio Melotti Date: Tue, 25 Dec 2012 14:25:47 +0200 Subject: [PATCH 11/38] #16765: remove unused import. --- Lib/cgi.py | 1 - 1 file changed, 1 deletion(-) diff --git a/Lib/cgi.py b/Lib/cgi.py index e7cd7783164..67079db0d81 100755 --- a/Lib/cgi.py +++ b/Lib/cgi.py @@ -37,7 +37,6 @@ __version__ = "2.6" from operator import attrgetter import sys import os -import urllib import UserDict import urlparse From 513e9b4f610cc4b1edd7d6890d65b05aaba41188 Mon Sep 17 00:00:00 2001 From: Ezio Melotti Date: Tue, 25 Dec 2012 14:45:55 +0200 Subject: [PATCH 12/38] #16666: document default values for socket.getaddrinfo in the text to clarify that it doesn't accept keyword args. --- Doc/library/socket.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Doc/library/socket.rst b/Doc/library/socket.rst index 0e5dac0b777..7e8fb26a270 100644 --- a/Doc/library/socket.rst +++ b/Doc/library/socket.rst @@ -230,7 +230,7 @@ The module :mod:`socket` exports the following constants and functions: *source_address* was added. -.. function:: getaddrinfo(host, port, family=0, socktype=0, proto=0, flags=0) +.. function:: getaddrinfo(host, port[, family[, socktype[, proto[, flags]]]]) Translate the *host*/*port* argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. @@ -240,12 +240,12 @@ The module :mod:`socket` exports the following constants and functions: and *port*, you can pass ``NULL`` to the underlying C API. The *family*, *socktype* and *proto* arguments can be optionally specified - in order to narrow the list of addresses returned. Passing zero as a - value for each of these arguments selects the full range of results. + in order to narrow the list of addresses returned. By default, their value + is ``0``, meaning that the full range of results is selected. The *flags* argument can be one or several of the ``AI_*`` constants, - and will influence how results are computed and returned. - For example, :const:`AI_NUMERICHOST` will disable domain name resolution - and will raise an error if *host* is a domain name. + and will influence how results are computed and returned. Its default value + is ``0``. For example, :const:`AI_NUMERICHOST` will disable domain name + resolution and will raise an error if *host* is a domain name. The function returns a list of 5-tuples with the following structure: From 2380feeff8e574690831d2eb778ca52d3af09b8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristj=C3=A1n=20Valur=20J=C3=B3nsson?= Date: Tue, 25 Dec 2012 13:04:50 +0000 Subject: [PATCH 13/38] issue #879399 Fix line buffering of socket._fileobject --- Lib/socket.py | 4 +-- Lib/test/test_socket.py | 60 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 61 insertions(+), 3 deletions(-) diff --git a/Lib/socket.py b/Lib/socket.py index bd364e70db9..aac04f6ca7a 100644 --- a/Lib/socket.py +++ b/Lib/socket.py @@ -319,8 +319,8 @@ class _fileobject(object): self._wbuf.append(data) self._wbuf_len += len(data) if (self._wbufsize == 0 or - self._wbufsize == 1 and '\n' in data or - self._wbuf_len >= self._wbufsize): + (self._wbufsize == 1 and '\n' in data) or + (self._wbufsize > 1 and self._wbuf_len >= self._wbufsize)): self.flush() def writelines(self, list): diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py index 053c6fe7be5..fec62efe038 100644 --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -962,8 +962,8 @@ class FileObjectClassTestCase(SocketConnectedTest): def tearDown(self): self.serv_file.close() self.assertTrue(self.serv_file.closed) - self.serv_file = None SocketConnectedTest.tearDown(self) + self.serv_file = None def clientSetUp(self): SocketConnectedTest.clientSetUp(self) @@ -1151,6 +1151,64 @@ class LineBufferedFileObjectClassTestCase(FileObjectClassTestCase): bufsize = 1 # Default-buffered for reading; line-buffered for writing + class SocketMemo(object): + """A wrapper to keep track of sent data, needed to examine write behaviour""" + def __init__(self, sock): + self._sock = sock + self.sent = [] + + def send(self, data, flags=0): + n = self._sock.send(data, flags) + self.sent.append(data[:n]) + return n + + def sendall(self, data, flags=0): + self._sock.sendall(data, flags) + self.sent.append(data) + + def __getattr__(self, attr): + return getattr(self._sock, attr) + + def getsent(self): + return [e.tobytes() if isinstance(e, memoryview) else e for e in self.sent] + + def setUp(self): + FileObjectClassTestCase.setUp(self) + self.serv_file._sock = self.SocketMemo(self.serv_file._sock) + + def testLinebufferedWrite(self): + # Write two lines, in small chunks + msg = MSG.strip() + print >> self.serv_file, msg, + print >> self.serv_file, msg + + # second line: + print >> self.serv_file, msg, + print >> self.serv_file, msg, + print >> self.serv_file, msg + + # third line + print >> self.serv_file, '' + + self.serv_file.flush() + + msg1 = "%s %s\n"%(msg, msg) + msg2 = "%s %s %s\n"%(msg, msg, msg) + msg3 = "\n" + self.assertEqual(self.serv_file._sock.getsent(), [msg1, msg2, msg3]) + + def _testLinebufferedWrite(self): + msg = MSG.strip() + msg1 = "%s %s\n"%(msg, msg) + msg2 = "%s %s %s\n"%(msg, msg, msg) + msg3 = "\n" + l1 = self.cli_file.readline() + self.assertEqual(l1, msg1) + l2 = self.cli_file.readline() + self.assertEqual(l2, msg2) + l3 = self.cli_file.readline() + self.assertEqual(l3, msg3) + class SmallBufferedFileObjectClassTestCase(FileObjectClassTestCase): From 4268b3a751bb94da6bc2438a17c26cc3f88e32a8 Mon Sep 17 00:00:00 2001 From: Ezio Melotti Date: Tue, 25 Dec 2012 15:45:15 +0200 Subject: [PATCH 14/38] #16677: rename section header and fix markup. --- Doc/reference/expressions.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Doc/reference/expressions.rst b/Doc/reference/expressions.rst index bc9f1b4b3a8..e5955bfa555 100644 --- a/Doc/reference/expressions.rst +++ b/Doc/reference/expressions.rst @@ -1339,8 +1339,8 @@ their suffixes:: .. _operator-summary: -Summary -======= +Operator precedence +=================== .. index:: pair: operator; precedence @@ -1363,9 +1363,9 @@ groups from right to left). +-----------------------------------------------+-------------------------------------+ | :keyword:`and` | Boolean AND | +-----------------------------------------------+-------------------------------------+ -| :keyword:`not` *x* | Boolean NOT | +| :keyword:`not` ``x`` | Boolean NOT | +-----------------------------------------------+-------------------------------------+ -| :keyword:`in`, :keyword:`not` :keyword:`in`, | Comparisons, including membership | +| :keyword:`in`, :keyword:`not in`, | Comparisons, including membership | | :keyword:`is`, :keyword:`is not`, ``<``, | tests and identity tests, | | ``<=``, ``>``, ``>=``, ``<>``, ``!=``, ``==`` | | +-----------------------------------------------+-------------------------------------+ @@ -1391,7 +1391,7 @@ groups from right to left). +-----------------------------------------------+-------------------------------------+ | ``(expressions...)``, | Binding or tuple display, | | ``[expressions...]``, | list display, | -| ``{key:datum...}``, | dictionary display, | +| ``{key: value...}``, | dictionary display, | | ```expressions...``` | string conversion | +-----------------------------------------------+-------------------------------------+ From 3b65a9eeed7d960dd0e41ddc8773a2e0daf5ebf8 Mon Sep 17 00:00:00 2001 From: Ezio Melotti Date: Tue, 25 Dec 2012 18:10:49 +0200 Subject: [PATCH 15/38] #16760: use ref:`match-objects` instead of :class:`MatchObject`. --- Doc/howto/regex.rst | 49 +++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/Doc/howto/regex.rst b/Doc/howto/regex.rst index 95b0d04364a..2f552e39a1c 100644 --- a/Doc/howto/regex.rst +++ b/Doc/howto/regex.rst @@ -359,9 +359,9 @@ for a complete listing. +------------------+-----------------------------------------------+ :meth:`match` and :meth:`search` return ``None`` if no match can be found. If -they're successful, a ``MatchObject`` instance is returned, containing -information about the match: where it starts and ends, the substring it matched, -and more. +they're successful, a :ref:`match object ` instance is returned, +containing information about the match: where it starts and ends, the substring +it matched, and more. You can learn about this by interactively experimenting with the :mod:`re` module. If you have Tkinter available, you may also want to look at @@ -392,16 +392,16 @@ interpreter to print no output. You can explicitly print the result of None Now, let's try it on a string that it should match, such as ``tempo``. In this -case, :meth:`match` will return a :class:`MatchObject`, so you should store the -result in a variable for later use. :: +case, :meth:`match` will return a :ref:`match object `, so you +should store the result in a variable for later use. :: >>> m = p.match('tempo') >>> m #doctest: +ELLIPSIS <_sre.SRE_Match object at 0x...> -Now you can query the :class:`MatchObject` for information about the matching -string. :class:`MatchObject` instances also have several methods and -attributes; the most important ones are: +Now you can query the :ref:`match object ` for information +about the matching string. :ref:`match object ` instances +also have several methods and attributes; the most important ones are: +------------------+--------------------------------------------+ | Method/Attribute | Purpose | @@ -442,8 +442,9 @@ case. :: >>> m.span() (4, 11) -In actual programs, the most common style is to store the :class:`MatchObject` -in a variable, and then check if it was ``None``. This usually looks like:: +In actual programs, the most common style is to store the +:ref:`match object ` in a variable, and then check if it was +``None``. This usually looks like:: p = re.compile( ... ) m = p.match( 'string goes here' ) @@ -460,8 +461,8 @@ Two pattern methods return all of the matches for a pattern. ['12', '11', '10'] :meth:`findall` has to create the entire list before it can be returned as the -result. The :meth:`finditer` method returns a sequence of :class:`MatchObject` -instances as an :term:`iterator`. [#]_ :: +result. The :meth:`finditer` method returns a sequence of +:ref:`match object ` instances as an :term:`iterator`. [#]_ :: >>> iterator = p.finditer('12 drummers drumming, 11 ... 10 ...') >>> iterator #doctest: +ELLIPSIS @@ -482,7 +483,7 @@ You don't have to create a pattern object and call its methods; the :func:`search`, :func:`findall`, :func:`sub`, and so forth. These functions take the same arguments as the corresponding pattern method, with the RE string added as the first argument, and still return either ``None`` or a -:class:`MatchObject` instance. :: +:ref:`match object ` instance. :: >>> print re.match(r'From\s+', 'Fromage amk') None @@ -791,9 +792,9 @@ Groups indicated with ``'('``, ``')'`` also capture the starting and ending index of the text that they match; this can be retrieved by passing an argument to :meth:`group`, :meth:`start`, :meth:`end`, and :meth:`span`. Groups are numbered starting with 0. Group 0 is always present; it's the whole RE, so -:class:`MatchObject` methods all have group 0 as their default argument. Later -we'll see how to express groups that don't capture the span of text that they -match. :: +:ref:`match object ` methods all have group 0 as their default +argument. Later we'll see how to express groups that don't capture the span +of text that they match. :: >>> p = re.compile('(a)b') >>> m = p.match('ab') @@ -913,10 +914,10 @@ numbers, groups can be referenced by a name. The syntax for a named group is one of the Python-specific extensions: ``(?P...)``. *name* is, obviously, the name of the group. Named groups also behave exactly like capturing groups, and additionally associate a name -with a group. The :class:`MatchObject` methods that deal with capturing groups -all accept either integers that refer to the group by number or strings that -contain the desired group's name. Named groups are still given numbers, so you -can retrieve information about a group in two ways:: +with a group. The :ref:`match object ` methods that deal with +capturing groups all accept either integers that refer to the group by number +or strings that contain the desired group's name. Named groups are still +given numbers, so you can retrieve information about a group in two ways:: >>> p = re.compile(r'(?P\b\w+\b)') >>> m = p.search( '(((( Lots of punctuation )))' ) @@ -1180,11 +1181,11 @@ three variations of the replacement string. :: *replacement* can also be a function, which gives you even more control. If *replacement* is a function, the function is called for every non-overlapping -occurrence of *pattern*. On each call, the function is passed a -:class:`MatchObject` argument for the match and can use this information to -compute the desired replacement string and return it. +occurrence of *pattern*. On each call, the function is passed a +:ref:`match object ` argument for the match and can use this +information to compute the desired replacement string and return it. -In the following example, the replacement function translates decimals into +In the following example, the replacement function translates decimals into hexadecimal:: >>> def hexrepl(match): From c08ded9e4a3073e6f6315d0fa462debdb6d28304 Mon Sep 17 00:00:00 2001 From: Andrew Svetlov Date: Tue, 25 Dec 2012 18:50:03 +0200 Subject: [PATCH 16/38] rename MathcObject to match object in doctrings for re module (#16760) --- Modules/_sre.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/_sre.c b/Modules/_sre.c index 16e0303a276..8f47688d410 100644 --- a/Modules/_sre.c +++ b/Modules/_sre.c @@ -2546,7 +2546,7 @@ PyDoc_STRVAR(pattern_match_doc, PyDoc_STRVAR(pattern_search_doc, "search(string[, pos[, endpos]]) --> match object or None.\n\ Scan through string looking for a match, and return a corresponding\n\ - MatchObject instance. Return None if no position in the string matches."); + match object instance. Return None if no position in the string matches."); PyDoc_STRVAR(pattern_split_doc, "split(string[, maxsplit = 0]) --> list.\n\ From b0d1c37d737742eb098b985475987f460a13a6c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristj=C3=A1n=20Valur=20J=C3=B3nsson?= Date: Tue, 25 Dec 2012 22:46:32 +0000 Subject: [PATCH 17/38] Issue #14574: Ignore socket errors raised when flushing a connection on close. --- Doc/library/socketserver.rst | 4 ++-- Lib/SocketServer.py | 7 ++++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/Doc/library/socketserver.rst b/Doc/library/socketserver.rst index c34b4868066..d225392ba35 100644 --- a/Doc/library/socketserver.rst +++ b/Doc/library/socketserver.rst @@ -306,8 +306,8 @@ request. .. method:: RequestHandler.finish() Called after the :meth:`handle` method to perform any clean-up actions - required. The default implementation does nothing. If :meth:`setup` or - :meth:`handle` raise an exception, this function will not be called. + required. The default implementation does nothing. If :meth:`setup` + raises an exception, this function will not be called. .. method:: RequestHandler.handle() diff --git a/Lib/SocketServer.py b/Lib/SocketServer.py index 1594321909c..26611b74d1f 100644 --- a/Lib/SocketServer.py +++ b/Lib/SocketServer.py @@ -701,7 +701,12 @@ class StreamRequestHandler(BaseRequestHandler): def finish(self): if not self.wfile.closed: - self.wfile.flush() + try: + self.wfile.flush() + except socket.error: + # An final socket error may have occurred here, such as + # the local error ECONNABORTED. + pass self.wfile.close() self.rfile.close() From cf4710c3234f77d68e57bf8fe2d9ca4e96a8b085 Mon Sep 17 00:00:00 2001 From: Chris Jerdonek Date: Tue, 25 Dec 2012 14:50:21 -0800 Subject: [PATCH 18/38] Add additional links and index entries for "argument" and "parameter". This adds to the work done for issue #15990 (i.e. f44b8d69e5fc and the commits referenced there). --- Doc/faq/programming.rst | 4 ++++ Doc/glossary.rst | 5 +++-- Doc/reference/compound_stmts.rst | 16 +++++++++++----- Doc/reference/expressions.rst | 18 +++++++++++------- 4 files changed, 29 insertions(+), 14 deletions(-) diff --git a/Doc/faq/programming.rst b/Doc/faq/programming.rst index 8e218c0029c..edee68af140 100644 --- a/Doc/faq/programming.rst +++ b/Doc/faq/programming.rst @@ -469,6 +469,10 @@ In the unlikely case that you care about Python versions older than 2.0, use apply(g, (x,)+args, kwargs) +.. index:: + single: argument; difference from parameter + single: parameter; difference from argument + .. _faq-argument-vs-parameter: What is the difference between arguments and parameters? diff --git a/Doc/glossary.rst b/Doc/glossary.rst index e742336d293..392a60cd94c 100644 --- a/Doc/glossary.rst +++ b/Doc/glossary.rst @@ -245,8 +245,9 @@ Glossary function A series of statements which returns some value to a caller. It can also - be passed zero or more arguments which may be used in the execution of - the body. See also :term:`argument` and :term:`method`. + be passed zero or more :term:`arguments ` which may be used in + the execution of the body. See also :term:`parameter`, :term:`method`, + and the :ref:`function` section. __future__ A pseudo-module which programmers can use to enable new language features diff --git a/Doc/reference/compound_stmts.rst b/Doc/reference/compound_stmts.rst index a86eb11f880..4a616eb7a9b 100644 --- a/Doc/reference/compound_stmts.rst +++ b/Doc/reference/compound_stmts.rst @@ -407,6 +407,9 @@ is equivalent to :: statement. +.. index:: + single: parameter; function definition + .. _function: .. _def: @@ -467,12 +470,15 @@ is equivalent to:: def func(): pass func = f1(arg)(f2(func)) -.. index:: triple: default; parameter; value +.. index:: + triple: default; parameter; value + single: argument; function definition -When one or more top-level parameters have the form *parameter* ``=`` -*expression*, the function is said to have "default parameter values." For a -parameter with a default value, the corresponding argument may be omitted from a -call, in which case the parameter's default value is substituted. If a +When one or more top-level :term:`parameters ` have the form +*parameter* ``=`` *expression*, the function is said to have "default parameter +values." For a parameter with a default value, the corresponding +:term:`argument` may be omitted from a call, in which +case the parameter's default value is substituted. If a parameter has a default value, all following parameters must also have a default value --- this is a syntactic restriction that is not expressed by the grammar. diff --git a/Doc/reference/expressions.rst b/Doc/reference/expressions.rst index e5955bfa555..812fb70ed2a 100644 --- a/Doc/reference/expressions.rst +++ b/Doc/reference/expressions.rst @@ -667,17 +667,18 @@ upper bound and stride, respectively, substituting ``None`` for missing expressions. +.. index:: + object: callable + single: call + single: argument; call semantics + .. _calls: Calls ----- -.. index:: single: call - -.. index:: object: callable - -A call calls a callable object (e.g., a function) with a possibly empty series -of arguments: +A call calls a callable object (e.g., a :term:`function`) with a possibly empty +series of :term:`arguments `: .. productionlist:: call: `primary` "(" [`argument_list` [","] @@ -696,12 +697,15 @@ of arguments: A trailing comma may be present after the positional and keyword arguments but does not affect the semantics. +.. index:: + single: parameter; call semantics + The primary must evaluate to a callable object (user-defined functions, built-in functions, methods of built-in objects, class objects, methods of class instances, and certain class instances themselves are callable; extensions may define additional callable object types). All argument expressions are evaluated before the call is attempted. Please refer to section :ref:`function` -for the syntax of formal parameter lists. +for the syntax of formal :term:`parameter` lists. If keyword arguments are present, they are first converted to positional arguments, as follows. First, a list of unfilled slots is created for the From 2f01e239cb67d7d72d08e2b6f1a7c7769ee41b25 Mon Sep 17 00:00:00 2001 From: Senthil Kumaran Date: Wed, 26 Dec 2012 01:45:22 -0800 Subject: [PATCH 19/38] Issue #16702: Skip proxies for localhost in urllib2_localnet tests --- Lib/test/test_urllib2_localnet.py | 8 ++++++++ Misc/NEWS | 3 +++ 2 files changed, 11 insertions(+) diff --git a/Lib/test/test_urllib2_localnet.py b/Lib/test/test_urllib2_localnet.py index 0fda7709017..ec3437597d8 100644 --- a/Lib/test/test_urllib2_localnet.py +++ b/Lib/test/test_urllib2_localnet.py @@ -5,7 +5,9 @@ import urllib2 import BaseHTTPServer import unittest import hashlib + from test import test_support + mimetools = test_support.import_module('mimetools', deprecated=True) threading = test_support.import_module('threading') @@ -346,6 +348,12 @@ class TestUrlopen(BaseTestCase): for transparent redirection have been written. """ + def setUp(self): + proxy_handler = urllib2.ProxyHandler({}) + opener = urllib2.build_opener(proxy_handler) + urllib2.install_opener(opener) + super(TestUrlopen, self).setUp() + def start_server(self, responses): handler = GetRequestHandler(responses) diff --git a/Misc/NEWS b/Misc/NEWS index 58a637455b7..381b0915942 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -164,6 +164,9 @@ Core and Builtins Library ------- +- Issue #16702: test_urllib2_localnet tests now correctly ignores proxies for + localhost tests. + - Issue #16713: Fix the parsing of tel url with params using urlparse module. - Issue #16443: Add docstrings to regular expression match objects. From 4947049b40f6ca304bce5bef3dcbac23e9ed54e1 Mon Sep 17 00:00:00 2001 From: Jesus Cea Date: Wed, 26 Dec 2012 16:46:04 +0100 Subject: [PATCH 20/38] Closes #16789: :meth:`quit` links to constants instead of own module --- Doc/library/ftplib.rst | 8 ++++---- Doc/library/poplib.rst | 2 +- Doc/library/smtplib.rst | 3 ++- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/Doc/library/ftplib.rst b/Doc/library/ftplib.rst index b8f5b4e6959..988278952b5 100644 --- a/Doc/library/ftplib.rst +++ b/Doc/library/ftplib.rst @@ -370,10 +370,10 @@ followed by ``lines`` for the text version or ``binary`` for the binary version. .. method:: FTP.close() Close the connection unilaterally. This should not be applied to an already - closed connection such as after a successful call to :meth:`quit`. After this - call the :class:`FTP` instance should not be used any more (after a call to - :meth:`close` or :meth:`quit` you cannot reopen the connection by issuing - another :meth:`login` method). + closed connection such as after a successful call to :meth:`~FTP.quit`. + After this call the :class:`FTP` instance should not be used any more (after + a call to :meth:`close` or :meth:`~FTP.quit` you cannot reopen the + connection by issuing another :meth:`login` method). FTP_TLS Objects diff --git a/Doc/library/poplib.rst b/Doc/library/poplib.rst index ca77e6e8653..07c243fde93 100644 --- a/Doc/library/poplib.rst +++ b/Doc/library/poplib.rst @@ -102,7 +102,7 @@ An :class:`POP3` instance has the following methods: .. method:: POP3.pass_(password) Send password, response includes message count and mailbox size. Note: the - mailbox on the server is locked until :meth:`quit` is called. + mailbox on the server is locked until :meth:`~poplib.quit` is called. .. method:: POP3.apop(user, secret) diff --git a/Doc/library/smtplib.rst b/Doc/library/smtplib.rst index b0b58e8e8a1..044bbde28b8 100644 --- a/Doc/library/smtplib.rst +++ b/Doc/library/smtplib.rst @@ -32,7 +32,8 @@ Protocol) and :rfc:`1869` (SMTP Service Extensions). setting will be used). For normal use, you should only require the initialization/connect, - :meth:`sendmail`, and :meth:`quit` methods. An example is included below. + :meth:`sendmail`, and :meth:`~smtplib.quit` methods. + An example is included below. .. versionchanged:: 2.6 *timeout* was added. From 4a5a4c28085910c6a40e40f01d763d55f5190e38 Mon Sep 17 00:00:00 2001 From: Hynek Schlawack Date: Thu, 27 Dec 2012 10:24:21 +0100 Subject: [PATCH 21/38] #16618: Add more glob regression tests Mostly about symlinks and str/unicode behavior. Patch by Serhiy Storchaka. --- Lib/test/test_glob.py | 99 +++++++++++++++++++++++++++++++++---------- Misc/NEWS | 3 ++ 2 files changed, 79 insertions(+), 23 deletions(-) diff --git a/Lib/test/test_glob.py b/Lib/test/test_glob.py index fee3a60a7e6..b360d09dfa6 100644 --- a/Lib/test/test_glob.py +++ b/Lib/test/test_glob.py @@ -1,9 +1,14 @@ -import unittest -from test.test_support import run_unittest, TESTFN import glob import os import shutil import sys +import unittest + +from test.test_support import run_unittest, TESTFN + + +def fsdecode(s): + return unicode(s, sys.getfilesystemencoding()) class GlobTests(unittest.TestCase): @@ -31,7 +36,8 @@ class GlobTests(unittest.TestCase): self.mktemp('a', 'bcd', 'efg', 'ha') if hasattr(os, 'symlink'): os.symlink(self.norm('broken'), self.norm('sym1')) - os.symlink(self.norm('broken'), self.norm('sym2')) + os.symlink('broken', self.norm('sym2')) + os.symlink(os.path.join('a', 'bcd'), self.norm('sym3')) def tearDown(self): shutil.rmtree(self.tempdir) @@ -44,10 +50,16 @@ class GlobTests(unittest.TestCase): p = os.path.join(self.tempdir, pattern) res = glob.glob(p) self.assertEqual(list(glob.iglob(p)), res) + ures = [fsdecode(x) for x in res] + self.assertEqual(glob.glob(fsdecode(p)), ures) + self.assertEqual(list(glob.iglob(fsdecode(p))), ures) return res def assertSequencesEqual_noorder(self, l1, l2): + l1 = list(l1) + l2 = list(l2) self.assertEqual(set(l1), set(l2)) + self.assertEqual(sorted(l1), sorted(l2)) def test_glob_literal(self): eq = self.assertSequencesEqual_noorder @@ -56,15 +68,19 @@ class GlobTests(unittest.TestCase): eq(self.glob('aab'), [self.norm('aab')]) eq(self.glob('zymurgy'), []) + res = glob.glob('*') + self.assertEqual({type(r) for r in res}, {str}) + res = glob.glob(os.path.join(os.curdir, '*')) + self.assertEqual({type(r) for r in res}, {str}) + # test return types are unicode, but only if os.listdir # returns unicode filenames - uniset = set([unicode]) - tmp = os.listdir(u'.') - if set(type(x) for x in tmp) == uniset: - u1 = glob.glob(u'*') - u2 = glob.glob(u'./*') - self.assertEqual(set(type(r) for r in u1), uniset) - self.assertEqual(set(type(r) for r in u2), uniset) + tmp = os.listdir(fsdecode(os.curdir)) + if {type(x) for x in tmp} == {unicode}: + res = glob.glob(u'*') + self.assertEqual({type(r) for r in res}, {unicode}) + res = glob.glob(os.path.join(fsdecode(os.curdir), u'*')) + self.assertEqual({type(r) for r in res}, {unicode}) def test_glob_one_directory(self): eq = self.assertSequencesEqual_noorder @@ -93,23 +109,60 @@ class GlobTests(unittest.TestCase): eq(self.glob('*', '*a'), []) eq(self.glob('a', '*', '*', '*a'), [self.norm('a', 'bcd', 'efg', 'ha')]) - eq(self.glob('?a?', '*F'), map(self.norm, [os.path.join('aaa', 'zzzF'), - os.path.join('aab', 'F')])) + eq(self.glob('?a?', '*F'), [self.norm('aaa', 'zzzF'), + self.norm('aab', 'F')]) def test_glob_directory_with_trailing_slash(self): - # We are verifying that when there is wildcard pattern which - # ends with os.sep doesn't blow up. - res = glob.glob(self.tempdir + '*' + os.sep) - self.assertEqual(len(res), 1) - # either of these results are reasonable - self.assertIn(res[0], [self.tempdir, self.tempdir + os.sep]) + # Patterns ending with a slash shouldn't match non-dirs + res = glob.glob(self.norm('Z*Z') + os.sep) + self.assertEqual(res, []) + res = glob.glob(self.norm('ZZZ') + os.sep) + self.assertEqual(res, []) + # When there is a wildcard pattern which ends with os.sep, glob() + # doesn't blow up. + res = glob.glob(self.norm('aa*') + os.sep) + self.assertEqual(len(res), 2) + # either of these results is reasonable + self.assertIn(set(res), [ + {self.norm('aaa'), self.norm('aab')}, + {self.norm('aaa') + os.sep, self.norm('aab') + os.sep}, + ]) + def test_glob_unicode_directory_with_trailing_slash(self): + # Same as test_glob_directory_with_trailing_slash, but with an + # unicode argument. + res = glob.glob(fsdecode(self.norm('Z*Z') + os.sep)) + self.assertEqual(res, []) + res = glob.glob(fsdecode(self.norm('ZZZ') + os.sep)) + self.assertEqual(res, []) + res = glob.glob(fsdecode(self.norm('aa*') + os.sep)) + self.assertEqual(len(res), 2) + # either of these results is reasonable + self.assertIn(set(res), [ + {fsdecode(self.norm('aaa')), fsdecode(self.norm('aab'))}, + {fsdecode(self.norm('aaa') + os.sep), + fsdecode(self.norm('aab') + os.sep)}, + ]) + + @unittest.skipUnless(hasattr(os, 'symlink'), "Requires symlink support") + def test_glob_symlinks(self): + eq = self.assertSequencesEqual_noorder + eq(self.glob('sym3'), [self.norm('sym3')]) + eq(self.glob('sym3', '*'), [self.norm('sym3', 'EF'), + self.norm('sym3', 'efg')]) + self.assertIn(self.glob('sym3' + os.sep), + [[self.norm('sym3')], [self.norm('sym3') + os.sep]]) + eq(self.glob('*', '*F'), + [self.norm('aaa', 'zzzF'), self.norm('aab', 'F'), + self.norm('sym3', 'EF')]) + + @unittest.skipUnless(hasattr(os, 'symlink'), "Requires symlink support") def test_glob_broken_symlinks(self): - if hasattr(os, 'symlink'): - eq = self.assertSequencesEqual_noorder - eq(self.glob('sym*'), [self.norm('sym1'), self.norm('sym2')]) - eq(self.glob('sym1'), [self.norm('sym1')]) - eq(self.glob('sym2'), [self.norm('sym2')]) + eq = self.assertSequencesEqual_noorder + eq(self.glob('sym*'), [self.norm('sym1'), self.norm('sym2'), + self.norm('sym3')]) + eq(self.glob('sym1'), [self.norm('sym1')]) + eq(self.glob('sym2'), [self.norm('sym2')]) @unittest.skipUnless(sys.platform == "win32", "Win32 specific test") def test_glob_magic_in_drive(self): diff --git a/Misc/NEWS b/Misc/NEWS index 381b0915942..7642e6067a1 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -574,6 +574,9 @@ Extension Modules Tests ----- +- Issue #16618: Add more regression tests for glob. + Patch by Serhiy Storchaka. + - Issue #16664: Add regression tests for glob's behaviour concerning entries starting with a ".". Patch by Sebastian Kreft. From 0e091b036503adc1c46022dbf974bb2f64ceed17 Mon Sep 17 00:00:00 2001 From: Brian Curtin Date: Thu, 27 Dec 2012 12:28:51 -0600 Subject: [PATCH 22/38] Fix #14420. Check for PyLong as well as PyInt when converting in Py2Reg. This fixes a ValueError seen in winreg.SetValueEx when passed long winreg.REG_DWORD values that should be supported by the underlying API. --- Lib/test/test_winreg.py | 12 ++++++++++++ Misc/NEWS | 4 ++++ PC/_winreg.c | 11 ++++++----- 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/Lib/test/test_winreg.py b/Lib/test/test_winreg.py index a741b65e07f..c4ae73746ca 100644 --- a/Lib/test/test_winreg.py +++ b/Lib/test/test_winreg.py @@ -314,6 +314,18 @@ class LocalWinregTests(BaseWinregTests): finally: DeleteKey(HKEY_CURRENT_USER, test_key_name) + def test_setvalueex_value_range(self): + # Test for Issue #14420, accept proper ranges for SetValueEx. + # Py2Reg, which gets called by SetValueEx, was using PyLong_AsLong, + # thus raising OverflowError. The implementation now uses + # PyLong_AsUnsignedLong to match DWORD's size. + try: + with CreateKey(HKEY_CURRENT_USER, test_key_name) as ck: + self.assertNotEqual(ck.handle, 0) + SetValueEx(ck, "test_name", None, REG_DWORD, 0x80000000) + finally: + DeleteKey(HKEY_CURRENT_USER, test_key_name) + @unittest.skipUnless(REMOTE_NAME, "Skipping remote registry tests") class RemoteWinregTests(BaseWinregTests): diff --git a/Misc/NEWS b/Misc/NEWS index 7642e6067a1..ea9e6bf0528 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -9,6 +9,10 @@ What's New in Python 2.7.4 Core and Builtins ----------------- +- Issue #14420: Support the full DWORD (unsigned long) range in Py2Reg + when passed a REG_DWORD value. Fixes ValueError in winreg.SetValueEx when + given a long. + - Issue #13863: Work around buggy 'fstat' implementation on Windows / NTFS that lead to incorrect timestamps (off by one hour) being stored in .pyc files on some systems. diff --git a/PC/_winreg.c b/PC/_winreg.c index 445c3edd76e..813e99383ad 100644 --- a/PC/_winreg.c +++ b/PC/_winreg.c @@ -753,7 +753,8 @@ Py2Reg(PyObject *value, DWORD typ, BYTE **retDataBuf, DWORD *retDataSize) Py_ssize_t i,j; switch (typ) { case REG_DWORD: - if (value != Py_None && !PyInt_Check(value)) + if (value != Py_None && + !(PyInt_Check(value) || PyLong_Check(value))) return FALSE; *retDataBuf = (BYTE *)PyMem_NEW(DWORD, 1); if (*retDataBuf==NULL){ @@ -765,10 +766,10 @@ Py2Reg(PyObject *value, DWORD typ, BYTE **retDataBuf, DWORD *retDataSize) DWORD zero = 0; memcpy(*retDataBuf, &zero, sizeof(DWORD)); } - else - memcpy(*retDataBuf, - &PyInt_AS_LONG((PyIntObject *)value), - sizeof(DWORD)); + else { + DWORD d = PyLong_AsUnsignedLong(value); + memcpy(*retDataBuf, &d, sizeof(DWORD)); + } break; case REG_SZ: case REG_EXPAND_SZ: From 61006a211339f592dcb60f20ee7e478ad012556d Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Thu, 27 Dec 2012 21:34:23 +0200 Subject: [PATCH 23/38] Issue #16504: Catch SyntaxErrors raised by tokenizer in IDLE. --- Lib/idlelib/EditorWindow.py | 2 +- Misc/NEWS | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Lib/idlelib/EditorWindow.py b/Lib/idlelib/EditorWindow.py index efd3c54d9a3..0a01c9ec305 100644 --- a/Lib/idlelib/EditorWindow.py +++ b/Lib/idlelib/EditorWindow.py @@ -1611,7 +1611,7 @@ class IndentSearcher(object): try: try: _tokenize.tokenize(self.readline, self.tokeneater) - except _tokenize.TokenError: + except (_tokenize.TokenError, SyntaxError): # since we cut off the tokenizer early, we can trigger # spurious errors pass diff --git a/Misc/NEWS b/Misc/NEWS index 7642e6067a1..9429d4e6650 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -164,6 +164,9 @@ Core and Builtins Library ------- +- Issue #16504: IDLE now catches SyntaxErrors raised by tokenizer. Patch by + Roger Serwy. + - Issue #16702: test_urllib2_localnet tests now correctly ignores proxies for localhost tests. From 33e05e7905c00f601e4d1fea9ec0df0b3b9cb39c Mon Sep 17 00:00:00 2001 From: Brian Curtin Date: Thu, 27 Dec 2012 14:37:06 -0600 Subject: [PATCH 24/38] Fix #16759. Convert DWORD registry values using unsigned long. When converting REG_DWORD registry values into Python, the conversion needs to be made from an *unsigned* long (k instead of i) to match the DWORD type. --- Lib/test/test_winreg.py | 17 +++++++++++++++++ Misc/NEWS | 4 ++++ PC/_winreg.c | 4 ++-- 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_winreg.py b/Lib/test/test_winreg.py index c4ae73746ca..2799e194802 100644 --- a/Lib/test/test_winreg.py +++ b/Lib/test/test_winreg.py @@ -326,6 +326,23 @@ class LocalWinregTests(BaseWinregTests): finally: DeleteKey(HKEY_CURRENT_USER, test_key_name) + def test_queryvalueex_return_value(self): + # Test for Issue #16759, return unsigned int from QueryValueEx. + # Reg2Py, which gets called by QueryValueEx, was returning a value + # generated by PyLong_FromLong. The implmentation now uses + # PyLong_FromUnsignedLong to match DWORD's size. + try: + with CreateKey(HKEY_CURRENT_USER, test_key_name) as ck: + self.assertNotEqual(ck.handle, 0) + test_val = 0x80000000 + SetValueEx(ck, "test_name", None, REG_DWORD, test_val) + ret_val, ret_type = QueryValueEx(ck, "test_name") + self.assertEqual(ret_type, REG_DWORD) + self.assertEqual(ret_val, test_val) + finally: + DeleteKey(HKEY_CURRENT_USER, test_key_name) + + @unittest.skipUnless(REMOTE_NAME, "Skipping remote registry tests") class RemoteWinregTests(BaseWinregTests): diff --git a/Misc/NEWS b/Misc/NEWS index 9f8c89a15f9..6c0e000f59c 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -9,6 +9,10 @@ What's New in Python 2.7.4 Core and Builtins ----------------- +- Issue #16759: Support the full DWORD (unsigned long) range in Reg2Py + when retreiving a REG_DWORD value. This corrects functions like + winreg.QueryValueEx that may have been returning truncated values. + - Issue #14420: Support the full DWORD (unsigned long) range in Py2Reg when passed a REG_DWORD value. Fixes ValueError in winreg.SetValueEx when given a long. diff --git a/PC/_winreg.c b/PC/_winreg.c index 813e99383ad..d60b1511929 100644 --- a/PC/_winreg.c +++ b/PC/_winreg.c @@ -918,9 +918,9 @@ Reg2Py(char *retDataBuf, DWORD retDataSize, DWORD typ) switch (typ) { case REG_DWORD: if (retDataSize == 0) - obData = Py_BuildValue("i", 0); + obData = Py_BuildValue("k", 0); else - obData = Py_BuildValue("i", + obData = Py_BuildValue("k", *(int *)retDataBuf); break; case REG_SZ: From 6f70fe804690bbfea9caefe1ba01029aa1abf0eb Mon Sep 17 00:00:00 2001 From: Chris Jerdonek Date: Thu, 27 Dec 2012 12:53:29 -0800 Subject: [PATCH 25/38] Issue #16790: add some of the recent issue #16045 int tests to test_long. This patch also provides a simple way to share tests going forward between test_int and test_long. --- Lib/test/test_int.py | 29 +++++++++++++++++++---------- Lib/test/test_long.py | 6 ++++-- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/Lib/test/test_int.py b/Lib/test/test_int.py index 88627017e5b..045ef7c76ad 100644 --- a/Lib/test/test_int.py +++ b/Lib/test/test_int.py @@ -45,7 +45,25 @@ if have_unicode: (unichr(0x200), ValueError), ] -class IntTestCases(unittest.TestCase): +class IntLongCommonTests(object): + + """Mixin of test cases to share between both test_int and test_long.""" + + # Change to int or long in the TestCase subclass. + ntype = None + + def test_no_args(self): + self.assertEqual(self.ntype(), 0) + + def test_keyword_args(self): + # Test invoking constructor using keyword arguments. + self.assertEqual(self.ntype(x=1.2), 1) + self.assertEqual(self.ntype('100', base=2), 4) + self.assertEqual(self.ntype(x='100', base=2), 4) + +class IntTestCases(IntLongCommonTests, unittest.TestCase): + + ntype = int def test_basic(self): self.assertEqual(int(314), 314) @@ -316,15 +334,6 @@ class IntTestCases(unittest.TestCase): self.assertEqual(int(float(2**54+10)), 2**54+8) self.assertEqual(int(float(2**54+11)), 2**54+12) - def test_no_args(self): - self.assertEquals(int(), 0) - - def test_keyword_args(self): - # Test invoking int() using keyword arguments. - self.assertEquals(int(x=1.2), 1) - self.assertEquals(int('100', base=2), 4) - self.assertEquals(int(x='100', base=2), 4) - def test_valid_non_numeric_input_types_for_x(self): # Test possible valid non-numeric types for x, including subclasses # of the allowed built-in types. diff --git a/Lib/test/test_long.py b/Lib/test/test_long.py index 58cfc3a2a33..f0847e7ab43 100644 --- a/Lib/test/test_long.py +++ b/Lib/test/test_long.py @@ -1,10 +1,11 @@ import unittest -from test import test_support import sys import random import math +from test import test_int, test_support + # Used for lazy formatting of failure messages class Frm(object): def __init__(self, format, *args): @@ -78,8 +79,9 @@ if test_support.have_unicode: (unichr(0x200), ValueError), ] +class LongTest(test_int.IntLongCommonTests, unittest.TestCase): -class LongTest(unittest.TestCase): + ntype = long # Get quasi-random long consisting of ndigits digits (in base BASE). # quasi == the most-significant digit will not be 0, and the number From 270767b2ceb5452d052b280eb1b174d7a32d43f5 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Thu, 27 Dec 2012 23:07:00 +0200 Subject: [PATCH 26/38] Issue #16792: Mark small ints test as CPython-only. --- Lib/test/test_int.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Lib/test/test_int.py b/Lib/test/test_int.py index 045ef7c76ad..099640a1cfc 100644 --- a/Lib/test/test_int.py +++ b/Lib/test/test_int.py @@ -378,6 +378,14 @@ class IntTestCases(IntLongCommonTests, unittest.TestCase): self.assertEquals(int(base=1), 0) self.assertEquals(int(base=1000), 0) + @test_support.cpython_only + def test_small_ints(self): + self.assertTrue(int('10') is 10) + self.assertTrue(int('-1') is -1) + if have_unicode: + self.assertTrue(int(u'10') is 10) + self.assertTrue(int(u'-1') is -1) + def test_intconversion(self): # Test __int__() class ClassicMissingMethods: From 8876145fabec7924981f36019f0c2e45f73fbad2 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Fri, 28 Dec 2012 00:32:19 +0200 Subject: [PATCH 27/38] Issue #16793. Replace deprecated unittest asserts with modern counterparts. --- Lib/ctypes/test/test_bitfields.py | 8 ++++---- Lib/test/test_calendar.py | 2 +- Lib/test/test_int.py | 10 +++++----- Lib/test/test_mutex.py | 2 +- Lib/test/test_tarfile.py | 2 +- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Lib/ctypes/test/test_bitfields.py b/Lib/ctypes/test/test_bitfields.py index 090fb4dfc5e..3bcc67fb75e 100644 --- a/Lib/ctypes/test/test_bitfields.py +++ b/Lib/ctypes/test/test_bitfields.py @@ -246,9 +246,9 @@ class BitFieldTest(unittest.TestCase): _fields_ = [("a", c_uint32, 32)] x = X() x.a = 10 - self.assertEquals(x.a, 10) + self.assertEqual(x.a, 10) x.a = 0xFDCBA987 - self.assertEquals(x.a, 0xFDCBA987) + self.assertEqual(x.a, 0xFDCBA987) @unittest.skipUnless(hasattr(ctypes, "c_uint64"), "c_int64 is required") def test_uint64(self): @@ -256,9 +256,9 @@ class BitFieldTest(unittest.TestCase): _fields_ = [("a", c_uint64, 64)] x = X() x.a = 10 - self.assertEquals(x.a, 10) + self.assertEqual(x.a, 10) x.a = 0xFEDCBA9876543211 - self.assertEquals(x.a, 0xFEDCBA9876543211) + self.assertEqual(x.a, 0xFEDCBA9876543211) if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_calendar.py b/Lib/test/test_calendar.py index 5d6549c6cd8..0f91d295903 100644 --- a/Lib/test/test_calendar.py +++ b/Lib/test/test_calendar.py @@ -261,7 +261,7 @@ class CalendarTestCase(unittest.TestCase): return calendar.LocaleHTMLCalendar(locale='').formatmonthname(2010, 10) new_october = calendar.TextCalendar().formatmonthname(2010, 10, 10) - self.assertEquals(old_october, new_october) + self.assertEqual(old_october, new_october) def test_itermonthdates(self): # ensure itermonthdates doesn't overflow after datetime.MAXYEAR diff --git a/Lib/test/test_int.py b/Lib/test/test_int.py index 099640a1cfc..f1d4f95821f 100644 --- a/Lib/test/test_int.py +++ b/Lib/test/test_int.py @@ -347,8 +347,8 @@ class IntTestCases(IntLongCommonTests, unittest.TestCase): for x in values: msg = 'x has value %s and type %s' % (x, type(x).__name__) try: - self.assertEquals(int(x), 100, msg=msg) - self.assertEquals(int(x, 2), 4, msg=msg) + self.assertEqual(int(x), 100, msg=msg) + self.assertEqual(int(x, 2), 4, msg=msg) except TypeError, err: raise AssertionError('For %s got TypeError: %s' % (type(x).__name__, err)) @@ -373,10 +373,10 @@ class IntTestCases(IntLongCommonTests, unittest.TestCase): # expects x to be a string if base is given. @test_support.cpython_only def test_int_base_without_x_returns_0(self): - self.assertEquals(int(base=6), 0) + self.assertEqual(int(base=6), 0) # Even invalid bases don't raise an exception. - self.assertEquals(int(base=1), 0) - self.assertEquals(int(base=1000), 0) + self.assertEqual(int(base=1), 0) + self.assertEqual(int(base=1000), 0) @test_support.cpython_only def test_small_ints(self): diff --git a/Lib/test/test_mutex.py b/Lib/test/test_mutex.py index 28822133947..030080e3a4a 100644 --- a/Lib/test/test_mutex.py +++ b/Lib/test/test_mutex.py @@ -14,7 +14,7 @@ class MutexTest(unittest.TestCase): m.lock(called_by_mutex2, "eggs") def called_by_mutex2(some_data): - self.assertEquals(some_data, "eggs") + self.assertEqual(some_data, "eggs") self.assertTrue(m.test(), "mutex not held") self.assertTrue(ready_for_2, "called_by_mutex2 called too soon") diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py index a3685ea273a..9ec7744efbe 100644 --- a/Lib/test/test_tarfile.py +++ b/Lib/test/test_tarfile.py @@ -858,7 +858,7 @@ class WriteTest(WriteTestBase): tar = tarfile.open(tmpname, "r") for t in tar: - self.assert_(t.name == "." or t.name.startswith("./")) + self.assertTrue(t.name == "." or t.name.startswith("./")) tar.close() finally: os.chdir(cwd) From c90be30b0de9089e3abef0f288caf4a693f81356 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Fri, 28 Dec 2012 00:44:20 +0200 Subject: [PATCH 28/38] Issue #16792: Use assertIs() to test identity. --- Lib/test/test_int.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_int.py b/Lib/test/test_int.py index f1d4f95821f..b3b12e651df 100644 --- a/Lib/test/test_int.py +++ b/Lib/test/test_int.py @@ -380,11 +380,11 @@ class IntTestCases(IntLongCommonTests, unittest.TestCase): @test_support.cpython_only def test_small_ints(self): - self.assertTrue(int('10') is 10) - self.assertTrue(int('-1') is -1) + self.assertIs(int('10'), 10) + self.assertIs(int('-1'), -1) if have_unicode: - self.assertTrue(int(u'10') is 10) - self.assertTrue(int(u'-1') is -1) + self.assertIs(int(u'10'), 10) + self.assertIs(int(u'-1'), -1) def test_intconversion(self): # Test __int__() From 82ee30384c02d26293c41dbb64d9ac36d30bd888 Mon Sep 17 00:00:00 2001 From: Ezio Melotti Date: Fri, 28 Dec 2012 01:59:24 +0200 Subject: [PATCH 29/38] #16796: fix typo. Patch by Michael Schurter. --- Doc/library/argparse.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst index 2380a509e94..73d454e8edf 100644 --- a/Doc/library/argparse.rst +++ b/Doc/library/argparse.rst @@ -1439,7 +1439,7 @@ Sub-commands different functions which require different kinds of command-line arguments. :class:`ArgumentParser` supports the creation of such sub-commands with the :meth:`add_subparsers` method. The :meth:`add_subparsers` method is normally - called with no arguments and returns an special action object. This object + called with no arguments and returns a special action object. This object has a single method, :meth:`~ArgumentParser.add_parser`, which takes a command name and any :class:`ArgumentParser` constructor arguments, and returns an :class:`ArgumentParser` object that can be modified as usual. From 3684c79e00ad923fa2400458c1a02d6afa3c5ce8 Mon Sep 17 00:00:00 2001 From: Chris Jerdonek Date: Thu, 27 Dec 2012 18:14:01 -0800 Subject: [PATCH 30/38] Issue #15324: Fix regrtest parsing of --fromfile and --randomize options. --- Lib/test/regrtest.py | 4 ++-- Misc/NEWS | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Lib/test/regrtest.py b/Lib/test/regrtest.py index f01dcef308a..dd47cc36e01 100755 --- a/Lib/test/regrtest.py +++ b/Lib/test/regrtest.py @@ -32,7 +32,7 @@ Verbosity Selecting tests --r/--random -- randomize test execution order (see below) +-r/--randomize -- randomize test execution order (see below) --randseed -- pass a random seed to reproduce a previous random run -f/--fromfile -- read names of tests to run from a file (see below) -x/--exclude -- arguments are tests to *exclude* @@ -258,7 +258,7 @@ def main(tests=None, testdir=None, verbose=0, quiet=False, try: opts, args = getopt.getopt(sys.argv[1:], 'hvqxsSrf:lu:t:TD:NLR:FwWM:j:', ['help', 'verbose', 'verbose2', 'verbose3', 'quiet', - 'exclude', 'single', 'slow', 'random', 'fromfile', 'findleaks', + 'exclude', 'single', 'slow', 'randomize', 'fromfile=', 'findleaks', 'use=', 'threshold=', 'trace', 'coverdir=', 'nocoverdir', 'runleaks', 'huntrleaks=', 'memlimit=', 'randseed=', 'multiprocess=', 'slaveargs=', 'forever', 'header']) diff --git a/Misc/NEWS b/Misc/NEWS index 6c0e000f59c..38413bd928c 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -585,6 +585,8 @@ Extension Modules Tests ----- +- Issue #15324: Fix regrtest parsing of --fromfile and --randomize options. + - Issue #16618: Add more regression tests for glob. Patch by Serhiy Storchaka. From cf095f8e0f0ed1111995a5b8a8a5ebdb189683f2 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Fri, 28 Dec 2012 09:31:59 +0200 Subject: [PATCH 31/38] Issue #16761: Raise TypeError when int() or long() called with base argument only. --- Lib/test/test_int.py | 14 ++------------ Misc/NEWS | 3 +++ Objects/intobject.c | 8 +++++++- Objects/longobject.c | 8 +++++++- 4 files changed, 19 insertions(+), 14 deletions(-) diff --git a/Lib/test/test_int.py b/Lib/test/test_int.py index b3b12e651df..365f9a247c9 100644 --- a/Lib/test/test_int.py +++ b/Lib/test/test_int.py @@ -60,6 +60,8 @@ class IntLongCommonTests(object): self.assertEqual(self.ntype(x=1.2), 1) self.assertEqual(self.ntype('100', base=2), 4) self.assertEqual(self.ntype(x='100', base=2), 4) + self.assertRaises(TypeError, self.ntype, base=10) + self.assertRaises(TypeError, self.ntype, base=0) class IntTestCases(IntLongCommonTests, unittest.TestCase): @@ -365,18 +367,6 @@ class IntTestCases(IntLongCommonTests, unittest.TestCase): def test_error_on_string_base(self): self.assertRaises(TypeError, int, 100, base='foo') - # Include the following because in contrast CPython raises no error - # for bad integer bases when x is not given. - self.assertRaises(TypeError, int, base='foo') - - # For example, PyPy 1.9.0 raised TypeError for these cases because it - # expects x to be a string if base is given. - @test_support.cpython_only - def test_int_base_without_x_returns_0(self): - self.assertEqual(int(base=6), 0) - # Even invalid bases don't raise an exception. - self.assertEqual(int(base=1), 0) - self.assertEqual(int(base=1000), 0) @test_support.cpython_only def test_small_ints(self): diff --git a/Misc/NEWS b/Misc/NEWS index 38413bd928c..b718641a95a 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -9,6 +9,9 @@ What's New in Python 2.7.4 Core and Builtins ----------------- +- Issue #16761: Calling ``int()`` and ``long()`` with *base* argument only + now raises TypeError. + - Issue #16759: Support the full DWORD (unsigned long) range in Reg2Py when retreiving a REG_DWORD value. This corrects functions like winreg.QueryValueEx that may have been returning truncated values. diff --git a/Objects/intobject.c b/Objects/intobject.c index 74955adbeff..1ae8006c282 100644 --- a/Objects/intobject.c +++ b/Objects/intobject.c @@ -1059,8 +1059,14 @@ int_new(PyTypeObject *type, PyObject *args, PyObject *kwds) if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oi:int", kwlist, &x, &base)) return NULL; - if (x == NULL) + if (x == NULL) { + if (base != -909) { + PyErr_SetString(PyExc_TypeError, + "int() missing string argument"); + return NULL; + } return PyInt_FromLong(0L); + } if (base == -909) return PyNumber_Int(x); if (PyString_Check(x)) { diff --git a/Objects/longobject.c b/Objects/longobject.c index 9296ad49b1c..5a6338f6302 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -3987,8 +3987,14 @@ long_new(PyTypeObject *type, PyObject *args, PyObject *kwds) if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oi:long", kwlist, &x, &base)) return NULL; - if (x == NULL) + if (x == NULL) { + if (base != -909) { + PyErr_SetString(PyExc_TypeError, + "long() missing string argument"); + return NULL; + } return PyLong_FromLong(0L); + } if (base == -909) return PyNumber_Long(x); else if (PyString_Check(x)) { From c195b4e88c39f58dccea0678ec517c1632d337f4 Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Fri, 28 Dec 2012 00:03:30 -0800 Subject: [PATCH 32/38] Make the from_iterable() recipe more usable. The code isn't exactly equivalent because a classmethod would only make sense inside a chain class, and it would need "cls" as a first argument, and it would need to return an instance of "chain" rather than a generator. The updated example drops the @classmethod decorator so that it can be used standalone: list(from_iterable(['abc', 'def'])) This should be communicate what from_iterable does. --- Doc/library/itertools.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Doc/library/itertools.rst b/Doc/library/itertools.rst index 8bb9e3672a4..a7f0058b4cd 100644 --- a/Doc/library/itertools.rst +++ b/Doc/library/itertools.rst @@ -106,9 +106,8 @@ loops that truncate the stream. .. classmethod:: chain.from_iterable(iterable) Alternate constructor for :func:`chain`. Gets chained inputs from a - single iterable argument that is evaluated lazily. Equivalent to:: + single iterable argument that is evaluated lazily. Roughly equivalent to:: - @classmethod def from_iterable(iterables): # chain.from_iterable(['ABC', 'DEF']) --> A B C D E F for it in iterables: From 40f12ab0c5c5adc4a8b4a03a57ffa94c87ecc2cb Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Fri, 28 Dec 2012 19:03:43 +0100 Subject: [PATCH 33/38] Backport Python 3.2 fix for issue #12065, and add another test for SSLSocket.connect_ex(). --- Lib/ssl.py | 20 +++++++++++--------- Lib/test/test_ssl.py | 28 ++++++++++++++++++++++++++++ Misc/NEWS | 3 +++ 3 files changed, 42 insertions(+), 9 deletions(-) diff --git a/Lib/ssl.py b/Lib/ssl.py index 1951a620d96..88296358a02 100644 --- a/Lib/ssl.py +++ b/Lib/ssl.py @@ -313,17 +313,19 @@ class SSLSocket(socket): self.cert_reqs, self.ssl_version, self.ca_certs, self.ciphers) try: - socket.connect(self, addr) - if self.do_handshake_on_connect: - self.do_handshake() - except socket_error as e: if return_errno: - return e.errno + rc = socket.connect_ex(self, addr) else: - self._sslobj = None - raise e - self._connected = True - return 0 + rc = None + socket.connect(self, addr) + if not rc: + if self.do_handshake_on_connect: + self.do_handshake() + self._connected = True + return rc + except socket_error: + self._sslobj = None + raise def connect(self, addr): """Connects to remote ADDR, and then wraps the connection in diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index 58da942f492..9f5138719e8 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -280,6 +280,34 @@ class NetworkedTests(unittest.TestCase): finally: s.close() + def test_timeout_connect_ex(self): + # Issue #12065: on a timeout, connect_ex() should return the original + # errno (mimicking the behaviour of non-SSL sockets). + with test_support.transient_internet("svn.python.org"): + s = ssl.wrap_socket(socket.socket(socket.AF_INET), + cert_reqs=ssl.CERT_REQUIRED, + ca_certs=SVN_PYTHON_ORG_ROOT_CERT, + do_handshake_on_connect=False) + try: + s.settimeout(0.0000001) + rc = s.connect_ex(('svn.python.org', 443)) + if rc == 0: + self.skipTest("svn.python.org responded too quickly") + self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK)) + finally: + s.close() + + def test_connect_ex_error(self): + with test_support.transient_internet("svn.python.org"): + s = ssl.wrap_socket(socket.socket(socket.AF_INET), + cert_reqs=ssl.CERT_REQUIRED, + ca_certs=SVN_PYTHON_ORG_ROOT_CERT) + try: + self.assertEqual(errno.ECONNREFUSED, + s.connect_ex(("svn.python.org", 444))) + finally: + s.close() + @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows") def test_makefile_close(self): # Issue #5238: creating a file-like object with makefile() shouldn't diff --git a/Misc/NEWS b/Misc/NEWS index b718641a95a..f087f415d6a 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -175,6 +175,9 @@ Core and Builtins Library ------- +- Issue #12065: connect_ex() on an SSL socket now returns the original errno + when the socket's timeout expires (it used to return None). + - Issue #16504: IDLE now catches SyntaxErrors raised by tokenizer. Patch by Roger Serwy. From 4ed797efbc2401d34c95bbb0cea921535c868d16 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sat, 29 Dec 2012 22:25:59 +0200 Subject: [PATCH 34/38] Issue #16485: Fix file descriptor not being closed if file header patching fails on closing of aifc file. --- Lib/aifc.py | 38 ++++++++++++++++++++++---------------- Lib/test/test_aifc.py | 7 +++++++ Misc/NEWS | 3 +++ 3 files changed, 32 insertions(+), 16 deletions(-) diff --git a/Lib/aifc.py b/Lib/aifc.py index b8adc852ed6..a0cfe5fc57e 100644 --- a/Lib/aifc.py +++ b/Lib/aifc.py @@ -732,22 +732,28 @@ class Aifc_write: self._patchheader() def close(self): - self._ensure_header_written(0) - if self._datawritten & 1: - # quick pad to even size - self._file.write(chr(0)) - self._datawritten = self._datawritten + 1 - self._writemarkers() - if self._nframeswritten != self._nframes or \ - self._datalength != self._datawritten or \ - self._marklength: - self._patchheader() - if self._comp: - self._comp.CloseCompressor() - self._comp = None - # Prevent ref cycles - self._convert = None - self._file.close() + if self._file is None: + return + try: + self._ensure_header_written(0) + if self._datawritten & 1: + # quick pad to even size + self._file.write(chr(0)) + self._datawritten = self._datawritten + 1 + self._writemarkers() + if self._nframeswritten != self._nframes or \ + self._datalength != self._datawritten or \ + self._marklength: + self._patchheader() + if self._comp: + self._comp.CloseCompressor() + self._comp = None + finally: + # Prevent ref cycles + self._convert = None + f = self._file + self._file = None + f.close() # # Internal methods. diff --git a/Lib/test/test_aifc.py b/Lib/test/test_aifc.py index e4928382582..62b3d180184 100644 --- a/Lib/test/test_aifc.py +++ b/Lib/test/test_aifc.py @@ -106,6 +106,13 @@ class AIFCTest(unittest.TestCase): self.assertEqual(testfile.closed, False) f.close() self.assertEqual(testfile.closed, True) + testfile = open(TESTFN, 'wb') + fout = aifc.open(testfile, 'wb') + self.assertFalse(testfile.closed) + with self.assertRaises(aifc.Error): + fout.close() + self.assertTrue(testfile.closed) + fout.close() # do nothing class AIFCLowLevelTest(unittest.TestCase): diff --git a/Misc/NEWS b/Misc/NEWS index f087f415d6a..8ec9675fb47 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -175,6 +175,9 @@ Core and Builtins Library ------- +- Issue #16485: Fix file descriptor not being closed if file header patching + fails on closing of aifc file. + - Issue #12065: connect_ex() on an SSL socket now returns the original errno when the socket's timeout expires (it used to return None). From 14e27d896f5d07eb4f24aee1f76f3cafd66c2b2b Mon Sep 17 00:00:00 2001 From: Andrew Svetlov Date: Sat, 29 Dec 2012 23:09:32 +0200 Subject: [PATCH 35/38] Fix docstring in curses (#16782) --- Lib/curses/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/curses/__init__.py b/Lib/curses/__init__.py index bd7d5f61cf4..ecf59de37d0 100644 --- a/Lib/curses/__init__.py +++ b/Lib/curses/__init__.py @@ -5,7 +5,7 @@ the package, and perhaps a particular module inside it. import curses from curses import textpad - curses.initwin() + curses.initscr() ... """ From 421489f8a6d9485b484fb5d51bcb5df094190b7e Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sun, 30 Dec 2012 20:15:10 +0200 Subject: [PATCH 36/38] Issue #16645: Fix hardlink extracting test for tarfile. --- Lib/test/test_tarfile.py | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py index 9ec7744efbe..af59e277f3e 100644 --- a/Lib/test/test_tarfile.py +++ b/Lib/test/test_tarfile.py @@ -297,26 +297,21 @@ class MiscReadTest(CommonReadTest): def test_extract_hardlink(self): # Test hardlink extraction (e.g. bug #857297). - tar = tarfile.open(tarname, errorlevel=1, encoding="iso8859-1") + with tarfile.open(tarname, errorlevel=1, encoding="iso8859-1") as tar: + tar.extract("ustar/regtype", TEMPDIR) + self.addCleanup(os.remove, os.path.join(TEMPDIR, "ustar/regtype")) - tar.extract("ustar/regtype", TEMPDIR) - try: tar.extract("ustar/lnktype", TEMPDIR) - except EnvironmentError, e: - if e.errno == errno.ENOENT: - self.fail("hardlink not extracted properly") + self.addCleanup(os.remove, os.path.join(TEMPDIR, "ustar/lnktype")) + with open(os.path.join(TEMPDIR, "ustar/lnktype"), "rb") as f: + data = f.read() + self.assertEqual(md5sum(data), md5_regtype) - data = open(os.path.join(TEMPDIR, "ustar/lnktype"), "rb").read() - self.assertEqual(md5sum(data), md5_regtype) - - try: tar.extract("ustar/symtype", TEMPDIR) - except EnvironmentError, e: - if e.errno == errno.ENOENT: - self.fail("symlink not extracted properly") - - data = open(os.path.join(TEMPDIR, "ustar/symtype"), "rb").read() - self.assertEqual(md5sum(data), md5_regtype) + self.addCleanup(os.remove, os.path.join(TEMPDIR, "ustar/symtype")) + with open(os.path.join(TEMPDIR, "ustar/symtype"), "rb") as f: + data = f.read() + self.assertEqual(md5sum(data), md5_regtype) def test_extractall(self): # Test if extractall() correctly restores directory permissions From cef2006eaff86f843b8f0fc21fc7b652415b96ed Mon Sep 17 00:00:00 2001 From: Giampaolo Rodola' Date: Mon, 31 Dec 2012 17:23:09 +0100 Subject: [PATCH 37/38] Fix issue 10527: make multiprocessing use poll() instead of select() if available. --- Lib/multiprocessing/connection.py | 21 +++++++++++++++++++++ Lib/test/test_multiprocessing.py | 1 + Misc/NEWS | 2 ++ 3 files changed, 24 insertions(+) diff --git a/Lib/multiprocessing/connection.py b/Lib/multiprocessing/connection.py index 4421ac5cfd7..6c398fdc918 100644 --- a/Lib/multiprocessing/connection.py +++ b/Lib/multiprocessing/connection.py @@ -200,6 +200,27 @@ if sys.platform != 'win32': return c1, c2 else: + if hasattr(select, 'poll'): + def _poll(fds, timeout): + if timeout is not None: + timeout = int(timeout) * 1000 # timeout is in milliseconds + fd_map = {} + pollster = select.poll() + for fd in fds: + pollster.register(fd, select.POLLIN) + if hasattr(fd, 'fileno'): + fd_map[fd.fileno()] = fd + else: + fd_map[fd] = fd + ls = [] + for fd, event in pollster.poll(timeout): + if event & select.POLLNVAL: + raise ValueError('invalid file descriptor %i' % fd) + ls.append(fd_map[fd]) + return ls + else: + def _poll(fds, timeout): + return select.select(fds, [], [], timeout)[0] from _multiprocessing import win32 diff --git a/Lib/test/test_multiprocessing.py b/Lib/test/test_multiprocessing.py index 15870570db0..f140aca63f1 100644 --- a/Lib/test/test_multiprocessing.py +++ b/Lib/test/test_multiprocessing.py @@ -1513,6 +1513,7 @@ class _TestConnection(BaseTestCase): self.assertTimingAlmostEqual(poll.elapsed, TIMEOUT1) conn.send(None) + time.sleep(.1) self.assertEqual(poll(TIMEOUT1), True) self.assertTimingAlmostEqual(poll.elapsed, 0) diff --git a/Misc/NEWS b/Misc/NEWS index 8ec9675fb47..e99efca3ffd 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -175,6 +175,8 @@ Core and Builtins Library ------- +- Issue 10527: make multiprocessing use poll() instead of select() if available. + - Issue #16485: Fix file descriptor not being closed if file header patching fails on closing of aifc file. From 10e93a6d40502e100c68090730e0b3190df97854 Mon Sep 17 00:00:00 2001 From: Ned Deily Date: Mon, 31 Dec 2012 15:06:38 -0800 Subject: [PATCH 38/38] Issue #14958: backport to 2.7.x from 3.3 (patch by Roger Serwy) --- Lib/idlelib/ColorDelegator.py | 9 +++++---- Misc/NEWS | 3 +++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Lib/idlelib/ColorDelegator.py b/Lib/idlelib/ColorDelegator.py index 7f4d740ffac..0610c4b6aac 100644 --- a/Lib/idlelib/ColorDelegator.py +++ b/Lib/idlelib/ColorDelegator.py @@ -20,10 +20,11 @@ def make_pat(): # 1st 'file' colorized normal, 2nd as builtin, 3rd as string builtin = r"([^.'\"\\#]\b|^)" + any("BUILTIN", builtinlist) + r"\b" comment = any("COMMENT", [r"#[^\n]*"]) - sqstring = r"(\b[rRuU])?'[^'\\\n]*(\\.[^'\\\n]*)*'?" - dqstring = r'(\b[rRuU])?"[^"\\\n]*(\\.[^"\\\n]*)*"?' - sq3string = r"(\b[rRuU])?'''[^'\\]*((\\.|'(?!''))[^'\\]*)*(''')?" - dq3string = r'(\b[rRuU])?"""[^"\\]*((\\.|"(?!""))[^"\\]*)*(""")?' + stringprefix = r"(\br|u|ur|R|U|UR|Ur|uR|b|B|br|Br|bR|BR)?" + sqstring = stringprefix + r"'[^'\\\n]*(\\.[^'\\\n]*)*'?" + dqstring = stringprefix + r'"[^"\\\n]*(\\.[^"\\\n]*)*"?' + sq3string = stringprefix + r"'''[^'\\]*((\\.|'(?!''))[^'\\]*)*(''')?" + dq3string = stringprefix + r'"""[^"\\]*((\\.|"(?!""))[^"\\]*)*(""")?' string = any("STRING", [sq3string, dq3string, sqstring, dqstring]) return kw + "|" + builtin + "|" + comment + "|" + string +\ "|" + any("SYNC", [r"\n"]) diff --git a/Misc/NEWS b/Misc/NEWS index e99efca3ffd..8bfa5690176 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -430,6 +430,9 @@ Library - Issue #12157: Make pool.map() empty iterables correctly. Initial patch by mouad. +- Issue #14958: Change IDLE systax highlighting to recognize all string and byte + literals currently supported in Python 2.7. + - Issue #14962: Update text coloring in IDLE shell window after changing options. Patch by Roger Serwy.