From fc095202afe7f81eeba2794e9ac12cd6252d55de Mon Sep 17 00:00:00 2001 From: R David Murray Date: Mon, 16 Jul 2012 22:31:32 -0400 Subject: #15375: remove duplicated word 'child' --- Doc/library/subprocess.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/subprocess.rst b/Doc/library/subprocess.rst index 5e4bcd9..3aae137 100644 --- a/Doc/library/subprocess.rst +++ b/Doc/library/subprocess.rst @@ -289,7 +289,7 @@ functions. Popen(['/bin/sh', '-c', args[0], args[1], ...]) - On Windows: the :class:`Popen` class uses CreateProcess() to execute the child + On Windows: the :class:`Popen` class uses CreateProcess() to execute the child program, which operates on strings. If *args* is a sequence, it will be converted to a string in a manner described in :ref:`converting-argument-sequence`. -- cgit v0.12 From 6642d1f97d7b89509159214253900eb3d970e223 Mon Sep 17 00:00:00 2001 From: Meador Inge Date: Wed, 18 Jul 2012 14:09:04 -0500 Subject: Issue #15368: make bytecode generation deterministic. --- Misc/NEWS | 5 ++++- Python/compile.c | 24 ++++++++++++++++++++++-- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS index 4b05aa3..6a2abb5 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -1,4 +1,4 @@ -Python News +,Python News +++++++++++ What's New in Python 2.7.4 @@ -9,6 +9,9 @@ What's New in Python 2.7.4 Core and Builtins ----------------- +- Issue #15368: An issue that caused bytecode generation to be + non-deterministic when using randomized hashing (-R) has been fixed. + - Issue #15033: Fix the exit status bug when modules invoked using -m swith, return the proper failure return value (1). Patch contributed by Jeff Knupp. diff --git a/Python/compile.c b/Python/compile.c index 119c60f..d50344c 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -359,14 +359,31 @@ each key. static PyObject * dictbytype(PyObject *src, int scope_type, int flag, int offset) { - Py_ssize_t pos = 0, i = offset, scope; + Py_ssize_t pos = 0, i = offset, scope, num_keys, key_i; PyObject *k, *v, *dest = PyDict_New(); + PyObject *sorted_keys; assert(offset >= 0); if (dest == NULL) return NULL; - while (PyDict_Next(src, &pos, &k, &v)) { + /* Sort the keys so that we have a deterministic order on the indexes + saved in the returned dictionary. These indexes are used as indexes + into the free and cell var storage. Therefore if they aren't + deterministic, then the generated bytecode is not deterministic. + */ + sorted_keys = PyDict_Keys(src); + if (sorted_keys == NULL) + return NULL; + if (PyList_Sort(sorted_keys) != 0) { + Py_DECREF(sorted_keys); + return NULL; + } + num_keys = PyList_GET_SIZE(src); + + for (key_i = 0; key_i < num_keys; key_i++) { + k = PyList_GET_ITEM(sorted_keys, key_i); + v = PyDict_GetItem(src, k); /* XXX this should probably be a macro in symtable.h */ assert(PyInt_Check(v)); scope = (PyInt_AS_LONG(v) >> SCOPE_OFF) & SCOPE_MASK; @@ -374,12 +391,14 @@ dictbytype(PyObject *src, int scope_type, int flag, int offset) if (scope == scope_type || PyInt_AS_LONG(v) & flag) { PyObject *tuple, *item = PyInt_FromLong(i); if (item == NULL) { + Py_DECREF(sorted_keys); Py_DECREF(dest); return NULL; } i++; tuple = PyTuple_Pack(2, k, k->ob_type); if (!tuple || PyDict_SetItem(dest, tuple, item) < 0) { + Py_DECREF(sorted_keys); Py_DECREF(item); Py_DECREF(dest); Py_XDECREF(tuple); @@ -389,6 +408,7 @@ dictbytype(PyObject *src, int scope_type, int flag, int offset) Py_DECREF(tuple); } } + Py_DECREF(sorted_keys); return dest; } -- cgit v0.12 From b8a569065eb05b14a7aef1d837159e7135defbfb Mon Sep 17 00:00:00 2001 From: Meador Inge Date: Wed, 18 Jul 2012 16:32:37 -0500 Subject: Issue #15368: fixing variable typo. --- Python/compile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Python/compile.c b/Python/compile.c index d50344c..3cf8c6e 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -379,7 +379,7 @@ dictbytype(PyObject *src, int scope_type, int flag, int offset) Py_DECREF(sorted_keys); return NULL; } - num_keys = PyList_GET_SIZE(src); + num_keys = PyList_GET_SIZE(sorted_keys); for (key_i = 0; key_i < num_keys; key_i++) { k = PyList_GET_ITEM(sorted_keys, key_i); -- cgit v0.12 From 0e3755e58a0495f835fc2eb89c7a72e87366346c Mon Sep 17 00:00:00 2001 From: Meador Inge Date: Wed, 18 Jul 2012 17:48:34 -0500 Subject: remove unused variable --- Python/compile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Python/compile.c b/Python/compile.c index 3cf8c6e..531bed4 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -359,7 +359,7 @@ each key. static PyObject * dictbytype(PyObject *src, int scope_type, int flag, int offset) { - Py_ssize_t pos = 0, i = offset, scope, num_keys, key_i; + Py_ssize_t i = offset, scope, num_keys, key_i; PyObject *k, *v, *dest = PyDict_New(); PyObject *sorted_keys; -- cgit v0.12 From 59488d233bb663af24492759fd0316ab499200d0 Mon Sep 17 00:00:00 2001 From: R David Murray Date: Wed, 18 Jul 2012 19:44:08 -0400 Subject: Closes #9254: backport __import__ docstring/doc mentions of importlib. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Patch by Éric Araujo. --- Doc/library/functions.rst | 13 +++---------- Python/bltinmodule.c | 8 ++++++-- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index a324e51..dc8ee9a 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -1558,7 +1558,7 @@ available. They are listed here in alphabetical order. .. note:: This is an advanced function that is not needed in everyday Python - programming. + programming, unlike :func:`importlib.import_module`. This function is invoked by the :keyword:`import` statement. It can be replaced (by importing the :mod:`__builtin__` module and assigning to @@ -1609,15 +1609,8 @@ available. They are listed here in alphabetical order. names. If you simply want to import a module (potentially within a package) by name, - you can call :func:`__import__` and then look it up in :data:`sys.modules`:: - - >>> import sys - >>> name = 'foo.bar.baz' - >>> __import__(name) - - >>> baz = sys.modules[name] - >>> baz - + use :func:`importlib.import_module`. + .. versionchanged:: 2.5 The level parameter was added. diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 373f870..3def080 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -53,8 +53,12 @@ builtin___import__(PyObject *self, PyObject *args, PyObject *kwds) PyDoc_STRVAR(import_doc, "__import__(name, globals={}, locals={}, fromlist=[], level=-1) -> module\n\ \n\ -Import a module. The globals are only used to determine the context;\n\ -they are not modified. The locals are currently unused. The fromlist\n\ +Import a module. Because this function is meant for use by the Python\n\ +interpreter and not for general use it is better to use\n\ +importlib.import_module() to programmatically import a module.\n\ +\n\ +The globals argument is only used to determine the context;\n\ +they are not modified. The locals argument is unused. The fromlist\n\ should be a list of names to emulate ``from name import ...'', or an\n\ empty list to emulate ``import name''.\n\ When importing a module from a package, note that __import__('A.B', ...)\n\ -- cgit v0.12 From 25be3f68e02b06c43dfa9eb831fddd69fa33fc64 Mon Sep 17 00:00:00 2001 From: Meador Inge Date: Wed, 18 Jul 2012 23:51:05 -0500 Subject: Issue #6493: Fix handling of c_uint32 bitfields with width of 32 on Windows. --- Lib/ctypes/test/test_bitfields.py | 20 +++++++++++++++ Misc/NEWS | 3 +++ Modules/_ctypes/cfield.c | 51 ++++++++++++++++++--------------------- 3 files changed, 46 insertions(+), 28 deletions(-) diff --git a/Lib/ctypes/test/test_bitfields.py b/Lib/ctypes/test/test_bitfields.py index e9c46c2..090fb4d 100644 --- a/Lib/ctypes/test/test_bitfields.py +++ b/Lib/ctypes/test/test_bitfields.py @@ -240,5 +240,25 @@ class BitFieldTest(unittest.TestCase): _anonymous_ = ["_"] _fields_ = [("_", X)] + @unittest.skipUnless(hasattr(ctypes, "c_uint32"), "c_int32 is required") + def test_uint32(self): + class X(Structure): + _fields_ = [("a", c_uint32, 32)] + x = X() + x.a = 10 + self.assertEquals(x.a, 10) + x.a = 0xFDCBA987 + self.assertEquals(x.a, 0xFDCBA987) + + @unittest.skipUnless(hasattr(ctypes, "c_uint64"), "c_int64 is required") + def test_uint64(self): + class X(Structure): + _fields_ = [("a", c_uint64, 64)] + x = X() + x.a = 10 + self.assertEquals(x.a, 10) + x.a = 0xFEDCBA9876543211 + self.assertEquals(x.a, 0xFEDCBA9876543211) + if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS b/Misc/NEWS index 6a2abb5..c5fc1bd 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -87,6 +87,9 @@ Core and Builtins Library ------- +- Issue #6493: An issue in ctypes on Windows that caused structure bitfields + of type ctypes.c_uint32 and width 32 to incorrectly be set has been fixed. + - Issue #14635: telnetlib will use poll() rather than select() when possible to avoid failing due to the select() file descriptor limit. diff --git a/Modules/_ctypes/cfield.c b/Modules/_ctypes/cfield.c index 1aab202..5e0fc75 100644 --- a/Modules/_ctypes/cfield.c +++ b/Modules/_ctypes/cfield.c @@ -431,12 +431,8 @@ get_ulonglong(PyObject *v, unsigned PY_LONG_LONG *p) #define LOW_BIT(x) ((x) & 0xFFFF) #define NUM_BITS(x) ((x) >> 16) -/* This seems nore a compiler issue than a Windows/non-Windows one */ -#ifdef MS_WIN32 -# define BIT_MASK(size) ((1 << NUM_BITS(size))-1) -#else -# define BIT_MASK(size) ((1LL << NUM_BITS(size))-1) -#endif +/* Doesn't work if NUM_BITS(size) == 0, but it never happens in SET() call. */ +#define BIT_MASK(type, size) (((((type)1 << (NUM_BITS(size) - 1)) - 1) << 1) + 1) /* This macro CHANGES the first parameter IN PLACE. For proper sign handling, we must first shift left, then right. @@ -448,10 +444,10 @@ get_ulonglong(PyObject *v, unsigned PY_LONG_LONG *p) } /* This macro RETURNS the first parameter with the bit field CHANGED. */ -#define SET(x, v, size) \ +#define SET(type, x, v, size) \ (NUM_BITS(size) ? \ - ( ( x & ~(BIT_MASK(size) << LOW_BIT(size)) ) | ( (v & BIT_MASK(size)) << LOW_BIT(size) ) ) \ - : v) + ( ( (type)x & ~(BIT_MASK(type, size) << LOW_BIT(size)) ) | ( ((type)v & BIT_MASK(type, size)) << LOW_BIT(size) ) ) \ + : (type)v) /* byte swapping macros */ #define SWAP_2(v) \ @@ -523,7 +519,7 @@ b_set(void *ptr, PyObject *value, Py_ssize_t size) long val; if (get_long(value, &val) < 0) return NULL; - *(signed char *)ptr = (signed char)SET(*(signed char *)ptr, (signed char)val, size); + *(signed char *)ptr = SET(signed char, *(signed char *)ptr, val, size); _RET(value); } @@ -542,8 +538,7 @@ B_set(void *ptr, PyObject *value, Py_ssize_t size) unsigned long val; if (get_ulong(value, &val) < 0) return NULL; - *(unsigned char *)ptr = (unsigned char)SET(*(unsigned char*)ptr, - (unsigned short)val, size); + *(unsigned char *)ptr = SET(unsigned char, *(unsigned char*)ptr, val, size); _RET(value); } @@ -564,7 +559,7 @@ h_set(void *ptr, PyObject *value, Py_ssize_t size) if (get_long(value, &val) < 0) return NULL; memcpy(&x, ptr, sizeof(x)); - x = SET(x, (short)val, size); + x = SET(short, x, val, size); memcpy(ptr, &x, sizeof(x)); _RET(value); } @@ -579,7 +574,7 @@ h_set_sw(void *ptr, PyObject *value, Py_ssize_t size) return NULL; memcpy(&field, ptr, sizeof(field)); field = SWAP_2(field); - field = SET(field, (short)val, size); + field = SET(short, field, val, size); field = SWAP_2(field); memcpy(ptr, &field, sizeof(field)); _RET(value); @@ -612,7 +607,7 @@ H_set(void *ptr, PyObject *value, Py_ssize_t size) if (get_ulong(value, &val) < 0) return NULL; memcpy(&x, ptr, sizeof(x)); - x = SET(x, (unsigned short)val, size); + x = SET(unsigned short, x, val, size); memcpy(ptr, &x, sizeof(x)); _RET(value); } @@ -626,7 +621,7 @@ H_set_sw(void *ptr, PyObject *value, Py_ssize_t size) return NULL; memcpy(&field, ptr, sizeof(field)); field = SWAP_2(field); - field = SET(field, (unsigned short)val, size); + field = SET(unsigned short, field, val, size); field = SWAP_2(field); memcpy(ptr, &field, sizeof(field)); _RET(value); @@ -660,7 +655,7 @@ i_set(void *ptr, PyObject *value, Py_ssize_t size) if (get_long(value, &val) < 0) return NULL; memcpy(&x, ptr, sizeof(x)); - x = SET(x, (int)val, size); + x = SET(int, x, val, size); memcpy(ptr, &x, sizeof(x)); _RET(value); } @@ -674,7 +669,7 @@ i_set_sw(void *ptr, PyObject *value, Py_ssize_t size) return NULL; memcpy(&field, ptr, sizeof(field)); field = SWAP_INT(field); - field = SET(field, (int)val, size); + field = SET(int, field, val, size); field = SWAP_INT(field); memcpy(ptr, &field, sizeof(field)); _RET(value); @@ -761,7 +756,7 @@ I_set(void *ptr, PyObject *value, Py_ssize_t size) if (get_ulong(value, &val) < 0) return NULL; memcpy(&x, ptr, sizeof(x)); - x = SET(x, (unsigned int)val, size); + x = SET(unsigned int, x, val, size); memcpy(ptr, &x, sizeof(x)); _RET(value); } @@ -774,7 +769,7 @@ I_set_sw(void *ptr, PyObject *value, Py_ssize_t size) if (get_ulong(value, &val) < 0) return NULL; memcpy(&field, ptr, sizeof(field)); - field = (unsigned int)SET(field, (unsigned int)val, size); + field = SET(unsigned int, field, (unsigned int)val, size); field = SWAP_INT(field); memcpy(ptr, &field, sizeof(field)); _RET(value); @@ -808,7 +803,7 @@ l_set(void *ptr, PyObject *value, Py_ssize_t size) if (get_long(value, &val) < 0) return NULL; memcpy(&x, ptr, sizeof(x)); - x = SET(x, val, size); + x = SET(long, x, val, size); memcpy(ptr, &x, sizeof(x)); _RET(value); } @@ -822,7 +817,7 @@ l_set_sw(void *ptr, PyObject *value, Py_ssize_t size) return NULL; memcpy(&field, ptr, sizeof(field)); field = SWAP_LONG(field); - field = (long)SET(field, val, size); + field = SET(long, field, val, size); field = SWAP_LONG(field); memcpy(ptr, &field, sizeof(field)); _RET(value); @@ -856,7 +851,7 @@ L_set(void *ptr, PyObject *value, Py_ssize_t size) if (get_ulong(value, &val) < 0) return NULL; memcpy(&x, ptr, sizeof(x)); - x = SET(x, val, size); + x = SET(unsigned long, x, val, size); memcpy(ptr, &x, sizeof(x)); _RET(value); } @@ -870,7 +865,7 @@ L_set_sw(void *ptr, PyObject *value, Py_ssize_t size) return NULL; memcpy(&field, ptr, sizeof(field)); field = SWAP_LONG(field); - field = (unsigned long)SET(field, val, size); + field = SET(unsigned long, field, val, size); field = SWAP_LONG(field); memcpy(ptr, &field, sizeof(field)); _RET(value); @@ -905,7 +900,7 @@ q_set(void *ptr, PyObject *value, Py_ssize_t size) if (get_longlong(value, &val) < 0) return NULL; memcpy(&x, ptr, sizeof(x)); - x = SET(x, val, size); + x = SET(PY_LONG_LONG, x, val, size); memcpy(ptr, &x, sizeof(x)); _RET(value); } @@ -919,7 +914,7 @@ q_set_sw(void *ptr, PyObject *value, Py_ssize_t size) return NULL; memcpy(&field, ptr, sizeof(field)); field = SWAP_8(field); - field = (PY_LONG_LONG)SET(field, val, size); + field = SET(PY_LONG_LONG, field, val, size); field = SWAP_8(field); memcpy(ptr, &field, sizeof(field)); _RET(value); @@ -952,7 +947,7 @@ Q_set(void *ptr, PyObject *value, Py_ssize_t size) if (get_ulonglong(value, &val) < 0) return NULL; memcpy(&x, ptr, sizeof(x)); - x = SET(x, val, size); + x = SET(PY_LONG_LONG, x, val, size); memcpy(ptr, &x, sizeof(x)); _RET(value); } @@ -966,7 +961,7 @@ Q_set_sw(void *ptr, PyObject *value, Py_ssize_t size) return NULL; memcpy(&field, ptr, sizeof(field)); field = SWAP_8(field); - field = (unsigned PY_LONG_LONG)SET(field, val, size); + field = SET(unsigned PY_LONG_LONG, field, val, size); field = SWAP_8(field); memcpy(ptr, &field, sizeof(field)); _RET(value); -- cgit v0.12 From bee739baa771b7c54169e799fbfe1a55c5fce3d6 Mon Sep 17 00:00:00 2001 From: Vinay Sajip Date: Fri, 20 Jul 2012 09:48:46 +0100 Subject: Issue #15399: Added versionchanged for processName. --- Doc/library/logging.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Doc/library/logging.rst b/Doc/library/logging.rst index b77fd36..7ed1f1a 100644 --- a/Doc/library/logging.rst +++ b/Doc/library/logging.rst @@ -629,6 +629,9 @@ format string. .. versionchanged:: 2.5 *funcName* was added. +.. versionchanged:: 2.6 + *processName* was added. + .. _logger-adapter: LoggerAdapter Objects -- cgit v0.12 From 715a63b78349952ccc0fb3dd3139e2d822006d35 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Sat, 21 Jul 2012 00:52:06 +0200 Subject: Issue #14579: Fix error handling bug in the utf-16 decoder. Patch by Serhiy Storchaka. --- Lib/test/test_codecs.py | 28 ++++++++++++++++++++++++++-- Misc/NEWS | 3 +++ Objects/unicodeobject.c | 2 +- 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_codecs.py b/Lib/test/test_codecs.py index d434f83..57669f8 100644 --- a/Lib/test/test_codecs.py +++ b/Lib/test/test_codecs.py @@ -495,7 +495,19 @@ class UTF16LETest(ReadTest): ) def test_errors(self): - self.assertRaises(UnicodeDecodeError, codecs.utf_16_le_decode, "\xff", "strict", True) + tests = [ + (b'\xff', u'\ufffd'), + (b'A\x00Z', u'A\ufffd'), + (b'A\x00B\x00C\x00D\x00Z', u'ABCD\ufffd'), + (b'\x00\xd8', u'\ufffd'), + (b'\x00\xd8A', u'\ufffd'), + (b'\x00\xd8A\x00', u'\ufffdA'), + (b'\x00\xdcA\x00', u'\ufffdA'), + ] + for raw, expected in tests: + self.assertRaises(UnicodeDecodeError, codecs.utf_16_le_decode, + raw, 'strict', True) + self.assertEqual(raw.decode('utf-16le', 'replace'), expected) class UTF16BETest(ReadTest): encoding = "utf-16-be" @@ -516,7 +528,19 @@ class UTF16BETest(ReadTest): ) def test_errors(self): - self.assertRaises(UnicodeDecodeError, codecs.utf_16_be_decode, "\xff", "strict", True) + tests = [ + (b'\xff', u'\ufffd'), + (b'\x00A\xff', u'A\ufffd'), + (b'\x00A\x00B\x00C\x00DZ', u'ABCD\ufffd'), + (b'\xd8\x00', u'\ufffd'), + (b'\xd8\x00\xdc', u'\ufffd'), + (b'\xd8\x00\x00A', u'\ufffdA'), + (b'\xdc\x00\x00A', u'\ufffdA'), + ] + for raw, expected in tests: + self.assertRaises(UnicodeDecodeError, codecs.utf_16_be_decode, + raw, 'strict', True) + self.assertEqual(raw.decode('utf-16be', 'replace'), expected) class UTF8Test(ReadTest): encoding = "utf-8" diff --git a/Misc/NEWS b/Misc/NEWS index c5fc1bd..3766a33 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -9,6 +9,9 @@ What's New in Python 2.7.4 Core and Builtins ----------------- +- Issue #14579: Fix error handling bug in the utf-16 decoder. Patch by + Serhiy Storchaka. + - Issue #15368: An issue that caused bytecode generation to be non-deterministic when using randomized hashing (-R) has been fixed. diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index 7af7b50..59b138a 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -2564,7 +2564,7 @@ PyUnicode_DecodeUTF16Stateful(const char *s, } /* UTF-16 code pair: */ - if (q >= e) { + if (e - q < 2) { errmsg = "unexpected end of data"; startinpos = (((const char *)q)-2)-starts; endinpos = ((const char *)e)-starts; -- cgit v0.12 From dee8af225b04c28b2ed7e9dfcef6d93b7ae1c827 Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Fri, 20 Jul 2012 17:47:59 -0700 Subject: Fix whitespace --- Python/peephole.c | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/Python/peephole.c b/Python/peephole.c index 7521b9c..ae84efa 100644 --- a/Python/peephole.c +++ b/Python/peephole.c @@ -347,7 +347,7 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names, codestr = (unsigned char *)memcpy(codestr, PyString_AS_STRING(code), codelen); - /* Verify that RETURN_VALUE terminates the codestring. This allows + /* Verify that RETURN_VALUE terminates the codestring. This allows the various transformation patterns to look ahead several instructions without additional checks to make sure they are not looking beyond the end of the code string. @@ -445,8 +445,8 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names, case BUILD_LIST: j = GETARG(codestr, i); h = i - 3 * j; - if (h >= 0 && - j <= lastlc && + if (h >= 0 && + j <= lastlc && ((opcode == BUILD_TUPLE && ISBASICBLOCK(blocks, h, 3*(j+1))) || (opcode == BUILD_LIST && @@ -490,8 +490,8 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names, case BINARY_AND: case BINARY_XOR: case BINARY_OR: - if (lastlc >= 2 && - ISBASICBLOCK(blocks, i-6, 7) && + if (lastlc >= 2 && + ISBASICBLOCK(blocks, i-6, 7) && fold_binops_on_constants(&codestr[i-6], consts)) { i -= 2; assert(codestr[i] == LOAD_CONST); @@ -500,13 +500,13 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names, break; /* Fold unary ops on constants. - LOAD_CONST c1 UNARY_OP --> LOAD_CONST unary_op(c) */ + LOAD_CONST c1 UNARY_OP --> LOAD_CONST unary_op(c) */ case UNARY_NEGATIVE: case UNARY_CONVERT: case UNARY_INVERT: - if (lastlc >= 1 && - ISBASICBLOCK(blocks, i-3, 4) && - fold_unaryops_on_constants(&codestr[i-3], consts)) { + if (lastlc >= 1 && + ISBASICBLOCK(blocks, i-3, 4) && + fold_unaryops_on_constants(&codestr[i-3], consts)) { i -= 2; assert(codestr[i] == LOAD_CONST); cumlc = 1; @@ -532,8 +532,7 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names, tgt = GETJUMPTGT(codestr, i); j = codestr[tgt]; if (CONDITIONAL_JUMP(j)) { - /* NOTE: all possible jumps here are - absolute! */ + /* NOTE: all possible jumps here are absolute! */ if (JUMPS_ON_TRUE(j) == JUMPS_ON_TRUE(opcode)) { /* The second jump will be taken iff the first is. */ @@ -544,13 +543,10 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names, SETARG(codestr, i, tgttgt); goto reoptimize_current; } else { - /* The second jump is not taken - if the first is (so jump past - it), and all conditional - jumps pop their argument when - they're not taken (so change - the first jump to pop its - argument when it's taken). */ + /* The second jump is not taken if the first is (so + jump past it), and all conditional jumps pop their + argument when they're not taken (so change the + first jump to pop its argument when it's taken). */ if (JUMPS_ON_TRUE(opcode)) codestr[i] = POP_JUMP_IF_TRUE; else @@ -586,8 +582,8 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names, if (opcode == JUMP_FORWARD) /* JMP_ABS can go backwards */ opcode = JUMP_ABSOLUTE; if (!ABSOLUTE_JUMP(opcode)) - tgttgt -= i + 3; /* Calc relative jump addr */ - if (tgttgt < 0) /* No backward relative jumps */ + tgttgt -= i + 3; /* Calc relative jump addr */ + if (tgttgt < 0) /* No backward relative jumps */ continue; codestr[i] = opcode; SETARG(codestr, i, tgttgt); -- cgit v0.12 From d33a9beb8d9de33b86d305ed4733b3e5acacd37e Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Sat, 21 Jul 2012 16:48:16 +0200 Subject: Fix typo introduced in 79d54fba49b3. --- Misc/NEWS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS b/Misc/NEWS index 3766a33..16ab202 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -1,4 +1,4 @@ -,Python News +Python News +++++++++++ What's New in Python 2.7.4 -- cgit v0.12 From ac9b5c67d35ee100ff1d80f4d55c307aab4ca4e7 Mon Sep 17 00:00:00 2001 From: R David Murray Date: Sat, 21 Jul 2012 14:37:29 -0400 Subject: #15342: Add clarifying sentence to posixpath.join docstring. This sentence appears as a clarifying note in the HTML docs, and seems worth having in the docstring since it covers a very common use case that isn't otherwise obvious. Thanks to Yongzhi Pan for the suggestion. --- Lib/posixpath.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Lib/posixpath.py b/Lib/posixpath.py index 690c70d..5ddf25b 100644 --- a/Lib/posixpath.py +++ b/Lib/posixpath.py @@ -68,7 +68,8 @@ def isabs(s): def join(a, *p): """Join two or more pathname components, inserting '/' as needed. If any component is an absolute path, all previous path components - will be discarded.""" + will be discarded. An empty last part will result in a path that + ends with a separator.""" path = a for b in p: if b.startswith('/'): -- cgit v0.12 From 1a2c1fbfd2208407e1af365b161276b6f103c1ad Mon Sep 17 00:00:00 2001 From: R David Murray Date: Sat, 21 Jul 2012 17:06:28 -0400 Subject: #14391: clarify docstring discussion of Action's 'type' argument's value. --- Lib/argparse.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Lib/argparse.py b/Lib/argparse.py index a9129de..d867611 100644 --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -740,10 +740,10 @@ class Action(_AttributeHolder): - default -- The value to be produced if the option is not specified. - - type -- The type which the command-line arguments should be converted - to, should be one of 'string', 'int', 'float', 'complex' or a - callable object that accepts a single string argument. If None, - 'string' is assumed. + - type -- A callable that accepts a single string argument, and + returns the converted value. The standard Python types str, int, + float, and complex are useful examples of such callables. If None, + str is used. - choices -- A container of values that should be allowed. If not None, after a command-line argument has been converted to the appropriate -- cgit v0.12 From 056c31f9cc10a8697a40c817eae42f7e38a1cf80 Mon Sep 17 00:00:00 2001 From: R David Murray Date: Sat, 21 Jul 2012 22:35:00 -0400 Subject: #12353: argparse now correctly handles null argument values. Patch by Torsten Landschoff. --- Lib/argparse.py | 2 +- Lib/test/test_argparse.py | 1 + Misc/NEWS | 2 ++ 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Lib/argparse.py b/Lib/argparse.py index d867611..f365385 100644 --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -1967,7 +1967,7 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer): for arg_string in arg_strings: # for regular arguments, just add them back into the list - if arg_string[0] not in self.fromfile_prefix_chars: + if not arg_string or arg_string[0] not in self.fromfile_prefix_chars: new_arg_strings.append(arg_string) # replace arguments referencing files with the file content diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py index 1a5f05e..a7a4b00 100644 --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -1374,6 +1374,7 @@ class TestArgumentsFromFile(TempDirMixin, ParserTestCase): ('X @hello', NS(a=None, x='X', y=['hello world!'])), ('-a B @recursive Y Z', NS(a='A', x='hello world!', y=['Y', 'Z'])), ('X @recursive Z -a B', NS(a='B', x='X', y=['hello world!', 'Z'])), + (["-a", "", "X", "Y"], NS(a='', x='X', y=['Y'])), ] diff --git a/Misc/NEWS b/Misc/NEWS index 16ab202..7a2eb5b 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -90,6 +90,8 @@ Core and Builtins Library ------- +- Issue #12353: argparse now correctly handles null argument values. + - Issue #6493: An issue in ctypes on Windows that caused structure bitfields of type ctypes.c_uint32 and width 32 to incorrectly be set has been fixed. -- cgit v0.12 From 68f555c03ad32671a76c5762313bbf33c0ae4842 Mon Sep 17 00:00:00 2001 From: R David Murray Date: Sat, 21 Jul 2012 22:54:34 -0400 Subject: #13922: argparse no longer incorrectly strips '--' after the first one. Patch by Jeff Knupp. --- Lib/argparse.py | 7 +++++-- Lib/test/test_argparse.py | 37 +++++++++++++++++++++++++------------ Misc/ACKS | 1 + Misc/NEWS | 3 +++ 4 files changed, 34 insertions(+), 14 deletions(-) diff --git a/Lib/argparse.py b/Lib/argparse.py index f365385..80df97b 100644 --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -2174,9 +2174,12 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer): # Value conversion methods # ======================== def _get_values(self, action, arg_strings): - # for everything but PARSER args, strip out '--' + # for everything but PARSER, REMAINDER args, strip out first '--' if action.nargs not in [PARSER, REMAINDER]: - arg_strings = [s for s in arg_strings if s != '--'] + try: + arg_strings.remove('--') + except ValueError: + pass # optional argument produces a default when not present if not arg_strings and action.nargs == OPTIONAL: diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py index a7a4b00..80dbc22 100644 --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -1764,6 +1764,14 @@ class TestAddSubparsers(TestCase): parser2.add_argument('-y', choices='123', help='y help') parser2.add_argument('z', type=complex, nargs='*', help='z help') + # add third sub-parser + parser3_kwargs = dict(description='3 description') + if subparser_help: + parser3_kwargs['help'] = '3 help' + parser3 = subparsers.add_parser('3', **parser3_kwargs) + parser3.add_argument('t', type=int, help='t help') + parser3.add_argument('u', nargs='...', help='u help') + # return the main parser return parser @@ -1793,6 +1801,10 @@ class TestAddSubparsers(TestCase): self.parser.parse_args('--foo 0.125 1 c'.split()), NS(foo=True, bar=0.125, w=None, x='c'), ) + self.assertEqual( + self.parser.parse_args('-1.5 3 11 -- a --foo 7 -- b'.split()), + NS(foo=False, bar=-1.5, t=11, u=['a', '--foo', '7', '--', 'b']), + ) def test_parse_known_args(self): self.assertEqual( @@ -1827,15 +1839,15 @@ class TestAddSubparsers(TestCase): def test_help(self): self.assertEqual(self.parser.format_usage(), - 'usage: PROG [-h] [--foo] bar {1,2} ...\n') + 'usage: PROG [-h] [--foo] bar {1,2,3} ...\n') self.assertEqual(self.parser.format_help(), textwrap.dedent('''\ - usage: PROG [-h] [--foo] bar {1,2} ... + usage: PROG [-h] [--foo] bar {1,2,3} ... main description positional arguments: bar bar help - {1,2} command help + {1,2,3} command help optional arguments: -h, --help show this help message and exit @@ -1846,15 +1858,15 @@ class TestAddSubparsers(TestCase): # Make sure - is still used for help if it is a non-first prefix char parser = self._get_parser(prefix_chars='+:-') self.assertEqual(parser.format_usage(), - 'usage: PROG [-h] [++foo] bar {1,2} ...\n') + 'usage: PROG [-h] [++foo] bar {1,2,3} ...\n') self.assertEqual(parser.format_help(), textwrap.dedent('''\ - usage: PROG [-h] [++foo] bar {1,2} ... + usage: PROG [-h] [++foo] bar {1,2,3} ... main description positional arguments: bar bar help - {1,2} command help + {1,2,3} command help optional arguments: -h, --help show this help message and exit @@ -1865,15 +1877,15 @@ class TestAddSubparsers(TestCase): def test_help_alternate_prefix_chars(self): parser = self._get_parser(prefix_chars='+:/') self.assertEqual(parser.format_usage(), - 'usage: PROG [+h] [++foo] bar {1,2} ...\n') + 'usage: PROG [+h] [++foo] bar {1,2,3} ...\n') self.assertEqual(parser.format_help(), textwrap.dedent('''\ - usage: PROG [+h] [++foo] bar {1,2} ... + usage: PROG [+h] [++foo] bar {1,2,3} ... main description positional arguments: bar bar help - {1,2} command help + {1,2,3} command help optional arguments: +h, ++help show this help message and exit @@ -1882,18 +1894,19 @@ class TestAddSubparsers(TestCase): def test_parser_command_help(self): self.assertEqual(self.command_help_parser.format_usage(), - 'usage: PROG [-h] [--foo] bar {1,2} ...\n') + 'usage: PROG [-h] [--foo] bar {1,2,3} ...\n') self.assertEqual(self.command_help_parser.format_help(), textwrap.dedent('''\ - usage: PROG [-h] [--foo] bar {1,2} ... + usage: PROG [-h] [--foo] bar {1,2,3} ... main description positional arguments: bar bar help - {1,2} command help + {1,2,3} command help 1 1 help 2 2 help + 3 3 help optional arguments: -h, --help show this help message and exit diff --git a/Misc/ACKS b/Misc/ACKS index 471e6a9..75659f0 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -462,6 +462,7 @@ Thomas Kluyver Kim Knapp Lenny Kneler Pat Knight +Jeff Knupp Greg Kochanski Damon Kohler Marko Kohtala diff --git a/Misc/NEWS b/Misc/NEWS index 7a2eb5b..b73bf0a 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -90,6 +90,9 @@ Core and Builtins Library ------- +- Issue #13922: argparse no longer incorrectly strips '--'s that appear + after the first one. + - Issue #12353: argparse now correctly handles null argument values. - Issue #6493: An issue in ctypes on Windows that caused structure bitfields -- cgit v0.12