From 9e00938f25f80bbff05c6946062a767f11123848 Mon Sep 17 00:00:00 2001 From: Ezio Melotti Date: Sat, 7 May 2011 17:40:23 +0300 Subject: #12017: Fix segfault in json.loads() while decoding highly-nested objects using the C accelerations. --- Lib/json/tests/test_recursion.py | 19 +++++++++++++++++++ Misc/NEWS | 3 +++ Modules/_json.c | 30 ++++++++++++++++++++++++++---- 3 files changed, 48 insertions(+), 4 deletions(-) diff --git a/Lib/json/tests/test_recursion.py b/Lib/json/tests/test_recursion.py index 1e9b8ab757..548bb89ed5 100644 --- a/Lib/json/tests/test_recursion.py +++ b/Lib/json/tests/test_recursion.py @@ -65,3 +65,22 @@ class TestRecursion(TestCase): pass else: self.fail("didn't raise ValueError on default recursion") + + + def test_highly_nested_objects(self): + # test that loading highly-nested objects doesn't segfault when C + # accelerations are used. See #12017 + # str + with self.assertRaises(RuntimeError): + json.loads('{"a":' * 100000 + '1' + '}' * 100000) + with self.assertRaises(RuntimeError): + json.loads('{"a":' * 100000 + '[1]' + '}' * 100000) + with self.assertRaises(RuntimeError): + json.loads('[' * 100000 + '1' + ']' * 100000) + # unicode + with self.assertRaises(RuntimeError): + json.loads(u'{"a":' * 100000 + u'1' + u'}' * 100000) + with self.assertRaises(RuntimeError): + json.loads(u'{"a":' * 100000 + u'[1]' + u'}' * 100000) + with self.assertRaises(RuntimeError): + json.loads(u'[' * 100000 + u'1' + u']' * 100000) diff --git a/Misc/NEWS b/Misc/NEWS index 7207f4b919..8c760576a6 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -358,6 +358,9 @@ Library Extension Modules ----------------- +- Issue #12017: Fix segfault in json.loads() while decoding highly-nested + objects using the C accelerations. + - Issue #1838: Prevent segfault in ctypes, when _as_parameter_ on a class is set to an instance of the class. diff --git a/Modules/_json.c b/Modules/_json.c index 7a1fabdba1..4b4ef89282 100644 --- a/Modules/_json.c +++ b/Modules/_json.c @@ -1488,6 +1488,7 @@ scan_once_str(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *n Returns a new PyObject representation of the term. */ + PyObject *res; char *str = PyString_AS_STRING(pystr); Py_ssize_t length = PyString_GET_SIZE(pystr); if (idx >= length) { @@ -1503,10 +1504,20 @@ scan_once_str(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *n next_idx_ptr); case '{': /* object */ - return _parse_object_str(s, pystr, idx + 1, next_idx_ptr); + if (Py_EnterRecursiveCall(" while decoding a JSON object " + "from a byte string")) + return NULL; + res = _parse_object_str(s, pystr, idx + 1, next_idx_ptr); + Py_LeaveRecursiveCall(); + return res; case '[': /* array */ - return _parse_array_str(s, pystr, idx + 1, next_idx_ptr); + if (Py_EnterRecursiveCall(" while decoding a JSON array " + "from a byte string")) + return NULL; + res = _parse_array_str(s, pystr, idx + 1, next_idx_ptr); + Py_LeaveRecursiveCall(); + return res; case 'n': /* null */ if ((idx + 3 < length) && str[idx + 1] == 'u' && str[idx + 2] == 'l' && str[idx + 3] == 'l') { @@ -1564,6 +1575,7 @@ scan_once_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_ Returns a new PyObject representation of the term. */ + PyObject *res; Py_UNICODE *str = PyUnicode_AS_UNICODE(pystr); Py_ssize_t length = PyUnicode_GET_SIZE(pystr); if (idx >= length) { @@ -1578,10 +1590,20 @@ scan_once_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_ next_idx_ptr); case '{': /* object */ - return _parse_object_unicode(s, pystr, idx + 1, next_idx_ptr); + if (Py_EnterRecursiveCall(" while decoding a JSON object " + "from a unicode string")) + return NULL; + res = _parse_object_unicode(s, pystr, idx + 1, next_idx_ptr); + Py_LeaveRecursiveCall(); + return res; case '[': /* array */ - return _parse_array_unicode(s, pystr, idx + 1, next_idx_ptr); + if (Py_EnterRecursiveCall(" while decoding a JSON array " + "from a unicode string")) + return NULL; + res = _parse_array_unicode(s, pystr, idx + 1, next_idx_ptr); + Py_LeaveRecursiveCall(); + return res; case 'n': /* null */ if ((idx + 3 < length) && str[idx + 1] == 'u' && str[idx + 2] == 'l' && str[idx + 3] == 'l') { -- cgit v1.2.1 From da62936f29d98c1d88e7ba589122d0e3fcf0fdc9 Mon Sep 17 00:00:00 2001 From: Ezio Melotti Date: Sat, 7 May 2011 19:21:22 +0300 Subject: #10169: Fix argument parsing in socket.sendto() to avoid error masking. --- Lib/test/test_socket.py | 39 +++++++++++++++++++++++++++++++++++++++ Misc/NEWS | 2 ++ Modules/socketmodule.c | 20 +++++++++++++++----- 3 files changed, 56 insertions(+), 5 deletions(-) diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py index d41bca51b5..7ee16ebced 100644 --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -274,6 +274,45 @@ class GeneralModuleTests(unittest.TestCase): self.assertRaises(socket.error, raise_gaierror, "Error raising socket exception.") + def testSendtoErrors(self): + # Testing that sendto doens't masks failures. See #10169. + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + self.addCleanup(s.close) + s.bind(('', 0)) + sockname = s.getsockname() + # 2 args + with self.assertRaises(UnicodeEncodeError): + s.sendto(u'\u2620', sockname) + with self.assertRaises(TypeError) as cm: + s.sendto(5j, sockname) + self.assertIn('not complex', str(cm.exception)) + with self.assertRaises(TypeError) as cm: + s.sendto('foo', None) + self.assertIn('not NoneType', str(cm.exception)) + # 3 args + with self.assertRaises(UnicodeEncodeError): + s.sendto(u'\u2620', 0, sockname) + with self.assertRaises(TypeError) as cm: + s.sendto(5j, 0, sockname) + self.assertIn('not complex', str(cm.exception)) + with self.assertRaises(TypeError) as cm: + s.sendto('foo', 0, None) + self.assertIn('not NoneType', str(cm.exception)) + with self.assertRaises(TypeError) as cm: + s.sendto('foo', 'bar', sockname) + self.assertIn('an integer is required', str(cm.exception)) + with self.assertRaises(TypeError) as cm: + s.sendto('foo', None, None) + self.assertIn('an integer is required', str(cm.exception)) + # wrong number of args + with self.assertRaises(TypeError) as cm: + s.sendto('foo') + self.assertIn('(1 given)', str(cm.exception)) + with self.assertRaises(TypeError) as cm: + s.sendto('foo', 0, sockname, 4) + self.assertIn('(4 given)', str(cm.exception)) + + def testCrucialConstants(self): # Testing for mission critical constants socket.AF_INET diff --git a/Misc/NEWS b/Misc/NEWS index 8c760576a6..8f3c0b9ab1 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -358,6 +358,8 @@ Library Extension Modules ----------------- +- Issue #10169: Fix argument parsing in socket.sendto() to avoid error masking. + - Issue #12017: Fix segfault in json.loads() while decoding highly-nested objects using the C accelerations. diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index d14910a613..96b83b1150 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -2826,14 +2826,24 @@ sock_sendto(PySocketSockObject *s, PyObject *args) Py_ssize_t len; sock_addr_t addrbuf; int addrlen, n = -1, flags, timeout; + int arglen; flags = 0; - if (!PyArg_ParseTuple(args, "s*O:sendto", &pbuf, &addro)) { - PyErr_Clear(); - if (!PyArg_ParseTuple(args, "s*iO:sendto", - &pbuf, &flags, &addro)) - return NULL; + arglen = PyTuple_Size(args); + switch(arglen) { + case 2: + PyArg_ParseTuple(args, "s*O:sendto", &pbuf, &addro); + break; + case 3: + PyArg_ParseTuple(args, "s*iO:sendto", &pbuf, &flags, &addro); + break; + default: + PyErr_Format(PyExc_TypeError, "sendto() takes 2 or 3" + " arguments (%d given)", arglen); } + if (PyErr_Occurred()) + return NULL; + buf = pbuf.buf; len = pbuf.len; -- cgit v1.2.1 From 1823ad7451885e88a8e44b14975e6e54f131b9d1 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Sat, 7 May 2011 19:59:33 +0200 Subject: Issue #11927: SMTP_SSL now uses port 465 by default as documented. Patch by Kasun Herath. --- Lib/smtplib.py | 6 ++++-- Lib/test/test_smtpnet.py | 7 +++++++ Misc/ACKS | 1 + Misc/NEWS | 3 +++ 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/Lib/smtplib.py b/Lib/smtplib.py index e7d3786229..e3ffb37be3 100755 --- a/Lib/smtplib.py +++ b/Lib/smtplib.py @@ -222,6 +222,7 @@ class SMTP: ehlo_msg = "ehlo" ehlo_resp = None does_esmtp = 0 + default_port = SMTP_PORT def __init__(self, host='', port=0, local_hostname=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT): @@ -237,7 +238,6 @@ class SMTP: """ self.timeout = timeout self.esmtp_features = {} - self.default_port = SMTP_PORT if host: (code, msg) = self.connect(host, port) if code != 220: @@ -756,13 +756,15 @@ if _have_ssl: are also optional - they can contain a PEM formatted private key and certificate chain file for the SSL connection. """ + + default_port = SMTP_SSL_PORT + def __init__(self, host='', port=0, local_hostname=None, keyfile=None, certfile=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT): self.keyfile = keyfile self.certfile = certfile SMTP.__init__(self, host, port, local_hostname, timeout) - self.default_port = SMTP_SSL_PORT def _get_socket(self, host, port, timeout): if self.debuglevel > 0: diff --git a/Lib/test/test_smtpnet.py b/Lib/test/test_smtpnet.py index f25343d27f..2dc39eb8f7 100644 --- a/Lib/test/test_smtpnet.py +++ b/Lib/test/test_smtpnet.py @@ -17,6 +17,13 @@ class SmtpSSLTest(unittest.TestCase): server.ehlo() server.quit() + def test_connect_default_port(self): + test_support.get_attribute(smtplib, 'SMTP_SSL') + with test_support.transient_internet(self.testServer): + server = smtplib.SMTP_SSL(self.testServer) + server.ehlo() + server.quit() + def test_main(): test_support.run_unittest(SmtpSSLTest) diff --git a/Misc/ACKS b/Misc/ACKS index 3c0e370735..9b9ff68523 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -337,6 +337,7 @@ Malte Helmert Lance Finn Helsten Jonathan Hendry James Henstridge +Kasun Herath Chris Herborth Ivan Herman Jürgen Hermann diff --git a/Misc/NEWS b/Misc/NEWS index 8f3c0b9ab1..36d0080694 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -77,6 +77,9 @@ Core and Builtins Library ------- +- Issue #11927: SMTP_SSL now uses port 465 by default as documented. Patch + by Kasun Herath. + - Issue 11999: fixed sporadic sync failure mailbox.Maildir due to its trying to detect mtime changes by comparing to the system clock instead of to the previous value of the mtime. -- cgit v1.2.1 From 672c2cc8124b7b4b39c0bfc92e62b819c742e642 Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Sat, 7 May 2011 14:16:42 -0700 Subject: Some tests were incorrectly marked as C specific. --- Lib/test/test_heapq.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_heapq.py b/Lib/test/test_heapq.py index d5d8c1a179..f0753cf385 100644 --- a/Lib/test/test_heapq.py +++ b/Lib/test/test_heapq.py @@ -305,8 +305,6 @@ def L(seqn): return chain(imap(lambda x:x, R(Ig(G(seqn))))) class TestErrorHandling(unittest.TestCase): - # only for C implementation - module = c_heapq def test_non_sequence(self): for f in (self.module.heapify, self.module.heappop): @@ -351,12 +349,19 @@ class TestErrorHandling(unittest.TestCase): self.assertRaises(TypeError, f, 2, N(s)) self.assertRaises(ZeroDivisionError, f, 2, E(s)) +class TestErrorHandling_Python(unittest.TestCase): + module = py_heapq + +class TestErrorHandling_C(TestErrorHandling): + module = c_heapq + #============================================================================== def test_main(verbose=None): - test_classes = [TestHeapPython, TestHeapC, TestErrorHandling] + test_classes = [TestHeapPython, TestHeapC, TestErrorHandling_Python, + TestErrorHandling_C] test_support.run_unittest(*test_classes) # verify reference counting -- cgit v1.2.1 From 0da0db8698b731156ac0a4928d217060ab8c6d11 Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Sat, 7 May 2011 15:19:34 -0700 Subject: Fix cut and paste error. --- Lib/test/test_heapq.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_heapq.py b/Lib/test/test_heapq.py index f0753cf385..fb533dfba2 100644 --- a/Lib/test/test_heapq.py +++ b/Lib/test/test_heapq.py @@ -349,7 +349,7 @@ class TestErrorHandling(unittest.TestCase): self.assertRaises(TypeError, f, 2, N(s)) self.assertRaises(ZeroDivisionError, f, 2, E(s)) -class TestErrorHandling_Python(unittest.TestCase): +class TestErrorHandling_Python(TestErrorHandling): module = py_heapq class TestErrorHandling_C(TestErrorHandling): -- cgit v1.2.1 From 4f2efab870ac997d6b1f2ae9f13278b25330a024 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 8 May 2011 15:32:04 -0500 Subject: import_fresh_module ought to be in __all__ --- Lib/test/test_support.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_support.py b/Lib/test/test_support.py index cb2e03b905..97bfae8373 100644 --- a/Lib/test/test_support.py +++ b/Lib/test/test_support.py @@ -35,7 +35,8 @@ __all__ = ["Error", "TestFailed", "ResourceDenied", "import_module", "run_with_locale", "set_memlimit", "bigmemtest", "bigaddrspacetest", "BasicTestRunner", "run_unittest", "run_doctest", "threading_setup", "threading_cleanup", "reap_children", "cpython_only", - "check_impl_detail", "get_attribute", "py3k_bytes"] + "check_impl_detail", "get_attribute", "py3k_bytes", + "import_fresh_module"] class Error(Exception): -- cgit v1.2.1 From 760c8b1cff5ebeb37d265dd39319f0b560043302 Mon Sep 17 00:00:00 2001 From: Ezio Melotti Date: Mon, 9 May 2011 03:54:30 +0300 Subject: Add a note to the str.find doc to suggest the use of the "in" operator. --- Doc/library/stdtypes.rst | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index 64496326f7..0e32348b9b 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -944,6 +944,15 @@ string functions based on regular expressions. *start* and *end* are interpreted as in slice notation. Return ``-1`` if *sub* is not found. + .. note:: + + The :meth:`~str.find` method should be used only if you need to know the + position of *sub*. To check if *sub* is a substring or not, use the + :keyword:`in` operator:: + + >>> 'Py' in 'Python' + True + .. method:: str.format(*args, **kwargs) -- cgit v1.2.1 From d0dfbaed094ea8af18aaac9d0db1ffac5ea0c9a6 Mon Sep 17 00:00:00 2001 From: Ezio Melotti Date: Mon, 9 May 2011 05:58:17 +0300 Subject: Fix deprecation warnings in test_unittest. --- Lib/unittest/test/test_result.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Lib/unittest/test/test_result.py b/Lib/unittest/test/test_result.py index f0f3a639c0..eb68c1d01c 100644 --- a/Lib/unittest/test/test_result.py +++ b/Lib/unittest/test/test_result.py @@ -503,7 +503,7 @@ class TestOutputBuffering(unittest.TestCase): class Foo(unittest.TestCase): @classmethod def setUpClass(cls): - 1/0 + 1//0 def test_foo(self): pass suite = unittest.TestSuite([Foo('test_foo')]) @@ -517,7 +517,7 @@ class TestOutputBuffering(unittest.TestCase): class Foo(unittest.TestCase): @classmethod def tearDownClass(cls): - 1/0 + 1//0 def test_foo(self): pass suite = unittest.TestSuite([Foo('test_foo')]) @@ -534,7 +534,7 @@ class TestOutputBuffering(unittest.TestCase): class Module(object): @staticmethod def setUpModule(): - 1/0 + 1//0 Foo.__module__ = 'Module' sys.modules['Module'] = Module @@ -553,7 +553,7 @@ class TestOutputBuffering(unittest.TestCase): class Module(object): @staticmethod def tearDownModule(): - 1/0 + 1//0 Foo.__module__ = 'Module' sys.modules['Module'] = Module -- cgit v1.2.1 From 49e05585eae364183f70a36e05b5285a95fc6f5b Mon Sep 17 00:00:00 2001 From: Ezio Melotti Date: Mon, 9 May 2011 06:28:42 +0300 Subject: #11910: change import_fresh_module to return None when one of the "fresh" modules can not be imported. --- Lib/test/test_support.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_support.py b/Lib/test/test_support.py index 97bfae8373..df4d1241a6 100644 --- a/Lib/test/test_support.py +++ b/Lib/test/test_support.py @@ -84,12 +84,14 @@ def import_module(name, deprecated=False): def _save_and_remove_module(name, orig_modules): """Helper function to save and remove a module from sys.modules - Return value is True if the module was in sys.modules and - False otherwise.""" + Return True if the module was in sys.modules, False otherwise. + Raise ImportError if the module can't be imported.""" saved = True try: orig_modules[name] = sys.modules[name] except KeyError: + # try to import the module and raise an error if it can't be imported + __import__(name) saved = False else: del sys.modules[name] @@ -99,8 +101,7 @@ def _save_and_remove_module(name, orig_modules): def _save_and_block_module(name, orig_modules): """Helper function to save and block a module in sys.modules - Return value is True if the module was in sys.modules and - False otherwise.""" + Return True if the module was in sys.modules, False otherwise.""" saved = True try: orig_modules[name] = sys.modules[name] @@ -116,6 +117,7 @@ def import_fresh_module(name, fresh=(), blocked=(), deprecated=False): the sys.modules cache is restored to its original state. Modules named in fresh are also imported anew if needed by the import. + If one of these modules can't be imported, None is returned. Importing of modules named in blocked is prevented while the fresh import takes place. @@ -137,6 +139,8 @@ def import_fresh_module(name, fresh=(), blocked=(), deprecated=False): if not _save_and_block_module(blocked_name, orig_modules): names_to_remove.append(blocked_name) fresh_module = importlib.import_module(name) + except ImportError: + fresh_module = None finally: for orig_name, module in orig_modules.items(): sys.modules[orig_name] = module -- cgit v1.2.1 From 315ed7bebe6c2c60372e83687d6d8c220f584f98 Mon Sep 17 00:00:00 2001 From: Ezio Melotti Date: Mon, 9 May 2011 06:54:53 +0300 Subject: #11910: Fix test_heapq to skip the C tests when _heapq is missing. --- Lib/test/test_heapq.py | 44 +++++++++++++++++++++++++++++--------------- Misc/NEWS | 2 ++ 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/Lib/test/test_heapq.py b/Lib/test/test_heapq.py index fb533dfba2..8cf6d4dd8f 100644 --- a/Lib/test/test_heapq.py +++ b/Lib/test/test_heapq.py @@ -1,16 +1,31 @@ """Unittests for heapq.""" +import sys import random -import unittest + from test import test_support -import sys +from unittest import TestCase, skipUnless -# We do a bit of trickery here to be able to test both the C implementation -# and the Python implementation of the module. -import heapq as c_heapq py_heapq = test_support.import_fresh_module('heapq', blocked=['_heapq']) +c_heapq = test_support.import_fresh_module('heapq', fresh=['_heapq']) + +# _heapq.nlargest/nsmallest are saved in heapq._nlargest/_smallest when +# _heapq is imported, so check them there +func_names = ['heapify', 'heappop', 'heappush', 'heappushpop', + 'heapreplace', '_nlargest', '_nsmallest'] + +class TestModules(TestCase): + def test_py_functions(self): + for fname in func_names: + self.assertEqual(getattr(py_heapq, fname).__module__, 'heapq') + + @skipUnless(c_heapq, 'requires _heapq') + def test_c_functions(self): + for fname in func_names: + self.assertEqual(getattr(c_heapq, fname).__module__, '_heapq') -class TestHeap(unittest.TestCase): + +class TestHeap(TestCase): module = None def test_push_pop(self): @@ -175,16 +190,12 @@ class TestHeap(unittest.TestCase): self.assertEqual(self.module.nlargest(n, data, key=f), sorted(data, key=f, reverse=True)[:n]) + class TestHeapPython(TestHeap): module = py_heapq - # As an early adopter, we sanity check the - # test_support.import_fresh_module utility function - def test_pure_python(self): - self.assertFalse(sys.modules['heapq'] is self.module) - self.assertTrue(hasattr(self.module.heapify, 'func_code')) - +@skipUnless(c_heapq, 'requires _heapq') class TestHeapC(TestHeap): module = c_heapq @@ -304,7 +315,7 @@ def L(seqn): 'Test multiple tiers of iterators' return chain(imap(lambda x:x, R(Ig(G(seqn))))) -class TestErrorHandling(unittest.TestCase): +class TestErrorHandling(TestCase): def test_non_sequence(self): for f in (self.module.heapify, self.module.heappop): @@ -349,9 +360,12 @@ class TestErrorHandling(unittest.TestCase): self.assertRaises(TypeError, f, 2, N(s)) self.assertRaises(ZeroDivisionError, f, 2, E(s)) + class TestErrorHandling_Python(TestErrorHandling): module = py_heapq + +@skipUnless(c_heapq, 'requires _heapq') class TestErrorHandling_C(TestErrorHandling): module = c_heapq @@ -360,8 +374,8 @@ class TestErrorHandling_C(TestErrorHandling): def test_main(verbose=None): - test_classes = [TestHeapPython, TestHeapC, TestErrorHandling_Python, - TestErrorHandling_C] + test_classes = [TestModules, TestHeapPython, TestHeapC, + TestErrorHandling_Python, TestErrorHandling_C] test_support.run_unittest(*test_classes) # verify reference counting diff --git a/Misc/NEWS b/Misc/NEWS index 36d0080694..08d15308bc 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -421,6 +421,8 @@ IDLE Tests ----- +- Issue #11910: Fix test_heapq to skip the C tests when _heapq is missing. + - Fix test_startfile to wait for child process to terminate before finishing. - Issue #11719: Fix message about unexpected test_msilib skip on non-Windows -- cgit v1.2.1 From 81b01802092ce74087e371a7bf48908b4657ee6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20v=2E=20L=C3=B6wis?= Date: Mon, 9 May 2011 08:19:13 +0200 Subject: Issue 11164: Remove obsolete allnodes test from minidom test. Patch by Arfrever Frehtes Taifersar Arahesis. --- Lib/test/test_minidom.py | 20 -------------------- Misc/NEWS | 2 ++ 2 files changed, 2 insertions(+), 20 deletions(-) diff --git a/Lib/test/test_minidom.py b/Lib/test/test_minidom.py index efb9240767..7b7524a122 100644 --- a/Lib/test/test_minidom.py +++ b/Lib/test/test_minidom.py @@ -46,26 +46,6 @@ def create_doc_with_doctype(): return doc class MinidomTest(unittest.TestCase): - def tearDown(self): - try: - Node.allnodes - except AttributeError: - # We don't actually have the minidom from the standard library, - # but are picking up the PyXML version from site-packages. - pass - else: - self.confirm(len(Node.allnodes) == 0, - "assertion: len(Node.allnodes) == 0") - if len(Node.allnodes): - print "Garbage left over:" - if verbose: - print Node.allnodes.items()[0:10] - else: - # Don't print specific nodes if repeatable results - # are needed - print len(Node.allnodes) - Node.allnodes = {} - def confirm(self, test, testname = "Test"): self.assertTrue(test, testname) diff --git a/Misc/NEWS b/Misc/NEWS index 08d15308bc..13778650c6 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -77,6 +77,8 @@ Core and Builtins Library ------- +- Issue #11164: Remove obsolete allnodes test from minidom test. + - Issue #11927: SMTP_SSL now uses port 465 by default as documented. Patch by Kasun Herath. -- cgit v1.2.1 From e3dc6fb9c89a5b998b4b97d61a20e6a72bcf3935 Mon Sep 17 00:00:00 2001 From: Ezio Melotti Date: Mon, 9 May 2011 18:32:18 +0300 Subject: Some more tests were incorrectly marked as C specific. --- Lib/test/test_heapq.py | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/Lib/test/test_heapq.py b/Lib/test/test_heapq.py index 8cf6d4dd8f..5932a40c28 100644 --- a/Lib/test/test_heapq.py +++ b/Lib/test/test_heapq.py @@ -190,17 +190,8 @@ class TestHeap(TestCase): self.assertEqual(self.module.nlargest(n, data, key=f), sorted(data, key=f, reverse=True)[:n]) - -class TestHeapPython(TestHeap): - module = py_heapq - - -@skipUnless(c_heapq, 'requires _heapq') -class TestHeapC(TestHeap): - module = c_heapq - def test_comparison_operator(self): - # Issue 3501: Make sure heapq works with both __lt__ and __le__ + # Issue 3051: Make sure heapq works with both __lt__ and __le__ def hsort(data, comp): data = map(comp, data) self.module.heapify(data) @@ -221,6 +212,15 @@ class TestHeapC(TestHeap): self.assertEqual(hsort(data, LE), target) +class TestHeapPython(TestHeap): + module = py_heapq + + +@skipUnless(c_heapq, 'requires _heapq') +class TestHeapC(TestHeap): + module = c_heapq + + #============================================================================== class LenOnly: @@ -316,6 +316,7 @@ def L(seqn): return chain(imap(lambda x:x, R(Ig(G(seqn))))) class TestErrorHandling(TestCase): + module = None def test_non_sequence(self): for f in (self.module.heapify, self.module.heappop): @@ -361,12 +362,12 @@ class TestErrorHandling(TestCase): self.assertRaises(ZeroDivisionError, f, 2, E(s)) -class TestErrorHandling_Python(TestErrorHandling): +class TestErrorHandlingPython(TestErrorHandling): module = py_heapq @skipUnless(c_heapq, 'requires _heapq') -class TestErrorHandling_C(TestErrorHandling): +class TestErrorHandlingC(TestErrorHandling): module = c_heapq @@ -375,7 +376,7 @@ class TestErrorHandling_C(TestErrorHandling): def test_main(verbose=None): test_classes = [TestModules, TestHeapPython, TestHeapC, - TestErrorHandling_Python, TestErrorHandling_C] + TestErrorHandlingPython, TestErrorHandlingC] test_support.run_unittest(*test_classes) # verify reference counting -- cgit v1.2.1 From a5c3962c4b40d84039b9e48dbe82ed82712fde72 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 10 May 2011 00:22:59 +0200 Subject: (Merge 3.1) Issue #1195: Fix input() if it is interrupted by CTRL+d and then CTRL+c, clear the end-of-file indicator after CTRL+d. --- Misc/NEWS | 3 +++ Parser/myreadline.c | 1 + 2 files changed, 4 insertions(+) diff --git a/Misc/NEWS b/Misc/NEWS index 13778650c6..369d0a3360 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -9,6 +9,9 @@ What's New in Python 2.7.2? Core and Builtins ----------------- +- Issue #1195: Fix input() if it is interrupted by CTRL+d and then CTRL+c, + clear the end-of-file indicator after CTRL+d. + - Issue #8651: PyArg_Parse*() functions raise an OverflowError if the file doesn't have PY_SSIZE_T_CLEAN define and the size doesn't fit in an int (length bigger than 2^31-1 bytes). diff --git a/Parser/myreadline.c b/Parser/myreadline.c index 8a76e0c23b..34fb45c932 100644 --- a/Parser/myreadline.c +++ b/Parser/myreadline.c @@ -77,6 +77,7 @@ my_fgets(char *buf, int len, FILE *fp) } #endif /* MS_WINDOWS */ if (feof(fp)) { + clearerr(fp); return -1; /* EOF */ } #ifdef EINTR -- cgit v1.2.1 From d04aae080f4ec96db68494c659da5d4579e972ba Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 10 May 2011 01:52:03 +0200 Subject: (Merge 3.1) Issue #12012: ssl.PROTOCOL_SSLv2 becomes optional OpenSSL is now compiled with OPENSSL_NO_SSL2 defined (without the SSLv2 protocol) on Debian: fix the ssl module on Debian Testing and Debian Sid. Optimize also ssl.get_protocol_name(): speed does matter! --- Doc/library/ssl.rst | 3 +++ Lib/ssl.py | 24 +++++++++++++----------- Lib/test/test_ssl.py | 49 +++++++++++++++++++++++++++---------------------- Misc/NEWS | 2 ++ Modules/_ssl.c | 8 +++++++- 5 files changed, 52 insertions(+), 34 deletions(-) diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst index a7e78bd6e2..f4cac3a14a 100644 --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -237,6 +237,9 @@ Functions, Constants, and Exceptions Selects SSL version 2 as the channel encryption protocol. + This protocol is not available if OpenSSL is compiled with OPENSSL_NO_SSL2 + flag. + .. warning:: SSL version 2 is insecure. Its use is highly discouraged. diff --git a/Lib/ssl.py b/Lib/ssl.py index 72fbae57ff..f3e5123976 100644 --- a/Lib/ssl.py +++ b/Lib/ssl.py @@ -62,7 +62,6 @@ import _ssl # if we can't import it, let the error propagate from _ssl import OPENSSL_VERSION_NUMBER, OPENSSL_VERSION_INFO, OPENSSL_VERSION from _ssl import SSLError from _ssl import CERT_NONE, CERT_OPTIONAL, CERT_REQUIRED -from _ssl import PROTOCOL_SSLv2, PROTOCOL_SSLv3, PROTOCOL_SSLv23, PROTOCOL_TLSv1 from _ssl import RAND_status, RAND_egd, RAND_add from _ssl import \ SSL_ERROR_ZERO_RETURN, \ @@ -74,6 +73,18 @@ from _ssl import \ SSL_ERROR_WANT_CONNECT, \ SSL_ERROR_EOF, \ SSL_ERROR_INVALID_ERROR_CODE +from _ssl import PROTOCOL_SSLv3, PROTOCOL_SSLv23, PROTOCOL_TLSv1 +_PROTOCOL_NAMES = { + PROTOCOL_TLSv1: "TLSv1", + PROTOCOL_SSLv23: "SSLv23", + PROTOCOL_SSLv3: "SSLv3", +} +try: + from _ssl import PROTOCOL_SSLv2 +except ImportError: + pass +else: + _PROTOCOL_NAMES[PROTOCOL_SSLv2] = "SSLv2" from socket import socket, _fileobject, _delegate_methods, error as socket_error from socket import getnameinfo as _getnameinfo @@ -425,16 +436,7 @@ def get_server_certificate(addr, ssl_version=PROTOCOL_SSLv3, ca_certs=None): return DER_cert_to_PEM_cert(dercert) def get_protocol_name(protocol_code): - if protocol_code == PROTOCOL_TLSv1: - return "TLSv1" - elif protocol_code == PROTOCOL_SSLv23: - return "SSLv23" - elif protocol_code == PROTOCOL_SSLv2: - return "SSLv2" - elif protocol_code == PROTOCOL_SSLv3: - return "SSLv3" - else: - return "" + return _PROTOCOL_NAMES.get(protocol_code, '') # a replacement for the old socket.ssl function diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index 2567218415..be2f51acaf 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -58,32 +58,35 @@ class BasicTests(unittest.TestCase): # Issue #9415: Ubuntu hijacks their OpenSSL and forcefully disables SSLv2 def skip_if_broken_ubuntu_ssl(func): - # We need to access the lower-level wrapper in order to create an - # implicit SSL context without trying to connect or listen. - try: - import _ssl - except ImportError: - # The returned function won't get executed, just ignore the error - pass - @functools.wraps(func) - def f(*args, **kwargs): + if hasattr(ssl, 'PROTOCOL_SSLv2'): + # We need to access the lower-level wrapper in order to create an + # implicit SSL context without trying to connect or listen. try: - s = socket.socket(socket.AF_INET) - _ssl.sslwrap(s._sock, 0, None, None, - ssl.CERT_NONE, ssl.PROTOCOL_SSLv2, None, None) - except ssl.SSLError as e: - if (ssl.OPENSSL_VERSION_INFO == (0, 9, 8, 15, 15) and - platform.linux_distribution() == ('debian', 'squeeze/sid', '') - and 'Invalid SSL protocol variant specified' in str(e)): - raise unittest.SkipTest("Patched Ubuntu OpenSSL breaks behaviour") - return func(*args, **kwargs) - return f + import _ssl + except ImportError: + # The returned function won't get executed, just ignore the error + pass + @functools.wraps(func) + def f(*args, **kwargs): + try: + s = socket.socket(socket.AF_INET) + _ssl.sslwrap(s._sock, 0, None, None, + ssl.CERT_NONE, ssl.PROTOCOL_SSLv2, None, None) + except ssl.SSLError as e: + if (ssl.OPENSSL_VERSION_INFO == (0, 9, 8, 15, 15) and + platform.linux_distribution() == ('debian', 'squeeze/sid', '') + and 'Invalid SSL protocol variant specified' in str(e)): + raise unittest.SkipTest("Patched Ubuntu OpenSSL breaks behaviour") + return func(*args, **kwargs) + return f + else: + return func class BasicSocketTests(unittest.TestCase): def test_constants(self): - ssl.PROTOCOL_SSLv2 + #ssl.PROTOCOL_SSLv2 ssl.PROTOCOL_SSLv23 ssl.PROTOCOL_SSLv3 ssl.PROTOCOL_TLSv1 @@ -1008,7 +1011,8 @@ else: try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True) try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL) try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED) - try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False) + if hasattr(ssl, 'PROTOCOL_SSLv2'): + try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False) try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False) try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False) @@ -1020,7 +1024,8 @@ else: try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True) try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL) try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED) - try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False) + if hasattr(ssl, 'PROTOCOL_SSLv2'): + try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False) try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False) try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False) diff --git a/Misc/NEWS b/Misc/NEWS index 369d0a3360..0214c0befb 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -80,6 +80,8 @@ Core and Builtins Library ------- +- Issue #12012: ssl.PROTOCOL_SSLv2 becomes optional. + - Issue #11164: Remove obsolete allnodes test from minidom test. - Issue #11927: SMTP_SSL now uses port 465 by default as documented. Patch diff --git a/Modules/_ssl.c b/Modules/_ssl.c index 6ed0f4fa0a..5af5bdeb70 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -62,8 +62,10 @@ enum py_ssl_cert_requirements { }; enum py_ssl_version { +#ifndef OPENSSL_NO_SSL2 PY_SSL_VERSION_SSL2, - PY_SSL_VERSION_SSL3, +#endif + PY_SSL_VERSION_SSL3=1, PY_SSL_VERSION_SSL23, PY_SSL_VERSION_TLS1 }; @@ -302,8 +304,10 @@ newPySSLObject(PySocketSockObject *Sock, char *key_file, char *cert_file, self->ctx = SSL_CTX_new(TLSv1_method()); /* Set up context */ else if (proto_version == PY_SSL_VERSION_SSL3) self->ctx = SSL_CTX_new(SSLv3_method()); /* Set up context */ +#ifndef OPENSSL_NO_SSL2 else if (proto_version == PY_SSL_VERSION_SSL2) self->ctx = SSL_CTX_new(SSLv2_method()); /* Set up context */ +#endif else if (proto_version == PY_SSL_VERSION_SSL23) self->ctx = SSL_CTX_new(SSLv23_method()); /* Set up context */ PySSL_END_ALLOW_THREADS @@ -1708,8 +1712,10 @@ init_ssl(void) PY_SSL_CERT_REQUIRED); /* protocol versions */ +#ifndef OPENSSL_NO_SSL2 PyModule_AddIntConstant(m, "PROTOCOL_SSLv2", PY_SSL_VERSION_SSL2); +#endif PyModule_AddIntConstant(m, "PROTOCOL_SSLv3", PY_SSL_VERSION_SSL3); PyModule_AddIntConstant(m, "PROTOCOL_SSLv23", -- cgit v1.2.1 From e1a2bb917ddf2d0d9a89417d204cfbc2f95e603d Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Tue, 10 May 2011 00:39:02 -0700 Subject: Issue 12047: Expand the style guide. --- Doc/documenting/style.rst | 104 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/Doc/documenting/style.rst b/Doc/documenting/style.rst index c3dded9b77..80955fda58 100644 --- a/Doc/documenting/style.rst +++ b/Doc/documenting/style.rst @@ -65,6 +65,110 @@ Unix The name of the operating system developed at AT&T Bell Labs in the early 1970s. +Affirmative Tone +---------------- + +The documentation focuses on affirmatively stating what the language does and +how to use it effectively. + +Except for certain security risks or segfault risks, the docs should avoid +wording along the lines of "feature x is dangerous" or "experts only". These +kinds of value judgments belong in external blogs and wikis, not in the core +documentation. + +Bad example (creating worry in the mind of a reader): + + Warning: failing to explicitly close a file could result in lost data or + excessive resource consumption. Never rely on reference counting to + automatically close a file. + +Good example (establishing confident knowledge in the effective use of the language): + + A best practice for using files is use a try/finally pair to explicitly + close a file after it is used. Alternatively, using a with-statement can + achieve the same effect. This assures that files are flushed and file + descriptor resources are released in a timely manner. + +Economy of Expression +--------------------- + +More documentation is not necessarily better documentation. Error on the side +of being succinct. + +It is an unfortunate fact that making documentation longer can be an impediment +to understanding and can result in even more ways to misread or misinterpret the +text. Long descriptions full of corner cases and caveats can create the +impression that a function is more complex or harder to use than it actually is. + +The documentation for :func:`super` is an example of where a good deal of +information was condensed into a few short paragraphs. Discussion of +:func:`super` could have filled a chapter in a book, but it is often easier to +grasp a terse description than a lengthy narrative. + + +Code Examples +------------- + +Short code examples can be a useful adjunct to understanding. Readers can often +grasp a simple example more quickly than they can digest a formal description in +prose. + +People learn faster with concrete, motivating examples that match the context of +a typical use case. For instance, the :func:`str.rpartition` method is better +demonstrated with an example splitting the domain from a URL than it would be +with an example of removing the last word from a line of Monty Python dialog. + +The ellipsis for the :attr:`sys.ps2` secondary interpreter prompt should only be +used sparingly, where it is necessary to clearly differentiate between input +lines and output lines. Besides contributing visual clutter, it makes it +difficult for readers to cut-and-paste examples so they can experiment with +variations. + +Code Equivalents +---------------- + +Giving pure Python code equivalents (or approximate equivalents) can be a useful +adjunct to a prose description. A documenter should carefully weigh whether the +code equivalent adds value. + +A good example is the code equivalent for :func:`all`. The short 4-line code +equivalent is easily digested; it re-emphasizes the early-out behavior; and it +clarifies the handling of the corner-case where the iterable is empty. In +addition, it serves as a model for people wanting to implement a commonly +requested alternative where :func:`all` would return the specific object +evaluating to False whenever the function terminates early. + +A more questionable example is the code for :func:`itertools.groupby`. Its code +equivalent borders on being too complex to be a quick aid to understanding. +Despite its complexity, the code equivalent was kept because it serves as a +model to alternative implementations and because the operation of the "grouper" +is more easily shown in code than in English prose. + +An example of when not to use a code equivalent is for the :func:`oct` function. +The exact steps in converting a number to octal doesn't add value for a user +trying to learn what the function does. + +Audience +-------- + +The tone of the tutorial (and all the docs) needs to be respectful of the +reader's intelligence. Don't presume that the readers are stupid. Lay out the +relevant information, show motivating use cases, provide glossary links, and do +our best to connect-the-dots, but don't talk down to them or waste their time. + +The tutorial is meant for newcomers, many of whom will be using the tutorial to +evaluate the language as a whole. The experience needs to be positive and not +leave the reader with worries that something bad will happen if they make a +misstep. The tutorial serves as guide for intelligent and curious readers, +saving details for the how-to guides and other sources. + +Be careful accepting requests for documentation changes from the rare but vocal +category of reader who is looking for vindication for one of their programming +errors ("I made a mistake, therefore the docs must be wrong ..."). Typically, +the documentation wasn't consulted until after the error was made. It is +unfortunate, but typically no documentation edit would have saved the user from +making false assumptions about the language ("I was surprised by ..."). + .. _Apple Publications Style Guide: http://developer.apple.com/mac/library/documentation/UserExperience/Conceptual/APStyleGuide/APSG_2009.pdf -- cgit v1.2.1 From 32bb603da8b576d1fdfdd3ccebe91cf7dc5d3963 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Tue, 10 May 2011 19:16:03 +0200 Subject: Issue #8498: In socket.accept(), allow to specify 0 as a backlog value in order to accept exactly one connection. Patch by Daniel Evers. --- Doc/library/socket.rst | 4 ++-- Lib/test/test_socket.py | 7 +++++++ Misc/ACKS | 1 + Misc/NEWS | 3 +++ Modules/socketmodule.c | 11 +++++++---- 5 files changed, 20 insertions(+), 6 deletions(-) diff --git a/Doc/library/socket.rst b/Doc/library/socket.rst index 96152f9d39..d6b1e4c5e5 100644 --- a/Doc/library/socket.rst +++ b/Doc/library/socket.rst @@ -644,8 +644,8 @@ correspond to Unix system calls applicable to sockets. .. method:: socket.listen(backlog) Listen for connections made to the socket. The *backlog* argument specifies the - maximum number of queued connections and should be at least 1; the maximum value - is system-dependent (usually 5). + maximum number of queued connections and should be at least 0; the maximum value + is system-dependent (usually 5), the minimum value is forced to 0. .. method:: socket.makefile([mode[, bufsize]]) diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py index 7ee16ebced..12e09dddeb 100644 --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -700,6 +700,13 @@ class GeneralModuleTests(unittest.TestCase): def test_sendall_interrupted_with_timeout(self): self.check_sendall_interrupted(True) + def testListenBacklog0(self): + srv = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + srv.bind((HOST, 0)) + # backlog = 0 + srv.listen(0) + srv.close() + @unittest.skipUnless(thread, 'Threading required for this test.') class BasicTCPTest(SocketConnectedTest): diff --git a/Misc/ACKS b/Misc/ACKS index 9b9ff68523..4270934f23 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -243,6 +243,7 @@ Carey Evans Tim Everett Paul Everitt David Everly +Daniel Evers Greg Ewing Martijn Faassen Clovis Fabricio diff --git a/Misc/NEWS b/Misc/NEWS index 0214c0befb..7517baf648 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -80,6 +80,9 @@ Core and Builtins Library ------- +- Issue #8498: In socket.accept(), allow to specify 0 as a backlog value in + order to accept exactly one connection. Patch by Daniel Evers. + - Issue #12012: ssl.PROTOCOL_SSLv2 becomes optional. - Issue #11164: Remove obsolete allnodes test from minidom test. diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index 96b83b1150..76d860cac5 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -2244,8 +2244,10 @@ sock_listen(PySocketSockObject *s, PyObject *arg) if (backlog == -1 && PyErr_Occurred()) return NULL; Py_BEGIN_ALLOW_THREADS - if (backlog < 1) - backlog = 1; + /* To avoid problems on systems that don't allow a negative backlog + * (which doesn't make sense anyway) we force a minimum value of 0. */ + if (backlog < 0) + backlog = 0; res = listen(s->sock_fd, backlog); Py_END_ALLOW_THREADS if (res < 0) @@ -2258,8 +2260,9 @@ PyDoc_STRVAR(listen_doc, "listen(backlog)\n\ \n\ Enable a server to accept connections. The backlog argument must be at\n\ -least 1; it specifies the number of unaccepted connection that the system\n\ -will allow before refusing new connections."); +least 0 (if it is lower, it is set to 0); it specifies the number of\n\ +unaccepted connections that the system will allow before refusing new\n\ +connections."); #ifndef NO_DUP -- cgit v1.2.1 From e6fa5704a39e757702245eda7a6266c80955b2b2 Mon Sep 17 00:00:00 2001 From: Ezio Melotti Date: Wed, 11 May 2011 00:55:35 +0300 Subject: #12051: Fix segfault in json.dumps() while encoding highly-nested objects using the C accelerations. --- Lib/json/tests/test_recursion.py | 22 +++++++++++++++++++++- Misc/NEWS | 3 +++ Modules/_json.c | 17 +++++++++++++++-- 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/Lib/json/tests/test_recursion.py b/Lib/json/tests/test_recursion.py index 548bb89ed5..1f2d7b3b5c 100644 --- a/Lib/json/tests/test_recursion.py +++ b/Lib/json/tests/test_recursion.py @@ -16,6 +16,11 @@ class RecursiveJSONEncoder(json.JSONEncoder): return 'JSONTestObject' return json.JSONEncoder.default(o) +class EndlessJSONEncoder(json.JSONEncoder): + def default(self, o): + """If check_circular is False, this will keep adding another list.""" + return [o] + class TestRecursion(TestCase): def test_listrecursion(self): @@ -67,7 +72,7 @@ class TestRecursion(TestCase): self.fail("didn't raise ValueError on default recursion") - def test_highly_nested_objects(self): + def test_highly_nested_objects_decoding(self): # test that loading highly-nested objects doesn't segfault when C # accelerations are used. See #12017 # str @@ -84,3 +89,18 @@ class TestRecursion(TestCase): json.loads(u'{"a":' * 100000 + u'[1]' + u'}' * 100000) with self.assertRaises(RuntimeError): json.loads(u'[' * 100000 + u'1' + u']' * 100000) + + def test_highly_nested_objects_encoding(self): + # See #12051 + l, d = [], {} + for x in xrange(100000): + l, d = [l], {'k':d} + with self.assertRaises(RuntimeError): + json.dumps(l) + with self.assertRaises(RuntimeError): + json.dumps(d) + + def test_endless_recursion(self): + # See #12051 + with self.assertRaises(RuntimeError): + EndlessJSONEncoder(check_circular=False).encode(5j) diff --git a/Misc/NEWS b/Misc/NEWS index 7517baf648..90f36a181e 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -373,6 +373,9 @@ Extension Modules - Issue #10169: Fix argument parsing in socket.sendto() to avoid error masking. +- Issue #12051: Fix segfault in json.dumps() while encoding highly-nested + objects using the C accelerations. + - Issue #12017: Fix segfault in json.loads() while decoding highly-nested objects using the C accelerations. diff --git a/Modules/_json.c b/Modules/_json.c index 4b4ef89282..6b321e57f5 100644 --- a/Modules/_json.c +++ b/Modules/_json.c @@ -1999,10 +1999,18 @@ encoder_listencode_obj(PyEncoderObject *s, PyObject *rval, PyObject *obj, Py_ssi return _steal_list_append(rval, encoded); } else if (PyList_Check(obj) || PyTuple_Check(obj)) { - return encoder_listencode_list(s, rval, obj, indent_level); + if (Py_EnterRecursiveCall(" while encoding a JSON object")) + return -1; + rv = encoder_listencode_list(s, rval, obj, indent_level); + Py_LeaveRecursiveCall(); + return rv; } else if (PyDict_Check(obj)) { - return encoder_listencode_dict(s, rval, obj, indent_level); + if (Py_EnterRecursiveCall(" while encoding a JSON object")) + return -1; + rv = encoder_listencode_dict(s, rval, obj, indent_level); + Py_LeaveRecursiveCall(); + return rv; } else { PyObject *ident = NULL; @@ -2028,7 +2036,12 @@ encoder_listencode_obj(PyEncoderObject *s, PyObject *rval, PyObject *obj, Py_ssi Py_XDECREF(ident); return -1; } + + if (Py_EnterRecursiveCall(" while encoding a JSON object")) + return -1; rv = encoder_listencode_obj(s, rval, newobj, indent_level); + Py_LeaveRecursiveCall(); + Py_DECREF(newobj); if (rv) { Py_XDECREF(ident); -- cgit v1.2.1 From 994268f6858412d618168e07fa316cf0e236df8f Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Thu, 12 May 2011 07:47:06 +0200 Subject: #12061: remove duplicate glossary entry. --- Doc/glossary.rst | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/Doc/glossary.rst b/Doc/glossary.rst index 782263460e..fa811442c2 100644 --- a/Doc/glossary.rst +++ b/Doc/glossary.rst @@ -392,26 +392,6 @@ Glossary value is assigned. ``**`` is used to accept or pass a dictionary of keyword arguments. See :term:`argument`. - key function - A key function or collation function is a callable that returns a value - used for sorting or ordering. For example, :func:`locale.strxfrm` is - used to produce a sort key that is aware of locale specific sort - conventions. - - A number of tools in Python accept key functions to control how elements - are ordered or grouped. They include :func:`min`, :func:`max`, - :func:`sorted`, :meth:`list.sort`, :func:`heapq.nsmallest`, - :func:`heapq.nlargest`, and :func:`itertools.groupby`. - - There are several ways to create a key function. For example. the - :meth:`str.lower` method can serve as a key function for case insensitive - sorts. Alternatively, an ad-hoc key function can be built from a - :keyword:`lambda` expression such as ``lambda r: (r[0], r[2])``. Also, - the :mod:`operator` module provides three key function constuctors: - :func:`~operator.attrgetter`, :func:`~operator.itemgetter`, and - :func:`~operator.methodcaller`. See the :ref:`sortinghowto` for - examples of how to create and use key functions. - lambda An anonymous inline function consisting of a single :term:`expression` which is evaluated when the function is called. The syntax to create -- cgit v1.2.1 From 1b737dd131e1395800f53df0de7b06b2fcecb678 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Fri, 13 May 2011 00:31:52 +0200 Subject: Issue #12062: In the `io` module, fix a flushing bug when doing a certain type of I/O sequence on a file opened in read+write mode (namely: reading, seeking a bit forward, writing, then seeking before the previous write but still within buffered data, and writing again). --- Lib/test/test_io.py | 26 ++++++++++++++++++++++++++ Misc/NEWS | 5 +++++ Modules/_io/bufferedio.c | 2 +- 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py index 0bad56deba..8af8a64622 100644 --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -1462,6 +1462,32 @@ class BufferedRandomTest(BufferedReaderTest, BufferedWriterTest): self.assertEqual(s, b"A" + b"B" * overwrite_size + b"A" * (9 - overwrite_size)) + def test_write_rewind_write(self): + # Various combinations of reading / writing / seeking backwards / writing again + def mutate(bufio, pos1, pos2): + assert pos2 >= pos1 + # Fill the buffer + bufio.seek(pos1) + bufio.read(pos2 - pos1) + bufio.write(b'\x02') + # This writes earlier than the previous write, but still inside + # the buffer. + bufio.seek(pos1) + bufio.write(b'\x01') + + b = b"\x80\x81\x82\x83\x84" + for i in range(0, len(b)): + for j in range(i, len(b)): + raw = self.BytesIO(b) + bufio = self.tp(raw, 100) + mutate(bufio, i, j) + bufio.flush() + expected = bytearray(b) + expected[j] = 2 + expected[i] = 1 + self.assertEqual(raw.getvalue(), expected, + "failed result for i=%d, j=%d" % (i, j)) + def test_truncate_after_read_or_write(self): raw = self.BytesIO(b"A" * 10) bufio = self.tp(raw, 100) diff --git a/Misc/NEWS b/Misc/NEWS index 90f36a181e..34f311bc9a 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -80,6 +80,11 @@ Core and Builtins Library ------- +- Issue #12062: In the `io` module, fix a flushing bug when doing a certain + type of I/O sequence on a file opened in read+write mode (namely: reading, + seeking a bit forward, writing, then seeking before the previous write but + still within buffered data, and writing again). + - Issue #8498: In socket.accept(), allow to specify 0 as a backlog value in order to accept exactly one connection. Patch by Daniel Evers. diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c index 5816a93432..144aea20d8 100644 --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -1810,7 +1810,7 @@ bufferedwriter_write(buffered *self, PyObject *args) avail = Py_SAFE_DOWNCAST(self->buffer_size - self->pos, Py_off_t, Py_ssize_t); if (buf.len <= avail) { memcpy(self->buffer + self->pos, buf.buf, buf.len); - if (!VALID_WRITE_BUFFER(self)) { + if (!VALID_WRITE_BUFFER(self) || self->write_pos > self->pos) { self->write_pos = self->pos; } ADJUST_POSITION(self, self->pos + buf.len); -- cgit v1.2.1 From fba3758032d9831b9cc4a717aa9fb02bbf9cc598 Mon Sep 17 00:00:00 2001 From: "Kurt B. Kaiser" Date: Thu, 12 May 2011 21:18:47 -0400 Subject: Issue #11896: Save on Close failed despite selecting "Yes" in dialog. Backport 70055:35ed0efd7dd3 --- Lib/idlelib/IOBinding.py | 44 ++++++++++++++++++++++---------------------- Lib/idlelib/NEWS.txt | 6 +++++- Lib/idlelib/ScriptBinding.py | 16 +++++++--------- 3 files changed, 34 insertions(+), 32 deletions(-) diff --git a/Lib/idlelib/IOBinding.py b/Lib/idlelib/IOBinding.py index a5b610ef87..a8c351fa8c 100644 --- a/Lib/idlelib/IOBinding.py +++ b/Lib/idlelib/IOBinding.py @@ -320,17 +320,20 @@ class IOBinding: return "yes" message = "Do you want to save %s before closing?" % ( self.filename or "this untitled document") - m = tkMessageBox.Message( - title="Save On Close", - message=message, - icon=tkMessageBox.QUESTION, - type=tkMessageBox.YESNOCANCEL, - master=self.text) - reply = m.show() - if reply == "yes": + confirm = tkMessageBox.askyesnocancel( + title="Save On Close", + message=message, + default=tkMessageBox.YES, + master=self.text) + if confirm: + reply = "yes" self.save(None) if not self.get_saved(): reply = "cancel" + elif confirm is None: + reply = "cancel" + else: + reply = "no" self.text.focus_set() return reply @@ -339,7 +342,7 @@ class IOBinding: self.save_as(event) else: if self.writefile(self.filename): - self.set_saved(1) + self.set_saved(True) try: self.editwin.store_file_breaks() except AttributeError: # may be a PyShell @@ -465,15 +468,12 @@ class IOBinding: self.text.insert("end-1c", "\n") def print_window(self, event): - m = tkMessageBox.Message( - title="Print", - message="Print to Default Printer", - icon=tkMessageBox.QUESTION, - type=tkMessageBox.OKCANCEL, - default=tkMessageBox.OK, - master=self.text) - reply = m.show() - if reply != tkMessageBox.OK: + confirm = tkMessageBox.askokcancel( + title="Print", + message="Print to Default Printer", + default=tkMessageBox.OK, + master=self.text) + if not confirm: self.text.focus_set() return "break" tempfilename = None @@ -488,8 +488,8 @@ class IOBinding: if not self.writefile(tempfilename): os.unlink(tempfilename) return "break" - platform=os.name - printPlatform=1 + platform = os.name + printPlatform = True if platform == 'posix': #posix platform command = idleConf.GetOption('main','General', 'print-command-posix') @@ -497,7 +497,7 @@ class IOBinding: elif platform == 'nt': #win32 platform command = idleConf.GetOption('main','General','print-command-win') else: #no printing for this platform - printPlatform=0 + printPlatform = False if printPlatform: #we can try to print for this platform command = command % filename pipe = os.popen(command, "r") @@ -511,7 +511,7 @@ class IOBinding: output = "Printing command: %s\n" % repr(command) + output tkMessageBox.showerror("Print status", output, master=self.text) else: #no printing for this platform - message="Printing is not enabled for this platform: %s" % platform + message = "Printing is not enabled for this platform: %s" % platform tkMessageBox.showinfo("Print status", message, master=self.text) if tempfilename: os.unlink(tempfilename) diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt index 5eac219b2f..e0af3616e9 100644 --- a/Lib/idlelib/NEWS.txt +++ b/Lib/idlelib/NEWS.txt @@ -3,8 +3,12 @@ What's New in IDLE 2.7.2? *Release date: XX-XX-XXXX* + +- Issue #11896: Save on Close failed despite selecting "Yes" in dialog. + - toggle failing on Tk 8.5, causing IDLE exits and strange selection behavior. Issue 4676. Improve selection extension behaviour. + - toggle non-functional when NumLock set on Windows. Issue 3851. @@ -31,7 +35,7 @@ What's New in IDLE 2.7? - Tk 8.5 Text widget requires 'wordprocessor' tabstyle attr to handle mixed space/tab properly. Issue 5129, patch by Guilherme Polo. - + - Issue #3549: On MacOS the preferences menu was not present diff --git a/Lib/idlelib/ScriptBinding.py b/Lib/idlelib/ScriptBinding.py index 3a441650a9..9a16e3c779 100644 --- a/Lib/idlelib/ScriptBinding.py +++ b/Lib/idlelib/ScriptBinding.py @@ -184,9 +184,9 @@ class ScriptBinding: if autosave and filename: self.editwin.io.save(None) else: - reply = self.ask_save_dialog() + confirm = self.ask_save_dialog() self.editwin.text.focus_set() - if reply == "ok": + if confirm: self.editwin.io.save(None) filename = self.editwin.io.filename else: @@ -195,13 +195,11 @@ class ScriptBinding: def ask_save_dialog(self): msg = "Source Must Be Saved\n" + 5*' ' + "OK to Save?" - mb = tkMessageBox.Message(title="Save Before Run or Check", - message=msg, - icon=tkMessageBox.QUESTION, - type=tkMessageBox.OKCANCEL, - default=tkMessageBox.OK, - master=self.editwin.text) - return mb.show() + confirm = tkMessageBox.askokcancel(title="Save Before Run or Check", + message=msg, + default=tkMessageBox.OK, + master=self.editwin.text) + return confirm def errorbox(self, title, message): # XXX This should really be a function of EditorWindow... -- cgit v1.2.1 From 3c06dbd9531a4996db571d81a8319768d56030ae Mon Sep 17 00:00:00 2001 From: Ezio Melotti Date: Sat, 14 May 2011 06:02:25 +0300 Subject: Change import_fresh_module to work with packages. --- Lib/test/test_support.py | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/Lib/test/test_support.py b/Lib/test/test_support.py index df4d1241a6..04ab443a4b 100644 --- a/Lib/test/test_support.py +++ b/Lib/test/test_support.py @@ -84,19 +84,15 @@ def import_module(name, deprecated=False): def _save_and_remove_module(name, orig_modules): """Helper function to save and remove a module from sys.modules - Return True if the module was in sys.modules, False otherwise. Raise ImportError if the module can't be imported.""" - saved = True - try: - orig_modules[name] = sys.modules[name] - except KeyError: - # try to import the module and raise an error if it can't be imported + # try to import the module and raise an error if it can't be imported + if name not in sys.modules: __import__(name) - saved = False - else: del sys.modules[name] - return saved - + for modname in list(sys.modules): + if modname == name or modname.startswith(name + '.'): + orig_modules[modname] = sys.modules[modname] + del sys.modules[modname] def _save_and_block_module(name, orig_modules): """Helper function to save and block a module in sys.modules -- cgit v1.2.1 From 57534a7af2c74b84ab859373cd8ede12961aba0e Mon Sep 17 00:00:00 2001 From: Ezio Melotti Date: Sat, 14 May 2011 06:24:53 +0300 Subject: #5723: Improve json tests to be executed with and without accelerations. --- Lib/json/decoder.py | 4 +- Lib/json/tests/__init__.py | 46 ++++++++++++++++-- Lib/json/tests/test_check_circular.py | 24 ++++++---- Lib/json/tests/test_decode.py | 37 ++++++++------- Lib/json/tests/test_default.py | 13 +++-- Lib/json/tests/test_dump.py | 16 ++++--- Lib/json/tests/test_encode_basestring_ascii.py | 28 +++++------ Lib/json/tests/test_fail.py | 18 +++---- Lib/json/tests/test_float.py | 23 +++++---- Lib/json/tests/test_indent.py | 23 +++++---- Lib/json/tests/test_pass1.py | 17 ++++--- Lib/json/tests/test_pass2.py | 16 ++++--- Lib/json/tests/test_pass3.py | 16 ++++--- Lib/json/tests/test_recursion.py | 66 +++++++++++++------------- Lib/json/tests/test_scanstring.py | 32 +++++-------- Lib/json/tests/test_separators.py | 18 +++---- Lib/json/tests/test_speedups.py | 28 +++++------ Lib/json/tests/test_unicode.py | 53 +++++++++++---------- Lib/test/test_support.py | 4 +- Misc/NEWS | 2 + 20 files changed, 271 insertions(+), 213 deletions(-) diff --git a/Lib/json/decoder.py b/Lib/json/decoder.py index eeebf45868..1f2da72ffb 100644 --- a/Lib/json/decoder.py +++ b/Lib/json/decoder.py @@ -4,7 +4,7 @@ import re import sys import struct -from json.scanner import make_scanner +from json import scanner try: from _json import scanstring as c_scanstring except ImportError: @@ -356,7 +356,7 @@ class JSONDecoder(object): self.parse_object = JSONObject self.parse_array = JSONArray self.parse_string = scanstring - self.scan_once = make_scanner(self) + self.scan_once = scanner.make_scanner(self) def decode(self, s, _w=WHITESPACE.match): """Return the Python representation of ``s`` (a ``str`` or ``unicode`` diff --git a/Lib/json/tests/__init__.py b/Lib/json/tests/__init__.py index 1a1e3e6d5a..90cb2b7ad6 100644 --- a/Lib/json/tests/__init__.py +++ b/Lib/json/tests/__init__.py @@ -1,7 +1,46 @@ import os import sys -import unittest +import json import doctest +import unittest + +from test import test_support + +# import json with and without accelerations +cjson = test_support.import_fresh_module('json', fresh=['_json']) +pyjson = test_support.import_fresh_module('json', blocked=['_json']) + +# create two base classes that will be used by the other tests +class PyTest(unittest.TestCase): + json = pyjson + loads = staticmethod(pyjson.loads) + dumps = staticmethod(pyjson.dumps) + +@unittest.skipUnless(cjson, 'requires _json') +class CTest(unittest.TestCase): + if cjson is not None: + json = cjson + loads = staticmethod(cjson.loads) + dumps = staticmethod(cjson.dumps) + +# test PyTest and CTest checking if the functions come from the right module +class TestPyTest(PyTest): + def test_pyjson(self): + self.assertEqual(self.json.scanner.make_scanner.__module__, + 'json.scanner') + self.assertEqual(self.json.decoder.scanstring.__module__, + 'json.decoder') + self.assertEqual(self.json.encoder.encode_basestring_ascii.__module__, + 'json.encoder') + +class TestCTest(CTest): + def test_cjson(self): + self.assertEqual(self.json.scanner.make_scanner.__module__, '_json') + self.assertEqual(self.json.decoder.scanstring.__module__, '_json') + self.assertEqual(self.json.encoder.c_make_encoder.__module__, '_json') + self.assertEqual(self.json.encoder.encode_basestring_ascii.__module__, + '_json') + here = os.path.dirname(__file__) @@ -17,12 +56,11 @@ def test_suite(): return suite def additional_tests(): - import json - import json.encoder - import json.decoder suite = unittest.TestSuite() for mod in (json, json.encoder, json.decoder): suite.addTest(doctest.DocTestSuite(mod)) + suite.addTest(TestPyTest('test_pyjson')) + suite.addTest(TestCTest('test_cjson')) return suite def main(): diff --git a/Lib/json/tests/test_check_circular.py b/Lib/json/tests/test_check_circular.py index 3c3f96ad71..3ad3d24196 100644 --- a/Lib/json/tests/test_check_circular.py +++ b/Lib/json/tests/test_check_circular.py @@ -1,30 +1,34 @@ -from unittest import TestCase -import json +from json.tests import PyTest, CTest + def default_iterable(obj): return list(obj) -class TestCheckCircular(TestCase): +class TestCheckCircular(object): def test_circular_dict(self): dct = {} dct['a'] = dct - self.assertRaises(ValueError, json.dumps, dct) + self.assertRaises(ValueError, self.dumps, dct) def test_circular_list(self): lst = [] lst.append(lst) - self.assertRaises(ValueError, json.dumps, lst) + self.assertRaises(ValueError, self.dumps, lst) def test_circular_composite(self): dct2 = {} dct2['a'] = [] dct2['a'].append(dct2) - self.assertRaises(ValueError, json.dumps, dct2) + self.assertRaises(ValueError, self.dumps, dct2) def test_circular_default(self): - json.dumps([set()], default=default_iterable) - self.assertRaises(TypeError, json.dumps, [set()]) + self.dumps([set()], default=default_iterable) + self.assertRaises(TypeError, self.dumps, [set()]) def test_circular_off_default(self): - json.dumps([set()], default=default_iterable, check_circular=False) - self.assertRaises(TypeError, json.dumps, [set()], check_circular=False) + self.dumps([set()], default=default_iterable, check_circular=False) + self.assertRaises(TypeError, self.dumps, [set()], check_circular=False) + + +class TestPyCheckCircular(TestCheckCircular, PyTest): pass +class TestCCheckCircular(TestCheckCircular, CTest): pass diff --git a/Lib/json/tests/test_decode.py b/Lib/json/tests/test_decode.py index 082159560d..aa8bbe9b54 100644 --- a/Lib/json/tests/test_decode.py +++ b/Lib/json/tests/test_decode.py @@ -1,18 +1,17 @@ import decimal -from unittest import TestCase from StringIO import StringIO - -import json from collections import OrderedDict +from json.tests import PyTest, CTest + -class TestDecode(TestCase): +class TestDecode(object): def test_decimal(self): - rval = json.loads('1.1', parse_float=decimal.Decimal) + rval = self.loads('1.1', parse_float=decimal.Decimal) self.assertTrue(isinstance(rval, decimal.Decimal)) self.assertEqual(rval, decimal.Decimal('1.1')) def test_float(self): - rval = json.loads('1', parse_int=float) + rval = self.loads('1', parse_int=float) self.assertTrue(isinstance(rval, float)) self.assertEqual(rval, 1.0) @@ -20,28 +19,32 @@ class TestDecode(TestCase): # Several optimizations were made that skip over calls to # the whitespace regex, so this test is designed to try and # exercise the uncommon cases. The array cases are already covered. - rval = json.loads('{ "key" : "value" , "k":"v" }') + rval = self.loads('{ "key" : "value" , "k":"v" }') self.assertEqual(rval, {"key":"value", "k":"v"}) def test_empty_objects(self): - self.assertEqual(json.loads('{}'), {}) - self.assertEqual(json.loads('[]'), []) - self.assertEqual(json.loads('""'), u"") - self.assertIsInstance(json.loads('""'), unicode) + self.assertEqual(self.loads('{}'), {}) + self.assertEqual(self.loads('[]'), []) + self.assertEqual(self.loads('""'), u"") + self.assertIsInstance(self.loads('""'), unicode) def test_object_pairs_hook(self): s = '{"xkd":1, "kcw":2, "art":3, "hxm":4, "qrt":5, "pad":6, "hoy":7}' p = [("xkd", 1), ("kcw", 2), ("art", 3), ("hxm", 4), ("qrt", 5), ("pad", 6), ("hoy", 7)] - self.assertEqual(json.loads(s), eval(s)) - self.assertEqual(json.loads(s, object_pairs_hook=lambda x: x), p) - self.assertEqual(json.load(StringIO(s), - object_pairs_hook=lambda x: x), p) - od = json.loads(s, object_pairs_hook=OrderedDict) + self.assertEqual(self.loads(s), eval(s)) + self.assertEqual(self.loads(s, object_pairs_hook=lambda x: x), p) + self.assertEqual(self.json.load(StringIO(s), + object_pairs_hook=lambda x: x), p) + od = self.loads(s, object_pairs_hook=OrderedDict) self.assertEqual(od, OrderedDict(p)) self.assertEqual(type(od), OrderedDict) # the object_pairs_hook takes priority over the object_hook - self.assertEqual(json.loads(s, + self.assertEqual(self.loads(s, object_pairs_hook=OrderedDict, object_hook=lambda x: None), OrderedDict(p)) + + +class TestPyDecode(TestDecode, PyTest): pass +class TestCDecode(TestDecode, CTest): pass diff --git a/Lib/json/tests/test_default.py b/Lib/json/tests/test_default.py index 6a03eeb834..c2a07f605e 100644 --- a/Lib/json/tests/test_default.py +++ b/Lib/json/tests/test_default.py @@ -1,9 +1,12 @@ -from unittest import TestCase +from json.tests import PyTest, CTest -import json -class TestDefault(TestCase): +class TestDefault(object): def test_default(self): self.assertEqual( - json.dumps(type, default=repr), - json.dumps(repr(type))) + self.dumps(type, default=repr), + self.dumps(repr(type))) + + +class TestPyDefault(TestDefault, PyTest): pass +class TestCDefault(TestDefault, CTest): pass diff --git a/Lib/json/tests/test_dump.py b/Lib/json/tests/test_dump.py index 89978e0cd1..9a7c8ccdd0 100644 --- a/Lib/json/tests/test_dump.py +++ b/Lib/json/tests/test_dump.py @@ -1,21 +1,23 @@ -from unittest import TestCase from cStringIO import StringIO +from json.tests import PyTest, CTest -import json -class TestDump(TestCase): +class TestDump(object): def test_dump(self): sio = StringIO() - json.dump({}, sio) + self.json.dump({}, sio) self.assertEqual(sio.getvalue(), '{}') def test_dumps(self): - self.assertEqual(json.dumps({}), '{}') + self.assertEqual(self.dumps({}), '{}') def test_encode_truefalse(self): - self.assertEqual(json.dumps( + self.assertEqual(self.dumps( {True: False, False: True}, sort_keys=True), '{"false": true, "true": false}') - self.assertEqual(json.dumps( + self.assertEqual(self.dumps( {2: 3.0, 4.0: 5L, False: 1, 6L: True}, sort_keys=True), '{"false": 1, "2": 3.0, "4.0": 5, "6": true}') + +class TestPyDump(TestDump, PyTest): pass +class TestCDump(TestDump, CTest): pass diff --git a/Lib/json/tests/test_encode_basestring_ascii.py b/Lib/json/tests/test_encode_basestring_ascii.py index 0e501107ce..9f9d5a5deb 100644 --- a/Lib/json/tests/test_encode_basestring_ascii.py +++ b/Lib/json/tests/test_encode_basestring_ascii.py @@ -1,8 +1,6 @@ -from unittest import TestCase - -import json.encoder -from json import dumps from collections import OrderedDict +from json.tests import PyTest, CTest + CASES = [ (u'/\\"\ucafe\ubabe\uab98\ufcde\ubcda\uef4a\x08\x0c\n\r\t`1~!@#$%^&*()_+-=[]{}|;:\',./<>?', '"/\\\\\\"\\ucafe\\ubabe\\uab98\\ufcde\\ubcda\\uef4a\\b\\f\\n\\r\\t`1~!@#$%^&*()_+-=[]{}|;:\',./<>?"'), @@ -23,19 +21,11 @@ CASES = [ (u'\u0123\u4567\u89ab\ucdef\uabcd\uef4a', '"\\u0123\\u4567\\u89ab\\ucdef\\uabcd\\uef4a"'), ] -class TestEncodeBaseStringAscii(TestCase): - def test_py_encode_basestring_ascii(self): - self._test_encode_basestring_ascii(json.encoder.py_encode_basestring_ascii) - - def test_c_encode_basestring_ascii(self): - if not json.encoder.c_encode_basestring_ascii: - return - self._test_encode_basestring_ascii(json.encoder.c_encode_basestring_ascii) - - def _test_encode_basestring_ascii(self, encode_basestring_ascii): - fname = encode_basestring_ascii.__name__ +class TestEncodeBasestringAscii(object): + def test_encode_basestring_ascii(self): + fname = self.json.encoder.encode_basestring_ascii.__name__ for input_string, expect in CASES: - result = encode_basestring_ascii(input_string) + result = self.json.encoder.encode_basestring_ascii(input_string) self.assertEqual(result, expect, '{0!r} != {1!r} for {2}({3!r})'.format( result, expect, fname, input_string)) @@ -43,5 +33,9 @@ class TestEncodeBaseStringAscii(TestCase): def test_ordered_dict(self): # See issue 6105 items = [('one', 1), ('two', 2), ('three', 3), ('four', 4), ('five', 5)] - s = json.dumps(OrderedDict(items)) + s = self.dumps(OrderedDict(items)) self.assertEqual(s, '{"one": 1, "two": 2, "three": 3, "four": 4, "five": 5}') + + +class TestPyEncodeBasestringAscii(TestEncodeBasestringAscii, PyTest): pass +class TestCEncodeBasestringAscii(TestEncodeBasestringAscii, CTest): pass diff --git a/Lib/json/tests/test_fail.py b/Lib/json/tests/test_fail.py index dd9ec4137e..ae962c88a4 100644 --- a/Lib/json/tests/test_fail.py +++ b/Lib/json/tests/test_fail.py @@ -1,6 +1,4 @@ -from unittest import TestCase - -import json +from json.tests import PyTest, CTest # Fri Dec 30 18:57:26 2005 JSONDOCS = [ @@ -61,15 +59,15 @@ SKIPS = { 18: "spec doesn't specify any nesting limitations", } -class TestFail(TestCase): +class TestFail(object): def test_failures(self): for idx, doc in enumerate(JSONDOCS): idx = idx + 1 if idx in SKIPS: - json.loads(doc) + self.loads(doc) continue try: - json.loads(doc) + self.loads(doc) except ValueError: pass else: @@ -79,7 +77,11 @@ class TestFail(TestCase): data = {'a' : 1, (1, 2) : 2} #This is for c encoder - self.assertRaises(TypeError, json.dumps, data) + self.assertRaises(TypeError, self.dumps, data) #This is for python encoder - self.assertRaises(TypeError, json.dumps, data, indent=True) + self.assertRaises(TypeError, self.dumps, data, indent=True) + + +class TestPyFail(TestFail, PyTest): pass +class TestCFail(TestFail, CTest): pass diff --git a/Lib/json/tests/test_float.py b/Lib/json/tests/test_float.py index ec0cad1314..12d35074c9 100644 --- a/Lib/json/tests/test_float.py +++ b/Lib/json/tests/test_float.py @@ -1,19 +1,22 @@ import math -from unittest import TestCase +from json.tests import PyTest, CTest -import json -class TestFloat(TestCase): +class TestFloat(object): def test_floats(self): for num in [1617161771.7650001, math.pi, math.pi**100, math.pi**-100, 3.1]: - self.assertEqual(float(json.dumps(num)), num) - self.assertEqual(json.loads(json.dumps(num)), num) - self.assertEqual(json.loads(unicode(json.dumps(num))), num) + self.assertEqual(float(self.dumps(num)), num) + self.assertEqual(self.loads(self.dumps(num)), num) + self.assertEqual(self.loads(unicode(self.dumps(num))), num) def test_ints(self): for num in [1, 1L, 1<<32, 1<<64]: - self.assertEqual(json.dumps(num), str(num)) - self.assertEqual(int(json.dumps(num)), num) - self.assertEqual(json.loads(json.dumps(num)), num) - self.assertEqual(json.loads(unicode(json.dumps(num))), num) + self.assertEqual(self.dumps(num), str(num)) + self.assertEqual(int(self.dumps(num)), num) + self.assertEqual(self.loads(self.dumps(num)), num) + self.assertEqual(self.loads(unicode(self.dumps(num))), num) + + +class TestPyFloat(TestFloat, PyTest): pass +class TestCFloat(TestFloat, CTest): pass diff --git a/Lib/json/tests/test_indent.py b/Lib/json/tests/test_indent.py index 64b9b9c604..9b1876123a 100644 --- a/Lib/json/tests/test_indent.py +++ b/Lib/json/tests/test_indent.py @@ -1,10 +1,9 @@ -from unittest import TestCase - -import json import textwrap from StringIO import StringIO +from json.tests import PyTest, CTest + -class TestIndent(TestCase): +class TestIndent(object): def test_indent(self): h = [['blorpie'], ['whoops'], [], 'd-shtaeou', 'd-nthiouh', 'i-vhbjkhnth', {'nifty': 87}, {'field': 'yes', 'morefield': False} ] @@ -31,11 +30,11 @@ class TestIndent(TestCase): ]""") - d1 = json.dumps(h) - d2 = json.dumps(h, indent=2, sort_keys=True, separators=(',', ': ')) + d1 = self.dumps(h) + d2 = self.dumps(h, indent=2, sort_keys=True, separators=(',', ': ')) - h1 = json.loads(d1) - h2 = json.loads(d2) + h1 = self.loads(d1) + h2 = self.loads(d2) self.assertEqual(h1, h) self.assertEqual(h2, h) @@ -44,14 +43,18 @@ class TestIndent(TestCase): def test_indent0(self): h = {3: 1} def check(indent, expected): - d1 = json.dumps(h, indent=indent) + d1 = self.dumps(h, indent=indent) self.assertEqual(d1, expected) sio = StringIO() - json.dump(h, sio, indent=indent) + self.json.dump(h, sio, indent=indent) self.assertEqual(sio.getvalue(), expected) # indent=0 should emit newlines check(0, '{\n"3": 1\n}') # indent=None is more compact check(None, '{"3": 1}') + + +class TestPyIndent(TestIndent, PyTest): pass +class TestCIndent(TestIndent, CTest): pass diff --git a/Lib/json/tests/test_pass1.py b/Lib/json/tests/test_pass1.py index 719c113759..82d71543ba 100644 --- a/Lib/json/tests/test_pass1.py +++ b/Lib/json/tests/test_pass1.py @@ -1,6 +1,5 @@ -from unittest import TestCase +from json.tests import PyTest, CTest -import json # from http://json.org/JSON_checker/test/pass1.json JSON = r''' @@ -62,15 +61,19 @@ JSON = r''' ,"rosebud"] ''' -class TestPass1(TestCase): +class TestPass1(object): def test_parse(self): # test in/out equivalence and parsing - res = json.loads(JSON) - out = json.dumps(res) - self.assertEqual(res, json.loads(out)) + res = self.loads(JSON) + out = self.dumps(res) + self.assertEqual(res, self.loads(out)) try: - json.dumps(res, allow_nan=False) + self.dumps(res, allow_nan=False) except ValueError: pass else: self.fail("23456789012E666 should be out of range") + + +class TestPyPass1(TestPass1, PyTest): pass +class TestCPass1(TestPass1, CTest): pass diff --git a/Lib/json/tests/test_pass2.py b/Lib/json/tests/test_pass2.py index 379117e905..a2bb6d7211 100644 --- a/Lib/json/tests/test_pass2.py +++ b/Lib/json/tests/test_pass2.py @@ -1,14 +1,18 @@ -from unittest import TestCase -import json +from json.tests import PyTest, CTest + # from http://json.org/JSON_checker/test/pass2.json JSON = r''' [[[[[[[[[[[[[[[[[[["Not too deep"]]]]]]]]]]]]]]]]]]] ''' -class TestPass2(TestCase): +class TestPass2(object): def test_parse(self): # test in/out equivalence and parsing - res = json.loads(JSON) - out = json.dumps(res) - self.assertEqual(res, json.loads(out)) + res = self.loads(JSON) + out = self.dumps(res) + self.assertEqual(res, self.loads(out)) + + +class TestPyPass2(TestPass2, PyTest): pass +class TestCPass2(TestPass2, CTest): pass diff --git a/Lib/json/tests/test_pass3.py b/Lib/json/tests/test_pass3.py index 9151c4321c..221f9a0c3d 100644 --- a/Lib/json/tests/test_pass3.py +++ b/Lib/json/tests/test_pass3.py @@ -1,6 +1,5 @@ -from unittest import TestCase +from json.tests import PyTest, CTest -import json # from http://json.org/JSON_checker/test/pass3.json JSON = r''' @@ -12,9 +11,14 @@ JSON = r''' } ''' -class TestPass3(TestCase): + +class TestPass3(object): def test_parse(self): # test in/out equivalence and parsing - res = json.loads(JSON) - out = json.dumps(res) - self.assertEqual(res, json.loads(out)) + res = self.loads(JSON) + out = self.dumps(res) + self.assertEqual(res, self.loads(out)) + + +class TestPyPass3(TestPass3, PyTest): pass +class TestCPass3(TestPass3, CTest): pass diff --git a/Lib/json/tests/test_recursion.py b/Lib/json/tests/test_recursion.py index 1f2d7b3b5c..b5221e5d16 100644 --- a/Lib/json/tests/test_recursion.py +++ b/Lib/json/tests/test_recursion.py @@ -1,33 +1,16 @@ -from unittest import TestCase +from json.tests import PyTest, CTest -import json class JSONTestObject: pass -class RecursiveJSONEncoder(json.JSONEncoder): - recurse = False - def default(self, o): - if o is JSONTestObject: - if self.recurse: - return [JSONTestObject] - else: - return 'JSONTestObject' - return json.JSONEncoder.default(o) - -class EndlessJSONEncoder(json.JSONEncoder): - def default(self, o): - """If check_circular is False, this will keep adding another list.""" - return [o] - - -class TestRecursion(TestCase): +class TestRecursion(object): def test_listrecursion(self): x = [] x.append(x) try: - json.dumps(x) + self.dumps(x) except ValueError: pass else: @@ -36,7 +19,7 @@ class TestRecursion(TestCase): y = [x] x.append(y) try: - json.dumps(x) + self.dumps(x) except ValueError: pass else: @@ -44,13 +27,13 @@ class TestRecursion(TestCase): y = [] x = [y, y] # ensure that the marker is cleared - json.dumps(x) + self.dumps(x) def test_dictrecursion(self): x = {} x["test"] = x try: - json.dumps(x) + self.dumps(x) except ValueError: pass else: @@ -58,9 +41,19 @@ class TestRecursion(TestCase): x = {} y = {"a": x, "b": x} # ensure that the marker is cleared - json.dumps(x) + self.dumps(x) def test_defaultrecursion(self): + class RecursiveJSONEncoder(self.json.JSONEncoder): + recurse = False + def default(self, o): + if o is JSONTestObject: + if self.recurse: + return [JSONTestObject] + else: + return 'JSONTestObject' + return pyjson.JSONEncoder.default(o) + enc = RecursiveJSONEncoder() self.assertEqual(enc.encode(JSONTestObject), '"JSONTestObject"') enc.recurse = True @@ -77,18 +70,18 @@ class TestRecursion(TestCase): # accelerations are used. See #12017 # str with self.assertRaises(RuntimeError): - json.loads('{"a":' * 100000 + '1' + '}' * 100000) + self.loads('{"a":' * 100000 + '1' + '}' * 100000) with self.assertRaises(RuntimeError): - json.loads('{"a":' * 100000 + '[1]' + '}' * 100000) + self.loads('{"a":' * 100000 + '[1]' + '}' * 100000) with self.assertRaises(RuntimeError): - json.loads('[' * 100000 + '1' + ']' * 100000) + self.loads('[' * 100000 + '1' + ']' * 100000) # unicode with self.assertRaises(RuntimeError): - json.loads(u'{"a":' * 100000 + u'1' + u'}' * 100000) + self.loads(u'{"a":' * 100000 + u'1' + u'}' * 100000) with self.assertRaises(RuntimeError): - json.loads(u'{"a":' * 100000 + u'[1]' + u'}' * 100000) + self.loads(u'{"a":' * 100000 + u'[1]' + u'}' * 100000) with self.assertRaises(RuntimeError): - json.loads(u'[' * 100000 + u'1' + u']' * 100000) + self.loads(u'[' * 100000 + u'1' + u']' * 100000) def test_highly_nested_objects_encoding(self): # See #12051 @@ -96,11 +89,20 @@ class TestRecursion(TestCase): for x in xrange(100000): l, d = [l], {'k':d} with self.assertRaises(RuntimeError): - json.dumps(l) + self.dumps(l) with self.assertRaises(RuntimeError): - json.dumps(d) + self.dumps(d) def test_endless_recursion(self): # See #12051 + class EndlessJSONEncoder(self.json.JSONEncoder): + def default(self, o): + """If check_circular is False, this will keep adding another list.""" + return [o] + with self.assertRaises(RuntimeError): EndlessJSONEncoder(check_circular=False).encode(5j) + + +class TestPyRecursion(TestRecursion, PyTest): pass +class TestCRecursion(TestRecursion, CTest): pass diff --git a/Lib/json/tests/test_scanstring.py b/Lib/json/tests/test_scanstring.py index d85816112a..4fef8cbabf 100644 --- a/Lib/json/tests/test_scanstring.py +++ b/Lib/json/tests/test_scanstring.py @@ -1,23 +1,10 @@ import sys -from unittest import TestCase, skipUnless +from json.tests import PyTest, CTest -import json -import json.decoder -try: - import _json -except ImportError: - _json = None - -class TestScanString(TestCase): - def test_py_scanstring(self): - self._test_scanstring(json.decoder.py_scanstring) - - @skipUnless(_json, 'test requires the _json module') - def test_c_scanstring(self): - self._test_scanstring(json.decoder.c_scanstring) - - def _test_scanstring(self, scanstring): +class TestScanstring(object): + def test_scanstring(self): + scanstring = self.json.decoder.scanstring self.assertEqual( scanstring('"z\\ud834\\udd20x"', 1, None, True), (u'z\U0001d120x', 16)) @@ -108,10 +95,15 @@ class TestScanString(TestCase): (u'Bad value', 12)) def test_issue3623(self): - self.assertRaises(ValueError, json.decoder.scanstring, b"xxx", 1, + self.assertRaises(ValueError, self.json.decoder.scanstring, b"xxx", 1, "xxx") self.assertRaises(UnicodeDecodeError, - json.encoder.encode_basestring_ascii, b"xx\xff") + self.json.encoder.encode_basestring_ascii, b"xx\xff") def test_overflow(self): - self.assertRaises(OverflowError, json.decoder.scanstring, b"xxx", sys.maxsize+1) + with self.assertRaises(OverflowError): + self.json.decoder.scanstring(b"xxx", sys.maxsize+1) + + +class TestPyScanstring(TestScanstring, PyTest): pass +class TestCScanstring(TestScanstring, CTest): pass diff --git a/Lib/json/tests/test_separators.py b/Lib/json/tests/test_separators.py index d5b92bd65d..a4246e1f2d 100644 --- a/Lib/json/tests/test_separators.py +++ b/Lib/json/tests/test_separators.py @@ -1,10 +1,8 @@ import textwrap -from unittest import TestCase +from json.tests import PyTest, CTest -import json - -class TestSeparators(TestCase): +class TestSeparators(object): def test_separators(self): h = [['blorpie'], ['whoops'], [], 'd-shtaeou', 'd-nthiouh', 'i-vhbjkhnth', {'nifty': 87}, {'field': 'yes', 'morefield': False} ] @@ -31,12 +29,16 @@ class TestSeparators(TestCase): ]""") - d1 = json.dumps(h) - d2 = json.dumps(h, indent=2, sort_keys=True, separators=(' ,', ' : ')) + d1 = self.dumps(h) + d2 = self.dumps(h, indent=2, sort_keys=True, separators=(' ,', ' : ')) - h1 = json.loads(d1) - h2 = json.loads(d2) + h1 = self.loads(d1) + h2 = self.loads(d2) self.assertEqual(h1, h) self.assertEqual(h2, h) self.assertEqual(d2, expect) + + +class TestPySeparators(TestSeparators, PyTest): pass +class TestCSeparators(TestSeparators, CTest): pass diff --git a/Lib/json/tests/test_speedups.py b/Lib/json/tests/test_speedups.py index 1505065693..7186a40932 100644 --- a/Lib/json/tests/test_speedups.py +++ b/Lib/json/tests/test_speedups.py @@ -1,29 +1,23 @@ -from unittest import TestCase, skipUnless +from json.tests import CTest -from json import decoder, encoder, scanner -try: - import _json -except ImportError: - _json = None - -@skipUnless(_json, 'test requires the _json module') -class TestSpeedups(TestCase): +class TestSpeedups(CTest): def test_scanstring(self): - self.assertEqual(decoder.scanstring.__module__, "_json") - self.assertIs(decoder.scanstring, decoder.c_scanstring) + self.assertEqual(self.json.decoder.scanstring.__module__, "_json") + self.assertIs(self.json.decoder.scanstring, self.json.decoder.c_scanstring) def test_encode_basestring_ascii(self): - self.assertEqual(encoder.encode_basestring_ascii.__module__, "_json") - self.assertIs(encoder.encode_basestring_ascii, - encoder.c_encode_basestring_ascii) + self.assertEqual(self.json.encoder.encode_basestring_ascii.__module__, + "_json") + self.assertIs(self.json.encoder.encode_basestring_ascii, + self.json.encoder.c_encode_basestring_ascii) -class TestDecode(TestCase): +class TestDecode(CTest): def test_make_scanner(self): - self.assertRaises(AttributeError, scanner.c_make_scanner, 1) + self.assertRaises(AttributeError, self.json.scanner.c_make_scanner, 1) def test_make_encoder(self): - self.assertRaises(TypeError, encoder.c_make_encoder, + self.assertRaises(TypeError, self.json.encoder.c_make_encoder, None, "\xCD\x7D\x3D\x4E\x12\x4C\xF9\x79\xD7\x52\xBA\x82\xF2\x27\x4A\x7D\xA0\xCA\x75", None) diff --git a/Lib/json/tests/test_unicode.py b/Lib/json/tests/test_unicode.py index ad7fe2476b..31cf38925c 100644 --- a/Lib/json/tests/test_unicode.py +++ b/Lib/json/tests/test_unicode.py @@ -1,11 +1,10 @@ -from unittest import TestCase - -import json from collections import OrderedDict +from json.tests import PyTest, CTest + -class TestUnicode(TestCase): +class TestUnicode(object): def test_encoding1(self): - encoder = json.JSONEncoder(encoding='utf-8') + encoder = self.json.JSONEncoder(encoding='utf-8') u = u'\N{GREEK SMALL LETTER ALPHA}\N{GREEK CAPITAL LETTER OMEGA}' s = u.encode('utf-8') ju = encoder.encode(u) @@ -15,68 +14,72 @@ class TestUnicode(TestCase): def test_encoding2(self): u = u'\N{GREEK SMALL LETTER ALPHA}\N{GREEK CAPITAL LETTER OMEGA}' s = u.encode('utf-8') - ju = json.dumps(u, encoding='utf-8') - js = json.dumps(s, encoding='utf-8') + ju = self.dumps(u, encoding='utf-8') + js = self.dumps(s, encoding='utf-8') self.assertEqual(ju, js) def test_encoding3(self): u = u'\N{GREEK SMALL LETTER ALPHA}\N{GREEK CAPITAL LETTER OMEGA}' - j = json.dumps(u) + j = self.dumps(u) self.assertEqual(j, '"\\u03b1\\u03a9"') def test_encoding4(self): u = u'\N{GREEK SMALL LETTER ALPHA}\N{GREEK CAPITAL LETTER OMEGA}' - j = json.dumps([u]) + j = self.dumps([u]) self.assertEqual(j, '["\\u03b1\\u03a9"]') def test_encoding5(self): u = u'\N{GREEK SMALL LETTER ALPHA}\N{GREEK CAPITAL LETTER OMEGA}' - j = json.dumps(u, ensure_ascii=False) + j = self.dumps(u, ensure_ascii=False) self.assertEqual(j, u'"{0}"'.format(u)) def test_encoding6(self): u = u'\N{GREEK SMALL LETTER ALPHA}\N{GREEK CAPITAL LETTER OMEGA}' - j = json.dumps([u], ensure_ascii=False) + j = self.dumps([u], ensure_ascii=False) self.assertEqual(j, u'["{0}"]'.format(u)) def test_big_unicode_encode(self): u = u'\U0001d120' - self.assertEqual(json.dumps(u), '"\\ud834\\udd20"') - self.assertEqual(json.dumps(u, ensure_ascii=False), u'"\U0001d120"') + self.assertEqual(self.dumps(u), '"\\ud834\\udd20"') + self.assertEqual(self.dumps(u, ensure_ascii=False), u'"\U0001d120"') def test_big_unicode_decode(self): u = u'z\U0001d120x' - self.assertEqual(json.loads('"' + u + '"'), u) - self.assertEqual(json.loads('"z\\ud834\\udd20x"'), u) + self.assertEqual(self.loads('"' + u + '"'), u) + self.assertEqual(self.loads('"z\\ud834\\udd20x"'), u) def test_unicode_decode(self): for i in range(0, 0xd7ff): u = unichr(i) s = '"\\u{0:04x}"'.format(i) - self.assertEqual(json.loads(s), u) + self.assertEqual(self.loads(s), u) def test_object_pairs_hook_with_unicode(self): s = u'{"xkd":1, "kcw":2, "art":3, "hxm":4, "qrt":5, "pad":6, "hoy":7}' p = [(u"xkd", 1), (u"kcw", 2), (u"art", 3), (u"hxm", 4), (u"qrt", 5), (u"pad", 6), (u"hoy", 7)] - self.assertEqual(json.loads(s), eval(s)) - self.assertEqual(json.loads(s, object_pairs_hook = lambda x: x), p) - od = json.loads(s, object_pairs_hook = OrderedDict) + self.assertEqual(self.loads(s), eval(s)) + self.assertEqual(self.loads(s, object_pairs_hook = lambda x: x), p) + od = self.loads(s, object_pairs_hook = OrderedDict) self.assertEqual(od, OrderedDict(p)) self.assertEqual(type(od), OrderedDict) # the object_pairs_hook takes priority over the object_hook - self.assertEqual(json.loads(s, + self.assertEqual(self.loads(s, object_pairs_hook = OrderedDict, object_hook = lambda x: None), OrderedDict(p)) def test_default_encoding(self): - self.assertEqual(json.loads(u'{"a": "\xe9"}'.encode('utf-8')), + self.assertEqual(self.loads(u'{"a": "\xe9"}'.encode('utf-8')), {'a': u'\xe9'}) def test_unicode_preservation(self): - self.assertEqual(type(json.loads(u'""')), unicode) - self.assertEqual(type(json.loads(u'"a"')), unicode) - self.assertEqual(type(json.loads(u'["a"]')[0]), unicode) + self.assertEqual(type(self.loads(u'""')), unicode) + self.assertEqual(type(self.loads(u'"a"')), unicode) + self.assertEqual(type(self.loads(u'["a"]')[0]), unicode) # Issue 10038. - self.assertEqual(type(json.loads('"foo"')), unicode) + self.assertEqual(type(self.loads('"foo"')), unicode) + + +class TestPyUnicode(TestUnicode, PyTest): pass +class TestCUnicode(TestUnicode, CTest): pass diff --git a/Lib/test/test_support.py b/Lib/test/test_support.py index 04ab443a4b..e237709366 100644 --- a/Lib/test/test_support.py +++ b/Lib/test/test_support.py @@ -120,8 +120,8 @@ def import_fresh_module(name, fresh=(), blocked=(), deprecated=False): If deprecated is True, any module or package deprecation messages will be suppressed.""" - # NOTE: test_heapq and test_warnings include extra sanity checks to make - # sure that this utility function is working as expected + # NOTE: test_heapq, test_json, and test_warnings include extra sanity + # checks to make sure that this utility function is working as expected with _ignore_deprecated_imports(deprecated): # Keep track of modules saved for later restoration as well # as those which just need a blocking entry removed diff --git a/Misc/NEWS b/Misc/NEWS index 34f311bc9a..d9af57c781 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -439,6 +439,8 @@ IDLE Tests ----- +- Issue #5723: Improve json tests to be executed with and without accelerations. + - Issue #11910: Fix test_heapq to skip the C tests when _heapq is missing. - Fix test_startfile to wait for child process to terminate before finishing. -- cgit v1.2.1 From 84eadc8ce69ed90456c10807ae176656fd81c392 Mon Sep 17 00:00:00 2001 From: Ezio Melotti Date: Sat, 14 May 2011 08:19:43 +0300 Subject: #7960: fix docstrings for captured_output and captured_stdout. --- Lib/test/test_support.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Lib/test/test_support.py b/Lib/test/test_support.py index e237709366..81bb3ca017 100644 --- a/Lib/test/test_support.py +++ b/Lib/test/test_support.py @@ -814,14 +814,8 @@ def transient_internet(resource_name, timeout=30.0, errnos=()): @contextlib.contextmanager def captured_output(stream_name): - """Run the 'with' statement body using a StringIO object in place of a - specific attribute on the sys module. - Example use (with 'stream_name=stdout'):: - - with captured_stdout() as s: - print "hello" - assert s.getvalue() == "hello" - """ + """Return a context manager used by captured_stdout and captured_stdin + that temporarily replaces the sys stream *stream_name* with a StringIO.""" import StringIO orig_stdout = getattr(sys, stream_name) setattr(sys, stream_name, StringIO.StringIO()) @@ -831,6 +825,12 @@ def captured_output(stream_name): setattr(sys, stream_name, orig_stdout) def captured_stdout(): + """Capture the output of sys.stdout: + + with captured_stdout() as s: + print "hello" + self.assertEqual(s.getvalue(), "hello") + """ return captured_output("stdout") def captured_stdin(): -- cgit v1.2.1 From 0d6026af237fc34d7a82b4c257ebfcf58e87178e Mon Sep 17 00:00:00 2001 From: Ezio Melotti Date: Sat, 14 May 2011 09:17:52 +0300 Subject: #11979: improve wording and markup in sockets howto. Patch by Xavier Morel. --- Doc/howto/sockets.rst | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/Doc/howto/sockets.rst b/Doc/howto/sockets.rst index 4002a3dbc8..443b15f50e 100644 --- a/Doc/howto/sockets.rst +++ b/Doc/howto/sockets.rst @@ -43,10 +43,10 @@ web server it's talking to uses both "server" sockets and "client" sockets. History ------- -Of the various forms of IPC (*Inter Process Communication*), sockets are by far -the most popular. On any given platform, there are likely to be other forms of -IPC that are faster, but for cross-platform communication, sockets are about the -only game in town. +Of the various forms of :abbr:`IPC (Inter Process Communication)`, +sockets are by far the most popular. On any given platform, there are +likely to be other forms of IPC that are faster, but for +cross-platform communication, sockets are about the only game in town. They were invented in Berkeley as part of the BSD flavor of Unix. They spread like wildfire with the Internet. With good reason --- the combination of sockets @@ -67,13 +67,14 @@ your browser did something like the following:: # - the normal http port s.connect(("www.mcmillan-inc.com", 80)) -When the ``connect`` completes, the socket ``s`` can now be used to send in a -request for the text of this page. The same socket will read the reply, and then -be destroyed. That's right - destroyed. Client sockets are normally only used -for one exchange (or a small set of sequential exchanges). +When the ``connect`` completes, the socket ``s`` can be used to send +in a request for the text of the page. The same socket will read the +reply, and then be destroyed. That's right, destroyed. Client sockets +are normally only used for one exchange (or a small set of sequential +exchanges). What happens in the web server is a bit more complex. First, the web server -creates a "server socket". :: +creates a "server socket":: #create an INET, STREAMing socket serversocket = socket.socket( @@ -97,7 +98,7 @@ Finally, the argument to ``listen`` tells the socket library that we want it to queue up as many as 5 connect requests (the normal max) before refusing outside connections. If the rest of the code is written properly, that should be plenty. -OK, now we have a "server" socket, listening on port 80. Now we enter the +Now that we have a "server" socket, listening on port 80, we can enter the mainloop of the web server:: while 1: @@ -146,7 +147,7 @@ perhaps a signon. But that's a design decision - it's not a rule of sockets. Now there are two sets of verbs to use for communication. You can use ``send`` and ``recv``, or you can transform your client socket into a file-like beast and -use ``read`` and ``write``. The latter is the way Java presents their sockets. +use ``read`` and ``write``. The latter is the way Java presents its sockets. I'm not going to talk about it here, except to warn you that you need to use ``flush`` on sockets. These are buffered "files", and a common mistake is to ``write`` something, and then ``read`` for a reply. Without a ``flush`` in @@ -167,11 +168,11 @@ this connection. Ever. You may be able to send data successfully; I'll talk about that some on the next page. A protocol like HTTP uses a socket for only one transfer. The client sends a -request, the reads a reply. That's it. The socket is discarded. This means that +request, then reads a reply. That's it. The socket is discarded. This means that a client can detect the end of the reply by receiving 0 bytes. But if you plan to reuse your socket for further transfers, you need to realize -that *there is no "EOT" (End of Transfer) on a socket.* I repeat: if a socket +that *there is no* :abbr:`EOT (End of Transfer)` *on a socket.* I repeat: if a socket ``send`` or ``recv`` returns after handling 0 bytes, the connection has been broken. If the connection has *not* been broken, you may wait on a ``recv`` forever, because the socket will *not* tell you that there's nothing more to @@ -337,7 +338,7 @@ Use ``select``. In C, coding ``select`` is fairly complex. In Python, it's a piece of cake, but it's close enough to the C version that if you understand ``select`` in Python, -you'll have little trouble with it in C. :: +you'll have little trouble with it in C:: ready_to_read, ready_to_write, in_error = \ select.select( @@ -354,9 +355,9 @@ call is blocking, but you can give it a timeout. This is generally a sensible thing to do - give it a nice long timeout (say a minute) unless you have good reason to do otherwise. -In return, you will get three lists. They have the sockets that are actually +In return, you will get three lists. They contain the sockets that are actually readable, writable and in error. Each of these lists is a subset (possibly -empty) of the corresponding list you passed in. And if you put a socket in more +empty) of the corresponding list you passed in. If you put a socket in more than one input list, it will only be (at most) in one output list. If a socket is in the output readable list, you can be -- cgit v1.2.1 From 31d50bcafcbfa62235364f472739666f9f0d2f01 Mon Sep 17 00:00:00 2001 From: Nadeem Vawda Date: Sat, 14 May 2011 14:29:07 +0200 Subject: Issue #12050: zlib.decompressobj().decompress() now clears the unconsumed_tail attribute when called without a max_length argument. --- Lib/test/test_zlib.py | 9 +++++++++ Misc/NEWS | 3 +++ Modules/zlibmodule.c | 19 ++++++++++++------- 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/Lib/test/test_zlib.py b/Lib/test/test_zlib.py index a003611a7c..7f631437b5 100644 --- a/Lib/test/test_zlib.py +++ b/Lib/test/test_zlib.py @@ -310,6 +310,15 @@ class CompressObjectTestCase(BaseCompressTestCase, unittest.TestCase): self.assertRaises(ValueError, dco.decompress, "", -1) self.assertEqual('', dco.unconsumed_tail) + def test_clear_unconsumed_tail(self): + # Issue #12050: calling decompress() without providing max_length + # should clear the unconsumed_tail attribute. + cdata = "x\x9cKLJ\x06\x00\x02M\x01" # "abc" + dco = zlib.decompressobj() + ddata = dco.decompress(cdata, 1) + ddata += dco.decompress(dco.unconsumed_tail) + self.assertEqual(dco.unconsumed_tail, "") + def test_flushes(self): # Test flush() with the various options, using all the # different levels in order to provide more variations. diff --git a/Misc/NEWS b/Misc/NEWS index d9af57c781..a603912a0c 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -80,6 +80,9 @@ Core and Builtins Library ------- +- Issue #12050: zlib.decompressobj().decompress() now clears the unconsumed_tail + attribute when called without a max_length argument. + - Issue #12062: In the `io` module, fix a flushing bug when doing a certain type of I/O sequence on a file opened in read+write mode (namely: reading, seeking a bit forward, writing, then seeking before the previous write but diff --git a/Modules/zlibmodule.c b/Modules/zlibmodule.c index 183f01e91a..bd6d6e256b 100644 --- a/Modules/zlibmodule.c +++ b/Modules/zlibmodule.c @@ -535,17 +535,22 @@ PyZlib_objdecompress(compobject *self, PyObject *args) Py_END_ALLOW_THREADS } - /* Not all of the compressed data could be accommodated in the output buffer - of specified size. Return the unconsumed tail in an attribute.*/ if(max_length) { + /* Not all of the compressed data could be accommodated in a buffer of + the specified size. Return the unconsumed tail in an attribute. */ Py_DECREF(self->unconsumed_tail); self->unconsumed_tail = PyString_FromStringAndSize((char *)self->zst.next_in, self->zst.avail_in); - if(!self->unconsumed_tail) { - Py_DECREF(RetVal); - RetVal = NULL; - goto error; - } + } + else if (PyString_GET_SIZE(self->unconsumed_tail) > 0) { + /* All of the compressed data was consumed. Clear unconsumed_tail. */ + Py_DECREF(self->unconsumed_tail); + self->unconsumed_tail = PyString_FromStringAndSize("", 0); + } + if(!self->unconsumed_tail) { + Py_DECREF(RetVal); + RetVal = NULL; + goto error; } /* The end of the compressed data has been reached, so set the -- cgit v1.2.1 From 39a4429a4c1728f2d49029365e802a344cf72cc2 Mon Sep 17 00:00:00 2001 From: "Gregory P. Smith" Date: Sat, 14 May 2011 15:07:53 -0700 Subject: Fixes Issue #12059: Properly handle missing hash functions even when the expected builtin modules are not present. This includes a unittest for __get_builtin_constructor() in the face of such an error. --- Lib/hashlib.py | 43 +++++++++++++++++++++++-------------------- Lib/test/test_hashlib.py | 18 ++++++++++++++++++ 2 files changed, 41 insertions(+), 20 deletions(-) diff --git a/Lib/hashlib.py b/Lib/hashlib.py index 48f2cfddbd..2732d184aa 100644 --- a/Lib/hashlib.py +++ b/Lib/hashlib.py @@ -64,26 +64,29 @@ __all__ = __always_supported + ('new', 'algorithms') def __get_builtin_constructor(name): - if name in ('SHA1', 'sha1'): - import _sha - return _sha.new - elif name in ('MD5', 'md5'): - import _md5 - return _md5.new - elif name in ('SHA256', 'sha256', 'SHA224', 'sha224'): - import _sha256 - bs = name[3:] - if bs == '256': - return _sha256.sha256 - elif bs == '224': - return _sha256.sha224 - elif name in ('SHA512', 'sha512', 'SHA384', 'sha384'): - import _sha512 - bs = name[3:] - if bs == '512': - return _sha512.sha512 - elif bs == '384': - return _sha512.sha384 + try: + if name in ('SHA1', 'sha1'): + import _sha + return _sha.new + elif name in ('MD5', 'md5'): + import _md5 + return _md5.new + elif name in ('SHA256', 'sha256', 'SHA224', 'sha224'): + import _sha256 + bs = name[3:] + if bs == '256': + return _sha256.sha256 + elif bs == '224': + return _sha256.sha224 + elif name in ('SHA512', 'sha512', 'SHA384', 'sha384'): + import _sha512 + bs = name[3:] + if bs == '512': + return _sha512.sha512 + elif bs == '384': + return _sha512.sha384 + except ImportError: + pass # no extension module, this hash is unsupported. raise ValueError('unsupported hash type %s' % name) diff --git a/Lib/test/test_hashlib.py b/Lib/test/test_hashlib.py index ed41672ef0..855ecbfb4e 100644 --- a/Lib/test/test_hashlib.py +++ b/Lib/test/test_hashlib.py @@ -115,6 +115,24 @@ class HashLibTestCase(unittest.TestCase): else: self.assertTrue(0 == "hashlib didn't reject bogus hash name") + def test_get_builtin_constructor(self): + get_builtin_constructor = hashlib.__dict__[ + '__get_builtin_constructor'] + self.assertRaises(ValueError, get_builtin_constructor, 'test') + try: + import _md5 + except ImportError: + pass + # This forces an ImportError for "import _md5" statements + sys.modules['_md5'] = None + try: + self.assertRaises(ValueError, get_builtin_constructor, 'md5') + finally: + if '_md5' in locals(): + sys.modules['_md5'] = _md5 + else: + del sys.modules['_md5'] + def test_hexdigest(self): for name in self.supported_hash_names: h = hashlib.new(name) -- cgit v1.2.1 From 4672fdc66b62eb9f6b9d1d193e026ce566acdc79 Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Sun, 15 May 2011 08:50:32 +0200 Subject: Port #6498 fix: fix several misspellings of "SystemExit" as "SystemError". --- Doc/c-api/veryhigh.rst | 10 +++++----- Python/pythonrun.c | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Doc/c-api/veryhigh.rst b/Doc/c-api/veryhigh.rst index 23f7c852db..927368d7a1 100644 --- a/Doc/c-api/veryhigh.rst +++ b/Doc/c-api/veryhigh.rst @@ -32,11 +32,11 @@ the same library that the Python runtime is using. prepared exactly as those which are passed to a C program's :cfunc:`main` function. It is important to note that the argument list may be modified (but the contents of the strings pointed to by the argument list are not). The return - value will be the integer passed to the :func:`sys.exit` function, ``1`` if the - interpreter exits due to an exception, or ``2`` if the parameter list does not - represent a valid Python command line. + value will be ```0``` if the interpreter exits normally (ie, without an + exception), ``1`` if the interpreter exits due to an exception, or ``2`` + if the parameter list does not represent a valid Python command line. - Note that if an otherwise unhandled :exc:`SystemError` is raised, this + Note that if an otherwise unhandled :exc:`SystemExit` is raised, this function will not return ``1``, but exit the process, as long as ``Py_InspectFlag`` is not set. @@ -82,7 +82,7 @@ the same library that the Python runtime is using. there was an error, there is no way to get the exception information. For the meaning of *flags*, see below. - Note that if an otherwise unhandled :exc:`SystemError` is raised, this + Note that if an otherwise unhandled :exc:`SystemExit` is raised, this function will not return ``-1``, but exit the process, as long as ``Py_InspectFlag`` is not set. diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 87ffb397ca..bfb7fca9de 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -76,7 +76,7 @@ extern void _PyGILState_Fini(void); int Py_DebugFlag; /* Needed by parser.c */ int Py_VerboseFlag; /* Needed by import.c */ int Py_InteractiveFlag; /* Needed by Py_FdIsInteractive() below */ -int Py_InspectFlag; /* Needed to determine whether to exit at SystemError */ +int Py_InspectFlag; /* Needed to determine whether to exit at SystemExit */ int Py_NoSiteFlag; /* Suppress 'import site' */ int Py_BytesWarningFlag; /* Warn on str(bytes) and str(buffer) */ int Py_DontWriteBytecodeFlag; /* Suppress writing bytecode files (*.py[co]) */ -- cgit v1.2.1 From 7c10778ef104ba5be60b6812db59872c1007ce4a Mon Sep 17 00:00:00 2001 From: Ronald Oussoren Date: Sun, 15 May 2011 16:44:27 +0200 Subject: Issue #9516: avoid errors in sysconfig when MACOSX_DEPLOYMENT_TARGET is set in shell. Without this patch python will fail to start properly when the environment variable MACOSX_DEPLOYMENT_TARGET is set on MacOSX and has a value that is not compatible with the value during Python's build. This is caused by code in sysconfig that was only meant to be used in disutils. --- Lib/distutils/sysconfig.py | 2 +- Lib/distutils/tests/test_build_ext.py | 56 ++++++++++++++++++++++++++++++++++- Lib/distutils/util.py | 4 +-- Lib/sysconfig.py | 19 +----------- Lib/test/test_sysconfig.py | 50 +++++++++++++++++++++++++++++-- 5 files changed, 105 insertions(+), 26 deletions(-) diff --git a/Lib/distutils/sysconfig.py b/Lib/distutils/sysconfig.py index 33cc5a38a5..d206e0cdf9 100644 --- a/Lib/distutils/sysconfig.py +++ b/Lib/distutils/sysconfig.py @@ -389,7 +389,7 @@ def _init_posix(): cur_target = os.getenv('MACOSX_DEPLOYMENT_TARGET', '') if cur_target == '': cur_target = cfg_target - os.putenv('MACOSX_DEPLOYMENT_TARGET', cfg_target) + os.environ['MACOSX_DEPLOYMENT_TARGET'] = cfg_target elif map(int, cfg_target.split('.')) > map(int, cur_target.split('.')): my_msg = ('$MACOSX_DEPLOYMENT_TARGET mismatch: now "%s" but "%s" during configure' % (cur_target, cfg_target)) diff --git a/Lib/distutils/tests/test_build_ext.py b/Lib/distutils/tests/test_build_ext.py index 86568ebb7a..46dcb5ed5d 100644 --- a/Lib/distutils/tests/test_build_ext.py +++ b/Lib/distutils/tests/test_build_ext.py @@ -3,12 +3,13 @@ import os import tempfile import shutil from StringIO import StringIO +import textwrap from distutils.core import Extension, Distribution from distutils.command.build_ext import build_ext from distutils import sysconfig from distutils.tests import support -from distutils.errors import DistutilsSetupError +from distutils.errors import DistutilsSetupError, CompileError import unittest from test import test_support @@ -430,6 +431,59 @@ class BuildExtTestCase(support.TempdirManager, wanted = os.path.join(cmd.build_lib, 'UpdateManager', 'fdsend' + ext) self.assertEqual(ext_path, wanted) + @unittest.skipUnless(sys.platform == 'darwin', 'test only relevant for MacOSX') + def test_deployment_target(self): + self._try_compile_deployment_target() + + orig_environ = os.environ + os.environ = orig_environ.copy() + self.addCleanup(setattr, os, 'environ', orig_environ) + + os.environ['MACOSX_DEPLOYMENT_TARGET']='10.1' + self._try_compile_deployment_target() + + + def _try_compile_deployment_target(self): + deptarget_c = os.path.join(self.tmp_dir, 'deptargetmodule.c') + + with open(deptarget_c, 'w') as fp: + fp.write(textwrap.dedent('''\ + #include + + int dummy; + + #if TARGET != MAC_OS_X_VERSION_MIN_REQUIRED + #error "Unexpected target" + #endif + + ''')) + + target = sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET') + target = tuple(map(int, target.split('.'))) + target = '%02d%01d0' % target + + deptarget_ext = Extension( + 'deptarget', + [deptarget_c], + extra_compile_args=['-DTARGET=%s'%(target,)], + ) + dist = Distribution({ + 'name': 'deptarget', + 'ext_modules': [deptarget_ext] + }) + dist.package_dir = self.tmp_dir + cmd = build_ext(dist) + cmd.build_lib = self.tmp_dir + cmd.build_temp = self.tmp_dir + + try: + old_stdout = sys.stdout + cmd.ensure_finalized() + cmd.run() + + except CompileError: + self.fail("Wrong deployment target during compilation") + def test_suite(): return unittest.makeSuite(BuildExtTestCase) diff --git a/Lib/distutils/util.py b/Lib/distutils/util.py index f06e4fdf88..6c49f0b1cb 100644 --- a/Lib/distutils/util.py +++ b/Lib/distutils/util.py @@ -97,9 +97,7 @@ def get_platform (): from distutils.sysconfig import get_config_vars cfgvars = get_config_vars() - macver = os.environ.get('MACOSX_DEPLOYMENT_TARGET') - if not macver: - macver = cfgvars.get('MACOSX_DEPLOYMENT_TARGET') + macver = cfgvars.get('MACOSX_DEPLOYMENT_TARGET') if 1: # Always calculate the release of the running machine, diff --git a/Lib/sysconfig.py b/Lib/sysconfig.py index 3146f30510..9e8acc55ee 100644 --- a/Lib/sysconfig.py +++ b/Lib/sysconfig.py @@ -297,21 +297,6 @@ def _init_posix(vars): msg = msg + " (%s)" % e.strerror raise IOError(msg) - # On MacOSX we need to check the setting of the environment variable - # MACOSX_DEPLOYMENT_TARGET: configure bases some choices on it so - # it needs to be compatible. - # If it isn't set we set it to the configure-time value - if sys.platform == 'darwin' and 'MACOSX_DEPLOYMENT_TARGET' in vars: - cfg_target = vars['MACOSX_DEPLOYMENT_TARGET'] - cur_target = os.getenv('MACOSX_DEPLOYMENT_TARGET', '') - if cur_target == '': - cur_target = cfg_target - os.putenv('MACOSX_DEPLOYMENT_TARGET', cfg_target) - elif map(int, cfg_target.split('.')) > map(int, cur_target.split('.')): - msg = ('$MACOSX_DEPLOYMENT_TARGET mismatch: now "%s" but "%s" ' - 'during configure' % (cur_target, cfg_target)) - raise IOError(msg) - # On AIX, there are wrong paths to the linker scripts in the Makefile # -- these paths are relative to the Python source, but when installed # the scripts are in another directory. @@ -616,9 +601,7 @@ def get_platform(): # machine is going to compile and link as if it were # MACOSX_DEPLOYMENT_TARGET. cfgvars = get_config_vars() - macver = os.environ.get('MACOSX_DEPLOYMENT_TARGET') - if not macver: - macver = cfgvars.get('MACOSX_DEPLOYMENT_TARGET') + macver = cfgvars.get('MACOSX_DEPLOYMENT_TARGET') if 1: # Always calculate the release of the running machine, diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py index 142eb2fb3f..95fbe0ea61 100644 --- a/Lib/test/test_sysconfig.py +++ b/Lib/test/test_sysconfig.py @@ -141,7 +141,7 @@ class TestSysConfig(unittest.TestCase): ('Darwin Kernel Version 8.11.1: ' 'Wed Oct 10 18:23:28 PDT 2007; ' 'root:xnu-792.25.20~1/RELEASE_I386'), 'PowerPC')) - os.environ['MACOSX_DEPLOYMENT_TARGET'] = '10.3' + get_config_vars()['MACOSX_DEPLOYMENT_TARGET'] = '10.3' get_config_vars()['CFLAGS'] = ('-fno-strict-aliasing -DNDEBUG -g ' '-fwrapv -O3 -Wall -Wstrict-prototypes') @@ -161,7 +161,6 @@ class TestSysConfig(unittest.TestCase): 'Wed Oct 10 18:23:28 PDT 2007; ' 'root:xnu-792.25.20~1/RELEASE_I386'), 'i386')) get_config_vars()['MACOSX_DEPLOYMENT_TARGET'] = '10.3' - os.environ['MACOSX_DEPLOYMENT_TARGET'] = '10.3' get_config_vars()['CFLAGS'] = ('-fno-strict-aliasing -DNDEBUG -g ' '-fwrapv -O3 -Wall -Wstrict-prototypes') @@ -176,7 +175,7 @@ class TestSysConfig(unittest.TestCase): sys.maxint = maxint # macbook with fat binaries (fat, universal or fat64) - os.environ['MACOSX_DEPLOYMENT_TARGET'] = '10.4' + get_config_vars()['MACOSX_DEPLOYMENT_TARGET'] = '10.4' get_config_vars()['CFLAGS'] = ('-arch ppc -arch i386 -isysroot ' '/Developer/SDKs/MacOSX10.4u.sdk ' '-fno-strict-aliasing -fno-common ' @@ -265,6 +264,51 @@ class TestSysConfig(unittest.TestCase): user_path = get_path(name, 'posix_user') self.assertEqual(user_path, global_path.replace(base, user)) + @unittest.skipUnless(sys.platform == "darwin", "test only relevant on MacOSX") + def test_platform_in_subprocess(self): + my_platform = sysconfig.get_platform() + + # Test without MACOSX_DEPLOYMENT_TARGET in the environment + + env = os.environ.copy() + if 'MACOSX_DEPLOYMENT_TARGET' in env: + del env['MACOSX_DEPLOYMENT_TARGET'] + + with open('/dev/null', 'w') as devnull_fp: + p = subprocess.Popen([ + sys.executable, '-c', + 'import sysconfig; print(sysconfig.get_platform())', + ], + stdout=subprocess.PIPE, + stderr=devnull_fp, + env=env) + test_platform = p.communicate()[0].strip() + test_platform = test_platform.decode('utf-8') + status = p.wait() + + self.assertEqual(status, 0) + self.assertEqual(my_platform, test_platform) + + + # Test with MACOSX_DEPLOYMENT_TARGET in the environment, and + # using a value that is unlikely to be the default one. + env = os.environ.copy() + env['MACOSX_DEPLOYMENT_TARGET'] = '10.1' + + p = subprocess.Popen([ + sys.executable, '-c', + 'import sysconfig; print(sysconfig.get_platform())', + ], + stdout=subprocess.PIPE, + stderr=open('/dev/null'), + env=env) + test_platform = p.communicate()[0].strip() + test_platform = test_platform.decode('utf-8') + status = p.wait() + + self.assertEqual(status, 0) + self.assertEqual(my_platform, test_platform) + def test_main(): run_unittest(TestSysConfig) -- cgit v1.2.1 From a8955a20fee9ec71292e5c617a925e8b68181fdc Mon Sep 17 00:00:00 2001 From: Ronald Oussoren Date: Sun, 15 May 2011 16:51:10 +0200 Subject: NEWS entry for fix of issue #9516 --- Misc/NEWS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Misc/NEWS b/Misc/NEWS index a603912a0c..23f77e5560 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -80,6 +80,9 @@ Core and Builtins Library ------- +- Issue #9516: avoid errors in sysconfig when MACOSX_DEPLOYMENT_TARGET is + set in shell. + - Issue #12050: zlib.decompressobj().decompress() now clears the unconsumed_tail attribute when called without a max_length argument. -- cgit v1.2.1 From cab755ed09b7ffc071a363ea5f5525eaed20cb73 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 16 May 2011 17:16:18 +0200 Subject: Issue #12057: Convert CJK encoding testcase BLOB into multiple text files --- Lib/test/cjkencodings/big5-utf8.txt | 9 + Lib/test/cjkencodings/big5.txt | 9 + Lib/test/cjkencodings/big5hkscs-utf8.txt | 2 + Lib/test/cjkencodings/big5hkscs.txt | 2 + Lib/test/cjkencodings/cp949-utf8.txt | 9 + Lib/test/cjkencodings/cp949.txt | 9 + Lib/test/cjkencodings/euc_jisx0213-utf8.txt | 8 + Lib/test/cjkencodings/euc_jisx0213.txt | 8 + Lib/test/cjkencodings/euc_jp-utf8.txt | 7 + Lib/test/cjkencodings/euc_jp.txt | 7 + Lib/test/cjkencodings/euc_kr-utf8.txt | 7 + Lib/test/cjkencodings/euc_kr.txt | 7 + Lib/test/cjkencodings/gb18030-utf8.txt | 15 + Lib/test/cjkencodings/gb18030.txt | 15 + Lib/test/cjkencodings/gb2312-utf8.txt | 6 + Lib/test/cjkencodings/gb2312.txt | 6 + Lib/test/cjkencodings/gbk-utf8.txt | 14 + Lib/test/cjkencodings/gbk.txt | 14 + Lib/test/cjkencodings/johab-utf8.txt | 9 + Lib/test/cjkencodings/johab.txt | 9 + Lib/test/cjkencodings/shift_jis-utf8.txt | 7 + Lib/test/cjkencodings/shift_jis.txt | 7 + Lib/test/cjkencodings/shift_jisx0213-utf8.txt | 8 + Lib/test/cjkencodings/shift_jisx0213.txt | 8 + Lib/test/cjkencodings_test.py | 1019 ------------------------- 25 files changed, 202 insertions(+), 1019 deletions(-) create mode 100644 Lib/test/cjkencodings/big5-utf8.txt create mode 100644 Lib/test/cjkencodings/big5.txt create mode 100644 Lib/test/cjkencodings/big5hkscs-utf8.txt create mode 100644 Lib/test/cjkencodings/big5hkscs.txt create mode 100644 Lib/test/cjkencodings/cp949-utf8.txt create mode 100644 Lib/test/cjkencodings/cp949.txt create mode 100644 Lib/test/cjkencodings/euc_jisx0213-utf8.txt create mode 100644 Lib/test/cjkencodings/euc_jisx0213.txt create mode 100644 Lib/test/cjkencodings/euc_jp-utf8.txt create mode 100644 Lib/test/cjkencodings/euc_jp.txt create mode 100644 Lib/test/cjkencodings/euc_kr-utf8.txt create mode 100644 Lib/test/cjkencodings/euc_kr.txt create mode 100644 Lib/test/cjkencodings/gb18030-utf8.txt create mode 100644 Lib/test/cjkencodings/gb18030.txt create mode 100644 Lib/test/cjkencodings/gb2312-utf8.txt create mode 100644 Lib/test/cjkencodings/gb2312.txt create mode 100644 Lib/test/cjkencodings/gbk-utf8.txt create mode 100644 Lib/test/cjkencodings/gbk.txt create mode 100644 Lib/test/cjkencodings/johab-utf8.txt create mode 100644 Lib/test/cjkencodings/johab.txt create mode 100644 Lib/test/cjkencodings/shift_jis-utf8.txt create mode 100644 Lib/test/cjkencodings/shift_jis.txt create mode 100644 Lib/test/cjkencodings/shift_jisx0213-utf8.txt create mode 100644 Lib/test/cjkencodings/shift_jisx0213.txt delete mode 100644 Lib/test/cjkencodings_test.py diff --git a/Lib/test/cjkencodings/big5-utf8.txt b/Lib/test/cjkencodings/big5-utf8.txt new file mode 100644 index 0000000000..a0a534a964 --- /dev/null +++ b/Lib/test/cjkencodings/big5-utf8.txt @@ -0,0 +1,9 @@ +如何在 Python 中使用既有的 C library? + 在資訊科技快速發展的今天, 開發及測試軟體的速度是不容忽視的 +課題. 為加快開發及測試的速度, 我們便常希望能利用一些已開發好的 +library, 並有一個 fast prototyping 的 programming language 可 +供使用. 目前有許許多多的 library 是以 C 寫成, 而 Python 是一個 +fast prototyping 的 programming language. 故我們希望能將既有的 +C library 拿到 Python 的環境中測試及整合. 其中最主要也是我們所 +要討論的問題就是: + diff --git a/Lib/test/cjkencodings/big5.txt b/Lib/test/cjkencodings/big5.txt new file mode 100644 index 0000000000..f4424959e9 --- /dev/null +++ b/Lib/test/cjkencodings/big5.txt @@ -0,0 +1,9 @@ +pb Python ϥάJ C library? +@bTާֳtoi, }oδճn骺t׬Oe +D. [ֶ}oδժt, ڭ̫K`ƱQΤ@Ǥw}on +library, æ@ fast prototyping programming language i +Ѩϥ. ثe\\hh library OH C g, Python O@ +fast prototyping programming language. Gڭ̧ƱNJ +C library Python ҤդξX. 䤤̥Dn]Oڭ̩ +nQתDNO: + diff --git a/Lib/test/cjkencodings/big5hkscs-utf8.txt b/Lib/test/cjkencodings/big5hkscs-utf8.txt new file mode 100644 index 0000000000..f744ce9ae0 --- /dev/null +++ b/Lib/test/cjkencodings/big5hkscs-utf8.txt @@ -0,0 +1,2 @@ +𠄌Ě鵮罓洆 +ÊÊ̄ê êê̄ diff --git a/Lib/test/cjkencodings/big5hkscs.txt b/Lib/test/cjkencodings/big5hkscs.txt new file mode 100644 index 0000000000..81c42b3503 --- /dev/null +++ b/Lib/test/cjkencodings/big5hkscs.txt @@ -0,0 +1,2 @@ +E\sڍ +fb diff --git a/Lib/test/cjkencodings/cp949-utf8.txt b/Lib/test/cjkencodings/cp949-utf8.txt new file mode 100644 index 0000000000..5655e38517 --- /dev/null +++ b/Lib/test/cjkencodings/cp949-utf8.txt @@ -0,0 +1,9 @@ +똠방각하 펲시콜라 + +㉯㉯납!! 因九月패믤릔궈 ⓡⓖ훀¿¿¿ 긍뒙 ⓔ뎨 ㉯. . +亞영ⓔ능횹 . . . . 서울뤄 뎐학乙 家훀 ! ! !ㅠ.ㅠ +흐흐흐 ㄱㄱㄱ☆ㅠ_ㅠ 어릨 탸콰긐 뎌응 칑九들乙 ㉯드긐 +설릌 家훀 . . . . 굴애쉌 ⓔ궈 ⓡ릘㉱긐 因仁川女中까즼 +와쒀훀 ! ! 亞영ⓔ 家능궈 ☆上관 없능궈능 亞능뒈훀 글애듴 +ⓡ려듀九 싀풔숴훀 어릨 因仁川女中싁⑨들앜!! ㉯㉯납♡ ⌒⌒* + diff --git a/Lib/test/cjkencodings/cp949.txt b/Lib/test/cjkencodings/cp949.txt new file mode 100644 index 0000000000..16549aa5e4 --- /dev/null +++ b/Lib/test/cjkencodings/cp949.txt @@ -0,0 +1,9 @@ +c氢 ݶ + +!! Вp ިR ѵ . . +䬿Ѵ . . . . ʫR ! ! !. + ٤_  O h O +j ʫR . . . . ֚f ѱ ސtƒO  +;R ! ! 䬿 ʫɱ ߾ ɱŴ 䬴ɵR ۾֊ +޷ ǴR  Ĩ!! ҡ* + diff --git a/Lib/test/cjkencodings/euc_jisx0213-utf8.txt b/Lib/test/cjkencodings/euc_jisx0213-utf8.txt new file mode 100644 index 0000000000..9a56a2e18b --- /dev/null +++ b/Lib/test/cjkencodings/euc_jisx0213-utf8.txt @@ -0,0 +1,8 @@ +Python の開発は、1990 年ごろから開始されています。 +開発者の Guido van Rossum は教育用のプログラミング言語「ABC」の開発に参加していましたが、ABC は実用上の目的にはあまり適していませんでした。 +このため、Guido はより実用的なプログラミング言語の開発を開始し、英国 BBS 放送のコメディ番組「モンティ パイソン」のファンである Guido はこの言語を「Python」と名づけました。 +このような背景から生まれた Python の言語設計は、「シンプル」で「習得が容易」という目標に重点が置かれています。 +多くのスクリプト系言語ではユーザの目先の利便性を優先して色々な機能を言語要素として取り入れる場合が多いのですが、Python ではそういった小細工が追加されることはあまりありません。 +言語自体の機能は最小限に押さえ、必要な機能は拡張モジュールとして追加する、というのが Python のポリシーです。 + +ノか゚ ト゚ トキ喝塀 𡚴𪎌 麀齁𩛰 diff --git a/Lib/test/cjkencodings/euc_jisx0213.txt b/Lib/test/cjkencodings/euc_jisx0213.txt new file mode 100644 index 0000000000..51e9268ca9 --- /dev/null +++ b/Lib/test/cjkencodings/euc_jisx0213.txt @@ -0,0 +1,8 @@ +Python γȯϡ1990 ǯ鳫ϤƤޤ +ȯԤ Guido van Rossum ϶ѤΥץߥ󥰸ABCפγȯ˻äƤޤABC ϼѾŪˤϤޤŬƤޤǤ +ΤᡢGuido ϤŪʥץߥ󥰸γȯ򳫻Ϥѹ BBS Υǥȡ֥ƥ ѥפΥեǤ Guido ϤθPythonפ̾Ťޤ +Τ褦طʤޤ줿 Python θ߷פϡ֥ץפǡֽưספȤɸ˽֤Ƥޤ +¿ΥץȷϸǤϥ桼ͥ褷ƿʵǽǤȤƼ礬¿ΤǤPython ǤϤäٹɲä뤳ȤϤޤꤢޤ +켫ΤεǽϺǾ¤˲ɬפʵǽϳĥ⥸塼Ȥɲä롢ȤΤ Python ΥݥꥷǤ + +Τ ȥ ԏ diff --git a/Lib/test/cjkencodings/euc_jp-utf8.txt b/Lib/test/cjkencodings/euc_jp-utf8.txt new file mode 100644 index 0000000000..7763250ebb --- /dev/null +++ b/Lib/test/cjkencodings/euc_jp-utf8.txt @@ -0,0 +1,7 @@ +Python の開発は、1990 年ごろから開始されています。 +開発者の Guido van Rossum は教育用のプログラミング言語「ABC」の開発に参加していましたが、ABC は実用上の目的にはあまり適していませんでした。 +このため、Guido はより実用的なプログラミング言語の開発を開始し、英国 BBS 放送のコメディ番組「モンティ パイソン」のファンである Guido はこの言語を「Python」と名づけました。 +このような背景から生まれた Python の言語設計は、「シンプル」で「習得が容易」という目標に重点が置かれています。 +多くのスクリプト系言語ではユーザの目先の利便性を優先して色々な機能を言語要素として取り入れる場合が多いのですが、Python ではそういった小細工が追加されることはあまりありません。 +言語自体の機能は最小限に押さえ、必要な機能は拡張モジュールとして追加する、というのが Python のポリシーです。 + diff --git a/Lib/test/cjkencodings/euc_jp.txt b/Lib/test/cjkencodings/euc_jp.txt new file mode 100644 index 0000000000..9da6b5d83d --- /dev/null +++ b/Lib/test/cjkencodings/euc_jp.txt @@ -0,0 +1,7 @@ +Python γȯϡ1990 ǯ鳫ϤƤޤ +ȯԤ Guido van Rossum ϶ѤΥץߥ󥰸ABCפγȯ˻äƤޤABC ϼѾŪˤϤޤŬƤޤǤ +ΤᡢGuido ϤŪʥץߥ󥰸γȯ򳫻Ϥѹ BBS Υǥȡ֥ƥ ѥפΥեǤ Guido ϤθPythonפ̾Ťޤ +Τ褦طʤޤ줿 Python θ߷פϡ֥ץפǡֽưספȤɸ˽֤Ƥޤ +¿ΥץȷϸǤϥ桼ͥ褷ƿʵǽǤȤƼ礬¿ΤǤPython ǤϤäٹɲä뤳ȤϤޤꤢޤ +켫ΤεǽϺǾ¤˲ɬפʵǽϳĥ⥸塼Ȥɲä롢ȤΤ Python ΥݥꥷǤ + diff --git a/Lib/test/cjkencodings/euc_kr-utf8.txt b/Lib/test/cjkencodings/euc_kr-utf8.txt new file mode 100644 index 0000000000..16c37412b6 --- /dev/null +++ b/Lib/test/cjkencodings/euc_kr-utf8.txt @@ -0,0 +1,7 @@ +◎ 파이썬(Python)은 배우기 쉽고, 강력한 프로그래밍 언어입니다. 파이썬은 +효율적인 고수준 데이터 구조와 간단하지만 효율적인 객체지향프로그래밍을 +지원합니다. 파이썬의 우아(優雅)한 문법과 동적 타이핑, 그리고 인터프리팅 +환경은 파이썬을 스크립팅과 여러 분야에서와 대부분의 플랫폼에서의 빠른 +애플리케이션 개발을 할 수 있는 이상적인 언어로 만들어줍니다. + +☆첫가끝: 날아라 쓔쓔쓩~ 닁큼! 뜽금없이 전홥니다. 뷁. 그런거 읎다. diff --git a/Lib/test/cjkencodings/euc_kr.txt b/Lib/test/cjkencodings/euc_kr.txt new file mode 100644 index 0000000000..f68dd35028 --- /dev/null +++ b/Lib/test/cjkencodings/euc_kr.txt @@ -0,0 +1,7 @@ + ̽(Python) , α׷ Դϴ. ̽ +ȿ ȿ üα׷ +մϴ. ̽ () Ÿ, ׸ +ȯ ̽ ũð о߿ κ ÷ +ø̼ ִ ̻ ݴϴ. + +ù: ƶ ԤФԤԤФԾ~ ԤҤŭ! ԤѤݾ ԤȤϴ. ԤΤ. ׷ ԤѤ. diff --git a/Lib/test/cjkencodings/gb18030-utf8.txt b/Lib/test/cjkencodings/gb18030-utf8.txt new file mode 100644 index 0000000000..2060d2593e --- /dev/null +++ b/Lib/test/cjkencodings/gb18030-utf8.txt @@ -0,0 +1,15 @@ +Python(派森)语言是一种功能强大而完善的通用型计算机程序设计语言, +已经具有十多年的发展历史,成熟且稳定。这种语言具有非常简捷而清晰 +的语法特点,适合完成各种高层任务,几乎可以在所有的操作系统中 +运行。这种语言简单而强大,适合各种人士学习使用。目前,基于这 +种语言的相关技术正在飞速的发展,用户数量急剧扩大,相关的资源非常多。 +如何在 Python 中使用既有的 C library? + 在資訊科技快速發展的今天, 開發及測試軟體的速度是不容忽視的 +課題. 為加快開發及測試的速度, 我們便常希望能利用一些已開發好的 +library, 並有一個 fast prototyping 的 programming language 可 +供使用. 目前有許許多多的 library 是以 C 寫成, 而 Python 是一個 +fast prototyping 的 programming language. 故我們希望能將既有的 +C library 拿到 Python 的環境中測試及整合. 其中最主要也是我們所 +要討論的問題就是: +파이썬은 강력한 기능을 지닌 범용 컴퓨터 프로그래밍 언어다. + diff --git a/Lib/test/cjkencodings/gb18030.txt b/Lib/test/cjkencodings/gb18030.txt new file mode 100644 index 0000000000..5d1f6dca23 --- /dev/null +++ b/Lib/test/cjkencodings/gb18030.txt @@ -0,0 +1,15 @@ +PythonɭһֹǿƵͨͼԣ +ѾʮķչʷȶԾзdzݶ +﷨ص㣬ʺɸָ߲񣬼еIJϵͳ +СԼ򵥶ǿʺϸʿѧϰʹáĿǰ +ԵؼڷٵķչûصԴdzࡣ + Python ʹüе C library? +YӍƼٰlչĽ, _lyԇܛwٶDzݺҕ +n}. ӿ_lyԇٶ, ҂㳣ϣһЩ_lõ +library, Kһ fast prototyping programming language +ʹ. ĿǰSS library C , Python һ +fast prototyping programming language. ҂ϣ܌е +C library õ Python ĭhМyԇ. ҪҲ҂ +ҪӑՓĆ}: +51332131 760463 858635 3195 0930 435755 5509899304 292599. + diff --git a/Lib/test/cjkencodings/gb2312-utf8.txt b/Lib/test/cjkencodings/gb2312-utf8.txt new file mode 100644 index 0000000000..efb7d8f95c --- /dev/null +++ b/Lib/test/cjkencodings/gb2312-utf8.txt @@ -0,0 +1,6 @@ +Python(派森)语言是一种功能强大而完善的通用型计算机程序设计语言, +已经具有十多年的发展历史,成熟且稳定。这种语言具有非常简捷而清晰 +的语法特点,适合完成各种高层任务,几乎可以在所有的操作系统中 +运行。这种语言简单而强大,适合各种人士学习使用。目前,基于这 +种语言的相关技术正在飞速的发展,用户数量急剧扩大,相关的资源非常多。 + diff --git a/Lib/test/cjkencodings/gb2312.txt b/Lib/test/cjkencodings/gb2312.txt new file mode 100644 index 0000000000..1536ac10b9 --- /dev/null +++ b/Lib/test/cjkencodings/gb2312.txt @@ -0,0 +1,6 @@ +PythonɭһֹǿƵͨͼԣ +ѾʮķչʷȶԾзdzݶ +﷨ص㣬ʺɸָ߲񣬼еIJϵͳ +СԼ򵥶ǿʺϸʿѧϰʹáĿǰ +ԵؼڷٵķչûصԴdzࡣ + diff --git a/Lib/test/cjkencodings/gbk-utf8.txt b/Lib/test/cjkencodings/gbk-utf8.txt new file mode 100644 index 0000000000..75bbd31ec5 --- /dev/null +++ b/Lib/test/cjkencodings/gbk-utf8.txt @@ -0,0 +1,14 @@ +Python(派森)语言是一种功能强大而完善的通用型计算机程序设计语言, +已经具有十多年的发展历史,成熟且稳定。这种语言具有非常简捷而清晰 +的语法特点,适合完成各种高层任务,几乎可以在所有的操作系统中 +运行。这种语言简单而强大,适合各种人士学习使用。目前,基于这 +种语言的相关技术正在飞速的发展,用户数量急剧扩大,相关的资源非常多。 +如何在 Python 中使用既有的 C library? + 在資訊科技快速發展的今天, 開發及測試軟體的速度是不容忽視的 +課題. 為加快開發及測試的速度, 我們便常希望能利用一些已開發好的 +library, 並有一個 fast prototyping 的 programming language 可 +供使用. 目前有許許多多的 library 是以 C 寫成, 而 Python 是一個 +fast prototyping 的 programming language. 故我們希望能將既有的 +C library 拿到 Python 的環境中測試及整合. 其中最主要也是我們所 +要討論的問題就是: + diff --git a/Lib/test/cjkencodings/gbk.txt b/Lib/test/cjkencodings/gbk.txt new file mode 100644 index 0000000000..8788f8a2dc --- /dev/null +++ b/Lib/test/cjkencodings/gbk.txt @@ -0,0 +1,14 @@ +PythonɭһֹǿƵͨͼԣ +ѾʮķչʷȶԾзdzݶ +﷨ص㣬ʺɸָ߲񣬼еIJϵͳ +СԼ򵥶ǿʺϸʿѧϰʹáĿǰ +ԵؼڷٵķչûصԴdzࡣ + Python ʹüе C library? +YӍƼٰlչĽ, _lyԇܛwٶDzݺҕ +n}. ӿ_lyԇٶ, ҂㳣ϣһЩ_lõ +library, Kһ fast prototyping programming language +ʹ. ĿǰSS library C , Python һ +fast prototyping programming language. ҂ϣ܌е +C library õ Python ĭhМyԇ. ҪҲ҂ +ҪӑՓĆ}: + diff --git a/Lib/test/cjkencodings/johab-utf8.txt b/Lib/test/cjkencodings/johab-utf8.txt new file mode 100644 index 0000000000..5655e38517 --- /dev/null +++ b/Lib/test/cjkencodings/johab-utf8.txt @@ -0,0 +1,9 @@ +똠방각하 펲시콜라 + +㉯㉯납!! 因九月패믤릔궈 ⓡⓖ훀¿¿¿ 긍뒙 ⓔ뎨 ㉯. . +亞영ⓔ능횹 . . . . 서울뤄 뎐학乙 家훀 ! ! !ㅠ.ㅠ +흐흐흐 ㄱㄱㄱ☆ㅠ_ㅠ 어릨 탸콰긐 뎌응 칑九들乙 ㉯드긐 +설릌 家훀 . . . . 굴애쉌 ⓔ궈 ⓡ릘㉱긐 因仁川女中까즼 +와쒀훀 ! ! 亞영ⓔ 家능궈 ☆上관 없능궈능 亞능뒈훀 글애듴 +ⓡ려듀九 싀풔숴훀 어릨 因仁川女中싁⑨들앜!! ㉯㉯납♡ ⌒⌒* + diff --git a/Lib/test/cjkencodings/johab.txt b/Lib/test/cjkencodings/johab.txt new file mode 100644 index 0000000000..067781b785 --- /dev/null +++ b/Lib/test/cjkencodings/johab.txt @@ -0,0 +1,9 @@ +wba \ũa + +s!! gÚ zٯٯٯ w ѕ . . + Date: Tue, 17 May 2011 01:18:33 +0200 Subject: Issue #11614: Fix test_linecache, cjkencodings_test.py doesn't exist anymore --- Lib/test/test_linecache.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_linecache.py b/Lib/test/test_linecache.py index 407bebce8c..b5f80a4f43 100644 --- a/Lib/test/test_linecache.py +++ b/Lib/test/test_linecache.py @@ -9,7 +9,7 @@ from test import test_support as support FILENAME = linecache.__file__ INVALID_NAME = '!@$)(!@#_1' EMPTY = '' -TESTS = 'cjkencodings_test inspect_fodder inspect_fodder2 mapping_tests' +TESTS = 'inspect_fodder inspect_fodder2 mapping_tests' TESTS = TESTS.split() TEST_PATH = os.path.dirname(support.__file__) MODULES = "linecache abc".split() -- cgit v1.2.1 From aa749990f44691d71834e2929ab6e17568947642 Mon Sep 17 00:00:00 2001 From: Senthil Kumaran Date: Tue, 17 May 2011 10:12:18 +0800 Subject: Fix closes issue #12088 - fixes the tarfile.extractall issue when the symlinks/hardlink was broken. It handles now in a graceful manner (No exception is raised, behavior similar GNU tar). --- Lib/tarfile.py | 4 +++- Lib/test/test_tarfile.py | 60 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/Lib/tarfile.py b/Lib/tarfile.py index 105a75880d..6b9303e898 100644 --- a/Lib/tarfile.py +++ b/Lib/tarfile.py @@ -2239,12 +2239,14 @@ class TarFile(object): if hasattr(os, "symlink") and hasattr(os, "link"): # For systems that support symbolic and hard links. if tarinfo.issym(): - if os.path.exists(targetpath): + if os.path.lexists(targetpath): os.unlink(targetpath) os.symlink(tarinfo.linkname, targetpath) else: # See extract(). if os.path.exists(tarinfo._link_target): + if os.path.lexists(targetpath): + os.unlink(targetpath) os.link(tarinfo._link_target, targetpath) else: self._extract_member(self._find_link_target(tarinfo), targetpath) diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py index f78f9ce03f..6962f8e2d7 100644 --- a/Lib/test/test_tarfile.py +++ b/Lib/test/test_tarfile.py @@ -872,6 +872,66 @@ class WriteTest(WriteTestBase): os.unlink(temparchive) shutil.rmtree(tempdir) + @unittest.skipUnless(hasattr(os, 'symlink'), "needs os.symlink") + def test_extractall_broken_symlinks(self): + # Test if extractall works properly when tarfile contains broken + # symlinks + tempdir = os.path.join(TEMPDIR, "testsymlinks") + temparchive = os.path.join(TEMPDIR, "testsymlinks.tar") + os.mkdir(tempdir) + try: + source_file = os.path.join(tempdir,'source') + target_file = os.path.join(tempdir,'symlink') + with open(source_file,'w') as f: + f.write('something\n') + os.symlink(source_file, target_file) + tar = tarfile.open(temparchive,'w') + tar.add(target_file, arcname=os.path.basename(target_file)) + tar.close() + # remove the real file + os.unlink(source_file) + # Let's extract it to the location which contains the symlink + tar = tarfile.open(temparchive,'r') + # this should not raise OSError: [Errno 17] File exists + try: + tar.extractall(path=tempdir) + except OSError: + self.fail("extractall failed with broken symlinked files") + finally: + tar.close() + finally: + os.unlink(temparchive) + shutil.rmtree(tempdir) + + @unittest.skipUnless(hasattr(os, 'link'), "needs os.link") + def test_extractall_hardlinks(self): + # Test if extractall works properly when tarfile contains symlinks + tempdir = os.path.join(TEMPDIR, "testsymlinks") + temparchive = os.path.join(TEMPDIR, "testsymlinks.tar") + os.mkdir(tempdir) + try: + source_file = os.path.join(tempdir,'source') + target_file = os.path.join(tempdir,'symlink') + with open(source_file,'w') as f: + f.write('something\n') + os.link(source_file, target_file) + tar = tarfile.open(temparchive,'w') + tar.add(source_file, arcname=os.path.basename(source_file)) + tar.add(target_file, arcname=os.path.basename(target_file)) + tar.close() + # Let's extract it to the location which contains the symlink + tar = tarfile.open(temparchive,'r') + # this should not raise OSError: [Errno 17] File exists + try: + tar.extractall(path=tempdir) + except OSError: + self.fail("extractall failed with linked files") + finally: + tar.close() + finally: + os.unlink(temparchive) + shutil.rmtree(tempdir) + class StreamWriteTest(WriteTestBase): mode = "w|" -- cgit v1.2.1 From 85129b4f7ccb977fad224af9dc452fb1e0c23868 Mon Sep 17 00:00:00 2001 From: Ezio Melotti Date: Tue, 17 May 2011 05:17:35 +0300 Subject: #12093: fix typo in struct doc. Patch by Sandro Tosi. --- Doc/library/struct.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/struct.rst b/Doc/library/struct.rst index 0b8052c40d..18f6a83b6b 100644 --- a/Doc/library/struct.rst +++ b/Doc/library/struct.rst @@ -314,7 +314,7 @@ the result in a named tuple:: >>> from collections import namedtuple >>> Student = namedtuple('Student', 'name serialnum school gradelevel') - >>> Student._make(unpack('<10sHHb', s)) + >>> Student._make(unpack('<10sHHb', record)) Student(name='raymond ', serialnum=4658, school=264, gradelevel=8) The ordering of format characters may have an impact on size since the padding -- cgit v1.2.1 From 7dca4ee0e691dcf69bd6f4a5761366d7d11abbb3 Mon Sep 17 00:00:00 2001 From: Ezio Melotti Date: Tue, 17 May 2011 05:39:22 +0300 Subject: #12092: backport rephrasing of a paragraph in the tutorial. --- Doc/tutorial/controlflow.rst | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Doc/tutorial/controlflow.rst b/Doc/tutorial/controlflow.rst index de93beb244..5c7ca4e0a4 100644 --- a/Doc/tutorial/controlflow.rst +++ b/Doc/tutorial/controlflow.rst @@ -455,10 +455,9 @@ and of course it would print:: shopkeeper : Michael Palin sketch : Cheese Shop Sketch -Note that the :meth:`sort` method of the list of keyword argument names is -called before printing the contents of the ``keywords`` dictionary; if this is -not done, the order in which the arguments are printed is undefined. - +Note that the list of keyword argument names is created by sorting the result +of the keywords dictionary's ``keys()`` method before printing its contents; +if this is not done, the order in which the arguments are printed is undefined. .. _tut-arbitraryargs: -- cgit v1.2.1 From 5bf77fca1e8c862bddf43abed69a66350b2f9448 Mon Sep 17 00:00:00 2001 From: Ronald Oussoren Date: Tue, 17 May 2011 13:22:30 +0200 Subject: (backport)Fix #10154 and #10090: locale normalizes the UTF-8 encoding to "UTF-8" instead of "UTF8" On MacOSX and OpenBSD (and possibly other BSDs) "en_US.UTF-8" is a valid locale while "en_US.UTF8" is not. As the former works on Linux as well it is better to normalize to that value. --- Lib/locale.py | 2 +- Misc/NEWS | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Lib/locale.py b/Lib/locale.py index 921f4f6bef..bb4aa37b29 100644 --- a/Lib/locale.py +++ b/Lib/locale.py @@ -621,7 +621,7 @@ locale_encoding_alias = { 'tactis': 'TACTIS', 'euc_jp': 'eucJP', 'euc_kr': 'eucKR', - 'utf_8': 'UTF8', + 'utf_8': 'UTF-8', 'koi8_r': 'KOI8-R', 'koi8_u': 'KOI8-U', # XXX This list is still incomplete. If you know more diff --git a/Misc/NEWS b/Misc/NEWS index 23f77e5560..3262205db4 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -80,6 +80,9 @@ Core and Builtins Library ------- +- Issue #10154, #10090: change the normalization of UTF-8 to "UTF-8" instead + of "UTF8" in the locale module as the latter is not supported MacOSX and OpenBSD. + - Issue #9516: avoid errors in sysconfig when MACOSX_DEPLOYMENT_TARGET is set in shell. -- cgit v1.2.1 From 61736bc38c208cb5ad133f2845696356210e9e54 Mon Sep 17 00:00:00 2001 From: Ronald Oussoren Date: Tue, 17 May 2011 15:13:46 +0200 Subject: (backport) Fixes #11088: IDLE crashes when using F5 to run a script on OSX with Tk 8.5 Without this patch IDLE will crash reliably on OSX when Tkinter is linked to TkCocoa 8.5.x. To reproduce: * Create a new file (script.py) with the following two lines: x = raw_input('prompt: ') print x * Save the script * Run the script using the F5 keyboard shortcut (running from the menu works fine) The patch is a fairly crude hack, but we haven't found a better workaround for this Tk bug yet. --- Lib/idlelib/ScriptBinding.py | 17 +++++++++++++++++ Misc/NEWS | 3 +++ 2 files changed, 20 insertions(+) diff --git a/Lib/idlelib/ScriptBinding.py b/Lib/idlelib/ScriptBinding.py index 9a16e3c779..1139b30784 100644 --- a/Lib/idlelib/ScriptBinding.py +++ b/Lib/idlelib/ScriptBinding.py @@ -26,6 +26,7 @@ import tkMessageBox from idlelib import PyShell from idlelib.configHandler import idleConf +from idlelib import macosxSupport IDENTCHARS = string.ascii_letters + string.digits + "_" @@ -53,6 +54,9 @@ class ScriptBinding: self.flist = self.editwin.flist self.root = self.editwin.root + if macosxSupport.runningAsOSXApp(): + self.editwin.text_frame.bind('<>', self._run_module_event) + def check_module_event(self, event): filename = self.getfilename() if not filename: @@ -166,6 +170,19 @@ class ScriptBinding: interp.runcode(code) return 'break' + if macosxSupport.runningAsOSXApp(): + # Tk-Cocoa in MacOSX is broken until at least + # Tk 8.5.9, and without this rather + # crude workaround IDLE would hang when a user + # tries to run a module using the keyboard shortcut + # (the menu item works fine). + _run_module_event = run_module_event + + def run_module_event(self, event): + self.editwin.text_frame.after(200, + lambda: self.editwin.text_frame.event_generate('<>')) + return 'break' + def getfilename(self): """Get source filename. If not saved, offer to save (or create) file diff --git a/Misc/NEWS b/Misc/NEWS index 3262205db4..c666d3e47f 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -80,6 +80,9 @@ Core and Builtins Library ------- +- Issue #11088: don't crash when using F5 to run a script in IDLE on MacOSX + with Tk 8.5. + - Issue #10154, #10090: change the normalization of UTF-8 to "UTF-8" instead of "UTF8" in the locale module as the latter is not supported MacOSX and OpenBSD. -- cgit v1.2.1 From 0658bfff5f392f83d9ea19c2eb06862f0382337d Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 17 May 2011 15:49:56 +0200 Subject: Issue #12057: Fix .hgeol and test_multibytecodec_support for the conversion of the CJK encoding testcase BLOB into multiple text files. --- .hgeol | 3 ++- Lib/test/test_multibytecodec_support.py | 17 ++++++++++++----- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/.hgeol b/.hgeol index e1c19926a8..fe666055d3 100644 --- a/.hgeol +++ b/.hgeol @@ -27,8 +27,9 @@ **.zip = BIN Lib/email/test/data/msg_26.txt = BIN -Lib/test/sndhdrdata/sndhdr.* = BIN +Lib/test/cjkencodings/* = BIN Lib/test/decimaltestdata/*.decTest = BIN +Lib/test/sndhdrdata/sndhdr.* = BIN # All other files (which presumably are human-editable) are "native". # This must be the last rule! diff --git a/Lib/test/test_multibytecodec_support.py b/Lib/test/test_multibytecodec_support.py index 0639032a2d..94529096d2 100644 --- a/Lib/test/test_multibytecodec_support.py +++ b/Lib/test/test_multibytecodec_support.py @@ -4,8 +4,11 @@ # Common Unittest Routines for CJK codecs # -import sys, codecs -import unittest, re +import codecs +import os +import re +import sys +import unittest from httplib import HTTPException from test import test_support from StringIO import StringIO @@ -326,6 +329,10 @@ class TestBase_Mapping(unittest.TestCase): self.fail('Decoding failed while testing %s -> %s: %s' % ( repr(csetch), repr(unich), exc.reason)) -def load_teststring(encoding): - from test import cjkencodings_test - return cjkencodings_test.teststring[encoding] +def load_teststring(name): + dir = os.path.join(os.path.dirname(__file__), 'cjkencodings') + with open(os.path.join(dir, name + '.txt'), 'rb') as f: + encoded = f.read() + with open(os.path.join(dir, name + '-utf8.txt'), 'rb') as f: + utf8 = f.read() + return encoded, utf8 -- cgit v1.2.1 From 43716e25c8c956eb8df9e81bc1d529a9d625e079 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Tue, 17 May 2011 18:31:20 -0500 Subject: stop using the old brain-dead interface for providing attributes/methods This closes #12099. --- Misc/NEWS | 4 + Modules/_sre.c | 238 ++++++++++++++++++++++++++++----------------------------- 2 files changed, 122 insertions(+), 120 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS index 23f77e5560..28559643ce 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -382,6 +382,10 @@ Library Extension Modules ----------------- +- Stop using the old interface for providing methods and attributes in the _sre + module. Among other things, this gives these classes ``__class__`` + attributes. (See #12099) + - Issue #10169: Fix argument parsing in socket.sendto() to avoid error masking. - Issue #12051: Fix segfault in json.dumps() while encoding highly-nested diff --git a/Modules/_sre.c b/Modules/_sre.c index 9315f102c7..200e8dd95f 100644 --- a/Modules/_sre.c +++ b/Modules/_sre.c @@ -2598,46 +2598,22 @@ static PyMethodDef pattern_methods[] = { {NULL, NULL} }; -static PyObject* -pattern_getattr(PatternObject* self, char* name) -{ - PyObject* res; - - res = Py_FindMethod(pattern_methods, (PyObject*) self, name); - - if (res) - return res; - - PyErr_Clear(); - - /* attributes */ - if (!strcmp(name, "pattern")) { - Py_INCREF(self->pattern); - return self->pattern; - } - - if (!strcmp(name, "flags")) - return Py_BuildValue("i", self->flags); - - if (!strcmp(name, "groups")) - return Py_BuildValue("i", self->groups); - - if (!strcmp(name, "groupindex") && self->groupindex) { - Py_INCREF(self->groupindex); - return self->groupindex; - } - - PyErr_SetString(PyExc_AttributeError, name); - return NULL; -} +#define PAT_OFF(x) offsetof(PatternObject, x) +static PyMemberDef pattern_members[] = { + {"pattern", T_OBJECT, PAT_OFF(pattern), READONLY}, + {"flags", T_INT, PAT_OFF(flags), READONLY}, + {"groups", T_PYSSIZET, PAT_OFF(groups), READONLY}, + {"groupindex", T_OBJECT, PAT_OFF(groupindex), READONLY}, + {NULL} /* Sentinel */ +}; statichere PyTypeObject Pattern_Type = { PyObject_HEAD_INIT(NULL) 0, "_" SRE_MODULE ".SRE_Pattern", sizeof(PatternObject), sizeof(SRE_CODE), (destructor)pattern_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - (getattrfunc)pattern_getattr, /*tp_getattr*/ + 0, /* tp_print */ + 0, /* tp_getattrn */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ @@ -2650,12 +2626,16 @@ statichere PyTypeObject Pattern_Type = { 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ pattern_doc, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ offsetof(PatternObject, weakreflist), /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + pattern_methods, /* tp_methods */ + pattern_members, /* tp_members */ }; static int _validate(PatternObject *self); /* Forward */ @@ -3562,7 +3542,7 @@ match_deepcopy(MatchObject* self, PyObject* memo) #endif } -static PyMethodDef match_methods[] = { +static struct PyMethodDef match_methods[] = { {"group", (PyCFunction) match_group, METH_VARARGS}, {"start", (PyCFunction) match_start, METH_VARARGS}, {"end", (PyCFunction) match_end, METH_VARARGS}, @@ -3575,80 +3555,90 @@ static PyMethodDef match_methods[] = { {NULL, NULL} }; -static PyObject* -match_getattr(MatchObject* self, char* name) +static PyObject * +match_lastindex_get(MatchObject *self) { - PyObject* res; - - res = Py_FindMethod(match_methods, (PyObject*) self, name); - if (res) - return res; - - PyErr_Clear(); - - if (!strcmp(name, "lastindex")) { - if (self->lastindex >= 0) - return Py_BuildValue("i", self->lastindex); - Py_INCREF(Py_None); - return Py_None; - } - - if (!strcmp(name, "lastgroup")) { - if (self->pattern->indexgroup && self->lastindex >= 0) { - PyObject* result = PySequence_GetItem( - self->pattern->indexgroup, self->lastindex - ); - if (result) - return result; - PyErr_Clear(); - } - Py_INCREF(Py_None); - return Py_None; - } - - if (!strcmp(name, "string")) { - if (self->string) { - Py_INCREF(self->string); - return self->string; - } else { - Py_INCREF(Py_None); - return Py_None; - } - } + if (self->lastindex >= 0) + return Py_BuildValue("i", self->lastindex); + Py_INCREF(Py_None); + return Py_None; +} - if (!strcmp(name, "regs")) { - if (self->regs) { - Py_INCREF(self->regs); - return self->regs; - } else - return match_regs(self); +static PyObject * +match_lastgroup_get(MatchObject *self) +{ + if (self->pattern->indexgroup && self->lastindex >= 0) { + PyObject* result = PySequence_GetItem( + self->pattern->indexgroup, self->lastindex + ); + if (result) + return result; + PyErr_Clear(); } + Py_INCREF(Py_None); + return Py_None; +} - if (!strcmp(name, "re")) { - Py_INCREF(self->pattern); - return (PyObject*) self->pattern; - } +static PyObject * +match_regs_get(MatchObject *self) +{ + if (self->regs) { + Py_INCREF(self->regs); + return self->regs; + } else + return match_regs(self); +} - if (!strcmp(name, "pos")) - return Py_BuildValue("i", self->pos); +static PyGetSetDef match_getset[] = { + {"lastindex", (getter)match_lastindex_get, (setter)NULL}, + {"lastgroup", (getter)match_lastgroup_get, (setter)NULL}, + {"regs", (getter)match_regs_get, (setter)NULL}, + {NULL} +}; - if (!strcmp(name, "endpos")) - return Py_BuildValue("i", self->endpos); +#define MATCH_OFF(x) offsetof(MatchObject, x) +static PyMemberDef match_members[] = { + {"string", T_OBJECT, MATCH_OFF(string), READONLY}, + {"re", T_OBJECT, MATCH_OFF(pattern), READONLY}, + {"pos", T_PYSSIZET, MATCH_OFF(pos), READONLY}, + {"endpos", T_PYSSIZET, MATCH_OFF(endpos), READONLY}, + {NULL} +}; - PyErr_SetString(PyExc_AttributeError, name); - return NULL; -} /* FIXME: implement setattr("string", None) as a special case (to detach the associated string, if any */ -statichere PyTypeObject Match_Type = { - PyObject_HEAD_INIT(NULL) - 0, "_" SRE_MODULE ".SRE_Match", +static PyTypeObject Match_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "_" SRE_MODULE ".SRE_Match", sizeof(MatchObject), sizeof(Py_ssize_t), - (destructor)match_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - (getattrfunc)match_getattr /*tp_getattr*/ + (destructor)match_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + match_methods, /* tp_methods */ + match_members, /* tp_members */ + match_getset, /* tp_getset */ }; static PyObject* @@ -3797,34 +3787,42 @@ static PyMethodDef scanner_methods[] = { {NULL, NULL} }; -static PyObject* -scanner_getattr(ScannerObject* self, char* name) -{ - PyObject* res; - - res = Py_FindMethod(scanner_methods, (PyObject*) self, name); - if (res) - return res; - - PyErr_Clear(); - - /* attributes */ - if (!strcmp(name, "pattern")) { - Py_INCREF(self->pattern); - return self->pattern; - } - - PyErr_SetString(PyExc_AttributeError, name); - return NULL; -} +#define SCAN_OFF(x) offsetof(ScannerObject, x) +static PyMemberDef scanner_members[] = { + {"pattern", T_OBJECT, SCAN_OFF(pattern), READONLY}, + {NULL} /* Sentinel */ +}; statichere PyTypeObject Scanner_Type = { PyObject_HEAD_INIT(NULL) 0, "_" SRE_MODULE ".SRE_Scanner", sizeof(ScannerObject), 0, (destructor)scanner_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - (getattrfunc)scanner_getattr, /*tp_getattr*/ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + scanner_methods, /* tp_methods */ + scanner_members, /* tp_members */ + 0, /* tp_getset */ }; static PyObject* -- cgit v1.2.1 From af7a070e2915b0a39cc85caf3fb683f5ba31d98f Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Wed, 18 May 2011 17:28:50 -0500 Subject: Minor code cleanup. --- Lib/random.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/random.py b/Lib/random.py index 1ab75d57d8..987cff16c4 100644 --- a/Lib/random.py +++ b/Lib/random.py @@ -317,7 +317,7 @@ class Random(_random.Random): n = len(population) if not 0 <= k <= n: - raise ValueError, "sample larger than population" + raise ValueError("sample larger than population") random = self.random _int = int result = [None] * k -- cgit v1.2.1 From 8eb7dfc56c306cc700effe0ec38109541cf79a78 Mon Sep 17 00:00:00 2001 From: Ezio Melotti Date: Fri, 20 May 2011 15:04:38 +0300 Subject: #12072: add missing parenthesis in the doc. Patch by Sandro Tosi. --- Doc/c-api/buffer.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/c-api/buffer.rst b/Doc/c-api/buffer.rst index a75b07bf1c..21e8c4ab8a 100644 --- a/Doc/c-api/buffer.rst +++ b/Doc/c-api/buffer.rst @@ -276,7 +276,7 @@ Buffer related functions .. cfunction:: void PyBuffer_FillContiguousStrides(int ndim, Py_ssize_t *shape, Py_ssize_t *strides, Py_ssize_t itemsize, char fortran) Fill the *strides* array with byte-strides of a contiguous (C-style if - *fortran* is ``'C'`` or Fortran-style if *fortran* is ``'F'`` array of the + *fortran* is ``'C'`` or Fortran-style if *fortran* is ``'F'``) array of the given shape with the given number of bytes per element. -- cgit v1.2.1 From 80f71e2ae7fae2761fb394df0ff4a3e01c310c3a Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Fri, 20 May 2011 11:41:13 -0500 Subject: add example for not using access --- Doc/library/os.rst | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/Doc/library/os.rst b/Doc/library/os.rst index b16fb1fa36..0466da4487 100644 --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -916,7 +916,26 @@ Files and Directories Using :func:`access` to check if a user is authorized to e.g. open a file before actually doing so using :func:`open` creates a security hole, because the user might exploit the short time interval between checking - and opening the file to manipulate it. + and opening the file to manipulate it. It's preferable to use :term:`EAFP` + techniques. For example:: + + if os.access("myfile", os.R_OK): + with open("myfile") as fp: + return fp.read() + return "some default data" + + is better written as:: + + try: + fp = open("myfile") + except OSError as e: + if e.errno == errno.EACCESS: + return "some default data" + # Not a permission error. + raise + else: + with fp: + return fp.read() .. note:: -- cgit v1.2.1 From 0caa97dc7cdfcb4f3c95d988d5059d81415ff2a2 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Fri, 20 May 2011 11:49:06 -0500 Subject: this should actually be an IOError --- Doc/library/os.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/os.rst b/Doc/library/os.rst index 0466da4487..7915b2237b 100644 --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -928,7 +928,7 @@ Files and Directories try: fp = open("myfile") - except OSError as e: + except IOError as e: if e.errno == errno.EACCESS: return "some default data" # Not a permission error. -- cgit v1.2.1 From 3c8e4143bf8556d52e078e2f18b496afa2389ac3 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sat, 21 May 2011 02:13:22 +0200 Subject: Issue #12124: zipimport doesn't keep a reference to zlib.decompress() anymore to be able to unload the module. --- Lib/test/test_zipimport.py | 17 ----------------- Misc/NEWS | 5 ++++- Modules/zipimport.c | 47 +++++++++++++++++++++++----------------------- 3 files changed, 27 insertions(+), 42 deletions(-) diff --git a/Lib/test/test_zipimport.py b/Lib/test/test_zipimport.py index 5974c8bfb6..a66738a778 100644 --- a/Lib/test/test_zipimport.py +++ b/Lib/test/test_zipimport.py @@ -25,11 +25,6 @@ import StringIO from traceback import extract_tb, extract_stack, print_tb raise_src = 'def do_raise(): raise TypeError\n' -# so we only run testAFakeZlib once if this test is run repeatedly -# which happens when we look for ref leaks -test_imported = False - - def make_pyc(co, mtime): data = marshal.dumps(co) if type(mtime) is type(0.0): @@ -463,19 +458,7 @@ class BadFileZipImportTestCase(unittest.TestCase): zipimport._zip_directory_cache.clear() -def cleanup(): - # this is necessary if test is run repeated (like when finding leaks) - global test_imported - if test_imported: - zipimport._zip_directory_cache.clear() - if hasattr(UncompressedZipImportTestCase, 'testAFakeZlib'): - delattr(UncompressedZipImportTestCase, 'testAFakeZlib') - if hasattr(CompressedZipImportTestCase, 'testAFakeZlib'): - delattr(CompressedZipImportTestCase, 'testAFakeZlib') - test_imported = True - def test_main(): - cleanup() try: test_support.run_unittest( UncompressedZipImportTestCase, diff --git a/Misc/NEWS b/Misc/NEWS index 93af718400..296d2c1646 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -80,13 +80,16 @@ Core and Builtins Library ------- +- Issue #12124: zipimport doesn't keep a reference to zlib.decompress() anymore + to be able to unload the module. + - Issue #11088: don't crash when using F5 to run a script in IDLE on MacOSX with Tk 8.5. - Issue #10154, #10090: change the normalization of UTF-8 to "UTF-8" instead of "UTF8" in the locale module as the latter is not supported MacOSX and OpenBSD. -- Issue #9516: avoid errors in sysconfig when MACOSX_DEPLOYMENT_TARGET is +- Issue #9516: avoid errors in sysconfig when MACOSX_DEPLOYMENT_TARGET is set in shell. - Issue #12050: zlib.decompressobj().decompress() now clears the unconsumed_tail diff --git a/Modules/zipimport.c b/Modules/zipimport.c index 9224a6880c..b7a1b8da9f 100644 --- a/Modules/zipimport.c +++ b/Modules/zipimport.c @@ -798,35 +798,33 @@ error: /* Return the zlib.decompress function object, or NULL if zlib couldn't be imported. The function is cached when found, so subsequent calls - don't import zlib again. Returns a *borrowed* reference. - XXX This makes zlib.decompress immortal. */ + don't import zlib again. */ static PyObject * get_decompress_func(void) { - static PyObject *decompress = NULL; + static int importing_zlib = 0; + PyObject *zlib; + PyObject *decompress; - if (decompress == NULL) { - PyObject *zlib; - static int importing_zlib = 0; - - if (importing_zlib != 0) - /* Someone has a zlib.py[co] in their Zip file; - let's avoid a stack overflow. */ - return NULL; - importing_zlib = 1; - zlib = PyImport_ImportModuleNoBlock("zlib"); - importing_zlib = 0; - if (zlib != NULL) { - decompress = PyObject_GetAttrString(zlib, - "decompress"); - Py_DECREF(zlib); - } - else - PyErr_Clear(); - if (Py_VerboseFlag) - PySys_WriteStderr("# zipimport: zlib %s\n", - zlib != NULL ? "available": "UNAVAILABLE"); + if (importing_zlib != 0) + /* Someone has a zlib.py[co] in their Zip file; + let's avoid a stack overflow. */ + return NULL; + importing_zlib = 1; + zlib = PyImport_ImportModuleNoBlock("zlib"); + importing_zlib = 0; + if (zlib != NULL) { + decompress = PyObject_GetAttrString(zlib, + "decompress"); + Py_DECREF(zlib); + } + else { + PyErr_Clear(); + decompress = NULL; } + if (Py_VerboseFlag) + PySys_WriteStderr("# zipimport: zlib %s\n", + zlib != NULL ? "available": "UNAVAILABLE"); return decompress; } @@ -911,6 +909,7 @@ get_data(char *archive, PyObject *toc_entry) goto error; } data = PyObject_CallFunction(decompress, "Oi", raw_data, -15); + Py_DECREF(decompress); error: Py_DECREF(raw_data); return data; -- cgit v1.2.1 From 68169df54edbfa43de2f9f09fd76d34cde33774c Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Sat, 21 May 2011 09:39:57 -0700 Subject: Simplify example --- Doc/library/collections.rst | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Doc/library/collections.rst b/Doc/library/collections.rst index 88c4f0f9ee..53e5ff96f8 100644 --- a/Doc/library/collections.rst +++ b/Doc/library/collections.rst @@ -862,10 +862,6 @@ so that the counter remembers the order elements are first encountered:: class OrderedCounter(Counter, OrderedDict): 'Counter that remembers the order elements are first encountered' - def __init__(self, iterable=None, **kwds): - OrderedDict.__init__(self) - Counter.__init__(self, iterable, **kwds) - def __repr__(self): return '%s(%r)' % (self.__class__.__name__, OrderedDict(self)) -- cgit v1.2.1 From e34fddd499be36f24e609838958b6a2a9c49751b Mon Sep 17 00:00:00 2001 From: Eli Bendersky Date: Sun, 22 May 2011 06:49:01 +0300 Subject: Issue 12126: removing incorrect claim about return value of select --- Doc/howto/sockets.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Doc/howto/sockets.rst b/Doc/howto/sockets.rst index 443b15f50e..b0a3fa4df4 100644 --- a/Doc/howto/sockets.rst +++ b/Doc/howto/sockets.rst @@ -357,8 +357,7 @@ reason to do otherwise. In return, you will get three lists. They contain the sockets that are actually readable, writable and in error. Each of these lists is a subset (possibly -empty) of the corresponding list you passed in. If you put a socket in more -than one input list, it will only be (at most) in one output list. +empty) of the corresponding list you passed in. If a socket is in the output readable list, you can be as-close-to-certain-as-we-ever-get-in-this-business that a ``recv`` on that -- cgit v1.2.1 From 4d810a88d85abf16018a01c8c2b44192d1131cc6 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sun, 22 May 2011 13:22:28 +0200 Subject: Issue #12012: test_ssl uses test_support.import_module() Skip the whole file if the SSL module is missing. It was already the case, except that the SkipTest exception was raised in test_main(). This commit fixes an error in test_ssl if the ssl module is missing. --- Lib/test/test_ssl.py | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index be2f51acaf..3df4d0c34c 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -20,12 +20,7 @@ import platform from BaseHTTPServer import HTTPServer from SimpleHTTPServer import SimpleHTTPRequestHandler -# Optionally test SSL support, if we have it in the tested platform -skip_expected = False -try: - import ssl -except ImportError: - skip_expected = True +ssl = test_support.import_module("ssl") HOST = test_support.HOST CERTFILE = None @@ -1334,9 +1329,6 @@ else: def test_main(verbose=False): - if skip_expected: - raise unittest.SkipTest("No SSL support") - global CERTFILE, SVN_PYTHON_ORG_ROOT_CERT CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir, "keycert.pem") -- cgit v1.2.1 From d1f1b1663d1a36b5caee6fc62bdf84ef067f5171 Mon Sep 17 00:00:00 2001 From: Barry Warsaw Date: Sun, 22 May 2011 21:16:55 -0400 Subject: These files have Windows line endings in 2.6. --- .hgeol | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.hgeol b/.hgeol index e1c19926a8..8ab8e56cb2 100644 --- a/.hgeol +++ b/.hgeol @@ -30,6 +30,12 @@ Lib/email/test/data/msg_26.txt = BIN Lib/test/sndhdrdata/sndhdr.* = BIN Lib/test/decimaltestdata/*.decTest = BIN +Doc/make.bat = CRLF +Tools/buildbot/*.bat = CRLF +Tools/msi/merge.py = CRLF +PC/VS7.1/*.bat = CRLF +PC/VS8.0/*.bat = CRLF + # All other files (which presumably are human-editable) are "native". # This must be the last rule! -- cgit v1.2.1 From 8a9762f029dece5648224936c8e1b44b3b6928e2 Mon Sep 17 00:00:00 2001 From: Eli Bendersky Date: Mon, 23 May 2011 06:10:26 +0300 Subject: Issue 12003: fixing error in xrange alternative sample --- Doc/library/functions.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index 4b63c9f70e..962a53d45e 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -1464,7 +1464,7 @@ available. They are listed here in alphabetical order. also requires that the number of elements fit in a native C long. If a larger range is needed, an alternate version can be crafted using the :mod:`itertools` module: ``islice(count(start, step), - (stop-start+step-1)//step)``. + (stop-start+step-1+2*(step<0))//step)``. .. function:: zip([iterable, ...]) -- cgit v1.2.1 From b5e277ca522d94bdbf1426bfd8c43fee2f8153f3 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 23 May 2011 16:19:31 +0200 Subject: test_codecs now removes the temporay file (created by the test) --- Lib/test/test_codecs.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/Lib/test/test_codecs.py b/Lib/test/test_codecs.py index 7cd7141b06..f7f27cc7d9 100644 --- a/Lib/test/test_codecs.py +++ b/Lib/test/test_codecs.py @@ -469,13 +469,11 @@ class UTF16Test(ReadTest): s1 = u'Hello\r\nworld\r\n' s = s1.encode(self.encoding) - try: - with open(test_support.TESTFN, 'wb') as fp: - fp.write(s) - with codecs.open(test_support.TESTFN, 'U', encoding=self.encoding) as reader: - self.assertEqual(reader.read(), s1) - finally: - test_support.unlink(test_support.TESTFN) + self.addCleanup(test_support.unlink, test_support.TESTFN) + with open(test_support.TESTFN, 'wb') as fp: + fp.write(s) + with codecs.open(test_support.TESTFN, 'U', encoding=self.encoding) as reader: + self.assertEqual(reader.read(), s1) class UTF16LETest(ReadTest): encoding = "utf-16-le" @@ -1532,6 +1530,7 @@ class BomTest(unittest.TestCase): "utf-32", "utf-32-le", "utf-32-be") + self.addCleanup(test_support.unlink, test_support.TESTFN) for encoding in tests: # Check if the BOM is written only once with codecs.open(test_support.TESTFN, 'w+', encoding=encoding) as f: -- cgit v1.2.1 From 5725b114b822cc357bf9702c879d0825feb38473 Mon Sep 17 00:00:00 2001 From: Barry Warsaw Date: Mon, 23 May 2011 15:22:56 -0400 Subject: Replay changeset 70238:03e488b5c009 from fubar branch. Original commit message: Reconcile with the 2.6svn branch. The 2.6.7 release will be made from Subversion, but there were differences, so this brings them in sync. These changes should *not* propagate to any newer versions. --- Doc/README.txt | 2 +- Doc/copyright.rst | 2 +- Doc/library/configparser.rst | 12 +++++------- Doc/library/logging.rst | 4 ---- Doc/license.rst | 4 ++++ Include/patchlevel.h | 8 ++++---- LICENSE | 2 ++ Lib/distutils/__init__.py | 2 +- Lib/idlelib/idlever.py | 2 +- Lib/pydoc_topics.py | 2 +- Misc/NEWS | 23 ++++++++++++++++------- Misc/RPM/python-2.6.spec | 2 +- PC/python_nt.rc | 2 +- Python/Python-ast.c | 4 ++-- Python/getcopyright.c | 2 +- README | 7 ++++--- 16 files changed, 45 insertions(+), 35 deletions(-) diff --git a/Doc/README.txt b/Doc/README.txt index d32d1edbba..ef1c1f7293 100644 --- a/Doc/README.txt +++ b/Doc/README.txt @@ -127,7 +127,7 @@ The Python source is copyrighted, but you can freely use and copy it as long as you don't change or remove the copyright notice: ---------------------------------------------------------------------- -Copyright (c) 2000-2008 Python Software Foundation. +Copyright (c) 2000-2011 Python Software Foundation. All rights reserved. Copyright (c) 2000 BeOpen.com. diff --git a/Doc/copyright.rst b/Doc/copyright.rst index 893b541b22..ff6b677252 100644 --- a/Doc/copyright.rst +++ b/Doc/copyright.rst @@ -4,7 +4,7 @@ Copyright Python and this documentation is: -Copyright © 2001-2010 Python Software Foundation. All rights reserved. +Copyright © 2001-2011 Python Software Foundation. All rights reserved. Copyright © 2000 BeOpen.com. All rights reserved. diff --git a/Doc/library/configparser.rst b/Doc/library/configparser.rst index 7f68de762f..867f0912fd 100644 --- a/Doc/library/configparser.rst +++ b/Doc/library/configparser.rst @@ -79,12 +79,9 @@ write-back, as will be the keys within each section. The basic configuration object. When *defaults* is given, it is initialized into the dictionary of intrinsic defaults. When *dict_type* is given, it will be used to create the dictionary objects for the list of sections, for the - options within a section, and for the default values. This class does not + options within a section, and for the default values. This class does not support the magical interpolation behavior. - All option names are passed through the :meth:`optionxform` method. Its - default implementation converts option names to lower case. - .. versionadded:: 2.3 .. versionchanged:: 2.6 @@ -101,9 +98,10 @@ write-back, as will be the keys within each section. *defaults*. All option names used in interpolation will be passed through the - :meth:`optionxform` method just like any other option name reference. Using - the default implementation of :meth:`optionxform`, the values ``foo %(bar)s`` - and ``foo %(BAR)s`` are equivalent. + :meth:`optionxform` method just like any other option name reference. For + example, using the default implementation of :meth:`optionxform` (which converts + option names to lower case), the values ``foo %(bar)s`` and ``foo %(BAR)s`` are + equivalent. .. class:: SafeConfigParser([defaults[, dict_type]]) diff --git a/Doc/library/logging.rst b/Doc/library/logging.rst index 6674dfa6fe..c95b8de781 100644 --- a/Doc/library/logging.rst +++ b/Doc/library/logging.rst @@ -2545,8 +2545,6 @@ logging module using these functions or by making calls to the main API (defined in :mod:`logging` itself) and defining handlers which are declared either in :mod:`logging` or :mod:`logging.handlers`. -.. currentmodule:: logging.config - .. function:: fileConfig(fname[, defaults]) @@ -2580,8 +2578,6 @@ in :mod:`logging` itself) and defining handlers which are declared either in :func:`listen`. -.. currentmodule:: logging - .. _logging-config-fileformat: Configuration file format diff --git a/Doc/license.rst b/Doc/license.rst index 6ab673c0cf..a9cec20f09 100644 --- a/Doc/license.rst +++ b/Doc/license.rst @@ -104,6 +104,10 @@ been GPL-compatible; the table below summarizes the various releases. +----------------+--------------+-----------+------------+-----------------+ | 2.6.5 | 2.6.4 | 2010 | PSF | yes | +----------------+--------------+-----------+------------+-----------------+ +| 2.6.6 | 2.6.5 | 2010 | PSF | yes | ++----------------+--------------+-----------+------------+-----------------+ +| 2.6.7 | 2.6.6 | 2011 | PSF | yes | ++----------------+--------------+-----------+------------+-----------------+ .. note:: diff --git a/Include/patchlevel.h b/Include/patchlevel.h index 3952d075cf..abe0763a3a 100644 --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -22,12 +22,12 @@ /*--start constants--*/ #define PY_MAJOR_VERSION 2 #define PY_MINOR_VERSION 6 -#define PY_MICRO_VERSION 6 -#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_FINAL -#define PY_RELEASE_SERIAL 0 +#define PY_MICRO_VERSION 7 +#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_GAMMA +#define PY_RELEASE_SERIAL 1 /* Version as a string */ -#define PY_VERSION "2.6.6+" +#define PY_VERSION "2.6.7rc1" /*--end constants--*/ /* Subversion Revision number of this file (not of the repository) */ diff --git a/LICENSE b/LICENSE index 1050ea9d66..a19aada157 100644 --- a/LICENSE +++ b/LICENSE @@ -63,6 +63,8 @@ the various releases. 2.6.3 2.6.2 2009 PSF yes 2.6.4 2.6.3 2009 PSF yes 2.6.5 2.6.4 2010 PSF yes + 2.6.6 2.6.5 2010 PSF yes + 2.6.7 2.6.6 2011 PSF yes Footnotes: diff --git a/Lib/distutils/__init__.py b/Lib/distutils/__init__.py index 90f96feae1..6f4c021c62 100644 --- a/Lib/distutils/__init__.py +++ b/Lib/distutils/__init__.py @@ -22,5 +22,5 @@ __revision__ = "$Id$" # #--start constants-- -__version__ = "2.6.6" +__version__ = "2.6.7rc1" #--end constants-- diff --git a/Lib/idlelib/idlever.py b/Lib/idlelib/idlever.py index 2888aaf5ca..23959679e6 100644 --- a/Lib/idlelib/idlever.py +++ b/Lib/idlelib/idlever.py @@ -1 +1 @@ -IDLE_VERSION = "2.6.6" +IDLE_VERSION = "2.6.7rc1" diff --git a/Lib/pydoc_topics.py b/Lib/pydoc_topics.py index 572879f514..c169960b92 100644 --- a/Lib/pydoc_topics.py +++ b/Lib/pydoc_topics.py @@ -1,4 +1,4 @@ -# Autogenerated by Sphinx on Mon Aug 23 19:33:46 2010 +# Autogenerated by Sphinx on Fri May 6 18:02:17 2011 topics = {'assert': u'\nThe ``assert`` statement\n************************\n\nAssert statements are a convenient way to insert debugging assertions\ninto a program:\n\n assert_stmt ::= "assert" expression ["," expression]\n\nThe simple form, ``assert expression``, is equivalent to\n\n if __debug__:\n if not expression: raise AssertionError\n\nThe extended form, ``assert expression1, expression2``, is equivalent\nto\n\n if __debug__:\n if not expression1: raise AssertionError(expression2)\n\nThese equivalences assume that ``__debug__`` and ``AssertionError``\nrefer to the built-in variables with those names. In the current\nimplementation, the built-in variable ``__debug__`` is ``True`` under\nnormal circumstances, ``False`` when optimization is requested\n(command line option -O). The current code generator emits no code\nfor an assert statement when optimization is requested at compile\ntime. Note that it is unnecessary to include the source code for the\nexpression that failed in the error message; it will be displayed as\npart of the stack trace.\n\nAssignments to ``__debug__`` are illegal. The value for the built-in\nvariable is determined when the interpreter starts.\n', 'assignment': u'\nAssignment statements\n*********************\n\nAssignment statements are used to (re)bind names to values and to\nmodify attributes or items of mutable objects:\n\n assignment_stmt ::= (target_list "=")+ (expression_list | yield_expression)\n target_list ::= target ("," target)* [","]\n target ::= identifier\n | "(" target_list ")"\n | "[" target_list "]"\n | attributeref\n | subscription\n | slicing\n\n(See section *Primaries* for the syntax definitions for the last three\nsymbols.)\n\nAn assignment statement evaluates the expression list (remember that\nthis can be a single expression or a comma-separated list, the latter\nyielding a tuple) and assigns the single resulting object to each of\nthe target lists, from left to right.\n\nAssignment is defined recursively depending on the form of the target\n(list). When a target is part of a mutable object (an attribute\nreference, subscription or slicing), the mutable object must\nultimately perform the assignment and decide about its validity, and\nmay raise an exception if the assignment is unacceptable. The rules\nobserved by various types and the exceptions raised are given with the\ndefinition of the object types (see section *The standard type\nhierarchy*).\n\nAssignment of an object to a target list is recursively defined as\nfollows.\n\n* If the target list is a single target: The object is assigned to\n that target.\n\n* If the target list is a comma-separated list of targets: The object\n must be an iterable with the same number of items as there are\n targets in the target list, and the items are assigned, from left to\n right, to the corresponding targets. (This rule is relaxed as of\n Python 1.5; in earlier versions, the object had to be a tuple.\n Since strings are sequences, an assignment like ``a, b = "xy"`` is\n now legal as long as the string has the right length.)\n\nAssignment of an object to a single target is recursively defined as\nfollows.\n\n* If the target is an identifier (name):\n\n * If the name does not occur in a ``global`` statement in the\n current code block: the name is bound to the object in the current\n local namespace.\n\n * Otherwise: the name is bound to the object in the current global\n namespace.\n\n The name is rebound if it was already bound. This may cause the\n reference count for the object previously bound to the name to reach\n zero, causing the object to be deallocated and its destructor (if it\n has one) to be called.\n\n* If the target is a target list enclosed in parentheses or in square\n brackets: The object must be an iterable with the same number of\n items as there are targets in the target list, and its items are\n assigned, from left to right, to the corresponding targets.\n\n* If the target is an attribute reference: The primary expression in\n the reference is evaluated. It should yield an object with\n assignable attributes; if this is not the case, ``TypeError`` is\n raised. That object is then asked to assign the assigned object to\n the given attribute; if it cannot perform the assignment, it raises\n an exception (usually but not necessarily ``AttributeError``).\n\n Note: If the object is a class instance and the attribute reference\n occurs on both sides of the assignment operator, the RHS expression,\n ``a.x`` can access either an instance attribute or (if no instance\n attribute exists) a class attribute. The LHS target ``a.x`` is\n always set as an instance attribute, creating it if necessary.\n Thus, the two occurrences of ``a.x`` do not necessarily refer to the\n same attribute: if the RHS expression refers to a class attribute,\n the LHS creates a new instance attribute as the target of the\n assignment:\n\n class Cls:\n x = 3 # class variable\n inst = Cls()\n inst.x = inst.x + 1 # writes inst.x as 4 leaving Cls.x as 3\n\n This description does not necessarily apply to descriptor\n attributes, such as properties created with ``property()``.\n\n* If the target is a subscription: The primary expression in the\n reference is evaluated. It should yield either a mutable sequence\n object (such as a list) or a mapping object (such as a dictionary).\n Next, the subscript expression is evaluated.\n\n If the primary is a mutable sequence object (such as a list), the\n subscript must yield a plain integer. If it is negative, the\n sequence\'s length is added to it. The resulting value must be a\n nonnegative integer less than the sequence\'s length, and the\n sequence is asked to assign the assigned object to its item with\n that index. If the index is out of range, ``IndexError`` is raised\n (assignment to a subscripted sequence cannot add new items to a\n list).\n\n If the primary is a mapping object (such as a dictionary), the\n subscript must have a type compatible with the mapping\'s key type,\n and the mapping is then asked to create a key/datum pair which maps\n the subscript to the assigned object. This can either replace an\n existing key/value pair with the same key value, or insert a new\n key/value pair (if no key with the same value existed).\n\n* If the target is a slicing: The primary expression in the reference\n is evaluated. It should yield a mutable sequence object (such as a\n list). The assigned object should be a sequence object of the same\n type. Next, the lower and upper bound expressions are evaluated,\n insofar they are present; defaults are zero and the sequence\'s\n length. The bounds should evaluate to (small) integers. If either\n bound is negative, the sequence\'s length is added to it. The\n resulting bounds are clipped to lie between zero and the sequence\'s\n length, inclusive. Finally, the sequence object is asked to replace\n the slice with the items of the assigned sequence. The length of\n the slice may be different from the length of the assigned sequence,\n thus changing the length of the target sequence, if the object\n allows it.\n\n**CPython implementation detail:** In the current implementation, the\nsyntax for targets is taken to be the same as for expressions, and\ninvalid syntax is rejected during the code generation phase, causing\nless detailed error messages.\n\nWARNING: Although the definition of assignment implies that overlaps\nbetween the left-hand side and the right-hand side are \'safe\' (for\nexample ``a, b = b, a`` swaps two variables), overlaps *within* the\ncollection of assigned-to variables are not safe! For instance, the\nfollowing program prints ``[0, 2]``:\n\n x = [0, 1]\n i = 0\n i, x[i] = 1, 2\n print x\n\n\nAugmented assignment statements\n===============================\n\nAugmented assignment is the combination, in a single statement, of a\nbinary operation and an assignment statement:\n\n augmented_assignment_stmt ::= augtarget augop (expression_list | yield_expression)\n augtarget ::= identifier | attributeref | subscription | slicing\n augop ::= "+=" | "-=" | "*=" | "/=" | "//=" | "%=" | "**="\n | ">>=" | "<<=" | "&=" | "^=" | "|="\n\n(See section *Primaries* for the syntax definitions for the last three\nsymbols.)\n\nAn augmented assignment evaluates the target (which, unlike normal\nassignment statements, cannot be an unpacking) and the expression\nlist, performs the binary operation specific to the type of assignment\non the two operands, and assigns the result to the original target.\nThe target is only evaluated once.\n\nAn augmented assignment expression like ``x += 1`` can be rewritten as\n``x = x + 1`` to achieve a similar, but not exactly equal effect. In\nthe augmented version, ``x`` is only evaluated once. Also, when\npossible, the actual operation is performed *in-place*, meaning that\nrather than creating a new object and assigning that to the target,\nthe old object is modified instead.\n\nWith the exception of assigning to tuples and multiple targets in a\nsingle statement, the assignment done by augmented assignment\nstatements is handled the same way as normal assignments. Similarly,\nwith the exception of the possible *in-place* behavior, the binary\noperation performed by augmented assignment is the same as the normal\nbinary operations.\n\nFor targets which are attribute references, the same *caveat about\nclass and instance attributes* applies as for regular assignments.\n', 'atom-identifiers': u'\nIdentifiers (Names)\n*******************\n\nAn identifier occurring as an atom is a name. See section\n*Identifiers and keywords* for lexical definition and section *Naming\nand binding* for documentation of naming and binding.\n\nWhen the name is bound to an object, evaluation of the atom yields\nthat object. When a name is not bound, an attempt to evaluate it\nraises a ``NameError`` exception.\n\n**Private name mangling:** When an identifier that textually occurs in\na class definition begins with two or more underscore characters and\ndoes not end in two or more underscores, it is considered a *private\nname* of that class. Private names are transformed to a longer form\nbefore code is generated for them. The transformation inserts the\nclass name in front of the name, with leading underscores removed, and\na single underscore inserted in front of the class name. For example,\nthe identifier ``__spam`` occurring in a class named ``Ham`` will be\ntransformed to ``_Ham__spam``. This transformation is independent of\nthe syntactical context in which the identifier is used. If the\ntransformed name is extremely long (longer than 255 characters),\nimplementation defined truncation may happen. If the class name\nconsists only of underscores, no transformation is done.\n', diff --git a/Misc/NEWS b/Misc/NEWS index b5be9f2186..980de3c750 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -4,10 +4,10 @@ Python News (editors: check NEWS.help for information about editing NEWS using ReST.) -What's New in Python 2.6.7? -=========================== +What's New in Python 2.6.7 rc 1? +================================ -*Release date: XXXX-XX-XX* +*Release date: 2011-05-06* *NOTE: Python 2.6 is in security-fix-only mode. No non-security bug fixes are allowed. Python 2.6.7 and beyond will be source only releases.* @@ -19,11 +19,20 @@ Core and Builtins Library ------- -- Issue #11442: Add a charset parameter to the Content-type in SimpleHTTPServer - to avoid XSS attacks. +- Issue #9129: smtpd.py is vulnerable to DoS attacks deriving from missing + error handling when accepting a new connection. + + +What's New in Python 2.6.6? +=========================== + +*Release date: 2010-08-24* -- Issue #11662: Make urllib and urllib2 ignore redirections if the - scheme is not HTTP, HTTPS or FTP (CVE-2011-1521). +Core and Builtins +----------------- + +Library +------- What's New in Python 2.6.6 rc 2? diff --git a/Misc/RPM/python-2.6.spec b/Misc/RPM/python-2.6.spec index be88719db6..d5873b4b6a 100644 --- a/Misc/RPM/python-2.6.spec +++ b/Misc/RPM/python-2.6.spec @@ -39,7 +39,7 @@ %define name python #--start constants-- -%define version 2.6.6 +%define version 2.6.7rc1 %define libver 2.6 #--end constants-- %define release 1pydotorg diff --git a/PC/python_nt.rc b/PC/python_nt.rc index f5fff8720a..8cccf2dc2a 100644 --- a/PC/python_nt.rc +++ b/PC/python_nt.rc @@ -61,7 +61,7 @@ BEGIN VALUE "FileDescription", "Python Core\0" VALUE "FileVersion", PYTHON_VERSION VALUE "InternalName", "Python DLL\0" - VALUE "LegalCopyright", "Copyright 2001-2010 Python Software Foundation. Copyright 2000 BeOpen.com. Copyright 1995-2001 CNRI. Copyright 1991-1995 SMC.\0" + VALUE "LegalCopyright", "Copyright 2001-2011 Python Software Foundation. Copyright 2000 BeOpen.com. Copyright 1995-2001 CNRI. Copyright 1991-1995 SMC.\0" VALUE "OriginalFilename", PYTHON_DLL_NAME "\0" VALUE "ProductName", "Python\0" VALUE "ProductVersion", PYTHON_VERSION diff --git a/Python/Python-ast.c b/Python/Python-ast.c index bc6cca0635..45fe444e26 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -2,7 +2,7 @@ /* - __version__ 62047. + __version__ . This module must be committed separately after each AST grammar change; The __version__ number is set to the revision number of the commit @@ -6300,7 +6300,7 @@ init_ast(void) if (PyDict_SetItemString(d, "AST", (PyObject*)&AST_type) < 0) return; if (PyModule_AddIntConstant(m, "PyCF_ONLY_AST", PyCF_ONLY_AST) < 0) return; - if (PyModule_AddStringConstant(m, "__version__", "62047") < 0) + if (PyModule_AddStringConstant(m, "__version__", "") < 0) return; if (PyDict_SetItemString(d, "mod", (PyObject*)mod_type) < 0) return; if (PyDict_SetItemString(d, "Module", (PyObject*)Module_type) < 0) diff --git a/Python/getcopyright.c b/Python/getcopyright.c index a5e7fa6396..824c7b1c82 100644 --- a/Python/getcopyright.c +++ b/Python/getcopyright.c @@ -4,7 +4,7 @@ static char cprt[] = "\ -Copyright (c) 2001-2010 Python Software Foundation.\n\ +Copyright (c) 2001-2011 Python Software Foundation.\n\ All Rights Reserved.\n\ \n\ Copyright (c) 2000 BeOpen.com.\n\ diff --git a/README b/README index 63af54dc87..88cd00df06 100644 --- a/README +++ b/README @@ -1,8 +1,9 @@ -This is Python version 2.6.6 -============================ +This is Python version 2.6.7rc1 +=============================== Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 -Python Software Foundation. All rights reserved. +Python Software Foundation. +All rights reserved. Copyright (c) 2000 BeOpen.com. All rights reserved. -- cgit v1.2.1 From bdd75a6280cbad208effe3e8a51ff3b81e15768b Mon Sep 17 00:00:00 2001 From: Barry Warsaw Date: Mon, 23 May 2011 15:26:11 -0400 Subject: Replay changeset 70248:c714e2f92f63 from fubar branch. Original commit message: Cross-port changes for 2.6.7rc2 from the Subversion branch. --- Include/patchlevel.h | 4 ++-- Lib/distutils/__init__.py | 2 +- Lib/idlelib/idlever.py | 2 +- Lib/pydoc_topics.py | 2 +- Misc/NEWS | 19 +++++++++++++++++++ Misc/RPM/python-2.6.spec | 2 +- README | 2 +- 7 files changed, 26 insertions(+), 7 deletions(-) diff --git a/Include/patchlevel.h b/Include/patchlevel.h index abe0763a3a..a1e4f51b7b 100644 --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -24,10 +24,10 @@ #define PY_MINOR_VERSION 6 #define PY_MICRO_VERSION 7 #define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_GAMMA -#define PY_RELEASE_SERIAL 1 +#define PY_RELEASE_SERIAL 2 /* Version as a string */ -#define PY_VERSION "2.6.7rc1" +#define PY_VERSION "2.6.7rc2" /*--end constants--*/ /* Subversion Revision number of this file (not of the repository) */ diff --git a/Lib/distutils/__init__.py b/Lib/distutils/__init__.py index 6f4c021c62..b2a208201c 100644 --- a/Lib/distutils/__init__.py +++ b/Lib/distutils/__init__.py @@ -22,5 +22,5 @@ __revision__ = "$Id$" # #--start constants-- -__version__ = "2.6.7rc1" +__version__ = "2.6.7rc2" #--end constants-- diff --git a/Lib/idlelib/idlever.py b/Lib/idlelib/idlever.py index 23959679e6..d3df9d989f 100644 --- a/Lib/idlelib/idlever.py +++ b/Lib/idlelib/idlever.py @@ -1 +1 @@ -IDLE_VERSION = "2.6.7rc1" +IDLE_VERSION = "2.6.7rc2" diff --git a/Lib/pydoc_topics.py b/Lib/pydoc_topics.py index c169960b92..af11f5fb28 100644 --- a/Lib/pydoc_topics.py +++ b/Lib/pydoc_topics.py @@ -1,4 +1,4 @@ -# Autogenerated by Sphinx on Fri May 6 18:02:17 2011 +# Autogenerated by Sphinx on Fri May 20 19:52:20 2011 topics = {'assert': u'\nThe ``assert`` statement\n************************\n\nAssert statements are a convenient way to insert debugging assertions\ninto a program:\n\n assert_stmt ::= "assert" expression ["," expression]\n\nThe simple form, ``assert expression``, is equivalent to\n\n if __debug__:\n if not expression: raise AssertionError\n\nThe extended form, ``assert expression1, expression2``, is equivalent\nto\n\n if __debug__:\n if not expression1: raise AssertionError(expression2)\n\nThese equivalences assume that ``__debug__`` and ``AssertionError``\nrefer to the built-in variables with those names. In the current\nimplementation, the built-in variable ``__debug__`` is ``True`` under\nnormal circumstances, ``False`` when optimization is requested\n(command line option -O). The current code generator emits no code\nfor an assert statement when optimization is requested at compile\ntime. Note that it is unnecessary to include the source code for the\nexpression that failed in the error message; it will be displayed as\npart of the stack trace.\n\nAssignments to ``__debug__`` are illegal. The value for the built-in\nvariable is determined when the interpreter starts.\n', 'assignment': u'\nAssignment statements\n*********************\n\nAssignment statements are used to (re)bind names to values and to\nmodify attributes or items of mutable objects:\n\n assignment_stmt ::= (target_list "=")+ (expression_list | yield_expression)\n target_list ::= target ("," target)* [","]\n target ::= identifier\n | "(" target_list ")"\n | "[" target_list "]"\n | attributeref\n | subscription\n | slicing\n\n(See section *Primaries* for the syntax definitions for the last three\nsymbols.)\n\nAn assignment statement evaluates the expression list (remember that\nthis can be a single expression or a comma-separated list, the latter\nyielding a tuple) and assigns the single resulting object to each of\nthe target lists, from left to right.\n\nAssignment is defined recursively depending on the form of the target\n(list). When a target is part of a mutable object (an attribute\nreference, subscription or slicing), the mutable object must\nultimately perform the assignment and decide about its validity, and\nmay raise an exception if the assignment is unacceptable. The rules\nobserved by various types and the exceptions raised are given with the\ndefinition of the object types (see section *The standard type\nhierarchy*).\n\nAssignment of an object to a target list is recursively defined as\nfollows.\n\n* If the target list is a single target: The object is assigned to\n that target.\n\n* If the target list is a comma-separated list of targets: The object\n must be an iterable with the same number of items as there are\n targets in the target list, and the items are assigned, from left to\n right, to the corresponding targets. (This rule is relaxed as of\n Python 1.5; in earlier versions, the object had to be a tuple.\n Since strings are sequences, an assignment like ``a, b = "xy"`` is\n now legal as long as the string has the right length.)\n\nAssignment of an object to a single target is recursively defined as\nfollows.\n\n* If the target is an identifier (name):\n\n * If the name does not occur in a ``global`` statement in the\n current code block: the name is bound to the object in the current\n local namespace.\n\n * Otherwise: the name is bound to the object in the current global\n namespace.\n\n The name is rebound if it was already bound. This may cause the\n reference count for the object previously bound to the name to reach\n zero, causing the object to be deallocated and its destructor (if it\n has one) to be called.\n\n* If the target is a target list enclosed in parentheses or in square\n brackets: The object must be an iterable with the same number of\n items as there are targets in the target list, and its items are\n assigned, from left to right, to the corresponding targets.\n\n* If the target is an attribute reference: The primary expression in\n the reference is evaluated. It should yield an object with\n assignable attributes; if this is not the case, ``TypeError`` is\n raised. That object is then asked to assign the assigned object to\n the given attribute; if it cannot perform the assignment, it raises\n an exception (usually but not necessarily ``AttributeError``).\n\n Note: If the object is a class instance and the attribute reference\n occurs on both sides of the assignment operator, the RHS expression,\n ``a.x`` can access either an instance attribute or (if no instance\n attribute exists) a class attribute. The LHS target ``a.x`` is\n always set as an instance attribute, creating it if necessary.\n Thus, the two occurrences of ``a.x`` do not necessarily refer to the\n same attribute: if the RHS expression refers to a class attribute,\n the LHS creates a new instance attribute as the target of the\n assignment:\n\n class Cls:\n x = 3 # class variable\n inst = Cls()\n inst.x = inst.x + 1 # writes inst.x as 4 leaving Cls.x as 3\n\n This description does not necessarily apply to descriptor\n attributes, such as properties created with ``property()``.\n\n* If the target is a subscription: The primary expression in the\n reference is evaluated. It should yield either a mutable sequence\n object (such as a list) or a mapping object (such as a dictionary).\n Next, the subscript expression is evaluated.\n\n If the primary is a mutable sequence object (such as a list), the\n subscript must yield a plain integer. If it is negative, the\n sequence\'s length is added to it. The resulting value must be a\n nonnegative integer less than the sequence\'s length, and the\n sequence is asked to assign the assigned object to its item with\n that index. If the index is out of range, ``IndexError`` is raised\n (assignment to a subscripted sequence cannot add new items to a\n list).\n\n If the primary is a mapping object (such as a dictionary), the\n subscript must have a type compatible with the mapping\'s key type,\n and the mapping is then asked to create a key/datum pair which maps\n the subscript to the assigned object. This can either replace an\n existing key/value pair with the same key value, or insert a new\n key/value pair (if no key with the same value existed).\n\n* If the target is a slicing: The primary expression in the reference\n is evaluated. It should yield a mutable sequence object (such as a\n list). The assigned object should be a sequence object of the same\n type. Next, the lower and upper bound expressions are evaluated,\n insofar they are present; defaults are zero and the sequence\'s\n length. The bounds should evaluate to (small) integers. If either\n bound is negative, the sequence\'s length is added to it. The\n resulting bounds are clipped to lie between zero and the sequence\'s\n length, inclusive. Finally, the sequence object is asked to replace\n the slice with the items of the assigned sequence. The length of\n the slice may be different from the length of the assigned sequence,\n thus changing the length of the target sequence, if the object\n allows it.\n\n**CPython implementation detail:** In the current implementation, the\nsyntax for targets is taken to be the same as for expressions, and\ninvalid syntax is rejected during the code generation phase, causing\nless detailed error messages.\n\nWARNING: Although the definition of assignment implies that overlaps\nbetween the left-hand side and the right-hand side are \'safe\' (for\nexample ``a, b = b, a`` swaps two variables), overlaps *within* the\ncollection of assigned-to variables are not safe! For instance, the\nfollowing program prints ``[0, 2]``:\n\n x = [0, 1]\n i = 0\n i, x[i] = 1, 2\n print x\n\n\nAugmented assignment statements\n===============================\n\nAugmented assignment is the combination, in a single statement, of a\nbinary operation and an assignment statement:\n\n augmented_assignment_stmt ::= augtarget augop (expression_list | yield_expression)\n augtarget ::= identifier | attributeref | subscription | slicing\n augop ::= "+=" | "-=" | "*=" | "/=" | "//=" | "%=" | "**="\n | ">>=" | "<<=" | "&=" | "^=" | "|="\n\n(See section *Primaries* for the syntax definitions for the last three\nsymbols.)\n\nAn augmented assignment evaluates the target (which, unlike normal\nassignment statements, cannot be an unpacking) and the expression\nlist, performs the binary operation specific to the type of assignment\non the two operands, and assigns the result to the original target.\nThe target is only evaluated once.\n\nAn augmented assignment expression like ``x += 1`` can be rewritten as\n``x = x + 1`` to achieve a similar, but not exactly equal effect. In\nthe augmented version, ``x`` is only evaluated once. Also, when\npossible, the actual operation is performed *in-place*, meaning that\nrather than creating a new object and assigning that to the target,\nthe old object is modified instead.\n\nWith the exception of assigning to tuples and multiple targets in a\nsingle statement, the assignment done by augmented assignment\nstatements is handled the same way as normal assignments. Similarly,\nwith the exception of the possible *in-place* behavior, the binary\noperation performed by augmented assignment is the same as the normal\nbinary operations.\n\nFor targets which are attribute references, the same *caveat about\nclass and instance attributes* applies as for regular assignments.\n', 'atom-identifiers': u'\nIdentifiers (Names)\n*******************\n\nAn identifier occurring as an atom is a name. See section\n*Identifiers and keywords* for lexical definition and section *Naming\nand binding* for documentation of naming and binding.\n\nWhen the name is bound to an object, evaluation of the atom yields\nthat object. When a name is not bound, an attempt to evaluate it\nraises a ``NameError`` exception.\n\n**Private name mangling:** When an identifier that textually occurs in\na class definition begins with two or more underscore characters and\ndoes not end in two or more underscores, it is considered a *private\nname* of that class. Private names are transformed to a longer form\nbefore code is generated for them. The transformation inserts the\nclass name in front of the name, with leading underscores removed, and\na single underscore inserted in front of the class name. For example,\nthe identifier ``__spam`` occurring in a class named ``Ham`` will be\ntransformed to ``_Ham__spam``. This transformation is independent of\nthe syntactical context in which the identifier is used. If the\ntransformed name is extremely long (longer than 255 characters),\nimplementation defined truncation may happen. If the class name\nconsists only of underscores, no transformation is done.\n', diff --git a/Misc/NEWS b/Misc/NEWS index 980de3c750..d1bbdba9a7 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -4,6 +4,25 @@ Python News (editors: check NEWS.help for information about editing NEWS using ReST.) +What's New in Python 2.6.7 rc 2? +================================ + +*Release date: 2011-05-20* + +*NOTE: Python 2.6 is in security-fix-only mode. No non-security bug fixes are + allowed. Python 2.6.7 and beyond will be source only releases.* + + +Library +------- + +- Issue #11662: Make urllib and urllib2 ignore redirections if the + scheme is not HTTP, HTTPS or FTP (CVE-2011-1521). + +- Issue #11442: Add a charset parameter to the Content-type in SimpleHTTPServer + to avoid XSS attacks. + + What's New in Python 2.6.7 rc 1? ================================ diff --git a/Misc/RPM/python-2.6.spec b/Misc/RPM/python-2.6.spec index d5873b4b6a..06f1311111 100644 --- a/Misc/RPM/python-2.6.spec +++ b/Misc/RPM/python-2.6.spec @@ -39,7 +39,7 @@ %define name python #--start constants-- -%define version 2.6.7rc1 +%define version 2.6.7rc2 %define libver 2.6 #--end constants-- %define release 1pydotorg diff --git a/README b/README index 88cd00df06..56754a9a70 100644 --- a/README +++ b/README @@ -1,4 +1,4 @@ -This is Python version 2.6.7rc1 +This is Python version 2.6.7rc2 =============================== Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 -- cgit v1.2.1 From 51228dcd1c23959cdd68712c8b2507bed4effccf Mon Sep 17 00:00:00 2001 From: Barry Warsaw Date: Mon, 23 May 2011 15:27:52 -0400 Subject: Replay changeset 70249:b571c7a8cf2e from fubar branch. Original commit message: Merging post 2.6.7rc2 changes from Subversion. --- Include/patchlevel.h | 2 +- Misc/NEWS | 12 +++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/Include/patchlevel.h b/Include/patchlevel.h index a1e4f51b7b..b0f049e8b7 100644 --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -27,7 +27,7 @@ #define PY_RELEASE_SERIAL 2 /* Version as a string */ -#define PY_VERSION "2.6.7rc2" +#define PY_VERSION "2.6.7rc2+" /*--end constants--*/ /* Subversion Revision number of this file (not of the repository) */ diff --git a/Misc/NEWS b/Misc/NEWS index d1bbdba9a7..99935e90fd 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -2,7 +2,17 @@ Python News +++++++++++ -(editors: check NEWS.help for information about editing NEWS using ReST.) +What's New in Python 2.6.7? +=========================== + +*Release date: XXXX-XX-XX* + +Core and Builtins +----------------- + +Library +------- + What's New in Python 2.6.7 rc 2? ================================ -- cgit v1.2.1 From 9687c64f9d19f5ae610cee770736330a3e1576be Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Mon, 23 May 2011 16:11:05 -0500 Subject: correctly lookup __dir__ --- Lib/test/test_descr.py | 1 + Misc/NEWS | 3 +++ Objects/object.c | 8 +++++--- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index 1fe0de582a..dc18f336df 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -1718,6 +1718,7 @@ order (MRO) for bases """ ("__exit__", run_context, swallow, set(), {"__enter__" : iden}), ("__complex__", complex, complex_num, set(), {}), ("__format__", format, format_impl, set(), {}), + ("__dir__", dir, empty_seq, set(), {}), ] class Checker(object): diff --git a/Misc/NEWS b/Misc/NEWS index 296d2c1646..8b7d726c39 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -9,6 +9,9 @@ What's New in Python 2.7.2? Core and Builtins ----------------- +- Correct lookup of __dir__ on objects. Among other things, this causes errors + besides AttributeError found on lookup to be propagated. + - Issue #1195: Fix input() if it is interrupted by CTRL+d and then CTRL+c, clear the end-of-file indicator after CTRL+d. diff --git a/Objects/object.c b/Objects/object.c index b6ad5de477..1e033d25e8 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -1905,11 +1905,13 @@ static PyObject * _dir_object(PyObject *obj) { PyObject *result = NULL; - PyObject *dirfunc = PyObject_GetAttrString((PyObject *)obj->ob_type, - "__dir__"); + static PyObject *dir_str = NULL; + PyObject *dirfunc = _PyObject_LookupSpecial(obj, "__dir__", &dir_str); assert(obj); if (dirfunc == NULL) { + if (PyErr_Occurred()) + return NULL; /* use default implementation */ PyErr_Clear(); if (PyModule_Check(obj)) @@ -1921,7 +1923,7 @@ _dir_object(PyObject *obj) } else { /* use __dir__ */ - result = PyObject_CallFunctionObjArgs(dirfunc, obj, NULL); + result = PyObject_CallFunctionObjArgs(dirfunc, NULL); Py_DECREF(dirfunc); if (result == NULL) return NULL; -- cgit v1.2.1 From 7384c85a664f22d4703aea4ceca6e1dc2a74cafa Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Mon, 23 May 2011 17:11:21 -0500 Subject: handle old-style instances --- Objects/object.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/Objects/object.c b/Objects/object.c index 1e033d25e8..5cf15b6a40 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -1906,14 +1906,21 @@ _dir_object(PyObject *obj) { PyObject *result = NULL; static PyObject *dir_str = NULL; - PyObject *dirfunc = _PyObject_LookupSpecial(obj, "__dir__", &dir_str); + PyObject *dirfunc; assert(obj); - if (dirfunc == NULL) { + if (PyInstance_Check(obj)) { + dirfunc = PyObject_GetAttrString(obj, "__dir__"); + if (dirfunc == NULL && !PyErr_ExceptionMatches(PyExc_AttributeError)) + return NULL; + } + else { + dirfunc = _PyObject_LookupSpecial(obj, "__dir__", &dir_str); if (PyErr_Occurred()) return NULL; + } + if (dirfunc == NULL) { /* use default implementation */ - PyErr_Clear(); if (PyModule_Check(obj)) result = _specialized_dir_module(obj); else if (PyType_Check(obj) || PyClass_Check(obj)) -- cgit v1.2.1 From 01e8e6d6e8bd22049c3d850aed0262578c185390 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Mon, 23 May 2011 18:17:55 -0500 Subject: must clear an AttributeError if it is set --- Objects/object.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Objects/object.c b/Objects/object.c index 5cf15b6a40..94a18d37db 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -1911,8 +1911,12 @@ _dir_object(PyObject *obj) assert(obj); if (PyInstance_Check(obj)) { dirfunc = PyObject_GetAttrString(obj, "__dir__"); - if (dirfunc == NULL && !PyErr_ExceptionMatches(PyExc_AttributeError)) - return NULL; + if (dirfunc == NULL) { + if (PyErr_ExceptionMatches(PyExc_AttributeError)) + PyErr_Clear(); + else + return NULL; + } } else { dirfunc = _PyObject_LookupSpecial(obj, "__dir__", &dir_str); -- cgit v1.2.1 From 3db5f1d86143ce3b24f187b170b19fe639af000c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Araujo?= Date: Wed, 25 May 2011 18:06:16 +0200 Subject: Fix two typos --- Doc/documenting/style.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/documenting/style.rst b/Doc/documenting/style.rst index 80955fda58..192894085a 100644 --- a/Doc/documenting/style.rst +++ b/Doc/documenting/style.rst @@ -92,7 +92,7 @@ Good example (establishing confident knowledge in the effective use of the langu Economy of Expression --------------------- -More documentation is not necessarily better documentation. Error on the side +More documentation is not necessarily better documentation. Err on the side of being succinct. It is an unfortunate fact that making documentation longer can be an impediment @@ -154,7 +154,7 @@ Audience The tone of the tutorial (and all the docs) needs to be respectful of the reader's intelligence. Don't presume that the readers are stupid. Lay out the relevant information, show motivating use cases, provide glossary links, and do -our best to connect-the-dots, but don't talk down to them or waste their time. +your best to connect the dots, but don't talk down to them or waste their time. The tutorial is meant for newcomers, many of whom will be using the tutorial to evaluate the language as a whole. The experience needs to be positive and not -- cgit v1.2.1