From solipsis at pitrou.net Thu Jul 1 01:23:55 2010 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Thu, 1 Jul 2010 01:23:55 +0200 (CEST) Subject: [Python-checkins] Daily py3k reference leaks (r82407): sum=0 Message-ID: <20100630232355.4AB2A1770A@ns6635.ovh.net> py3k results for svn r82407 (hg cset 40435013f940) -------------------------------------------------- Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/py3k/refleaks/reflogluNgCL', '-x'] From python-checkins at python.org Thu Jul 1 01:58:07 2010 From: python-checkins at python.org (ezio.melotti) Date: Thu, 1 Jul 2010 01:58:07 +0200 (CEST) Subject: [Python-checkins] r82412 - in tracker/instances/python-dev/html: issue.item.html issue.item.js Message-ID: <20100630235807.73769EEA48@mail.python.org> Author: ezio.melotti Date: Thu Jul 1 01:58:07 2010 New Revision: 82412 Log: Avoid using display:block -- the resize works with display:inline too. Also close the span properly in issue.item.html. Modified: tracker/instances/python-dev/html/issue.item.html tracker/instances/python-dev/html/issue.item.js Modified: tracker/instances/python-dev/html/issue.item.html ============================================================================== --- tracker/instances/python-dev/html/issue.item.html (original) +++ tracker/instances/python-dev/html/issue.item.html Thu Jul 1 01:58:07 2010 @@ -145,7 +145,7 @@ tal:define="current_user request/user/username" tal:condition="python:request.user.username != 'anonymous' and current_user not in str(context.nosy).replace(' ','').split(',')" tal:attributes="onclick string:add_to_nosy('$current_user')" - onclick="add_to_nosy(the_current_username)" /> + onclick="add_to_nosy(the_current_username)"> Modified: tracker/instances/python-dev/html/issue.item.js ============================================================================== --- tracker/instances/python-dev/html/issue.item.js (original) +++ tracker/instances/python-dev/html/issue.item.js Thu Jul 1 01:58:07 2010 @@ -38,6 +38,6 @@ // hide the button and resize the list to fill the void var new_width = nosy.offsetWidth + add_me_button.offsetWidth; add_me_button.style.display = 'none'; - nosy.style.display = 'block'; + nosy.style.display = 'inline'; nosy.style.width = new_width + "px"; } From python-checkins at python.org Thu Jul 1 09:32:02 2010 From: python-checkins at python.org (ezio.melotti) Date: Thu, 1 Jul 2010 09:32:02 +0200 (CEST) Subject: [Python-checkins] r82413 - in python/branches/py3k: Lib/test/test_codeccallbacks.py Lib/test/test_unicode.py Misc/NEWS Objects/unicodeobject.c Message-ID: <20100701073202.76D7CEEAEF@mail.python.org> Author: ezio.melotti Date: Thu Jul 1 09:32:02 2010 New Revision: 82413 Log: Update PyUnicode_DecodeUTF8 from RFC 2279 to RFC 3629. 1) #8271: when a byte sequence is invalid, only the start byte and all the valid continuation bytes are now replaced by U+FFFD, instead of replacing the number of bytes specified by the start byte. See http://www.unicode.org/versions/Unicode5.2.0/ch03.pdf (pages 94-95); 2) 5- and 6-bytes-long UTF-8 sequences are now considered invalid (no changes in behavior); 3) Change the error messages "unexpected code byte" to "invalid start byte" and "invalid data" to "invalid continuation byte"; 4) Add an extensive set of tests in test_unicode; 5) Fix test_codeccallbacks because it was failing after this change. Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/test/test_codeccallbacks.py python/branches/py3k/Lib/test/test_unicode.py python/branches/py3k/Misc/NEWS python/branches/py3k/Objects/unicodeobject.c Modified: python/branches/py3k/Lib/test/test_codeccallbacks.py ============================================================================== --- python/branches/py3k/Lib/test/test_codeccallbacks.py (original) +++ python/branches/py3k/Lib/test/test_codeccallbacks.py Thu Jul 1 09:32:02 2010 @@ -153,28 +153,30 @@ sout += bytes("\\U%08x" % sys.maxunicode, "ascii") self.assertEqual(sin.encode("iso-8859-15", "backslashreplace"), sout) - def test_decoderelaxedutf8(self): - # This is the test for a decoding callback handler, - # that relaxes the UTF-8 minimal encoding restriction. - # A null byte that is encoded as "\xc0\x80" will be - # decoded as a null byte. All other illegal sequences - # will be handled strictly. + def test_decoding_callbacks(self): + # This is a test for a decoding callback handler + # that allows the decoding of the invalid sequence + # "\xc0\x80" and returns "\x00" instead of raising an error. + # All other illegal sequences will be handled strictly. def relaxedutf8(exc): if not isinstance(exc, UnicodeDecodeError): raise TypeError("don't know how to handle %r" % exc) - if exc.object[exc.start:exc.end].startswith(b"\xc0\x80"): + if exc.object[exc.start:exc.start+2] == b"\xc0\x80": return ("\x00", exc.start+2) # retry after two bytes else: raise exc - codecs.register_error( - "test.relaxedutf8", relaxedutf8) + codecs.register_error("test.relaxedutf8", relaxedutf8) + # all the "\xc0\x80" will be decoded to "\x00" sin = b"a\x00b\xc0\x80c\xc3\xbc\xc0\x80\xc0\x80" sout = "a\x00b\x00c\xfc\x00\x00" self.assertEqual(sin.decode("utf-8", "test.relaxedutf8"), sout) + + # "\xc0\x81" is not valid and a UnicodeDecodeError will be raised sin = b"\xc0\x80\xc0\x81" - self.assertRaises(UnicodeError, sin.decode, "utf-8", "test.relaxedutf8") + self.assertRaises(UnicodeDecodeError, sin.decode, + "utf-8", "test.relaxedutf8") def test_charmapencode(self): # For charmap encodings the replacement string will be Modified: python/branches/py3k/Lib/test/test_unicode.py ============================================================================== --- python/branches/py3k/Lib/test/test_unicode.py (original) +++ python/branches/py3k/Lib/test/test_unicode.py Thu Jul 1 09:32:02 2010 @@ -942,6 +942,159 @@ # * strict decoding testing for all of the # UTF8_ERROR cases in PyUnicode_DecodeUTF8 + def test_utf8_decode_valid_sequences(self): + sequences = [ + # single byte + (b'\x00', '\x00'), (b'a', 'a'), (b'\x7f', '\x7f'), + # 2 bytes + (b'\xc2\x80', '\x80'), (b'\xdf\xbf', '\u07ff'), + # 3 bytes + (b'\xe0\xa0\x80', '\u0800'), (b'\xed\x9f\xbf', '\ud7ff'), + (b'\xee\x80\x80', '\uE000'), (b'\xef\xbf\xbf', '\uffff'), + # 4 bytes + (b'\xF0\x90\x80\x80', '\U00010000'), + (b'\xf4\x8f\xbf\xbf', '\U0010FFFF') + ] + for seq, res in sequences: + self.assertEqual(seq.decode('utf-8'), res) + + + def test_utf8_decode_invalid_sequences(self): + # continuation bytes in a sequence of 2, 3, or 4 bytes + continuation_bytes = [bytes([x]) for x in range(0x80, 0xC0)] + # start bytes of a 2-byte sequence equivalent to codepoints < 0x7F + invalid_2B_seq_start_bytes = [bytes([x]) for x in range(0xC0, 0xC2)] + # start bytes of a 4-byte sequence equivalent to codepoints > 0x10FFFF + invalid_4B_seq_start_bytes = [bytes([x]) for x in range(0xF5, 0xF8)] + invalid_start_bytes = ( + continuation_bytes + invalid_2B_seq_start_bytes + + invalid_4B_seq_start_bytes + [bytes([x]) for x in range(0xF7, 0x100)] + ) + + for byte in invalid_start_bytes: + self.assertRaises(UnicodeDecodeError, byte.decode, 'utf-8') + + for sb in invalid_2B_seq_start_bytes: + for cb in continuation_bytes: + self.assertRaises(UnicodeDecodeError, (sb+cb).decode, 'utf-8') + + for sb in invalid_4B_seq_start_bytes: + for cb1 in continuation_bytes[:3]: + for cb3 in continuation_bytes[:3]: + self.assertRaises(UnicodeDecodeError, + (sb+cb1+b'\x80'+cb3).decode, 'utf-8') + + for cb in [bytes([x]) for x in range(0x80, 0xA0)]: + self.assertRaises(UnicodeDecodeError, + (b'\xE0'+cb+b'\x80').decode, 'utf-8') + self.assertRaises(UnicodeDecodeError, + (b'\xE0'+cb+b'\xBF').decode, 'utf-8') + # surrogates + for cb in [bytes([x]) for x in range(0xA0, 0xC0)]: + self.assertRaises(UnicodeDecodeError, + (b'\xED'+cb+b'\x80').decode, 'utf-8') + self.assertRaises(UnicodeDecodeError, + (b'\xED'+cb+b'\xBF').decode, 'utf-8') + for cb in [bytes([x]) for x in range(0x80, 0x90)]: + self.assertRaises(UnicodeDecodeError, + (b'\xF0'+cb+b'\x80\x80').decode, 'utf-8') + self.assertRaises(UnicodeDecodeError, + (b'\xF0'+cb+b'\xBF\xBF').decode, 'utf-8') + for cb in [bytes([x]) for x in range(0x90, 0xC0)]: + self.assertRaises(UnicodeDecodeError, + (b'\xF4'+cb+b'\x80\x80').decode, 'utf-8') + self.assertRaises(UnicodeDecodeError, + (b'\xF4'+cb+b'\xBF\xBF').decode, 'utf-8') + + def test_issue8271(self): + # Issue #8271: during the decoding of an invalid UTF-8 byte sequence, + # only the start byte and the continuation byte(s) are now considered + # invalid, instead of the number of bytes specified by the start byte. + # See http://www.unicode.org/versions/Unicode5.2.0/ch03.pdf (page 95, + # table 3-8, Row 2) for more information about the algorithm used. + FFFD = '\ufffd' + sequences = [ + # invalid start bytes + (b'\x80', FFFD), # continuation byte + (b'\x80\x80', FFFD*2), # 2 continuation bytes + (b'\xc0', FFFD), + (b'\xc0\xc0', FFFD*2), + (b'\xc1', FFFD), + (b'\xc1\xc0', FFFD*2), + (b'\xc0\xc1', FFFD*2), + # with start byte of a 2-byte sequence + (b'\xc2', FFFD), # only the start byte + (b'\xc2\xc2', FFFD*2), # 2 start bytes + (b'\xc2\xc2\xc2', FFFD*3), # 2 start bytes + (b'\xc2\x41', FFFD+'A'), # invalid continuation byte + # with start byte of a 3-byte sequence + (b'\xe1', FFFD), # only the start byte + (b'\xe1\xe1', FFFD*2), # 2 start bytes + (b'\xe1\xe1\xe1', FFFD*3), # 3 start bytes + (b'\xe1\xe1\xe1\xe1', FFFD*4), # 4 start bytes + (b'\xe1\x80', FFFD), # only 1 continuation byte + (b'\xe1\x41', FFFD+'A'), # invalid continuation byte + (b'\xe1\x41\x80', FFFD+'A'+FFFD), # invalid cb followed by valid cb + (b'\xe1\x41\x41', FFFD+'AA'), # 2 invalid continuation bytes + (b'\xe1\x80\x41', FFFD+'A'), # only 1 valid continuation byte + (b'\xe1\x80\xe1\x41', FFFD*2+'A'), # 1 valid and the other invalid + (b'\xe1\x41\xe1\x80', FFFD+'A'+FFFD), # 1 invalid and the other valid + # with start byte of a 4-byte sequence + (b'\xf1', FFFD), # only the start byte + (b'\xf1\xf1', FFFD*2), # 2 start bytes + (b'\xf1\xf1\xf1', FFFD*3), # 3 start bytes + (b'\xf1\xf1\xf1\xf1', FFFD*4), # 4 start bytes + (b'\xf1\xf1\xf1\xf1\xf1', FFFD*5), # 5 start bytes + (b'\xf1\x80', FFFD), # only 1 continuation bytes + (b'\xf1\x80\x80', FFFD), # only 2 continuation bytes + (b'\xf1\x80\x41', FFFD+'A'), # 1 valid cb and 1 invalid + (b'\xf1\x80\x41\x41', FFFD+'AA'), # 1 valid cb and 1 invalid + (b'\xf1\x80\x80\x41', FFFD+'A'), # 2 valid cb and 1 invalid + (b'\xf1\x41\x80', FFFD+'A'+FFFD), # 1 invalid cv and 1 valid + (b'\xf1\x41\x80\x80', FFFD+'A'+FFFD*2), # 1 invalid cb and 2 invalid + (b'\xf1\x41\x80\x41', FFFD+'A'+FFFD+'A'), # 2 invalid cb and 1 invalid + (b'\xf1\x41\x41\x80', FFFD+'AA'+FFFD), # 1 valid cb and 1 invalid + (b'\xf1\x41\xf1\x80', FFFD+'A'+FFFD), + (b'\xf1\x41\x80\xf1', FFFD+'A'+FFFD*2), + (b'\xf1\xf1\x80\x41', FFFD*2+'A'), + (b'\xf1\x41\xf1\xf1', FFFD+'A'+FFFD*2), + # with invalid start byte of a 4-byte sequence (rfc2279) + (b'\xf5', FFFD), # only the start byte + (b'\xf5\xf5', FFFD*2), # 2 start bytes + (b'\xf5\x80', FFFD*2), # only 1 continuation byte + (b'\xf5\x80\x80', FFFD*3), # only 2 continuation byte + (b'\xf5\x80\x80\x80', FFFD*4), # 3 continuation bytes + (b'\xf5\x80\x41', FFFD*2+'A'), # 1 valid cb and 1 invalid + (b'\xf5\x80\x41\xf5', FFFD*2+'A'+FFFD), + (b'\xf5\x41\x80\x80\x41', FFFD+'A'+FFFD*2+'A'), + # with invalid start byte of a 5-byte sequence (rfc2279) + (b'\xf8', FFFD), # only the start byte + (b'\xf8\xf8', FFFD*2), # 2 start bytes + (b'\xf8\x80', FFFD*2), # only one continuation byte + (b'\xf8\x80\x41', FFFD*2 + 'A'), # 1 valid cb and 1 invalid + (b'\xf8\x80\x80\x80\x80', FFFD*5), # invalid 5 bytes seq with 5 bytes + # with invalid start byte of a 6-byte sequence (rfc2279) + (b'\xfc', FFFD), # only the start byte + (b'\xfc\xfc', FFFD*2), # 2 start bytes + (b'\xfc\x80\x80', FFFD*3), # only 2 continuation bytes + (b'\xfc\x80\x80\x80\x80\x80', FFFD*6), # 6 continuation bytes + # invalid start byte + (b'\xfe', FFFD), + (b'\xfe\x80\x80', FFFD*3), + # other sequences + (b'\xf1\x80\x41\x42\x43', '\ufffd\x41\x42\x43'), + (b'\xf1\x80\xff\x42\x43', '\ufffd\ufffd\x42\x43'), + (b'\xf1\x80\xc2\x81\x43', '\ufffd\x81\x43'), + (b'\x61\xF1\x80\x80\xE1\x80\xC2\x62\x80\x63\x80\xBF\x64', + '\x61\uFFFD\uFFFD\uFFFD\x62\uFFFD\x63\uFFFD\uFFFD\x64'), + ] + for n, (seq, res) in enumerate(sequences): + self.assertRaises(UnicodeDecodeError, seq.decode, 'utf-8', 'strict') + self.assertEqual(seq.decode('utf-8', 'replace'), res) + self.assertEqual((seq+b'b').decode('utf-8', 'replace'), res+'b') + self.assertEqual(seq.decode('utf-8', 'ignore'), + res.replace('\uFFFD', '')) + def test_codecs_idna(self): # Test whether trailing dot is preserved self.assertEqual("www.python.org.".encode("idna"), b"www.python.org.") Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Thu Jul 1 09:32:02 2010 @@ -12,6 +12,14 @@ Core and Builtins ----------------- +- Issue #8271: during the decoding of an invalid UTF-8 byte sequence, only the + start byte and the continuation byte(s) are now considered invalid, instead + of the number of bytes specified by the start byte. + E.g.: '\xf1\x80AB'.decode('utf-8', 'replace') now returns u'\ufffdAB' and + replaces with U+FFFD only the start byte ('\xf1') and the continuation byte + ('\x80') even if '\xf1' is the start byte of a 4-bytes sequence. + Previous versions returned a single u'\ufffd'. + - Issue #9011: A negated imaginary literal (e.g., "-7j") now has real part -0.0 rather than 0.0. So "-7j" is now exactly equivalent to "-(7j)". Modified: python/branches/py3k/Objects/unicodeobject.c ============================================================================== --- python/branches/py3k/Objects/unicodeobject.c (original) +++ python/branches/py3k/Objects/unicodeobject.c Thu Jul 1 09:32:02 2010 @@ -2285,24 +2285,24 @@ static char utf8_code_length[256] = { - /* Map UTF-8 encoded prefix byte to sequence length. zero means - illegal prefix. see RFC 2279 for details */ + /* Map UTF-8 encoded prefix byte to sequence length. Zero means + illegal prefix. See RFC 3629 for details */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 00-0F */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 70-7F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80-8F */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* B0-BF */ + 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* C0-C1 + C2-CF */ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* D0-DF */ + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* E0-EF */ + 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* F0-F4 + F5-FF */ }; PyObject *PyUnicode_DecodeUTF8(const char *s, @@ -2332,6 +2332,7 @@ { const char *starts = s; int n; + int k; Py_ssize_t startinpos; Py_ssize_t endinpos; Py_ssize_t outpos; @@ -2415,7 +2416,9 @@ else { errmsg = "unexpected end of data"; startinpos = s-starts; - endinpos = size; + endinpos = startinpos+1; + for (k=1; (k < size-startinpos) && ((s[k]&0xC0) == 0x80); k++) + endinpos++; goto utf8Error; } } @@ -2423,7 +2426,7 @@ switch (n) { case 0: - errmsg = "unexpected code byte"; + errmsg = "invalid start byte"; startinpos = s-starts; endinpos = startinpos+1; goto utf8Error; @@ -2436,63 +2439,67 @@ case 2: if ((s[1] & 0xc0) != 0x80) { - errmsg = "invalid data"; + errmsg = "invalid continuation byte"; startinpos = s-starts; - endinpos = startinpos+2; + endinpos = startinpos + 1; goto utf8Error; } ch = ((s[0] & 0x1f) << 6) + (s[1] & 0x3f); - if (ch < 0x80) { - startinpos = s-starts; - endinpos = startinpos+2; - errmsg = "illegal encoding"; - goto utf8Error; - } - else - *p++ = (Py_UNICODE)ch; + assert ((ch > 0x007F) && (ch <= 0x07FF)); + *p++ = (Py_UNICODE)ch; break; case 3: + /* XXX: surrogates shouldn't be valid UTF-8! + see http://www.unicode.org/versions/Unicode5.2.0/ch03.pdf + (table 3-7) and http://www.rfc-editor.org/rfc/rfc3629.txt + Uncomment the 2 lines below to make them invalid, + codepoints: d800-dfff; UTF-8: \xed\xa0\x80-\xed\xbf\xbf. */ if ((s[1] & 0xc0) != 0x80 || - (s[2] & 0xc0) != 0x80) { - errmsg = "invalid data"; + (s[2] & 0xc0) != 0x80 || + ((unsigned char)s[0] == 0xE0 && + (unsigned char)s[1] < 0xA0) || + ((unsigned char)s[0] == 0xED && + (unsigned char)s[1] > 0x9F)) { + errmsg = "invalid continuation byte"; startinpos = s-starts; - endinpos = startinpos+3; + endinpos = startinpos + 1; + + /* if s[1] first two bits are 1 and 0, then the invalid + continuation byte is s[2], so increment endinpos by 1, + if not, s[1] is invalid and endinpos doesn't need to + be incremented. */ + if ((s[1] & 0xC0) == 0x80) + endinpos++; goto utf8Error; } ch = ((s[0] & 0x0f) << 12) + ((s[1] & 0x3f) << 6) + (s[2] & 0x3f); - if (ch < 0x0800 || (ch >= 0xd800 && ch <= 0xDFFF)) { - errmsg = "illegal encoding"; - startinpos = s-starts; - endinpos = startinpos+3; - goto utf8Error; - } - else - *p++ = (Py_UNICODE)ch; + assert ((ch > 0x07FF) && (ch <= 0xFFFF)); + *p++ = (Py_UNICODE)ch; break; case 4: if ((s[1] & 0xc0) != 0x80 || (s[2] & 0xc0) != 0x80 || - (s[3] & 0xc0) != 0x80) { - errmsg = "invalid data"; + (s[3] & 0xc0) != 0x80 || + ((unsigned char)s[0] == 0xF0 && + (unsigned char)s[1] < 0x90) || + ((unsigned char)s[0] == 0xF4 && + (unsigned char)s[1] > 0x8F)) { + errmsg = "invalid continuation byte"; startinpos = s-starts; - endinpos = startinpos+4; + endinpos = startinpos + 1; + if ((s[1] & 0xC0) == 0x80) { + endinpos++; + if ((s[2] & 0xC0) == 0x80) + endinpos++; + } goto utf8Error; } ch = ((s[0] & 0x7) << 18) + ((s[1] & 0x3f) << 12) + - ((s[2] & 0x3f) << 6) + (s[3] & 0x3f); - /* validate and convert to UTF-16 */ - if ((ch < 0x10000) /* minimum value allowed for 4 - byte encoding */ - || (ch > 0x10ffff)) /* maximum value allowed for - UTF-16 */ - { - errmsg = "illegal encoding"; - startinpos = s-starts; - endinpos = startinpos+4; - goto utf8Error; - } + ((s[2] & 0x3f) << 6) + (s[3] & 0x3f); + assert ((ch > 0xFFFF) && (ch <= 0x10ffff)); + #ifdef Py_UNICODE_WIDE *p++ = (Py_UNICODE)ch; #else @@ -2508,13 +2515,6 @@ *p++ = (Py_UNICODE)(0xDC00 + (ch & 0x03FF)); #endif break; - - default: - /* Other sizes are only needed for UCS-4 */ - errmsg = "unsupported Unicode code range"; - startinpos = s-starts; - endinpos = startinpos+n; - goto utf8Error; } s += n; continue; From python-checkins at python.org Thu Jul 1 17:07:15 2010 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 1 Jul 2010 17:07:15 +0200 (CEST) Subject: [Python-checkins] r82415 - python/trunk/Doc/library/math.rst Message-ID: <20100701150715.51429F6915@mail.python.org> Author: benjamin.peterson Date: Thu Jul 1 17:07:15 2010 New Revision: 82415 Log: remove docs about delegating to special methods; it does no such thing Modified: python/trunk/Doc/library/math.rst Modified: python/trunk/Doc/library/math.rst ============================================================================== --- python/trunk/Doc/library/math.rst (original) +++ python/trunk/Doc/library/math.rst Thu Jul 1 17:07:15 2010 @@ -57,9 +57,6 @@ Return the floor of *x* as a float, the largest integer value less than or equal to *x*. - .. versionchanged:: 2.6 - Added :meth:`__floor__` delegation. - .. function:: fmod(x, y) @@ -137,7 +134,7 @@ .. function:: trunc(x) Return the :class:`Real` value *x* truncated to an :class:`Integral` (usually - a long integer). Delegates to ``x.__trunc__()``. + a long integer). .. versionadded:: 2.6 From python-checkins at python.org Thu Jul 1 17:09:15 2010 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 1 Jul 2010 17:09:15 +0200 (CEST) Subject: [Python-checkins] r82416 - python/branches/py3k Message-ID: <20100701150915.09235EEB64@mail.python.org> Author: benjamin.peterson Date: Thu Jul 1 17:09:14 2010 New Revision: 82416 Log: Blocked revisions 82415 via svnmerge ........ r82415 | benjamin.peterson | 2010-07-01 10:07:15 -0500 (Thu, 01 Jul 2010) | 1 line remove docs about delegating to special methods; it does no such thing ........ Modified: python/branches/py3k/ (props changed) From python-checkins at python.org Thu Jul 1 17:16:55 2010 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 1 Jul 2010 17:16:55 +0200 (CEST) Subject: [Python-checkins] r82417 - in python/branches/py3k: Lib/test/test_descr.py Misc/NEWS Modules/mathmodule.c Message-ID: <20100701151655.6E378EEBB1@mail.python.org> Author: benjamin.peterson Date: Thu Jul 1 17:16:55 2010 New Revision: 82417 Log: correctly lookup __trunc__ and __floor__ Modified: python/branches/py3k/Lib/test/test_descr.py python/branches/py3k/Misc/NEWS python/branches/py3k/Modules/mathmodule.c Modified: python/branches/py3k/Lib/test/test_descr.py ============================================================================== --- python/branches/py3k/Lib/test/test_descr.py (original) +++ python/branches/py3k/Lib/test/test_descr.py Thu Jul 1 17:16:55 2010 @@ -1,6 +1,7 @@ import builtins import sys import types +import math import unittest from copy import deepcopy @@ -1578,6 +1579,8 @@ ("__exit__", run_context, swallow, set(), {"__enter__" : iden}), ("__complex__", complex, complex_num, set(), {}), ("__format__", format, format_impl, set(), {}), + ("__floor__", math.floor, zero, set(), {}), + ("__trunc__", math.trunc, zero, set(), {}), ] class Checker(object): Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Thu Jul 1 17:16:55 2010 @@ -1374,6 +1374,9 @@ Extension Modules ----------------- +- In the math module, correctly lookup __trunc__ and __floor__ as special + methods. + - Issue #9005: Prevent utctimetuple() from producing year 0 or year 10,000. Prior to this change, timezone adjustment in utctimetuple() could produce tm_year value of 0 or 10,000. Now an OverflowError is Modified: python/branches/py3k/Modules/mathmodule.c ============================================================================== --- python/branches/py3k/Modules/mathmodule.c (original) +++ python/branches/py3k/Modules/mathmodule.c Thu Jul 1 17:16:55 2010 @@ -883,17 +883,13 @@ static PyObject *floor_str = NULL; PyObject *method; - if (floor_str == NULL) { - floor_str = PyUnicode_InternFromString("__floor__"); - if (floor_str == NULL) + method = _PyObject_LookupSpecial(number, "__floor__", &floor_str); + if (method == NULL) { + if (PyErr_Occurred()) return NULL; - } - - method = _PyType_Lookup(Py_TYPE(number), floor_str); - if (method == NULL) return math_1_to_int(number, floor, 0); - else - return PyObject_CallFunction(method, "O", number); + } + return PyObject_CallFunctionObjArgs(method, NULL); } PyDoc_STRVAR(math_floor_doc, @@ -1427,20 +1423,15 @@ return NULL; } - if (trunc_str == NULL) { - trunc_str = PyUnicode_InternFromString("__trunc__"); - if (trunc_str == NULL) - return NULL; - } - - trunc = _PyType_Lookup(Py_TYPE(number), trunc_str); + trunc = _PyObject_LookupSpecial(number, "__trunc__", &trunc_str); if (trunc == NULL) { - PyErr_Format(PyExc_TypeError, - "type %.100s doesn't define __trunc__ method", - Py_TYPE(number)->tp_name); + if (!PyErr_Occurred()) + PyErr_Format(PyExc_TypeError, + "type %.100s doesn't define __trunc__ method", + Py_TYPE(number)->tp_name); return NULL; } - return PyObject_CallFunctionObjArgs(trunc, number, NULL); + return PyObject_CallFunctionObjArgs(trunc, NULL); } PyDoc_STRVAR(math_trunc_doc, From python-checkins at python.org Thu Jul 1 18:16:24 2010 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 1 Jul 2010 18:16:24 +0200 (CEST) Subject: [Python-checkins] r82418 - in python/branches/release26-maint: Doc/library/math.rst Message-ID: <20100701161624.EE662F692F@mail.python.org> Author: benjamin.peterson Date: Thu Jul 1 18:16:24 2010 New Revision: 82418 Log: Merged revisions 82415 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r82415 | benjamin.peterson | 2010-07-01 10:07:15 -0500 (Thu, 01 Jul 2010) | 1 line remove docs about delegating to special methods; it does no such thing ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Doc/library/math.rst Modified: python/branches/release26-maint/Doc/library/math.rst ============================================================================== --- python/branches/release26-maint/Doc/library/math.rst (original) +++ python/branches/release26-maint/Doc/library/math.rst Thu Jul 1 18:16:24 2010 @@ -57,9 +57,6 @@ Return the floor of *x* as a float, the largest integer value less than or equal to *x*. - .. versionchanged:: 2.6 - Added :meth:`__floor__` delegation. - .. function:: fmod(x, y) @@ -137,7 +134,7 @@ .. function:: trunc(x) Return the :class:`Real` value *x* truncated to an :class:`Integral` (usually - a long integer). Delegates to ``x.__trunc__()``. + a long integer). .. versionadded:: 2.6 From python-checkins at python.org Thu Jul 1 18:16:35 2010 From: python-checkins at python.org (alexander.belopolsky) Date: Thu, 1 Jul 2010 18:16:35 +0200 (CEST) Subject: [Python-checkins] r82419 - in sandbox/branches/py3k-datetime: datetime.py test_datetime.py Message-ID: <20100701161635.88A6CEED3A@mail.python.org> Author: alexander.belopolsky Date: Thu Jul 1 18:16:35 2010 New Revision: 82419 Log: Fixed pickling to pass a more rigid test suit. Modified: sandbox/branches/py3k-datetime/datetime.py sandbox/branches/py3k-datetime/test_datetime.py Modified: sandbox/branches/py3k-datetime/datetime.py ============================================================================== --- sandbox/branches/py3k-datetime/datetime.py (original) +++ sandbox/branches/py3k-datetime/datetime.py Thu Jul 1 18:16:35 2010 @@ -269,6 +269,8 @@ raise ValueError("%s()=%d, must be in -1439..1439" % (name, offset)) def _check_date_fields(year, month, day): + if not isinstance(year, int): + raise TypeError('int expected') if not MINYEAR <= year <= MAXYEAR: raise ValueError('year must be in %d..%d' % (MINYEAR, MAXYEAR), year) if not 1 <= month <= 12: @@ -278,6 +280,8 @@ raise ValueError('day must be in 1..%d' % dim, day) def _check_time_fields(hour, minute, second, microsecond): + if not isinstance(hour, int): + raise TypeError('int expected') if not 0 <= hour <= 23: raise ValueError('hour must be in 0..23', hour) if not 0 <= minute <= 59: @@ -660,7 +664,7 @@ year, month, day (required, base 1) """ - if isinstance(year, bytes): + if isinstance(year, bytes) and len(year) == 4: # Pickle support self = object.__new__(cls) self.__setstate(year) @@ -1008,7 +1012,7 @@ tzinfo (default to None) """ self = object.__new__(cls) - if isinstance(hour, str): + if isinstance(hour, bytes) and len(hour) == 6: # Pickle support self.__setstate(hour, minute or None) return self @@ -1256,18 +1260,18 @@ def __getstate(self): us2, us3 = divmod(self.__microsecond, 256) us1, us2 = divmod(us2, 256) - basestate = ("%c" * 6) % (self.__hour, self.__minute, self.__second, - us1, us2, us3) + basestate = bytes([self.__hour, self.__minute, self.__second, + us1, us2, us3]) if self._tzinfo is None: return (basestate,) else: return (basestate, self._tzinfo) def __setstate(self, string, tzinfo): - if len(string) != 6 or ord(string[0]) >= 24: + if len(string) != 6 or string[0] >= 24: raise TypeError("an integer is required") - self.__hour, self.__minute, self.__second, us1, us2, us3 = \ - map(ord, string) + (self.__hour, self.__minute, self.__second, + us1, us2, us3) = string self.__microsecond = (((us1 << 8) | us2) << 8) | us3 self._tzinfo = tzinfo @@ -1287,7 +1291,7 @@ def __new__(cls, year, month=None, day=None, hour=0, minute=0, second=0, microsecond=0, tzinfo=None): - if isinstance(year, bytes): + if isinstance(year, bytes) and len(year) == 10: # Pickle support self = date.__new__(cls, year[:4]) self.__setstate(year, month) Modified: sandbox/branches/py3k-datetime/test_datetime.py ============================================================================== --- sandbox/branches/py3k-datetime/test_datetime.py (original) +++ sandbox/branches/py3k-datetime/test_datetime.py Thu Jul 1 18:16:35 2010 @@ -261,6 +261,33 @@ t.replace(tzinfo=tz).dst()) ############################################################################# +# Base clase for testing pickling state of timedelta, time, date and +# datetime instances. + +class ReduceStructure: + initargs = 1, 1, 1 + statetype = (bytes, tzinfo) + def test_reduce(self): + obj = self.theclass(*self.initargs) + factory, state = obj.__reduce__()[:2] + self.assertIs(factory, self.theclass) + for v, t in zip(state, self.statetype): + self.assertIsInstance(v, t) + + def test_construct_from_state(self): + obj = self.theclass(*self.initargs) + factory, state = obj.__reduce__()[:2] + initbytes = state[0] + # This test should be overriden in tests for classes that + # don't produce their state as bytes. Curently, timedelta + # and timezone + assert isinstance(initbytes, bytes) + obj = factory(initbytes) + self.assertIs(type(obj), self.theclass) + self.assertRaises(TypeError, factory, initbytes[:-1]) + self.assertRaises(TypeError, factory, initbytes + b'x') + +############################################################################# # Base clase for testing a particular aspect of timedelta, time, date and # datetime comparisons. @@ -297,10 +324,10 @@ ############################################################################# # timedelta tests -class TestTimeDelta(HarmlessMixedComparison, unittest.TestCase): +class TestTimeDelta(HarmlessMixedComparison, ReduceStructure, unittest.TestCase): theclass = timedelta - + statetype = (int, int, int) def test_constructor(self): eq = self.assertEqual td = timedelta @@ -326,6 +353,9 @@ eq(td(seconds=0.001), td(milliseconds=1)) eq(td(milliseconds=0.001), td(microseconds=1)) + def test_construct_from_state(self): + pass + def test_computations(self): eq = self.assertEqual td = timedelta @@ -758,11 +788,12 @@ class SubclassDate(date): sub_var = 1 -class TestDate(HarmlessMixedComparison, unittest.TestCase): +class TestDate(HarmlessMixedComparison, ReduceStructure, unittest.TestCase): # Tests here should pass for both dates and datetimes, except for a # few tests that TestDateTime overrides. theclass = date + statetype = (bytes,) def test_basic_attributes(self): dt = self.theclass(2002, 3, 1) @@ -1387,6 +1418,7 @@ class TestDateTime(TestDate): theclass = datetime + statetype = (bytes, tzinfo) def test_basic_attributes(self): dt = self.theclass(2002, 3, 1, 12, 0) @@ -1735,6 +1767,8 @@ # than one microsecond smaller than an integer. self.assertEqual(self.theclass.fromtimestamp(0.9999999), self.theclass.fromtimestamp(1)) + self.assertEqual(self.theclass.utcfromtimestamp(0.9999999), + self.theclass.utcfromtimestamp(1)) def test_insane_fromtimestamp(self): # It's possible that some platform maps time_t to double, @@ -1962,7 +1996,7 @@ class SubclassTime(time): sub_var = 1 -class TestTime(HarmlessMixedComparison, unittest.TestCase): +class TestTime(HarmlessMixedComparison, ReduceStructure, unittest.TestCase): theclass = time From python-checkins at python.org Thu Jul 1 19:45:52 2010 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 1 Jul 2010 19:45:52 +0200 (CEST) Subject: [Python-checkins] r82420 - python/trunk/Doc/library/2to3.rst Message-ID: <20100701174552.DC93FEEB23@mail.python.org> Author: benjamin.peterson Date: Thu Jul 1 19:45:52 2010 New Revision: 82420 Log: fix fixer name Modified: python/trunk/Doc/library/2to3.rst Modified: python/trunk/Doc/library/2to3.rst ============================================================================== --- python/trunk/Doc/library/2to3.rst (original) +++ python/trunk/Doc/library/2to3.rst Thu Jul 1 19:45:52 2010 @@ -276,7 +276,7 @@ Converts the :keyword:`print` statement to the :func:`print` function. -.. 2to3fixer:: raises +.. 2to3fixer:: raise Converts ``raise E, V`` to ``raise E(V)``, and ``raise E, V, T`` to ``raise E(V).with_traceback(T)``. If ``E`` is a tuple, the translation will be From python-checkins at python.org Thu Jul 1 19:48:17 2010 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 1 Jul 2010 19:48:17 +0200 (CEST) Subject: [Python-checkins] r82421 - in python/branches/release26-maint: Doc/library/2to3.rst Message-ID: <20100701174817.2423AEE9F4@mail.python.org> Author: benjamin.peterson Date: Thu Jul 1 19:48:16 2010 New Revision: 82421 Log: Merged revisions 82420 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r82420 | benjamin.peterson | 2010-07-01 12:45:52 -0500 (Thu, 01 Jul 2010) | 1 line fix fixer name ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Doc/library/2to3.rst Modified: python/branches/release26-maint/Doc/library/2to3.rst ============================================================================== --- python/branches/release26-maint/Doc/library/2to3.rst (original) +++ python/branches/release26-maint/Doc/library/2to3.rst Thu Jul 1 19:48:16 2010 @@ -276,7 +276,7 @@ Converts the :keyword:`print` statement to the :func:`print` function. -.. 2to3fixer:: raises +.. 2to3fixer:: raise Converts ``raise E, V`` to ``raise E(V)``, and ``raise E, V, T`` to ``raise E(V).with_traceback(T)``. If ``E`` is a tuple, the translation will be From python-checkins at python.org Thu Jul 1 19:49:01 2010 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 1 Jul 2010 19:49:01 +0200 (CEST) Subject: [Python-checkins] r82422 - in python/branches/py3k: Doc/library/2to3.rst Message-ID: <20100701174901.61836EEA84@mail.python.org> Author: benjamin.peterson Date: Thu Jul 1 19:49:01 2010 New Revision: 82422 Log: Merged revisions 82420 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r82420 | benjamin.peterson | 2010-07-01 12:45:52 -0500 (Thu, 01 Jul 2010) | 1 line fix fixer name ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Doc/library/2to3.rst Modified: python/branches/py3k/Doc/library/2to3.rst ============================================================================== --- python/branches/py3k/Doc/library/2to3.rst (original) +++ python/branches/py3k/Doc/library/2to3.rst Thu Jul 1 19:49:01 2010 @@ -276,7 +276,7 @@ Converts the :keyword:`print` statement to the :func:`print` function. -.. 2to3fixer:: raises +.. 2to3fixer:: raise Converts ``raise E, V`` to ``raise E(V)``, and ``raise E, V, T`` to ``raise E(V).with_traceback(T)``. If ``E`` is a tuple, the translation will be From python-checkins at python.org Thu Jul 1 19:51:42 2010 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 1 Jul 2010 19:51:42 +0200 (CEST) Subject: [Python-checkins] r82423 - in python/branches/release31-maint: Doc/library/2to3.rst Message-ID: <20100701175142.879D4EEA65@mail.python.org> Author: benjamin.peterson Date: Thu Jul 1 19:51:42 2010 New Revision: 82423 Log: Merged revisions 82422 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ................ r82422 | benjamin.peterson | 2010-07-01 12:49:01 -0500 (Thu, 01 Jul 2010) | 9 lines Merged revisions 82420 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r82420 | benjamin.peterson | 2010-07-01 12:45:52 -0500 (Thu, 01 Jul 2010) | 1 line fix fixer name ........ ................ Modified: python/branches/release31-maint/ (props changed) python/branches/release31-maint/Doc/library/2to3.rst Modified: python/branches/release31-maint/Doc/library/2to3.rst ============================================================================== --- python/branches/release31-maint/Doc/library/2to3.rst (original) +++ python/branches/release31-maint/Doc/library/2to3.rst Thu Jul 1 19:51:42 2010 @@ -276,7 +276,7 @@ Converts the :keyword:`print` statement to the :func:`print` function. -.. 2to3fixer:: raises +.. 2to3fixer:: raise Converts ``raise E, V`` to ``raise E(V)``, and ``raise E, V, T`` to ``raise E(V).with_traceback(T)``. If ``E`` is a tuple, the translation will be From python-checkins at python.org Thu Jul 1 21:16:58 2010 From: python-checkins at python.org (alexander.belopolsky) Date: Thu, 1 Jul 2010 21:16:58 +0200 (CEST) Subject: [Python-checkins] r82424 - sandbox/branches/py3k-datetime/datetime.py Message-ID: <20100701191658.3B67CEE9A4@mail.python.org> Author: alexander.belopolsky Date: Thu Jul 1 21:16:58 2010 New Revision: 82424 Log: added __slots__ specifications Modified: sandbox/branches/py3k-datetime/datetime.py Modified: sandbox/branches/py3k-datetime/datetime.py ============================================================================== --- sandbox/branches/py3k-datetime/datetime.py (original) +++ sandbox/branches/py3k-datetime/datetime.py Thu Jul 1 21:16:58 2010 @@ -316,6 +316,7 @@ Representation: (days, seconds, microseconds). Why? Because I felt like it. """ + __slots__ = '__days', '__seconds', '__microseconds' def __new__(cls, days=0, seconds=0, microseconds=0, # XXX The following should only be used as keyword args: @@ -656,6 +657,7 @@ Properties (readonly): year, month, day """ + __slots__ = '__year', '__month', '__day' def __new__(cls, year, month=None, day=None): """Constructor. @@ -916,7 +918,7 @@ Subclasses must override the name(), utcoffset() and dst() methods. """ - + __slots__ = () def tzname(self, dt): "datetime -> string name of time zone." raise NotImplementedError("tzinfo subclass must override tzname()") @@ -1289,6 +1291,9 @@ # XXX needs docstrings # See http://www.zope.org/Members/fdrake/DateTimeWiki/TimeZoneInfo + __slots__ = date.__slots__ + ( + '__hour', '__minute', '__second', + '__microsecond', '_tzinfo') def __new__(cls, year, month=None, day=None, hour=0, minute=0, second=0, microsecond=0, tzinfo=None): if isinstance(year, bytes) and len(year) == 10: @@ -1765,6 +1770,8 @@ return week1monday class timezone(tzinfo): + __slots__ = '__offset', '__name' + def __init__(self, offset, *args): # Reproduce C behavior n = len(args) From python-checkins at python.org Thu Jul 1 22:10:47 2010 From: python-checkins at python.org (ezio.melotti) Date: Thu, 1 Jul 2010 22:10:47 +0200 (CEST) Subject: [Python-checkins] r82425 - in tracker/instances/python-dev/html: issue.item.html issue.search.html page.html Message-ID: <20100701201047.DA893EE98A@mail.python.org> Author: ezio.melotti Date: Thu Jul 1 22:10:47 2010 New Revision: 82425 Log: #343: Remove the "(list)" for superseder and dependencies. Modified: tracker/instances/python-dev/html/issue.item.html tracker/instances/python-dev/html/issue.search.html tracker/instances/python-dev/html/page.html Modified: tracker/instances/python-dev/html/issue.item.html ============================================================================== --- tracker/instances/python-dev/html/issue.item.html (original) +++ tracker/instances/python-dev/html/issue.item.html Thu Jul 1 22:10:47 2010 @@ -93,8 +93,8 @@ Dependencies: - + @@ -104,8 +104,8 @@ Superseder: - + Modified: tracker/instances/python-dev/html/issue.search.html ============================================================================== --- tracker/instances/python-dev/html/issue.search.html (original) +++ tracker/instances/python-dev/html/issue.search.html Thu Jul 1 22:10:47 2010 @@ -42,6 +42,15 @@   + + Ignore attachments: + +   +   +   + + Title: Modified: tracker/instances/python-dev/html/page.html ============================================================================== --- tracker/instances/python-dev/html/page.html (original) +++ tracker/instances/python-dev/html/page.html Thu Jul 1 22:10:47 2010 @@ -42,6 +42,7 @@ + @@ -145,7 +146,8 @@ })" i18n:translate="">Show Having Patch
  • - Search + Search
  • From python-checkins at python.org Thu Jul 1 22:16:23 2010 From: python-checkins at python.org (ezio.melotti) Date: Thu, 1 Jul 2010 22:16:23 +0200 (CEST) Subject: [Python-checkins] r82426 - in tracker/instances/python-dev/html: issue.search.html page.html Message-ID: <20100701201623.64B72EE98A@mail.python.org> Author: ezio.melotti Date: Thu Jul 1 22:16:23 2010 New Revision: 82426 Log: Revert accidental changes in two files that were unrelated. Modified: tracker/instances/python-dev/html/issue.search.html tracker/instances/python-dev/html/page.html Modified: tracker/instances/python-dev/html/issue.search.html ============================================================================== --- tracker/instances/python-dev/html/issue.search.html (original) +++ tracker/instances/python-dev/html/issue.search.html Thu Jul 1 22:16:23 2010 @@ -42,15 +42,6 @@   - - Ignore attachments: - -   -   -   - - Title: Modified: tracker/instances/python-dev/html/page.html ============================================================================== --- tracker/instances/python-dev/html/page.html (original) +++ tracker/instances/python-dev/html/page.html Thu Jul 1 22:16:23 2010 @@ -42,7 +42,6 @@ - @@ -146,8 +145,7 @@ })" i18n:translate="">Show Having Patch
  • - Search + Search
  • From python-checkins at python.org Thu Jul 1 22:23:17 2010 From: python-checkins at python.org (ezio.melotti) Date: Thu, 1 Jul 2010 22:23:17 +0200 (CEST) Subject: [Python-checkins] r82427 - tracker/instances/python-dev/html/issue.item.html Message-ID: <20100701202317.8EDC5D2CC@mail.python.org> Author: ezio.melotti Date: Thu Jul 1 22:23:17 2010 New Revision: 82427 Log: #251: Remove the nosy count from the issue page. Modified: tracker/instances/python-dev/html/issue.item.html Modified: tracker/instances/python-dev/html/issue.item.html ============================================================================== --- tracker/instances/python-dev/html/issue.item.html (original) +++ tracker/instances/python-dev/html/issue.item.html Thu Jul 1 22:23:17 2010 @@ -135,7 +135,7 @@ - Nosy List: + Nosy List: From python-checkins at python.org Thu Jul 1 22:26:54 2010 From: python-checkins at python.org (ezio.melotti) Date: Thu, 1 Jul 2010 22:26:54 +0200 (CEST) Subject: [Python-checkins] r82428 - tracker/instances/python-dev/html/issue.item.html Message-ID: <20100701202654.A3D90EDB4@mail.python.org> Author: ezio.melotti Date: Thu Jul 1 22:26:54 2010 New Revision: 82428 Log: Remove trailing whitespace and add a missing colon after "Keywords". Modified: tracker/instances/python-dev/html/issue.item.html Modified: tracker/instances/python-dev/html/issue.item.html ============================================================================== --- tracker/instances/python-dev/html/issue.item.html (original) +++ tracker/instances/python-dev/html/issue.item.html Thu Jul 1 22:26:54 2010 @@ -116,8 +116,8 @@ tal:attributes="href string:issue${sup/id}; title sup/title;"> -->
    View: -
    + tal:attributes="href string:issue${context/superseder/id}; title context/superseder/title;"> +
    @@ -126,7 +126,7 @@ - + copy of B\n\ \n\ -Return a copy of B with only its first character capitalized (ASCII)."); +Return a copy of B with only its first character capitalized (ASCII)\n\ +and the rest lower-cased."); void _Py_bytes_capitalize(char *result, char *s, Py_ssize_t len) Modified: python/branches/py3k/Objects/unicodeobject.c ============================================================================== --- python/branches/py3k/Objects/unicodeobject.c (original) +++ python/branches/py3k/Objects/unicodeobject.c Mon Jul 5 14:00:56 2010 @@ -6705,7 +6705,7 @@ "S.capitalize() -> str\n\ \n\ Return a capitalized version of S, i.e. make the first character\n\ -have upper case."); +have upper case and the rest lower case."); static PyObject* unicode_capitalize(PyUnicodeObject *self) From python-checkins at python.org Mon Jul 5 14:04:08 2010 From: python-checkins at python.org (senthil.kumaran) Date: Mon, 5 Jul 2010 14:04:08 +0200 (CEST) Subject: [Python-checkins] r82574 - in python/branches/release27-maint: Objects/bytes_methods.c Objects/unicodeobject.c Message-ID: <20100705120408.1C854EE99A@mail.python.org> Author: senthil.kumaran Date: Mon Jul 5 14:04:07 2010 New Revision: 82574 Log: Merged revisions 82573 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ........ r82573 | senthil.kumaran | 2010-07-05 17:30:56 +0530 (Mon, 05 Jul 2010) | 3 lines Fix the docstrings of the capitalize method. ........ Modified: python/branches/release27-maint/ (props changed) python/branches/release27-maint/Objects/bytes_methods.c python/branches/release27-maint/Objects/unicodeobject.c Modified: python/branches/release27-maint/Objects/bytes_methods.c ============================================================================== --- python/branches/release27-maint/Objects/bytes_methods.c (original) +++ python/branches/release27-maint/Objects/bytes_methods.c Mon Jul 5 14:04:07 2010 @@ -332,7 +332,8 @@ PyDoc_STRVAR_shared(_Py_capitalize__doc__, "B.capitalize() -> copy of B\n\ \n\ -Return a copy of B with only its first character capitalized (ASCII)."); +Return a copy of B with only its first character capitalized (ASCII)\n\ +and the rest lower-cased."); void _Py_bytes_capitalize(char *result, char *s, Py_ssize_t len) Modified: python/branches/release27-maint/Objects/unicodeobject.c ============================================================================== --- python/branches/release27-maint/Objects/unicodeobject.c (original) +++ python/branches/release27-maint/Objects/unicodeobject.c Mon Jul 5 14:04:07 2010 @@ -5938,7 +5938,7 @@ "S.capitalize() -> unicode\n\ \n\ Return a capitalized version of S, i.e. make the first character\n\ -have upper case."); +have upper case and the rest lower case."); static PyObject* unicode_capitalize(PyUnicodeObject *self) From python-checkins at python.org Mon Jul 5 14:04:24 2010 From: python-checkins at python.org (senthil.kumaran) Date: Mon, 5 Jul 2010 14:04:24 +0200 (CEST) Subject: [Python-checkins] r82575 - in python/branches/release31-maint: Objects/bytes_methods.c Objects/unicodeobject.c Message-ID: <20100705120424.2673FF4B4@mail.python.org> Author: senthil.kumaran Date: Mon Jul 5 14:04:23 2010 New Revision: 82575 Log: Merged revisions 82573 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ........ r82573 | senthil.kumaran | 2010-07-05 17:30:56 +0530 (Mon, 05 Jul 2010) | 3 lines Fix the docstrings of the capitalize method. ........ Modified: python/branches/release31-maint/ (props changed) python/branches/release31-maint/Objects/bytes_methods.c python/branches/release31-maint/Objects/unicodeobject.c Modified: python/branches/release31-maint/Objects/bytes_methods.c ============================================================================== --- python/branches/release31-maint/Objects/bytes_methods.c (original) +++ python/branches/release31-maint/Objects/bytes_methods.c Mon Jul 5 14:04:23 2010 @@ -332,7 +332,8 @@ PyDoc_STRVAR_shared(_Py_capitalize__doc__, "B.capitalize() -> copy of B\n\ \n\ -Return a copy of B with only its first character capitalized (ASCII)."); +Return a copy of B with only its first character capitalized (ASCII)\n\ +and the rest lower-cased."); void _Py_bytes_capitalize(char *result, char *s, Py_ssize_t len) Modified: python/branches/release31-maint/Objects/unicodeobject.c ============================================================================== --- python/branches/release31-maint/Objects/unicodeobject.c (original) +++ python/branches/release31-maint/Objects/unicodeobject.c Mon Jul 5 14:04:23 2010 @@ -6766,7 +6766,7 @@ "S.capitalize() -> str\n\ \n\ Return a capitalized version of S, i.e. make the first character\n\ -have upper case."); +have upper case and the rest lower case."); static PyObject* unicode_capitalize(PyUnicodeObject *self) From python-checkins at python.org Mon Jul 5 16:59:41 2010 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 5 Jul 2010 16:59:41 +0200 (CEST) Subject: [Python-checkins] r82576 - python/branches/py3k/Lib/test/test_imp.py Message-ID: <20100705145941.1F407EBB7@mail.python.org> Author: benjamin.peterson Date: Mon Jul 5 16:59:40 2010 New Revision: 82576 Log: pydoc still has a silly encoding Modified: python/branches/py3k/Lib/test/test_imp.py Modified: python/branches/py3k/Lib/test/test_imp.py ============================================================================== --- python/branches/py3k/Lib/test/test_imp.py (original) +++ python/branches/py3k/Lib/test/test_imp.py Mon Jul 5 16:59:40 2010 @@ -44,7 +44,7 @@ class ImportTests(unittest.TestCase): def test_find_module_encoding(self): - fd = imp.find_module("heapq")[0] + fd = imp.find_module("pydoc")[0] self.assertEqual(fd.encoding, "iso-8859-1") def test_issue1267(self): From python-checkins at python.org Mon Jul 5 17:01:22 2010 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 5 Jul 2010 17:01:22 +0200 (CEST) Subject: [Python-checkins] r82577 - python/branches/py3k/Objects/typeobject.c Message-ID: <20100705150122.A246AF061@mail.python.org> Author: benjamin.peterson Date: Mon Jul 5 17:01:22 2010 New Revision: 82577 Log: cleanup basicsize logic #3268 Modified: python/branches/py3k/Objects/typeobject.c Modified: python/branches/py3k/Objects/typeobject.c ============================================================================== --- python/branches/py3k/Objects/typeobject.c (original) +++ python/branches/py3k/Objects/typeobject.c Mon Jul 5 17:01:22 2010 @@ -3476,11 +3476,8 @@ static void inherit_special(PyTypeObject *type, PyTypeObject *base) { - Py_ssize_t oldsize, newsize; /* Copying basicsize is connected to the GC flags */ - oldsize = base->tp_basicsize; - newsize = type->tp_basicsize ? type->tp_basicsize : oldsize; if (!(type->tp_flags & Py_TPFLAGS_HAVE_GC) && (base->tp_flags & Py_TPFLAGS_HAVE_GC) && (!type->tp_traverse && !type->tp_clear)) { @@ -3507,7 +3504,8 @@ type->tp_new = base->tp_new; } } - type->tp_basicsize = newsize; + if (type->tp_basicsize == 0) + type->tp_basicsize = base->tp_basicsize; /* Copy other non-function slots */ From python-checkins at python.org Mon Jul 5 17:05:34 2010 From: python-checkins at python.org (alexander.belopolsky) Date: Mon, 5 Jul 2010 17:05:34 +0200 (CEST) Subject: [Python-checkins] r82578 - python/branches/py3k/Lib/test/test_datetime.py Message-ID: <20100705150534.05EABF134@mail.python.org> Author: alexander.belopolsky Date: Mon Jul 5 17:05:33 2010 New Revision: 82578 Log: Added more tests for utctimetuple() Modified: python/branches/py3k/Lib/test/test_datetime.py Modified: python/branches/py3k/Lib/test/test_datetime.py ============================================================================== --- python/branches/py3k/Lib/test/test_datetime.py (original) +++ python/branches/py3k/Lib/test/test_datetime.py Mon Jul 5 17:05:33 2010 @@ -3008,7 +3008,7 @@ def test_utctimetuple(self): class DST(tzinfo): - def __init__(self, dstvalue): + def __init__(self, dstvalue=0): if isinstance(dstvalue, int): dstvalue = timedelta(minutes=dstvalue) self.dstvalue = dstvalue @@ -3043,6 +3043,26 @@ # is never in effect for a UTC time. self.assertEqual(0, t.tm_isdst) + # For naive datetime, utctimetuple == timetuple except for isdst + d = cls(1, 2, 3, 10, 20, 30, 40) + t = d.utctimetuple() + self.assertEqual(t[:-1], d.timetuple()[:-1]) + self.assertEqual(0, t.tm_isdst) + # Same if utcoffset is None + class NOFS(DST): + def utcoffset(self, dt): + return None + d = cls(1, 2, 3, 10, 20, 30, 40, tzinfo=NOFS()) + t = d.utctimetuple() + self.assertEqual(t[:-1], d.timetuple()[:-1]) + self.assertEqual(0, t.tm_isdst) + # Check that bad tzinfo is detected + class BOFS(DST): + def utcoffset(self, dt): + return "EST" + d = cls(1, 2, 3, 10, 20, 30, 40, tzinfo=BOFS()) + self.assertRaises(TypeError, d.utctimetuple) + # Check that utctimetuple() is the same as # astimezone(utc).timetuple() d = cls(2010, 11, 13, 14, 15, 16, 171819) From python-checkins at python.org Mon Jul 5 17:26:36 2010 From: python-checkins at python.org (alexander.belopolsky) Date: Mon, 5 Jul 2010 17:26:36 +0200 (CEST) Subject: [Python-checkins] r82579 - in python/branches/release31-maint: Lib/test/test_datetime.py Message-ID: <20100705152636.89BE1EC35@mail.python.org> Author: alexander.belopolsky Date: Mon Jul 5 17:26:36 2010 New Revision: 82579 Log: Merged revisions 82578 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ........ r82578 | alexander.belopolsky | 2010-07-05 11:05:33 -0400 (Mon, 05 Jul 2010) | 1 line Added more tests for utctimetuple() ........ Modified: python/branches/release31-maint/ (props changed) python/branches/release31-maint/Lib/test/test_datetime.py Modified: python/branches/release31-maint/Lib/test/test_datetime.py ============================================================================== --- python/branches/release31-maint/Lib/test/test_datetime.py (original) +++ python/branches/release31-maint/Lib/test/test_datetime.py Mon Jul 5 17:26:36 2010 @@ -2738,7 +2738,7 @@ def test_utctimetuple(self): class DST(tzinfo): - def __init__(self, dstvalue): + def __init__(self, dstvalue=0): if isinstance(dstvalue, int): dstvalue = timedelta(minutes=dstvalue) self.dstvalue = dstvalue @@ -2772,6 +2772,25 @@ self.assertEqual(d.toordinal() - date(1, 1, 1).toordinal() + 1, t.tm_yday) self.assertEqual(0, t.tm_isdst) + # For naive datetime, utctimetuple == timetuple except for isdst + d = cls(1, 2, 3, 10, 20, 30, 40) + t = d.utctimetuple() + self.assertEqual(t[:-1], d.timetuple()[:-1]) + self.assertEqual(0, t.tm_isdst) + # Same if utcoffset is None + class NOFS(DST): + def utcoffset(self, dt): + return None + d = cls(1, 2, 3, 10, 20, 30, 40, tzinfo=NOFS()) + t = d.utctimetuple() + self.assertEqual(t[:-1], d.timetuple()[:-1]) + self.assertEqual(0, t.tm_isdst) + # Check that bad tzinfo is detected + class BOFS(DST): + def utcoffset(self, dt): + return "EST" + d = cls(1, 2, 3, 10, 20, 30, 40, tzinfo=BOFS()) + self.assertRaises(TypeError, d.utctimetuple) # At the edges, UTC adjustment can normalize into years out-of-range # for a datetime object. Ensure that a correct timetuple is From python-checkins at python.org Mon Jul 5 18:06:06 2010 From: python-checkins at python.org (r.david.murray) Date: Mon, 5 Jul 2010 18:06:06 +0200 (CEST) Subject: [Python-checkins] r82581 - in python/branches/release27-maint: Lib/optparse.py Misc/NEWS Message-ID: <20100705160606.14CE1F151@mail.python.org> Author: r.david.murray Date: Mon Jul 5 18:06:05 2010 New Revision: 82581 Log: #9161: Fix regression in acceptance of unicode strings in add_option calls. The original change in 2.6 was made during rc1 changeover, and did not get ported to 2.7. The original change may not even have been intentional, but if so it doesn't seem to have caused any problems. Modified: python/branches/release27-maint/Lib/optparse.py python/branches/release27-maint/Misc/NEWS Modified: python/branches/release27-maint/Lib/optparse.py ============================================================================== --- python/branches/release27-maint/Lib/optparse.py (original) +++ python/branches/release27-maint/Lib/optparse.py Mon Jul 5 18:06:05 2010 @@ -1008,7 +1008,7 @@ """add_option(Option) add_option(opt_str, ..., kwarg=val, ...) """ - if type(args[0]) is types.StringType: + if type(args[0]) in types.StringTypes: option = self.option_class(*args, **kwargs) elif len(args) == 1 and not kwargs: option = args[0] Modified: python/branches/release27-maint/Misc/NEWS ============================================================================== --- python/branches/release27-maint/Misc/NEWS (original) +++ python/branches/release27-maint/Misc/NEWS Mon Jul 5 18:06:05 2010 @@ -16,6 +16,9 @@ Library ------- +- Issue #9161: Fix regression in optparse's acceptance of unicode + strings in add_option calls. + - Issue #9130: Fix validation of relative imports in parser module. - Issue #9128: Fix validation of class decorators in parser module. From python-checkins at python.org Mon Jul 5 18:50:01 2010 From: python-checkins at python.org (georg.brandl) Date: Mon, 5 Jul 2010 18:50:01 +0200 (CEST) Subject: [Python-checkins] r82584 - peps/trunk/pep-0392.txt Message-ID: <20100705165001.CA467EDD9@mail.python.org> Author: georg.brandl Date: Mon Jul 5 18:50:01 2010 New Revision: 82584 Log: Giving back the time machine. Modified: peps/trunk/pep-0392.txt Modified: peps/trunk/pep-0392.txt ============================================================================== --- peps/trunk/pep-0392.txt (original) +++ peps/trunk/pep-0392.txt Mon Jul 5 18:50:01 2010 @@ -43,8 +43,8 @@ - 3.2 beta 2: November 27, 2010 - 3.2 candidate 1: December 11, 2010 -- 3.2 candidate 2: January 1, 2010 -- 3.2 final: January 15, 2010 +- 3.2 candidate 2: January 1, 2011 +- 3.2 final: January 15, 2011 .. don't forget to update final date above as well From python-checkins at python.org Mon Jul 5 19:11:05 2010 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 5 Jul 2010 19:11:05 +0200 (CEST) Subject: [Python-checkins] r82585 - python/branches/py3k/Lib/test/test_math.py Message-ID: <20100705171105.485DDCA1C@mail.python.org> Author: benjamin.peterson Date: Mon Jul 5 19:11:05 2010 New Revision: 82585 Log: looking up on the type is correct, so this isn't an XXX Modified: python/branches/py3k/Lib/test/test_math.py Modified: python/branches/py3k/Lib/test/test_math.py ============================================================================== --- python/branches/py3k/Lib/test/test_math.py (original) +++ python/branches/py3k/Lib/test/test_math.py Mon Jul 5 19:11:05 2010 @@ -923,13 +923,6 @@ self.assertRaises(TypeError, math.trunc, 1, 2) self.assertRaises(TypeError, math.trunc, TestNoTrunc()) - # XXX Doesn't work because the method is looked up on - # the type only. - #t = TestNoTrunc() - #t.__trunc__ = lambda *args: args - #self.assertEquals((), math.trunc(t)) - #self.assertRaises(TypeError, math.trunc, t, 0) - def testIsnan(self): self.assertTrue(math.isnan(float("nan"))) self.assertTrue(math.isnan(float("inf")* 0.)) From python-checkins at python.org Mon Jul 5 19:13:21 2010 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 5 Jul 2010 19:13:21 +0200 (CEST) Subject: [Python-checkins] r82586 - python/branches/release27-maint/Lib/test/test_math.py Message-ID: <20100705171321.B6B67CA1C@mail.python.org> Author: benjamin.peterson Date: Mon Jul 5 19:13:21 2010 New Revision: 82586 Log: be more generous to implementations that have implemented correctly Modified: python/branches/release27-maint/Lib/test/test_math.py Modified: python/branches/release27-maint/Lib/test/test_math.py ============================================================================== --- python/branches/release27-maint/Lib/test/test_math.py (original) +++ python/branches/release27-maint/Lib/test/test_math.py Mon Jul 5 19:13:21 2010 @@ -876,8 +876,8 @@ self.assertRaises(TypeError, math.trunc) self.assertRaises(TypeError, math.trunc, 1, 2) - # XXX: This is not ideal, but see the comment in math_trunc(). - self.assertRaises(AttributeError, math.trunc, TestNoTrunc()) + self.assertRaises((AttributeError, TypeError), math.trunc, + TestNoTrunc()) t = TestNoTrunc() t.__trunc__ = lambda *args: args From python-checkins at python.org Mon Jul 5 19:48:38 2010 From: python-checkins at python.org (georg.brandl) Date: Mon, 5 Jul 2010 19:48:38 +0200 (CEST) Subject: [Python-checkins] r82587 - python/branches/py3k/Doc/whatsnew/2.7.rst Message-ID: <20100705174838.986FEEDD9@mail.python.org> Author: georg.brandl Date: Mon Jul 5 19:48:38 2010 New Revision: 82587 Log: #9166: NotImplemented is not an exception. Modified: python/branches/py3k/Doc/whatsnew/2.7.rst Modified: python/branches/py3k/Doc/whatsnew/2.7.rst ============================================================================== --- python/branches/py3k/Doc/whatsnew/2.7.rst (original) +++ python/branches/py3k/Doc/whatsnew/2.7.rst Mon Jul 5 19:48:38 2010 @@ -1072,7 +1072,7 @@ (Added by Raymond Hettinger; :issue:`1818`.) Finally, the :class:`~collections.Mapping` abstract base class now - raises a :exc:`NotImplemented` exception if a mapping is compared to + returns :const:`NotImplemented` if a mapping is compared to another type that isn't a :class:`Mapping`. (Fixed by Daniel Stutzbach; :issue:`8729`.) From python-checkins at python.org Mon Jul 5 19:50:56 2010 From: python-checkins at python.org (georg.brandl) Date: Mon, 5 Jul 2010 19:50:56 +0200 (CEST) Subject: [Python-checkins] r82588 - in python/branches/release27-maint: Doc/whatsnew/2.7.rst Message-ID: <20100705175056.1EB50EC40@mail.python.org> Author: georg.brandl Date: Mon Jul 5 19:50:55 2010 New Revision: 82588 Log: Merged revisions 82587 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ........ r82587 | georg.brandl | 2010-07-05 19:48:38 +0200 (Mo, 05 Jul 2010) | 1 line #9166: NotImplemented is not an exception. ........ Modified: python/branches/release27-maint/ (props changed) python/branches/release27-maint/Doc/whatsnew/2.7.rst Modified: python/branches/release27-maint/Doc/whatsnew/2.7.rst ============================================================================== --- python/branches/release27-maint/Doc/whatsnew/2.7.rst (original) +++ python/branches/release27-maint/Doc/whatsnew/2.7.rst Mon Jul 5 19:50:55 2010 @@ -1073,7 +1073,7 @@ (Added by Raymond Hettinger; :issue:`1818`.) Finally, the :class:`~collections.Mapping` abstract base class now - raises a :exc:`NotImplemented` exception if a mapping is compared to + returns :const:`NotImplemented` if a mapping is compared to another type that isn't a :class:`Mapping`. (Fixed by Daniel Stutzbach; :issue:`8729`.) From python-checkins at python.org Mon Jul 5 19:57:31 2010 From: python-checkins at python.org (alexander.belopolsky) Date: Mon, 5 Jul 2010 19:57:31 +0200 (CEST) Subject: [Python-checkins] r82589 - python/branches/py3k/Lib/test/test_datetime.py Message-ID: <20100705175731.774D6F197@mail.python.org> Author: alexander.belopolsky Date: Mon Jul 5 19:57:31 2010 New Revision: 82589 Log: Added two more test cases for datetime Modified: python/branches/py3k/Lib/test/test_datetime.py Modified: python/branches/py3k/Lib/test/test_datetime.py ============================================================================== --- python/branches/py3k/Lib/test/test_datetime.py (original) +++ python/branches/py3k/Lib/test/test_datetime.py Mon Jul 5 19:57:31 2010 @@ -881,6 +881,7 @@ def test_computations(self): a = self.theclass(2002, 1, 31) b = self.theclass(1956, 1, 31) + c = self.theclass(2001,2,1) diff = a-b self.assertEqual(diff.days, 46*365 + len(range(1956, 2002, 4))) @@ -906,6 +907,7 @@ self.assertEqual(a - (a + day), -day) self.assertEqual(a - (a - week), week) self.assertEqual(a - (a - day), day) + self.assertEqual(c - (c - day), day) # Add/sub ints or floats should be illegal for i in 1, 1.0: @@ -1347,6 +1349,10 @@ for month_byte in b'9', b'\0', b'\r', b'\xff': self.assertRaises(TypeError, self.theclass, base[:2] + month_byte + base[3:]) + # Good bytes, but bad tzinfo: + self.assertRaises(TypeError, self.theclass, + bytes([1] * len(base)), 'EST') + for ord_byte in range(1, 13): # This shouldn't blow up because of the month byte alone. If # the implementation changes to do more-careful checking, it may From brett at python.org Mon Jul 5 21:22:19 2010 From: brett at python.org (Brett Cannon) Date: Mon, 5 Jul 2010 12:22:19 -0700 Subject: [Python-checkins] r82562 - in sandbox/trunk/pep362: README setup.py tests/test_pep362.py In-Reply-To: <4C314757.2060505@gmail.com> References: <20100704205218.0EEF4F68C9@mail.python.org> <4C314757.2060505@gmail.com> Message-ID: I decided to do a find-and-replace rather than trying to "fix" the method calls with a more proper one. It was just faster and easier. On Sun, Jul 4, 2010 at 19:45, Ezio Melotti wrote: > On 04/07/2010 23.52, brett.cannon wrote: >> >> Author: brett.cannon >> Date: Sun Jul ?4 22:52:17 2010 >> New Revision: 82562 >> >> Log: >> Update to run under Python 2.7 and 3.1 without any warnings. >> >> Modified: >> ? ?sandbox/trunk/pep362/README >> ? ?sandbox/trunk/pep362/setup.py >> ? ?sandbox/trunk/pep362/tests/test_pep362.py >> >> Modified: sandbox/trunk/pep362/README >> >> ============================================================================== >> --- sandbox/trunk/pep362/README (original) >> +++ sandbox/trunk/pep362/README Sun Jul ?4 22:52:17 2010 >> @@ -38,6 +38,11 @@ >> >> ?The version number will get bumped as open issues in the PEP are closed. >> >> +0.6.2 >> +----- >> + >> +* Move test suite over to assert* methods. >> + >> ?0.6 >> ?--- >> >> >> Modified: sandbox/trunk/pep362/setup.py >> >> ============================================================================== >> --- sandbox/trunk/pep362/setup.py ? ? ? (original) >> +++ sandbox/trunk/pep362/setup.py ? ? ? Sun Jul ?4 22:52:17 2010 >> @@ -3,7 +3,7 @@ >> [...] >> ? ? ?@version_specific(2) >> ? ? ?def test_parameter_tuple(self): >> ? ? ? ? ?# A function with a tuple as a parameter should work. >> ? ? ? ? ?sig = pep362.Signature(pep362_py2_fodder.tuple_args) >> - ? ? ? ?self.failUnlessEqual('tuple_args', sig.name) >> + ? ? ? ?self.assertEqual('tuple_args', sig.name) >> ? ? ? ? ?param = list(sig)[0] >> - ? ? ? ?self.failUnless(isinstance(param.name, tuple)) >> - ? ? ? ?self.failUnlessEqual(('a', ('b',)), param.name) >> - ? ? ? ?self.failUnlessEqual(0, param.position) >> - ? ? ? ?self.failUnless(not hasattr(param, 'default_value')) >> + ? ? ? ?self.assertTrue(isinstance(param.name, tuple)) > > This could be an assertIsInstance (unless you need to support Python <=2.6). > >> + ? ? ? ?self.assertEqual(('a', ('b',)), param.name) >> + ? ? ? ?self.assertEqual(0, param.position) >> + ? ? ? ?self.assertTrue(not hasattr(param, 'default_value')) > > This and several others could use assertFalse, instead of assertTrue(not > ...) > >> >> [...] > > Best Regards, > Ezio Melotti > _______________________________________________ > Python-checkins mailing list > Python-checkins at python.org > http://mail.python.org/mailman/listinfo/python-checkins > From python-checkins at python.org Mon Jul 5 22:04:55 2010 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 5 Jul 2010 22:04:55 +0200 (CEST) Subject: [Python-checkins] r82591 - python/branches/py3k/Grammar/Grammar Message-ID: <20100705200455.163ABF4D4@mail.python.org> Author: benjamin.peterson Date: Mon Jul 5 22:04:54 2010 New Revision: 82591 Log: untabify Modified: python/branches/py3k/Grammar/Grammar Modified: python/branches/py3k/Grammar/Grammar ============================================================================== --- python/branches/py3k/Grammar/Grammar (original) +++ python/branches/py3k/Grammar/Grammar Mon Jul 5 22:04:54 2010 @@ -11,9 +11,9 @@ # "How to Change Python's Grammar" # Start symbols for the grammar: -# single_input is a single interactive statement; -# file_input is a module or sequence of commands read from an input file; -# eval_input is the input for the eval() and input() functions. +# single_input is a single interactive statement; +# file_input is a module or sequence of commands read from an input file; +# eval_input is the input for the eval() and input() functions. # NB: compound_stmt in single_input is followed by extra NEWLINE! single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE file_input: (NEWLINE | stmt)* ENDMARKER @@ -71,9 +71,9 @@ for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite] try_stmt: ('try' ':' suite ((except_clause ':' suite)+ - ['else' ':' suite] - ['finally' ':' suite] | - 'finally' ':' suite)) + ['else' ':' suite] + ['finally' ':' suite] | + 'finally' ':' suite)) with_stmt: 'with' with_item (',' with_item)* ':' suite with_item: test ['as' expr] # NB compile.c makes sure that the default except clause is last From python-checkins at python.org Mon Jul 5 22:05:43 2010 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 5 Jul 2010 22:05:43 +0200 (CEST) Subject: [Python-checkins] r82592 - python/branches/release27-maint/Grammar/Grammar Message-ID: <20100705200543.89E15F41E@mail.python.org> Author: benjamin.peterson Date: Mon Jul 5 22:05:43 2010 New Revision: 82592 Log: untabify Modified: python/branches/release27-maint/Grammar/Grammar Modified: python/branches/release27-maint/Grammar/Grammar ============================================================================== --- python/branches/release27-maint/Grammar/Grammar (original) +++ python/branches/release27-maint/Grammar/Grammar Mon Jul 5 22:05:43 2010 @@ -11,9 +11,9 @@ # "How to Change Python's Grammar" # Start symbols for the grammar: -# single_input is a single interactive statement; -# file_input is a module or sequence of commands read from an input file; -# eval_input is the input for the eval() and input() functions. +# single_input is a single interactive statement; +# file_input is a module or sequence of commands read from an input file; +# eval_input is the input for the eval() and input() functions. # NB: compound_stmt in single_input is followed by extra NEWLINE! single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE file_input: (NEWLINE | stmt)* ENDMARKER @@ -68,9 +68,9 @@ for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite] try_stmt: ('try' ':' suite ((except_clause ':' suite)+ - ['else' ':' suite] - ['finally' ':' suite] | - 'finally' ':' suite)) + ['else' ':' suite] + ['finally' ':' suite] | + 'finally' ':' suite)) with_stmt: 'with' with_item (',' with_item)* ':' suite with_item: test ['as' expr] # NB compile.c makes sure that the default except clause is last From python-checkins at python.org Mon Jul 5 22:13:06 2010 From: python-checkins at python.org (georg.brandl) Date: Mon, 5 Jul 2010 22:13:06 +0200 (CEST) Subject: [Python-checkins] r82593 - python/branches/py3k/Demo/classes/README Message-ID: <20100705201306.C40A8F4D4@mail.python.org> Author: georg.brandl Date: Mon Jul 5 22:13:06 2010 New Revision: 82593 Log: Remove Dbm. Modified: python/branches/py3k/Demo/classes/README Modified: python/branches/py3k/Demo/classes/README ============================================================================== --- python/branches/py3k/Demo/classes/README (original) +++ python/branches/py3k/Demo/classes/README Mon Jul 5 22:13:06 2010 @@ -2,7 +2,6 @@ Complex.py Complex numbers Dates.py Date manipulation package by Tim Peters -Dbm.py Wrapper around built-in dbm, supporting arbitrary values Range.py Example of a generator: re-implement built-in range() Rev.py Yield the reverse of a sequence Vec.py A simple vector class From python-checkins at python.org Mon Jul 5 22:13:42 2010 From: python-checkins at python.org (georg.brandl) Date: Mon, 5 Jul 2010 22:13:42 +0200 (CEST) Subject: [Python-checkins] r82594 - python/branches/py3k/Demo/classes/Vec.py Message-ID: <20100705201342.0ABB3E795@mail.python.org> Author: georg.brandl Date: Mon Jul 5 22:13:41 2010 New Revision: 82594 Log: Update Vec class constructor, remove indirection via function, use operator module. Modified: python/branches/py3k/Demo/classes/Vec.py Modified: python/branches/py3k/Demo/classes/Vec.py ============================================================================== --- python/branches/py3k/Demo/classes/Vec.py (original) +++ python/branches/py3k/Demo/classes/Vec.py Mon Jul 5 22:13:41 2010 @@ -1,8 +1,6 @@ # A simple vector class - -def vec(*v): - return Vec(*v) +import operator class Vec: @@ -10,14 +8,16 @@ def __init__(self, *v): self.v = list(v) - def fromlist(self, v): + @classmethod + def fromlist(cls, v): if not isinstance(v, list): raise TypeError - self.v = v[:] - return self + inst = cls() + inst.v = v + return inst def __repr__(self): - return 'vec(' + repr(self.v)[1:-1] + ')' + return 'Vec(' + repr(self.v)[1:-1] + ')' def __len__(self): return len(self.v) @@ -27,24 +27,24 @@ def __add__(self, other): # Element-wise addition - v = list(map(lambda x, y: x+y, self, other)) - return Vec().fromlist(v) + v = list(map(operator.add, self, other)) + return Vec.fromlist(v) def __sub__(self, other): # Element-wise subtraction - v = list(map(lambda x, y: x-y, self, other)) - return Vec().fromlist(v) + v = list(map(operator.sub, self, other)) + return Vec.fromlist(v) def __mul__(self, scalar): # Multiply by scalar v = [x*scalar for x in self.v] - return Vec().fromlist(v) + return Vec.fromlist(v) def test(): - a = vec(1, 2, 3) - b = vec(3, 2, 1) + a = Vec(1, 2, 3) + b = Vec(3, 2, 1) print(a) print(b) print(a+b) From python-checkins at python.org Mon Jul 5 22:14:26 2010 From: python-checkins at python.org (mark.dickinson) Date: Mon, 5 Jul 2010 22:14:26 +0200 (CEST) Subject: [Python-checkins] r82595 - python/branches/py3k/Modules/_math.c Message-ID: <20100705201426.90D11D319@mail.python.org> Author: mark.dickinson Date: Mon Jul 5 22:14:26 2010 New Revision: 82595 Log: Post-detabification cleanup. Modified: python/branches/py3k/Modules/_math.c Modified: python/branches/py3k/Modules/_math.c ============================================================================== --- python/branches/py3k/Modules/_math.c (original) +++ python/branches/py3k/Modules/_math.c Mon Jul 5 22:14:26 2010 @@ -56,13 +56,13 @@ if (Py_IS_INFINITY(x)) { return x+x; } else { - return log(x)+ln2; /* acosh(huge)=log(2x) */ + return log(x)+ln2; /* acosh(huge)=log(2x) */ } } else if (x == 1.) { - return 0.0; /* acosh(1) = 0 */ + return 0.0; /* acosh(1) = 0 */ } - else if (x > 2.) { /* 2 < x < 2**28 */ + else if (x > 2.) { /* 2 < x < 2**28 */ double t = x*x; return log(2.0*x - 1.0 / (x + sqrt(t - 1.0))); } @@ -94,7 +94,7 @@ return x+x; } if (absx < two_pow_m28) { /* |x| < 2**-28 */ - return x; /* return x inexact except 0 */ + return x; /* return x inexact except 0 */ } if (absx > two_pow_p28) { /* |x| > 2**28 */ w = log(absx)+ln2; @@ -114,9 +114,9 @@ * Method : * 1.Reduced x to positive by atanh(-x) = -atanh(x) * 2.For x>=0.5 - * 1 2x x - * atanh(x) = --- * log(1 + -------) = 0.5 * log1p(2 * --------) - * 2 1 - x 1 - x + * 1 2x x + * atanh(x) = --- * log(1 + -------) = 0.5 * log1p(2 * -------) + * 2 1 - x 1 - x * * For x<0.5 * atanh(x) = 0.5*log1p(2x+2x*x/(1-x)) @@ -194,7 +194,7 @@ /* For x small, we use the following approach. Let y be the nearest float to 1+x, then - 1+x = y * (1 - (y-1-x)/y) + 1+x = y * (1 - (y-1-x)/y) so log(1+x) = log(y) + log(1-(y-1-x)/y). Since (y-1-x)/y is tiny, the second term is well approximated by (y-1-x)/y. If abs(x) >= From python-checkins at python.org Mon Jul 5 22:16:40 2010 From: python-checkins at python.org (mark.dickinson) Date: Mon, 5 Jul 2010 22:16:40 +0200 (CEST) Subject: [Python-checkins] r82596 - in python/branches/release27-maint: Modules/_math.c Message-ID: <20100705201640.3FF96C81F@mail.python.org> Author: mark.dickinson Date: Mon Jul 5 22:16:40 2010 New Revision: 82596 Log: Merged revisions 82595 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ........ r82595 | mark.dickinson | 2010-07-05 21:14:26 +0100 (Mon, 05 Jul 2010) | 1 line Post-detabification cleanup. ........ Modified: python/branches/release27-maint/ (props changed) python/branches/release27-maint/Modules/_math.c Modified: python/branches/release27-maint/Modules/_math.c ============================================================================== --- python/branches/release27-maint/Modules/_math.c (original) +++ python/branches/release27-maint/Modules/_math.c Mon Jul 5 22:16:40 2010 @@ -56,13 +56,13 @@ if (Py_IS_INFINITY(x)) { return x+x; } else { - return log(x)+ln2; /* acosh(huge)=log(2x) */ + return log(x)+ln2; /* acosh(huge)=log(2x) */ } } else if (x == 1.) { - return 0.0; /* acosh(1) = 0 */ + return 0.0; /* acosh(1) = 0 */ } - else if (x > 2.) { /* 2 < x < 2**28 */ + else if (x > 2.) { /* 2 < x < 2**28 */ double t = x*x; return log(2.0*x - 1.0 / (x + sqrt(t - 1.0))); } @@ -94,7 +94,7 @@ return x+x; } if (absx < two_pow_m28) { /* |x| < 2**-28 */ - return x; /* return x inexact except 0 */ + return x; /* return x inexact except 0 */ } if (absx > two_pow_p28) { /* |x| > 2**28 */ w = log(absx)+ln2; @@ -114,9 +114,9 @@ * Method : * 1.Reduced x to positive by atanh(-x) = -atanh(x) * 2.For x>=0.5 - * 1 2x x - * atanh(x) = --- * log(1 + -------) = 0.5 * log1p(2 * --------) - * 2 1 - x 1 - x + * 1 2x x + * atanh(x) = --- * log(1 + -------) = 0.5 * log1p(2 * -------) + * 2 1 - x 1 - x * * For x<0.5 * atanh(x) = 0.5*log1p(2x+2x*x/(1-x)) @@ -194,7 +194,7 @@ /* For x small, we use the following approach. Let y be the nearest float to 1+x, then - 1+x = y * (1 - (y-1-x)/y) + 1+x = y * (1 - (y-1-x)/y) so log(1+x) = log(y) + log(1-(y-1-x)/y). Since (y-1-x)/y is tiny, the second term is well approximated by (y-1-x)/y. If abs(x) >= From alexander.belopolsky at gmail.com Mon Jul 5 22:42:16 2010 From: alexander.belopolsky at gmail.com (Alexander Belopolsky) Date: Mon, 5 Jul 2010 16:42:16 -0400 Subject: [Python-checkins] r82594 - python/branches/py3k/Demo/classes/Vec.py In-Reply-To: <20100705201342.0ABB3E795@mail.python.org> References: <20100705201342.0ABB3E795@mail.python.org> Message-ID: On Mon, Jul 5, 2010 at 4:13 PM, georg.brandl wrote: .. > ? ? ? ? # Element-wise addition > - ? ? ? ?v = list(map(lambda x, y: x+y, self, other)) > - ? ? ? ?return Vec().fromlist(v) > + ? ? ? ?v = list(map(operator.add, self, other)) > + ? ? ? ?return Vec.fromlist(v) I wonder if it would be more fitting in a 3.x demo to compute v as v = [x + y for x, y in zip(self.v, other.v)] or provide __iter__ and do simply v = [x + y for x, y in zip(self, other)] I know this suggestion may be premature before it is decided what stays in Demo and what does not, but +import operator has caught my eye. From g.brandl at gmx.net Mon Jul 5 23:12:22 2010 From: g.brandl at gmx.net (Georg Brandl) Date: Mon, 05 Jul 2010 23:12:22 +0200 Subject: [Python-checkins] r82570 - python/branches/py3k/Doc/library/stdtypes.rst In-Reply-To: <20100705114143.25BBFEE99A@mail.python.org> References: <20100705114143.25BBFEE99A@mail.python.org> Message-ID: Am 05.07.2010 13:41, schrieb senthil.kumaran: > Author: senthil.kumaran > Date: Mon Jul 5 13:41:42 2010 > New Revision: 82570 > > Log: > Fix: Issue9091 Minor documentation clarification. > > > > Modified: > python/branches/py3k/Doc/library/stdtypes.rst > > Modified: python/branches/py3k/Doc/library/stdtypes.rst > ============================================================================== > --- python/branches/py3k/Doc/library/stdtypes.rst (original) > +++ python/branches/py3k/Doc/library/stdtypes.rst Mon Jul 5 13:41:42 2010 > @@ -966,7 +966,8 @@ > > .. method:: str.capitalize() > > - Return a copy of the string with only its first character capitalized. > + Return a copy of the string with its first character capitalized and the > + rest lowered. That should be "lowercased" IINM. Georg From g.brandl at gmx.net Mon Jul 5 23:14:49 2010 From: g.brandl at gmx.net (Georg Brandl) Date: Mon, 05 Jul 2010 23:14:49 +0200 Subject: [Python-checkins] r82594 - python/branches/py3k/Demo/classes/Vec.py In-Reply-To: References: <20100705201342.0ABB3E795@mail.python.org> Message-ID: Am 05.07.2010 22:42, schrieb Alexander Belopolsky: > On Mon, Jul 5, 2010 at 4:13 PM, georg.brandl wrote: > .. >> # Element-wise addition >> - v = list(map(lambda x, y: x+y, self, other)) >> - return Vec().fromlist(v) >> + v = list(map(operator.add, self, other)) >> + return Vec.fromlist(v) > > I wonder if it would be more fitting in a 3.x demo to compute v as > > v = [x + y for x, y in zip(self.v, other.v)] > > or provide __iter__ and do simply > > v = [x + y for x, y in zip(self, other)] > > I know this suggestion may be premature before it is decided what > stays in Demo and what does not, but +import operator has caught my > eye. Well, why not. Go ahead. Georg From python-checkins at python.org Mon Jul 5 23:36:21 2010 From: python-checkins at python.org (victor.stinner) Date: Mon, 5 Jul 2010 23:36:21 +0200 (CEST) Subject: [Python-checkins] r82597 - python/branches/py3k/Doc/c-api/arg.rst Message-ID: <20100705213621.9047BEDB2@mail.python.org> Author: victor.stinner Date: Mon Jul 5 23:36:21 2010 New Revision: 82597 Log: #9158: Fix y* format of PyArg_Parse*() functions documentation Modified: python/branches/py3k/Doc/c-api/arg.rst Modified: python/branches/py3k/Doc/c-api/arg.rst ============================================================================== --- python/branches/py3k/Doc/c-api/arg.rst (original) +++ python/branches/py3k/Doc/c-api/arg.rst Mon Jul 5 23:36:21 2010 @@ -100,7 +100,7 @@ contain embedded NUL bytes; if it does, a :exc:`TypeError` exception is raised. -``y*`` (:class:`bytes`, :class:`bytearray` or buffer compatible object) [Py_buffer \*] +``y*`` (:class:`bytes`, :class:`bytearray` or buffer compatible object) [Py_buffer] This variant on ``s*`` doesn't accept Unicode objects, only objects supporting the buffer protocol. **This is the recommended way to accept binary data.** From python-checkins at python.org Mon Jul 5 23:38:37 2010 From: python-checkins at python.org (victor.stinner) Date: Mon, 5 Jul 2010 23:38:37 +0200 (CEST) Subject: [Python-checkins] r82598 - in python/branches/release31-maint: Doc/c-api/arg.rst Message-ID: <20100705213837.C98C4F68D1@mail.python.org> Author: victor.stinner Date: Mon Jul 5 23:38:37 2010 New Revision: 82598 Log: Merged revisions 82597 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ........ r82597 | victor.stinner | 2010-07-05 23:36:21 +0200 (lun., 05 juil. 2010) | 2 lines #9158: Fix y* format of PyArg_Parse*() functions documentation ........ Modified: python/branches/release31-maint/ (props changed) python/branches/release31-maint/Doc/c-api/arg.rst Modified: python/branches/release31-maint/Doc/c-api/arg.rst ============================================================================== --- python/branches/release31-maint/Doc/c-api/arg.rst (original) +++ python/branches/release31-maint/Doc/c-api/arg.rst Mon Jul 5 23:38:37 2010 @@ -100,7 +100,7 @@ contain embedded NUL bytes; if it does, a :exc:`TypeError` exception is raised. -``y*`` (:class:`bytes`, :class:`bytearray` or buffer compatible object) [Py_buffer \*] +``y*`` (:class:`bytes`, :class:`bytearray` or buffer compatible object) [Py_buffer] This variant on ``s*`` doesn't accept Unicode objects, only objects supporting the buffer protocol. **This is the recommended way to accept binary data.** From python-checkins at python.org Mon Jul 5 23:44:06 2010 From: python-checkins at python.org (alexander.belopolsky) Date: Mon, 5 Jul 2010 23:44:06 +0200 (CEST) Subject: [Python-checkins] r82599 - python/branches/py3k/Demo/classes/Vec.py Message-ID: <20100705214406.07607EDB2@mail.python.org> Author: alexander.belopolsky Date: Mon Jul 5 23:44:05 2010 New Revision: 82599 Log: "Modernized" the demo a little. Modified: python/branches/py3k/Demo/classes/Vec.py Modified: python/branches/py3k/Demo/classes/Vec.py ============================================================================== --- python/branches/py3k/Demo/classes/Vec.py (original) +++ python/branches/py3k/Demo/classes/Vec.py Mon Jul 5 23:44:05 2010 @@ -1,10 +1,27 @@ -# A simple vector class +class Vec: + """ A simple vector class -import operator + Instances of the Vec class can be constructed from numbers + >>> a = Vec(1, 2, 3) + >>> b = Vec(3, 2, 1) -class Vec: + added + >>> a + b + Vec(4, 4, 4) + + subtracted + >>> a - b + Vec(-2, 0, 2) + + and multiplied by a scalar on the left + >>> 3.0 * a + Vec(3.0, 6.0, 9.0) + or on the right + >>> a * 3.0 + Vec(3.0, 6.0, 9.0) + """ def __init__(self, *v): self.v = list(v) @@ -17,7 +34,8 @@ return inst def __repr__(self): - return 'Vec(' + repr(self.v)[1:-1] + ')' + args = ', '.join(repr(x) for x in self.v) + return 'Vec({})'.format(args) def __len__(self): return len(self.v) @@ -27,28 +45,24 @@ def __add__(self, other): # Element-wise addition - v = list(map(operator.add, self, other)) + v = [x + y for x, y in zip(self.v, other.v)] return Vec.fromlist(v) def __sub__(self, other): # Element-wise subtraction - v = list(map(operator.sub, self, other)) + v = [x - y for x, y in zip(self.v, other.v)] return Vec.fromlist(v) def __mul__(self, scalar): # Multiply by scalar - v = [x*scalar for x in self.v] + v = [x * scalar for x in self.v] return Vec.fromlist(v) + __rmul__ = __mul__ def test(): - a = Vec(1, 2, 3) - b = Vec(3, 2, 1) - print(a) - print(b) - print(a+b) - print(a-b) - print(a*3.0) + import doctest + doctest.testmod() test() From python-checkins at python.org Tue Jul 6 00:11:16 2010 From: python-checkins at python.org (brett.cannon) Date: Tue, 6 Jul 2010 00:11:16 +0200 (CEST) Subject: [Python-checkins] r82600 - python/branches/py3k/Lib/test/test_xmlrpc_net.py Message-ID: <20100705221116.E7A75D2D2@mail.python.org> Author: brett.cannon Date: Tue Jul 6 00:11:16 2010 New Revision: 82600 Log: Fix test_xmlrpc_net to no longer fail since there are no more buildbots for trunk. Modified: python/branches/py3k/Lib/test/test_xmlrpc_net.py Modified: python/branches/py3k/Lib/test/test_xmlrpc_net.py ============================================================================== --- python/branches/py3k/Lib/test/test_xmlrpc_net.py (original) +++ python/branches/py3k/Lib/test/test_xmlrpc_net.py Tue Jul 6 00:11:16 2010 @@ -48,7 +48,7 @@ # Perform a minimal sanity check on the result, just to be sure # the request means what we think it means. self.assertIsInstance(builders, collections.Sequence) - self.assertTrue([x for x in builders if "trunk" in x], builders) + self.assertTrue([x for x in builders if "3.x" in x], builders) def test_main(): From eric at trueblade.com Tue Jul 6 01:12:31 2010 From: eric at trueblade.com (Eric Smith) Date: Mon, 05 Jul 2010 19:12:31 -0400 Subject: [Python-checkins] r82570 - python/branches/py3k/Doc/library/stdtypes.rst In-Reply-To: References: <20100705114143.25BBFEE99A@mail.python.org> Message-ID: <4C3266DF.7050907@trueblade.com> On 7/5/10 5:12 PM, Georg Brandl wrote: > Am 05.07.2010 13:41, schrieb senthil.kumaran: >> Author: senthil.kumaran >> Date: Mon Jul 5 13:41:42 2010 >> New Revision: 82570 >> >> Log: >> Fix: Issue9091 Minor documentation clarification. >> >> >> >> Modified: >> python/branches/py3k/Doc/library/stdtypes.rst >> >> Modified: python/branches/py3k/Doc/library/stdtypes.rst >> ============================================================================== >> --- python/branches/py3k/Doc/library/stdtypes.rst (original) >> +++ python/branches/py3k/Doc/library/stdtypes.rst Mon Jul 5 13:41:42 2010 >> @@ -966,7 +966,8 @@ >> >> .. method:: str.capitalize() >> >> - Return a copy of the string with only its first character capitalized. >> + Return a copy of the string with its first character capitalized and the >> + rest lowered. > > That should be "lowercased" IINM. Yes, that would be a better word. -- Eric. From solipsis at pitrou.net Tue Jul 6 01:25:03 2010 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Tue, 6 Jul 2010 01:25:03 +0200 (CEST) Subject: [Python-checkins] Daily py3k reference leaks (r82595): sum=0 Message-ID: <20100705232503.4021C17721@ns6635.ovh.net> py3k results for svn r82595 (hg cset 43bb2c640f17) -------------------------------------------------- Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/py3k/refleaks/reflogTSIzMe', '-x'] From python-checkins at python.org Tue Jul 6 04:08:36 2010 From: python-checkins at python.org (senthil.kumaran) Date: Tue, 6 Jul 2010 04:08:36 +0200 (CEST) Subject: [Python-checkins] r82601 - python/branches/py3k/Doc/library/stdtypes.rst Message-ID: <20100706020836.E47A6F0BA@mail.python.org> Author: senthil.kumaran Date: Tue Jul 6 04:08:36 2010 New Revision: 82601 Log: Change 'lowered' to 'lowercased' Modified: python/branches/py3k/Doc/library/stdtypes.rst Modified: python/branches/py3k/Doc/library/stdtypes.rst ============================================================================== --- python/branches/py3k/Doc/library/stdtypes.rst (original) +++ python/branches/py3k/Doc/library/stdtypes.rst Tue Jul 6 04:08:36 2010 @@ -967,7 +967,7 @@ .. method:: str.capitalize() Return a copy of the string with its first character capitalized and the - rest lowered. + rest lowercased. .. method:: str.center(width[, fillchar]) From python-checkins at python.org Tue Jul 6 05:03:34 2010 From: python-checkins at python.org (senthil.kumaran) Date: Tue, 6 Jul 2010 05:03:34 +0200 (CEST) Subject: [Python-checkins] r82602 - in python/branches/release31-maint: Doc/library/stdtypes.rst Message-ID: <20100706030334.4C4EFED8F@mail.python.org> Author: senthil.kumaran Date: Tue Jul 6 05:03:34 2010 New Revision: 82602 Log: Merged revisions 82601 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ........ r82601 | senthil.kumaran | 2010-07-06 07:38:36 +0530 (Tue, 06 Jul 2010) | 3 lines Change 'lowered' to 'lowercased' ........ Modified: python/branches/release31-maint/ (props changed) python/branches/release31-maint/Doc/library/stdtypes.rst Modified: python/branches/release31-maint/Doc/library/stdtypes.rst ============================================================================== --- python/branches/release31-maint/Doc/library/stdtypes.rst (original) +++ python/branches/release31-maint/Doc/library/stdtypes.rst Tue Jul 6 05:03:34 2010 @@ -801,7 +801,7 @@ .. method:: str.capitalize() Return a copy of the string with its first character capitalized and the - rest lowered. + rest lowercased. .. method:: str.center(width[, fillchar]) From python-checkins at python.org Tue Jul 6 05:06:53 2010 From: python-checkins at python.org (senthil.kumaran) Date: Tue, 6 Jul 2010 05:06:53 +0200 (CEST) Subject: [Python-checkins] r82603 - in python/branches/release27-maint: Doc/library/stdtypes.rst Message-ID: <20100706030653.33F60F074@mail.python.org> Author: senthil.kumaran Date: Tue Jul 6 05:06:53 2010 New Revision: 82603 Log: Merged revisions 82601 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ........ r82601 | senthil.kumaran | 2010-07-06 07:38:36 +0530 (Tue, 06 Jul 2010) | 3 lines Change 'lowered' to 'lowercased' ........ Modified: python/branches/release27-maint/ (props changed) python/branches/release27-maint/Doc/library/stdtypes.rst Modified: python/branches/release27-maint/Doc/library/stdtypes.rst ============================================================================== --- python/branches/release27-maint/Doc/library/stdtypes.rst (original) +++ python/branches/release27-maint/Doc/library/stdtypes.rst Tue Jul 6 05:06:53 2010 @@ -831,7 +831,7 @@ .. method:: str.capitalize() Return a copy of the string with its first character capitalized and the - rest lowered. + rest lowercased. For 8-bit strings, this method is locale-dependent. From orsenthil at gmail.com Tue Jul 6 05:07:53 2010 From: orsenthil at gmail.com (Senthil Kumaran) Date: Tue, 6 Jul 2010 08:37:53 +0530 Subject: [Python-checkins] r82570 - python/branches/py3k/Doc/library/stdtypes.rst In-Reply-To: <4C3266DF.7050907@trueblade.com> References: <20100705114143.25BBFEE99A@mail.python.org> <4C3266DF.7050907@trueblade.com> Message-ID: <20100706030753.GD1583@remy> On Mon, Jul 05, 2010 at 07:12:31PM -0400, Eric Smith wrote: > >>+ Return a copy of the string with its first character capitalized and the > >>+ rest lowered. > > > >That should be "lowercased" IINM. > > Yes, that would be a better word. > I changed that one. Thanks! -- Senthil A arte ? uma magia que liberta a mentira de ser verdadeira. -- Theodor Adorno, fil?sofo alem?o From python-checkins at python.org Tue Jul 6 12:53:30 2010 From: python-checkins at python.org (matthias.klose) Date: Tue, 6 Jul 2010 12:53:30 +0200 (CEST) Subject: [Python-checkins] r82604 - python/branches/py3k/Python/sysmodule.c Message-ID: <20100706105330.B3BD0EEA07@mail.python.org> Author: matthias.klose Date: Tue Jul 6 12:53:30 2010 New Revision: 82604 Log: - sysmodule.c (get_hash_info): Define as static function. Modified: python/branches/py3k/Python/sysmodule.c Modified: python/branches/py3k/Python/sysmodule.c ============================================================================== --- python/branches/py3k/Python/sysmodule.c (original) +++ python/branches/py3k/Python/sysmodule.c Tue Jul 6 12:53:30 2010 @@ -595,7 +595,7 @@ 5, }; -PyObject * +static PyObject * get_hash_info(void) { PyObject *hash_info; From python-checkins at python.org Tue Jul 6 15:54:53 2010 From: python-checkins at python.org (alexander.belopolsky) Date: Tue, 6 Jul 2010 15:54:53 +0200 (CEST) Subject: [Python-checkins] r82605 - in sandbox/branches/py3k-datetime: datetime.py test_datetime.py Message-ID: <20100706135453.5D3C5EE98E@mail.python.org> Author: alexander.belopolsky Date: Tue Jul 6 15:54:47 2010 New Revision: 82605 Log: Added type check for better match with C implementation Modified: sandbox/branches/py3k-datetime/datetime.py sandbox/branches/py3k-datetime/test_datetime.py Modified: sandbox/branches/py3k-datetime/datetime.py ============================================================================== --- sandbox/branches/py3k-datetime/datetime.py (original) +++ sandbox/branches/py3k-datetime/datetime.py Tue Jul 6 15:54:47 2010 @@ -665,7 +665,8 @@ year, month, day (required, base 1) """ - if isinstance(year, bytes) and len(year) == 4: + if (isinstance(year, bytes) and len(year) == 4 and + 1 <= year[2] <= 12 and month is None): # Month is sane # Pickle support self = object.__new__(cls) self.__setstate(year) @@ -978,6 +979,8 @@ else: return (self.__class__, args, state) +_tzinfo_class = tzinfo + class time: """Time with time zone. @@ -1272,7 +1275,10 @@ (self._hour, self._minute, self._second, us1, us2, us3) = string self._microsecond = (((us1 << 8) | us2) << 8) | us3 - self._tzinfo = tzinfo + if tzinfo is None or isinstance(tzinfo, _tzinfo_class): + self._tzinfo = tzinfo + else: + raise TypeError("bad tzinfo state arg %r" % tzinfo) def __reduce__(self): return (time, self._getstate()) @@ -1741,7 +1747,10 @@ self._minute, self._second, us1, us2, us3) = string self._year = yhi * 256 + ylo self._microsecond = (((us1 << 8) | us2) << 8) | us3 - self._tzinfo = tzinfo + if tzinfo is None or isinstance(tzinfo, _tzinfo_class): + self._tzinfo = tzinfo + else: + raise TypeError("bad tzinfo state arg %r" % tzinfo) def __reduce__(self): return (self.__class__, self._getstate()) Modified: sandbox/branches/py3k-datetime/test_datetime.py ============================================================================== --- sandbox/branches/py3k-datetime/test_datetime.py (original) +++ sandbox/branches/py3k-datetime/test_datetime.py Tue Jul 6 15:54:47 2010 @@ -69,34 +69,11 @@ return self.__name def dst(self, dt): return self.__dstoffset - def __eq__(self, other): - return (self.__offset == other.__offset and - self.__name == other.__name and - self.__dstoffset == other.__dstoffset) - def __getinitargs__(self): - return (self.__offset, - self.__name, - self.__dstoffset) class PicklableFixedOffset(FixedOffset): def __init__(self, offset=None, name=None, dstoffset=None): FixedOffset.__init__(self, offset, name, dstoffset) - - -class PicklableFixedOffsetWithState(PicklableFixedOffset): - - def __init__(self, offset=None, name=None, dstoffset=None, - state=None): - FixedOffset.__init__(self, offset, name, dstoffset) - self.__state = state - def __getstate__(self): - return self.__state - def __setstate__(self, state): - self.__state = state - def __eq__(self, other): - return (FixedOffset.__eq__(self, other) and - self.__state == other.__state) class TestTZInfo(unittest.TestCase): @@ -148,7 +125,6 @@ offset = timedelta(minutes=-300) for otype, args in [ (PicklableFixedOffset, (offset, 'cookie')), - (PicklableFixedOffsetWithState, (offset, 'cookie', 'state')), (timezone, (offset,)), (timezone, (offset, "EST"))]: orig = otype(*args) @@ -164,7 +140,6 @@ self.assertIs(type(derived), otype) self.assertEqual(derived.utcoffset(None), offset) self.assertEqual(derived.tzname(None), oname) - self.assertEqual(derived, orig) class TestTimeZone(unittest.TestCase): @@ -261,33 +236,6 @@ t.replace(tzinfo=tz).dst()) ############################################################################# -# Base clase for testing pickling state of timedelta, time, date and -# datetime instances. - -class ReduceStructure: - initargs = 1, 1, 1 - statetype = (bytes, tzinfo) - def test_reduce(self): - obj = self.theclass(*self.initargs) - factory, state = obj.__reduce__()[:2] - self.assertIs(factory, self.theclass) - for v, t in zip(state, self.statetype): - self.assertIsInstance(v, t) - - def test_construct_from_state(self): - obj = self.theclass(*self.initargs) - factory, state = obj.__reduce__()[:2] - initbytes = state[0] - # This test should be overriden in tests for classes that - # don't produce their state as bytes. Curently, timedelta - # and timezone - assert isinstance(initbytes, bytes) - obj = factory(initbytes) - self.assertIs(type(obj), self.theclass) - self.assertRaises(TypeError, factory, initbytes[:-1]) - self.assertRaises(TypeError, factory, initbytes + b'x') - -############################################################################# # Base clase for testing a particular aspect of timedelta, time, date and # datetime comparisons. @@ -324,10 +272,10 @@ ############################################################################# # timedelta tests -class TestTimeDelta(HarmlessMixedComparison, ReduceStructure, unittest.TestCase): +class TestTimeDelta(HarmlessMixedComparison, unittest.TestCase): theclass = timedelta - statetype = (int, int, int) + def test_constructor(self): eq = self.assertEqual td = timedelta @@ -353,9 +301,6 @@ eq(td(seconds=0.001), td(milliseconds=1)) eq(td(milliseconds=0.001), td(microseconds=1)) - def test_construct_from_state(self): - pass - def test_computations(self): eq = self.assertEqual td = timedelta @@ -788,12 +733,11 @@ class SubclassDate(date): sub_var = 1 -class TestDate(HarmlessMixedComparison, ReduceStructure, unittest.TestCase): +class TestDate(HarmlessMixedComparison, unittest.TestCase): # Tests here should pass for both dates and datetimes, except for a # few tests that TestDateTime overrides. theclass = date - statetype = (bytes,) def test_basic_attributes(self): dt = self.theclass(2002, 3, 1) @@ -937,6 +881,7 @@ def test_computations(self): a = self.theclass(2002, 1, 31) b = self.theclass(1956, 1, 31) + c = self.theclass(2001,2,1) diff = a-b self.assertEqual(diff.days, 46*365 + len(range(1956, 2002, 4))) @@ -962,6 +907,7 @@ self.assertEqual(a - (a + day), -day) self.assertEqual(a - (a - week), week) self.assertEqual(a - (a - day), day) + self.assertEqual(c - (c - day), day) # Add/sub ints or floats should be illegal for i in 1, 1.0: @@ -1403,6 +1349,10 @@ for month_byte in b'9', b'\0', b'\r', b'\xff': self.assertRaises(TypeError, self.theclass, base[:2] + month_byte + base[3:]) + # Good bytes, but bad tzinfo: + self.assertRaises(TypeError, self.theclass, + bytes([1] * len(base)), 'EST') + for ord_byte in range(1, 13): # This shouldn't blow up because of the month byte alone. If # the implementation changes to do more-careful checking, it may @@ -1418,7 +1368,6 @@ class TestDateTime(TestDate): theclass = datetime - statetype = (bytes, tzinfo) def test_basic_attributes(self): dt = self.theclass(2002, 3, 1, 12, 0) @@ -1767,8 +1716,6 @@ # than one microsecond smaller than an integer. self.assertEqual(self.theclass.fromtimestamp(0.9999999), self.theclass.fromtimestamp(1)) - self.assertEqual(self.theclass.utcfromtimestamp(0.9999999), - self.theclass.utcfromtimestamp(1)) def test_insane_fromtimestamp(self): # It's possible that some platform maps time_t to double, @@ -1996,7 +1943,7 @@ class SubclassTime(time): sub_var = 1 -class TestTime(HarmlessMixedComparison, ReduceStructure, unittest.TestCase): +class TestTime(HarmlessMixedComparison, unittest.TestCase): theclass = time @@ -3067,7 +3014,7 @@ def test_utctimetuple(self): class DST(tzinfo): - def __init__(self, dstvalue): + def __init__(self, dstvalue=0): if isinstance(dstvalue, int): dstvalue = timedelta(minutes=dstvalue) self.dstvalue = dstvalue @@ -3102,6 +3049,26 @@ # is never in effect for a UTC time. self.assertEqual(0, t.tm_isdst) + # For naive datetime, utctimetuple == timetuple except for isdst + d = cls(1, 2, 3, 10, 20, 30, 40) + t = d.utctimetuple() + self.assertEqual(t[:-1], d.timetuple()[:-1]) + self.assertEqual(0, t.tm_isdst) + # Same if utcoffset is None + class NOFS(DST): + def utcoffset(self, dt): + return None + d = cls(1, 2, 3, 10, 20, 30, 40, tzinfo=NOFS()) + t = d.utctimetuple() + self.assertEqual(t[:-1], d.timetuple()[:-1]) + self.assertEqual(0, t.tm_isdst) + # Check that bad tzinfo is detected + class BOFS(DST): + def utcoffset(self, dt): + return "EST" + d = cls(1, 2, 3, 10, 20, 30, 40, tzinfo=BOFS()) + self.assertRaises(TypeError, d.utctimetuple) + # Check that utctimetuple() is the same as # astimezone(utc).timetuple() d = cls(2010, 11, 13, 14, 15, 16, 171819) From python-checkins at python.org Tue Jul 6 16:55:57 2010 From: python-checkins at python.org (mark.dickinson) Date: Tue, 6 Jul 2010 16:55:57 +0200 (CEST) Subject: [Python-checkins] r82606 - python/branches/py3k-issue4970 Message-ID: <20100706145557.5EE5EEE98E@mail.python.org> Author: mark.dickinson Date: Tue Jul 6 16:55:57 2010 New Revision: 82606 Log: Delete branch that was used to fix issue 4970 (signal 32 on gentoo buildbot). Removed: python/branches/py3k-issue4970/ From python-checkins at python.org Tue Jul 6 17:00:41 2010 From: python-checkins at python.org (mark.dickinson) Date: Tue, 6 Jul 2010 17:00:41 +0200 (CEST) Subject: [Python-checkins] r82607 - python/branches/py3k/Modules/_math.c Message-ID: <20100706150041.12A07EEA0C@mail.python.org> Author: mark.dickinson Date: Tue Jul 6 17:00:40 2010 New Revision: 82607 Log: Indentation and PEP 7 fixes. Modified: python/branches/py3k/Modules/_math.c Modified: python/branches/py3k/Modules/_math.c ============================================================================== --- python/branches/py3k/Modules/_math.c (original) +++ python/branches/py3k/Modules/_math.c Tue Jul 6 17:00:40 2010 @@ -55,7 +55,8 @@ else if (x >= two_pow_p28) { /* x > 2**28 */ if (Py_IS_INFINITY(x)) { return x+x; - } else { + } + else { return log(x)+ln2; /* acosh(huge)=log(2x) */ } } @@ -173,15 +174,15 @@ */ if (fabs(x) < 0.7) { - double u; - u = exp(x); - if (u == 1.0) - return x; - else - return (u - 1.0) * x / log(u); + double u; + u = exp(x); + if (u == 1.0) + return x; + else + return (u - 1.0) * x / log(u); } else - return exp(x) - 1.0; + return exp(x) - 1.0; } /* log1p(x) = log(1+x). The log1p function is designed to avoid the @@ -213,17 +214,19 @@ double y; if (fabs(x) < DBL_EPSILON/2.) { - return x; - } else if (-0.5 <= x && x <= 1.) { - /* WARNING: it's possible than an overeager compiler - will incorrectly optimize the following two lines - to the equivalent of "return log(1.+x)". If this - happens, then results from log1p will be inaccurate - for small x. */ - y = 1.+x; - return log(y)-((y-1.)-x)/y; - } else { - /* NaNs and infinities should end up here */ - return log(1.+x); + return x; + } + else if (-0.5 <= x && x <= 1.) { + /* WARNING: it's possible than an overeager compiler + will incorrectly optimize the following two lines + to the equivalent of "return log(1.+x)". If this + happens, then results from log1p will be inaccurate + for small x. */ + y = 1.+x; + return log(y)-((y-1.)-x)/y; + } + else { + /* NaNs and infinities should end up here */ + return log(1.+x); } } From python-checkins at python.org Tue Jul 6 17:03:42 2010 From: python-checkins at python.org (mark.dickinson) Date: Tue, 6 Jul 2010 17:03:42 +0200 (CEST) Subject: [Python-checkins] r82608 - in python/branches/release27-maint: Modules/_math.c Message-ID: <20100706150342.35800EE99A@mail.python.org> Author: mark.dickinson Date: Tue Jul 6 17:03:42 2010 New Revision: 82608 Log: Merged revisions 82607 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ........ r82607 | mark.dickinson | 2010-07-06 16:00:40 +0100 (Tue, 06 Jul 2010) | 1 line Indentation and PEP 7 fixes. ........ Modified: python/branches/release27-maint/ (props changed) python/branches/release27-maint/Modules/_math.c Modified: python/branches/release27-maint/Modules/_math.c ============================================================================== --- python/branches/release27-maint/Modules/_math.c (original) +++ python/branches/release27-maint/Modules/_math.c Tue Jul 6 17:03:42 2010 @@ -55,7 +55,8 @@ else if (x >= two_pow_p28) { /* x > 2**28 */ if (Py_IS_INFINITY(x)) { return x+x; - } else { + } + else { return log(x)+ln2; /* acosh(huge)=log(2x) */ } } @@ -173,15 +174,15 @@ */ if (fabs(x) < 0.7) { - double u; - u = exp(x); - if (u == 1.0) - return x; - else - return (u - 1.0) * x / log(u); + double u; + u = exp(x); + if (u == 1.0) + return x; + else + return (u - 1.0) * x / log(u); } else - return exp(x) - 1.0; + return exp(x) - 1.0; } /* log1p(x) = log(1+x). The log1p function is designed to avoid the @@ -213,17 +214,19 @@ double y; if (fabs(x) < DBL_EPSILON/2.) { - return x; - } else if (-0.5 <= x && x <= 1.) { - /* WARNING: it's possible than an overeager compiler - will incorrectly optimize the following two lines - to the equivalent of "return log(1.+x)". If this - happens, then results from log1p will be inaccurate - for small x. */ - y = 1.+x; - return log(y)-((y-1.)-x)/y; - } else { - /* NaNs and infinities should end up here */ - return log(1.+x); + return x; + } + else if (-0.5 <= x && x <= 1.) { + /* WARNING: it's possible than an overeager compiler + will incorrectly optimize the following two lines + to the equivalent of "return log(1.+x)". If this + happens, then results from log1p will be inaccurate + for small x. */ + y = 1.+x; + return log(y)-((y-1.)-x)/y; + } + else { + /* NaNs and infinities should end up here */ + return log(1.+x); } } From python-checkins at python.org Tue Jul 6 17:08:55 2010 From: python-checkins at python.org (vinay.sajip) Date: Tue, 6 Jul 2010 17:08:55 +0200 (CEST) Subject: [Python-checkins] r82609 - in python/branches: py3k/Doc/library/logging.rst release26-maint/Doc/library/logging.rst release27-maint/Doc/library/logging.rst Message-ID: <20100706150855.F3889EE992@mail.python.org> Author: vinay.sajip Date: Tue Jul 6 17:08:55 2010 New Revision: 82609 Log: Minor improvements to logging documentation. Modified: python/branches/py3k/Doc/library/logging.rst python/branches/release26-maint/Doc/library/logging.rst python/branches/release27-maint/Doc/library/logging.rst Modified: python/branches/py3k/Doc/library/logging.rst ============================================================================== --- python/branches/py3k/Doc/library/logging.rst (original) +++ python/branches/py3k/Doc/library/logging.rst Tue Jul 6 17:08:55 2010 @@ -246,7 +246,7 @@ methods listed above, but this is how to log at custom log levels. :func:`getLogger` returns a reference to a logger instance with the specified -if it is provided, or ``root`` if not. The names are period-separated +name if it is provided, or ``root`` if not. The names are period-separated hierarchical structures. Multiple calls to :func:`getLogger` with the same name will return a reference to the same logger object. Loggers that are further down in the hierarchical list are children of loggers higher up in the list. @@ -1572,6 +1572,11 @@ 69 myapp.area2 WARNING Jail zesty vixen who grabbed pay from quack. 69 myapp.area2 ERROR The five boxing wizards jump quickly. +Note that there are some security issues with pickle in some scenarios. If +these affect you, you can use an alternative serialization scheme by overriding +the :meth:`makePickle` method and implementing your alternative there, as +well as adapting the above script to use your alternative serialization. + Using arbitrary objects as messages ----------------------------------- Modified: python/branches/release26-maint/Doc/library/logging.rst ============================================================================== --- python/branches/release26-maint/Doc/library/logging.rst (original) +++ python/branches/release26-maint/Doc/library/logging.rst Tue Jul 6 17:08:55 2010 @@ -55,10 +55,12 @@ Most applications are probably going to want to log to a file, so let's start with that case. Using the :func:`basicConfig` function, we can set up the -default handler so that debug messages are written to a file:: +default handler so that debug messages are written to a file (in the example, +we assume that you have the appropriate permissions to create a file called +*example.log* in the current directory):: import logging - LOG_FILENAME = '/tmp/logging_example.out' + LOG_FILENAME = 'example.log' logging.basicConfig(filename=LOG_FILENAME,level=logging.DEBUG) logging.debug('This message should go to the log file') @@ -77,7 +79,7 @@ import logging import logging.handlers - LOG_FILENAME = '/tmp/logging_rotatingfile_example.out' + LOG_FILENAME = 'logging_rotatingfile_example.out' # Set up a specific logger with our desired output level my_logger = logging.getLogger('MyLogger') @@ -102,14 +104,14 @@ The result should be 6 separate files, each with part of the log history for the application:: - /tmp/logging_rotatingfile_example.out - /tmp/logging_rotatingfile_example.out.1 - /tmp/logging_rotatingfile_example.out.2 - /tmp/logging_rotatingfile_example.out.3 - /tmp/logging_rotatingfile_example.out.4 - /tmp/logging_rotatingfile_example.out.5 + logging_rotatingfile_example.out + logging_rotatingfile_example.out.1 + logging_rotatingfile_example.out.2 + logging_rotatingfile_example.out.3 + logging_rotatingfile_example.out.4 + logging_rotatingfile_example.out.5 -The most current file is always :file:`/tmp/logging_rotatingfile_example.out`, +The most current file is always :file:`logging_rotatingfile_example.out`, and each time it reaches the size limit it is renamed with the suffix ``.1``. Each of the existing backup files is renamed to increment the suffix (``.1`` becomes ``.2``, etc.) and the ``.6`` file is erased. @@ -246,16 +248,16 @@ methods listed above, but this is how to log at custom log levels. :func:`getLogger` returns a reference to a logger instance with the specified -if it it is provided, or ``root`` if not. The names are period-separated +name if it is provided, or ``root`` if not. The names are period-separated hierarchical structures. Multiple calls to :func:`getLogger` with the same name will return a reference to the same logger object. Loggers that are further down in the hierarchical list are children of loggers higher up in the list. For example, given a logger with a name of ``foo``, loggers with names of -``foo.bar``, ``foo.bar.baz``, and ``foo.bam`` are all children of ``foo``. -Child loggers propagate messages up to their parent loggers. Because of this, -it is unnecessary to define and configure all the loggers an application uses. -It is sufficient to configure a top-level logger and create child loggers as -needed. +``foo.bar``, ``foo.bar.baz``, and ``foo.bam`` are all descendants of ``foo``. +Child loggers propagate messages up to the handlers associated with their +ancestor loggers. Because of this, it is unnecessary to define and configure +handlers for all the loggers an application uses. It is sufficient to +configure handlers for a top-level logger and create child loggers as needed. Handlers @@ -283,15 +285,16 @@ are there two :func:`setLevel` methods? The level set in the logger determines which severity of messages it will pass to its handlers. The level set in each handler determines which messages that handler will send on. - :func:`setFormatter` selects a Formatter object for this handler to use. + +* :func:`setFormatter` selects a Formatter object for this handler to use. * :func:`addFilter` and :func:`removeFilter` respectively configure and deconfigure filter objects on handlers. -Application code should not directly instantiate and use handlers. Instead, the -:class:`Handler` class is a base class that defines the interface that all -Handlers should have and establishes some default behavior that child classes -can use (or override). +Application code should not directly instantiate and use instances of +:class:`Handler`. Instead, the :class:`Handler` class is a base class that +defines the interface that all handlers should have and establishes some +default behavior that child classes can use (or override). Formatters @@ -510,7 +513,9 @@ can have zero, one or more handlers associated with it (via the :meth:`addHandler` method of :class:`Logger`). In addition to any handlers directly associated with a logger, *all handlers associated with all ancestors -of the logger* are called to dispatch the message. +of the logger* are called to dispatch the message (unless the *propagate* flag +for a logger is set to a false value, at which point the passing to ancestor +handlers stops). Just as for loggers, handlers can have levels associated with them. A handler's level acts as a filter in the same way as a logger's level does. If a handler @@ -712,7 +717,11 @@ Provides an overriding level *lvl* for all loggers which takes precedence over the logger's own level. When the need arises to temporarily throttle logging - output down across the whole application, this function can be useful. + output down across the whole application, this function can be useful. Its + effect is to disable all logging calls of severity *lvl* and below, so that + if you call it with a value of INFO, then all INFO and DEBUG events would be + discarded, whereas those of severity WARNING and above would be processed + according to the logger's effective level. .. function:: addLevelName(lvl, levelName) @@ -748,12 +757,12 @@ Does basic configuration for the logging system by creating a :class:`StreamHandler` with a default :class:`Formatter` and adding it to the - root logger. The function does nothing if any handlers have been defined for - the root logger. The functions :func:`debug`, :func:`info`, :func:`warning`, + root logger. The functions :func:`debug`, :func:`info`, :func:`warning`, :func:`error` and :func:`critical` will call :func:`basicConfig` automatically if no handlers are defined for the root logger. - This function does nothing if the root logger already has handlers configured. + This function does nothing if the root logger already has handlers + configured for it. .. versionchanged:: 2.4 Formerly, :func:`basicConfig` did not take any keyword arguments. @@ -827,8 +836,8 @@ .. attribute:: Logger.propagate If this evaluates to false, logging messages are not passed by this logger or by - child loggers to higher level (ancestor) loggers. The constructor sets this - attribute to 1. + its child loggers to the handlers of higher level (ancestor) loggers. The + constructor sets this attribute to 1. .. method:: Logger.setLevel(lvl) @@ -1043,14 +1052,14 @@ logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)s %(message)s', - filename='/tmp/myapp.log', + filename='myapp.log', filemode='w') logging.debug('A debug message') logging.info('Some information') logging.warning('A shot across the bows') The :meth:`basicConfig` method is used to change the configuration defaults, -which results in output (written to ``/tmp/myapp.log``) which should look +which results in output (written to ``myapp.log``) which should look something like the following:: 2004-07-02 13:00:08,743 DEBUG A debug message @@ -1499,6 +1508,11 @@ 69 myapp.area2 WARNING Jail zesty vixen who grabbed pay from quack. 69 myapp.area2 ERROR The five boxing wizards jump quickly. +Note that there are some security issues with pickle in some scenarios. If +these affect you, you can use an alternative serialization scheme by overriding +the :meth:`makePickle` method and implementing your alternative there, as +well as adapting the above script to use your alternative serialization. + Using arbitrary objects as messages ----------------------------------- @@ -1659,14 +1673,14 @@ StreamHandler ^^^^^^^^^^^^^ -.. module:: logging.handlers - The :class:`StreamHandler` class, located in the core :mod:`logging` package, sends logging output to streams such as *sys.stdout*, *sys.stderr* or any file-like object (or, more precisely, any object which supports :meth:`write` and :meth:`flush` methods). +.. currentmodule:: logging + .. class:: StreamHandler([strm]) Returns a new instance of the :class:`StreamHandler` class. If *strm* is @@ -1850,6 +1864,11 @@ The extensions are date-and-time based, using the strftime format ``%Y-%m-%d_%H-%M-%S`` or a leading portion thereof, depending on the rollover interval. + + When computing the next rollover time for the first time (when the handler + is created), the last modification time of an existing log file, or else + the current time, is used to compute when the next rotation will occur. + If the *utc* argument is true, times in UTC will be used; otherwise local time is used. @@ -1922,6 +1941,11 @@ Pickles the record's attribute dictionary in binary format with a length prefix, and returns it ready for transmission across the socket. + Note that pickles aren't completely secure. If you are concerned about + security, you may want to override this method to implement a more secure + mechanism. For example, you can sign pickles using HMAC and then verify + them on the receiving end, or alternatively you can disable unpickling of + global objects on the receiving end. .. method:: send(packet) @@ -2002,6 +2026,85 @@ or integers - if strings are passed, internal mapping dictionaries are used to convert them to integers. + The symbolic ``LOG_`` values are defined in :class:`SysLogHandler` and + mirror the values defined in the ``sys/syslog.h`` header file. + + **Priorities** + + +--------------------------+---------------+ + | Name (string) | Symbolic value| + +==========================+===============+ + | ``alert`` | LOG_ALERT | + +--------------------------+---------------+ + | ``crit`` or ``critical`` | LOG_CRIT | + +--------------------------+---------------+ + | ``debug`` | LOG_DEBUG | + +--------------------------+---------------+ + | ``emerg`` or ``panic`` | LOG_EMERG | + +--------------------------+---------------+ + | ``err`` or ``error`` | LOG_ERR | + +--------------------------+---------------+ + | ``info`` | LOG_INFO | + +--------------------------+---------------+ + | ``notice`` | LOG_NOTICE | + +--------------------------+---------------+ + | ``warn`` or ``warning`` | LOG_WARNING | + +--------------------------+---------------+ + + **Facilities** + + +---------------+---------------+ + | Name (string) | Symbolic value| + +===============+===============+ + | ``auth`` | LOG_AUTH | + +---------------+---------------+ + | ``authpriv`` | LOG_AUTHPRIV | + +---------------+---------------+ + | ``cron`` | LOG_CRON | + +---------------+---------------+ + | ``daemon`` | LOG_DAEMON | + +---------------+---------------+ + | ``ftp`` | LOG_FTP | + +---------------+---------------+ + | ``kern`` | LOG_KERN | + +---------------+---------------+ + | ``lpr`` | LOG_LPR | + +---------------+---------------+ + | ``mail`` | LOG_MAIL | + +---------------+---------------+ + | ``news`` | LOG_NEWS | + +---------------+---------------+ + | ``syslog`` | LOG_SYSLOG | + +---------------+---------------+ + | ``user`` | LOG_USER | + +---------------+---------------+ + | ``uucp`` | LOG_UUCP | + +---------------+---------------+ + | ``local0`` | LOG_LOCAL0 | + +---------------+---------------+ + | ``local1`` | LOG_LOCAL1 | + +---------------+---------------+ + | ``local2`` | LOG_LOCAL2 | + +---------------+---------------+ + | ``local3`` | LOG_LOCAL3 | + +---------------+---------------+ + | ``local4`` | LOG_LOCAL4 | + +---------------+---------------+ + | ``local5`` | LOG_LOCAL5 | + +---------------+---------------+ + | ``local6`` | LOG_LOCAL6 | + +---------------+---------------+ + | ``local7`` | LOG_LOCAL7 | + +---------------+---------------+ + + .. method:: mapPriority(levelname) + + Maps a logging level name to a syslog priority name. + You may need to override this if you are using custom levels, or + if the default algorithm is not suitable for your needs. The + default algorithm maps ``DEBUG``, ``INFO``, ``WARNING``, ``ERROR`` and + ``CRITICAL`` to the equivalent syslog names, and all other level + names to "warning". .. _nt-eventlog-handler: @@ -2481,17 +2584,17 @@ ^^^^^^^^^^^^^^^^^^^^^^^^^ The configuration file format understood by :func:`fileConfig` is based on -ConfigParser functionality. The file must contain sections called ``[loggers]``, -``[handlers]`` and ``[formatters]`` which identify by name the entities of each -type which are defined in the file. For each such entity, there is a separate -section which identified how that entity is configured. Thus, for a logger named -``log01`` in the ``[loggers]`` section, the relevant configuration details are -held in a section ``[logger_log01]``. Similarly, a handler called ``hand01`` in -the ``[handlers]`` section will have its configuration held in a section called -``[handler_hand01]``, while a formatter called ``form01`` in the -``[formatters]`` section will have its configuration specified in a section -called ``[formatter_form01]``. The root logger configuration must be specified -in a section called ``[logger_root]``. +:mod:`ConfigParser` functionality. The file must contain sections called +``[loggers]``, ``[handlers]`` and ``[formatters]`` which identify by name the +entities of each type which are defined in the file. For each such entity, +there is a separate section which identifies how that entity is configured. +Thus, for a logger named ``log01`` in the ``[loggers]`` section, the relevant +configuration details are held in a section ``[logger_log01]``. Similarly, a +handler called ``hand01`` in the ``[handlers]`` section will have its +configuration held in a section called ``[handler_hand01]``, while a formatter +called ``form01`` in the ``[formatters]`` section will have its configuration +specified in a section called ``[formatter_form01]``. The root logger +configuration must be specified in a section called ``[logger_root]``. Examples of these sections in the file are given below. :: Modified: python/branches/release27-maint/Doc/library/logging.rst ============================================================================== --- python/branches/release27-maint/Doc/library/logging.rst (original) +++ python/branches/release27-maint/Doc/library/logging.rst Tue Jul 6 17:08:55 2010 @@ -248,7 +248,7 @@ methods listed above, but this is how to log at custom log levels. :func:`getLogger` returns a reference to a logger instance with the specified -if it is provided, or ``root`` if not. The names are period-separated +name if it is provided, or ``root`` if not. The names are period-separated hierarchical structures. Multiple calls to :func:`getLogger` with the same name will return a reference to the same logger object. Loggers that are further down in the hierarchical list are children of loggers higher up in the list. @@ -1590,6 +1590,11 @@ 69 myapp.area2 WARNING Jail zesty vixen who grabbed pay from quack. 69 myapp.area2 ERROR The five boxing wizards jump quickly. +Note that there are some security issues with pickle in some scenarios. If +these affect you, you can use an alternative serialization scheme by overriding +the :meth:`makePickle` method and implementing your alternative there, as +well as adapting the above script to use your alternative serialization. + Using arbitrary objects as messages ----------------------------------- From python-checkins at python.org Tue Jul 6 17:11:44 2010 From: python-checkins at python.org (mark.dickinson) Date: Tue, 6 Jul 2010 17:11:44 +0200 (CEST) Subject: [Python-checkins] r82610 - python/branches/py3k/Objects/floatobject.c Message-ID: <20100706151144.AE1A4EE992@mail.python.org> Author: mark.dickinson Date: Tue Jul 6 17:11:44 2010 New Revision: 82610 Log: Style nit. Modified: python/branches/py3k/Objects/floatobject.c Modified: python/branches/py3k/Objects/floatobject.c ============================================================================== --- python/branches/py3k/Objects/floatobject.c (original) +++ python/branches/py3k/Objects/floatobject.c Tue Jul 6 17:11:44 2010 @@ -1422,7 +1422,7 @@ round_up = 1; break; } - if (round_up == 1) { + if (round_up) { x += 2*half_eps; if (top_exp == DBL_MAX_EXP && x == ldexp((double)(2*half_eps), DBL_MANT_DIG)) From python-checkins at python.org Tue Jul 6 17:39:15 2010 From: python-checkins at python.org (mark.dickinson) Date: Tue, 6 Jul 2010 17:39:15 +0200 (CEST) Subject: [Python-checkins] r82611 - python/branches/py3k-dtoa Message-ID: <20100706153915.109B0EE9B1@mail.python.org> Author: mark.dickinson Date: Tue Jul 6 17:39:14 2010 New Revision: 82611 Log: Initialized merge tracking via "svnmerge" with revisions "1-82024" from svn+ssh://pythondev at svn.python.org/python/branches/py3k Modified: python/branches/py3k-dtoa/ (props changed) From python-checkins at python.org Tue Jul 6 17:55:29 2010 From: python-checkins at python.org (mark.dickinson) Date: Tue, 6 Jul 2010 17:55:29 +0200 (CEST) Subject: [Python-checkins] r82612 - in python/branches/py3k-dtoa: Demo/classes/Complex.py Demo/classes/Dates.py Demo/classes/Dbm.py Demo/classes/README Demo/classes/Range.py Demo/classes/Rev.py Demo/classes/Vec.py Demo/embed/Makefile Demo/embed/demo.c Demo/md5test/md5driver.py Demo/parser/test_parser.py Demo/parser/test_unparse.py Demo/parser/unparse.py Doc/README.txt Doc/c-api/arg.rst Doc/c-api/datetime.rst Doc/c-api/init.rst Doc/c-api/intro.rst Doc/c-api/number.rst Doc/c-api/unicode.rst Doc/data/refcounts.dat Doc/distutils/builtdist.rst Doc/documenting/building.rst Doc/documenting/index.rst Doc/documenting/markup.rst Doc/documenting/style.rst Doc/faq/gui.rst Doc/glossary.rst Doc/howto/functional.rst Doc/howto/unicode.rst Doc/library/2to3.rst Doc/library/calendar.rst Doc/library/codecs.rst Doc/library/contextlib.rst Doc/library/datetime.rst Doc/library/dis.rst Doc/library/http.server.rst Doc/library/importlib.rst Doc/library/logging.rst Doc/library/os.path.rst Doc/library/os.rst Doc/library/pdb.rst Doc/library/re.rst Doc/library/socket.rst Doc/library/ssl.rst Doc/library/stdtypes.rst Doc/library/string.rst Doc/library/struct.rst Doc/library/sys.rst Doc/library/sysconfig.rst Doc/library/unittest.rst Doc/library/urllib.parse.rst Doc/library/urllib.request.rst Doc/library/warnings.rst Doc/reference/compound_stmts.rst Doc/reference/datamodel.rst Doc/reference/introduction.rst Doc/reference/lexical_analysis.rst Doc/tools/sphinxext/pyspecific.py Doc/tutorial/classes.rst Doc/tutorial/controlflow.rst Doc/tutorial/introduction.rst Doc/using/mac.rst Doc/whatsnew/2.7.rst Doc/whatsnew/3.0.rst Doc/whatsnew/3.2.rst Grammar/Grammar Include/longobject.h Include/pyctype.h Include/traceback.h Include/unicodeobject.h Lib/_strptime.py Lib/contextlib.py Lib/ctypes/__init__.py Lib/ctypes/test/test_callbacks.py Lib/ctypes/test/test_win32.py Lib/dis.py Lib/distutils/msvc9compiler.py Lib/distutils/unixccompiler.py Lib/encodings/aliases.py Lib/encodings/cp858.py Lib/heapq.py Lib/http/cookiejar.py Lib/idlelib/textView.py Lib/importlib/__init__.py Lib/importlib/_bootstrap.py Lib/importlib/abc.py Lib/importlib/test/extension/test_case_sensitivity.py Lib/importlib/test/extension/test_finder.py Lib/importlib/test/extension/test_loader.py Lib/importlib/test/extension/test_path_hook.py Lib/importlib/test/import_/test_path.py Lib/importlib/test/regrtest.py Lib/importlib/test/source/test_abc_loader.py Lib/importlib/test/source/test_case_sensitivity.py Lib/importlib/test/source/test_file_loader.py Lib/importlib/test/source/test_finder.py Lib/importlib/test/source/test_path_hook.py Lib/importlib/test/source/test_source_encoding.py Lib/importlib/test/test_abc.py Lib/importlib/test/test_api.py Lib/importlib/test/test_util.py Lib/inspect.py Lib/lib2to3 Lib/lib2to3/fixes/fix_itertools_imports.py Lib/lib2to3/tests/test_fixers.py Lib/logging/config.py Lib/macpath.py Lib/ntpath.py Lib/os2emxpath.py Lib/pdb.doc Lib/pdb.py Lib/pickletools.py Lib/posixpath.py Lib/pydoc.py Lib/site.py Lib/smtpd.py Lib/subprocess.py Lib/test/test_audioop.py Lib/test/test_codeccallbacks.py Lib/test/test_codecs.py Lib/test/test_complex.py Lib/test/test_contextlib.py Lib/test/test_datetime.py Lib/test/test_descr.py Lib/test/test_dict.py Lib/test/test_dis.py Lib/test/test_enumerate.py Lib/test/test_exceptions.py Lib/test/test_extcall.py Lib/test/test_float.py Lib/test/test_genericpath.py Lib/test/test_getargs2.py Lib/test/test_http_cookiejar.py Lib/test/test_imp.py Lib/test/test_import.py Lib/test/test_inspect.py Lib/test/test_iter.py Lib/test/test_keywordonlyarg.py Lib/test/test_logging.py Lib/test/test_math.py Lib/test/test_optparse.py Lib/test/test_os.py Lib/test/test_parser.py Lib/test/test_property.py Lib/test/test_pyexpat.py Lib/test/test_runpy.py Lib/test/test_strtod.py Lib/test/test_subprocess.py Lib/test/test_syntax.py Lib/test/test_tokenize.py Lib/test/test_tuple.py Lib/test/test_unicode.py Lib/test/test_urllib.py Lib/test/test_xmlrpc_net.py Lib/urllib/parse.py Lib/urllib/request.py Lib/uuid.py Lib/warnings.py Misc/ACKS Misc/NEWS Misc/Vim/vimrc Modules/_ctypes/callproc.c Modules/_ctypes/libffi/fficonfig.py.in Modules/_ctypes/libffi_msvc/LICENSE Modules/_ctypes/libffi_msvc/README Modules/_ctypes/libffi_msvc/README.ctypes Modules/_ctypes/libffi_msvc/ffi.c Modules/_ctypes/libffi_msvc/ffi.h Modules/_ctypes/libffi_msvc/ffi_common.h Modules/_ctypes/libffi_msvc/fficonfig.h Modules/_ctypes/libffi_msvc/ffitarget.h Modules/_ctypes/libffi_msvc/prep_cif.c Modules/_ctypes/libffi_msvc/types.c Modules/_ctypes/libffi_msvc/win32.c Modules/_ctypes/libffi_msvc/win64.asm Modules/_math.c Modules/_scproxy.c Modules/_ssl.c Modules/_testcapimodule.c Modules/_time.c Modules/_time.h Modules/audioop.c Modules/datetimemodule.c Modules/mathmodule.c Modules/parsermodule.c Modules/posixmodule.c Modules/selectmodule.c Modules/timemodule.c Modules/xxmodule.c Objects/abstract.c Objects/bytes_methods.c Objects/descrobject.c Objects/enumobject.c Objects/exceptions.c Objects/floatobject.c Objects/frameobject.c Objects/typeobject.c Objects/unicodeobject.c PC/VS8.0/pythoncore.vcproj PCbuild/_ctypes.vcproj PCbuild/pythoncore.vcproj Parser/Python.asdl Parser/asdl_c.py Python/Python-ast.c Python/_warnings.c Python/ast.c Python/ceval.c Python/compile.c Python/getargs.c Python/import.c Python/pythonrun.c Python/sysmodule.c Python/traceback.c README Tools/README Tools/scripts Tools/scripts/patchcheck.py Tools/webchecker configure setup.py Message-ID: <20100706155529.F3BC4EEA13@mail.python.org> Author: mark.dickinson Date: Tue Jul 6 17:55:27 2010 New Revision: 82612 Log: Merged revisions 82028,82034-82035,82037-82038,82041,82043,82045,82049,82051,82053,82055,82057,82059,82061,82068,82070-82071,82073,82076,82084,82089-82090,82113-82115,82119,82125,82128,82131,82138,82146,82148,82152,82156,82159,82162-82163,82166,82168,82171,82180-82181,82184-82186,82190,82193-82194,82200,82202,82204,82206,82208,82211,82214,82220,82223,82226,82228,82230-82232,82234,82238,82244,82247,82252,82255,82259,82262-82263,82269-82270,82273,82278,82281,82283,82286,82288-82302,82304-82316,82318,82320-82321,82326,82328,82331,82333,82336,82342-82343,82346-82347,82349,82351,82354,82357-82360,82365,82370-82371,82373,82375-82377,82381,82383-82384,82386-82387,82391-82394,82402,82405,82407,82410,82413,82416-82417,82422,82430,82434,82437-82438,82440,82442-82443,82448,82452,82456,82462,82464-82465,82467-82468,82471-82472,82478,82480-82481,82484-82485,82487-82488,82495,82507,82510,82514-82524,82526-82527,82533,82535,82537-82538,82540-82542,82547,82550-82553,82555,82557-82561,82567,82570,82573,82576-82578,82585,82587,82589,82591,82593-82595,82597,82599-82601,82604,82607,82609-82610 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ................ r82028 | senthil.kumaran | 2010-06-16 18:44:57 +0100 (Wed, 16 Jun 2010) | 9 lines Merged revisions 82026 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r82026 | senthil.kumaran | 2010-06-16 23:07:32 +0530 (Wed, 16 Jun 2010) | 3 lines Addressing RDM's review comments on the doc change. ........ ................ r82034 | alexander.belopolsky | 2010-06-16 23:38:15 +0100 (Wed, 16 Jun 2010) | 6 lines Issue #9012: "Separate compilation of time and datetime modules." Segregated code shared between time and datetime modules into Modules/_time.c. Added a new header file, Modules/_time.h, which will be used instead of Include/timefuncs.h for declarations shared between time and datetime modules. ................ r82035 | victor.stinner | 2010-06-17 00:05:06 +0100 (Thu, 17 Jun 2010) | 4 lines Issue #9012: Add _time.c and _time.h to the Visual Studio project file Add these new files, added by r82034, to the pythoncore project. ................ r82037 | victor.stinner | 2010-06-17 00:33:54 +0100 (Thu, 17 Jun 2010) | 4 lines Issue #850997: mbcs encoding (Windows only) handles errors argument: strict mode raises unicode errors. The encoder only supports "strict" and "replace" error handlers, the decoder only supports "strict" and "ignore" error handlers. ................ r82038 | victor.stinner | 2010-06-17 00:48:49 +0100 (Thu, 17 Jun 2010) | 2 lines Issue #850997: Oops, I forgot the author of the patch: Mark Hammond ................ r82041 | r.david.murray | 2010-06-17 03:04:29 +0100 (Thu, 17 Jun 2010) | 16 lines Merged revisions 82039 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r82039 | r.david.murray | 2010-06-16 21:36:52 -0400 (Wed, 16 Jun 2010) | 10 lines #8720: fix inspect regression by teaching getsourcefile about linecache. The fix for issue 4050 caused a regression: before that fix, source lines in the linecache would eventually be found by inspect. After the fix inspect reports an error earlier, and the source isn't found. The fix for the fix is to have getsourcefile look in the linecache for the file and return the psuedo-filename if the source is there, just as it already returns it if there is a PEP 302 loader. ........ ................ r82043 | mark.dickinson | 2010-06-17 13:33:22 +0100 (Thu, 17 Jun 2010) | 6 lines Issue #9011: Remove buggy and unnecessary ST->AST compilation code dealing with unary minus applied to a constant. The removed code was mutating the ST, causing a second compilation to fail. (The peephole optimizer already takes care of optimizing this case, so there's no lost optimization opportunity here.) ................ r82045 | r.david.murray | 2010-06-17 14:23:18 +0100 (Thu, 17 Jun 2010) | 5 lines Don't use os.normcase when the result we are expecting is None. This worked fine on linux but fails on Windows. That may or may not be a but in normcase. ................ r82049 | senthil.kumaran | 2010-06-17 17:48:06 +0100 (Thu, 17 Jun 2010) | 9 lines Merged revisions 82047 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r82047 | senthil.kumaran | 2010-06-17 22:08:34 +0530 (Thu, 17 Jun 2010) | 3 lines Fix Issue4452 - Incorrect docstring of os.setpgrp ........ ................ r82051 | mark.dickinson | 2010-06-17 19:24:52 +0100 (Thu, 17 Jun 2010) | 2 lines Add note about changes to the `round` function between 2.x and 3.x. ................ r82053 | alexander.belopolsky | 2010-06-17 19:30:34 +0100 (Thu, 17 Jun 2010) | 2 lines Issue #6641: The datetime.strptime method now supports the %z directive. ................ r82055 | barry.warsaw | 2010-06-17 19:38:20 +0100 (Thu, 17 Jun 2010) | 2 lines Typo repair. ................ r82057 | victor.stinner | 2010-06-17 22:43:33 +0100 (Thu, 17 Jun 2010) | 2 lines Issue #8203: Fix IDLE Credits dialog: view_file() uses its encoding argument. ................ r82059 | victor.stinner | 2010-06-18 00:08:50 +0100 (Fri, 18 Jun 2010) | 5 lines Issue #6543: Write the traceback in the terminal encoding instead of utf-8. Fix the encoding of the modules filename. Reindent also traceback.h, just because I hate tabs :-) ................ r82061 | victor.stinner | 2010-06-18 00:17:37 +0100 (Fri, 18 Jun 2010) | 2 lines Issue #6543: Mention the author of the patch, Amaury Forgeot d'Arc ................ r82068 | senthil.kumaran | 2010-06-18 16:08:18 +0100 (Fri, 18 Jun 2010) | 3 lines Fix Issue1368368 - prompt_user_passwd() in FancyURLopener masks 401 Unauthorized error page ................ r82070 | alexander.belopolsky | 2010-06-18 17:22:00 +0100 (Fri, 18 Jun 2010) | 1 line Fixed a typo in a comment. ................ r82071 | alexander.belopolsky | 2010-06-18 17:57:49 +0100 (Fri, 18 Jun 2010) | 1 line Added a new line at the end of the file. ................ r82073 | alexander.belopolsky | 2010-06-18 19:44:37 +0100 (Fri, 18 Jun 2010) | 4 lines Issue #6641: Original commit for this issue, r82053, introduced a regression making datetime subclass' strptime return datetime rather than subclass instances. Fixed this bug and a few typos. ................ r82076 | jean-paul.calderone | 2010-06-18 21:03:54 +0100 (Fri, 18 Jun 2010) | 19 lines Merged revisions 82075 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r82075 | jean-paul.calderone | 2010-06-18 16:00:17 -0400 (Fri, 18 Jun 2010) | 12 lines Revert r60115 This revision introduced quoting for strings containing | based on a misunderstanding of the commonly used quoting rules used on Windows. | is interpreted by cmd.exe, not by the MS C runtime argv initializer. It only needs to be quoted if it is part of an argument passed through cmd.exe. See issue1300, issue7839, and issue8972. ........ ................ r82084 | victor.stinner | 2010-06-19 00:59:45 +0100 (Sat, 19 Jun 2010) | 6 lines Issue #8939: Improve arg.rst * Add :ctype: to Py_BEGIN_ALLOW_THREADS and int * "s" and "s#" formats of Py_BuildValue(): specify that the Python object type is str in the description ................ r82089 | jean-paul.calderone | 2010-06-19 20:54:48 +0100 (Sat, 19 Jun 2010) | 1 line merge forward from the python 2.x branch ................ r82090 | jean-paul.calderone | 2010-06-19 20:58:37 +0100 (Sat, 19 Jun 2010) | 1 line Revert r82089. Commit was intended for a branch. ................ r82113 | benjamin.peterson | 2010-06-20 16:25:14 +0100 (Sun, 20 Jun 2010) | 8 lines Blocked revisions 82112 via svnmerge ........ r82112 | benjamin.peterson | 2010-06-20 10:12:04 -0500 (Sun, 20 Jun 2010) | 1 line update emacs section ........ ................ r82114 | benjamin.peterson | 2010-06-20 16:27:07 +0100 (Sun, 20 Jun 2010) | 1 line update release schedule url ................ r82115 | benjamin.peterson | 2010-06-20 16:27:42 +0100 (Sun, 20 Jun 2010) | 1 line add copyright years ................ r82119 | mark.dickinson | 2010-06-20 21:01:04 +0100 (Sun, 20 Jun 2010) | 9 lines Merged revisions 82117 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r82117 | mark.dickinson | 2010-06-20 19:50:19 +0100 (Sun, 20 Jun 2010) | 1 line Merge test_strtod and test_float string-to-float conversion tests. ........ ................ r82125 | brett.cannon | 2010-06-21 03:49:35 +0100 (Mon, 21 Jun 2010) | 2 lines Move over to assertIs. ................ r82128 | alexander.belopolsky | 2010-06-21 16:21:14 +0100 (Mon, 21 Jun 2010) | 2 lines Issue #9005: Prevent utctimetuple() from producing year 0 or year 10,000. ................ r82131 | benjamin.peterson | 2010-06-21 16:37:16 +0100 (Mon, 21 Jun 2010) | 9 lines Merged revisions 82130 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r82130 | benjamin.peterson | 2010-06-21 10:27:46 -0500 (Mon, 21 Jun 2010) | 1 line fix finding visual studio 2008 on 64 bit #8854 ........ ................ r82138 | thomas.heller | 2010-06-21 17:00:31 +0100 (Mon, 21 Jun 2010) | 13 lines Merged revisions 82126-82127 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r82126 | thomas.heller | 2010-06-21 16:00:24 +0200 (Mo, 21 Jun 2010) | 1 line Fix #8959 by reverting revision 80761. ........ r82127 | thomas.heller | 2010-06-21 17:01:18 +0200 (Mo, 21 Jun 2010) | 2 lines Add tests for problems reported in issue 8959. ........ ................ r82146 | senthil.kumaran | 2010-06-22 03:42:52 +0100 (Tue, 22 Jun 2010) | 3 lines Minor docs issue. ................ r82148 | senthil.kumaran | 2010-06-22 03:57:23 +0100 (Tue, 22 Jun 2010) | 3 lines Minor comment formatting. ................ r82152 | alexander.belopolsky | 2010-06-22 15:07:33 +0100 (Tue, 22 Jun 2010) | 1 line Added more test cases ................ r82156 | benjamin.peterson | 2010-06-22 19:11:34 +0100 (Tue, 22 Jun 2010) | 10 lines Blocked revisions 82155 via svnmerge ........ r82155 | benjamin.peterson | 2010-06-22 13:09:02 -0500 (Tue, 22 Jun 2010) | 4 lines keep UserDict an old-style class Be generous in abc.py to allow this. ........ ................ r82159 | benjamin.peterson | 2010-06-22 20:21:52 +0100 (Tue, 22 Jun 2010) | 9 lines Merged revisions 82157 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r82157 | benjamin.peterson | 2010-06-22 14:16:37 -0500 (Tue, 22 Jun 2010) | 1 line remove INT_MAX assertions; they can fail with large Py_ssize_t #9058 ........ ................ r82162 | benjamin.peterson | 2010-06-22 20:52:02 +0100 (Tue, 22 Jun 2010) | 8 lines Blocked revisions 82161 via svnmerge ........ r82161 | benjamin.peterson | 2010-06-22 14:49:47 -0500 (Tue, 22 Jun 2010) | 1 line bump revision ........ ................ r82163 | benjamin.peterson | 2010-06-22 21:02:39 +0100 (Tue, 22 Jun 2010) | 9 lines Merged revisions 82160 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r82160 | benjamin.peterson | 2010-06-22 14:45:51 -0500 (Tue, 22 Jun 2010) | 1 line spacing nit; this isn't C ........ ................ r82166 | benjamin.peterson | 2010-06-22 21:29:32 +0100 (Tue, 22 Jun 2010) | 9 lines Merged revisions 82165 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r82165 | benjamin.peterson | 2010-06-22 15:26:20 -0500 (Tue, 22 Jun 2010) | 1 line must force gc here ........ ................ r82168 | benjamin.peterson | 2010-06-22 21:34:34 +0100 (Tue, 22 Jun 2010) | 9 lines Merged revisions 82167 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r82167 | benjamin.peterson | 2010-06-22 15:32:02 -0500 (Tue, 22 Jun 2010) | 1 line mark ref counting as impl detail ........ ................ r82171 | antoine.pitrou | 2010-06-22 22:49:39 +0100 (Tue, 22 Jun 2010) | 10 lines Merged revisions 82169 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r82169 | antoine.pitrou | 2010-06-22 23:42:05 +0200 (mar., 22 juin 2010) | 4 lines Fix misindents in compile.c (for Benjamin). Of course, whoever used the wrong indentation rules needs to be spanked. ........ ................ r82180 | stefan.krah | 2010-06-23 19:35:33 +0100 (Wed, 23 Jun 2010) | 8 lines Blocked revisions 82177 via svnmerge ........ r82177 | stefan.krah | 2010-06-23 20:12:09 +0200 (Wed, 23 Jun 2010) | 3 lines Issue #8930: Remaining indentation fixes after the Grand Unified Indenting. ........ ................ r82181 | stefan.krah | 2010-06-23 19:42:39 +0100 (Wed, 23 Jun 2010) | 3 lines Issue #8930: Remaining indentation fixes after the Grand Unified Indenting. ................ r82184 | alexander.belopolsky | 2010-06-23 22:40:15 +0100 (Wed, 23 Jun 2010) | 1 line Issue #9051: Instances of timezone class can now be pickled. ................ r82185 | alexander.belopolsky | 2010-06-23 23:29:48 +0100 (Wed, 23 Jun 2010) | 1 line Test future pickle protocols. Thanks Antoine Pitrou for suggestion. ................ r82186 | alexander.belopolsky | 2010-06-23 23:58:49 +0100 (Wed, 23 Jun 2010) | 1 line Added more test cases ................ r82190 | benjamin.peterson | 2010-06-24 01:17:03 +0100 (Thu, 24 Jun 2010) | 9 lines Merged revisions 82189 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r82189 | benjamin.peterson | 2010-06-23 19:12:40 -0500 (Wed, 23 Jun 2010) | 1 line prevent assignment to set literals ........ ................ r82193 | stefan.krah | 2010-06-24 11:22:10 +0100 (Thu, 24 Jun 2010) | 10 lines Blocked revisions 82191 via svnmerge ........ r82191 | stefan.krah | 2010-06-24 11:33:05 +0200 (Thu, 24 Jun 2010) | 5 lines Issue #9020: The Py_IS* macros from pyctype.h should generally only be used with signed/unsigned char arguments. For integer arguments, EOF has to be handled separately. ........ ................ r82194 | stefan.krah | 2010-06-24 11:25:08 +0100 (Thu, 24 Jun 2010) | 3 lines Add specification for the Py_IS* macros in pyctype.h. ................ r82200 | victor.stinner | 2010-06-24 23:08:25 +0100 (Thu, 24 Jun 2010) | 3 lines Issue #8949: "z" format of PyArg_Parse*() functions doesn't accept bytes objects, as described in the documentation. ................ r82202 | victor.stinner | 2010-06-24 23:31:12 +0100 (Thu, 24 Jun 2010) | 2 lines PyArg_Parse*() functions: factorize code for s/z and u/Z formats ................ r82204 | antoine.pitrou | 2010-06-24 23:34:04 +0100 (Thu, 24 Jun 2010) | 5 lines Issue #8682: The ssl module now temporary increments the reference count of a socket object got through `PyWeakref_GetObject`, so as to avoid possible deallocation while the object is still being used. ................ r82206 | victor.stinner | 2010-06-24 23:57:10 +0100 (Thu, 24 Jun 2010) | 2 lines getbuffer(): release the buffer on error (if the buffer is not contiguous) ................ r82208 | victor.stinner | 2010-06-25 01:02:38 +0100 (Fri, 25 Jun 2010) | 3 lines Issue #8850: Remove "w" and "w#" formats from PyArg_Parse*() functions, use "w*" format instead. Add tests for "w*" format. ................ r82211 | antoine.pitrou | 2010-06-25 01:07:34 +0100 (Fri, 25 Jun 2010) | 10 lines Merged revisions 82210 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r82210 | antoine.pitrou | 2010-06-25 02:03:21 +0200 (ven., 25 juin 2010) | 4 lines Issue #9075: In the ssl module, remove the setting of a `debug` flag on an OpenSSL structure. ........ ................ r82214 | ezio.melotti | 2010-06-25 11:56:11 +0100 (Fri, 25 Jun 2010) | 1 line #9018: os.path.normcase() now raises a TypeError if the argument is not str or bytes. ................ r82220 | benjamin.peterson | 2010-06-25 20:30:21 +0100 (Fri, 25 Jun 2010) | 1 line only take into account positional arguments count in related error messages ................ r82223 | mark.dickinson | 2010-06-25 21:22:24 +0100 (Fri, 25 Jun 2010) | 9 lines Merged revisions 82221 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r82221 | mark.dickinson | 2010-06-25 21:19:48 +0100 (Fri, 25 Jun 2010) | 1 line Fix indentation of Python code example in C comment. ........ ................ r82226 | benjamin.peterson | 2010-06-25 21:37:22 +0100 (Fri, 25 Jun 2010) | 9 lines Merged revisions 82225 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r82225 | benjamin.peterson | 2010-06-25 15:34:01 -0500 (Fri, 25 Jun 2010) | 1 line mark implementation detail as such ........ ................ r82228 | benjamin.peterson | 2010-06-25 22:24:10 +0100 (Fri, 25 Jun 2010) | 8 lines Blocked revisions 82227 via svnmerge ........ r82227 | benjamin.peterson | 2010-06-25 16:19:04 -0500 (Fri, 25 Jun 2010) | 1 line this must be a typo ........ ................ r82230 | benjamin.peterson | 2010-06-26 00:02:11 +0100 (Sat, 26 Jun 2010) | 9 lines Merged revisions 82229 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r82229 | benjamin.peterson | 2010-06-25 17:58:47 -0500 (Fri, 25 Jun 2010) | 1 line mark implementation detail as such ........ ................ r82231 | benjamin.peterson | 2010-06-26 00:24:35 +0100 (Sat, 26 Jun 2010) | 1 line fix typos ................ r82232 | benjamin.peterson | 2010-06-26 00:37:15 +0100 (Sat, 26 Jun 2010) | 1 line remove old, outdated tool ................ r82234 | r.david.murray | 2010-06-26 01:17:12 +0100 (Sat, 26 Jun 2010) | 9 lines Merged revisions 82233 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r82233 | r.david.murray | 2010-06-25 20:06:44 -0400 (Fri, 25 Jun 2010) | 2 lines #4640: add a test to optparse that proves issue is invalid. ........ ................ r82238 | alexander.belopolsky | 2010-06-26 03:15:07 +0100 (Sat, 26 Jun 2010) | 11 lines Merged revisions 82236 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r82236 | alexander.belopolsky | 2010-06-25 22:05:19 -0400 (Fri, 25 Jun 2010) | 4 lines Issue #9024: Fixed mark-up for PyDateTime_IMPORT macro and added that it is typically used in module initialization function. Thanks Tim Golden for the patch. ........ ................ r82244 | r.david.murray | 2010-06-26 04:34:33 +0100 (Sat, 26 Jun 2010) | 9 lines Merged revisions 82242 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r82242 | r.david.murray | 2010-06-25 23:27:32 -0400 (Fri, 25 Jun 2010) | 2 lines Fix indentation in recently added test. ........ ................ r82247 | r.david.murray | 2010-06-26 19:44:14 +0100 (Sat, 26 Jun 2010) | 14 lines Blocked revisions 82246 via svnmerge ........ r82246 | r.david.murray | 2010-06-26 14:39:50 -0400 (Sat, 26 Jun 2010) | 8 lines #9085: email versions have gotten out of sync, 2.7 is actually 4.0.3. In 2.5 the email version was bumped to 4.0.2 just before release but after the maintenance branch was set up. The bump was not backported to trunk, and 2.6 went out the door with a version number of 4.0.1. I bumped this to 4.0.2 because of a behavior change, but that makes it look the same as 2.5. So bump it again to 4.0.3. ........ ................ r82252 | ezio.melotti | 2010-06-26 19:50:39 +0100 (Sat, 26 Jun 2010) | 9 lines Merged revisions 82248 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r82248 | ezio.melotti | 2010-06-26 21:44:42 +0300 (Sat, 26 Jun 2010) | 1 line Fix extra space. ........ ................ r82255 | alexander.belopolsky | 2010-06-26 19:57:02 +0100 (Sat, 26 Jun 2010) | 9 lines Merged revisions 82251 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r82251 | alexander.belopolsky | 2010-06-26 14:49:10 -0400 (Sat, 26 Jun 2010) | 1 line Issue 9024: Added :cdata: tag to PyDateTimeAPI ........ ................ r82259 | brett.cannon | 2010-06-26 23:29:06 +0100 (Sat, 26 Jun 2010) | 6 lines Having CFLAGS come before OPT prevents silencing certain classes of warnings from the fact that OPT contains -Wall be default. This is annoying when compilers like clang have thorough debugging information about things that Python does extensively (e.g. -Wunused-value for unused return values caused by a macro use). ................ r82262 | georg.brandl | 2010-06-27 11:17:12 +0100 (Sun, 27 Jun 2010) | 1 line #9078: fix some Unicode C API descriptions, in comments and docs. ................ r82263 | georg.brandl | 2010-06-27 11:37:48 +0100 (Sun, 27 Jun 2010) | 1 line #9064: accept number of frames for "up" and "down" commands in pdb. ................ r82269 | georg.brandl | 2010-06-27 11:59:19 +0100 (Sun, 27 Jun 2010) | 1 line Wording fix. ................ r82270 | georg.brandl | 2010-06-27 12:24:03 +0100 (Sun, 27 Jun 2010) | 1 line Untabify. ................ r82273 | ronald.oussoren | 2010-06-27 13:37:46 +0100 (Sun, 27 Jun 2010) | 15 lines Merged revisions 82272 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r82272 | ronald.oussoren | 2010-06-27 14:36:16 +0200 (Sun, 27 Jun 2010) | 8 lines Two small fixes for the support for SDKs on MacOSX: 1) The code that checks if an path should be located in the SDK explicitly excludes /usr/local. This fixes issue9046 2) The SDK variant for filtering "db_dirs_to_check" in setup.py was not doing anything because of a missing assignment. ........ ................ r82278 | ronald.oussoren | 2010-06-27 13:45:47 +0100 (Sun, 27 Jun 2010) | 12 lines Merged revisions 82276 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r82276 | ronald.oussoren | 2010-06-27 14:43:47 +0200 (Sun, 27 Jun 2010) | 5 lines The uuid library on OSX 10.5 seems to contain the same bug as the one on OSX 10.6, therefore don't use it there either. This fixes issue8621. ........ ................ r82281 | ronald.oussoren | 2010-06-27 13:51:31 +0100 (Sun, 27 Jun 2010) | 19 lines Merged revisions 82150 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r82150 | ronald.oussoren | 2010-06-22 11:32:22 +0200 (Tue, 22 Jun 2010) | 12 lines The code in _scproxy (a mac specific helper module to detect proxy settings) had the wrong logic for detecting if the checkbox 'Exclude simple hostnames' is checked. This checkin fixes that. As a result the test failure 'Issue8455' goes away on systems where the checkbox is not checked. I'm carefully avoiding saying that is fixes that issue, test_urllib2_localnet assumes that system proxy settings are empty (not just on OSX, see Issue8455 for details). ........ ................ r82283 | georg.brandl | 2010-06-27 14:28:06 +0100 (Sun, 27 Jun 2010) | 8 lines Blocked revisions 82271 via svnmerge ........ r82271 | georg.brandl | 2010-06-27 13:24:15 +0200 (So, 27 Jun 2010) | 1 line Untabify. ........ ................ r82286 | ronald.oussoren | 2010-06-27 15:26:30 +0100 (Sun, 27 Jun 2010) | 11 lines Merged revisions 82284 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r82284 | ronald.oussoren | 2010-06-27 15:59:39 +0200 (Sun, 27 Jun 2010) | 4 lines Fix for Issue8883: without this patch test_urllib will fail when there is a bare IP address in the "Bypass proxy settings for these Hosts & Domains" list on MacOSX. ........ ................ r82288 | mark.dickinson | 2010-06-27 18:36:54 +0100 (Sun, 27 Jun 2010) | 1 line Issue #9089: PyNumber_Int is no more. Remove it from the docs. ................ r82289 | mark.dickinson | 2010-06-27 19:18:01 +0100 (Sun, 27 Jun 2010) | 1 line Issue #9089: Remove intobject.h from MSVC project files. ................ r82290 | mark.dickinson | 2010-06-27 19:19:09 +0100 (Sun, 27 Jun 2010) | 1 line Issue #9089: Remove references to intobject.c and intobject.h from comments. ................ r82291 | brett.cannon | 2010-06-27 21:40:18 +0100 (Sun, 27 Jun 2010) | 1 line Revert r82259; still no good way to override instead of replace OPT, but changing order alters pydebug optimization flags. ................ r82292 | benjamin.peterson | 2010-06-27 21:50:37 +0100 (Sun, 27 Jun 2010) | 451 lines Blocked revisions 79620,79624-79625,79633-79637,79639-79640,79650-79651,79654,79673,79693,79695,79697-79698,79704,79706-79707,79710,79712-79714,79718-79719,79722,79730,79744,79750,79755,79760,79769,79808,79811,79890,80062,80065,80082,80086,80171,80189,80242-80243,80374,80411-80412,80445,80579-80581,80700,80737,80745,80752,80794,80813-80814,80823,80963,80982,81012-81013,81030,81035,81088,81140-81141,81149-81151,81275,81484,81502,81517,81561,81705,81847,81919,81964,82056,82136-82137,82142,82149 via svnmerge ........ r79620 | brian.curtin | 2010-04-02 16:18:14 -0500 (Fri, 02 Apr 2010) | 9 lines Implement #7347. Add CreateKeyEx, DeleteKeyEx, and update _winreg tests. *ReflectionKey functions used to not be documented or tested, but they are now sufficiently documented and tested on platforms where they apply. Additionally, fixed a bug in QueryReflectionKey which was returning an incorrect value. All tests pass from XP through Windows 7, on 32 and 64-bit platforms. ........ r79624 | ezio.melotti | 2010-04-02 16:43:10 -0500 (Fri, 02 Apr 2010) | 1 line Fix test_compiler.py that was using unittest.__file__ to find Lib/ (unittest is now a package). ........ r79625 | brian.curtin | 2010-04-02 16:51:37 -0500 (Fri, 02 Apr 2010) | 2 lines Add a line about #7347 to Misc\News ........ r79633 | brian.curtin | 2010-04-02 18:26:06 -0500 (Fri, 02 Apr 2010) | 14 lines Implement #1220212. Add os.kill support for Windows. os.kill takes one of two newly added signals, CTRL_C_EVENT and CTRL_BREAK_EVENT, or any integer value. The events are a special case which work with subprocess console applications which implement a special console control handler. Any other value but those two will cause os.kill to use TerminateProcess, outright killing the process. This change adds win_console_handler.py, which is a script to implement SetConsoleCtrlHandler and applicable handler function, using ctypes. subprocess also gets another attribute which is a necessary flag to creationflags in Popen in order to send the CTRL events. ........ r79634 | brian.curtin | 2010-04-02 18:31:28 -0500 (Fri, 02 Apr 2010) | 2 lines Add note about #1220212 (os.kill on Windows) ........ r79635 | benjamin.peterson | 2010-04-02 18:31:40 -0500 (Fri, 02 Apr 2010) | 1 line set svn:eol-style on new file ........ r79636 | benjamin.peterson | 2010-04-02 18:59:41 -0500 (Fri, 02 Apr 2010) | 4 lines always check _PyString_Resize for error also normalize how this error is checked ........ r79637 | raymond.hettinger | 2010-04-02 19:39:26 -0500 (Fri, 02 Apr 2010) | 1 line Clear cyclical references in list based OrderedDict. ........ r79639 | benjamin.peterson | 2010-04-02 19:57:33 -0500 (Fri, 02 Apr 2010) | 1 line more _PyString_Resize error checking ........ r79640 | brian.curtin | 2010-04-02 19:59:32 -0500 (Fri, 02 Apr 2010) | 3 lines Fix assertRaises usage on reflection functions which should raise NotImplementedError on Windows XP and below. ........ r79650 | raymond.hettinger | 2010-04-02 22:14:28 -0500 (Fri, 02 Apr 2010) | 1 line Improve clear() method. Keeps key/value refcnts >= 1 until final dict.clear() so that decrefs to zero won't trigger arbitrary code . Also runs a bit faster. ........ r79651 | raymond.hettinger | 2010-04-03 02:57:09 -0500 (Sat, 03 Apr 2010) | 1 line Factor-out constant expressions ........ r79654 | victor.stinner | 2010-04-03 03:40:16 -0500 (Sat, 03 Apr 2010) | 5 lines Issue #8227: Fix C API documentation, argument parsing * 'z', 'z#', 'z*' does also accept Unicode * unify types name: replace "string or Unicode objet" by "string or Unicode" ........ r79673 | brian.curtin | 2010-04-03 08:58:39 -0500 (Sat, 03 Apr 2010) | 2 lines Add missing return statement in an error condition. ........ r79693 | benjamin.peterson | 2010-04-03 10:38:38 -0500 (Sat, 03 Apr 2010) | 1 line wrap ........ r79695 | benjamin.peterson | 2010-04-03 10:40:29 -0500 (Sat, 03 Apr 2010) | 1 line remove unneeded argument ........ r79697 | benjamin.peterson | 2010-04-03 10:44:56 -0500 (Sat, 03 Apr 2010) | 1 line silence PyCObject warnings in bsddb ........ r79698 | benjamin.peterson | 2010-04-03 10:45:59 -0500 (Sat, 03 Apr 2010) | 1 line spelling ........ r79704 | benjamin.peterson | 2010-04-03 10:58:15 -0500 (Sat, 03 Apr 2010) | 1 line remove deprecation warnings silence attempting ........ r79706 | benjamin.peterson | 2010-04-03 11:06:42 -0500 (Sat, 03 Apr 2010) | 1 line stop CObject deprecation warnings in test___all__ ........ r79707 | mark.dickinson | 2010-04-03 11:41:20 -0500 (Sat, 03 Apr 2010) | 5 lines Ensure 'module removed' warning messages contain the word 'module' or 'package'. This should fix the test_py3kwarn failure on OS X. test_support.import_module also requires this. ........ r79710 | mark.dickinson | 2010-04-03 11:54:02 -0500 (Sat, 03 Apr 2010) | 1 line Replace backquotes with repr(), to silence a SyntaxWarning. ........ r79712 | raymond.hettinger | 2010-04-03 12:10:05 -0500 (Sat, 03 Apr 2010) | 1 line Silence a compiler warning. ........ r79713 | raymond.hettinger | 2010-04-03 13:10:37 -0500 (Sat, 03 Apr 2010) | 1 line Add count() method to collections.deque(). ........ r79714 | mark.dickinson | 2010-04-03 13:17:54 -0500 (Sat, 03 Apr 2010) | 1 line Silence DeprecationWarnings from uses of has_key and <> in plat-mac. ........ r79718 | antoine.pitrou | 2010-04-03 16:42:18 -0500 (Sat, 03 Apr 2010) | 3 lines Remove useless (?) import from r79706 ........ r79719 | benjamin.peterson | 2010-04-03 16:50:40 -0500 (Sat, 03 Apr 2010) | 1 line import bsddb more robustly ........ r79722 | raymond.hettinger | 2010-04-03 17:34:15 -0500 (Sat, 03 Apr 2010) | 1 line Expand test coverage for deque.count(). ........ r79730 | raymond.hettinger | 2010-04-03 20:24:59 -0500 (Sat, 03 Apr 2010) | 1 line Issue 5479: Add functools.total_ordering class decorator. ........ r79744 | raymond.hettinger | 2010-04-04 02:33:46 -0500 (Sun, 04 Apr 2010) | 1 line Documentation nit ........ r79750 | raymond.hettinger | 2010-04-04 13:34:45 -0500 (Sun, 04 Apr 2010) | 1 line Add functools.CmpToKey() ........ r79755 | raymond.hettinger | 2010-04-04 16:45:01 -0500 (Sun, 04 Apr 2010) | 6 lines Add tests for cmp_to_key. Adopt PEP 8 compliant function name. Factor-out existing uses cmp_to_key. Update documentation to use internal pointers instead of external resource. ........ r79760 | raymond.hettinger | 2010-04-04 17:24:03 -0500 (Sun, 04 Apr 2010) | 1 line Add tests for functools.total_ordering. ........ r79769 | benjamin.peterson | 2010-04-04 18:23:22 -0500 (Sun, 04 Apr 2010) | 1 line fix dis on new style classes #8310 ........ r79808 | raymond.hettinger | 2010-04-05 13:53:43 -0500 (Mon, 05 Apr 2010) | 1 line Classes that override __eq__ also need to define __hash__. ........ r79811 | brian.curtin | 2010-04-05 14:04:23 -0500 (Mon, 05 Apr 2010) | 7 lines Fix a failing test on an apparently slow Windows buildbot. On slower Windows machines, waiting 0.1 seconds can sometimes not be enough for a subprocess to start and be ready to accept signals, causing the test to fail. One buildbot is also choking on input()/EOFError so that was changed to not depend on input. ........ r79890 | mark.dickinson | 2010-04-07 05:18:27 -0500 (Wed, 07 Apr 2010) | 4 lines Use some more interesting test values for (unsigned) long long ctypes tests, in the hope of getting more information about the test_ctypes failures on Sparc (see issue #8314). ........ r80062 | r.david.murray | 2010-04-13 15:57:40 -0500 (Tue, 13 Apr 2010) | 2 lines Issue #5277: Fix quote counting when parsing RFC 2231 encoded parameters. ........ r80065 | brian.curtin | 2010-04-13 21:24:24 -0500 (Tue, 13 Apr 2010) | 6 lines Add a small sleep to let a subprocess start before terminating it. David Bolen's buildbot isn't know for it's speed, and it seems that we may have been trying to kill the subprocess before it was fully initialized. I ran with this change on the bot itself and it seemed to work. ........ r80082 | georg.brandl | 2010-04-14 16:36:49 -0500 (Wed, 14 Apr 2010) | 1 line #8370: fix module name in backported doc addition. ........ r80086 | brian.curtin | 2010-04-14 19:40:40 -0500 (Wed, 14 Apr 2010) | 9 lines Fix os.kill tests to be more robust and work with slower machines. Rather than depending on some sleep value, start up an interpreter as a subprocess and communicate with it. Because subprocess pipes can't be read from until EOF and I want to read from them before that, use ctypes to peek by using PeekNamedPipe. Once the subprocess has written the message, then it is ready to roll and accept signals. After that, kill it. ........ r80171 | antoine.pitrou | 2010-04-18 06:16:24 -0500 (Sun, 18 Apr 2010) | 3 lines Fix bootstrap after r80166 ........ r80189 | victor.stinner | 2010-04-18 13:22:25 -0500 (Sun, 18 Apr 2010) | 1 line Revert r80166 (and r80171), restore Lib/platform.py. subprocess cannot be used in platform.py ........ r80242 | ronald.oussoren | 2010-04-20 03:53:12 -0500 (Tue, 20 Apr 2010) | 8 lines The PythonLauncher change is needed due to changes in how the BASECFLAGS and CFLAGS variables get filled by configure. The Mac/Makefile.in change ensures that pythonw gets build with the rigth deployment targets. ........ r80243 | ronald.oussoren | 2010-04-20 03:54:48 -0500 (Tue, 20 Apr 2010) | 3 lines This patch fixes the handling of a weak-linked variable and should fix issue #8095. ........ r80374 | antoine.pitrou | 2010-04-22 12:44:41 -0500 (Thu, 22 Apr 2010) | 3 lines Temporarily display OpenSSL version in verbose run -- trying to diagnose failure on Neal's buildbot. ........ r80411 | florent.xicluna | 2010-04-23 12:59:10 -0500 (Fri, 23 Apr 2010) | 2 lines Remove ImportWarnings filters. They become obsolete after r79310, issue #8205. ........ r80412 | florent.xicluna | 2010-04-23 13:10:12 -0500 (Fri, 23 Apr 2010) | 2 lines Fix the "regrtest -s" switch. ........ r80445 | brian.curtin | 2010-04-24 12:10:22 -0500 (Sat, 24 Apr 2010) | 2 lines Fix #5774. Some _winreg functions are documented as taking kwargs but don't. ........ r80579 | nick.coghlan | 2010-04-28 09:34:30 -0500 (Wed, 28 Apr 2010) | 1 line Also mention patch submitter's name in NEWS, not just in the commit message ........ r80580 | nick.coghlan | 2010-04-28 09:51:08 -0500 (Wed, 28 Apr 2010) | 1 line Issue 8202: when using the -m command line switch, sys.argv[0] is now '-m' instead of '-c' while searching for the module to be executed ........ r80581 | nick.coghlan | 2010-04-28 09:53:59 -0500 (Wed, 28 Apr 2010) | 1 line Add version changed note for -m tinkering with sys.argv[0] during the search process ........ r80700 | ronald.oussoren | 2010-05-02 04:55:57 -0500 (Sun, 02 May 2010) | 3 lines Small update to r80698 to ensure that webbrowser.open uses the default browser. ........ r80737 | brett.cannon | 2010-05-03 18:57:15 -0500 (Mon, 03 May 2010) | 4 lines Fix two potential uninitialization errors and an unneeded assignment. Found using Clang's static analyzer. ........ r80745 | brett.cannon | 2010-05-03 20:04:53 -0500 (Mon, 03 May 2010) | 5 lines Mention the code clean-up thanks to Clang's static analyzer in Modules. Was not applied to modules that will not compile under OS X, dbmmodule.c, getaddrinfo.c, and getnameinfo.c. ........ r80752 | victor.stinner | 2010-05-04 06:35:36 -0500 (Tue, 04 May 2010) | 4 lines _pyio: Fix TextIOWrapper constructor: os has no device_encoding() function _io module doesn't call this function which was introduced in Python3. ........ r80794 | barry.warsaw | 2010-05-05 11:17:22 -0500 (Wed, 05 May 2010) | 1 line NEWS ........ r80813 | brett.cannon | 2010-05-05 15:20:19 -0500 (Wed, 05 May 2010) | 4 lines Remove three unneeded variable assignments. Found using Clang's static analyzer. ........ r80814 | brett.cannon | 2010-05-05 15:24:30 -0500 (Wed, 05 May 2010) | 1 line Partially revert the over-reaching r80813. ........ r80823 | brett.cannon | 2010-05-05 15:54:53 -0500 (Wed, 05 May 2010) | 1 line Mention how Clang's static anaylzer was run over Objects/ and Python/. ........ r80963 | ronald.oussoren | 2010-05-08 03:44:37 -0500 (Sat, 08 May 2010) | 4 lines Fix for issue #7724: make it possible to build using the OSX 10.4u SDK on MacOSX 10.6 by honoring the specified SDK when looking for files. ........ r80982 | antoine.pitrou | 2010-05-08 10:23:57 -0500 (Sat, 08 May 2010) | 3 lines Revert r80963 - it broke compilation everywhere ........ r81012 | gregory.p.smith | 2010-05-08 18:38:49 -0500 (Sat, 08 May 2010) | 2 lines Fixes [issue7245] Better Ctrl-C support in pdb. ........ r81013 | gregory.p.smith | 2010-05-08 20:20:20 -0500 (Sat, 08 May 2010) | 5 lines Revert r81012. buildbot problems and its questionable of me to even add this to trunk while we're on the way to 2.7rc1. When fixed this can go into py3k first. Sorry. ........ r81030 | antoine.pitrou | 2010-05-09 10:15:11 -0500 (Sun, 09 May 2010) | 3 lines Fixup indentation of PC/_msi.c ........ r81035 | antoine.pitrou | 2010-05-09 13:32:48 -0500 (Sun, 09 May 2010) | 3 lines Remove spurious newlines, and add version number. ........ r81088 | brian.curtin | 2010-05-11 14:13:13 -0500 (Tue, 11 May 2010) | 13 lines #8575 - Update and reorganize some _winreg contents. I've removed the hopeful note about a future higher-level module since it's been in there for quite a long time and nothing of the sort has come up. There are a few places where markup was added to cross-reference other sections, and many of the external links have been removed and now point to newly created sections containing previously undocumented information. The Value Types section was created and it's contents were taken from a function-specific area, since it applies to more than just that function. It fits in better with the other newly documented constants. ........ r81140 | florent.xicluna | 2010-05-13 12:05:29 -0500 (Thu, 13 May 2010) | 3 lines Add sensible information about the OS X platform to diagnose issue #8423: test_pep277 fails on "x86 Tiger" buildbot but not on "PPC Tiger". ........ r81141 | florent.xicluna | 2010-05-13 13:16:06 -0500 (Thu, 13 May 2010) | 2 lines Revert the additional OS X information (r81140). Keep the endianness information. ........ r81149 | florent.xicluna | 2010-05-13 16:40:01 -0500 (Thu, 13 May 2010) | 2 lines Better test skipping, with message in the log. ........ r81150 | florent.xicluna | 2010-05-13 16:41:05 -0500 (Thu, 13 May 2010) | 2 lines Improve test feedback to troubleshoot issue #8423 on OS X. ........ r81151 | florent.xicluna | 2010-05-13 18:46:48 -0500 (Thu, 13 May 2010) | 2 lines Revert changeset r81150 which helped diagnose issue #8423 on some OS X buildbot. ........ r81275 | antoine.pitrou | 2010-05-17 14:56:59 -0500 (Mon, 17 May 2010) | 4 lines Issue #7079: Fix a possible crash when closing a file object while using it from another thread. Patch by Daniel Stutzbach. ........ r81484 | georg.brandl | 2010-05-22 16:26:21 -0500 (Sat, 22 May 2010) | 1 line NEWS rewrap and punctuation consistency. ........ r81502 | georg.brandl | 2010-05-24 16:37:54 -0500 (Mon, 24 May 2010) | 1 line #8616: update module name ........ r81517 | brian.curtin | 2010-05-25 10:06:15 -0500 (Tue, 25 May 2010) | 5 lines Fix #2810 - handle the case where some registry calls return ERROR_MORE_DATA, requiring another call to get the remaining data. Patch by Daniel Stutzbach ........ r81561 | alexander.belopolsky | 2010-05-26 15:57:04 -0500 (Wed, 26 May 2010) | 1 line Added Andrej Krpic. (Thanks for issue #7879 patch.) ........ r81705 | r.david.murray | 2010-06-04 14:51:06 -0500 (Fri, 04 Jun 2010) | 9 lines #4487: have Charset check with codecs for possible aliases. Previously, unexpected results occurred when email was passed, for example, 'utf8' as a charset name, since email would accept it but would *not* use the 'utf-8' codec for it, even though Python itself recognises that as an alias for utf-8. Now Charset checks with codecs for aliases as well as its own internal table. Issue 8898 has been opened to change this further in py3k so that all aliasing is routed through the codecs module. ........ r81847 | brian.curtin | 2010-06-08 16:15:06 -0500 (Tue, 08 Jun 2010) | 3 lines Move a variable declration outside of a loop to match what was done in r81843 for py3k. ........ r81919 | vinay.sajip | 2010-06-11 17:56:50 -0500 (Fri, 11 Jun 2010) | 1 line Issue #8924: logging: Improved error handling for Unicode in exception text. ........ r81964 | nick.coghlan | 2010-06-13 01:50:39 -0500 (Sun, 13 Jun 2010) | 1 line Revert r80580 due to some unintended side effects. See issue #8202 for details. ........ r82056 | florent.xicluna | 2010-06-17 15:30:56 -0500 (Thu, 17 Jun 2010) | 2 lines Add few words about test.test_genericpath.CommonTest ........ r82136 | benjamin.peterson | 2010-06-21 10:56:45 -0500 (Mon, 21 Jun 2010) | 1 line update pydoc-topics ........ r82137 | benjamin.peterson | 2010-06-21 10:57:57 -0500 (Mon, 21 Jun 2010) | 1 line bump verson to 2.7rc2 ........ r82142 | benjamin.peterson | 2010-06-21 12:28:30 -0500 (Mon, 21 Jun 2010) | 1 line towards final release ........ r82149 | ronald.oussoren | 2010-06-22 04:18:28 -0500 (Tue, 22 Jun 2010) | 11 lines Fix for issue8446: * Don't import 'ic' in webbrowser, that module is no longer used * Remove 'MacOS' from the list of modules that should emit a Py3kWarning on import. This is needed because one of the earlier tests triggers and import of this extension, and that causes a failure in test_py3kwarn (running test_py3kwarn separately worked fine) With these changes 'make tests' no longer says that test_py3kwarn fails. ........ ................ r82293 | benjamin.peterson | 2010-06-27 21:54:28 +0100 (Sun, 27 Jun 2010) | 13 lines Merged revisions 80712,81651 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r80712 | vinay.sajip | 2010-05-03 10:11:53 -0500 (Mon, 03 May 2010) | 1 line Issue #8576: logging updated to remove usage of find_unused_port(). ........ r81651 | vinay.sajip | 2010-06-02 05:05:31 -0500 (Wed, 02 Jun 2010) | 1 line Logging: improved error reporting for BaseConfigurator.resolve(). ........ ................ r82294 | benjamin.peterson | 2010-06-27 22:05:30 +0100 (Sun, 27 Jun 2010) | 174 lines Blocked revisions 80731-80736,80739,80741-80744,80746-80747,80807-80812,80815-80822,80843,80874 via svnmerge ........ r80731 | brett.cannon | 2010-05-03 18:41:23 -0500 (Mon, 03 May 2010) | 4 lines Remove unneeded variable initialization. Found using Clang's static analyzer. ........ r80732 | brett.cannon | 2010-05-03 18:41:51 -0500 (Mon, 03 May 2010) | 4 lines Remove an unused variable. Found using Clang's static analyzer. ........ r80733 | brett.cannon | 2010-05-03 18:42:40 -0500 (Mon, 03 May 2010) | 3 lines Clean up whitespace and remove unneeded variable initialization as found by Clang. ........ r80734 | brett.cannon | 2010-05-03 18:43:49 -0500 (Mon, 03 May 2010) | 4 lines Remove unneeded variable mutation and initializations. Found using Clang's static analyzer. ........ r80735 | brett.cannon | 2010-05-03 18:44:54 -0500 (Mon, 03 May 2010) | 4 lines Remove unneeded variable assignment. Found using Clang's static analyzer. ........ r80736 | brett.cannon | 2010-05-03 18:51:28 -0500 (Mon, 03 May 2010) | 4 lines Remove unused variables and a variable initialization. Found using Clang's static analyzer. ........ r80739 | brett.cannon | 2010-05-03 19:36:00 -0500 (Mon, 03 May 2010) | 4 lines Prevent a possible NULL de-reference and an unneeded variable assignment. Found using Clang's static analyzer. ........ r80741 | brett.cannon | 2010-05-03 19:48:11 -0500 (Mon, 03 May 2010) | 4 lines Fix a Py_DECREF to a Py_XDECREF. Found using Clang's static analyzer. ........ r80742 | brett.cannon | 2010-05-03 19:52:41 -0500 (Mon, 03 May 2010) | 4 lines Strip out extraneous whitespace, cast a some `const char *` to `void *` when passed to free() and make a `char *` to a `const char *` as found by Clang's static analyzer. ........ r80743 | brett.cannon | 2010-05-03 19:57:44 -0500 (Mon, 03 May 2010) | 4 lines Remove an unneeded variable assignment. Found using Clang's static analyzer. ........ r80744 | brett.cannon | 2010-05-03 20:01:00 -0500 (Mon, 03 May 2010) | 2 lines Fix some whitespace. ........ r80746 | brett.cannon | 2010-05-03 20:16:51 -0500 (Mon, 03 May 2010) | 4 lines Remove an unneeded variable and assignment. Found using Clang's static analyzer. ........ r80747 | brett.cannon | 2010-05-03 20:23:36 -0500 (Mon, 03 May 2010) | 4 lines Pull a NULL pointer check up to cover more cases in the function. Found using Clang's static analyzer. ........ r80807 | brett.cannon | 2010-05-05 15:14:27 -0500 (Wed, 05 May 2010) | 4 lines Remove an unnecessary variable. Found using Clang's static analyzer. ........ r80808 | brett.cannon | 2010-05-05 15:15:14 -0500 (Wed, 05 May 2010) | 2 lines Remove extraneous whitespace. ........ r80809 | brett.cannon | 2010-05-05 15:16:09 -0500 (Wed, 05 May 2010) | 4 lines Remove an unneeded variable increment. Found using Clang's static analyzer. ........ r80810 | brett.cannon | 2010-05-05 15:16:50 -0500 (Wed, 05 May 2010) | 4 lines Remove an unneeded variable. Found using Clang's static analyzer. ........ r80811 | brett.cannon | 2010-05-05 15:18:23 -0500 (Wed, 05 May 2010) | 4 lines Remove an unneeded variable assignment. Found using Clang's static analyzer. ........ r80812 | brett.cannon | 2010-05-05 15:19:26 -0500 (Wed, 05 May 2010) | 4 lines Remove an unneeded assignment. Found using Clang's static analyzer. ........ r80815 | brett.cannon | 2010-05-05 15:25:47 -0500 (Wed, 05 May 2010) | 1 line Fix whitespace. ........ r80816 | brett.cannon | 2010-05-05 15:26:58 -0500 (Wed, 05 May 2010) | 4 lines Remove an unneeded variable and fix a little whitespace. Found using Clang's static analyzer. ........ r80817 | brett.cannon | 2010-05-05 15:27:49 -0500 (Wed, 05 May 2010) | 4 lines Remove an unneeded variable increment. Found using Clang's static analyzer. ........ r80818 | brett.cannon | 2010-05-05 15:30:30 -0500 (Wed, 05 May 2010) | 8 lines Remove two unneeded branches to an 'if' statement by applying De Morgan's Law and creating a single 'if' statement along with a NULL default value for a variable. Also clean up a bunch of whitespace. Found using Clang's static analyzer. ........ r80819 | brett.cannon | 2010-05-05 15:35:24 -0500 (Wed, 05 May 2010) | 4 lines Remove an unnecessary variable assignment. Found using Clang's static analyzer. ........ r80820 | brett.cannon | 2010-05-05 15:38:52 -0500 (Wed, 05 May 2010) | 4 lines Change to a Py_XDECREF and fix some whitespace. Found using Clang's static analyzer. ........ r80821 | brett.cannon | 2010-05-05 15:50:03 -0500 (Wed, 05 May 2010) | 4 lines Explicitly add stdio.h and string.h to make strtod.c work standalone. Found using Clang's static analyzer. ........ r80822 | brett.cannon | 2010-05-05 15:53:20 -0500 (Wed, 05 May 2010) | 4 lines Remove an unneeded variable assignment. Found using Clang's static analyzer. ........ r80843 | brett.cannon | 2010-05-05 18:11:08 -0500 (Wed, 05 May 2010) | 1 line Revert a change where an expression is not needed now, but could be in the future. ........ r80874 | brett.cannon | 2010-05-06 12:56:36 -0500 (Thu, 06 May 2010) | 5 lines Add back in a line that was unneeded which advanced a pointer, but commented out as it is currently unneeded. This effectively adds back in the line removed in r80809 as a comment. ........ ................ r82295 | benjamin.peterson | 2010-06-27 22:15:09 +0100 (Sun, 27 Jun 2010) | 16 lines Blocked revisions 79925-79926,80397 via svnmerge ........ r79925 | nick.coghlan | 2010-04-10 09:24:36 -0500 (Sat, 10 Apr 2010) | 1 line Try to turn some buildbots green by allowing test_multiprocessing to pass even if it hits the sys.exc_clear code in the threading module, and improve the test coverage by making the ctypes dependencies a bit more granular (two of the cited ctypes objects don't exist on my system) ........ r79926 | nick.coghlan | 2010-04-10 10:01:54 -0500 (Sat, 10 Apr 2010) | 1 line Fix typo in comment ........ r80397 | sean.reifschneider | 2010-04-23 03:38:24 -0500 (Fri, 23 Apr 2010) | 2 lines Small comment documentation change to clarify "ident" selection. ........ ................ r82296 | benjamin.peterson | 2010-06-27 22:22:34 +0100 (Sun, 27 Jun 2010) | 12 lines Blocked revisions 80649,80710 via svnmerge ........ r80649 | tarek.ziade | 2010-04-30 07:15:12 -0500 (Fri, 30 Apr 2010) | 1 line Fixed #8577. distutils.sysconfig.get_python_inc() now differenciates buildir and srcdir ........ r80710 | brett.cannon | 2010-05-02 16:51:23 -0500 (Sun, 02 May 2010) | 1 line Update the Vim syntax highlight file. ........ ................ r82297 | benjamin.peterson | 2010-06-27 22:27:49 +0100 (Sun, 27 Jun 2010) | 16 lines Blocked revisions 80787,80793 via svnmerge ........ r80787 | ronald.oussoren | 2010-05-05 10:32:39 -0500 (Wed, 05 May 2010) | 5 lines Force exit using os._exit instead of sys.exit, this makes sure that the child does not continue testing. ........ r80793 | barry.warsaw | 2010-05-05 11:15:09 -0500 (Wed, 05 May 2010) | 5 lines Bug 7755: audiotest.au is arguably copyrighted material, but definitely makes Debian unhappy. The actual contents of the audio clip are unimportant, so replace it with something that we know is okay. Guido likes woodpeckers. ........ ................ r82298 | benjamin.peterson | 2010-06-27 22:45:24 +0100 (Sun, 27 Jun 2010) | 37 lines Merged revisions 81465-81466,81468,81679,81735,81760,81868,82183 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81465 | georg.brandl | 2010-05-22 06:29:19 -0500 (Sat, 22 May 2010) | 2 lines Issue #3924: Ignore cookies with invalid "version" field in cookielib. ........ r81466 | georg.brandl | 2010-05-22 06:31:16 -0500 (Sat, 22 May 2010) | 1 line Underscore the name of an internal utility function. ........ r81468 | georg.brandl | 2010-05-22 06:43:25 -0500 (Sat, 22 May 2010) | 1 line #8635: document enumerate() start parameter in docstring. ........ r81679 | benjamin.peterson | 2010-06-03 16:21:03 -0500 (Thu, 03 Jun 2010) | 1 line use a set for membership testing ........ r81735 | michael.foord | 2010-06-05 06:46:59 -0500 (Sat, 05 Jun 2010) | 1 line Extract error message truncating into a method (unittest.TestCase._truncateMessage). ........ r81760 | michael.foord | 2010-06-05 14:38:42 -0500 (Sat, 05 Jun 2010) | 1 line Issue 8302. SkipTest exception is setUpClass or setUpModule is now reported as a skip rather than an error. ........ r81868 | benjamin.peterson | 2010-06-09 14:45:04 -0500 (Wed, 09 Jun 2010) | 1 line fix code formatting ........ r82183 | benjamin.peterson | 2010-06-23 15:29:26 -0500 (Wed, 23 Jun 2010) | 1 line cpython only gc tests ........ ................ r82299 | benjamin.peterson | 2010-06-27 22:48:35 +0100 (Sun, 27 Jun 2010) | 13 lines Merged revisions 81881-81882 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81881 | andrew.kuchling | 2010-06-10 19:16:08 -0500 (Thu, 10 Jun 2010) | 1 line #5753: update demo.c to use PySys_SetArgvEx(), and add a comment ........ r81882 | andrew.kuchling | 2010-06-10 19:23:01 -0500 (Thu, 10 Jun 2010) | 1 line #5753: Suggest PySys_SetArgvEx() instead of PySys_SetArgv() ........ ................ r82300 | brett.cannon | 2010-06-27 22:49:22 +0100 (Sun, 27 Jun 2010) | 4 lines Add a link to PEP 3147 from the importlib docs. Closes issue 8667. Thanks Ashley Sands for the patch. ................ r82301 | benjamin.peterson | 2010-06-27 23:32:30 +0100 (Sun, 27 Jun 2010) | 303 lines Merged revisions 80605-80609,80642-80646,80651-80652,80674,80684-80686,80748,80852,80854,80870,80872-80873,80907,80915-80916,80951-80952,80976-80977,80985,81038-81040,81042,81053,81070,81104-81105,81114,81125,81245,81285,81402,81463,81516,81562-81563,81567,81593,81635,81680-81681,81684,81801,81888,81931-81933,81939-81942,81963,81984,81991,82120,82188,82264-82267 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r80605 | andrew.kuchling | 2010-04-28 19:22:16 -0500 (Wed, 28 Apr 2010) | 1 line Add various items ........ r80606 | andrew.kuchling | 2010-04-28 20:44:30 -0500 (Wed, 28 Apr 2010) | 6 lines Fix doubled 'the'. Markup fixes to use :exc:, :option: in a few places. (Glitch: unittest.main's -c ends up a link to the Python interpreter's -c option. Should we skip using :option: for that switch, or disable the auto-linking somehow?) ........ r80607 | andrew.kuchling | 2010-04-28 20:45:41 -0500 (Wed, 28 Apr 2010) | 1 line Add various unittest items ........ r80608 | benjamin.peterson | 2010-04-28 22:18:05 -0500 (Wed, 28 Apr 2010) | 1 line update pypy description ........ r80609 | benjamin.peterson | 2010-04-28 22:30:59 -0500 (Wed, 28 Apr 2010) | 1 line update pypy url ........ r80642 | andrew.kuchling | 2010-04-29 19:49:09 -0500 (Thu, 29 Apr 2010) | 1 line Always add space after RFC; reword paragraph ........ r80643 | andrew.kuchling | 2010-04-29 19:52:31 -0500 (Thu, 29 Apr 2010) | 6 lines Reword paragraph to make its meaning clearer. Antoine Pitrou: is my version of the paragraph still correct? R. David Murray: is this more understandable than the previous version? ........ r80644 | andrew.kuchling | 2010-04-29 20:02:15 -0500 (Thu, 29 Apr 2010) | 1 line Fix typos ........ r80645 | andrew.kuchling | 2010-04-29 20:32:47 -0500 (Thu, 29 Apr 2010) | 1 line Markup fix; clarify by adding 'in that order' ........ r80646 | andrew.kuchling | 2010-04-29 20:33:40 -0500 (Thu, 29 Apr 2010) | 1 line Add various items; rearrange unittest section a bit ........ r80651 | andrew.kuchling | 2010-04-30 08:46:55 -0500 (Fri, 30 Apr 2010) | 1 line Minor grammar re-wording ........ r80652 | andrew.kuchling | 2010-04-30 08:47:34 -0500 (Fri, 30 Apr 2010) | 1 line Add item ........ r80674 | andrew.kuchling | 2010-04-30 20:19:16 -0500 (Fri, 30 Apr 2010) | 1 line Add various items ........ r80684 | andrew.kuchling | 2010-05-01 07:05:52 -0500 (Sat, 01 May 2010) | 1 line Minor grammar fix ........ r80685 | andrew.kuchling | 2010-05-01 07:06:51 -0500 (Sat, 01 May 2010) | 1 line Describe memoryview ........ r80686 | antoine.pitrou | 2010-05-01 07:16:39 -0500 (Sat, 01 May 2010) | 4 lines Fix attribution. Travis didn't do much and he did a bad work. (yes, this is a sensitive subject, sorry) ........ r80748 | andrew.kuchling | 2010-05-03 20:24:22 -0500 (Mon, 03 May 2010) | 1 line Add some more items; the urlparse change is added twice ........ r80852 | andrew.kuchling | 2010-05-05 20:09:47 -0500 (Wed, 05 May 2010) | 1 line Reword paragraph; fix filename, which should be pyconfig.h ........ r80854 | andrew.kuchling | 2010-05-05 20:10:56 -0500 (Wed, 05 May 2010) | 1 line Add various items ........ r80870 | andrew.kuchling | 2010-05-06 09:14:09 -0500 (Thu, 06 May 2010) | 1 line Describe ElementTree 1.3; rearrange new-module sections; describe dict views as sets; small edits and items ........ r80872 | andrew.kuchling | 2010-05-06 12:21:59 -0500 (Thu, 06 May 2010) | 1 line Add 2 items; record ideas for two initial sections; clarify wording ........ r80873 | andrew.kuchling | 2010-05-06 12:27:57 -0500 (Thu, 06 May 2010) | 1 line Change section title; point to unittest2 ........ r80907 | andrew.kuchling | 2010-05-06 20:45:14 -0500 (Thu, 06 May 2010) | 1 line Add a new section on the development plan; add an item ........ r80915 | antoine.pitrou | 2010-05-07 05:15:51 -0500 (Fri, 07 May 2010) | 3 lines Fix some markup and a class name. Also, wrap a long line. ........ r80916 | andrew.kuchling | 2010-05-07 06:30:47 -0500 (Fri, 07 May 2010) | 1 line Re-word text ........ r80951 | andrew.kuchling | 2010-05-07 20:15:26 -0500 (Fri, 07 May 2010) | 1 line Add two items ........ r80952 | andrew.kuchling | 2010-05-07 20:35:55 -0500 (Fri, 07 May 2010) | 1 line Get accents correct ........ r80976 | andrew.kuchling | 2010-05-08 08:28:03 -0500 (Sat, 08 May 2010) | 1 line Add logging.dictConfig example; give up on writing a Ttk example ........ r80977 | andrew.kuchling | 2010-05-08 08:29:46 -0500 (Sat, 08 May 2010) | 1 line Markup fixes ........ r80985 | andrew.kuchling | 2010-05-08 10:39:46 -0500 (Sat, 08 May 2010) | 7 lines Write summary of the 2.7 release; rewrite the future section some more; mention PYTHONWARNINGS env. var; tweak some examples for readability. And with this commit, the "What's New" is done... except for a complete read-through to polish the text, and fixing any reported errors, but those tasks can easily wait until after beta2. ........ r81038 | benjamin.peterson | 2010-05-09 16:09:40 -0500 (Sun, 09 May 2010) | 1 line finish clause ........ r81039 | andrew.kuchling | 2010-05-10 09:18:27 -0500 (Mon, 10 May 2010) | 1 line Markup fix; re-word a sentence ........ r81040 | andrew.kuchling | 2010-05-10 09:20:12 -0500 (Mon, 10 May 2010) | 1 line Use title case ........ r81042 | andrew.kuchling | 2010-05-10 10:03:35 -0500 (Mon, 10 May 2010) | 1 line Link to unittest2 article ........ r81053 | florent.xicluna | 2010-05-10 14:59:22 -0500 (Mon, 10 May 2010) | 2 lines Add a link on maketrans(). ........ r81070 | andrew.kuchling | 2010-05-10 18:13:41 -0500 (Mon, 10 May 2010) | 1 line Fix typo ........ r81104 | andrew.kuchling | 2010-05-11 19:38:44 -0500 (Tue, 11 May 2010) | 1 line Revision pass: lots of edits, typo fixes, rearrangements ........ r81105 | andrew.kuchling | 2010-05-11 19:40:47 -0500 (Tue, 11 May 2010) | 1 line Let's call this done ........ r81114 | andrew.kuchling | 2010-05-12 08:56:07 -0500 (Wed, 12 May 2010) | 1 line Grammar fix ........ r81125 | andrew.kuchling | 2010-05-12 13:56:48 -0500 (Wed, 12 May 2010) | 1 line #8696: add documentation for logging.config.dictConfig (PEP 391) ........ r81245 | andrew.kuchling | 2010-05-16 18:31:16 -0500 (Sun, 16 May 2010) | 1 line Add cross-reference to later section ........ r81285 | vinay.sajip | 2010-05-18 03:16:27 -0500 (Tue, 18 May 2010) | 1 line Fixed minor typo in ReST markup. ........ r81402 | vinay.sajip | 2010-05-21 12:41:34 -0500 (Fri, 21 May 2010) | 1 line Updated logging documentation with more dictConfig information. ........ r81463 | georg.brandl | 2010-05-22 03:17:23 -0500 (Sat, 22 May 2010) | 1 line #8785: less confusing description of regex.find*. ........ r81516 | andrew.kuchling | 2010-05-25 08:34:08 -0500 (Tue, 25 May 2010) | 1 line Add three items ........ r81562 | andrew.kuchling | 2010-05-27 08:22:53 -0500 (Thu, 27 May 2010) | 1 line Rewrite wxWidgets section ........ r81563 | andrew.kuchling | 2010-05-27 08:30:09 -0500 (Thu, 27 May 2010) | 1 line Remove top-level 'General Questions' section, pushing up the questions it contains ........ r81567 | andrew.kuchling | 2010-05-27 16:29:59 -0500 (Thu, 27 May 2010) | 1 line Add item ........ r81593 | georg.brandl | 2010-05-29 03:46:18 -0500 (Sat, 29 May 2010) | 1 line #8616: add new turtle demo "nim". ........ r81635 | georg.brandl | 2010-06-01 02:25:23 -0500 (Tue, 01 Jun 2010) | 1 line Put docs for RegexObject.search() before RegexObject.match() to mirror re.search() and re.match() order. ........ r81680 | vinay.sajip | 2010-06-03 17:34:42 -0500 (Thu, 03 Jun 2010) | 1 line Issue #8890: Documentation changed to avoid reference to temporary files. ........ r81681 | sean.reifschneider | 2010-06-03 20:51:26 -0500 (Thu, 03 Jun 2010) | 2 lines Issue8810: Clearing up docstring for tzinfo.utcoffset. ........ r81684 | vinay.sajip | 2010-06-04 08:41:02 -0500 (Fri, 04 Jun 2010) | 1 line Issue #8890: Documentation changed to avoid reference to temporary files - other cases covered. ........ r81801 | andrew.kuchling | 2010-06-07 08:38:40 -0500 (Mon, 07 Jun 2010) | 1 line #8875: Remove duplicated paragraph ........ r81888 | andrew.kuchling | 2010-06-10 20:54:58 -0500 (Thu, 10 Jun 2010) | 1 line Add a few more items ........ r81931 | georg.brandl | 2010-06-12 01:26:54 -0500 (Sat, 12 Jun 2010) | 1 line Fix punctuation. ........ r81932 | georg.brandl | 2010-06-12 01:28:58 -0500 (Sat, 12 Jun 2010) | 1 line Document that an existing directory raises in mkdir(). ........ r81933 | georg.brandl | 2010-06-12 01:45:33 -0500 (Sat, 12 Jun 2010) | 1 line Update version in README. ........ r81939 | georg.brandl | 2010-06-12 04:45:01 -0500 (Sat, 12 Jun 2010) | 1 line Use newer toctree syntax. ........ r81940 | georg.brandl | 2010-06-12 04:45:28 -0500 (Sat, 12 Jun 2010) | 1 line Add document on how to build. ........ r81941 | georg.brandl | 2010-06-12 04:45:58 -0500 (Sat, 12 Jun 2010) | 1 line Fix gratuitous indentation. ........ r81942 | georg.brandl | 2010-06-12 04:46:03 -0500 (Sat, 12 Jun 2010) | 1 line Update README. ........ r81963 | andrew.kuchling | 2010-06-12 15:00:55 -0500 (Sat, 12 Jun 2010) | 1 line Grammar fix ........ r81984 | georg.brandl | 2010-06-14 10:58:39 -0500 (Mon, 14 Jun 2010) | 1 line #8993: fix reference. ........ r81991 | andrew.kuchling | 2010-06-14 19:38:58 -0500 (Mon, 14 Jun 2010) | 1 line Add another bunch of items ........ r82120 | andrew.kuchling | 2010-06-20 16:45:45 -0500 (Sun, 20 Jun 2010) | 1 line Note that Python 3.x isn't covered; add forward ref. for UTF-8; note error in 2.5 and up ........ r82188 | benjamin.peterson | 2010-06-23 19:02:46 -0500 (Wed, 23 Jun 2010) | 1 line remove reverted changed ........ r82264 | georg.brandl | 2010-06-27 05:47:47 -0500 (Sun, 27 Jun 2010) | 1 line Confusing punctuation. ........ r82265 | georg.brandl | 2010-06-27 05:49:23 -0500 (Sun, 27 Jun 2010) | 1 line Use designated syntax for optional grammar element. ........ r82266 | georg.brandl | 2010-06-27 05:51:44 -0500 (Sun, 27 Jun 2010) | 1 line Fix URL. ........ r82267 | georg.brandl | 2010-06-27 05:55:38 -0500 (Sun, 27 Jun 2010) | 1 line Two typos. ........ ................ r82302 | benjamin.peterson | 2010-06-27 23:37:28 +0100 (Sun, 27 Jun 2010) | 15 lines Merged revisions 81380 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81380 | brett.cannon | 2010-05-20 13:37:55 -0500 (Thu, 20 May 2010) | 8 lines Turned out that if you used explicit relative import syntax (e.g. from .os import sep) and it failed, import would still try the implicit relative import semantics of an absolute import (from os import sep). That's not right, so when level is negative, only do explicit relative import semantics. Fixes issue #7902. Thanks to Meador Inge for the patch. ........ ................ r82304 | benjamin.peterson | 2010-06-27 23:41:29 +0100 (Sun, 27 Jun 2010) | 13 lines Merged revisions 81499,81506 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81499 | georg.brandl | 2010-05-24 16:29:07 -0500 (Mon, 24 May 2010) | 1 line #8016: add the CP858 codec (approved by Benjamin). (Also add CP720 to the tests, it was missing there.) ........ r81506 | benjamin.peterson | 2010-05-24 17:04:53 -0500 (Mon, 24 May 2010) | 1 line set svn:eol-style ........ ................ r82305 | benjamin.peterson | 2010-06-27 23:44:51 +0100 (Sun, 27 Jun 2010) | 9 lines Merged revisions 82303 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r82303 | benjamin.peterson | 2010-06-27 17:40:26 -0500 (Sun, 27 Jun 2010) | 1 line mark tracking tests as implementation details ........ ................ r82306 | benjamin.peterson | 2010-06-28 00:16:51 +0100 (Mon, 28 Jun 2010) | 9 lines Blocked revisions 81700 via svnmerge ........ r81700 | martin.v.loewis | 2010-06-04 14:15:32 -0500 (Fri, 04 Jun 2010) | 2 lines Display installer warning that Windows 2000 won't be supported in future releases. ........ ................ r82307 | benjamin.peterson | 2010-06-28 00:21:13 +0100 (Mon, 28 Jun 2010) | 9 lines Merged revisions 81880 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81880 | andrew.kuchling | 2010-06-10 19:14:34 -0500 (Thu, 10 Jun 2010) | 1 line Edit comments for current Python; bump version number of Python ........ ................ r82308 | benjamin.peterson | 2010-06-28 00:26:04 +0100 (Mon, 28 Jun 2010) | 9 lines Recorded merge of revisions 80866 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r80866 | andrew.kuchling | 2010-05-06 08:03:39 -0500 (Thu, 06 May 2010) | 1 line Use anonymous hyperlinks ........ ................ r82309 | benjamin.peterson | 2010-06-28 00:31:03 +0100 (Mon, 28 Jun 2010) | 8 lines Blocked revisions 80396 via svnmerge ........ r80396 | sean.reifschneider | 2010-04-23 03:31:55 -0500 (Fri, 23 Apr 2010) | 2 lines issue8451: Making syslog module use sys.argv[0] for "ident". ........ ................ r82310 | benjamin.peterson | 2010-06-28 00:34:03 +0100 (Mon, 28 Jun 2010) | 9 lines Merged revisions 81004 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81004 | mark.dickinson | 2010-05-08 14:13:21 -0500 (Sat, 08 May 2010) | 1 line Fix configure bug that was misreporting availability of MacOS X 10.5 SDK as available on Linux but not on OS X. ........ ................ r82311 | benjamin.peterson | 2010-06-28 00:49:45 +0100 (Mon, 28 Jun 2010) | 24 lines Merged revisions 79894-79895,80098,80120 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r79894 | jeroen.ruigrok | 2010-04-07 09:33:37 -0500 (Wed, 07 Apr 2010) | 5 lines FreeBSD is not a sysv platform, so use freebsd.S instead of sysv.S (as is also the case in FreeBSD's port of libffi). Reviewed by: dickinsm ........ r79895 | jeroen.ruigrok | 2010-04-07 11:34:08 -0500 (Wed, 07 Apr 2010) | 2 lines Document the libffi FreeBSD fix. ........ r80098 | benjamin.peterson | 2010-04-15 16:42:16 -0500 (Thu, 15 Apr 2010) | 1 line add space ........ r80120 | antoine.pitrou | 2010-04-16 16:34:02 -0500 (Fri, 16 Apr 2010) | 3 lines Ignore jinja2 ........ ................ r82312 | benjamin.peterson | 2010-06-28 00:53:17 +0100 (Mon, 28 Jun 2010) | 8 lines Blocked revisions 79596 via svnmerge ........ r79596 | eric.smith | 2010-04-02 07:30:56 -0500 (Fri, 02 Apr 2010) | 1 line Issue 7994: Make object.__format__ with a non-empty format string a PendingDecprecationWarning. Still need to remove uses of this from various tests. ........ ................ r82313 | brett.cannon | 2010-06-28 00:57:46 +0100 (Mon, 28 Jun 2010) | 29 lines Implement importlib.abc.SourceLoader and deprecate PyLoader and PyPycLoader. SourceLoader is a simplification of both PyLoader and PyPycLoader. If one only wants to use source, then they need to only implement get_data and get_filename. To also use bytecode -- sourceless loading is not supported -- then two abstract methods -- path_mtime and set_data -- need to be implemented. Compared to PyLoader and PyPycLoader, there are less abstract methods introduced and bytecode files become an optimization controlled by the ABC and hidden from the user (this need came about as PEP 3147 showed that not treating bytecode as an optimization can cause problems for compatibility). PyLoader is deprecated in favor of SourceLoader. To be compatible from Python 3.1 onwards, a subclass need only use simple methods for source_path and is_package. Otherwise conditional subclassing based on whether Python 3.1 or Python 3.2 is being is the only change. The documentation and docstring for PyLoader explain what is exactly needed. PyPycLoader is deprecated also in favor of SourceLoader. Because PEP 3147 shifted bytecode path details so much, there is no foolproof way to provide backwards-compatibility with SourceLoader. Because of this the class is simply deprecated and users should move to SourceLoader (and optionally PyLoader for Python 3.1). This does lead to a loss of support for sourceless loading unfortunately. At some point before Python 3.2 is released, SourceLoader will be moved over to importlib._bootstrap so that the core code of importlib relies on the new code instead of the old PyPycLoader code. This commit is being done now so that there is no issue in having the API in Python 3.1a1. ................ r82314 | benjamin.peterson | 2010-06-28 01:01:59 +0100 (Mon, 28 Jun 2010) | 32 lines Merged revisions 77402,77505,77510 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r77402 | brett.cannon | 2010-01-09 20:56:19 -0600 (Sat, 09 Jan 2010) | 12 lines DeprecationWarning is now silent by default. This was originally suggested by Guido, discussed on the stdlib-sig mailing list, and given the OK by Guido directly to me. What this change essentially means is that Python has taken a policy of silencing warnings that are only of interest to developers by default. This should prevent users from seeing warnings which are triggered by an application being run against a new interpreter before the app developer has a chance to update their code. Closes issue #7319. Thanks to Antoine Pitrou, Ezio Melotti, and Brian Curtin for helping with the issue. ........ r77505 | brett.cannon | 2010-01-14 14:00:28 -0600 (Thu, 14 Jan 2010) | 7 lines The silencing of DeprecationWarning was not taking -3 into consideration. Since Py3K warnings are DeprecationWarning by default this was causing -3 to essentially be a no-op. Now DeprecationWarning is only silenced if -3 is not used. Closes issue #7700. Thanks Ezio Melotti and Florent Xicluna for patch help. ........ r77510 | brett.cannon | 2010-01-14 19:31:45 -0600 (Thu, 14 Jan 2010) | 1 line Remove C++/C99-style comments. ........ ................ r82315 | benjamin.peterson | 2010-06-28 01:16:12 +0100 (Mon, 28 Jun 2010) | 1 line fix versionchanged ................ r82316 | benjamin.peterson | 2010-06-28 01:24:13 +0100 (Mon, 28 Jun 2010) | 1 line fix test with more obviously incorrect bytecode ................ r82318 | benjamin.peterson | 2010-06-28 04:07:10 +0100 (Mon, 28 Jun 2010) | 9 lines Merged revisions 82317 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r82317 | benjamin.peterson | 2010-06-27 21:58:25 -0500 (Sun, 27 Jun 2010) | 1 line remove unused last argument to property_copy ........ ................ r82320 | brett.cannon | 2010-06-28 05:57:24 +0100 (Mon, 28 Jun 2010) | 11 lines Move importlib.abc.SourceLoader to _bootstrap. Required updating code relying on other modules to switch to _bootstrap's unique module requirements. This led to the realization that get_code was being too liberal in its exception catching when calling set_data by blindly grabbing IOError. Shifted the responsibility of safely ignoring writes to a read-only path to set_data. Importlib is still not relying on SourceLoader yet; requires creating a SourcelessLoader and updating the source finder. ................ r82321 | brett.cannon | 2010-06-28 06:46:25 +0100 (Mon, 28 Jun 2010) | 2 lines Add an inheritance test for importlib.abc.SourceLoader. ................ r82326 | senthil.kumaran | 2010-06-28 15:08:00 +0100 (Mon, 28 Jun 2010) | 9 lines Merged revisions 82324 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r82324 | senthil.kumaran | 2010-06-28 19:26:46 +0530 (Mon, 28 Jun 2010) | 3 lines Fix Issue8653 - Docstring for urlunsplit function. ........ ................ r82328 | alexander.belopolsky | 2010-06-28 15:36:55 +0100 (Mon, 28 Jun 2010) | 1 line Added missing white space ................ r82331 | benjamin.peterson | 2010-06-28 16:39:55 +0100 (Mon, 28 Jun 2010) | 9 lines Merged revisions 82330 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r82330 | benjamin.peterson | 2010-06-28 10:36:40 -0500 (Mon, 28 Jun 2010) | 1 line testcapi tests are definitely cpython only ........ ................ r82333 | benjamin.peterson | 2010-06-28 16:43:25 +0100 (Mon, 28 Jun 2010) | 9 lines Merged revisions 82332 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r82332 | benjamin.peterson | 2010-06-28 10:41:06 -0500 (Mon, 28 Jun 2010) | 1 line fix skipping condition ........ ................ r82336 | senthil.kumaran | 2010-06-28 18:31:40 +0100 (Mon, 28 Jun 2010) | 9 lines Merged revisions 82334 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r82334 | senthil.kumaran | 2010-06-28 22:37:40 +0530 (Mon, 28 Jun 2010) | 3 lines Documentation correction. urllib2.urlopen.info returns a mimetools.Message instance not HTTPMessage object. ........ ................ r82342 | benjamin.peterson | 2010-06-28 20:43:42 +0100 (Mon, 28 Jun 2010) | 1 line update error message ................ r82343 | mark.dickinson | 2010-06-28 20:44:20 +0100 (Mon, 28 Jun 2010) | 23 lines Merged revisions 82338,82340-82341 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r82338 | mark.dickinson | 2010-06-28 20:31:41 +0100 (Mon, 28 Jun 2010) | 9 lines Fix some shallow bugs in Demo/parser/unparse.py, and add tests: - insert commas between entries in del statement - left and right shifts were represented as >> and << (respectively); reverse - unindent properly after for: else: or while: else: - add parens around the result of an unary operation - add parens around negative numbers, to avoid turning (-1)**2 into -1**2. ........ r82340 | mark.dickinson | 2010-06-28 20:34:15 +0100 (Mon, 28 Jun 2010) | 1 line Fix typo in test_unparse.py. ........ r82341 | mark.dickinson | 2010-06-28 20:38:19 +0100 (Mon, 28 Jun 2010) | 1 line Set svn:eol-style on test_unparse.py. ........ ................ r82346 | mark.dickinson | 2010-06-28 21:09:18 +0100 (Mon, 28 Jun 2010) | 9 lines Merged revisions 82345 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r82345 | mark.dickinson | 2010-06-28 20:54:19 +0100 (Mon, 28 Jun 2010) | 1 line unparse.py: fix mispaced parentheses in chained comparisons ........ ................ r82347 | mark.dickinson | 2010-06-28 22:14:17 +0100 (Mon, 28 Jun 2010) | 18 lines Update Demo/parser/unparse.py to current Python 3.x syntax. Additions: - relative imports - keyword-only arguments - function annotations - class decorators - raise ... from ... - except ... as ... - nonlocal - bytes literals - set literals - set comprehensions - dict comprehensions Removals: - print statement. Some of this should be backported to 2.x. ................ r82349 | mark.dickinson | 2010-06-28 22:39:51 +0100 (Mon, 28 Jun 2010) | 1 line unparse.py: Typo fix. ................ r82351 | brian.curtin | 2010-06-29 01:14:28 +0100 (Tue, 29 Jun 2010) | 3 lines Update md5driver.py for 3.x. Changed an import, replaced md5.new() with md5(), and added an encode where needed. ................ r82354 | benjamin.peterson | 2010-06-29 02:27:35 +0100 (Tue, 29 Jun 2010) | 1 line rephrase and remove uneeded statement ................ r82357 | mark.dickinson | 2010-06-29 08:38:37 +0100 (Tue, 29 Jun 2010) | 9 lines Merged revisions 82356 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r82356 | mark.dickinson | 2010-06-29 08:37:25 +0100 (Tue, 29 Jun 2010) | 1 line Spelling. ........ ................ r82358 | mark.dickinson | 2010-06-29 08:48:23 +0100 (Tue, 29 Jun 2010) | 1 line unparse.py: respect coding cookie in input files ................ r82359 | mark.dickinson | 2010-06-29 09:52:36 +0100 (Tue, 29 Jun 2010) | 1 line Add parentheses around numeric literals, to avoid turning 3 .bit_length() into 3.bit_length(). ................ r82360 | mark.dickinson | 2010-06-29 11:01:48 +0100 (Tue, 29 Jun 2010) | 8 lines More unparse.py fixes: - parenthesize lambdas, to avoid turning (lambda : int)() into lambda: int() - unparse an infinite float literals in the AST as an overflowing finite value unparse.py now successfully round-trips on all valid Lib/*.py and Lib/test/*.py files. ................ r82365 | mark.dickinson | 2010-06-29 15:08:23 +0100 (Tue, 29 Jun 2010) | 1 line test_unparse.py: Do roundtrip testing for all Python files in Lib and Lib/test. ................ r82370 | vinay.sajip | 2010-06-29 16:31:15 +0100 (Tue, 29 Jun 2010) | 1 line Added information about pickle security and SocketHandler, and some cross-reference targets. ................ r82371 | benjamin.peterson | 2010-06-29 16:32:34 +0100 (Tue, 29 Jun 2010) | 8 lines Blocked revisions 82368 via svnmerge ........ r82368 | benjamin.peterson | 2010-06-29 10:18:02 -0500 (Tue, 29 Jun 2010) | 1 line group cStringIO docs under its factory function ........ ................ r82373 | benjamin.peterson | 2010-06-29 16:57:57 +0100 (Tue, 29 Jun 2010) | 1 line note that byte strings can be raw, too #9114 ................ r82375 | brett.cannon | 2010-06-29 19:26:11 +0100 (Tue, 29 Jun 2010) | 1 line Make a sentence a little less awkward. ................ r82376 | benjamin.peterson | 2010-06-29 19:36:39 +0100 (Tue, 29 Jun 2010) | 1 line update for nonlocal keyword ................ r82377 | mark.dickinson | 2010-06-29 19:38:59 +0100 (Tue, 29 Jun 2010) | 1 line Fix typo in unparsing of a class definition. ................ r82381 | mark.dickinson | 2010-06-29 21:10:42 +0100 (Tue, 29 Jun 2010) | 9 lines Merged revisions 82379 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r82379 | mark.dickinson | 2010-06-29 21:09:12 +0100 (Tue, 29 Jun 2010) | 1 line Issue #1789: clarify that the 'size' column in struct docs refers to standard size. ........ ................ r82383 | mark.dickinson | 2010-06-30 09:32:11 +0100 (Wed, 30 Jun 2010) | 1 line Collapse else: if: ... into elif: ................ r82384 | mark.dickinson | 2010-06-30 09:46:53 +0100 (Wed, 30 Jun 2010) | 1 line Output try-except-finally statements where appropriate. ................ r82386 | mark.dickinson | 2010-06-30 10:05:47 +0100 (Wed, 30 Jun 2010) | 1 line Better solution for attribute access on integer literals. ................ r82387 | mark.dickinson | 2010-06-30 10:14:43 +0100 (Wed, 30 Jun 2010) | 1 line Remove backtick syntax for repr. ................ r82391 | mark.dickinson | 2010-06-30 12:13:36 +0100 (Wed, 30 Jun 2010) | 1 line Issue #9011: Tests for Python 3.2's treatment of negated imaginary literals. ................ r82392 | mark.dickinson | 2010-06-30 12:14:30 +0100 (Wed, 30 Jun 2010) | 1 line Revert accidental extra changes included in r82391. ................ r82393 | mark.dickinson | 2010-06-30 12:45:53 +0100 (Wed, 30 Jun 2010) | 1 line Unparse infinite imaginary literals correctly. Add some more numeric tests. ................ r82394 | michael.foord | 2010-06-30 13:17:50 +0100 (Wed, 30 Jun 2010) | 1 line Issue 9110. Adding ContextDecorator to contextlib. This enables the creation of APIs that act as decorators as well as context managers. contextlib.contextmanager changed to use ContextDecorator. ................ r82402 | mark.dickinson | 2010-06-30 17:36:12 +0100 (Wed, 30 Jun 2010) | 12 lines Blocked revisions 82399-82400 via svnmerge ........ r82399 | mark.dickinson | 2010-06-30 15:19:56 +0100 (Wed, 30 Jun 2010) | 1 line Update Demo/parser directory; backport unparse fixes from py3k. ........ r82400 | mark.dickinson | 2010-06-30 17:27:57 +0100 (Wed, 30 Jun 2010) | 2 lines Issue #9125: Update parser module for "except ... as ..." syntax. ........ ................ r82405 | benjamin.peterson | 2010-06-30 18:39:45 +0100 (Wed, 30 Jun 2010) | 9 lines Merged revisions 82403 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r82403 | benjamin.peterson | 2010-06-30 12:11:08 -0500 (Wed, 30 Jun 2010) | 1 line mark test depending on ref counting ........ ................ r82407 | giampaolo.rodola | 2010-06-30 18:47:39 +0100 (Wed, 30 Jun 2010) | 9 lines Merged revisions 82404 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r82404 | giampaolo.rodola | 2010-06-30 19:38:28 +0200 (mer, 30 giu 2010) | 1 line fix issue #6589: cleanup asyncore.socket_map if smtpd.SMTPServer constructor raises an exception ........ ................ r82410 | benjamin.peterson | 2010-06-30 19:44:04 +0100 (Wed, 30 Jun 2010) | 9 lines Merged revisions 82409 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r82409 | benjamin.peterson | 2010-06-30 13:41:08 -0500 (Wed, 30 Jun 2010) | 1 line an AttributeError is perfectly acceptable here ........ ................ r82413 | ezio.melotti | 2010-07-01 08:32:02 +0100 (Thu, 01 Jul 2010) | 13 lines Update PyUnicode_DecodeUTF8 from RFC 2279 to RFC 3629. 1) #8271: when a byte sequence is invalid, only the start byte and all the valid continuation bytes are now replaced by U+FFFD, instead of replacing the number of bytes specified by the start byte. See http://www.unicode.org/versions/Unicode5.2.0/ch03.pdf (pages 94-95); 2) 5- and 6-bytes-long UTF-8 sequences are now considered invalid (no changes in behavior); 3) Change the error messages "unexpected code byte" to "invalid start byte" and "invalid data" to "invalid continuation byte"; 4) Add an extensive set of tests in test_unicode; 5) Fix test_codeccallbacks because it was failing after this change. ................ r82416 | benjamin.peterson | 2010-07-01 16:09:14 +0100 (Thu, 01 Jul 2010) | 8 lines Blocked revisions 82415 via svnmerge ........ r82415 | benjamin.peterson | 2010-07-01 10:07:15 -0500 (Thu, 01 Jul 2010) | 1 line remove docs about delegating to special methods; it does no such thing ........ ................ r82417 | benjamin.peterson | 2010-07-01 16:16:55 +0100 (Thu, 01 Jul 2010) | 1 line correctly lookup __trunc__ and __floor__ ................ r82422 | benjamin.peterson | 2010-07-01 18:49:01 +0100 (Thu, 01 Jul 2010) | 9 lines Merged revisions 82420 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r82420 | benjamin.peterson | 2010-07-01 12:45:52 -0500 (Thu, 01 Jul 2010) | 1 line fix fixer name ........ ................ r82430 | benjamin.peterson | 2010-07-02 00:39:26 +0100 (Fri, 02 Jul 2010) | 8 lines Blocked revisions 82429 via svnmerge ........ r82429 | benjamin.peterson | 2010-07-01 18:35:37 -0500 (Thu, 01 Jul 2010) | 1 line trunc does use the special method, though ........ ................ r82434 | georg.brandl | 2010-07-02 08:41:51 +0100 (Fri, 02 Jul 2010) | 9 lines Merged revisions 82433 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r82433 | georg.brandl | 2010-07-02 09:33:50 +0200 (Fr, 02 Jul 2010) | 1 line Grammar and markup fixes. ........ ................ r82437 | benjamin.peterson | 2010-07-02 14:35:17 +0100 (Fri, 02 Jul 2010) | 1 line account for different ref counting semantics of _PyObject_LookupSpecial ................ r82438 | benjamin.peterson | 2010-07-02 14:46:42 +0100 (Fri, 02 Jul 2010) | 1 line fix lookup of __ceil__ ................ r82440 | nick.coghlan | 2010-07-02 16:57:50 +0100 (Fri, 02 Jul 2010) | 9 lines Merged revisions 82439 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r82439 | nick.coghlan | 2010-07-03 01:50:14 +1000 (Sat, 03 Jul 2010) | 1 line Fix a couple of minor nits in What's New before the release goes out ........ ................ r82442 | mark.dickinson | 2010-07-02 17:05:15 +0100 (Fri, 02 Jul 2010) | 1 line Style/consistency nit: make math_floor and math_ceil code look the same. ................ r82443 | nick.coghlan | 2010-07-02 17:14:05 +0100 (Fri, 02 Jul 2010) | 9 lines Merged revisions 82441 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r82441 | nick.coghlan | 2010-07-03 02:01:53 +1000 (Sat, 03 Jul 2010) | 1 line Issue 8202 actually caused an unintended behavioural change and was reverted in 2.7 - remove reference from What's New ........ ................ r82448 | benjamin.peterson | 2010-07-02 20:45:07 +0100 (Fri, 02 Jul 2010) | 9 lines Merged revisions 82447 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r82447 | benjamin.peterson | 2010-07-02 14:41:39 -0500 (Fri, 02 Jul 2010) | 1 line add space ........ ................ r82452 | mark.dickinson | 2010-07-02 21:26:07 +0100 (Fri, 02 Jul 2010) | 9 lines Merged revisions 82446 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r82446 | mark.dickinson | 2010-07-02 19:06:52 +0100 (Fri, 02 Jul 2010) | 1 line Clarify sys.float_info documentation. ........ ................ r82456 | brett.cannon | 2010-07-02 23:03:00 +0100 (Fri, 02 Jul 2010) | 7 lines Some people have mistaken Python bytecode as being stable and unchanging. In reality it's simply an implementation detail for CPython. This point is now clearly documented in both the docs for dis and the glossary. Closes issue #7829. Thanks to Terry Reedy for some initial suggestions on wording. ................ r82462 | ezio.melotti | 2010-07-03 00:18:51 +0100 (Sat, 03 Jul 2010) | 17 lines Merged revisions 82455,82457,82459 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r82455 | eric.smith | 2010-07-03 00:44:16 +0300 (Sat, 03 Jul 2010) | 1 line Moved period outside paren, where it belongs. ........ r82457 | ezio.melotti | 2010-07-03 01:17:29 +0300 (Sat, 03 Jul 2010) | 1 line #9139: Add examples for str.format(). ........ r82459 | ezio.melotti | 2010-07-03 01:50:39 +0300 (Sat, 03 Jul 2010) | 1 line #9139: the thousands separator is new in 2.7. Also add a missing variable in the example. ........ ................ r82464 | benjamin.peterson | 2010-07-03 00:25:44 +0100 (Sat, 03 Jul 2010) | 9 lines Merged revisions 82461 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r82461 | benjamin.peterson | 2010-07-02 18:05:27 -0500 (Fri, 02 Jul 2010) | 1 line don't require the presence of __getformat__ or __setformat__; use requires_IEEE_754 globally ........ ................ r82465 | brett.cannon | 2010-07-03 02:32:48 +0100 (Sat, 03 Jul 2010) | 3 lines Make test_import a little bit more robust for cleaning up after itself in the face of a failure. ................ r82467 | alexander.belopolsky | 2010-07-03 04:35:27 +0100 (Sat, 03 Jul 2010) | 9 lines Merged revisions 82466 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r82466 | alexander.belopolsky | 2010-07-02 23:27:12 -0400 (Fri, 02 Jul 2010) | 1 line Revert r81681 (issue 8810). ........ ................ r82468 | ezio.melotti | 2010-07-03 05:52:19 +0100 (Sat, 03 Jul 2010) | 1 line Update comment about surrogates. ................ r82471 | nick.coghlan | 2010-07-03 08:36:51 +0100 (Sat, 03 Jul 2010) | 1 line Issue 6507: accept source strings directly in dis.dis(). Original patch by Daniel Urban ................ r82472 | nick.coghlan | 2010-07-03 08:38:28 +0100 (Sat, 03 Jul 2010) | 1 line Issue 6507: missing patch submitter from NEWS entry in previous checkin ................ r82478 | mark.dickinson | 2010-07-03 10:17:16 +0100 (Sat, 03 Jul 2010) | 9 lines Merged revisions 82476 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r82476 | mark.dickinson | 2010-07-03 10:15:09 +0100 (Sat, 03 Jul 2010) | 1 line Fix typo in sys.float_info docs. ........ ................ r82480 | georg.brandl | 2010-07-03 11:21:50 +0100 (Sat, 03 Jul 2010) | 1 line Wrap and use the correct directive. ................ r82481 | georg.brandl | 2010-07-03 11:22:10 +0100 (Sat, 03 Jul 2010) | 1 line Use the right role. ................ r82484 | georg.brandl | 2010-07-03 11:26:17 +0100 (Sat, 03 Jul 2010) | 9 lines Recorded merge of revisions 82474 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r82474 | georg.brandl | 2010-07-03 10:40:13 +0200 (Sa, 03 Jul 2010) | 1 line Fix role name. ........ ................ r82485 | georg.brandl | 2010-07-03 11:26:54 +0100 (Sat, 03 Jul 2010) | 9 lines Merged revisions 82483 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r82483 | georg.brandl | 2010-07-03 12:25:54 +0200 (Sa, 03 Jul 2010) | 1 line Add link to bytecode docs. ........ ................ r82487 | georg.brandl | 2010-07-03 11:33:26 +0100 (Sat, 03 Jul 2010) | 1 line Fix markup. ................ r82488 | georg.brandl | 2010-07-03 11:41:33 +0100 (Sat, 03 Jul 2010) | 1 line Remove the need for a "()" empty argument list after opcodes. ................ r82495 | victor.stinner | 2010-07-03 14:44:22 +0100 (Sat, 03 Jul 2010) | 10 lines Merged revisions 82492 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r82492 | victor.stinner | 2010-07-03 15:36:19 +0200 (sam., 03 juil. 2010) | 3 lines Issue #7673: Fix security vulnerability (CVE-2010-2089) in the audioop module, ensure that the input string length is a multiple of the frame size ........ ................ r82507 | benjamin.peterson | 2010-07-03 16:09:20 +0100 (Sat, 03 Jul 2010) | 3 lines Removed merge tracking for "svnmerge" for svn+ssh://pythondev at svn.python.org/python/branches/py3k/python/trunk ................ r82510 | senthil.kumaran | 2010-07-03 18:48:22 +0100 (Sat, 03 Jul 2010) | 4 lines Fix Issue5468 - urlencode to handle bytes and other alternate encodings. (Extensive tests provided). Patch by Dan Mahn. ................ r82514 | alexander.belopolsky | 2010-07-03 21:35:53 +0100 (Sat, 03 Jul 2010) | 3 lines Issue #9094: Make python -m pickletools disassemble pickles given in the command line. ................ r82515 | mark.dickinson | 2010-07-03 22:00:51 +0100 (Sat, 03 Jul 2010) | 1 line Remove nonexistent tools from Tools README. ................ r82516 | brett.cannon | 2010-07-03 22:37:28 +0100 (Sat, 03 Jul 2010) | 2 lines Ignore __pycache__. ................ r82517 | alexander.belopolsky | 2010-07-03 22:42:47 +0100 (Sat, 03 Jul 2010) | 3 lines Issue #9151: Demo/classes/Dates.py does not work in 3.x Made minimal changes to make included test pass. ................ r82518 | brett.cannon | 2010-07-03 22:48:25 +0100 (Sat, 03 Jul 2010) | 34 lines Make importlib.abc.SourceLoader the primary mechanism for importlib. This required moving the class from importlib/abc.py into importlib/_bootstrap.py and jiggering some code to work better with the class. This included changing how the file finder worked to better meet import semantics. This also led to fixing importlib to handle the empty string from sys.path as import currently does (and making me wish we didn't support that instead just required people to insert '.' instead to represent cwd). It also required making the new set_data abstractmethod create any needed subdirectories implicitly thanks to __pycache__ (it was either this or grow the SourceLoader ABC to gain an 'exists' method and either a mkdir method or have set_data with no data arg mean to create a directory). Lastly, as an optimization the file loaders cache the file path where the finder found something to use for loading (this is thanks to having a sourceless loader separate from the source loader to simplify the code and cut out stat calls). Unfortunately test_runpy assumed a loader would always work for a module, even if you changed from underneath it what it was expected to work with. By simply dropping the previous loader in test_runpy so the proper loader can be returned by the finder fixed the failure. At this point importlib deviates from import on two points: 1. The exception raised when trying to import a file is different (import does an explicit file check to print a special message, importlib just says the path cannot be imported as if it was just some module name). 2. the co_filename on a code object is not being set to where bytecode was actually loaded from instead of where the marshalled code object originally came from (a solution for this has already been agreed upon on python-dev but has not been implemented yet; issue8611). ................ r82519 | brett.cannon | 2010-07-03 22:50:52 +0100 (Sat, 03 Jul 2010) | 1 line Trailing whitespace is bad for .rst files. ................ r82520 | brett.cannon | 2010-07-03 23:03:16 +0100 (Sat, 03 Jul 2010) | 1 line Fix a spelling mistake in a comment. ................ r82521 | alexander.belopolsky | 2010-07-03 23:05:41 +0100 (Sat, 03 Jul 2010) | 5 lines Issue #9151: Demo/classes/Dates.py does not work in 3.x Converted descriptive comment into a docstring. Cast attributes to int in __init__. Use __new__ instead of deleting attributes to "uninitialize". ................ r82522 | brett.cannon | 2010-07-03 23:18:47 +0100 (Sat, 03 Jul 2010) | 34 lines Make importlib.abc.SourceLoader the primary mechanism for importlib. This required moving the class from importlib/abc.py into importlib/_bootstrap.py and jiggering some code to work better with the class. This included changing how the file finder worked to better meet import semantics. This also led to fixing importlib to handle the empty string from sys.path as import currently does (and making me wish we didn't support that instead just required people to insert '.' instead to represent cwd). It also required making the new set_data abstractmethod create any needed subdirectories implicitly thanks to __pycache__ (it was either this or grow the SourceLoader ABC to gain an 'exists' method and either a mkdir method or have set_data with no data arg mean to create a directory). Lastly, as an optimization the file loaders cache the file path where the finder found something to use for loading (this is thanks to having a sourceless loader separate from the source loader to simplify the code and cut out stat calls). Unfortunately test_runpy assumed a loader would always work for a module, even if you changed from underneath it what it was expected to work with. By simply dropping the previous loader in test_runpy so the proper loader can be returned by the finder fixed the failure. At this point importlib deviates from import on two points: 1. The exception raised when trying to import a file is different (import does an explicit file check to print a special message, importlib just says the path cannot be imported as if it was just some module name). 2. the co_filename on a code object is not being set to where bytecode was actually loaded from instead of where the marshalled code object originally came from (a solution for this has already been agreed upon on python-dev but has not been implemented yet; issue8611). ................ r82523 | brett.cannon | 2010-07-03 23:32:41 +0100 (Sat, 03 Jul 2010) | 34 lines Make importlib.abc.SourceLoader the primary mechanism for importlib. This required moving the class from importlib/abc.py into importlib/_bootstrap.py and jiggering some code to work better with the class. This included changing how the file finder worked to better meet import semantics. This also led to fixing importlib to handle the empty string from sys.path as import currently does (and making me wish we didn't support that instead just required people to insert '.' instead to represent cwd). It also required making the new set_data abstractmethod create any needed subdirectories implicitly thanks to __pycache__ (it was either this or grow the SourceLoader ABC to gain an 'exists' method and either a mkdir method or have set_data with no data arg mean to create a directory). Lastly, as an optimization the file loaders cache the file path where the finder found something to use for loading (this is thanks to having a sourceless loader separate from the source loader to simplify the code and cut out stat calls). Unfortunately test_runpy assumed a loader would always work for a module, even if you changed from underneath it what it was expected to work with. By simply dropping the previous loader in test_runpy so the proper loader can be returned by the finder fixed the failure. At this point importlib deviates from import on two points: 1. The exception raised when trying to import a file is different (import does an explicit file check to print a special message, importlib just says the path cannot be imported as if it was just some module name). 2. the co_filename on a code object is not being set to where bytecode was actually loaded from instead of where the marshalled code object originally came from (a solution for this has already been agreed upon on python-dev but has not been implemented yet; issue8611). ................ r82524 | alexander.belopolsky | 2010-07-03 23:36:06 +0100 (Sat, 03 Jul 2010) | 1 line Made minimal modifications to pass included tests ................ r82526 | georg.brandl | 2010-07-04 08:25:18 +0100 (Sun, 04 Jul 2010) | 1 line Remove old and unsafe Dbm demo class. ................ r82527 | mark.dickinson | 2010-07-04 11:15:11 +0100 (Sun, 04 Jul 2010) | 1 line Fix refleak in Modules/audioop.c. ................ r82533 | alexander.belopolsky | 2010-07-04 17:28:08 +0100 (Sun, 04 Jul 2010) | 1 line Issue #9152: Removed dead code in datetime module ................ r82535 | benjamin.peterson | 2010-07-04 17:33:07 +0100 (Sun, 04 Jul 2010) | 3 lines Removed merge tracking for "svnmerge" for svn+ssh://pythondev at svn.python.org/sandbox/trunk/2to3/lib2to3 ................ r82537 | mark.dickinson | 2010-07-04 17:37:31 +0100 (Sun, 04 Jul 2010) | 2 lines Issue #9128: Fix validation of class decorators in parser module. ................ r82538 | benjamin.peterson | 2010-07-04 17:37:39 +0100 (Sun, 04 Jul 2010) | 3 lines Initialized merge tracking via "svnmerge" with revisions "0-80937" from svn+ssh://pythondev at svn.python.org/sandbox/trunk/2to3 ................ r82540 | benjamin.peterson | 2010-07-04 17:40:27 +0100 (Sun, 04 Jul 2010) | 3 lines Removed merge tracking for "svnmerge" for svn+ssh://pythondev at svn.python.org/sandbox/trunk/2to3 ................ r82541 | benjamin.peterson | 2010-07-04 17:41:33 +0100 (Sun, 04 Jul 2010) | 3 lines Initialized merge tracking via "svnmerge" with revisions "0-80937" from svn+ssh://pythondev at svn.python.org/sandbox/trunk/2to3/lib2to3 ................ r82542 | benjamin.peterson | 2010-07-04 17:44:15 +0100 (Sun, 04 Jul 2010) | 17 lines Merged revisions 81478,82530-82531 via svnmerge from svn+ssh://pythondev at svn.python.org/sandbox/trunk/2to3/lib2to3 ........ r81478 | benjamin.peterson | 2010-05-22 13:47:39 -0500 (Sat, 22 May 2010) | 1 line ensure doctests have some future_features ........ r82530 | benjamin.peterson | 2010-07-04 11:11:41 -0500 (Sun, 04 Jul 2010) | 1 line simplify ignore star imports from itertools #8892 ........ r82531 | benjamin.peterson | 2010-07-04 11:13:20 -0500 (Sun, 04 Jul 2010) | 1 line wrap with parenthesis not \ ........ ................ r82547 | alexander.belopolsky | 2010-07-04 18:00:20 +0100 (Sun, 04 Jul 2010) | 3 lines Issue #9118: help(None) will now return NoneType doc instead of starting interactive help. ................ r82550 | alexander.belopolsky | 2010-07-04 18:38:32 +0100 (Sun, 04 Jul 2010) | 1 line Fixed doctests ................ r82551 | alexander.belopolsky | 2010-07-04 18:47:30 +0100 (Sun, 04 Jul 2010) | 1 line Fixed the test ................ r82552 | mark.dickinson | 2010-07-04 19:11:51 +0100 (Sun, 04 Jul 2010) | 2 lines Issue #9130: Fix validation of relative imports in parser module. ................ r82553 | mark.dickinson | 2010-07-04 19:15:26 +0100 (Sun, 04 Jul 2010) | 1 line Fix symbol numbers in test_parser test. ................ r82555 | mark.dickinson | 2010-07-04 19:38:57 +0100 (Sun, 04 Jul 2010) | 2 lines Issue #9130: Validate ellipsis tokens in relative imports. ................ r82557 | mark.dickinson | 2010-07-04 19:49:18 +0100 (Sun, 04 Jul 2010) | 1 line Make Demo/parser/test_parser.py run. ................ r82558 | mark.dickinson | 2010-07-04 20:23:49 +0100 (Sun, 04 Jul 2010) | 1 line Remove coding cookie from heapq.py. ................ r82559 | mark.dickinson | 2010-07-04 20:27:12 +0100 (Sun, 04 Jul 2010) | 1 line Re-encode shlex.py in UTF-8, and remove coding cookie. ................ r82560 | mark.dickinson | 2010-07-04 21:07:09 +0100 (Sun, 04 Jul 2010) | 1 line Revert -r82559; it's not clear that this is the right thing to do, and the change obscures the original intentions. ................ r82561 | andrew.kuchling | 2010-07-04 21:47:00 +0100 (Sun, 04 Jul 2010) | 1 line Add brief explanation; remove no-longer-working link ................ r82567 | brett.cannon | 2010-07-04 23:05:34 +0100 (Sun, 04 Jul 2010) | 5 lines Do some basic refactoring. Along the way also list what files had their whitespace cleaned up and do the proper plurality for "N file(s)" based on N. Refactoring closes issue8912. Thanks to ??ric Araujo for the patch. ................ r82570 | senthil.kumaran | 2010-07-05 12:41:42 +0100 (Mon, 05 Jul 2010) | 3 lines Fix: Issue9091 Minor documentation clarification. ................ r82573 | senthil.kumaran | 2010-07-05 13:00:56 +0100 (Mon, 05 Jul 2010) | 3 lines Fix the docstrings of the capitalize method. ................ r82576 | benjamin.peterson | 2010-07-05 15:59:40 +0100 (Mon, 05 Jul 2010) | 1 line pydoc still has a silly encoding ................ r82577 | benjamin.peterson | 2010-07-05 16:01:22 +0100 (Mon, 05 Jul 2010) | 1 line cleanup basicsize logic #3268 ................ r82578 | alexander.belopolsky | 2010-07-05 16:05:33 +0100 (Mon, 05 Jul 2010) | 1 line Added more tests for utctimetuple() ................ r82585 | benjamin.peterson | 2010-07-05 18:11:05 +0100 (Mon, 05 Jul 2010) | 1 line looking up on the type is correct, so this isn't an XXX ................ r82587 | georg.brandl | 2010-07-05 18:48:38 +0100 (Mon, 05 Jul 2010) | 1 line #9166: NotImplemented is not an exception. ................ r82589 | alexander.belopolsky | 2010-07-05 18:57:31 +0100 (Mon, 05 Jul 2010) | 1 line Added two more test cases for datetime ................ r82591 | benjamin.peterson | 2010-07-05 21:04:54 +0100 (Mon, 05 Jul 2010) | 1 line untabify ................ r82593 | georg.brandl | 2010-07-05 21:13:06 +0100 (Mon, 05 Jul 2010) | 1 line Remove Dbm. ................ r82594 | georg.brandl | 2010-07-05 21:13:41 +0100 (Mon, 05 Jul 2010) | 1 line Update Vec class constructor, remove indirection via function, use operator module. ................ r82595 | mark.dickinson | 2010-07-05 21:14:26 +0100 (Mon, 05 Jul 2010) | 1 line Post-detabification cleanup. ................ r82597 | victor.stinner | 2010-07-05 22:36:21 +0100 (Mon, 05 Jul 2010) | 2 lines #9158: Fix y* format of PyArg_Parse*() functions documentation ................ r82599 | alexander.belopolsky | 2010-07-05 22:44:05 +0100 (Mon, 05 Jul 2010) | 1 line "Modernized" the demo a little. ................ r82600 | brett.cannon | 2010-07-05 23:11:16 +0100 (Mon, 05 Jul 2010) | 1 line Fix test_xmlrpc_net to no longer fail since there are no more buildbots for trunk. ................ r82601 | senthil.kumaran | 2010-07-06 03:08:36 +0100 (Tue, 06 Jul 2010) | 3 lines Change 'lowered' to 'lowercased' ................ r82604 | matthias.klose | 2010-07-06 11:53:30 +0100 (Tue, 06 Jul 2010) | 2 lines - sysmodule.c (get_hash_info): Define as static function. ................ r82607 | mark.dickinson | 2010-07-06 16:00:40 +0100 (Tue, 06 Jul 2010) | 1 line Indentation and PEP 7 fixes. ................ r82609 | vinay.sajip | 2010-07-06 16:08:55 +0100 (Tue, 06 Jul 2010) | 1 line Minor improvements to logging documentation. ................ r82610 | mark.dickinson | 2010-07-06 16:11:44 +0100 (Tue, 06 Jul 2010) | 1 line Style nit. ................ Added: python/branches/py3k-dtoa/Demo/parser/test_unparse.py - copied unchanged from r82610, /python/branches/py3k/Demo/parser/test_unparse.py python/branches/py3k-dtoa/Doc/documenting/building.rst - copied unchanged from r82610, /python/branches/py3k/Doc/documenting/building.rst python/branches/py3k-dtoa/Lib/encodings/cp858.py - copied unchanged from r82610, /python/branches/py3k/Lib/encodings/cp858.py python/branches/py3k-dtoa/Modules/_ctypes/libffi_msvc/LICENSE - copied unchanged from r82610, /python/branches/py3k/Modules/_ctypes/libffi_msvc/LICENSE python/branches/py3k-dtoa/Modules/_ctypes/libffi_msvc/README - copied unchanged from r82610, /python/branches/py3k/Modules/_ctypes/libffi_msvc/README python/branches/py3k-dtoa/Modules/_ctypes/libffi_msvc/README.ctypes - copied unchanged from r82610, /python/branches/py3k/Modules/_ctypes/libffi_msvc/README.ctypes python/branches/py3k-dtoa/Modules/_ctypes/libffi_msvc/ffi.c - copied unchanged from r82610, /python/branches/py3k/Modules/_ctypes/libffi_msvc/ffi.c python/branches/py3k-dtoa/Modules/_ctypes/libffi_msvc/ffi_common.h - copied unchanged from r82610, /python/branches/py3k/Modules/_ctypes/libffi_msvc/ffi_common.h python/branches/py3k-dtoa/Modules/_ctypes/libffi_msvc/ffitarget.h - copied unchanged from r82610, /python/branches/py3k/Modules/_ctypes/libffi_msvc/ffitarget.h python/branches/py3k-dtoa/Modules/_ctypes/libffi_msvc/prep_cif.c - copied unchanged from r82610, /python/branches/py3k/Modules/_ctypes/libffi_msvc/prep_cif.c python/branches/py3k-dtoa/Modules/_ctypes/libffi_msvc/types.c - copied unchanged from r82610, /python/branches/py3k/Modules/_ctypes/libffi_msvc/types.c python/branches/py3k-dtoa/Modules/_ctypes/libffi_msvc/win32.c - copied unchanged from r82610, /python/branches/py3k/Modules/_ctypes/libffi_msvc/win32.c python/branches/py3k-dtoa/Modules/_ctypes/libffi_msvc/win64.asm - copied unchanged from r82610, /python/branches/py3k/Modules/_ctypes/libffi_msvc/win64.asm python/branches/py3k-dtoa/Modules/_time.c - copied unchanged from r82610, /python/branches/py3k/Modules/_time.c python/branches/py3k-dtoa/Modules/_time.h - copied unchanged from r82610, /python/branches/py3k/Modules/_time.h Removed: python/branches/py3k-dtoa/Demo/classes/Dbm.py python/branches/py3k-dtoa/Tools/webchecker/ Modified: python/branches/py3k-dtoa/ (props changed) python/branches/py3k-dtoa/Demo/classes/Complex.py python/branches/py3k-dtoa/Demo/classes/Dates.py python/branches/py3k-dtoa/Demo/classes/README python/branches/py3k-dtoa/Demo/classes/Range.py python/branches/py3k-dtoa/Demo/classes/Rev.py python/branches/py3k-dtoa/Demo/classes/Vec.py python/branches/py3k-dtoa/Demo/embed/Makefile python/branches/py3k-dtoa/Demo/embed/demo.c python/branches/py3k-dtoa/Demo/md5test/md5driver.py python/branches/py3k-dtoa/Demo/parser/test_parser.py python/branches/py3k-dtoa/Demo/parser/unparse.py python/branches/py3k-dtoa/Doc/README.txt python/branches/py3k-dtoa/Doc/c-api/arg.rst python/branches/py3k-dtoa/Doc/c-api/datetime.rst python/branches/py3k-dtoa/Doc/c-api/init.rst python/branches/py3k-dtoa/Doc/c-api/intro.rst python/branches/py3k-dtoa/Doc/c-api/number.rst python/branches/py3k-dtoa/Doc/c-api/unicode.rst python/branches/py3k-dtoa/Doc/data/refcounts.dat python/branches/py3k-dtoa/Doc/distutils/builtdist.rst python/branches/py3k-dtoa/Doc/documenting/index.rst python/branches/py3k-dtoa/Doc/documenting/markup.rst python/branches/py3k-dtoa/Doc/documenting/style.rst python/branches/py3k-dtoa/Doc/faq/gui.rst python/branches/py3k-dtoa/Doc/glossary.rst python/branches/py3k-dtoa/Doc/howto/functional.rst python/branches/py3k-dtoa/Doc/howto/unicode.rst python/branches/py3k-dtoa/Doc/library/2to3.rst python/branches/py3k-dtoa/Doc/library/calendar.rst python/branches/py3k-dtoa/Doc/library/codecs.rst python/branches/py3k-dtoa/Doc/library/contextlib.rst python/branches/py3k-dtoa/Doc/library/datetime.rst python/branches/py3k-dtoa/Doc/library/dis.rst python/branches/py3k-dtoa/Doc/library/http.server.rst python/branches/py3k-dtoa/Doc/library/importlib.rst python/branches/py3k-dtoa/Doc/library/logging.rst python/branches/py3k-dtoa/Doc/library/os.path.rst python/branches/py3k-dtoa/Doc/library/os.rst python/branches/py3k-dtoa/Doc/library/pdb.rst python/branches/py3k-dtoa/Doc/library/re.rst python/branches/py3k-dtoa/Doc/library/socket.rst python/branches/py3k-dtoa/Doc/library/ssl.rst python/branches/py3k-dtoa/Doc/library/stdtypes.rst python/branches/py3k-dtoa/Doc/library/string.rst python/branches/py3k-dtoa/Doc/library/struct.rst python/branches/py3k-dtoa/Doc/library/sys.rst python/branches/py3k-dtoa/Doc/library/sysconfig.rst python/branches/py3k-dtoa/Doc/library/unittest.rst python/branches/py3k-dtoa/Doc/library/urllib.parse.rst python/branches/py3k-dtoa/Doc/library/urllib.request.rst python/branches/py3k-dtoa/Doc/library/warnings.rst python/branches/py3k-dtoa/Doc/reference/compound_stmts.rst python/branches/py3k-dtoa/Doc/reference/datamodel.rst python/branches/py3k-dtoa/Doc/reference/introduction.rst python/branches/py3k-dtoa/Doc/reference/lexical_analysis.rst python/branches/py3k-dtoa/Doc/tools/sphinxext/pyspecific.py python/branches/py3k-dtoa/Doc/tutorial/classes.rst python/branches/py3k-dtoa/Doc/tutorial/controlflow.rst python/branches/py3k-dtoa/Doc/tutorial/introduction.rst python/branches/py3k-dtoa/Doc/using/mac.rst python/branches/py3k-dtoa/Doc/whatsnew/2.7.rst python/branches/py3k-dtoa/Doc/whatsnew/3.0.rst python/branches/py3k-dtoa/Doc/whatsnew/3.2.rst python/branches/py3k-dtoa/Grammar/Grammar python/branches/py3k-dtoa/Include/longobject.h python/branches/py3k-dtoa/Include/pyctype.h python/branches/py3k-dtoa/Include/traceback.h python/branches/py3k-dtoa/Include/unicodeobject.h python/branches/py3k-dtoa/Lib/_strptime.py python/branches/py3k-dtoa/Lib/contextlib.py python/branches/py3k-dtoa/Lib/ctypes/__init__.py python/branches/py3k-dtoa/Lib/ctypes/test/test_callbacks.py python/branches/py3k-dtoa/Lib/ctypes/test/test_win32.py python/branches/py3k-dtoa/Lib/dis.py python/branches/py3k-dtoa/Lib/distutils/msvc9compiler.py python/branches/py3k-dtoa/Lib/distutils/unixccompiler.py python/branches/py3k-dtoa/Lib/encodings/aliases.py python/branches/py3k-dtoa/Lib/heapq.py python/branches/py3k-dtoa/Lib/http/cookiejar.py python/branches/py3k-dtoa/Lib/idlelib/textView.py python/branches/py3k-dtoa/Lib/importlib/__init__.py python/branches/py3k-dtoa/Lib/importlib/_bootstrap.py python/branches/py3k-dtoa/Lib/importlib/abc.py python/branches/py3k-dtoa/Lib/importlib/test/extension/test_case_sensitivity.py python/branches/py3k-dtoa/Lib/importlib/test/extension/test_finder.py python/branches/py3k-dtoa/Lib/importlib/test/extension/test_loader.py python/branches/py3k-dtoa/Lib/importlib/test/extension/test_path_hook.py python/branches/py3k-dtoa/Lib/importlib/test/import_/test_path.py python/branches/py3k-dtoa/Lib/importlib/test/regrtest.py python/branches/py3k-dtoa/Lib/importlib/test/source/test_abc_loader.py python/branches/py3k-dtoa/Lib/importlib/test/source/test_case_sensitivity.py python/branches/py3k-dtoa/Lib/importlib/test/source/test_file_loader.py python/branches/py3k-dtoa/Lib/importlib/test/source/test_finder.py python/branches/py3k-dtoa/Lib/importlib/test/source/test_path_hook.py python/branches/py3k-dtoa/Lib/importlib/test/source/test_source_encoding.py python/branches/py3k-dtoa/Lib/importlib/test/test_abc.py python/branches/py3k-dtoa/Lib/importlib/test/test_api.py python/branches/py3k-dtoa/Lib/importlib/test/test_util.py python/branches/py3k-dtoa/Lib/inspect.py python/branches/py3k-dtoa/Lib/lib2to3/ (props changed) python/branches/py3k-dtoa/Lib/lib2to3/fixes/fix_itertools_imports.py python/branches/py3k-dtoa/Lib/lib2to3/tests/test_fixers.py python/branches/py3k-dtoa/Lib/logging/config.py python/branches/py3k-dtoa/Lib/macpath.py python/branches/py3k-dtoa/Lib/ntpath.py python/branches/py3k-dtoa/Lib/os2emxpath.py python/branches/py3k-dtoa/Lib/pdb.doc python/branches/py3k-dtoa/Lib/pdb.py python/branches/py3k-dtoa/Lib/pickletools.py python/branches/py3k-dtoa/Lib/posixpath.py python/branches/py3k-dtoa/Lib/pydoc.py python/branches/py3k-dtoa/Lib/site.py python/branches/py3k-dtoa/Lib/smtpd.py python/branches/py3k-dtoa/Lib/subprocess.py python/branches/py3k-dtoa/Lib/test/test_audioop.py python/branches/py3k-dtoa/Lib/test/test_codeccallbacks.py python/branches/py3k-dtoa/Lib/test/test_codecs.py python/branches/py3k-dtoa/Lib/test/test_complex.py python/branches/py3k-dtoa/Lib/test/test_contextlib.py python/branches/py3k-dtoa/Lib/test/test_datetime.py python/branches/py3k-dtoa/Lib/test/test_descr.py python/branches/py3k-dtoa/Lib/test/test_dict.py python/branches/py3k-dtoa/Lib/test/test_dis.py python/branches/py3k-dtoa/Lib/test/test_enumerate.py python/branches/py3k-dtoa/Lib/test/test_exceptions.py python/branches/py3k-dtoa/Lib/test/test_extcall.py python/branches/py3k-dtoa/Lib/test/test_float.py python/branches/py3k-dtoa/Lib/test/test_genericpath.py python/branches/py3k-dtoa/Lib/test/test_getargs2.py python/branches/py3k-dtoa/Lib/test/test_http_cookiejar.py python/branches/py3k-dtoa/Lib/test/test_imp.py python/branches/py3k-dtoa/Lib/test/test_import.py python/branches/py3k-dtoa/Lib/test/test_inspect.py python/branches/py3k-dtoa/Lib/test/test_iter.py python/branches/py3k-dtoa/Lib/test/test_keywordonlyarg.py python/branches/py3k-dtoa/Lib/test/test_logging.py python/branches/py3k-dtoa/Lib/test/test_math.py python/branches/py3k-dtoa/Lib/test/test_optparse.py python/branches/py3k-dtoa/Lib/test/test_os.py python/branches/py3k-dtoa/Lib/test/test_parser.py python/branches/py3k-dtoa/Lib/test/test_property.py python/branches/py3k-dtoa/Lib/test/test_pyexpat.py python/branches/py3k-dtoa/Lib/test/test_runpy.py python/branches/py3k-dtoa/Lib/test/test_strtod.py python/branches/py3k-dtoa/Lib/test/test_subprocess.py python/branches/py3k-dtoa/Lib/test/test_syntax.py python/branches/py3k-dtoa/Lib/test/test_tokenize.py python/branches/py3k-dtoa/Lib/test/test_tuple.py python/branches/py3k-dtoa/Lib/test/test_unicode.py python/branches/py3k-dtoa/Lib/test/test_urllib.py python/branches/py3k-dtoa/Lib/test/test_xmlrpc_net.py python/branches/py3k-dtoa/Lib/urllib/parse.py python/branches/py3k-dtoa/Lib/urllib/request.py python/branches/py3k-dtoa/Lib/uuid.py python/branches/py3k-dtoa/Lib/warnings.py python/branches/py3k-dtoa/Misc/ACKS python/branches/py3k-dtoa/Misc/NEWS python/branches/py3k-dtoa/Misc/Vim/vimrc python/branches/py3k-dtoa/Modules/_ctypes/callproc.c python/branches/py3k-dtoa/Modules/_ctypes/libffi/fficonfig.py.in python/branches/py3k-dtoa/Modules/_ctypes/libffi_msvc/ffi.h python/branches/py3k-dtoa/Modules/_ctypes/libffi_msvc/fficonfig.h python/branches/py3k-dtoa/Modules/_math.c python/branches/py3k-dtoa/Modules/_scproxy.c python/branches/py3k-dtoa/Modules/_ssl.c python/branches/py3k-dtoa/Modules/_testcapimodule.c python/branches/py3k-dtoa/Modules/audioop.c python/branches/py3k-dtoa/Modules/datetimemodule.c python/branches/py3k-dtoa/Modules/mathmodule.c python/branches/py3k-dtoa/Modules/parsermodule.c python/branches/py3k-dtoa/Modules/posixmodule.c python/branches/py3k-dtoa/Modules/selectmodule.c python/branches/py3k-dtoa/Modules/timemodule.c python/branches/py3k-dtoa/Modules/xxmodule.c python/branches/py3k-dtoa/Objects/abstract.c python/branches/py3k-dtoa/Objects/bytes_methods.c python/branches/py3k-dtoa/Objects/descrobject.c python/branches/py3k-dtoa/Objects/enumobject.c python/branches/py3k-dtoa/Objects/exceptions.c python/branches/py3k-dtoa/Objects/floatobject.c python/branches/py3k-dtoa/Objects/frameobject.c python/branches/py3k-dtoa/Objects/typeobject.c python/branches/py3k-dtoa/Objects/unicodeobject.c python/branches/py3k-dtoa/PC/VS8.0/pythoncore.vcproj python/branches/py3k-dtoa/PCbuild/_ctypes.vcproj python/branches/py3k-dtoa/PCbuild/pythoncore.vcproj python/branches/py3k-dtoa/Parser/Python.asdl python/branches/py3k-dtoa/Parser/asdl_c.py python/branches/py3k-dtoa/Python/Python-ast.c python/branches/py3k-dtoa/Python/_warnings.c python/branches/py3k-dtoa/Python/ast.c python/branches/py3k-dtoa/Python/ceval.c python/branches/py3k-dtoa/Python/compile.c python/branches/py3k-dtoa/Python/getargs.c python/branches/py3k-dtoa/Python/import.c python/branches/py3k-dtoa/Python/pythonrun.c python/branches/py3k-dtoa/Python/sysmodule.c python/branches/py3k-dtoa/Python/traceback.c python/branches/py3k-dtoa/README python/branches/py3k-dtoa/Tools/README python/branches/py3k-dtoa/Tools/scripts/ (props changed) python/branches/py3k-dtoa/Tools/scripts/patchcheck.py python/branches/py3k-dtoa/configure python/branches/py3k-dtoa/setup.py Modified: python/branches/py3k-dtoa/Demo/classes/Complex.py ============================================================================== --- python/branches/py3k-dtoa/Demo/classes/Complex.py (original) +++ python/branches/py3k-dtoa/Demo/classes/Complex.py Tue Jul 6 17:55:27 2010 @@ -151,13 +151,9 @@ raise ValueError("can't convert Complex with nonzero im to float") return float(self.re) - def __cmp__(self, other): + def __eq__(self, other): other = ToComplex(other) - return cmp((self.re, self.im), (other.re, other.im)) - - def __rcmp__(self, other): - other = ToComplex(other) - return cmp(other, self) + return (self.re, self.im) == (other.re, other.im) def __bool__(self): return not (self.re == self.im == 0) @@ -190,14 +186,14 @@ __rmul__ = __mul__ - def __div__(self, other): + def __truediv__(self, other): other = ToComplex(other) d = float(other.re*other.re + other.im*other.im) if not d: raise ZeroDivisionError('Complex division') return Complex((self.re*other.re + self.im*other.im) / d, (self.im*other.re - self.re*other.im) / d) - def __rdiv__(self, other): + def __rtruediv__(self, other): other = ToComplex(other) return other / self @@ -226,8 +222,9 @@ print(' ', a, 'and', b, end=' ') try: result = eval(expr) - except: - result = sys.exc_info()[0] + except Exception as e: + print('!!\t!!\t!! error: {}'.format(e)) + return print('->', result) if isinstance(result, str) or isinstance(value, str): ok = (result == value) @@ -295,13 +292,6 @@ (Complex(1), Complex(0,10), 1), (2, Complex(4,0), 16), ], - 'cmp(a,b)': [ - (1, 10, -1), - (1, Complex(0,10), 1), - (Complex(0,10), 1, -1), - (Complex(0,10), Complex(1), -1), - (Complex(1), Complex(0,10), 1), - ], } for expr in sorted(testsuite): print(expr + ':') Modified: python/branches/py3k-dtoa/Demo/classes/Dates.py ============================================================================== --- python/branches/py3k-dtoa/Demo/classes/Dates.py (original) +++ python/branches/py3k-dtoa/Demo/classes/Dates.py Tue Jul 6 17:55:27 2010 @@ -1,45 +1,47 @@ -# Class Date supplies date objects that support date arithmetic. -# -# Date(month,day,year) returns a Date object. An instance prints as, -# e.g., 'Mon 16 Aug 1993'. -# -# Addition, subtraction, comparison operators, min, max, and sorting -# all work as expected for date objects: int+date or date+int returns -# the date `int' days from `date'; date+date raises an exception; -# date-int returns the date `int' days before `date'; date2-date1 returns -# an integer, the number of days from date1 to date2; int-date raises an -# exception; date1 < date2 is true iff date1 occurs before date2 (& -# similarly for other comparisons); min(date1,date2) is the earlier of -# the two dates and max(date1,date2) the later; and date objects can be -# used as dictionary keys. -# -# Date objects support one visible method, date.weekday(). This returns -# the day of the week the date falls on, as a string. -# -# Date objects also have 4 read-only data attributes: -# .month in 1..12 -# .day in 1..31 -# .year int or long int -# .ord the ordinal of the date relative to an arbitrary staring point -# -# The Dates module also supplies function today(), which returns the -# current date as a date object. -# -# Those entranced by calendar trivia will be disappointed, as no attempt -# has been made to accommodate the Julian (etc) system. On the other -# hand, at least this package knows that 2000 is a leap year but 2100 -# isn't, and works fine for years with a hundred decimal digits . - -# Tim Peters tim at ksr.com -# not speaking for Kendall Square Research Corp +""" +Class Date supplies date objects that support date arithmetic. -# Adapted to Python 1.1 (where some hacks to overcome coercion are unnecessary) -# by Guido van Rossum +Date(month,day,year) returns a Date object. An instance prints as, +e.g., 'Mon 16 Aug 1993'. -# Note that as of Python 2.3, a datetime module is included in the stardard -# library. +Addition, subtraction, comparison operators, min, max, and sorting +all work as expected for date objects: int+date or date+int returns +the date `int' days from `date'; date+date raises an exception; +date-int returns the date `int' days before `date'; date2-date1 returns +an integer, the number of days from date1 to date2; int-date raises an +exception; date1 < date2 is true iff date1 occurs before date2 (& +similarly for other comparisons); min(date1,date2) is the earlier of +the two dates and max(date1,date2) the later; and date objects can be +used as dictionary keys. + +Date objects support one visible method, date.weekday(). This returns +the day of the week the date falls on, as a string. + +Date objects also have 4 read-only data attributes: + .month in 1..12 + .day in 1..31 + .year int or long int + .ord the ordinal of the date relative to an arbitrary staring point + +The Dates module also supplies function today(), which returns the +current date as a date object. + +Those entranced by calendar trivia will be disappointed, as no attempt +has been made to accommodate the Julian (etc) system. On the other +hand, at least this package knows that 2000 is a leap year but 2100 +isn't, and works fine for years with a hundred decimal digits . + +Tim Peters tim at ksr.com +not speaking for Kendall Square Research Corp + +Adapted to Python 1.1 (where some hacks to overcome coercion are unnecessary) +by Guido van Rossum + +Note that as of Python 2.3, a datetime module is included in the stardard +library. +""" -# vi:set tabsize=8: +import functools _MONTH_NAMES = [ 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', @@ -57,8 +59,6 @@ dbm = dbm + dim del dbm, dim -_INT_TYPES = type(1), type(1) - def _is_leap(year): # 1 if leap year, else 0 if year % 4 != 0: return 0 if year % 400 == 0: return 1 @@ -85,11 +85,12 @@ _DI400Y = _days_before_year(400) # number of days in 400 years def _num2date(n): # return date with ordinal n - if type(n) not in _INT_TYPES: + if not isinstance(n, int): raise TypeError('argument must be integer: %r' % type(n)) - ans = Date(1,1,1) # arguments irrelevant; just getting a Date obj - del ans.ord, ans.month, ans.day, ans.year # un-initialize it + # Get uninitialized Date object. This is necesary because once + # attributes are set, they cannot be changed. + ans = Date.__new__(Date) ans.ord = n n400 = (n-1)//_DI400Y # # of 400-year blocks preceding @@ -99,11 +100,7 @@ if dby >= n: more = more - 1 dby = dby - _days_in_year(more) - year, n = year + more, int(n - dby) - - try: year = int(year) # chop to int, if it fits - except (ValueError, OverflowError): pass - + year, n = year + more, n - dby month = min(n//29 + 1, 12) dbm = _days_before_month(month, year) if dbm >= n: @@ -114,9 +111,9 @@ return ans def _num2day(n): # return weekday name of day with ordinal n - return _DAY_NAMES[ int(n % 7) ] - + return _DAY_NAMES[n % 7] + at functools.total_ordering class Date: def __init__(self, month, day, year): if not 1 <= month <= 12: @@ -124,7 +121,7 @@ dim = _days_in_month(month, year) if not 1 <= day <= dim: raise ValueError('day must be in 1..%r: %r' % (dim, day)) - self.month, self.day, self.year = month, day, year + self.month, self.day, self.year = map(int, (month, day, year)) self.ord = _date2num(self) # don't allow setting existing attributes @@ -133,8 +130,11 @@ raise AttributeError('read-only attribute ' + name) self.__dict__[name] = value - def __cmp__(self, other): - return cmp(self.ord, other.ord) + def __eq__(self, other): + return self.ord == other.ord + + def __lt__(self, other): + return self.ord < other.ord # define a hash function so dates can be used as dictionary keys def __hash__(self): @@ -150,14 +150,14 @@ # Python 1.1 coerces neither int+date nor date+int def __add__(self, n): - if type(n) not in _INT_TYPES: + if not isinstance(n, int): raise TypeError('can\'t add %r to date' % type(n)) return _num2date(self.ord + n) __radd__ = __add__ # handle int+date # Python 1.1 coerces neither date-int nor date-date def __sub__(self, other): - if type(other) in _INT_TYPES: # date-int + if isinstance(other, int): # date-int return _num2date(self.ord - other) else: return self.ord - other.ord # date-date Deleted: python/branches/py3k-dtoa/Demo/classes/Dbm.py ============================================================================== --- python/branches/py3k-dtoa/Demo/classes/Dbm.py Tue Jul 6 17:55:27 2010 +++ (empty file) @@ -1,66 +0,0 @@ -# A wrapper around the (optional) built-in class dbm, supporting keys -# and values of almost any type instead of just string. -# (Actually, this works only for keys and values that can be read back -# correctly after being converted to a string.) - - -class Dbm: - - def __init__(self, filename, mode, perm): - import dbm.ndbm - self.db = dbm.ndbm.open(filename, mode, perm) - - def __repr__(self): - s = '' - for key in self.keys(): - t = repr(key) + ': ' + repr(self[key]) - if s: t = ', ' + t - s = s + t - return '{' + s + '}' - - def __len__(self): - return len(self.db) - - def __getitem__(self, key): - return eval(self.db[repr(key)]) - - def __setitem__(self, key, value): - self.db[repr(key)] = repr(value) - - def __delitem__(self, key): - del self.db[repr(key)] - - def keys(self): - res = [] - for key in self.db.keys(): - res.append(eval(key)) - return res - - def has_key(self, key): - return repr(key) in self.db - - -def test(): - d = Dbm('@dbm', 'rw', 0o600) - print(d) - while 1: - try: - key = eval(input('key: ')) - if key in d: - value = d[key] - print('currently:', value) - value = eval(input('value: ')) - if value is None: - del d[key] - else: - d[key] = value - except KeyboardInterrupt: - print('') - print(d) - except EOFError: - print('[eof]') - break - print(d) - - -test() Modified: python/branches/py3k-dtoa/Demo/classes/README ============================================================================== --- python/branches/py3k-dtoa/Demo/classes/README (original) +++ python/branches/py3k-dtoa/Demo/classes/README Tue Jul 6 17:55:27 2010 @@ -2,7 +2,6 @@ Complex.py Complex numbers Dates.py Date manipulation package by Tim Peters -Dbm.py Wrapper around built-in dbm, supporting arbitrary values Range.py Example of a generator: re-implement built-in range() Rev.py Yield the reverse of a sequence Vec.py A simple vector class Modified: python/branches/py3k-dtoa/Demo/classes/Range.py ============================================================================== --- python/branches/py3k-dtoa/Demo/classes/Range.py (original) +++ python/branches/py3k-dtoa/Demo/classes/Range.py Tue Jul 6 17:55:27 2010 @@ -66,7 +66,7 @@ def test(): import time, builtins #Just a quick sanity check - correct_result = builtins.range(5, 100, 3) + correct_result = list(builtins.range(5, 100, 3)) oldrange_result = list(oldrange(5, 100, 3)) genrange_result = list(genrange(5, 100, 3)) if genrange_result != correct_result or oldrange_result != correct_result: Modified: python/branches/py3k-dtoa/Demo/classes/Rev.py ============================================================================== --- python/branches/py3k-dtoa/Demo/classes/Rev.py (original) +++ python/branches/py3k-dtoa/Demo/classes/Rev.py Tue Jul 6 17:55:27 2010 @@ -4,8 +4,7 @@ It works on mutable or inmutable sequences. ->>> chars = list(Rev('Hello World!')) ->>> print ''.join(chars) +>>> Rev('Hello World!') !dlroW olleH The .forw is so you can use anonymous sequences in __init__, and still @@ -16,16 +15,16 @@ confusion. Maybe it should be change to copy input sequence to break the connection completely ? ) ->>> nnn = range(3) +>>> nnn = list(range(3)) >>> rnn = Rev(nnn) ->>> for n in rnn: print n +>>> for n in rnn: n ... 2 1 0 >>> for n in range(4, 6): nnn.append(n) # update nnn ... ->>> for n in rnn: print n # prints reversed updated values +>>> for n in rnn: n # prints reversed updated values ... 5 4 @@ -35,7 +34,7 @@ >>> nnn = nnn[1:-1] >>> nnn [1, 2, 4] ->>> for n in rnn: print n # prints reversed values of old nnn +>>> for n in rnn: n # prints reversed values of old nnn ... 5 4 @@ -45,16 +44,15 @@ # >>> WH = Rev('Hello World!') ->>> print WH.forw, WH.back +>>> print(WH.forw, WH.back) Hello World! !dlroW olleH ->>> nnn = Rev(range(1, 10)) ->>> print nnn.forw +>>> nnn = Rev(list(range(1, 10))) +>>> print(nnn.forw) [1, 2, 3, 4, 5, 6, 7, 8, 9] ->>> print nnn.back +>>> print(nnn.back) [9, 8, 7, 6, 5, 4, 3, 2, 1] ->>> rrr = Rev(nnn) ->>> rrr +>>> Rev(nnn) <1, 2, 3, 4, 5, 6, 7, 8, 9> ''' Modified: python/branches/py3k-dtoa/Demo/classes/Vec.py ============================================================================== --- python/branches/py3k-dtoa/Demo/classes/Vec.py (original) +++ python/branches/py3k-dtoa/Demo/classes/Vec.py Tue Jul 6 17:55:27 2010 @@ -1,23 +1,41 @@ -# A simple vector class +class Vec: + """ A simple vector class + Instances of the Vec class can be constructed from numbers -def vec(*v): - return Vec(*v) + >>> a = Vec(1, 2, 3) + >>> b = Vec(3, 2, 1) + added + >>> a + b + Vec(4, 4, 4) -class Vec: + subtracted + >>> a - b + Vec(-2, 0, 2) + + and multiplied by a scalar on the left + >>> 3.0 * a + Vec(3.0, 6.0, 9.0) + or on the right + >>> a * 3.0 + Vec(3.0, 6.0, 9.0) + """ def __init__(self, *v): self.v = list(v) - def fromlist(self, v): + @classmethod + def fromlist(cls, v): if not isinstance(v, list): raise TypeError - self.v = v[:] - return self + inst = cls() + inst.v = v + return inst def __repr__(self): - return 'vec(' + repr(self.v)[1:-1] + ')' + args = ', '.join(repr(x) for x in self.v) + return 'Vec({})'.format(args) def __len__(self): return len(self.v) @@ -27,28 +45,24 @@ def __add__(self, other): # Element-wise addition - v = list(map(lambda x, y: x+y, self, other)) - return Vec().fromlist(v) + v = [x + y for x, y in zip(self.v, other.v)] + return Vec.fromlist(v) def __sub__(self, other): # Element-wise subtraction - v = list(map(lambda x, y: x-y, self, other)) - return Vec().fromlist(v) + v = [x - y for x, y in zip(self.v, other.v)] + return Vec.fromlist(v) def __mul__(self, scalar): # Multiply by scalar - v = [x*scalar for x in self.v] - return Vec().fromlist(v) + v = [x * scalar for x in self.v] + return Vec.fromlist(v) + __rmul__ = __mul__ def test(): - a = vec(1, 2, 3) - b = vec(3, 2, 1) - print(a) - print(b) - print(a+b) - print(a-b) - print(a*3.0) + import doctest + doctest.testmod() test() Modified: python/branches/py3k-dtoa/Demo/embed/Makefile ============================================================================== --- python/branches/py3k-dtoa/Demo/embed/Makefile (original) +++ python/branches/py3k-dtoa/Demo/embed/Makefile Tue Jul 6 17:55:27 2010 @@ -1,5 +1,5 @@ # Makefile for embedded Python use demo. -# (This version tailored for my Red Hat Linux 6.1 setup; +# (This version originally written on Red Hat Linux 6.1; # edit lines marked with XXX.) # XXX The compiler you are using @@ -10,7 +10,7 @@ srcdir= ../.. # Python version -VERSION= 3.0 +VERSION= 3.2 # Compiler flags OPT= -g @@ -21,7 +21,7 @@ # The Python library LIBPYTHON= $(blddir)/libpython$(VERSION).a -# XXX edit LIBS (in particular) to match $(blddir)/Modules/Makefile +# XXX edit LIBS (in particular) to match $(blddir)/Makefile LIBS= -lnsl -ldl -lreadline -ltermcap -lieee -lpthread -lutil LDFLAGS= -Xlinker -export-dynamic SYSLIBS= -lm Modified: python/branches/py3k-dtoa/Demo/embed/demo.c ============================================================================== --- python/branches/py3k-dtoa/Demo/embed/demo.c (original) +++ python/branches/py3k-dtoa/Demo/embed/demo.c Tue Jul 6 17:55:27 2010 @@ -20,10 +20,19 @@ Py_Initialize(); /* Define sys.argv. It is up to the application if you - want this; you can also let it undefined (since the Python + want this; you can also leave it undefined (since the Python code is generally not a main program it has no business - touching sys.argv...) */ - PySys_SetArgv(2, args); + touching sys.argv...) + + If the third argument is true, sys.path is modified to include + either the directory containing the script named by argv[0], or + the current working directory. This can be risky; if you run + an application embedding Python in a directory controlled by + someone else, attackers could put a Trojan-horse module in the + directory (say, a file named os.py) that your application would + then import and run. + */ + PySys_SetArgvEx(argc, argv, 0); /* Do some application specific code */ printf("Hello, brave new world\n\n"); Modified: python/branches/py3k-dtoa/Demo/md5test/md5driver.py ============================================================================== --- python/branches/py3k-dtoa/Demo/md5test/md5driver.py (original) +++ python/branches/py3k-dtoa/Demo/md5test/md5driver.py Tue Jul 6 17:55:27 2010 @@ -1,11 +1,10 @@ +from hashlib import md5 import string -import md5 from sys import argv def MDPrint(str): outstr = '' - for i in str: - o = ord(i) + for o in str: outstr = (outstr + string.hexdigits[(o >> 4) & 0xF] + string.hexdigits[o & 0xF]) @@ -42,7 +41,7 @@ print('MD5 time trial. Processing', TEST_BYTES, 'characters...') t1 = time() - mdContext = md5.new() + mdContext = md5() for i in range(TEST_BLOCKS): mdContext.update(data) @@ -57,13 +56,13 @@ def MDString(str): - MDPrint(md5.new(str).digest()) + MDPrint(md5(str.encode("utf-8")).digest()) print('"' + str + '"') def MDFile(filename): f = open(filename, 'rb') - mdContext = md5.new() + mdContext = md5() while 1: data = f.read(1024) @@ -78,7 +77,7 @@ import sys def MDFilter(): - mdContext = md5.new() + mdContext = md5() while 1: data = sys.stdin.read(16) Modified: python/branches/py3k-dtoa/Demo/parser/test_parser.py ============================================================================== --- python/branches/py3k-dtoa/Demo/parser/test_parser.py (original) +++ python/branches/py3k-dtoa/Demo/parser/test_parser.py Tue Jul 6 17:55:27 2010 @@ -11,19 +11,19 @@ global _numFailed print('----', fileName, end=' ') try: - ast = parser.suite(t) - tup = parser.ast2tuple(ast) - # this discards the first AST; a huge memory savings when running + st = parser.suite(t) + tup = parser.st2tuple(st) + # this discards the first ST; a huge memory savings when running # against a large source file like Tkinter.py. - ast = None - new = parser.tuple2ast(tup) + st = None + new = parser.tuple2st(tup) except parser.ParserError as err: print() print('parser module raised exception on input file', fileName + ':') traceback.print_exc() _numFailed = _numFailed + 1 else: - if tup != parser.ast2tuple(new): + if tup != parser.st2tuple(new): print() print('parser module failed on input file', fileName) _numFailed = _numFailed + 1 Modified: python/branches/py3k-dtoa/Demo/parser/unparse.py ============================================================================== --- python/branches/py3k-dtoa/Demo/parser/unparse.py (original) +++ python/branches/py3k-dtoa/Demo/parser/unparse.py Tue Jul 6 17:55:27 2010 @@ -1,9 +1,15 @@ "Usage: unparse.py " import sys -import _ast +import math +import ast +import tokenize import io import os +# Large float and imaginary literals get turned into infinities in the AST. +# We unparse those infinities to INFSTR. +INFSTR = "1e" + repr(sys.float_info.max_10_exp + 1) + def interleave(inter, f, seq): """Call f on each item in seq, calling inter() in between. """ @@ -20,7 +26,7 @@ class Unparser: """Methods in this class recursively traverse an AST and output source code for the abstract syntax; original formatting - is disregarged. """ + is disregarded. """ def __init__(self, tree, file = sys.stdout): """Unparser(tree, file=sys.stdout) -> None. @@ -80,10 +86,11 @@ def _ImportFrom(self, t): self.fill("from ") - self.write(t.module) + self.write("." * t.level) + if t.module: + self.write(t.module) self.write(" import ") interleave(lambda: self.write(", "), self.dispatch, t.names) - # XXX(jpe) what is level for? def _Assign(self, t): self.fill() @@ -115,7 +122,7 @@ def _Delete(self, t): self.fill("del ") - self.dispatch(t.targets) + interleave(lambda: self.write(", "), self.dispatch, t.targets) def _Assert(self, t): self.fill("assert ") @@ -124,24 +131,14 @@ self.write(", ") self.dispatch(t.msg) - def _Print(self, t): - self.fill("print ") - do_comma = False - if t.dest: - self.write(">>") - self.dispatch(t.dest) - do_comma = True - for e in t.values: - if do_comma:self.write(", ") - else:do_comma=True - self.dispatch(e) - if not t.nl: - self.write(",") - def _Global(self, t): self.fill("global ") interleave(lambda: self.write(", "), self.write, t.names) + def _Nonlocal(self, t): + self.fill("nonlocal ") + interleave(lambda: self.write(", "), self.write, t.names) + def _Yield(self, t): self.write("(") self.write("yield") @@ -151,15 +148,15 @@ self.write(")") def _Raise(self, t): - self.fill('raise ') - if t.type: - self.dispatch(t.type) - if t.inst: - self.write(", ") - self.dispatch(t.inst) - if t.tback: - self.write(", ") - self.dispatch(t.tback) + self.fill("raise") + if not t.exc: + assert not t.cause + return + self.write(" ") + self.dispatch(t.exc) + if t.cause: + self.write(" from ") + self.dispatch(t.cause) def _TryExcept(self, t): self.fill("try") @@ -176,10 +173,14 @@ self.leave() def _TryFinally(self, t): - self.fill("try") - self.enter() - self.dispatch(t.body) - self.leave() + if len(t.body) == 1 and isinstance(t.body[0], ast.TryExcept): + # try-except-finally + self.dispatch(t.body) + else: + self.fill("try") + self.enter() + self.dispatch(t.body) + self.leave() self.fill("finally") self.enter() @@ -192,21 +193,40 @@ self.write(" ") self.dispatch(t.type) if t.name: - self.write(", ") - self.dispatch(t.name) + self.write(" as ") + self.write(t.name) self.enter() self.dispatch(t.body) self.leave() def _ClassDef(self, t): self.write("\n") + for deco in t.decorator_list: + self.fill("@") + self.dispatch(deco) self.fill("class "+t.name) - if t.bases: - self.write("(") - for a in t.bases: - self.dispatch(a) - self.write(", ") - self.write(")") + self.write("(") + comma = False + for e in t.bases: + if comma: self.write(", ") + else: comma = True + self.dispatch(e) + for e in t.keywords: + if comma: self.write(", ") + else: comma = True + self.dispatch(e) + if t.starargs: + if comma: self.write(", ") + else: comma = True + self.write("*") + self.dispatch(t.starargs) + if t.kwargs: + if comma: self.write(", ") + else: comma = True + self.write("**") + self.dispatch(t.kwargs) + self.write(")") + self.enter() self.dispatch(t.body) self.leave() @@ -219,6 +239,9 @@ self.fill("def "+t.name + "(") self.dispatch(t.args) self.write(")") + if t.returns: + self.write(" -> ") + self.dispatch(t.returns) self.enter() self.dispatch(t.body) self.leave() @@ -235,15 +258,24 @@ self.fill("else") self.enter() self.dispatch(t.orelse) - self.leave + self.leave() def _If(self, t): self.fill("if ") self.dispatch(t.test) self.enter() - # XXX elif? self.dispatch(t.body) self.leave() + # collapse nested ifs into equivalent elifs. + while (t.orelse and len(t.orelse) == 1 and + isinstance(t.orelse[0], ast.If)): + t = t.orelse[0] + self.fill("elif ") + self.dispatch(t.test) + self.enter() + self.dispatch(t.body) + self.leave() + # final else if t.orelse: self.fill("else") self.enter() @@ -260,7 +292,7 @@ self.fill("else") self.enter() self.dispatch(t.orelse) - self.leave + self.leave() def _With(self, t): self.fill("with ") @@ -273,19 +305,18 @@ self.leave() # expr + def _Bytes(self, t): + self.write(repr(t.s)) + def _Str(self, tree): self.write(repr(tree.s)) def _Name(self, t): self.write(t.id) - def _Repr(self, t): - self.write("`") - self.dispatch(t.value) - self.write("`") - def _Num(self, t): - self.write(repr(t.n)) + # Substitute overflowing decimal literal for AST infinities. + self.write(repr(t.n).replace("inf", INFSTR)) def _List(self, t): self.write("[") @@ -306,6 +337,22 @@ self.dispatch(gen) self.write(")") + def _SetComp(self, t): + self.write("{") + self.dispatch(t.elt) + for gen in t.generators: + self.dispatch(gen) + self.write("}") + + def _DictComp(self, t): + self.write("{") + self.dispatch(t.key) + self.write(": ") + self.dispatch(t.value) + for gen in t.generators: + self.dispatch(gen) + self.write("}") + def _comprehension(self, t): self.write(" for ") self.dispatch(t.target) @@ -324,14 +371,20 @@ self.dispatch(t.orelse) self.write(")") + def _Set(self, t): + assert(t.elts) # should be at least one element + self.write("{") + interleave(lambda: self.write(", "), self.dispatch, t.elts) + self.write("}") + def _Dict(self, t): self.write("{") - def writem(xxx_todo_changeme): - (k, v) = xxx_todo_changeme + def write_pair(pair): + (k, v) = pair self.dispatch(k) self.write(": ") self.dispatch(v) - interleave(lambda: self.write(", "), writem, zip(t.keys, t.values)) + interleave(lambda: self.write(", "), write_pair, zip(t.keys, t.values)) self.write("}") def _Tuple(self, t): @@ -346,13 +399,14 @@ unop = {"Invert":"~", "Not": "not", "UAdd":"+", "USub":"-"} def _UnaryOp(self, t): - self.write(self.unop[t.op.__class__.__name__]) self.write("(") + self.write(self.unop[t.op.__class__.__name__]) + self.write(" ") self.dispatch(t.operand) self.write(")") binop = { "Add":"+", "Sub":"-", "Mult":"*", "Div":"/", "Mod":"%", - "LShift":">>", "RShift":"<<", "BitOr":"|", "BitXor":"^", "BitAnd":"&", + "LShift":"<<", "RShift":">>", "BitOr":"|", "BitXor":"^", "BitAnd":"&", "FloorDiv":"//", "Pow": "**"} def _BinOp(self, t): self.write("(") @@ -369,9 +423,9 @@ for o, e in zip(t.ops, t.comparators): self.write(" " + self.cmpops[o.__class__.__name__] + " ") self.dispatch(e) - self.write(")") + self.write(")") - boolops = {_ast.And: 'and', _ast.Or: 'or'} + boolops = {ast.And: 'and', ast.Or: 'or'} def _BoolOp(self, t): self.write("(") s = " %s " % self.boolops[t.op.__class__] @@ -380,6 +434,11 @@ def _Attribute(self,t): self.dispatch(t.value) + # Special case: 3.__abs__() is a syntax error, so if t.value + # is an integer literal then we need to either parenthesize + # it or add an extra space to get 3 .__abs__(). + if isinstance(t.value, ast.Num) and isinstance(t.value.n, int): + self.write(" ") self.write(".") self.write(t.attr) @@ -433,28 +492,55 @@ def _ExtSlice(self, t): interleave(lambda: self.write(', '), self.dispatch, t.dims) + # argument + def _arg(self, t): + self.write(t.arg) + if t.annotation: + self.write(": ") + self.dispatch(t.annotation) + # others def _arguments(self, t): first = True - nonDef = len(t.args)-len(t.defaults) - for a in t.args[0:nonDef]: + # normal arguments + defaults = [None] * (len(t.args) - len(t.defaults)) + t.defaults + for a, d in zip(t.args, defaults): if first:first = False else: self.write(", ") self.dispatch(a) - for a,d in zip(t.args[nonDef:], t.defaults): - if first:first = False - else: self.write(", ") - self.dispatch(a), - self.write("=") - self.dispatch(d) - if t.vararg: + if d: + self.write("=") + self.dispatch(d) + + # varargs, or bare '*' if no varargs but keyword-only arguments present + if t.vararg or t.kwonlyargs: if first:first = False else: self.write(", ") - self.write("*"+t.vararg) + self.write("*") + if t.vararg: + self.write(t.vararg) + if t.varargannotation: + self.write(": ") + self.dispatch(t.varargannotation) + + # keyword-only arguments + if t.kwonlyargs: + for a, d in zip(t.kwonlyargs, t.kw_defaults): + if first:first = False + else: self.write(", ") + self.dispatch(a), + if d: + self.write("=") + self.dispatch(d) + + # kwargs if t.kwarg: if first:first = False else: self.write(", ") self.write("**"+t.kwarg) + if t.kwargannotation: + self.write(": ") + self.dispatch(t.kwargannotation) def _keyword(self, t): self.write(t.arg) @@ -462,10 +548,12 @@ self.dispatch(t.value) def _Lambda(self, t): + self.write("(") self.write("lambda ") self.dispatch(t.args) self.write(": ") self.dispatch(t.body) + self.write(")") def _alias(self, t): self.write(t.name) @@ -473,8 +561,11 @@ self.write(" as "+t.asname) def roundtrip(filename, output=sys.stdout): - source = open(filename).read() - tree = compile(source, filename, "exec", _ast.PyCF_ONLY_AST) + with open(filename, "rb") as pyfile: + encoding = tokenize.detect_encoding(pyfile.readline)[0] + with open(filename, "r", encoding=encoding) as pyfile: + source = pyfile.read() + tree = compile(source, filename, "exec", ast.PyCF_ONLY_AST) Unparser(tree, output) Modified: python/branches/py3k-dtoa/Doc/README.txt ============================================================================== --- python/branches/py3k-dtoa/Doc/README.txt (original) +++ python/branches/py3k-dtoa/Doc/README.txt Tue Jul 6 17:55:27 2010 @@ -14,12 +14,11 @@ Building the docs ================= -You need to install Python 2.4 or higher (but Python 3.0 is not supported yet); -the toolset used to build the docs are written in Python. The toolset used -to build the documentation is called *Sphinx*, it is not included in this -tree, but maintained separately in the Python Subversion repository. Also -needed are Jinja, a templating engine (included in Sphinx as a Subversion -external), and optionally Pygments, a code highlighter. +You need to have Python 2.4 or higher installed; the toolset used to build the +docs is written in Python. It is called *Sphinx*, it is not included in this +tree, but maintained separately. Also needed are the docutils, supplying the +base markup that Sphinx uses, Jinja, a templating engine, and optionally +Pygments, a code highlighter. Using make @@ -47,29 +46,29 @@ convert them into a single Compiled HTML (.chm) file -- these are popular under Microsoft Windows, but very handy on every platform. - To create the CHM file, you need to run the Microsoft HTML Help Workshop - over the generated project (.hhp) file. + To create the CHM file, you need to run the Microsoft HTML Help Workshop over + the generated project (.hhp) file. - * "latex", which builds LaTeX source files that can be run with "pdflatex" - to produce PDF documents. + * "latex", which builds LaTeX source files as input to "pdflatex" to produce + PDF documents. * "text", which builds a plain text file for each source file. * "linkcheck", which checks all external references to see whether they are - broken, redirected or malformed, and outputs this information to stdout - as well as a plain-text (.txt) file. + broken, redirected or malformed, and outputs this information to stdout as + well as a plain-text (.txt) file. * "changes", which builds an overview over all versionadded/versionchanged/ deprecated items in the current version. This is meant as a help for the writer of the "What's New" document. - * "coverage", which builds a coverage overview for standard library modules - and C API. + * "coverage", which builds a coverage overview for standard library modules and + C API. - * "pydoc-topics", which builds a Python module containing a dictionary - with plain text documentation for the labels defined in - `tools/sphinxext/pyspecific.py` -- pydoc needs these to show topic - and keyword help. + * "pydoc-topics", which builds a Python module containing a dictionary with + plain text documentation for the labels defined in + `tools/sphinxext/pyspecific.py` -- pydoc needs these to show topic and + keyword help. A "make update" updates the Subversion checkouts in `tools/`. @@ -95,7 +94,7 @@ or by installing it from PyPI. -You can optionally also install Pygments, either as a checkout via :: +You can optionally also install Pygments, either as a checkout via :: svn co http://svn.python.org/projects/external/Pygments-1.3.1/pygments tools/pygments Modified: python/branches/py3k-dtoa/Doc/c-api/arg.rst ============================================================================== --- python/branches/py3k-dtoa/Doc/c-api/arg.rst (original) +++ python/branches/py3k-dtoa/Doc/c-api/arg.rst Tue Jul 6 17:55:27 2010 @@ -36,7 +36,7 @@ However, when a :ctype:`Py_buffer` structure gets filled, the underlying buffer is locked so that the caller can subsequently use the buffer even -inside a ``Py_BEGIN_ALLOW_THREADS`` block without the risk of mutable data +inside a :ctype:`Py_BEGIN_ALLOW_THREADS` block without the risk of mutable data being resized or destroyed. As a result, **you have to call** :cfunc:`PyBuffer_Release` after you have finished processing the data (or in any early abort case). @@ -48,9 +48,9 @@ the length argument (int or :ctype:`Py_ssize_t`) is controlled by defining the macro :cmacro:`PY_SSIZE_T_CLEAN` before including :file:`Python.h`. If the macro was defined, length is a - :ctype:`Py_ssize_t` rather than an int. This behavior will change + :ctype:`Py_ssize_t` rather than an :ctype:`int`. This behavior will change in a future Python version to only support :ctype:`Py_ssize_t` and - drop int support. It is best to always define :cmacro:`PY_SSIZE_T_CLEAN`. + drop :ctype:`int` support. It is best to always define :cmacro:`PY_SSIZE_T_CLEAN`. ``s`` (:class:`str`) [const char \*] @@ -100,7 +100,7 @@ contain embedded NUL bytes; if it does, a :exc:`TypeError` exception is raised. -``y*`` (:class:`bytes`, :class:`bytearray` or buffer compatible object) [Py_buffer \*] +``y*`` (:class:`bytes`, :class:`bytearray` or buffer compatible object) [Py_buffer] This variant on ``s*`` doesn't accept Unicode objects, only objects supporting the buffer protocol. **This is the recommended way to accept binary data.** @@ -150,21 +150,11 @@ any conversion. Raises :exc:`TypeError` if the object is not a Unicode object. The C variable may also be declared as :ctype:`PyObject\*`. -``w`` (:class:`bytearray` or read-write character buffer) [char \*] - Similar to ``y``, but accepts any object which implements the read-write buffer - interface. The caller must determine the length of the buffer by other means, - or use ``w#`` instead. Only single-segment buffer objects are accepted; - :exc:`TypeError` is raised for all others. - ``w*`` (:class:`bytearray` or read-write byte-oriented buffer) [Py_buffer] - This is to ``w`` what ``y*`` is to ``y``. - -``w#`` (:class:`bytearray` or read-write character buffer) [char \*, int] - Like ``y#``, but accepts any object which implements the read-write buffer - interface. The :ctype:`char \*` variable is set to point to the first byte - of the buffer, and the :ctype:`int` is set to the length of the buffer. - Only single-segment buffer objects are accepted; :exc:`TypeError` is raised - for all others. + This format accepts any object which implements the read-write buffer + interface. It fills a :ctype:`Py_buffer` structure provided by the caller. + The buffer may contain embedded null bytes. The caller have to call + :cfunc:`PyBuffer_Release` when it is done with the buffer. ``es`` (:class:`str`) [const char \*encoding, char \*\*buffer] This variant on ``s`` is used for encoding Unicode into a character buffer. @@ -492,11 +482,11 @@ strings a tad more readable. ``s`` (:class:`str` or ``None``) [char \*] - Convert a null-terminated C string to a Python object using ``'utf-8'`` + Convert a null-terminated C string to a Python :class:`str` object using ``'utf-8'`` encoding. If the C string pointer is *NULL*, ``None`` is used. ``s#`` (:class:`str` or ``None``) [char \*, int] - Convert a C string and its length to a Python object using ``'utf-8'`` + Convert a C string and its length to a Python :class:`str` object using ``'utf-8'`` encoding. If the C string pointer is *NULL*, the length is ignored and ``None`` is returned. Modified: python/branches/py3k-dtoa/Doc/c-api/datetime.rst ============================================================================== --- python/branches/py3k-dtoa/Doc/c-api/datetime.rst (original) +++ python/branches/py3k-dtoa/Doc/c-api/datetime.rst Tue Jul 6 17:55:27 2010 @@ -8,9 +8,10 @@ Various date and time objects are supplied by the :mod:`datetime` module. Before using any of these functions, the header file :file:`datetime.h` must be included in your source (note that this is not included by :file:`Python.h`), -and the macro :cfunc:`PyDateTime_IMPORT` must be invoked. The macro puts a -pointer to a C structure into a static variable, ``PyDateTimeAPI``, that is -used by the following macros. +and the macro :cmacro:`PyDateTime_IMPORT` must be invoked, usually as part of +the module initialisation function. The macro puts a pointer to a C structure +into a static variable, :cdata:`PyDateTimeAPI`, that is used by the following +macros. Type-check macros: Modified: python/branches/py3k-dtoa/Doc/c-api/init.rst ============================================================================== --- python/branches/py3k-dtoa/Doc/c-api/init.rst (original) +++ python/branches/py3k-dtoa/Doc/c-api/init.rst Tue Jul 6 17:55:27 2010 @@ -385,7 +385,7 @@ .. cfunction:: void PySys_SetArgv(int argc, wchar_t **argv) - This function works like :cfunc:`PySys_SetArgv` with *updatepath* set to 1. + This function works like :cfunc:`PySys_SetArgvEx` with *updatepath* set to 1. .. cfunction:: void Py_SetPythonHome(wchar_t *home) Modified: python/branches/py3k-dtoa/Doc/c-api/intro.rst ============================================================================== --- python/branches/py3k-dtoa/Doc/c-api/intro.rst (original) +++ python/branches/py3k-dtoa/Doc/c-api/intro.rst Tue Jul 6 17:55:27 2010 @@ -519,12 +519,12 @@ :mod:`builtins`, :mod:`__main__`, :mod:`sys`, and :mod:`exceptions`. It also initializes the module search path (``sys.path``). -.. index:: single: PySys_SetArgv() +.. index:: single: PySys_SetArgvEx() :cfunc:`Py_Initialize` does not set the "script argument list" (``sys.argv``). -If this variable is needed by Python code that will be executed later, it must -be set explicitly with a call to ``PySys_SetArgv(argc, argv)`` subsequent to -the call to :cfunc:`Py_Initialize`. +If this variable is needed by Python code that will be executed later, it must +be set explicitly with a call to ``PySys_SetArgvEx(argc, argv, updatepath)`` +after the call to :cfunc:`Py_Initialize`. On most systems (in particular, on Unix and Windows, although the details are slightly different), :cfunc:`Py_Initialize` calculates the module search path Modified: python/branches/py3k-dtoa/Doc/c-api/number.rst ============================================================================== --- python/branches/py3k-dtoa/Doc/c-api/number.rst (original) +++ python/branches/py3k-dtoa/Doc/c-api/number.rst Tue Jul 6 17:55:27 2010 @@ -215,18 +215,6 @@ the Python statement ``o1 |= o2``. -.. cfunction:: PyObject* PyNumber_Int(PyObject *o) - - Returns the *o* converted to an integer object on success, or *NULL* on - failure. This is the equivalent of the Python expression ``int(o)``. - - .. note:: - - This function is defined in the transitional :file:`intobject.h` - header file. It will be removed completely in Python 3.1. Use - the :cfunc:`PyNumber_Long` function instead. - - .. cfunction:: PyObject* PyNumber_Long(PyObject *o) .. index:: builtin: int Modified: python/branches/py3k-dtoa/Doc/c-api/unicode.rst ============================================================================== --- python/branches/py3k-dtoa/Doc/c-api/unicode.rst (original) +++ python/branches/py3k-dtoa/Doc/c-api/unicode.rst Tue Jul 6 17:55:27 2010 @@ -346,10 +346,10 @@ Coerce an encoded object *obj* to an Unicode object and return a reference with incremented refcount. - String and other char buffer compatible objects are decoded according to the - given encoding and using the error handling defined by errors. Both can be - *NULL* to have the interface use the default values (see the next section for - details). + :class:`bytes`, :class:`bytearray` and other char buffer compatible objects + are decoded according to the given encoding and using the error handling + defined by errors. Both can be *NULL* to have the interface use the default + values (see the next section for details). All other objects, including Unicode objects, cause a :exc:`TypeError` to be set. Modified: python/branches/py3k-dtoa/Doc/data/refcounts.dat ============================================================================== --- python/branches/py3k-dtoa/Doc/data/refcounts.dat (original) +++ python/branches/py3k-dtoa/Doc/data/refcounts.dat Tue Jul 6 17:55:27 2010 @@ -846,9 +846,6 @@ PyNumber_InPlaceXor:PyObject*:v:0: PyNumber_InPlaceXor:PyObject*:w:0: -PyNumber_Int:PyObject*::+1: -PyNumber_Int:PyObject*:o:0: - PyNumber_Invert:PyObject*::+1: PyNumber_Invert:PyObject*:o:0: Modified: python/branches/py3k-dtoa/Doc/distutils/builtdist.rst ============================================================================== --- python/branches/py3k-dtoa/Doc/distutils/builtdist.rst (original) +++ python/branches/py3k-dtoa/Doc/distutils/builtdist.rst Tue Jul 6 17:55:27 2010 @@ -322,7 +322,7 @@ option. By default the installer will display the cool "Python Powered" logo when it is -run, but you can also supply your own 152x161 bitmap which must be a Windows +run, but you can also supply your own 152x261 bitmap which must be a Windows :file:`.bmp` file with the :option:`--bitmap` option. The installer will also display a large title on the desktop background window @@ -375,7 +375,7 @@ The Postinstallation script --------------------------- -Starting with Python 2.3, a postinstallation script can be specified which the +Starting with Python 2.3, a postinstallation script can be specified with the :option:`--install-script` option. The basename of the script must be specified, and the script filename must also be listed in the scripts argument to the setup function. Modified: python/branches/py3k-dtoa/Doc/documenting/index.rst ============================================================================== --- python/branches/py3k-dtoa/Doc/documenting/index.rst (original) +++ python/branches/py3k-dtoa/Doc/documenting/index.rst Tue Jul 6 17:55:27 2010 @@ -10,9 +10,9 @@ `reStructuredText`_, developed by the `docutils`_ project, amended by custom directives and using a toolset named `Sphinx`_ to postprocess the HTML output. -This document describes the style guide for our documentation, the custom -reStructuredText markup introduced to support Python documentation and how it -should be used, as well as the Sphinx build system. +This document describes the style guide for our documentation as well as the +custom reStructuredText markup introduced by Sphinx to support Python +documentation and how it should be used. .. _reStructuredText: http://docutils.sf.net/rst.html .. _docutils: http://docutils.sf.net/ @@ -35,3 +35,4 @@ rest.rst markup.rst fromlatex.rst + building.rst Modified: python/branches/py3k-dtoa/Doc/documenting/markup.rst ============================================================================== --- python/branches/py3k-dtoa/Doc/documenting/markup.rst (original) +++ python/branches/py3k-dtoa/Doc/documenting/markup.rst Tue Jul 6 17:55:27 2010 @@ -698,10 +698,10 @@ .. toctree:: :maxdepth: 2 - intro.rst - strings.rst - datatypes.rst - numeric.rst + intro + strings + datatypes + numeric (many more files listed here) This accomplishes two things: @@ -709,8 +709,8 @@ * Tables of contents from all those files are inserted, with a maximum depth of two, that means one nested heading. ``toctree`` directives in those files are also taken into account. - * Sphinx knows that the relative order of the files ``intro.rst``, - ``strings.rst`` and so forth, and it knows that they are children of the + * Sphinx knows that the relative order of the files ``intro``, + ``strings`` and so forth, and it knows that they are children of the shown file, the library index. From this information it generates "next chapter", "previous chapter" and "parent chapter" links. Modified: python/branches/py3k-dtoa/Doc/documenting/style.rst ============================================================================== --- python/branches/py3k-dtoa/Doc/documenting/style.rst (original) +++ python/branches/py3k-dtoa/Doc/documenting/style.rst Tue Jul 6 17:55:27 2010 @@ -7,7 +7,7 @@ wherever possible. This particular style guide was selected mostly because it seems reasonable and is easy to get online. -Topics which are not covered in the Apple's style guide will be discussed in +Topics which are not covered in Apple's style guide will be discussed in this document. All reST files use an indentation of 3 spaces. The maximum line length is 80 Modified: python/branches/py3k-dtoa/Doc/faq/gui.rst ============================================================================== --- python/branches/py3k-dtoa/Doc/faq/gui.rst (original) +++ python/branches/py3k-dtoa/Doc/faq/gui.rst Tue Jul 6 17:55:27 2010 @@ -13,14 +13,14 @@ ===================== What platform-independent GUI toolkits exist for Python? --------------------------------------------------------- +======================================================== Depending on what platform(s) you are aiming at, there are several. .. XXX check links Tkinter -''''''' +------- Standard builds of Python include an object-oriented interface to the Tcl/Tk widget set, called Tkinter. This is probably the easiest to install and use. @@ -29,22 +29,27 @@ Unix platforms. wxWidgets -''''''''' +--------- -wxWidgets is a GUI class library written in C++ that's a portable -interface to various platform-specific libraries, and that has a -Python interface called `wxPython `__. - -wxWidgets preserves the look and feel of the -underlying graphics toolkit, and has a large set of widgets and -collection of GDI classes. See `the wxWidgets page -`_ for more details. +wxWidgets (http://www.wxwidgets.org) is a free, portable GUI class +library written in C++ that provides a native look and feel on a +number of platforms, with Windows, MacOS X, GTK, X11, all listed as +current stable targets. Language bindings are available for a number +of languages including Python, Perl, Ruby, etc. + +wxPython (http://www.wxpython.org) is the Python binding for +wxwidgets. While it often lags slightly behind the official wxWidgets +releases, it also offers a number of features via pure Python +extensions that are not available in other language bindings. There +is an active wxPython user and developer community. + +Both wxWidgets and wxPython are free, open source, software with +permissive licences that allow their use in commercial products as +well as in freeware or shareware. -wxWidgets supports Windows and MacOS; on Unix variants, -it supports both GTk+ and Motif toolkits. Qt -''' +--- There are bindings available for the Qt toolkit (`PyQt `_) and for KDE (`PyKDE `__). If @@ -55,13 +60,13 @@ `_. Gtk+ -'''' +---- PyGtk bindings for the `Gtk+ toolkit `_ have been implemented by James Henstridge; see . FLTK -'''' +---- Python bindings for `the FLTK toolkit `_, a simple yet powerful and mature cross-platform windowing system, are available from `the @@ -69,7 +74,7 @@ FOX -''' +---- A wrapper for `the FOX toolkit `_ called `FXpy `_ is available. FOX supports both Unix variants @@ -77,13 +82,13 @@ OpenGL -'''''' +------ For OpenGL bindings, see `PyOpenGL `_. What platform-specific GUI toolkits exist for Python? ------------------------------------------------------ +======================================================== `The Mac port `_ by Jack Jansen has a rich and ever-growing set of modules that support the native Mac toolbox calls. The port Modified: python/branches/py3k-dtoa/Doc/glossary.rst ============================================================================== --- python/branches/py3k-dtoa/Doc/glossary.rst (original) +++ python/branches/py3k-dtoa/Doc/glossary.rst Tue Jul 6 17:55:27 2010 @@ -57,11 +57,17 @@ bytecode Python source code is compiled into bytecode, the internal representation - of a Python program in the interpreter. The bytecode is also cached in - ``.pyc`` and ``.pyo`` files so that executing the same file is faster the - second time (recompilation from source to bytecode can be avoided). This - "intermediate language" is said to run on a :term:`virtual machine` - that executes the machine code corresponding to each bytecode. + of a Python program in the CPython interpreter. The bytecode is also + cached in ``.pyc`` and ``.pyo`` files so that executing the same file is + faster the second time (recompilation from source to bytecode can be + avoided). This "intermediate language" is said to run on a + :term:`virtual machine` that executes the machine code corresponding to + each bytecode. Do note that bytecodes are not expected to work between + different Python virtual machines, nor to be stable between Python + releases. + + A list of bytecode instructions can be found in the documentation for + :ref:`the dis module `. class A template for creating user-defined objects. Class definitions @@ -424,10 +430,11 @@ nested scope The ability to refer to a variable in an enclosing definition. For instance, a function defined inside another function can refer to - variables in the outer function. Note that nested scopes work only for - reference and not for assignment which will always write to the innermost - scope. In contrast, local variables both read and write in the innermost - scope. Likewise, global variables read and write to the global namespace. + variables in the outer function. Note that nested scopes by default work + only for reference and not for assignment. Local variables both read and + write in the innermost scope. Likewise, global variables read and write + to the global namespace. The :keyword:`nonlocal` allows writing to outer + scopes. new-style class Old name for the flavor of classes now used for all class objects. In Modified: python/branches/py3k-dtoa/Doc/howto/functional.rst ============================================================================== --- python/branches/py3k-dtoa/Doc/howto/functional.rst (original) +++ python/branches/py3k-dtoa/Doc/howto/functional.rst Tue Jul 6 17:55:27 2010 @@ -5,9 +5,6 @@ :Author: A. M. Kuchling :Release: 0.31 -(This is a first draft. Please send comments/error reports/suggestions to -amk at amk.ca.) - In this document, we'll take a tour of Python's features suitable for implementing programs in a functional style. After an introduction to the concepts of functional programming, we'll look at language features such as Modified: python/branches/py3k-dtoa/Doc/howto/unicode.rst ============================================================================== --- python/branches/py3k-dtoa/Doc/howto/unicode.rst (original) +++ python/branches/py3k-dtoa/Doc/howto/unicode.rst Tue Jul 6 17:55:27 2010 @@ -4,10 +4,12 @@ Unicode HOWTO ***************** -:Release: 1.1 +:Release: 1.11 -This HOWTO discusses Python's support for Unicode, and explains various problems -that people commonly encounter when trying to work with Unicode. +This HOWTO discusses Python 2.x's support for Unicode, and explains +various problems that people commonly encounter when trying to work +with Unicode. (This HOWTO has not yet been updated to cover the 3.x +versions of Python.) Introduction to Unicode @@ -146,8 +148,9 @@ 4. Many Internet standards are defined in terms of textual data, and can't handle content with embedded zero bytes. -Generally people don't use this encoding, instead choosing other encodings that -are more efficient and convenient. +Generally people don't use this encoding, instead choosing other +encodings that are more efficient and convenient. UTF-8 is probably +the most commonly supported encoding; it will be discussed below. Encodings don't have to handle every possible Unicode character, and most encodings don't. The rules for converting a Unicode string into the ASCII @@ -223,8 +226,8 @@ , for example. -Python's Unicode Support -======================== +Python 2.x's Unicode Support +============================ Now that you've learned the rudiments of Unicode, we can look at Python's Unicode features. @@ -266,8 +269,8 @@ >>> b'\x80abc'.decode("utf-8", "ignore") 'abc' -Encodings are specified as strings containing the encoding's name. Python comes -with roughly 100 different encodings; see the Python Library Reference at +Encodings are specified as strings containing the encoding's name. Python 3.2 +comes with roughly 100 different encodings; see the Python Library Reference at :ref:`standard-encodings` for a list. Some encodings have multiple names; for example, 'latin-1', 'iso_8859_1' and '8859' are all synonyms for the same encoding. @@ -626,7 +629,10 @@ Version 1.1: Feb-Nov 2008. Updates the document with respect to Python 3 changes. +Version 1.11: posted June 20 2010. Notes that Python 3.x is not covered, +and that the HOWTO only covers 2.x. +.. comment Describe Python 3.x support (new section? new document?) .. comment Additional topic: building Python w/ UCS2 or UCS4 support .. comment Describe use of codecs.StreamRecoder and StreamReaderWriter Modified: python/branches/py3k-dtoa/Doc/library/2to3.rst ============================================================================== --- python/branches/py3k-dtoa/Doc/library/2to3.rst (original) +++ python/branches/py3k-dtoa/Doc/library/2to3.rst Tue Jul 6 17:55:27 2010 @@ -276,7 +276,7 @@ Converts the :keyword:`print` statement to the :func:`print` function. -.. 2to3fixer:: raises +.. 2to3fixer:: raise Converts ``raise E, V`` to ``raise E(V)``, and ``raise E, V, T`` to ``raise E(V).with_traceback(T)``. If ``E`` is a tuple, the translation will be Modified: python/branches/py3k-dtoa/Doc/library/calendar.rst ============================================================================== --- python/branches/py3k-dtoa/Doc/library/calendar.rst (original) +++ python/branches/py3k-dtoa/Doc/library/calendar.rst Tue Jul 6 17:55:27 2010 @@ -15,7 +15,7 @@ are given as integers. For related functionality, see also the :mod:`datetime` and :mod:`time` modules. -Most of these functions and classses rely on the :mod:`datetime` module which +Most of these functions and classes rely on the :mod:`datetime` module which uses an idealized calendar, the current Gregorian calendar indefinitely extended in both directions. This matches the definition of the "proleptic Gregorian" calendar in Dershowitz and Reingold's book "Calendrical Calculations", where Modified: python/branches/py3k-dtoa/Doc/library/codecs.rst ============================================================================== --- python/branches/py3k-dtoa/Doc/library/codecs.rst (original) +++ python/branches/py3k-dtoa/Doc/library/codecs.rst Tue Jul 6 17:55:27 2010 @@ -953,6 +953,8 @@ +-----------------+--------------------------------+--------------------------------+ | cp857 | 857, IBM857 | Turkish | +-----------------+--------------------------------+--------------------------------+ +| cp858 | 858, IBM858 | Western Europe | ++-----------------+--------------------------------+--------------------------------+ | cp860 | 860, IBM860 | Portuguese | +-----------------+--------------------------------+--------------------------------+ | cp861 | 861, CP-IS, IBM861 | Icelandic | @@ -1223,6 +1225,23 @@ Convert a label to Unicode, as specified in :rfc:`3490`. +:mod:`encodings.mbcs` --- Windows ANSI codepage +----------------------------------------------- + +.. module:: encodings.mbcs + :synopsis: Windows ANSI codepage + +Encode operand according to the ANSI codepage (CP_ACP). This codec only +supports ``'strict'`` and ``'replace'`` error handlers to encode, and +``'strict'`` and ``'ignore'`` error handlers to decode. + +Availability: Windows only. + +.. versionchanged:: 3.2 + Before 3.2, the *errors* argument was ignored; ``'replace'`` was always used + to encode, and ``'ignore'`` to decode. + + :mod:`encodings.utf_8_sig` --- UTF-8 codec with BOM signature ------------------------------------------------------------- Modified: python/branches/py3k-dtoa/Doc/library/contextlib.rst ============================================================================== --- python/branches/py3k-dtoa/Doc/library/contextlib.rst (original) +++ python/branches/py3k-dtoa/Doc/library/contextlib.rst Tue Jul 6 17:55:27 2010 @@ -51,6 +51,11 @@ the exception has been handled, and execution will resume with the statement immediately following the :keyword:`with` statement. + contextmanager uses :class:`ContextDecorator` so the context managers it + creates can be used as decorators as well as in :keyword:`with` statements. + + .. versionchanged:: 3.2 + Use of :class:`ContextDecorator`. .. function:: closing(thing) @@ -79,6 +84,58 @@ ``page.close()`` will be called when the :keyword:`with` block is exited. +.. class:: ContextDecorator() + + A base class that enables a context manager to also be used as a decorator. + + Context managers inheriting from ``ContextDecorator`` have to implement + ``__enter__`` and ``__exit__`` as normal. ``__exit__`` retains its optional + exception handling even when used as a decorator. + + Example:: + + from contextlib import ContextDecorator + + class mycontext(ContextDecorator): + def __enter__(self): + print('Starting') + return self + + def __exit__(self, *exc): + print('Finishing') + return False + + >>> @mycontext() + ... def function(): + ... print('The bit in the middle') + ... + >>> function() + Starting + The bit in the middle + Finishing + + >>> with mycontext(): + ... print('The bit in the middle') + ... + Starting + The bit in the middle + Finishing + + Existing context managers that already have a base class can be extended by + using ``ContextDecorator`` as a mixin class:: + + from contextlib import ContextDecorator + + class mycontext(ContextBaseClass, ContextDecorator): + def __enter__(self): + return self + + def __exit__(self, *exc): + return False + + .. versionadded:: 3.2 + + .. seealso:: :pep:`0343` - The "with" statement Modified: python/branches/py3k-dtoa/Doc/library/datetime.rst ============================================================================== --- python/branches/py3k-dtoa/Doc/library/datetime.rst (original) +++ python/branches/py3k-dtoa/Doc/library/datetime.rst Tue Jul 6 17:55:27 2010 @@ -974,10 +974,10 @@ ``d.dst()`` returns. DST is never in effect for a UTC time. If *d* is aware, *d* is normalized to UTC time, by subtracting - ``d.utcoffset()``, and a :class:`time.struct_time` for the normalized time is - returned. :attr:`tm_isdst` is forced to 0. Note that the result's - :attr:`tm_year` member may be :const:`MINYEAR`\ -1 or :const:`MAXYEAR`\ +1, if - *d*.year was ``MINYEAR`` or ``MAXYEAR`` and UTC adjustment spills over a year + ``d.utcoffset()``, and a :class:`time.struct_time` for the + normalized time is returned. :attr:`tm_isdst` is forced to 0. Note + that an :exc:`OverflowError` may be raised if *d*.year was + ``MINYEAR`` or ``MAXYEAR`` and UTC adjustment spills over a year boundary. @@ -1760,3 +1760,10 @@ (5) For example, if :meth:`utcoffset` returns ``timedelta(hours=-3, minutes=-30)``, ``%z`` is replaced with the string ``'-0330'``. + +.. versionadded:: 3.2 + + When the ``%z`` directive is provided to the :meth:`strptime` + method, an aware :class:`datetime` object will be produced. The + ``tzinfo`` of the result will be set to a :class:`timezone` + instance. Modified: python/branches/py3k-dtoa/Doc/library/dis.rst ============================================================================== --- python/branches/py3k-dtoa/Doc/library/dis.rst (original) +++ python/branches/py3k-dtoa/Doc/library/dis.rst Tue Jul 6 17:55:27 2010 @@ -5,12 +5,19 @@ :synopsis: Disassembler for Python bytecode. -The :mod:`dis` module supports the analysis of Python :term:`bytecode` by -disassembling it. Since there is no Python assembler, this module defines the -Python assembly language. The Python bytecode which this module takes as an +The :mod:`dis` module supports the analysis of CPython :term:`bytecode` by +disassembling it. The CPython bytecode which this module takes as an input is defined in the file :file:`Include/opcode.h` and used by the compiler and the interpreter. +.. impl-detail:: + + Bytecode is an implementation detail of the CPython interpreter! No + guarantees are made that bytecode will not be added, removed, or changed + between versions of Python. Use of this module should not be considered to + work across Python VMs or Python releases. + + Example: Given the function :func:`myfunc`:: def myfunc(alist): @@ -31,23 +38,27 @@ .. function:: dis(x=None) - Disassemble the *x* object. *x* can denote either a module, a - class, a method, a function, or a code object. For a module, it disassembles - all functions. For a class, it disassembles all methods. For a single code - sequence, it prints one line per bytecode instruction. If no object is - provided, it disassembles the last traceback. + Disassemble the *x* object. *x* can denote either a module, a + class, a method, a function, a code object, a string of source code or a + byte sequence of raw bytecode. For a module, it disassembles all + functions. For a class, it disassembles all methods. For a code object + or sequence of raw bytecode, it prints one line per bytecode instruction. + Strings are first compiled to code objects with the :func:`compile` + built-in function before being disassembled. If no object is provided, + this function disassembles the last traceback. .. function:: distb(tb=None) - Disassembles the top-of-stack function of a traceback, using the last traceback - if none was passed. The instruction causing the exception is indicated. + Disassemble the top-of-stack function of a traceback, using the last + traceback if none was passed. The instruction causing the exception is + indicated. .. function:: disassemble(code, lasti=-1) disco(code, lasti=-1) - Disassembles a code object, indicating the last instruction if *lasti* was + Disassemble a code object, indicating the last instruction if *lasti* was provided. The output is divided in the following columns: #. the line number, for the first instruction of each line @@ -133,225 +144,233 @@ The Python compiler currently generates the following bytecode instructions. -.. opcode:: STOP_CODE () +**General instructions** + +.. opcode:: STOP_CODE Indicates end-of-code to the compiler, not used by the interpreter. -.. opcode:: NOP () +.. opcode:: NOP Do nothing code. Used as a placeholder by the bytecode optimizer. -.. opcode:: POP_TOP () +.. opcode:: POP_TOP Removes the top-of-stack (TOS) item. -.. opcode:: ROT_TWO () +.. opcode:: ROT_TWO Swaps the two top-most stack items. -.. opcode:: ROT_THREE () +.. opcode:: ROT_THREE Lifts second and third stack item one position up, moves top down to position three. -.. opcode:: ROT_FOUR () +.. opcode:: ROT_FOUR Lifts second, third and forth stack item one position up, moves top down to position four. -.. opcode:: DUP_TOP () +.. opcode:: DUP_TOP Duplicates the reference on top of the stack. -Unary Operations take the top of the stack, apply the operation, and push the -result back on the stack. +**Unary operations** + +Unary operations take the top of the stack, apply the operation, and push the +result back on the stack. -.. opcode:: UNARY_POSITIVE () +.. opcode:: UNARY_POSITIVE Implements ``TOS = +TOS``. -.. opcode:: UNARY_NEGATIVE () +.. opcode:: UNARY_NEGATIVE Implements ``TOS = -TOS``. -.. opcode:: UNARY_NOT () +.. opcode:: UNARY_NOT Implements ``TOS = not TOS``. -.. opcode:: UNARY_INVERT () +.. opcode:: UNARY_INVERT Implements ``TOS = ~TOS``. -.. opcode:: GET_ITER () +.. opcode:: GET_ITER Implements ``TOS = iter(TOS)``. + +**Binary operations** + Binary operations remove the top of the stack (TOS) and the second top-most stack item (TOS1) from the stack. They perform the operation, and put the result back on the stack. - -.. opcode:: BINARY_POWER () +.. opcode:: BINARY_POWER Implements ``TOS = TOS1 ** TOS``. -.. opcode:: BINARY_MULTIPLY () +.. opcode:: BINARY_MULTIPLY Implements ``TOS = TOS1 * TOS``. -.. opcode:: BINARY_FLOOR_DIVIDE () +.. opcode:: BINARY_FLOOR_DIVIDE Implements ``TOS = TOS1 // TOS``. -.. opcode:: BINARY_TRUE_DIVIDE () +.. opcode:: BINARY_TRUE_DIVIDE Implements ``TOS = TOS1 / TOS``. -.. opcode:: BINARY_MODULO () +.. opcode:: BINARY_MODULO Implements ``TOS = TOS1 % TOS``. -.. opcode:: BINARY_ADD () +.. opcode:: BINARY_ADD Implements ``TOS = TOS1 + TOS``. -.. opcode:: BINARY_SUBTRACT () +.. opcode:: BINARY_SUBTRACT Implements ``TOS = TOS1 - TOS``. -.. opcode:: BINARY_SUBSCR () +.. opcode:: BINARY_SUBSCR Implements ``TOS = TOS1[TOS]``. -.. opcode:: BINARY_LSHIFT () +.. opcode:: BINARY_LSHIFT Implements ``TOS = TOS1 << TOS``. -.. opcode:: BINARY_RSHIFT () +.. opcode:: BINARY_RSHIFT Implements ``TOS = TOS1 >> TOS``. -.. opcode:: BINARY_AND () +.. opcode:: BINARY_AND Implements ``TOS = TOS1 & TOS``. -.. opcode:: BINARY_XOR () +.. opcode:: BINARY_XOR Implements ``TOS = TOS1 ^ TOS``. -.. opcode:: BINARY_OR () +.. opcode:: BINARY_OR Implements ``TOS = TOS1 | TOS``. + +**In-place operations** + In-place operations are like binary operations, in that they remove TOS and TOS1, and push the result back on the stack, but the operation is done in-place when TOS1 supports it, and the resulting TOS may be (but does not have to be) the original TOS1. - -.. opcode:: INPLACE_POWER () +.. opcode:: INPLACE_POWER Implements in-place ``TOS = TOS1 ** TOS``. -.. opcode:: INPLACE_MULTIPLY () +.. opcode:: INPLACE_MULTIPLY Implements in-place ``TOS = TOS1 * TOS``. -.. opcode:: INPLACE_FLOOR_DIVIDE () +.. opcode:: INPLACE_FLOOR_DIVIDE Implements in-place ``TOS = TOS1 // TOS``. -.. opcode:: INPLACE_TRUE_DIVIDE () +.. opcode:: INPLACE_TRUE_DIVIDE Implements in-place ``TOS = TOS1 / TOS``. -.. opcode:: INPLACE_MODULO () +.. opcode:: INPLACE_MODULO Implements in-place ``TOS = TOS1 % TOS``. -.. opcode:: INPLACE_ADD () +.. opcode:: INPLACE_ADD Implements in-place ``TOS = TOS1 + TOS``. -.. opcode:: INPLACE_SUBTRACT () +.. opcode:: INPLACE_SUBTRACT Implements in-place ``TOS = TOS1 - TOS``. -.. opcode:: INPLACE_LSHIFT () +.. opcode:: INPLACE_LSHIFT Implements in-place ``TOS = TOS1 << TOS``. -.. opcode:: INPLACE_RSHIFT () +.. opcode:: INPLACE_RSHIFT Implements in-place ``TOS = TOS1 >> TOS``. -.. opcode:: INPLACE_AND () +.. opcode:: INPLACE_AND Implements in-place ``TOS = TOS1 & TOS``. -.. opcode:: INPLACE_XOR () +.. opcode:: INPLACE_XOR Implements in-place ``TOS = TOS1 ^ TOS``. -.. opcode:: INPLACE_OR () +.. opcode:: INPLACE_OR Implements in-place ``TOS = TOS1 | TOS``. -.. opcode:: STORE_SUBSCR () +.. opcode:: STORE_SUBSCR Implements ``TOS1[TOS] = TOS2``. -.. opcode:: DELETE_SUBSCR () +.. opcode:: DELETE_SUBSCR Implements ``del TOS1[TOS]``. -Miscellaneous opcodes. +**Miscellaneous opcodes** -.. opcode:: PRINT_EXPR () +.. opcode:: PRINT_EXPR Implements the expression statement for the interactive mode. TOS is removed from the stack and printed. In non-interactive mode, an expression statement is terminated with ``POP_STACK``. -.. opcode:: BREAK_LOOP () +.. opcode:: BREAK_LOOP Terminates a loop due to a :keyword:`break` statement. @@ -377,36 +396,35 @@ Calls ``dict.setitem(TOS1[-i], TOS, TOS1)``. Used to implement dict comprehensions. - For all of the SET_ADD, LIST_APPEND and MAP_ADD instructions, while the added value or key/value pair is popped off, the container object remains on the stack so that it is available for further iterations of the loop. -.. opcode:: RETURN_VALUE () +.. opcode:: RETURN_VALUE Returns with TOS to the caller of the function. -.. opcode:: YIELD_VALUE () +.. opcode:: YIELD_VALUE Pops ``TOS`` and yields it from a :term:`generator`. -.. opcode:: IMPORT_STAR () +.. opcode:: IMPORT_STAR Loads all symbols not starting with ``'_'`` directly from the module TOS to the local namespace. The module is popped after loading all names. This opcode implements ``from module import *``. -.. opcode:: POP_BLOCK () +.. opcode:: POP_BLOCK Removes one block from the block stack. Per frame, there is a stack of blocks, denoting nested loops, try statements, and such. -.. opcode:: POP_EXCEPT () +.. opcode:: POP_EXCEPT Removes one block from the block stack. The popped block must be an exception handler block, as implicitly created when entering an except handler. @@ -414,14 +432,14 @@ last three popped values are used to restore the exception state. -.. opcode:: END_FINALLY () +.. opcode:: END_FINALLY Terminates a :keyword:`finally` clause. The interpreter recalls whether the exception has to be re-raised, or whether the function returns, and continues with the outer-next block. -.. opcode:: LOAD_BUILD_CLASS () +.. opcode:: LOAD_BUILD_CLASS Pushes :func:`builtins.__build_class__` onto the stack. It is later called by ``CALL_FUNCTION`` to construct a class. @@ -439,7 +457,7 @@ :opcode:`UNPACK_SEQUENCE`). -.. opcode:: WITH_CLEANUP () +.. opcode:: WITH_CLEANUP Cleans up the stack when a :keyword:`with` statement block exits. TOS is the context manager's :meth:`__exit__` bound method. Below TOS are 1--3 @@ -649,7 +667,7 @@ Pushes a try block from a try-except clause onto the block stack. *delta* points to the finally block. -.. opcode:: STORE_MAP () +.. opcode:: STORE_MAP Store a key and value pair in a dictionary. Pops the key and value while leaving the dictionary on the stack. @@ -765,7 +783,7 @@ variable-arguments tuple, followed by explicit keyword and positional arguments. -.. opcode:: HAVE_ARGUMENT () +.. opcode:: HAVE_ARGUMENT This is not really an opcode. It identifies the dividing line between opcodes which don't take arguments ``< HAVE_ARGUMENT`` and those which do ``>= Modified: python/branches/py3k-dtoa/Doc/library/http.server.rst ============================================================================== --- python/branches/py3k-dtoa/Doc/library/http.server.rst (original) +++ python/branches/py3k-dtoa/Doc/library/http.server.rst Tue Jul 6 17:55:27 2010 @@ -284,28 +284,30 @@ For example usage, see the implementation of the :func:`test` function invocation in the :mod:`http.server` module. -The :class:`SimpleHTTPRequestHandler` class can be invoked the following manner -with the :mod:`http.server` to create a very basic webserver serving files -relative to the current directory.:: - import http.server - import socketserver +The :class:`SimpleHTTPRequestHandler` class can be used in the following +manner in order to create a very basic webserver serving files relative to +the current directory. :: - PORT = 8000 + import http.server + import socketserver - Handler = http.server.SimpleHTTPRequestHandler + PORT = 8000 - httpd = socketserver.TCPServer(("", PORT), Handler) + Handler = http.server.SimpleHTTPRequestHandler - print("serving at port", PORT) - httpd.serve_forever() + httpd = socketserver.TCPServer(("", PORT), Handler) -:mod:`http.server` can also be invoked directly using the ``-m`` switch of -interpreter a with ``port number`` argument which interfaces -:class:`SimpleHTTPRequestHandler` by default.:: + print("serving at port", PORT) + httpd.serve_forever() + +:mod:`http.server` can also be invoked directly using the :option:`-m` +switch of the interpreter a with ``port number`` argument. Similar to +the previous example, this serves files relative to the current directory. :: python -m http.server 8000 + .. class:: CGIHTTPRequestHandler(request, client_address, server) This class is used to serve either files or output of CGI scripts from the Modified: python/branches/py3k-dtoa/Doc/library/importlib.rst ============================================================================== --- python/branches/py3k-dtoa/Doc/library/importlib.rst (original) +++ python/branches/py3k-dtoa/Doc/library/importlib.rst Tue Jul 6 17:55:27 2010 @@ -18,12 +18,12 @@ :func:`__import__` function) in Python source code. This provides an implementation of :keyword:`import` which is portable to any Python interpreter. This also provides a reference implementation which is easier to -comprehend than one in a programming language other than Python. +comprehend than one implemented in a programming language other than Python. -Two, the components to implement :keyword:`import` can be exposed in this +Two, the components to implement :keyword:`import` are exposed in this package, making it easier for users to create their own custom objects (known generically as an :term:`importer`) to participate in the import process. -Details on providing custom importers can be found in :pep:`302`. +Details on custom importers can be found in :pep:`302`. .. seealso:: @@ -36,8 +36,7 @@ in :data:`sys.modules`). The :func:`.__import__` function - The built-in function for which the :keyword:`import` statement is - syntactic sugar. + The :keyword:`import` statement is syntactic sugar for this function. :pep:`235` Import on Case-Insensitive Platforms @@ -46,7 +45,7 @@ Defining Python Source Code Encodings :pep:`302` - New Import Hooks. + New Import Hooks :pep:`328` Imports: Multi-Line and Absolute/Relative @@ -57,14 +56,16 @@ :pep:`3120` Using UTF-8 as the Default Source Encoding + :pep:`3147` + PYC Repository Directories + Functions --------- .. function:: __import__(name, globals={}, locals={}, fromlist=list(), level=0) - An implementation of the built-in :func:`__import__` function. See the - built-in function's documentation for usage instructions. + An implementation of the built-in :func:`__import__` function. .. function:: import_module(name, package=None) @@ -210,22 +211,112 @@ .. method:: get_filename(fullname) - An abstract method that is to return the value for :attr:`__file__` for + An abstract method that is to return the value of :attr:`__file__` for the specified module. If no path is available, :exc:`ImportError` is raised. + If source code is available, then the method should return the path to + the source file, regardless of whether a bytecode was used to load the + module. + + +.. class:: SourceLoader + + An abstract base class for implementing source (and optionally bytecode) + file loading. The class inherits from both :class:`ResourceLoader` and + :class:`ExecutionLoader`, requiring the implementation of: + + * :meth:`ResourceLoader.get_data` + * :meth:`ExecutionLoader.get_filename` + Implement to only return the path to the source file; sourceless + loading is not supported. + + The abstract methods defined by this class are to add optional bytecode + file support. Not implementing these optional methods causes the loader to + only work with source code. Implementing the methods allows the loader to + work with source *and* bytecode files; it does not allow for *sourceless* + loading where only bytecode is provided. Bytecode files are an + optimization to speed up loading by removing the parsing step of Python's + compiler, and so no bytecode-specific API is exposed. + + .. method:: path_mtime(self, path) + + Optional abstract method which returns the modification time for the + specified path. + + .. method:: set_data(self, path, data) + + Optional abstract method which writes the specified bytes to a file + path. Any intermediate directories which do not exist are to be created + automatically. + + When writing to the path fails because the path is read-only + (:attr:`errno.EACCES`), do not propagate the exception. + + .. method:: get_code(self, fullname) + + Concrete implementation of :meth:`InspectLoader.get_code`. + + .. method:: load_module(self, fullname) + + Concrete implementation of :meth:`Loader.load_module`. + + .. method:: get_source(self, fullname) + + Concrete implementation of :meth:`InspectLoader.get_source`. + + .. method:: is_package(self, fullname) + + Concrete implementation of :meth:`InspectLoader.is_package`. A module + is determined to be a package if its file path is a file named + ``__init__`` when the file extension is removed. + .. class:: PyLoader An abstract base class inheriting from - :class:`importlib.abc.ExecutionLoader` and - :class:`importlib.abc.ResourceLoader` designed to ease the loading of + :class:`ExecutionLoader` and + :class:`ResourceLoader` designed to ease the loading of Python source modules (bytecode is not handled; see - :class:`importlib.abc.PyPycLoader` for a source/bytecode ABC). A subclass + :class:`SourceLoader` for a source/bytecode ABC). A subclass implementing this ABC will only need to worry about exposing how the source code is stored; all other details for loading Python source code will be handled by the concrete implementations of key methods. + .. deprecated:: 3.2 + This class has been deprecated in favor of :class:`SourceLoader` and is + slated for removal in Python 3.4. See below for how to create a + subclass that is compatbile with Python 3.1 onwards. + + If compatibility with Python 3.1 is required, then use the following idiom + to implement a subclass that will work with Python 3.1 onwards (make sure + to implement :meth:`ExecutionLoader.get_filename`):: + + try: + from importlib.abc import SourceLoader + except ImportError: + from importlib.abc import PyLoader as SourceLoader + + + class CustomLoader(SourceLoader): + def get_filename(self, fullname): + """Return the path to the source file.""" + # Implement ... + + def source_path(self, fullname): + """Implement source_path in terms of get_filename.""" + try: + return self.get_filename(fullname) + except ImportError: + return None + + def is_package(self, fullname): + """Implement is_package by looking for an __init__ file + name as returned by get_filename.""" + filename = os.path.basename(self.get_filename(fullname)) + return os.path.splitext(filename)[0] == '__init__' + + .. method:: source_path(fullname) An abstract method that returns the path to the source code for a @@ -267,10 +358,18 @@ .. class:: PyPycLoader - An abstract base class inheriting from :class:`importlib.abc.PyLoader`. + An abstract base class inheriting from :class:`PyLoader`. This ABC is meant to help in creating loaders that support both Python source and bytecode. + .. deprecated:: 3.2 + This class has been deprecated in favor of :class:`SourceLoader` and to + properly support :pep:`3147`. If compatibility is required with + Python 3.1, implement both :class:`SourceLoader` and :class:`PyLoader`; + instructions on how to do so are included in the documentation for + :class:`PyLoader`. Do note that this solution will not support + sourceless/bytecode-only loading; only source *and* bytecode loading. + .. method:: source_mtime(fullname) An abstract method which returns the modification time for the source @@ -289,8 +388,8 @@ .. method:: get_filename(fullname) A concrete implementation of - :meth:`importlib.abc.ExecutionLoader.get_filename` that relies on - :meth:`importlib.abc.PyLoader.source_path` and :meth:`bytecode_path`. + :meth:`ExecutionLoader.get_filename` that relies on + :meth:`PyLoader.source_path` and :meth:`bytecode_path`. If :meth:`source_path` returns a path, then that value is returned. Else if :meth:`bytecode_path` returns a path, that path will be returned. If a path is not available from both methods, @@ -417,100 +516,3 @@ attribute to be used at the global level of the module during initialization. - -Example -------- - -Below is an example meta path importer that uses a dict for back-end storage -for source code. While not an optimal solution -- manipulations of -:attr:`__path__` on packages does not influence import -- it does illustrate -what little is required to implement an importer. - -.. testcode:: - - """An importer where source is stored in a dict.""" - from importlib import abc - - - class DictImporter(abc.Finder, abc.PyLoader): - - """A meta path importer that stores source code in a dict. - - The keys are the module names -- packages must end in ``.__init__``. - The values must be something that can be passed to 'bytes'. - - """ - - def __init__(self, memory): - """Store the dict.""" - self.memory = memory - - def contains(self, name): - """See if a module or package is in the dict.""" - if name in self.memory: - return name - package_name = '{}.__init__'.format(name) - if package_name in self.memory: - return package_name - return False - - __contains__ = contains # Convenience. - - def find_module(self, fullname, path=None): - """Find the module in the dict.""" - if fullname in self: - return self - return None - - def source_path(self, fullname): - """Return the module name if the module is in the dict.""" - if not fullname in self: - raise ImportError - return fullname - - def get_data(self, path): - """Return the bytes for the source. - - The value found in the dict is passed through 'bytes' before being - returned. - - """ - name = self.contains(path) - if not name: - raise IOError - return bytes(self.memory[name]) - - def is_package(self, fullname): - """Tell if module is a package based on whether the dict contains the - name with ``.__init__`` appended to it.""" - if fullname not in self: - raise ImportError - if fullname in self.memory: - return False - # If name is in this importer but not as it is then it must end in - # ``__init__``. - else: - return True - -.. testcode:: - :hide: - - import importlib - import sys - - - # Build the dict; keys of name, value of __package__. - names = {'_top_level': '', '_pkg.__init__': '_pkg', '_pkg.mod': '_pkg'} - source = {name: "name = {!r}".format(name).encode() for name in names} - - # Register the meta path importer. - importer = DictImporter(source) - sys.meta_path.append(importer) - - # Sanity check. - for name in names: - module = importlib.import_module(name) - assert module.__name__ == name - assert getattr(module, 'name') == name - assert module.__loader__ is importer - assert module.__package__ == names[name] Modified: python/branches/py3k-dtoa/Doc/library/logging.rst ============================================================================== --- python/branches/py3k-dtoa/Doc/library/logging.rst (original) +++ python/branches/py3k-dtoa/Doc/library/logging.rst Tue Jul 6 17:55:27 2010 @@ -53,10 +53,12 @@ Most applications are probably going to want to log to a file, so let's start with that case. Using the :func:`basicConfig` function, we can set up the -default handler so that debug messages are written to a file:: +default handler so that debug messages are written to a file (in the example, +we assume that you have the appropriate permissions to create a file called +*example.log* in the current directory):: import logging - LOG_FILENAME = '/tmp/logging_example.out' + LOG_FILENAME = 'example.log' logging.basicConfig(filename=LOG_FILENAME,level=logging.DEBUG) logging.debug('This message should go to the log file') @@ -75,7 +77,7 @@ import logging import logging.handlers - LOG_FILENAME = '/tmp/logging_rotatingfile_example.out' + LOG_FILENAME = 'logging_rotatingfile_example.out' # Set up a specific logger with our desired output level my_logger = logging.getLogger('MyLogger') @@ -100,14 +102,14 @@ The result should be 6 separate files, each with part of the log history for the application:: - /tmp/logging_rotatingfile_example.out - /tmp/logging_rotatingfile_example.out.1 - /tmp/logging_rotatingfile_example.out.2 - /tmp/logging_rotatingfile_example.out.3 - /tmp/logging_rotatingfile_example.out.4 - /tmp/logging_rotatingfile_example.out.5 + logging_rotatingfile_example.out + logging_rotatingfile_example.out.1 + logging_rotatingfile_example.out.2 + logging_rotatingfile_example.out.3 + logging_rotatingfile_example.out.4 + logging_rotatingfile_example.out.5 -The most current file is always :file:`/tmp/logging_rotatingfile_example.out`, +The most current file is always :file:`logging_rotatingfile_example.out`, and each time it reaches the size limit it is renamed with the suffix ``.1``. Each of the existing backup files is renamed to increment the suffix (``.1`` becomes ``.2``, etc.) and the ``.6`` file is erased. @@ -244,7 +246,7 @@ methods listed above, but this is how to log at custom log levels. :func:`getLogger` returns a reference to a logger instance with the specified -if it is provided, or ``root`` if not. The names are period-separated +name if it is provided, or ``root`` if not. The names are period-separated hierarchical structures. Multiple calls to :func:`getLogger` with the same name will return a reference to the same logger object. Loggers that are further down in the hierarchical list are children of loggers higher up in the list. @@ -321,24 +323,34 @@ Configuring Logging ^^^^^^^^^^^^^^^^^^^ -Programmers can configure logging either by creating loggers, handlers, and -formatters explicitly in a main module with the configuration methods listed -above (using Python code), or by creating a logging config file. The following -code is an example of configuring a very simple logger, a console handler, and a -simple formatter in a Python module:: +Programmers can configure logging in three ways: + +1. Creating loggers, handlers, and formatters explicitly using Python + code that calls the configuration methods listed above. +2. Creating a logging config file and reading it using the :func:`fileConfig` + function. +3. Creating a dictionary of configuration information and passing it + to the :func:`dictConfig` function. + +The following example configures a very simple logger, a console +handler, and a simple formatter using Python code:: import logging # create logger logger = logging.getLogger("simple_example") logger.setLevel(logging.DEBUG) + # create console handler and set level to debug ch = logging.StreamHandler() ch.setLevel(logging.DEBUG) + # create formatter formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s") + # add formatter to ch ch.setFormatter(formatter) + # add ch to logger logger.addHandler(ch) @@ -428,6 +440,45 @@ class defined in package `mypackage` and module `mymodule`, where `mypackage` is available on the Python import path). +.. versionchanged:: 3.2 + +In Python 3.2, a new means of configuring logging has been introduced, using +dictionaries to hold configuration information. This provides a superset of the +functionality of the config-file-based approach outlined above, and is the +recommended configuration method for new applications and deployments. Because +a Python dictionary is used to hold configuration information, and since you +can populate that dictionary using different means, you have more options for +configuration. For example, you can use a configuration file in JSON format, +or, if you have access to YAML processing functionality, a file in YAML +format, to populate the configuration dictionary. Or, of course, you can +construct the dictionary in Python code, receive it in pickled form over a +socket, or use whatever approach makes sense for your application. + +Here's an example of the same configuration as above, in YAML format for +the new dictionary-based approach:: + + version: 1 + formatters: + simple: + format: format=%(asctime)s - %(name)s - %(levelname)s - %(message)s + handlers: + console: + class: logging.StreamHandler + level: DEBUG + formatter: simple + stream: ext://sys.stdout + loggers: + simpleExample: + level: DEBUG + handlers: [console] + propagate: no + root: + level: DEBUG + handlers: [console] + +For more information about logging using a dictionary, see +:ref:`logging-config-api`. + .. _library-config: Configuring Logging for a Library @@ -1065,14 +1116,14 @@ logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)s %(message)s', - filename='/tmp/myapp.log', + filename='myapp.log', filemode='w') logging.debug('A debug message') logging.info('Some information') logging.warning('A shot across the bows') The :meth:`basicConfig` method is used to change the configuration defaults, -which results in output (written to ``/tmp/myapp.log``) which should look +which results in output (written to ``myapp.log``) which should look something like the following:: 2004-07-02 13:00:08,743 DEBUG A debug message @@ -1364,6 +1415,8 @@ 2008-01-18 14:49:54,033 d.e.f WARNING IP: 127.0.0.1 User: jim A message at WARNING level with 2 parameters +.. _multiple-processes: + Logging to a single file from multiple processes ------------------------------------------------ @@ -1519,6 +1572,11 @@ 69 myapp.area2 WARNING Jail zesty vixen who grabbed pay from quack. 69 myapp.area2 ERROR The five boxing wizards jump quickly. +Note that there are some security issues with pickle in some scenarios. If +these affect you, you can use an alternative serialization scheme by overriding +the :meth:`makePickle` method and implementing your alternative there, as +well as adapting the above script to use your alternative serialization. + Using arbitrary objects as messages ----------------------------------- @@ -1674,6 +1732,8 @@ :exc:`NotImplementedError`. +.. _stream-handler: + StreamHandler ^^^^^^^^^^^^^ @@ -1707,6 +1767,8 @@ no output, so an explicit :meth:`flush` call may be needed at times. +.. _file-handler: + FileHandler ^^^^^^^^^^^ @@ -1715,7 +1777,7 @@ :class:`StreamHandler`. -.. class:: FileHandler(filename, mode='a', encoding=None, delay=0) +.. class:: FileHandler(filename, mode='a', encoding=None, delay=False) Returns a new instance of the :class:`FileHandler` class. The specified file is opened and used as the stream for logging. If *mode* is not specified, @@ -1733,6 +1795,7 @@ Outputs the record to the file. +.. _null-handler: NullHandler ^^^^^^^^^^^ @@ -1756,6 +1819,8 @@ See :ref:`library-config` for more information on how to use :class:`NullHandler`. +.. _watched-file-handler: + WatchedFileHandler ^^^^^^^^^^^^^^^^^^ @@ -1794,6 +1859,7 @@ changed. If it has, the existing stream is flushed and closed and the file opened again, before outputting the record to the file. +.. _rotating-file-handler: RotatingFileHandler ^^^^^^^^^^^^^^^^^^^ @@ -1834,6 +1900,7 @@ Outputs the record to the file, catering for rollover as described previously. +.. _timed-rotating-file-handler: TimedRotatingFileHandler ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -1843,7 +1910,7 @@ timed intervals. -.. class:: TimedRotatingFileHandler(filename, when='h', interval=1, backupCount=0, encoding=None, delay=0, utc=False) +.. class:: TimedRotatingFileHandler(filename, when='h', interval=1, backupCount=0, encoding=None, delay=False, utc=False) Returns a new instance of the :class:`TimedRotatingFileHandler` class. The specified file is opened and used as the stream for logging. On rotating it also @@ -1886,6 +1953,9 @@ one is deleted. The deletion logic uses the interval to determine which files to delete, so changing the interval may leave old files lying around. + If *delay* is true, then file opening is deferred until the first call to + :meth:`emit`. + .. method:: doRollover() @@ -1897,6 +1967,8 @@ Outputs the record to the file, catering for rollover as described above. +.. _socket-handler: + SocketHandler ^^^^^^^^^^^^^ @@ -1943,6 +2015,11 @@ Pickles the record's attribute dictionary in binary format with a length prefix, and returns it ready for transmission across the socket. + Note that pickles aren't completely secure. If you are concerned about + security, you may want to override this method to implement a more secure + mechanism. For example, you can sign pickles using HMAC and then verify + them on the receiving end, or alternatively you can disable unpickling of + global objects on the receiving end. .. method:: send(packet) @@ -1950,6 +2027,8 @@ partial sends which can happen when the network is busy. +.. _datagram-handler: + DatagramHandler ^^^^^^^^^^^^^^^ @@ -1983,6 +2062,8 @@ Send a pickled string to a socket. +.. _syslog-handler: + SysLogHandler ^^^^^^^^^^^^^ @@ -2172,6 +2253,7 @@ lookup to get the message ID. This version returns 1, which is the base message ID in :file:`win32service.pyd`. +.. _smtp-handler: SMTPHandler ^^^^^^^^^^^ @@ -2200,6 +2282,7 @@ If you want to specify a subject line which is record-dependent, override this method. +.. _memory-handler: MemoryHandler ^^^^^^^^^^^^^ @@ -2270,6 +2353,8 @@ Checks for buffer full or a record at the *flushLevel* or higher. +.. _http-handler: + HTTPHandler ^^^^^^^^^^^ @@ -2412,6 +2497,7 @@ just uses :func:`traceback.print_exception`. The resulting string is returned. +.. _filter: Filter Objects -------------- @@ -2437,6 +2523,7 @@ yes. If deemed appropriate, the record may be modified in-place by this method. +.. _log-record: LogRecord Objects ----------------- @@ -2468,6 +2555,7 @@ Returns the message for this :class:`LogRecord` instance after merging any user-supplied arguments with the message. +.. _logger-adapter: LoggerAdapter Objects --------------------- @@ -2553,19 +2641,57 @@ in :mod:`logging` itself) and defining handlers which are declared either in :mod:`logging` or :mod:`logging.handlers`. +.. function:: dictConfig(config) + + Takes the logging configuration from a dictionary. The contents of + this dictionary are described in :ref:`logging-config-dictschema` + below. + + If an error is encountered during configuration, this function will + raise a :exc:`ValueError`, :exc:`TypeError`, :exc:`AttributeError` + or :exc:`ImportError` with a suitably descriptive message. The + following is a (possibly incomplete) list of conditions which will + raise an error: + + * A ``level`` which is not a string or which is a string not + corresponding to an actual logging level. + * A ``propagate`` value which is not a boolean. + * An id which does not have a corresponding destination. + * A non-existent handler id found during an incremental call. + * An invalid logger name. + * Inability to resolve to an internal or external object. + + Parsing is performed by the :class:`DictConfigurator` class, whose + constructor is passed the dictionary used for configuration, and + has a :meth:`configure` method. The :mod:`logging.config` module + has a callable attribute :attr:`dictConfigClass` + which is initially set to :class:`DictConfigurator`. + You can replace the value of :attr:`dictConfigClass` with a + suitable implementation of your own. + + :func:`dictConfig` calls :attr:`dictConfigClass` passing + the specified dictionary, and then calls the :meth:`configure` method on + the returned object to put the configuration into effect:: + + def dictConfig(config): + dictConfigClass(config).configure() + + For example, a subclass of :class:`DictConfigurator` could call + ``DictConfigurator.__init__()`` in its own :meth:`__init__()`, then + set up custom prefixes which would be usable in the subsequent + :meth:`configure` call. :attr:`dictConfigClass` would be bound to + this new subclass, and then :func:`dictConfig` could be called exactly as + in the default, uncustomized state. -.. function:: fileConfig(fname, defaults=None, disable_existing_loggers=True) +.. function:: fileConfig(fname[, defaults]) Reads the logging configuration from a :mod:`configparser`\-format file named *fname*. This function can be called several times from an application, - allowing an end user the ability to select from various pre-canned + allowing an end user to select from various pre-canned configurations (if the developer provides a mechanism to present the choices and load the chosen configuration). Defaults to be passed to the ConfigParser can be specified in the *defaults* argument. - If *disable_existing_loggers* is true, any existing loggers that are not - children of named loggers will be disabled. - .. function:: listen(port=DEFAULT_LOGGING_CONFIG_PORT) @@ -2589,6 +2715,402 @@ :func:`listen`. +.. _logging-config-dictschema: + +Configuration dictionary schema +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Describing a logging configuration requires listing the various +objects to create and the connections between them; for example, you +may create a handler named "console" and then say that the logger +named "startup" will send its messages to the "console" handler. +These objects aren't limited to those provided by the :mod:`logging` +module because you might write your own formatter or handler class. +The parameters to these classes may also need to include external +objects such as ``sys.stderr``. The syntax for describing these +objects and connections is defined in :ref:`logging-config-dict-connections` +below. + +Dictionary Schema Details +""""""""""""""""""""""""" + +The dictionary passed to :func:`dictConfig` must contain the following +keys: + +* `version` - to be set to an integer value representing the schema + version. The only valid value at present is 1, but having this key + allows the schema to evolve while still preserving backwards + compatibility. + +All other keys are optional, but if present they will be interpreted +as described below. In all cases below where a 'configuring dict' is +mentioned, it will be checked for the special ``'()'`` key to see if a +custom instantiation is required. If so, the mechanism described in +:ref:`logging-config-dict-userdef` below is used to create an instance; +otherwise, the context is used to determine what to instantiate. + +* `formatters` - the corresponding value will be a dict in which each + key is a formatter id and each value is a dict describing how to + configure the corresponding Formatter instance. + + The configuring dict is searched for keys ``format`` and ``datefmt`` + (with defaults of ``None``) and these are used to construct a + :class:`logging.Formatter` instance. + +* `filters` - the corresponding value will be a dict in which each key + is a filter id and each value is a dict describing how to configure + the corresponding Filter instance. + + The configuring dict is searched for the key ``name`` (defaulting to the + empty string) and this is used to construct a :class:`logging.Filter` + instance. + +* `handlers` - the corresponding value will be a dict in which each + key is a handler id and each value is a dict describing how to + configure the corresponding Handler instance. + + The configuring dict is searched for the following keys: + + * ``class`` (mandatory). This is the fully qualified name of the + handler class. + + * ``level`` (optional). The level of the handler. + + * ``formatter`` (optional). The id of the formatter for this + handler. + + * ``filters`` (optional). A list of ids of the filters for this + handler. + + All *other* keys are passed through as keyword arguments to the + handler's constructor. For example, given the snippet:: + + handlers: + console: + class : logging.StreamHandler + formatter: brief + level : INFO + filters: [allow_foo] + stream : ext://sys.stdout + file: + class : logging.handlers.RotatingFileHandler + formatter: precise + filename: logconfig.log + maxBytes: 1024 + backupCount: 3 + + the handler with id ``console`` is instantiated as a + :class:`logging.StreamHandler`, using ``sys.stdout`` as the underlying + stream. The handler with id ``file`` is instantiated as a + :class:`logging.handlers.RotatingFileHandler` with the keyword arguments + ``filename='logconfig.log', maxBytes=1024, backupCount=3``. + +* `loggers` - the corresponding value will be a dict in which each key + is a logger name and each value is a dict describing how to + configure the corresponding Logger instance. + + The configuring dict is searched for the following keys: + + * ``level`` (optional). The level of the logger. + + * ``propagate`` (optional). The propagation setting of the logger. + + * ``filters`` (optional). A list of ids of the filters for this + logger. + + * ``handlers`` (optional). A list of ids of the handlers for this + logger. + + The specified loggers will be configured according to the level, + propagation, filters and handlers specified. + +* `root` - this will be the configuration for the root logger. + Processing of the configuration will be as for any logger, except + that the ``propagate`` setting will not be applicable. + +* `incremental` - whether the configuration is to be interpreted as + incremental to the existing configuration. This value defaults to + ``False``, which means that the specified configuration replaces the + existing configuration with the same semantics as used by the + existing :func:`fileConfig` API. + + If the specified value is ``True``, the configuration is processed + as described in the section on :ref:`logging-config-dict-incremental`. + +* `disable_existing_loggers` - whether any existing loggers are to be + disabled. This setting mirrors the parameter of the same name in + :func:`fileConfig`. If absent, this parameter defaults to ``True``. + This value is ignored if `incremental` is ``True``. + +.. _logging-config-dict-incremental: + +Incremental Configuration +""""""""""""""""""""""""" + +It is difficult to provide complete flexibility for incremental +configuration. For example, because objects such as filters +and formatters are anonymous, once a configuration is set up, it is +not possible to refer to such anonymous objects when augmenting a +configuration. + +Furthermore, there is not a compelling case for arbitrarily altering +the object graph of loggers, handlers, filters, formatters at +run-time, once a configuration is set up; the verbosity of loggers and +handlers can be controlled just by setting levels (and, in the case of +loggers, propagation flags). Changing the object graph arbitrarily in +a safe way is problematic in a multi-threaded environment; while not +impossible, the benefits are not worth the complexity it adds to the +implementation. + +Thus, when the ``incremental`` key of a configuration dict is present +and is ``True``, the system will completely ignore any ``formatters`` and +``filters`` entries, and process only the ``level`` +settings in the ``handlers`` entries, and the ``level`` and +``propagate`` settings in the ``loggers`` and ``root`` entries. + +Using a value in the configuration dict lets configurations to be sent +over the wire as pickled dicts to a socket listener. Thus, the logging +verbosity of a long-running application can be altered over time with +no need to stop and restart the application. + +.. _logging-config-dict-connections: + +Object connections +"""""""""""""""""" + +The schema describes a set of logging objects - loggers, +handlers, formatters, filters - which are connected to each other in +an object graph. Thus, the schema needs to represent connections +between the objects. For example, say that, once configured, a +particular logger has attached to it a particular handler. For the +purposes of this discussion, we can say that the logger represents the +source, and the handler the destination, of a connection between the +two. Of course in the configured objects this is represented by the +logger holding a reference to the handler. In the configuration dict, +this is done by giving each destination object an id which identifies +it unambiguously, and then using the id in the source object's +configuration to indicate that a connection exists between the source +and the destination object with that id. + +So, for example, consider the following YAML snippet:: + + formatters: + brief: + # configuration for formatter with id 'brief' goes here + precise: + # configuration for formatter with id 'precise' goes here + handlers: + h1: #This is an id + # configuration of handler with id 'h1' goes here + formatter: brief + h2: #This is another id + # configuration of handler with id 'h2' goes here + formatter: precise + loggers: + foo.bar.baz: + # other configuration for logger 'foo.bar.baz' + handlers: [h1, h2] + +(Note: YAML used here because it's a little more readable than the +equivalent Python source form for the dictionary.) + +The ids for loggers are the logger names which would be used +programmatically to obtain a reference to those loggers, e.g. +``foo.bar.baz``. The ids for Formatters and Filters can be any string +value (such as ``brief``, ``precise`` above) and they are transient, +in that they are only meaningful for processing the configuration +dictionary and used to determine connections between objects, and are +not persisted anywhere when the configuration call is complete. + +The above snippet indicates that logger named ``foo.bar.baz`` should +have two handlers attached to it, which are described by the handler +ids ``h1`` and ``h2``. The formatter for ``h1`` is that described by id +``brief``, and the formatter for ``h2`` is that described by id +``precise``. + + +.. _logging-config-dict-userdef: + +User-defined objects +"""""""""""""""""""" + +The schema supports user-defined objects for handlers, filters and +formatters. (Loggers do not need to have different types for +different instances, so there is no support in this configuration +schema for user-defined logger classes.) + +Objects to be configured are described by dictionaries +which detail their configuration. In some places, the logging system +will be able to infer from the context how an object is to be +instantiated, but when a user-defined object is to be instantiated, +the system will not know how to do this. In order to provide complete +flexibility for user-defined object instantiation, the user needs +to provide a 'factory' - a callable which is called with a +configuration dictionary and which returns the instantiated object. +This is signalled by an absolute import path to the factory being +made available under the special key ``'()'``. Here's a concrete +example:: + + formatters: + brief: + format: '%(message)s' + default: + format: '%(asctime)s %(levelname)-8s %(name)-15s %(message)s' + datefmt: '%Y-%m-%d %H:%M:%S' + custom: + (): my.package.customFormatterFactory + bar: baz + spam: 99.9 + answer: 42 + +The above YAML snippet defines three formatters. The first, with id +``brief``, is a standard :class:`logging.Formatter` instance with the +specified format string. The second, with id ``default``, has a +longer format and also defines the time format explicitly, and will +result in a :class:`logging.Formatter` initialized with those two format +strings. Shown in Python source form, the ``brief`` and ``default`` +formatters have configuration sub-dictionaries:: + + { + 'format' : '%(message)s' + } + +and:: + + { + 'format' : '%(asctime)s %(levelname)-8s %(name)-15s %(message)s', + 'datefmt' : '%Y-%m-%d %H:%M:%S' + } + +respectively, and as these dictionaries do not contain the special key +``'()'``, the instantiation is inferred from the context: as a result, +standard :class:`logging.Formatter` instances are created. The +configuration sub-dictionary for the third formatter, with id +``custom``, is:: + + { + '()' : 'my.package.customFormatterFactory', + 'bar' : 'baz', + 'spam' : 99.9, + 'answer' : 42 + } + +and this contains the special key ``'()'``, which means that +user-defined instantiation is wanted. In this case, the specified +factory callable will be used. If it is an actual callable it will be +used directly - otherwise, if you specify a string (as in the example) +the actual callable will be located using normal import mechanisms. +The callable will be called with the **remaining** items in the +configuration sub-dictionary as keyword arguments. In the above +example, the formatter with id ``custom`` will be assumed to be +returned by the call:: + + my.package.customFormatterFactory(bar='baz', spam=99.9, answer=42) + +The key ``'()'`` has been used as the special key because it is not a +valid keyword parameter name, and so will not clash with the names of +the keyword arguments used in the call. The ``'()'`` also serves as a +mnemonic that the corresponding value is a callable. + + +.. _logging-config-dict-externalobj: + +Access to external objects +"""""""""""""""""""""""""" + +There are times where a configuration needs to refer to objects +external to the configuration, for example ``sys.stderr``. If the +configuration dict is constructed using Python code, this is +straightforward, but a problem arises when the configuration is +provided via a text file (e.g. JSON, YAML). In a text file, there is +no standard way to distinguish ``sys.stderr`` from the literal string +``'sys.stderr'``. To facilitate this distinction, the configuration +system looks for certain special prefixes in string values and +treat them specially. For example, if the literal string +``'ext://sys.stderr'`` is provided as a value in the configuration, +then the ``ext://`` will be stripped off and the remainder of the +value processed using normal import mechanisms. + +The handling of such prefixes is done in a way analogous to protocol +handling: there is a generic mechanism to look for prefixes which +match the regular expression ``^(?P[a-z]+)://(?P.*)$`` +whereby, if the ``prefix`` is recognised, the ``suffix`` is processed +in a prefix-dependent manner and the result of the processing replaces +the string value. If the prefix is not recognised, then the string +value will be left as-is. + + +.. _logging-config-dict-internalobj: + +Access to internal objects +"""""""""""""""""""""""""" + +As well as external objects, there is sometimes also a need to refer +to objects in the configuration. This will be done implicitly by the +configuration system for things that it knows about. For example, the +string value ``'DEBUG'`` for a ``level`` in a logger or handler will +automatically be converted to the value ``logging.DEBUG``, and the +``handlers``, ``filters`` and ``formatter`` entries will take an +object id and resolve to the appropriate destination object. + +However, a more generic mechanism is needed for user-defined +objects which are not known to the :mod:`logging` module. For +example, consider :class:`logging.handlers.MemoryHandler`, which takes +a ``target`` argument which is another handler to delegate to. Since +the system already knows about this class, then in the configuration, +the given ``target`` just needs to be the object id of the relevant +target handler, and the system will resolve to the handler from the +id. If, however, a user defines a ``my.package.MyHandler`` which has +an ``alternate`` handler, the configuration system would not know that +the ``alternate`` referred to a handler. To cater for this, a generic +resolution system allows the user to specify:: + + handlers: + file: + # configuration of file handler goes here + + custom: + (): my.package.MyHandler + alternate: cfg://handlers.file + +The literal string ``'cfg://handlers.file'`` will be resolved in an +analogous way to strings with the ``ext://`` prefix, but looking +in the configuration itself rather than the import namespace. The +mechanism allows access by dot or by index, in a similar way to +that provided by ``str.format``. Thus, given the following snippet:: + + handlers: + email: + class: logging.handlers.SMTPHandler + mailhost: localhost + fromaddr: my_app at domain.tld + toaddrs: + - support_team at domain.tld + - dev_team at domain.tld + subject: Houston, we have a problem. + +in the configuration, the string ``'cfg://handlers'`` would resolve to +the dict with key ``handlers``, the string ``'cfg://handlers.email`` +would resolve to the dict with key ``email`` in the ``handlers`` dict, +and so on. The string ``'cfg://handlers.email.toaddrs[1]`` would +resolve to ``'dev_team.domain.tld'`` and the string +``'cfg://handlers.email.toaddrs[0]'`` would resolve to the value +``'support_team at domain.tld'``. The ``subject`` value could be accessed +using either ``'cfg://handlers.email.subject'`` or, equivalently, +``'cfg://handlers.email[subject]'``. The latter form only needs to be +used if the key contains spaces or non-alphanumeric characters. If an +index value consists only of decimal digits, access will be attempted +using the corresponding integer value, falling back to the string +value if needed. + +Given a string ``cfg://handlers.myhandler.mykey.123``, this will +resolve to ``config_dict['handlers']['myhandler']['mykey']['123']``. +If the string is specified as ``cfg://handlers.myhandler.mykey[123]``, +the system will attempt to retrieve the value from +``config_dict['handlers']['myhandler']['mykey'][123]``, and fall back +to ``config_dict['handlers']['myhandler']['mykey']['123']`` if that +fails. + .. _logging-config-fileformat: Configuration file format Modified: python/branches/py3k-dtoa/Doc/library/os.path.rst ============================================================================== --- python/branches/py3k-dtoa/Doc/library/os.path.rst (original) +++ python/branches/py3k-dtoa/Doc/library/os.path.rst Tue Jul 6 17:55:27 2010 @@ -201,6 +201,7 @@ Normalize the case of a pathname. On Unix and Mac OS X, this returns the path unchanged; on case-insensitive filesystems, it converts the path to lowercase. On Windows, it also converts forward slashes to backward slashes. + Raise a TypeError if the type of *path* is not ``str`` or ``bytes``. .. function:: normpath(path) Modified: python/branches/py3k-dtoa/Doc/library/os.rst ============================================================================== --- python/branches/py3k-dtoa/Doc/library/os.rst (original) +++ python/branches/py3k-dtoa/Doc/library/os.rst Tue Jul 6 17:55:27 2010 @@ -1115,7 +1115,8 @@ Create a directory named *path* with numeric mode *mode*. The default *mode* is ``0o777`` (octal). On some systems, *mode* is ignored. Where it is used, - the current umask value is first masked out. + the current umask value is first masked out. If the directory already + exists, :exc:`OSError` is raised. It is also possible to create temporary directories; see the :mod:`tempfile` module's :func:`tempfile.mkdtemp` function. Modified: python/branches/py3k-dtoa/Doc/library/pdb.rst ============================================================================== --- python/branches/py3k-dtoa/Doc/library/pdb.rst (original) +++ python/branches/py3k-dtoa/Doc/library/pdb.rst Tue Jul 6 17:55:27 2010 @@ -210,11 +210,13 @@ Print a stack trace, with the most recent frame at the bottom. An arrow indicates the current frame, which determines the context of most commands. -d(own) - Move the current frame one level down in the stack trace (to a newer frame). - -u(p) - Move the current frame one level up in the stack trace (to an older frame). +d(own) [*count*] + Move the current frame *count* (default one) levels down in the stack trace + (to a newer frame). + +u(p) [*count*] + Move the current frame *count* (default one) levels up in the stack trace + (to an older frame). b(reak) [[*filename*:]\ *lineno* | *function*\ [, *condition*]] With a *lineno* argument, set a break there in the current file. With a Modified: python/branches/py3k-dtoa/Doc/library/re.rst ============================================================================== --- python/branches/py3k-dtoa/Doc/library/re.rst (original) +++ python/branches/py3k-dtoa/Doc/library/re.rst Tue Jul 6 17:55:27 2010 @@ -709,18 +709,12 @@ The :class:`RegexObject` class supports the following methods and attributes: + .. method:: RegexObject.search(string[, pos[, endpos]]) - .. method:: RegexObject.match(string[, pos[, endpos]]) - - If zero or more characters at the beginning of *string* match this regular - expression, return a corresponding :class:`MatchObject` instance. Return - ``None`` if the string does not match the pattern; note that this is different - from a zero-length match. - - .. note:: - - If you want to locate a match anywhere in *string*, use - :meth:`~RegexObject.search` instead. + Scan through *string* looking for a location where this regular expression + produces a match, and return a corresponding :class:`MatchObject` instance. + Return ``None`` if no position in the string matches the pattern; note that this + is different from finding a zero-length match at some point in the string. The optional second parameter *pos* gives an index in the string where the search is to start; it defaults to ``0``. This is not completely equivalent to @@ -732,24 +726,34 @@ will be as if the string is *endpos* characters long, so only the characters from *pos* to ``endpos - 1`` will be searched for a match. If *endpos* is less than *pos*, no match will be found, otherwise, if *rx* is a compiled regular - expression object, ``rx.match(string, 0, 50)`` is equivalent to - ``rx.match(string[:50], 0)``. + expression object, ``rx.search(string, 0, 50)`` is equivalent to + ``rx.search(string[:50], 0)``. - >>> pattern = re.compile("o") - >>> pattern.match("dog") # No match as "o" is not at the start of "dog." - >>> pattern.match("dog", 1) # Match as "o" is the 2nd character of "dog". - <_sre.SRE_Match object at ...> + >>> pattern = re.compile("d") + >>> pattern.search("dog") # Match at index 0 + <_sre.SRE_Match object at ...> + >>> pattern.search("dog", 1) # No match; search doesn't include the "d" - .. method:: RegexObject.search(string[, pos[, endpos]]) + .. method:: RegexObject.match(string[, pos[, endpos]]) - Scan through *string* looking for a location where this regular expression - produces a match, and return a corresponding :class:`MatchObject` instance. - Return ``None`` if no position in the string matches the pattern; note that this - is different from finding a zero-length match at some point in the string. + If zero or more characters at the *beginning* of *string* match this regular + expression, return a corresponding :class:`MatchObject` instance. Return + ``None`` if the string does not match the pattern; note that this is different + from a zero-length match. The optional *pos* and *endpos* parameters have the same meaning as for the - :meth:`~RegexObject.match` method. + :meth:`~RegexObject.search` method. + + .. note:: + + If you want to locate a match anywhere in *string*, use + :meth:`~RegexObject.search` instead. + + >>> pattern = re.compile("o") + >>> pattern.match("dog") # No match as "o" is not at the start of "dog". + >>> pattern.match("dog", 1) # Match as "o" is the 2nd character of "dog". + <_sre.SRE_Match object at ...> .. method:: RegexObject.split(string[, maxsplit=0]) @@ -759,12 +763,16 @@ .. method:: RegexObject.findall(string[, pos[, endpos]]) - Identical to the :func:`findall` function, using the compiled pattern. + Similar to the :func:`findall` function, using the compiled pattern, but + also accepts optional *pos* and *endpos* parameters that limit the search + region like for :meth:`match`. .. method:: RegexObject.finditer(string[, pos[, endpos]]) - Identical to the :func:`finditer` function, using the compiled pattern. + Similar to the :func:`finditer` function, using the compiled pattern, but + also accepts optional *pos* and *endpos* parameters that limit the search + region like for :meth:`match`. .. method:: RegexObject.sub(repl, string[, count=0]) Modified: python/branches/py3k-dtoa/Doc/library/socket.rst ============================================================================== --- python/branches/py3k-dtoa/Doc/library/socket.rst (original) +++ python/branches/py3k-dtoa/Doc/library/socket.rst Tue Jul 6 17:55:27 2010 @@ -71,18 +71,21 @@ tuple, and the fields depend on the address type. The general tuple form is ``(addr_type, v1, v2, v3 [, scope])``, where: - - *addr_type* is one of TIPC_ADDR_NAMESEQ, TIPC_ADDR_NAME, or - TIPC_ADDR_ID. - - *scope* is one of TIPC_ZONE_SCOPE, TIPC_CLUSTER_SCOPE, and - TIPC_NODE_SCOPE. - - If *addr_type* is TIPC_ADDR_NAME, then *v1* is the server type, *v2* is - the port identifier, and *v3* should be 0. +- *addr_type* is one of TIPC_ADDR_NAMESEQ, TIPC_ADDR_NAME, or + TIPC_ADDR_ID. +- *scope* is one of TIPC_ZONE_SCOPE, TIPC_CLUSTER_SCOPE, and + TIPC_NODE_SCOPE. +- If *addr_type* is TIPC_ADDR_NAME, then *v1* is the server type, *v2* is + the port identifier, and *v3* should be 0. - If *addr_type* is TIPC_ADDR_NAMESEQ, then *v1* is the server type, *v2* - is the lower port number, and *v3* is the upper port number. + If *addr_type* is TIPC_ADDR_NAMESEQ, then *v1* is the server type, *v2* + is the lower port number, and *v3* is the upper port number. - If *addr_type* is TIPC_ADDR_ID, then *v1* is the node, *v2* is the - reference, and *v3* should be set to 0. + If *addr_type* is TIPC_ADDR_ID, then *v1* is the node, *v2* is the + reference, and *v3* should be set to 0. + + If *addr_type* is TIPC_ADDR_ID, then *v1* is the node, *v2* is the + reference, and *v3* should be set to 0. All errors raise exceptions. The normal exceptions for invalid argument types @@ -690,7 +693,7 @@ Set a timeout on blocking socket operations. The *value* argument can be a nonnegative float expressing seconds, or ``None``. If a float is given, - subsequent socket operations will raise an :exc:`timeout` exception if the + subsequent socket operations will raise a :exc:`timeout` exception if the timeout period *value* has elapsed before the operation has completed. Setting a timeout of ``None`` disables timeouts on socket operations. ``s.settimeout(0.0)`` is equivalent to ``s.setblocking(0)``; Modified: python/branches/py3k-dtoa/Doc/library/ssl.rst ============================================================================== --- python/branches/py3k-dtoa/Doc/library/ssl.rst (original) +++ python/branches/py3k-dtoa/Doc/library/ssl.rst Tue Jul 6 17:55:27 2010 @@ -110,13 +110,16 @@ .. note:: - This information varies depending on the version of OpenSSL. - For instance, in some older versions of OpenSSL (such as 0.9.7l on - OS X 10.4), an SSLv2 client could not connect to an SSLv23 server. - Conversely, starting from 1.0.0, an SSLv23 client will actually - try the SSLv3 protocol unless you explicitly enable SSLv2 ciphers. + Which connections succeed will vary depending on the version of + OpenSSL. For instance, in some older versions of OpenSSL (such + as 0.9.7l on OS X 10.4), an SSLv2 client could not connect to an + SSLv23 server. Another example: beginning with OpenSSL 1.0.0, + an SSLv23 client will not actually attempt SSLv2 connections + unless you explicitly enable SSLv2 ciphers; for example, you + might specify ``"ALL"`` or ``"SSLv2"`` as the *ciphers* parameter + to enable them. - The parameter ``ciphers`` sets the available ciphers for this SSL object. + The *ciphers* parameter sets the available ciphers for this SSL object. It should be a string in the `OpenSSL cipher list format `_. Modified: python/branches/py3k-dtoa/Doc/library/stdtypes.rst ============================================================================== --- python/branches/py3k-dtoa/Doc/library/stdtypes.rst (original) +++ python/branches/py3k-dtoa/Doc/library/stdtypes.rst Tue Jul 6 17:55:27 2010 @@ -452,7 +452,7 @@ Equivalent to:: def bit_length(self): - s = bin(x) # binary representation: bin(-37) --> '-0b100101' + s = bin(self) # binary representation: bin(-37) --> '-0b100101' s = s.lstrip('-0b') # remove leading zeros and minus sign return len(s) # len('100101') --> 6 @@ -966,7 +966,8 @@ .. method:: str.capitalize() - Return a copy of the string with only its first character capitalized. + Return a copy of the string with its first character capitalized and the + rest lowercased. .. method:: str.center(width[, fillchar]) @@ -1329,6 +1330,10 @@ You can use :meth:`str.maketrans` to create a translation map from character-to-character mappings in different formats. + You can use the :func:`~string.maketrans` helper function in the :mod:`string` + module to create a translation table. For string objects, set the *table* + argument to ``None`` for translations that only delete characters: + .. note:: An even more flexible approach is to create a custom character mapping @@ -2295,7 +2300,7 @@ File "", line 1, in ValueError: cannot modify size of memoryview object - Notice how the size of the memoryview object can not be changed. + Notice how the size of the memoryview object cannot be changed. :class:`memoryview` has two methods: Modified: python/branches/py3k-dtoa/Doc/library/string.rst ============================================================================== --- python/branches/py3k-dtoa/Doc/library/string.rst (original) +++ python/branches/py3k-dtoa/Doc/library/string.rst Tue Jul 6 17:55:27 2010 @@ -174,7 +174,7 @@ .. method:: convert_field(value, conversion) Converts the value (returned by :meth:`get_field`) given a conversion type - (as in the tuple returned by the :meth:`parse` method.) The default + (as in the tuple returned by the :meth:`parse` method). The default version understands 'r' (repr) and 's' (str) conversion types. @@ -185,7 +185,7 @@ The :meth:`str.format` method and the :class:`Formatter` class share the same syntax for format strings (although in the case of :class:`Formatter`, -subclasses can define their own format string syntax.) +subclasses can define their own format string syntax). Format strings contain "replacement fields" surrounded by curly braces ``{}``. Anything that is not contained in braces is considered literal text, which is @@ -197,7 +197,7 @@ .. productionlist:: sf replacement_field: "{" [`field_name`] ["!" `conversion`] [":" `format_spec`] "}" field_name: arg_name ("." `attribute_name` | "[" `element_index` "]")* - arg_name: (`identifier` | `integer`)? + arg_name: [`identifier` | `integer`] attribute_name: `identifier` element_index: `integer` | `index_string` index_string: + @@ -211,6 +211,8 @@ preceded by an exclamation point ``'!'``, and a *format_spec*, which is preceded by a colon ``':'``. These specify a non-default format for the replacement value. +See also the :ref:`formatspec` section. + The *field_name* itself begins with an *arg_name* that is either either a number or a keyword. If it's a number, it refers to a positional argument, and if it's a keyword, it refers to a named keyword argument. If the numerical arg_names in a format string @@ -221,6 +223,10 @@ attribute using :func:`getattr`, while an expression of the form ``'[index]'`` does an index lookup using :func:`__getitem__`. +.. versionchanged:: 3.1 + The positional argument specifiers can be omitted, so ``'{} {}'`` is + equivalent to ``'{0} {1}'``. + Some simple format string examples:: "First, thou shalt count to {0}" # References first positional argument @@ -261,26 +267,7 @@ format_spec are substituted before the *format_spec* string is interpreted. This allows the formatting of a value to be dynamically specified. -For example, suppose you wanted to have a replacement field whose field width is -determined by another variable:: - - "A man with two {0:{1}}".format("noses", 10) - -This would first evaluate the inner replacement field, making the format string -effectively:: - - "A man with two {0:10}" - -Then the outer replacement field would be evaluated, producing:: - - "noses " - -Which is substituted into the string, yielding:: - - "A man with two noses " - -(The extra space is because we specified a field width of 10, and because left -alignment is the default for strings.) +See the :ref:`formatexamples` section for some examples. .. _formatspec: @@ -290,7 +277,7 @@ "Format specifications" are used within replacement fields contained within a format string to define how individual values are presented (see -:ref:`formatstrings`.) They can also be passed directly to the built-in +:ref:`formatstrings`). They can also be passed directly to the built-in :func:`format` function. Each formattable type may define how the format specification is to be interpreted. @@ -324,7 +311,7 @@ | Option | Meaning | +=========+==========================================================+ | ``'<'`` | Forces the field to be left-aligned within the available | - | | space (This is the default.) | + | | space (this is the default). | +---------+----------------------------------------------------------+ | ``'>'`` | Forces the field to be right-aligned within the | | | available space. | @@ -366,6 +353,9 @@ For a locale aware separator, use the ``'n'`` integer presentation type instead. +.. versionchanged:: 3.1 + Added the ``','`` option (see also :pep:`378`). + *width* is a decimal integer defining the minimum field width. If not specified, then the field width will be determined by the content. @@ -484,6 +474,147 @@ +---------+----------------------------------------------------------+ +.. _formatexamples: + +Format examples +^^^^^^^^^^^^^^^ + +This section contains examples of the new format syntax and comparison with +the old ``%``-formatting. + +In most of the cases the syntax is similar to the old ``%``-formatting, with the +addition of the ``{}`` and with ``:`` used instead of ``%``. +For example, ``'%03.2f'`` can be translated to ``'{:03.2f}'``. + +The new format syntax also supports new and different options, shown in the +follow examples. + +Accessing arguments by position:: + + >>> '{0}, {1}, {2}'.format('a', 'b', 'c') + 'a, b, c' + >>> '{}, {}, {}'.format('a', 'b', 'c') # 3.1+ only + 'a, b, c' + >>> '{2}, {1}, {0}'.format('a', 'b', 'c') + 'c, b, a' + >>> '{2}, {1}, {0}'.format(*'abc') # unpacking argument sequence + 'c, b, a' + >>> '{0}{1}{0}'.format('abra', 'cad') # arguments' indices can be repeated + 'abracadabra' + +Accessing arguments by name:: + + >>> 'Coordinates: {latitude}, {longitude}'.format(latitude='37.24N', longitude='-115.81W') + 'Coordinates: 37.24N, -115.81W' + >>> coord = {'latitude': '37.24N', 'longitude': '-115.81W'} + >>> 'Coordinates: {latitude}, {longitude}'.format(**coord) + 'Coordinates: 37.24N, -115.81W' + +Accessing arguments' attributes:: + + >>> c = 3-5j + >>> ('The complex number {0} is formed from the real part {0.real} ' + ... 'and the imaginary part {0.imag}.').format(c) + 'The complex number (3-5j) is formed from the real part 3.0 and the imaginary part -5.0.' + >>> class Point: + ... def __init__(self, x, y): + ... self.x, self.y = x, y + ... def __str__(self): + ... return 'Point({self.x}, {self.y})'.format(self=self) + ... + >>> str(Point(4, 2)) + 'Point(4, 2)' + +Accessing arguments' items:: + + >>> coord = (3, 5) + >>> 'X: {0[0]}; Y: {0[1]}'.format(coord) + 'X: 3; Y: 5' + +Replacing ``%s`` and ``%r``:: + + >>> "repr() shows quotes: {!r}; str() doesn't: {!s}".format('test1', 'test2') + "repr() shows quotes: 'test1'; str() doesn't: test2" + +Aligning the text and specifying a width:: + + >>> '{:<30}'.format('left aligned') + 'left aligned ' + >>> '{:>30}'.format('right aligned') + ' right aligned' + >>> '{:^30}'.format('centered') + ' centered ' + >>> '{:*^30}'.format('centered') # use '*' as a fill char + '***********centered***********' + +Replacing ``%+f``, ``%-f``, and ``% f`` and specifying a sign:: + + >>> '{:+f}; {:+f}'.format(3.14, -3.14) # show it always + '+3.140000; -3.140000' + >>> '{: f}; {: f}'.format(3.14, -3.14) # show a space for positive numbers + ' 3.140000; -3.140000' + >>> '{:-f}; {:-f}'.format(3.14, -3.14) # show only the minus -- same as '{:f}; {:f}' + '3.140000; -3.140000' + +Replacing ``%x`` and ``%o`` and converting the value to different bases:: + + >>> # format also supports binary numbers + >>> "int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}".format(42) + 'int: 42; hex: 2a; oct: 52; bin: 101010' + >>> # with 0x, 0o, or 0b as prefix: + >>> "int: {0:d}; hex: {0:#x}; oct: {0:#o}; bin: {0:#b}".format(42) + 'int: 42; hex: 0x2a; oct: 0o52; bin: 0b101010' + +Using the comma as a thousands separator:: + + >>> '{:,}'.format(1234567890) + '1,234,567,890' + +Expressing a percentage:: + + >>> points = 19 + >>> total = 22 + >>> 'Correct answers: {:.2%}.'.format(points/total) + 'Correct answers: 86.36%' + +Using type-specific formatting:: + + >>> import datetime + >>> d = datetime.datetime(2010, 7, 4, 12, 15, 58) + >>> '{:%Y-%m-%d %H:%M:%S}'.format(d) + '2010-07-04 12:15:58' + +Nesting arguments and more complex examples:: + + >>> for align, text in zip('<^>', ['left', 'center', 'right']): + ... '{0:{align}{fill}16}'.format(text, fill=align, align=align) + ... + 'left<<<<<<<<<<<<' + '^^^^^center^^^^^' + '>>>>>>>>>>>right' + >>> + >>> octets = [192, 168, 0, 1] + >>> '{:02X}{:02X}{:02X}{:02X}'.format(*octets) + 'C0A80001' + >>> int(_, 16) + 3232235521 + >>> + >>> width = 5 + >>> for num in range(5,12): + ... for base in 'dXob': + ... print('{0:{width}{base}}'.format(num, base=base, width=width), end=' ') + ... print() + ... + 5 5 5 101 + 6 6 6 110 + 7 7 7 111 + 8 8 10 1000 + 9 9 11 1001 + 10 A 12 1010 + 11 B 13 1011 + + + .. _template-strings: Template strings Modified: python/branches/py3k-dtoa/Doc/library/struct.rst ============================================================================== --- python/branches/py3k-dtoa/Doc/library/struct.rst (original) +++ python/branches/py3k-dtoa/Doc/library/struct.rst Tue Jul 6 17:55:27 2010 @@ -151,7 +151,11 @@ ^^^^^^^^^^^^^^^^^ Format characters have the following meaning; the conversion between C and -Python values should be obvious given their types: +Python values should be obvious given their types. The 'Standard size' column +refers to the size of the packed value in bytes when using standard size; that +is, when the format string starts with one of ``'<'``, ``'>'``, ``'!'`` or +``'='``. When using native size, the size of the packed value is +platform-dependent. +--------+-------------------------+--------------------+----------------+------------+ | Format | C Type | Python type | Standard size | Notes | Modified: python/branches/py3k-dtoa/Doc/library/sys.rst ============================================================================== --- python/branches/py3k-dtoa/Doc/library/sys.rst (original) +++ python/branches/py3k-dtoa/Doc/library/sys.rst Tue Jul 6 17:55:27 2010 @@ -223,44 +223,65 @@ .. data:: float_info A structseq holding information about the float type. It contains low level - information about the precision and internal representation. Please study - your system's :file:`float.h` for more information. - - +---------------------+--------------------------------------------------+ - | attribute | explanation | - +=====================+==================================================+ - | :const:`epsilon` | Difference between 1 and the next representable | - | | floating point number | - +---------------------+--------------------------------------------------+ - | :const:`dig` | digits (see :file:`float.h`) | - +---------------------+--------------------------------------------------+ - | :const:`mant_dig` | mantissa digits (see :file:`float.h`) | - +---------------------+--------------------------------------------------+ - | :const:`max` | maximum representable finite float | - +---------------------+--------------------------------------------------+ - | :const:`max_exp` | maximum int e such that radix**(e-1) is in the | - | | range of finite representable floats | - +---------------------+--------------------------------------------------+ - | :const:`max_10_exp` | maximum int e such that 10**e is in the | - | | range of finite representable floats | - +---------------------+--------------------------------------------------+ - | :const:`min` | Minimum positive normalizer float | - +---------------------+--------------------------------------------------+ - | :const:`min_exp` | minimum int e such that radix**(e-1) is a | - | | normalized float | - +---------------------+--------------------------------------------------+ - | :const:`min_10_exp` | minimum int e such that 10**e is a normalized | - | | float | - +---------------------+--------------------------------------------------+ - | :const:`radix` | radix of exponent | - +---------------------+--------------------------------------------------+ - | :const:`rounds` | addition rounds (see :file:`float.h`) | - +---------------------+--------------------------------------------------+ - - .. note:: - - The information in the table is simplified. + information about the precision and internal representation. The values + correspond to the various floating-point constants defined in the standard + header file :file:`float.h` for the 'C' programming language; see section + 5.2.4.2.2 of the 1999 ISO/IEC C standard [C99]_, 'Characteristics of + floating types', for details. + + +---------------------+----------------+--------------------------------------------------+ + | attribute | float.h macro | explanation | + +=====================+================+==================================================+ + | :const:`epsilon` | DBL_EPSILON | difference between 1 and the least value greater | + | | | than 1 that is representable as a float | + +---------------------+----------------+--------------------------------------------------+ + | :const:`dig` | DBL_DIG | maximum number of decimal digits that can be | + | | | faithfully represented in a float; see below | + +---------------------+----------------+--------------------------------------------------+ + | :const:`mant_dig` | DBL_MANT_DIG | float precision: the number of base-``radix`` | + | | | digits in the significand of a float | + +---------------------+----------------+--------------------------------------------------+ + | :const:`max` | DBL_MAX | maximum representable finite float | + +---------------------+----------------+--------------------------------------------------+ + | :const:`max_exp` | DBL_MAX_EXP | maximum integer e such that ``radix**(e-1)`` is | + | | | a representable finite float | + +---------------------+----------------+--------------------------------------------------+ + | :const:`max_10_exp` | DBL_MAX_10_EXP | maximum integer e such that ``10**e`` is in the | + | | | range of representable finite floats | + +---------------------+----------------+--------------------------------------------------+ + | :const:`min` | DBL_MIN | minimum positive normalized float | + +---------------------+----------------+--------------------------------------------------+ + | :const:`min_exp` | DBL_MIN_EXP | minimum integer e such that ``radix**(e-1)`` is | + | | | a normalized float | + +---------------------+----------------+--------------------------------------------------+ + | :const:`min_10_exp` | DBL_MIN_10_EXP | minimum integer e such that ``10**e`` is a | + | | | normalized float | + +---------------------+----------------+--------------------------------------------------+ + | :const:`radix` | FLT_RADIX | radix of exponent representation | + +---------------------+----------------+--------------------------------------------------+ + | :const:`rounds` | FLT_ROUNDS | constant representing rounding mode | + | | | used for arithmetic operations | + +---------------------+----------------+--------------------------------------------------+ + + The attribute :attr:`sys.float_info.dig` needs further explanation. If + ``s`` is any string representing a decimal number with at most + :attr:`sys.float_info.dig` significant digits, then converting ``s`` to a + float and back again will recover a string representing the same decimal + value:: + >>> import sys + >>> sys.float_info.dig + 15 + >>> s = '3.14159265358979' # decimal string with 15 significant digits + >>> format(float(s), '.15g') # convert to float and back -> same value + '3.14159265358979' + + But for strings with more than :attr:`sys.float_info.dig` significant digits, + this isn't always true:: + + >>> s = '9876543211234567' # 16 significant digits is too many! + >>> format(float(s), '.16g') # conversion changes value + '9876543211234568' .. data:: float_repr_style @@ -957,3 +978,8 @@ first three characters of :const:`version`. It is provided in the :mod:`sys` module for informational purposes; modifying this value has no effect on the registry keys used by Python. Availability: Windows. + +.. rubric:: Citations + +.. [C99] ISO/IEC 9899:1999. "Programming languages -- C." A public draft of this standard is available at http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf . + Modified: python/branches/py3k-dtoa/Doc/library/sysconfig.rst ============================================================================== --- python/branches/py3k-dtoa/Doc/library/sysconfig.rst (original) +++ python/branches/py3k-dtoa/Doc/library/sysconfig.rst Tue Jul 6 17:55:27 2010 @@ -16,9 +16,9 @@ Configuration variables ----------------------- -A Python distribution contains a :file:`Makefile` file and a :file:`python.h` -that are necessary to build the Python binary itself, but also any C extension -created in a third party project and compiled using :mod:`distutils`. +A Python distribution contains a :file:`Makefile` and a :file:`pyconfig.h` +header file that are necessary to build both the Python binary itself and +third-party C extensions compiled using :mod:`distutils`. :mod:`sysconfig` puts all variables found in these files in a dictionary that can be accessed using :func:`get_config_vars` or :func:`get_config_var`. Modified: python/branches/py3k-dtoa/Doc/library/unittest.rst ============================================================================== --- python/branches/py3k-dtoa/Doc/library/unittest.rst (original) +++ python/branches/py3k-dtoa/Doc/library/unittest.rst Tue Jul 6 17:55:27 2010 @@ -220,26 +220,26 @@ unittest supports three command options. -* -f / --failfast +* :option:`-b` / :option:`--buffer` - Stop the test run on the first error or failure. + The standard output and standard error streams are buffered during the test + run. Output during a passing test is discarded. Output is echoed normally + on test fail or error and is added to the failure messages. -* -c / --catch +* :option:`-c` / :option:`--catch` - Control-c during the test run waits for the current test to end and then - reports all the results so far. A second control-c raises the normal - ``KeyboardInterrupt`` exception. + Control-C during the test run waits for the current test to end and then + reports all the results so far. A second control-C raises the normal + :exc:`KeyboardInterrupt` exception. See `Signal Handling`_ for the functions that provide this functionality. -* -b / --buffer +* :option:`-f` / :option:`--failfast` - The standard out and standard error streams are buffered during the test - run. Output during a passing test is discarded. Output is echoed normally - on test fail or error and is added to the failure messages. + Stop the test run on the first error or failure. .. versionadded:: 3.2 - The command line options ``-c``, ``-b`` and ``-f`` where added. + The command line options ``-c``, ``-b`` and ``-f`` were added. The command line can also be used for test discovery, for running all of the tests in a project or just a subset. @@ -270,8 +270,9 @@ -t directory Top level directory of project (default to start directory) -The -s, -p, & -t options can be passsed in as positional arguments. The -following two command lines are equivalent:: +The :option:`-s`, :option:`-p`, and :option:`-t` options can be passed in +as positional arguments in that order. The following two command lines +are equivalent:: python -m unittest discover -s project_directory -p '*_test.py' python -m unittest discover project_directory '*_test.py' @@ -829,6 +830,11 @@ compare equal, the test will fail with the explanation given by *msg*, or :const:`None`. + If *delta* is supplied instead of *places* then the difference + between *first* and *second* must be less than *delta*. + + Supplying both *delta* and *places* raises a ``TypeError``. + .. versionchanged:: 3.2 Objects that compare equal are automatically almost equal. Added the ``delta`` keyword argument. @@ -849,7 +855,7 @@ compare equal, the test will fail with the explanation given by *msg*, or :const:`None`. - If *delta* is supplied instead of *places* then the the difference + If *delta* is supplied instead of *places* then the difference between *first* and *second* must be more than *delta*. Supplying both *delta* and *places* raises a ``TypeError``. @@ -1902,12 +1908,12 @@ Signal Handling --------------- -The -c / --catch command line option to unittest, along with the ``catchbreak`` +The :option:`-c`/:option:`--catch` command line option to unittest, along with the ``catchbreak`` parameter to :func:`unittest.main()`, provide more friendly handling of -control-c during a test run. With catch break behavior enabled control-c will +control-C during a test run. With catch break behavior enabled control-C will allow the currently running test to complete, and the test run will then end and report all the results so far. A second control-c will raise a -``KeyboardInterrupt`` in the usual way. +:exc:`KeyboardInterrupt` in the usual way. The control-c handling signal handler attempts to remain compatible with code or tests that install their own :const:`signal.SIGINT` handler. If the ``unittest`` Modified: python/branches/py3k-dtoa/Doc/library/urllib.parse.rst ============================================================================== --- python/branches/py3k-dtoa/Doc/library/urllib.parse.rst (original) +++ python/branches/py3k-dtoa/Doc/library/urllib.parse.rst Tue Jul 6 17:55:27 2010 @@ -310,23 +310,29 @@ ``b'a&\xef'``. -.. function:: urlencode(query, doseq=False) +.. function:: urlencode(query, doseq=False, safe='', encoding=None, errors=None) - Convert a mapping object or a sequence of two-element tuples to a - "url-encoded" string, suitable to pass to :func:`urlopen` above as the - optional *data* argument. This is useful to pass a dictionary of form - fields to a ``POST`` request. The resulting string is a series of - ``key=value`` pairs separated by ``'&'`` characters, where both *key* and - *value* are quoted using :func:`quote_plus` above. When a sequence of - two-element tuples is used as the *query* argument, the first element of - each tuple is a key and the second is a value. The value element in itself - can be a sequence and in that case, if the optional parameter *doseq* is - evaluates to *True*, individual ``key=value`` pairs separated by ``'&'`` are - generated for each element of the value sequence for the key. The order of - parameters in the encoded string will match the order of parameter tuples in - the sequence. This module provides the functions :func:`parse_qs` and - :func:`parse_qsl` which are used to parse query strings into Python data - structures. + Convert a mapping object or a sequence of two-element tuples, which may + either be a :class:`str` or a :class:`bytes`, to a "url-encoded" string, + suitable to pass to :func:`urlopen` above as the optional *data* argument. + This is useful to pass a dictionary of form fields to a ``POST`` request. + The resulting string is a series of ``key=value`` pairs separated by ``'&'`` + characters, where both *key* and *value* are quoted using :func:`quote_plus` + above. When a sequence of two-element tuples is used as the *query* + argument, the first element of each tuple is a key and the second is a + value. The value element in itself can be a sequence and in that case, if + the optional parameter *doseq* is evaluates to *True*, individual + ``key=value`` pairs separated by ``'&'`` are generated for each element of + the value sequence for the key. The order of parameters in the encoded + string will match the order of parameter tuples in the sequence. This module + provides the functions :func:`parse_qs` and :func:`parse_qsl` which are used + to parse query strings into Python data structures. + + When *query* parameter is a :class:`str`, the *safe*, *encoding* and *error* + parameters are sent the :func:`quote_plus` for encoding. + + .. versionchanged:: 3.2 + query paramater supports bytes and string. .. seealso:: Modified: python/branches/py3k-dtoa/Doc/library/urllib.request.rst ============================================================================== --- python/branches/py3k-dtoa/Doc/library/urllib.request.rst (original) +++ python/branches/py3k-dtoa/Doc/library/urllib.request.rst Tue Jul 6 17:55:27 2010 @@ -40,8 +40,8 @@ commonly used to determine if a redirect was followed * :meth:`info` --- return the meta-information of the page, such as headers, - in the form of an :class:`http.client.HTTPMessage` instance (see `Quick - Reference to HTTP Headers `_) + in the form of an :func:`email.message_from_string` instance (see + `Quick Reference to HTTP Headers `_) Raises :exc:`URLError` on errors. Modified: python/branches/py3k-dtoa/Doc/library/warnings.rst ============================================================================== --- python/branches/py3k-dtoa/Doc/library/warnings.rst (original) +++ python/branches/py3k-dtoa/Doc/library/warnings.rst Tue Jul 6 17:55:27 2010 @@ -57,7 +57,7 @@ | :exc:`UserWarning` | The default category for :func:`warn`. | +----------------------------------+-----------------------------------------------+ | :exc:`DeprecationWarning` | Base category for warnings about deprecated | -| | features. | +| | features (ignored by default). | +----------------------------------+-----------------------------------------------+ | :exc:`SyntaxWarning` | Base category for warnings about dubious | | | syntactic features. | @@ -91,6 +91,9 @@ standard warning categories. A warning category must always be a subclass of the :exc:`Warning` class. +.. versionchanged:: 3.2 + :exc:`DeprecationWarning` is ignored by default. + .. _warning-filter: @@ -150,14 +153,6 @@ :mod:`warnings` module parses these when it is first imported (invalid options are ignored, after printing a message to ``sys.stderr``). -The warnings that are ignored by default may be enabled by passing :option:`-Wd` -to the interpreter. This enables default handling for all warnings, including -those that are normally ignored by default. This is particular useful for -enabling ImportWarning when debugging problems importing a developed package. -ImportWarning can also be enabled explicitly in Python code using:: - - warnings.simplefilter('default', ImportWarning) - .. _warning-suppress: @@ -233,6 +228,37 @@ entries from the warnings list before each new operation). +Updating Code For New Versions of Python +---------------------------------------- + +Warnings that are only of interest to the developer are ignored by default. As +such you should make sure to test your code with typically ignored warnings +made visible. You can do this from the command-line by passing :option:`-Wd` +to the interpreter (this is shorthand for :option:`-W default`). This enables +default handling for all warnings, including those that are ignored by default. +To change what action is taken for encountered warnings you simply change what +argument is passed to :option:`-W`, e.g. :option:`-W error`. See the +:option:`-W` flag for more details on what is possible. + +To programmatically do the same as :option:`-Wd`, use:: + + warnings.simplefilter('default') + +Make sure to execute this code as soon as possible. This prevents the +registering of what warnings have been raised from unexpectedly influencing how +future warnings are treated. + +Having certain warnings ignored by default is done to prevent a user from +seeing warnings that are only of interest to the developer. As you do not +necessarily have control over what interpreter a user uses to run their code, +it is possible that a new version of Python will be released between your +release cycles. The new interpreter release could trigger new warnings in your +code that were not there in an older interpreter, e.g. +:exc:`DeprecationWarning` for a module that you are using. While you as a +developer want to be notified that your code is using a deprecated module, to a +user this information is essentially noise and provides no benefit to them. + + .. _warning-functions: Available Functions Modified: python/branches/py3k-dtoa/Doc/reference/compound_stmts.rst ============================================================================== --- python/branches/py3k-dtoa/Doc/reference/compound_stmts.rst (original) +++ python/branches/py3k-dtoa/Doc/reference/compound_stmts.rst Tue Jul 6 17:55:27 2010 @@ -272,14 +272,12 @@ try: foo finally: - N = None del N -That means that you have to assign the exception to a different name if you want -to be able to refer to it after the except clause. The reason for this is that -with the traceback attached to them, exceptions will form a reference cycle with -the stack frame, keeping all locals in that frame alive until the next garbage -collection occurs. +This means the exception must be assigned to a different name to be able to +refer to it after the except clause. Exceptions are cleared because with the +traceback attached to them, they form a reference cycle with the stack frame, +keeping all locals in that frame alive until the next garbage collection occurs. .. index:: module: sys Modified: python/branches/py3k-dtoa/Doc/reference/datamodel.rst ============================================================================== --- python/branches/py3k-dtoa/Doc/reference/datamodel.rst (original) +++ python/branches/py3k-dtoa/Doc/reference/datamodel.rst Tue Jul 6 17:55:27 2010 @@ -1595,7 +1595,7 @@ In particular, the metaclass :class:`abc.ABCMeta` implements these methods in order to allow the addition of Abstract Base Classes (ABCs) as "virtual base -classes" to any class or type (including built-in types), and including to other +classes" to any class or type (including built-in types), including other ABCs. .. method:: class.__instancecheck__(self, instance) @@ -1614,7 +1614,7 @@ Note that these methods are looked up on the type (metaclass) of a class. They cannot be defined as class methods in the actual class. This is consistent with -the lookup of special methods that are called on instances, only that in this +the lookup of special methods that are called on instances, only in this case the instance is itself a class. .. seealso:: Modified: python/branches/py3k-dtoa/Doc/reference/introduction.rst ============================================================================== --- python/branches/py3k-dtoa/Doc/reference/introduction.rst (original) +++ python/branches/py3k-dtoa/Doc/reference/introduction.rst Tue Jul 6 17:55:27 2010 @@ -69,12 +69,12 @@ more information, see `the IronPython website `_. PyPy - An implementation of Python written in Python; even the bytecode interpreter is - written in Python. This is executed using CPython as the underlying - interpreter. One of the goals of the project is to encourage experimentation - with the language itself by making it easier to modify the interpreter (since it - is written in Python). Additional information is available on `the PyPy - project's home page `_. + An implementation of Python written completely in Python. It supports several + advanced features not found in other implementations like stackless support + and a Just in Time compiler. One of the goals of the project is to encourage + experimentation with the language itself by making it easier to modify the + interpreter (since it is written in Python). Additional information is + available on `the PyPy project's home page `_. Each of these implementations varies in some way from the language as documented in this manual, or introduces specific information beyond what's covered in the Modified: python/branches/py3k-dtoa/Doc/reference/lexical_analysis.rst ============================================================================== --- python/branches/py3k-dtoa/Doc/reference/lexical_analysis.rst (original) +++ python/branches/py3k-dtoa/Doc/reference/lexical_analysis.rst Tue Jul 6 17:55:27 2010 @@ -407,7 +407,7 @@ .. productionlist:: bytesliteral: `bytesprefix`(`shortbytes` | `longbytes`) - bytesprefix: "b" | "B" + bytesprefix: "b" | "B" | "br" | "Br" | "bR" | "BR" shortbytes: "'" `shortbytesitem`* "'" | '"' `shortbytesitem`* '"' longbytes: "'''" `longbytesitem`* "'''" | '"""' `longbytesitem`* '"""' shortbytesitem: `shortbyteschar` | `bytesescapeseq` @@ -431,16 +431,16 @@ characters that otherwise have a special meaning, such as newline, backslash itself, or the quote character. -String literals may optionally be prefixed with a letter ``'r'`` or ``'R'``; -such strings are called :dfn:`raw strings` and treat backslashes as literal -characters. As a result, ``'\U'`` and ``'\u'`` escapes in raw strings are not -treated specially. - Bytes literals are always prefixed with ``'b'`` or ``'B'``; they produce an instance of the :class:`bytes` type instead of the :class:`str` type. They may only contain ASCII characters; bytes with a numeric value of 128 or greater must be expressed with escapes. +Both string and bytes literals may optionally be prefixed with a letter ``'r'`` +or ``'R'``; such strings are called :dfn:`raw strings` and treat backslashes as +literal characters. As a result, in string literals, ``'\U'`` and ``'\u'`` +escapes in raw strings are not treated specially. + In triple-quoted strings, unescaped newlines and quotes are allowed (and are retained), except that three unescaped quotes in a row terminate the string. (A "quote" is the character used to open the string, i.e. either ``'`` or ``"``.) @@ -545,9 +545,9 @@ String literal concatenation ---------------------------- -Multiple adjacent string literals (delimited by whitespace), possibly using -different quoting conventions, are allowed, and their meaning is the same as -their concatenation. Thus, ``"hello" 'world'`` is equivalent to +Multiple adjacent string or bytes literals (delimited by whitespace), possibly +using different quoting conventions, are allowed, and their meaning is the same +as their concatenation. Thus, ``"hello" 'world'`` is equivalent to ``"helloworld"``. This feature can be used to reduce the number of backslashes needed, to split long strings conveniently across long lines, or even to add comments to parts of strings, for example:: Modified: python/branches/py3k-dtoa/Doc/tools/sphinxext/pyspecific.py ============================================================================== --- python/branches/py3k-dtoa/Doc/tools/sphinxext/pyspecific.py (original) +++ python/branches/py3k-dtoa/Doc/tools/sphinxext/pyspecific.py Tue Jul 6 17:55:27 2010 @@ -5,7 +5,7 @@ Sphinx extension with Python doc-specific markup. - :copyright: 2008, 2009 by Georg Brandl. + :copyright: 2008, 2009, 2010 by Georg Brandl. :license: Python license. """ @@ -149,7 +149,7 @@ import re from sphinx import addnodes -opcode_sig_re = re.compile(r'(\w+(?:\+\d)?)\s*\((.*)\)') +opcode_sig_re = re.compile(r'(\w+(?:\+\d)?)(?:\s*\((.*)\))?') def parse_opcode_signature(env, sig, signode): """Transform an opcode signature into RST nodes.""" @@ -158,9 +158,10 @@ raise ValueError opname, arglist = m.groups() signode += addnodes.desc_name(opname, opname) - paramlist = addnodes.desc_parameterlist() - signode += paramlist - paramlist += addnodes.desc_parameter(arglist, arglist) + if arglist is not None: + paramlist = addnodes.desc_parameterlist() + signode += paramlist + paramlist += addnodes.desc_parameter(arglist, arglist) return opname.strip() Modified: python/branches/py3k-dtoa/Doc/tutorial/classes.rst ============================================================================== --- python/branches/py3k-dtoa/Doc/tutorial/classes.rst (original) +++ python/branches/py3k-dtoa/Doc/tutorial/classes.rst Tue Jul 6 17:55:27 2010 @@ -580,7 +580,7 @@ ================= "Private" instance variables that cannot be accessed except from inside an -object, don't exist in Python. However, there is a convention that is followed +object don't exist in Python. However, there is a convention that is followed by most Python code: a name prefixed with an underscore (e.g. ``_spam``) should be treated as a non-public part of the API (whether it is a function, a method or a data member). It should be considered an implementation detail and subject Modified: python/branches/py3k-dtoa/Doc/tutorial/controlflow.rst ============================================================================== --- python/branches/py3k-dtoa/Doc/tutorial/controlflow.rst (original) +++ python/branches/py3k-dtoa/Doc/tutorial/controlflow.rst Tue Jul 6 17:55:27 2010 @@ -87,7 +87,6 @@ If you do need to iterate over a sequence of numbers, the built-in function :func:`range` comes in handy. It generates arithmetic progressions:: - >>> for i in range(5): ... print(i) ... @@ -97,9 +96,7 @@ 3 4 - - -The given end point is never part of the generated list; ``range(10)`` generates +The given end point is never part of the generated sequence; ``range(10)`` generates 10 values, the legal indices for items of a sequence of length 10. It is possible to let the range start at another number, or to specify a different increment (even negative; sometimes this is called the 'step'):: Modified: python/branches/py3k-dtoa/Doc/tutorial/introduction.rst ============================================================================== --- python/branches/py3k-dtoa/Doc/tutorial/introduction.rst (original) +++ python/branches/py3k-dtoa/Doc/tutorial/introduction.rst Tue Jul 6 17:55:27 2010 @@ -208,7 +208,7 @@ print(hello) -Note that newlines still need to be embedded in the string using ``\n``; the +Note that newlines still need to be embedded in the string using ``\n`` -- the newline following the trailing backslash is discarded. This example would print the following: Modified: python/branches/py3k-dtoa/Doc/using/mac.rst ============================================================================== --- python/branches/py3k-dtoa/Doc/using/mac.rst (original) +++ python/branches/py3k-dtoa/Doc/using/mac.rst Tue Jul 6 17:55:27 2010 @@ -114,8 +114,8 @@ ======= MacPython ships with the standard IDLE development environment. A good -introduction to using IDLE can be found at http://hkn.eecs.berkeley.edu/ -dyoo/python/idle_intro/index.html. +introduction to using IDLE can be found at +http://hkn.eecs.berkeley.edu/~dyoo/python/idle_intro/index.html. .. _mac-package-manager: Modified: python/branches/py3k-dtoa/Doc/whatsnew/2.7.rst ============================================================================== --- python/branches/py3k-dtoa/Doc/whatsnew/2.7.rst (original) +++ python/branches/py3k-dtoa/Doc/whatsnew/2.7.rst Tue Jul 6 17:55:27 2010 @@ -6,12 +6,11 @@ :Release: |release| :Date: |today| -.. Fix accents on Kristjan Valur Jonsson, Fuerstenau - -.. Big jobs: ElementTree 1.3, pep 391, sysconfig -.. unittest test discovery .. hyperlink all the methods & functions. +.. T_STRING_INPLACE not described in main docs +.. "Format String Syntax" in string.rst could use many more examples. + .. $Id$ Rules for maintenance: @@ -54,20 +53,77 @@ when researching a change. This article explains the new features in Python 2.7. The final -release of 2.7 is currently scheduled for June 2010; the detailed +release of 2.7 is currently scheduled for July 2010; the detailed schedule is described in :pep:`373`. -Python 2.7 is planned to be the last major release in the 2.x series. -Though more major releases have not been absolutely ruled out, the -Python maintainers are planning to focus more on Python 3.x. Despite -that, it's likely that the 2.7 release will have a longer period of -maintenance compared to earlier 2.x versions. - -.. Compare with previous release in 2 - 3 sentences here. - add hyperlink when the documentation becomes available online. +Numeric handling has been improved in many ways, for both +floating-point numbers and for the :class:`Decimal` class. There are +some useful additions to the standard library, such as a greatly +enhanced :mod:`unittest` module, the :mod:`argparse` module for +parsing command-line options, convenient ordered-dictionary and +:class:`Counter` classes in the :mod:`collections` module, and many +other improvements. + +Python 2.7 is planned to be the last of the 2.x releases, so we worked +on making it a good release for the long term. To help with porting +to Python 3, several new features from the Python 3.x series have been +included in 2.7. + +This article doesn't attempt to provide a complete specification of +the new features, but instead provides a convenient overview. For +full details, you should refer to the documentation for Python 2.7 at +http://docs.python.org. If you want to understand the rationale for +the design and implementation, refer to the PEP for a particular new +feature or the issue on http://bugs.python.org in which a change was +discussed. Whenever possible, "What's New in Python" links to the +bug/patch item for each change. .. _whatsnew27-python31: +The Future for Python 2.x +========================= + +Python 2.7 is intended to be the last major release in the 2.x series. +The Python maintainers are planning to focus their future efforts on +the Python 3.x series. + +This means that 2.7 will remain in place for a long time, running +production systems that have not been ported to Python 3.x. +Two consequences of the long-term significance of 2.7 are: + +* It's very likely the 2.7 release will have a longer period of + maintenance compared to earlier 2.x versions. Python 2.7 will + continue to be maintained while the transition to 3.x continues, and + the developers are planning to support Python 2.7 with bug-fix + releases beyond the typical two years. + +* A policy decision was made to silence warnings only of interest to + developers. :exc:`DeprecationWarning` and its + descendants are now ignored unless otherwise requested, preventing + users from seeing warnings triggered by an application. This change + was also made in the branch that will become Python 3.2. (Discussed + on stdlib-sig and carried out in :issue:`7319`.) + + In previous releases, :exc:`DeprecationWarning` messages were + enabled by default, providing Python developers with a clear + indication of where their code may break in a future major version + of Python. + + However, there are increasingly many users of Python-based + applications who are not directly involved in the development of + those applications. :exc:`DeprecationWarning` messages are + irrelevant to such users, making them worry about an application + that's actually working correctly and burdening application developers + with responding to these concerns. + + You can re-enable display of :exc:`DeprecationWarning` messages by + running Python with the :option:`-Wdefault` (short form: + :option:`-Wd`) switch, or by setting the :envvar:`PYTHONWARNINGS` + environment variable to ``"default"`` (or ``"d"``) before running + Python. Python code can also re-enable them + by calling ``warnings.simplefilter('default')``. + + Python 3.1 Features ======================= @@ -78,25 +134,31 @@ A partial list of 3.1 features that were backported to 2.7: -* A version of the :mod:`io` library, rewritten in C for performance. +* The syntax for set literals (``{1,2,3}`` is a mutable set). +* Dictionary and set comprehensions (``{ i: i*2 for i in range(3)}``). +* Multiple context managers in a single :keyword:`with` statement. +* A new version of the :mod:`io` library, rewritten in C for performance. * The ordered-dictionary type described in :ref:`pep-0372`. -* The new format specifier described in :ref:`pep-0378`. +* The new ``","`` format specifier described in :ref:`pep-0378`. * The :class:`memoryview` object. -* A small subset of the :mod:`importlib` module `described below <#importlib-section>`__. +* A small subset of the :mod:`importlib` module, + `described below <#importlib-section>`__. * Float-to-string and string-to-float conversions now round their - results more correctly. And :func:`repr` of a floating-point + results more correctly, and :func:`repr` of a floating-point number *x* returns a result that's guaranteed to round back to the same number when converted back to a string. +* The :ctype:`PyCapsule` type, used to provide a C API for extension modules. * The :cfunc:`PyLong_AsLongAndOverflow` C API function. -One porting change: the :option:`-3` switch now automatically -enables the :option:`-Qwarn` switch that causes warnings -about using classic division with integers and long integers. - Other new Python3-mode warnings include: * :func:`operator.isCallable` and :func:`operator.sequenceIncludes`, - which are not supported in 3.x. + which are not supported in 3.x, now trigger warnings. +* The :option:`-3` switch now automatically + enables the :option:`-Qwarn` switch that causes warnings + about using classic division with integers and long integers. + + .. ======================================================================== .. Large, PEP-level features and changes should be described here. @@ -104,22 +166,22 @@ .. _pep-0372: -PEP 372: Adding an ordered dictionary to collections +PEP 372: Adding an Ordered Dictionary to collections ==================================================== Regular Python dictionaries iterate over key/value pairs in arbitrary order. Over the years, a number of authors have written alternative implementations that remember the order that the keys were originally inserted. Based on -the experiences from those implementations, a new -:class:`~collections.OrderedDict` class has been introduced in the -:mod:`collections` module. +the experiences from those implementations, 2.7 introduces a new +:class:`~collections.OrderedDict` class in the :mod:`collections` module. -The :class:`~collections.OrderedDict` API is substantially the same as regular -dictionaries but will iterate over keys and values in a guaranteed order +The :class:`~collections.OrderedDict` API provides the same interface as regular +dictionaries but iterates over keys and values in a guaranteed order depending on when a key was first inserted:: >>> from collections import OrderedDict - >>> d = OrderedDict([('first', 1), ('second', 2), + >>> d = OrderedDict([('first', 1), + ... ('second', 2), ... ('third', 3)]) >>> d.items() [('first', 1), ('second', 2), ('third', 3)] @@ -156,9 +218,11 @@ Comparing two ordered dictionaries checks both the keys and values, and requires that the insertion order was the same:: - >>> od1 = OrderedDict([('first', 1), ('second', 2), + >>> od1 = OrderedDict([('first', 1), + ... ('second', 2), ... ('third', 3)]) - >>> od2 = OrderedDict([('third', 3), ('first', 1), + >>> od2 = OrderedDict([('third', 3), + ... ('first', 1), ... ('second', 2)]) >>> od1 == od2 False @@ -176,17 +240,12 @@ deletion doesn't have to traverse the entire linked list and therefore remains O(1). -.. XXX check O(1)-ness with Raymond -.. Also check if the 'somenamedtuple' in the collection module should -.. be replaced/removed in order to use -.. :meth:`~collections.namedtuple._asdict()` (see below) - The standard library now supports use of ordered dictionaries in several modules. -* The :mod:`ConfigParser` module uses them by default, letting - configuration files be read, modified, and then written back in their original - order. +* The :mod:`ConfigParser` module uses them by default, meaning that + configuration files can now read, modified, and then written back + in their original order. * The :meth:`~collections.somenamedtuple._asdict()` method for :func:`collections.namedtuple` now returns an ordered dictionary with the @@ -210,7 +269,7 @@ ================================================= To make program output more readable, it can be useful to add -separators to large numbers and render them as +separators to large numbers, rendering them as 18,446,744,073,709,551,616 instead of 18446744073709551616. The fully general solution for doing this is the :mod:`locale` module, @@ -237,8 +296,6 @@ comma-formatting mechanism isn't as general as the :mod:`locale` module, but it's easier to use. -.. XXX "Format String Syntax" in string.rst could use many more examples. - .. seealso:: :pep:`378` - Format Specifier for Thousands Separator @@ -248,13 +305,13 @@ ====================================================== The :mod:`argparse` module for parsing command-line arguments was -added, intended as a more powerful replacement for the +added as a more powerful replacement for the :mod:`optparse` module. This means Python now supports three different modules for parsing command-line arguments: :mod:`getopt`, :mod:`optparse`, and :mod:`argparse`. The :mod:`getopt` module closely resembles the C -:cfunc:`getopt` function, so it remains useful if you're writing a +library's :cfunc:`getopt` function, so it remains useful if you're writing a Python prototype that will eventually be rewritten in C. :mod:`optparse` becomes redundant, but there are no plans to remove it because there are many scripts still using it, and there's no @@ -306,23 +363,28 @@ -o FILE direct output to FILE instead of stdout -C NUM display NUM lines of added context -Similarly to :mod:`optparse`, the command-line switches and arguments +As with :mod:`optparse`, the command-line switches and arguments are returned as an object with attributes named by the *dest* parameters:: -> ./python.exe argparse-example.py -v - {'output': None, 'is_verbose': True, 'context': 0, 'inputs': []} + {'output': None, + 'is_verbose': True, + 'context': 0, + 'inputs': []} -> ./python.exe argparse-example.py -v -o /tmp/output -C 4 file1 file2 - {'output': '/tmp/output', 'is_verbose': True, 'context': 4, + {'output': '/tmp/output', + 'is_verbose': True, + 'context': 4, 'inputs': ['file1', 'file2']} :mod:`argparse` has much fancier validation than :mod:`optparse`; you can specify an exact number of arguments as an integer, 0 or more arguments by passing ``'*'``, 1 or more by passing ``'+'``, or an optional argument with ``'?'``. A top-level parser can contain -sub-parsers, so you can define subcommands that have different sets of +sub-parsers to define subcommands that have different sets of switches, as in ``svn commit``, ``svn checkout``, etc. You can -specify an argument type as :class:`~argparse.FileType`, which will +specify an argument's type as :class:`~argparse.FileType`, which will automatically open files for you and understands that ``'-'`` means standard input or output. @@ -331,6 +393,8 @@ `argparse module documentation `__ `Upgrading optparse code to use argparse `__ + Part of the Python documentation, describing how to convert + code that uses :mod:`optparse`. :pep:`389` - argparse - New Command Line Parsing Module PEP written and implemented by Steven Bethard. @@ -338,34 +402,88 @@ PEP 391: Dictionary-Based Configuration For Logging ==================================================== -.. not documented in library reference yet. +.. XXX not documented in library reference yet; add link here once it's added. -The :mod:`logging` module is very flexible; an application can define +The :mod:`logging` module is very flexible; applications can define a tree of logging subsystems, and each logger in this tree can filter out certain messages, format them differently, and direct messages to a varying number of handlers. All this flexibility can require a lot of configuration. You can write Python statements to create objects and set their properties, -but a complex set-up would require verbose but boring code. +but a complex set-up requires verbose but boring code. :mod:`logging` also supports a :func:`~logging.config.fileConfig` function that parses a file, but the file format doesn't support configuring filters, and it's messier to generate programmatically. Python 2.7 adds a :func:`~logging.config.dictConfig` function that -uses a dictionary, and there are many ways to produce a dictionary -from different sources. You can construct one with code, of course. -Python's standard library now includes a JSON parser, so you could -parse a file containing JSON, or you could use a YAML parsing library -if one is installed. +uses a dictionary to configure logging. There are many ways to +produce a dictionary from different sources: construct one with code; +parse a file containing JSON; or use a YAML parsing library if one is +installed. + +The following example configures two loggers, the root logger and a +logger named "network". Messages sent to the root logger will be +sent to the system log using the syslog protocol, and messages +to the "network" logger will be written to a :file:`network.log` file +that will be rotated once the log reaches 1Mb. + +:: + + import logging + import logging.config -XXX describe an example. + configdict = { + 'version': 1, # Configuration schema in use; must be 1 for now + 'formatters': { + 'standard': { + 'format': ('%(asctime)s %(name)-15s ' + '%(levelname)-8s %(message)s')}}, + + 'handlers': {'netlog': {'backupCount': 10, + 'class': 'logging.handlers.RotatingFileHandler', + 'filename': '/logs/network.log', + 'formatter': 'standard', + 'level': 'INFO', + 'maxBytes': 1024*1024}, + 'syslog': {'class': 'logging.handlers.SysLogHandler', + 'formatter': 'standard', + 'level': 'ERROR'}}, + + # Specify all the subordinate loggers + 'loggers': { + 'network': { + 'handlers': ['netlog'] + } + }, + # Specify properties of the root logger + 'root': { + 'handlers': ['syslog'] + }, + } + + # Set up configuration + logging.config.dictConfig(configdict) + + # As an example, log two error messages + logger = logging.getLogger('/') + logger.error('Database not found') -Two smaller enhancements to the logging module are: + netlogger = logging.getLogger('network') + netlogger.error('Connection failed') + +Three smaller enhancements to the :mod:`logging` module, all +implemented by Vinay Sajip, are: .. rev79293 -* :class:`Logger` instances gained a :meth:`getChild` that retrieves a +* The :class:`~logging.handlers.SysLogHandler` class now supports + syslogging over TCP. The constructor has a *socktype* parameter + giving the type of socket to use, either :const:`socket.SOCK_DGRAM` + for UDP or :const:`socket.SOCK_STREAM` for TCP. The default + protocol remains UDP. + +* :class:`Logger` instances gained a :meth:`getChild` method that retrieves a descendant logger using a relative path. For example, once you retrieve a logger by doing ``log = getLogger('app')``, calling ``log.getChild('network.listen')`` is equivalent to @@ -387,12 +505,10 @@ are different in Python 3.x. They return an object called a :dfn:`view` instead of a fully materialized list. -.. Views can be iterated over, but they also behave like sets. XXX not working. - It's not possible to change the return values of :meth:`keys`, :meth:`values`, and :meth:`items` in Python 2.7 because too much code would break. Instead the 3.x versions were added under the new names -of :meth:`viewkeys`, :meth:`viewvalues`, and :meth:`viewitems`. +:meth:`viewkeys`, :meth:`viewvalues`, and :meth:`viewitems`. :: @@ -402,6 +518,17 @@ >>> d.viewkeys() dict_keys([0, 130, 10, 140, 20, 150, 30, ..., 250]) +Views can be iterated over, but the key and item views also behave +like sets. The ``&`` operator performs intersection, and ``|`` +performs a union:: + + >>> d1 = dict((i*10, chr(65+i)) for i in range(26)) + >>> d2 = dict((i**.5, i) for i in range(1000)) + >>> d1.viewkeys() & d2.viewkeys() + set([0.0, 10.0, 20.0, 30.0]) + >>> d1.viewkeys() | range(0, 30) + set([0, 1, 130, 3, 4, 5, 6, ..., 120, 250]) + The view keeps track of the dictionary and its contents change as the dictionary is modified:: @@ -433,6 +560,58 @@ Backported to 2.7 by Alexandre Vassalotti; :issue:`1967`. +PEP 3137: The memoryview Object +==================================================== + +The :class:`memoryview` object provides a view of another object's +memory content that matches the :class:`bytes` type's interface. + + >>> import string + >>> m = memoryview(string.letters) + >>> m + + >>> len(m) # Returns length of underlying object + 52 + >>> m[0], m[25], m[26] # Indexing returns one byte + ('a', 'z', 'A') + >>> m2 = m[0:26] # Slicing returns another memoryview + >>> m2 + + +The content of the view can be converted to a string of bytes or +a list of integers: + + >>> m2.tobytes() + 'abcdefghijklmnopqrstuvwxyz' + >>> m2.tolist() + [97, 98, 99, 100, 101, 102, 103, ... 121, 122] + >>> + +:class:`memoryview` objects allow modifying the underlying object if +it's a mutable object. + + >>> m2[0] = 75 + Traceback (most recent call last): + File "", line 1, in + TypeError: cannot modify read-only memory + >>> b = bytearray(string.letters) # Creating a mutable object + >>> b + bytearray(b'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ') + >>> mb = memoryview(b) + >>> mb[0] = '*' # Assign to view, changing the bytearray. + >>> b[0:5] # The bytearray has been changed. + bytearray(b'*bcde') + >>> + +.. seealso:: + + :pep:`3137` - Immutable Bytes and Mutable Buffer + PEP written by Guido van Rossum. + Implemented by Travis Oliphant, Antoine Pitrou and others. + Backported to 2.7 by Antoine Pitrou; :issue:`2396`. + + + Other Language Changes ====================== @@ -458,9 +637,9 @@ 3.x, generalizing list/generator comprehensions to use the literal syntax for sets and dictionaries. - >>> {x:x*x for x in range(6)} + >>> {x: x*x for x in range(6)} {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25} - >>> {'a'*x for x in range(6)} + >>> {('a'*x) for x in range(6)} set(['', 'a', 'aa', 'aaa', 'aaaa', 'aaaaa']) Backported by Alexandre Vassalotti; :issue:`2333`. @@ -490,8 +669,8 @@ in many different places: :func:`str` on floats and complex numbers; the :class:`float` and :class:`complex` constructors; - numeric formatting; serialization and - deserialization of floats and complex numbers using the + numeric formatting; serializing and + deserializing floats and complex numbers using the :mod:`marshal`, :mod:`pickle` and :mod:`json` modules; parsing of float and imaginary literals in Python code; @@ -506,7 +685,7 @@ .. maybe add an example? The rounding library responsible for this improvement works on - Windows, and on Unix platforms using the gcc, icc, or suncc + Windows and on Unix platforms using the gcc, icc, or suncc compilers. There may be a small number of platforms where correct operation of this code cannot be guaranteed, so the code is not used on such systems. You can find out which code is being used @@ -516,6 +695,37 @@ Implemented by Eric Smith and Mark Dickinson, using David Gay's :file:`dtoa.c` library; :issue:`7117`. +* Conversions from long integers and regular integers to floating + point now round differently, returning the floating-point number + closest to the number. This doesn't matter for small integers that + can be converted exactly, but for large numbers that will + unavoidably lose precision, Python 2.7 now approximates more + closely. For example, Python 2.6 computed the following:: + + >>> n = 295147905179352891391 + >>> float(n) + 2.9514790517935283e+20 + >>> n - long(float(n)) + 65535L + + Python 2.7's floating-point result is larger, but much closer to the + true value:: + + >>> n = 295147905179352891391 + >>> float(n) + 2.9514790517935289e+20 + >>> n - long(float(n)) + -1L + + (Implemented by Mark Dickinson; :issue:`3166`.) + + Integer division is also more accurate in its rounding behaviours. (Also + implemented by Mark Dickinson; :issue:`1811`.) + +* Implicit coercion for complex numbers has been removed; the interpreter + will no longer ever attempt to call a :meth:`__coerce__` method on complex + objects. (Removed by Meador Inge and Mark Dickinson; :issue:`5211`.) + * The :meth:`str.format` method now supports automatic numbering of the replacement fields. This makes using :meth:`str.format` more closely resemble using ``%s`` formatting:: @@ -543,6 +753,16 @@ so it will now produce 'INF' and 'NAN'. (Contributed by Eric Smith; :issue:`3382`.) + A low-level change: the :meth:`object.__format__` method now triggers + a :exc:`PendingDeprecationWarning` if it's passed a format string, + because the :meth:`__format__` method for :class:`object` converts + the object to a string representation and formats that. Previously + the method silently applied the format string to the string + representation, but that could hide mistakes in Python code. If + you're supplying formatting information such as an alignment or + precision, presumably you're expecting the formatting to be applied + in some object-specific way. (Fixed by Eric Smith; :issue:`7994`.) + * The :func:`int` and :func:`long` types gained a ``bit_length`` method that returns the number of bits necessary to represent its argument in binary:: @@ -560,32 +780,11 @@ (Contributed by Fredrik Johansson and Victor Stinner; :issue:`3439`.) -* Conversions from long integers and regular integers to floating - point now round differently, returning the floating-point number - closest to the number. This doesn't matter for small integers that - can be converted exactly, but for large numbers that will - unavoidably lose precision, Python 2.7 now approximates more - closely. For example, Python 2.6 computed the following:: - - >>> n = 295147905179352891391 - >>> float(n) - 2.9514790517935283e+20 - >>> n - long(float(n)) - 65535L - - Python 2.7's floating-point result is larger, but much closer to the - true value:: - - >>> n = 295147905179352891391 - >>> float(n) - 2.9514790517935289e+20 - >>> n - long(float(n)) - -1L - - (Implemented by Mark Dickinson; :issue:`3166`.) - - Integer division is also more accurate in its rounding behaviours. (Also - implemented by Mark Dickinson; :issue:`1811`.) +* The :keyword:`import` statement will no longer try a relative import + if an absolute import (e.g. ``from .os import sep``) fails. This + fixes a bug, but could possibly break certain :keyword:`import` + statements that were only working by accident. (Fixed by Meador Inge; + :issue:`7902`.) * It's now possible for a subclass of the built-in :class:`unicode` type to override the :meth:`__unicode__` method. (Implemented by @@ -603,9 +802,15 @@ (Contributed by Amaury Forgeot d'Arc, after a suggestion by George Sakkis; :issue:`5982`.) -* A new encoding named "cp720", used primarily for Arabic text, is now - supported. (Contributed by Alexander Belchenko and Amaury Forgeot - d'Arc; :issue:`1616979`.) +* When a restricted set of attributes were set using ``__slots__``, + deleting an unset attribute would not raise :exc:`AttributeError` + as you would expect. Fixed by Benjamin Peterson; :issue:`7604`.) + +* Two new encodings are now supported: "cp720", used primarily for + Arabic text; and "cp858", a variant of CP 850 that adds the euro + symbol. (CP720 contributed by Alexander Belchenko and Amaury + Forgeot d'Arc in :issue:`1616979`; CP858 contributed by Tim Hatch in + :issue:`8016`.) * The :class:`file` object will now set the :attr:`filename` attribute on the :exc:`IOError` exception when trying to open a directory @@ -615,7 +820,7 @@ (fixed by Stefan Krah; :issue:`5677`). * The Python tokenizer now translates line endings itself, so the - :func:`compile` built-in function can now accept code using any + :func:`compile` built-in function now accepts code using any line-ending convention. Additionally, it no longer requires that the code end in a newline. @@ -648,13 +853,12 @@ For example, the following setting will print warnings every time they occur, but turn warnings from the :mod:`Cookie` module into an error. (The exact syntax for setting an environment variable varies -across operating systems and shells, so it may be different for you.) +across operating systems and shells.) :: export PYTHONWARNINGS=all,error:::Cookie:0 - .. ====================================================================== @@ -678,7 +882,7 @@ any of them. This would previously take quadratic time for garbage collection, but now the number of full garbage collections is reduced as the number of objects on the heap grows. - The new logic is to only perform a full garbage collection pass when + The new logic only performs a full garbage collection pass when the middle generation has been collected 10 times and when the number of survivor objects from the middle generation exceeds 10% of the number of objects in the oldest generation. (Suggested by Martin @@ -788,11 +992,11 @@ The new version features better Python 3.x compatibility, various bug fixes, and adds several new BerkeleyDB flags and methods. (Updated by Jes??s Cea Avi??n; :issue:`8156`. The pybsddb - changelog can be browsed at http://hg.jcea.es/pybsddb/file/tip/ChangeLog.) + changelog can be read at http://hg.jcea.es/pybsddb/file/tip/ChangeLog.) * The :mod:`bz2` module's :class:`~bz2.BZ2File` now supports the context - management protocol, so you can write ``with bz2.BZ2File(...) as f: ...``. - (Contributed by Hagen Fuerstenau; :issue:`3860`.) + management protocol, so you can write ``with bz2.BZ2File(...) as f:``. + (Contributed by Hagen F??rstenau; :issue:`3860`.) * New class: the :class:`~collections.Counter` class in the :mod:`collections` module is useful for tallying data. :class:`~collections.Counter` instances @@ -816,7 +1020,7 @@ >>> c['z'] 0 - There are three additional :class:`~collections.Counter` methods: + There are three additional :class:`~collections.Counter` methods. :meth:`~collections.Counter.most_common` returns the N most common elements and their counts. :meth:`~collections.Counter.elements` returns an iterator over the contained elements, repeating each @@ -843,12 +1047,20 @@ .. revision 79660 - The new :class:`~collections.OrderedDict` class is described in the earlier + New class: :class:`~collections.OrderedDict` is described in the earlier section :ref:`pep-0372`. + New method: The :class:`~collections.deque` data type now has a + :meth:`~collections.deque.count` method that returns the number of + contained elements equal to the supplied argument *x*, and a + :meth:`~collections.deque.reverse` method that reverses the elements + of the deque in-place. :class:`deque` also exposes its maximum + length as the read-only :attr:`~collections.deque.maxlen` attribute. + (Both features added by Raymond Hettinger.) + The :class:`~collections.namedtuple` class now has an optional *rename* parameter. If *rename* is true, field names that are invalid because they've - been repeated or that aren't legal Python identifiers will be + been repeated or aren't legal Python identifiers will be renamed to legal names that are derived from the field's position within the list of fields: @@ -859,13 +1071,43 @@ (Added by Raymond Hettinger; :issue:`1818`.) - The :class:`~collections.deque` data type now has a - :meth:`~collections.deque.count` method that returns the number of - contained elements equal to the supplied argument *x*, and a - :meth:`~collections.deque.reverse` method that reverses the elements - of the deque in-place. :class:`deque` also exposes its maximum - length as the read-only :attr:`~collections.deque.maxlen` attribute. - (Both features added by Raymond Hettinger.) + Finally, the :class:`~collections.Mapping` abstract base class now + returns :const:`NotImplemented` if a mapping is compared to + another type that isn't a :class:`Mapping`. + (Fixed by Daniel Stutzbach; :issue:`8729`.) + +* Constructors for the parsing classes in the :mod:`ConfigParser` module now + take a *allow_no_value* parameter, defaulting to false; if true, + options without values will be allowed. For example:: + + >>> import ConfigParser, StringIO + >>> sample_config = """ + ... [mysqld] + ... user = mysql + ... pid-file = /var/run/mysqld/mysqld.pid + ... skip-bdb + ... """ + >>> config = ConfigParser.RawConfigParser(allow_no_value=True) + >>> config.readfp(StringIO.StringIO(sample_config)) + >>> config.get('mysqld', 'user') + 'mysql' + >>> print config.get('mysqld', 'skip-bdb') + None + >>> print config.get('mysqld', 'unknown') + Traceback (most recent call last): + ... + NoOptionError: No option 'unknown' in section: 'mysqld' + + (Contributed by Mats Kindahl; :issue:`7005`.) + +* Deprecated function: :func:`contextlib.nested`, which allows + handling more than one context manager with a single :keyword:`with` + statement, has been deprecated, because the :keyword:`with` statement + now supports multiple context managers. + +* The :mod:`cookielib` module now ignores cookies that have an invalid + version field, one that doesn't contain an integer value. (Fixed by + John J. Lee; :issue:`3924`.) * The :mod:`copy` module's :func:`~copy.deepcopy` function will now correctly copy bound instance methods. (Implemented by @@ -885,7 +1127,7 @@ * New method: the :class:`~decimal.Decimal` class gained a :meth:`~decimal.Decimal.from_float` class method that performs an exact conversion of a floating-point number to a :class:`~decimal.Decimal`. - Note that this is an **exact** conversion that strives for the + This exact conversion strives for the closest decimal approximation to the floating-point representation's value; the resulting decimal value will therefore still include the inaccuracy, if any. @@ -893,27 +1135,57 @@ ``Decimal('0.1000000000000000055511151231257827021181583404541015625')``. (Implemented by Raymond Hettinger; :issue:`4796`.) - Most of the methods of the :class:`~decimal.Context` class now accept integers - as well as :class:`~decimal.Decimal` instances; the only exceptions are the - :meth:`~decimal.Context.canonical` and :meth:`~decimal.Context.is_canonical` - methods. (Patch by Juan Jos?? Conti; :issue:`7633`.) + Comparing instances of :class:`Decimal` with floating-point + numbers now produces sensible results based on the numeric values + of the operands. Previously such comparisons would fall back to + Python's default rules for comparing objects, which produced arbitrary + results based on their type. Note that you still cannot combine + :class:`Decimal` and floating-point in other operations such as addition, + since you should be explicitly choosing how to convert between float and + :class:`Decimal`. + (Fixed by Mark Dickinson; :issue:`2531`.) The constructor for :class:`~decimal.Decimal` now accepts floating-point numbers (added by Raymond Hettinger; :issue:`8257`) and non-European Unicode characters such as Arabic-Indic digits (contributed by Mark Dickinson; :issue:`6595`). + Most of the methods of the :class:`~decimal.Context` class now accept integers + as well as :class:`~decimal.Decimal` instances; the only exceptions are the + :meth:`~decimal.Context.canonical` and :meth:`~decimal.Context.is_canonical` + methods. (Patch by Juan Jos?? Conti; :issue:`7633`.) + When using :class:`~decimal.Decimal` instances with a string's :meth:`~str.format` method, the default alignment was previously - left-alignment. This has been changed to right-alignment, which seems + left-alignment. This has been changed to right-alignment, which is more sensible for numeric types. (Changed by Mark Dickinson; :issue:`6857`.) + Comparisons involving a signaling NaN value (or ``sNAN``) now signal + :const:`InvalidOperation` instead of silently returning a true or + false value depending on the comparison operator. Quiet NaN values + (or ``NaN``) are now hashable. (Fixed by Mark Dickinson; + :issue:`7279`.) + * The :mod:`difflib` module now produces output that is more - compatible with modern :command:`diff`/:command:`patch` tools thanks - to two changes: 1) the header giving the filename now uses a tab - character instead of spaces as a separator, and 2) the date format - used is now ISO-8601 style, ``2005-01-26 23:30:50``. (Fixed by - Anatoly Techtonik; :issue:`7585`.) + compatible with modern :command:`diff`/:command:`patch` tools + through one small change, using a tab character instead of spaces as + a separator in the header giving the filename. (Fixed by Anatoly + Techtonik; :issue:`7585`.) + +* The Distutils ``sdist`` command now always regenerates the + :file:`MANIFEST` file, since even if the :file:`MANIFEST.in` or + :file:`setup.py` files haven't been modified, the user might have + created some new files that should be included. + (Fixed by Tarek Ziad??; :issue:`8688`.) + +* The :mod:`doctest` module's :const:`IGNORE_EXCEPTION_DETAIL` flag + will now ignore the name of the module containing the exception + being tested. (Patch by Lennart Regebro; :issue:`7490`.) + +* The :mod:`email` module's :class:`~email.message.Message` class will + now accept a Unicode-valued payload, automatically converting the + payload to the encoding specified by :attr:`output_charset`. + (Added by R. David Murray; :issue:`1368247`.) * The :class:`~fractions.Fraction` class now accepts a single float or :class:`~decimal.Decimal` instance, or two rational numbers, as @@ -921,17 +1193,18 @@ rationals added in :issue:`5812`, and float/decimal in :issue:`8294`.) - An oversight was fixed, making the :class:`Fraction` match the other - numeric types; ordering comparisons (``<``, ``<=``, ``>``, ``>=``) between + Ordering comparisons (``<``, ``<=``, ``>``, ``>=``) between fractions and complex numbers now raise a :exc:`TypeError`. + This fixes an oversight, making the :class:`Fraction` match the other + numeric types. .. revision 79455 -* New class: a new :class:`~ftplib.FTP_TLS` class in +* New class: :class:`~ftplib.FTP_TLS` in the :mod:`ftplib` module provides secure FTP connections using TLS encapsulation of authentication as well as subsequent control and data transfers. - (Contributed by Giampaolo Rodola', :issue:`2054`.) + (Contributed by Giampaolo Rodola; :issue:`2054`.) The :meth:`~ftplib.FTP.storbinary` method for binary uploads can now restart uploads thanks to an added *rest* parameter (patch by Pablo Mouzo; @@ -957,8 +1230,8 @@ otherwise. (Contributed by Antoine Pitrou; :issue:`4688`.) * The :mod:`gzip` module's :class:`~gzip.GzipFile` now supports the context - management protocol, so you can write ``with gzip.GzipFile(...) as f: ...`` - (contributed by Hagen Fuerstenau; :issue:`3860`), and it now implements + management protocol, so you can write ``with gzip.GzipFile(...) as f:`` + (contributed by Hagen F??rstenau; :issue:`3860`), and it now implements the :class:`io.BufferedIOBase` ABC, so you can wrap it with :class:`io.BufferedReader` for faster processing (contributed by Nir Aides; :issue:`7471`). @@ -973,18 +1246,25 @@ * New attribute: the :mod:`hashlib` module now has an :attr:`~hashlib.hashlib.algorithms` attribute containing a tuple naming the supported algorithms. In Python 2.7, ``hashlib.algorithms`` contains - ``('md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512')`` + ``('md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512')``. (Contributed by Carl Chenet; :issue:`7418`.) * The default :class:`~httplib.HTTPResponse` class used by the :mod:`httplib` module now supports buffering, resulting in much faster reading of HTTP responses. - (Contributed by Kristjan Valur Jonsson; :issue:`4879`.) + (Contributed by Kristj??n Valur J??nsson; :issue:`4879`.) The :class:`~httplib.HTTPConnection` and :class:`~httplib.HTTPSConnection` classes now support a *source_address* parameter, a ``(host, port)`` 2-tuple giving the source address that will be used for the connection. (Contributed by Eldon Ziegler; :issue:`3972`.) +* The :mod:`ihooks` module now supports relative imports. Note that + :mod:`ihooks` is an older module for customizing imports, + superseded by the :mod:`imputil` module added in Python 2.0. + (Relative import support added by Neil Schemenauer.) + + .. revision 75423 + * The :mod:`imaplib` module now supports IPv6 addresses. (Contributed by Derek Morr; :issue:`1655`.) @@ -997,9 +1277,9 @@ >>> def f(a, b=1, *pos, **named): ... pass >>> getcallargs(f, 1, 2, 3) - {'a': 1, 'named': {}, 'b': 2, 'pos': (3,)} + {'a': 1, 'b': 2, 'pos': (3,), 'named': {}} >>> getcallargs(f, a=2, x=4) - {'a': 2, 'named': {'x': 4}, 'b': 1, 'pos': ()} + {'a': 2, 'b': 1, 'pos': (), 'named': {'x': 4}} >>> getcallargs(f) Traceback (most recent call last): ... @@ -1050,8 +1330,8 @@ floats or :class:`~decimal.Decimal` instances. (Implemented by Raymond Hettinger; :issue:`5032`.) - :func:`itertools.combinations` and :func:`itertools.product` were - previously raising :exc:`ValueError` for values of *r* larger than + :func:`itertools.combinations` and :func:`itertools.product` + previously raised :exc:`ValueError` for values of *r* larger than the input iterable. This was deemed a specification error, so they now return an empty iterator. (Fixed by Raymond Hettinger; :issue:`4816`.) @@ -1065,6 +1345,12 @@ with any object literal that decodes to a list of pairs. (Contributed by Raymond Hettinger; :issue:`5381`.) +* The :mod:`mailbox` module's :class:`Maildir` class now records the + timestamp on the directories it reads, and only re-reads them if the + modification time has subsequently changed. This improves + performance by avoiding unneeded directory scans. (Fixed by + A.M. Kuchling and Antoine Pitrou; :issue:`1607951`, :issue:`6896`.) + * New functions: the :mod:`math` module gained :func:`~math.erf` and :func:`~math.erfc` for the error function and the complementary error function, :func:`~math.expm1` which computes ``e**x - 1`` with more precision than @@ -1095,7 +1381,8 @@ real, effective, and saved GIDs and UIDs; :func:`~os.setresgid` and :func:`~os.setresuid`, which set real, effective, and saved GIDs and UIDs to new values; - :func:`~os.initgroups`. (GID/UID functions + :func:`~os.initgroups`, which initialize the group access list + for the current process. (GID/UID functions contributed by Travis H.; :issue:`6508`. Support for initgroups added by Jean-Paul Calderone; :issue:`7333`.) @@ -1117,6 +1404,20 @@ now accept an optional *flags* argument, for consistency with the other functions in the module. (Added by Gregory P. Smith.) +* New function: :func:`~runpy.run_path` in the :mod:`runpy` module + will execute the code at a provided *path* argument. *path* can be + the path of a Python source file (:file:`example.py`), a compiled + bytecode file (:file:`example.pyc`), a directory + (:file:`./package/`), or a zip archive (:file:`example.zip`). If a + directory or zip path is provided, it will be added to the front of + ``sys.path`` and the module :mod:`__main__` will be imported. It's + expected that the directory or zip contains a :file:`__main__.py`; + if it doesn't, some other :file:`__main__.py` might be imported from + a location later in ``sys.path``. This makes more of the machinery + of :mod:`runpy` available to scripts that want to mimic the way + Python's command line processes an explicit path name. + (Added by Nick Coghlan; :issue:`6816`.) + * New function: in the :mod:`shutil` module, :func:`~shutil.make_archive` takes a filename, archive type (zip or tar-format), and a directory path, and creates an archive containing the directory's contents. @@ -1128,12 +1429,17 @@ named pipes like a regular file by opening them for reading, and this would block indefinitely. (Fixed by Antoine Pitrou; :issue:`3002`.) +* The :mod:`signal` module no longer re-installs the signal handler + unless this is truly necessary, which fixes a bug that could make it + impossible to catch the EINTR signal robustly. (Fixed by + Charles-Francois Natali; :issue:`8354`.) + * New functions: in the :mod:`site` module, three new functions return various site- and user-specific paths. :func:`~site.getsitepackages` returns a list containing all - global site-packages directories, and + global site-packages directories, :func:`~site.getusersitepackages` returns the path of the user's - site-packages directory. + site-packages directory, and :func:`~site.getuserbase` returns the value of the :envvar:`USER_BASE` environment variable, giving the path to a directory that can be used to store data. @@ -1144,20 +1450,7 @@ catch and swallow the :exc:`KeyboardInterrupt` exception. (Fixed by Victor Stinner; :issue:`3137`.) -* The :mod:`socket` module's :class:`~ssl.SSL` objects now support the - buffer API, which fixed a test suite failure (fix by Antoine Pitrou; - :issue:`7133`). :class:`SSL` objects also now automatically set - OpenSSL's :cmacro:`SSL_MODE_AUTO_RETRY`, which will prevent an error - code being returned from :meth:`recv` operations that trigger an SSL - renegotiation (fix by Antoine Pitrou; :issue:`8222`). - - The version of OpenSSL being used is now available as the module - attributes :attr:`OPENSSL_VERSION` (a string), - :attr:`OPENSSL_VERSION_INFO` (a 5-tuple), and - :attr:`OPENSSL_VERSION_NUMBER` (an integer). (Added by Antoine - Pitrou; :issue:`8321`.) - - The :func:`~socket.create_connection` function +* The :func:`~socket.create_connection` function gained a *source_address* parameter, a ``(host, port)`` 2-tuple giving the source address that will be used for the connection. (Contributed by Eldon Ziegler; :issue:`3972`.) @@ -1168,11 +1461,16 @@ Antoine Pitrou; :issue:`8104`.) * The :mod:`SocketServer` module's :class:`~SocketServer.TCPServer` class now - has a :attr:`~SocketServer.TCPServer.disable_nagle_algorithm` class attribute. - The default value is False; if overridden to be True, + supports socket timeouts and disabling the Nagle algorithm. + The :attr:`~SocketServer.TCPServer.disable_nagle_algorithm` class attribute + defaults to False; if overridden to be True, new request connections will have the TCP_NODELAY option set to prevent buffering many small sends into a single TCP packet. - (Contributed by Kristjan Valur Jonsson; :issue:`6192`.) + The :attr:`~SocketServer.TCPServer.timeout` class attribute can hold + a timeout in seconds that will be applied to the request socket; if + no request is received within that time, :meth:`handle_timeout` + will be called and :meth:`handle_request` will return. + (Contributed by Kristj??n Valur J??nsson; :issue:`6192` and :issue:`6267`.) * Updated module: the :mod:`sqlite3` module has been updated to version 2.6.0 of the `pysqlite package `__. Version 2.6.0 includes a number of bugfixes, and adds @@ -1181,6 +1479,32 @@ and then call :meth:`~sqlite3.Connection.load_extension` to load a particular shared library. (Updated by Gerhard H??ring.) +* The :mod:`ssl` module's :class:`ssl.SSLSocket` objects now support the + buffer API, which fixed a test suite failure (fix by Antoine Pitrou; + :issue:`7133`) and automatically set + OpenSSL's :cmacro:`SSL_MODE_AUTO_RETRY`, which will prevent an error + code being returned from :meth:`recv` operations that trigger an SSL + renegotiation (fix by Antoine Pitrou; :issue:`8222`). + + The :func:`ssl.wrap_socket` constructor function now takes a + *ciphers* argument that's a string listing the encryption algorithms + to be allowed; the format of the string is described + `in the OpenSSL documentation + `__. + (Added by Antoine Pitrou; :issue:`8322`.) + + Another change makes the extension load all of OpenSSL's ciphers and + digest algorithms so that they're all available. Some SSL + certificates couldn't be verified, reporting an "unknown algorithm" + error. (Reported by Beda Kosata, and fixed by Antoine Pitrou; + :issue:`8484`.) + + The version of OpenSSL being used is now available as the module + attributes :data:`ssl.OPENSSL_VERSION` (a string), + :data:`ssl.OPENSSL_VERSION_INFO` (a 5-tuple), and + :data:`ssl.OPENSSL_VERSION_NUMBER` (an integer). (Added by Antoine + Pitrou; :issue:`8321`.) + * The :mod:`struct` module will no longer silently ignore overflow errors when a value is too large for a particular integer format code (one of ``bBhHiIlLqQ``); it now always raises a @@ -1216,6 +1540,10 @@ false for ones that are implicitly global. (Contributed by Jeremy Hylton.) +* The :mod:`syslog` module will now use the value of ``sys.argv[0]`` as the + identifier instead of the previous default value of ``'python'``. + (Changed by Sean Reifschneider; :issue:`8451`.) + * The ``sys.version_info`` value is now a named tuple, with attributes named :attr:`major`, :attr:`minor`, :attr:`micro`, :attr:`releaselevel`, and :attr:`serial`. (Contributed by Ross @@ -1237,7 +1565,7 @@ :mod:`tarfile` now supports filtering the :class:`~tarfile.TarInfo` objects being added to a tar file. When you call :meth:`~tarfile.TarFile.add`, - instance, you may supply an optional *filter* argument + you may supply an optional *filter* argument that's a callable. The *filter* callable will be passed the :class:`~tarfile.TarInfo` for every file being added, and can modify and return it. If the callable returns ``None``, the file will be excluded from the @@ -1262,8 +1590,39 @@ and has been updated to version 5.2.0 (updated by Florent Xicluna; :issue:`8024`). -* The :class:`~UserDict.UserDict` class is now a new-style class. (Changed by - Benjamin Peterson.) +* The :mod:`urlparse` module's :func:`~urlparse.urlsplit` now handles + unknown URL schemes in a fashion compliant with :rfc:`3986`: if the + URL is of the form ``"://..."``, the text before the + ``://`` is treated as the scheme, even if it's a made-up scheme that + the module doesn't know about. This change may break code that + worked around the old behaviour. For example, Python 2.6.4 or 2.5 + will return the following: + + >>> import urlparse + >>> urlparse.urlsplit('invented://host/filename?query') + ('invented', '', '//host/filename?query', '', '') + + Python 2.7 (and Python 2.6.5) will return: + + >>> import urlparse + >>> urlparse.urlsplit('invented://host/filename?query') + ('invented', 'host', '/filename?query', '', '') + + (Python 2.7 actually produces slightly different output, since it + returns a named tuple instead of a standard tuple.) + + The :mod:`urlparse` module also supports IPv6 literal addresses as defined by + :rfc:`2732` (contributed by Senthil Kumaran; :issue:`2987`). :: + + >>> urlparse.urlparse('http://[1080::8:800:200C:417A]/foo') + ParseResult(scheme='http', netloc='[1080::8:800:200C:417A]', + path='/foo', params='', query='', fragment='') + +* New class: the :class:`~weakref.WeakSet` class in the :mod:`weakref` + module is a set that only holds weak references to its elements; elements + will be removed once there are no references pointing to them. + (Originally implemented in Python 3.x by Raymond Hettinger, and backported + to 2.7 by Michael Foord.) * The ElementTree library, :mod:`xml.etree`, no longer escapes ampersands and angle brackets when outputting an XML processing @@ -1271,13 +1630,22 @@ or comment (which looks like ````). (Patch by Neil Muller; :issue:`2746`.) +* The XML-RPC client and server, provided by the :mod:`xmlrpclib` and + :mod:`SimpleXMLRPCServer` modules, have improved performance by + supporting HTTP/1.1 keep-alive and by optionally using gzip encoding + to compress the XML being exchanged. The gzip compression is + controlled by the :attr:`encode_threshold` attribute of + :class:`SimpleXMLRPCRequestHandler`, which contains a size in bytes; + responses larger than this will be compressed. + (Contributed by Kristj??n Valur J??nsson; :issue:`6267`.) + * The :mod:`zipfile` module's :class:`~zipfile.ZipFile` now supports the context - management protocol, so you can write ``with zipfile.ZipFile(...) as f: ...``. + management protocol, so you can write ``with zipfile.ZipFile(...) as f:``. (Contributed by Brian Curtin; :issue:`5511`.) - :mod:`zipfile` now supports archiving empty directories and + :mod:`zipfile` now also supports archiving empty directories and extracts them correctly. (Fixed by Kuba Wieczorek; :issue:`4710`.) - Reading files out of an archive is now faster, and interleaving + Reading files out of an archive is faster, and interleaving :meth:`~zipfile.ZipFile.read` and :meth:`~zipfile.ZipFile.readline` now works correctly. (Contributed by Nir Aides; :issue:`7610`.) @@ -1291,36 +1659,157 @@ :issue:`6003`.) +.. ====================================================================== +.. whole new modules get described in subsections here + + +.. _importlib-section: + +New module: importlib +------------------------------ + +Python 3.1 includes the :mod:`importlib` package, a re-implementation +of the logic underlying Python's :keyword:`import` statement. +:mod:`importlib` is useful for implementors of Python interpreters and +to users who wish to write new importers that can participate in the +import process. Python 2.7 doesn't contain the complete +:mod:`importlib` package, but instead has a tiny subset that contains +a single function, :func:`~importlib.import_module`. + +``import_module(name, package=None)`` imports a module. *name* is +a string containing the module or package's name. It's possible to do +relative imports by providing a string that begins with a ``.`` +character, such as ``..utils.errors``. For relative imports, the +*package* argument must be provided and is the name of the package that +will be used as the anchor for +the relative import. :func:`~importlib.import_module` both inserts the imported +module into ``sys.modules`` and returns the module object. + +Here are some examples:: + + >>> from importlib import import_module + >>> anydbm = import_module('anydbm') # Standard absolute import + >>> anydbm + + >>> # Relative import + >>> file_util = import_module('..file_util', 'distutils.command') + >>> file_util + + +:mod:`importlib` was implemented by Brett Cannon and introduced in +Python 3.1. + + New module: sysconfig --------------------------------- -XXX A new :mod:`sysconfig` module has been extracted from -:mod:`distutils` and put in the standard library. +The :mod:`sysconfig` module has been pulled out of the Distutils +package, becoming a new top-level module in its own right. +:mod:`sysconfig` provides functions for getting information about +Python's build process: compiler switches, installation paths, the +platform name, and whether Python is running from its source +directory. + +Some of the functions in the module are: + +* :func:`~sysconfig.get_config_var` returns variables from Python's + Makefile and the :file:`pyconfig.h` file. +* :func:`~sysconfig.get_config_vars` returns a dictionary containing + all of the configuration variables. +* :func:`~sysconfig.getpath` returns the configured path for + a particular type of module: the standard library, + site-specific modules, platform-specific modules, etc. +* :func:`~sysconfig.is_python_build` returns true if you're running a + binary from a Python source tree, and false otherwise. + +Consult the :mod:`sysconfig` documentation for more details and for +a complete list of functions. + +The Distutils package and :mod:`sysconfig` are now maintained by Tarek +Ziad??, who has also started a Distutils2 package (source repository at +http://hg.python.org/distutils2/) for developing a next-generation +version of Distutils. -The :mod:`sysconfig` module provides access to Python's configuration -information like the list of installation paths and the configuration -variables relevant for the current platform. (contributed by Tarek) -Updated module: ElementTree 1.3 ---------------------------------- +ttk: Themed Widgets for Tk +-------------------------- + +Tcl/Tk 8.5 includes a set of themed widgets that re-implement basic Tk +widgets but have a more customizable appearance and can therefore more +closely resemble the native platform's widgets. This widget +set was originally called Tile, but was renamed to Ttk (for "themed Tk") +on being added to Tcl/Tck release 8.5. -XXX write this. +To learn more, read the :mod:`ttk` module documentation. You may also +wish to read the Tcl/Tk manual page describing the +Ttk theme engine, available at +http://www.tcl.tk/man/tcl8.5/TkCmd/ttk_intro.htm. Some +screenshots of the Python/Ttk code in use are at +http://code.google.com/p/python-ttk/wiki/Screenshots. -.. ====================================================================== -.. whole new modules get described in subsections here +The :mod:`ttk` module was written by Guilherme Polo and added in +:issue:`2983`. An alternate version called ``Tile.py``, written by +Martin Franklin and maintained by Kevin Walzer, was proposed for +inclusion in :issue:`2618`, but the authors argued that Guilherme +Polo's work was more comprehensive. -Unit Testing Enhancements +.. _unittest-section: + +Updated module: unittest --------------------------------- -The :mod:`unittest` module was enhanced in several ways. -The progress messages now shows 'x' for expected failures +The :mod:`unittest` module was greatly enhanced; many +new features were added. Most of these features were implemented +by Michael Foord, unless otherwise noted. The enhanced version of +the module is downloadable separately for use with Python versions 2.4 to 2.6, +packaged as the :mod:`unittest2` package, from +http://pypi.python.org/pypi/unittest2. + +When used from the command line, the module can automatically discover +tests. It's not as fancy as `py.test `__ or +`nose `__, but provides a simple way +to run tests kept within a set of package directories. For example, +the following command will search the :file:`test/` subdirectory for +any importable test files named ``test*.py``:: + + python -m unittest discover -s test + +Consult the :mod:`unittest` module documentation for more details. +(Developed in :issue:`6001`.) + +The :func:`main` function supports some other new options: + +* :option:`-b` or :option:`--buffer` will buffer the standard output + and standard error streams during each test. If the test passes, + any resulting output will be discarded; on failure, the buffered + output will be displayed. + +* :option:`-c` or :option:`--catch` will cause the control-C interrupt + to be handled more gracefully. Instead of interrupting the test + process immediately, the currently running test will be completed + and then the partial results up to the interruption will be reported. + If you're impatient, a second press of control-C will cause an immediate + interruption. + + This control-C handler tries to avoid causing problems when the code + being tested or the tests being run have defined a signal handler of + their own, by noticing that a signal handler was already set and + calling it. If this doesn't work for you, there's a + :func:`removeHandler` decorator that can be used to mark tests that + should have the control-C handling disabled. + +* :option:`-f` or :option:`--failfast` makes + test execution stop immediately when a test fails instead of + continuing to execute further tests. (Suggested by Cliff Dyer and + implemented by Michael Foord; :issue:`8074`.) + +The progress messages now show 'x' for expected failures and 'u' for unexpected successes when run in verbose mode. (Contributed by Benjamin Peterson.) -Test cases can raise the :exc:`~unittest.SkipTest` exception to skip a test. -(:issue:`1034053`.) -.. XXX describe test discovery (Contributed by Michael Foord; :issue:`6001`.) +Test cases can raise the :exc:`~unittest.SkipTest` exception to skip a +test (:issue:`1034053`). The error messages for :meth:`~unittest.TestCase.assertEqual`, :meth:`~unittest.TestCase.assertTrue`, and :meth:`~unittest.TestCase.assertFalse` @@ -1330,7 +1819,7 @@ provide will be printed for failures. (Added by Michael Foord; :issue:`5663`.) The :meth:`~unittest.TestCase.assertRaises` method now -return a context handler when called without providing a callable +returns a context handler when called without providing a callable object to run. For example, you can write this:: with self.assertRaises(KeyError): @@ -1350,7 +1839,7 @@ The methods :meth:`~unittest.TestCase.addCleanup` and :meth:`~unittest.TestCase.doCleanups` were added. -:meth:`~unittest.TestCase.addCleanup` allows you to add cleanup functions that +:meth:`~unittest.TestCase.addCleanup` lets you add cleanup functions that will be called unconditionally (after :meth:`~unittest.TestCase.setUp` if :meth:`~unittest.TestCase.setUp` fails, otherwise after :meth:`~unittest.TestCase.tearDown`). This allows for much simpler resource allocation and deallocation during tests @@ -1382,10 +1871,10 @@ differences in the two strings. This comparison is now used by default when Unicode strings are compared with :meth:`~unittest.TestCase.assertEqual`. -* :meth:`~unittest.TestCase.assertRegexpMatches` checks whether its first argument is a - string matching a regular expression provided as its second argument. - - .. XXX add assertNotRegexpMatches see issue 8038 +* :meth:`~unittest.TestCase.assertRegexpMatches` and + :meth:`~unittest.TestCase.assertNotRegexpMatches` checks whether the + first argument is a string matching or not matching the regular + expression provided as the second argument (:issue:`8038`). * :meth:`~unittest.TestCase.assertRaisesRegexp` checks whether a particular exception is raised, and then also checks that the string representation of @@ -1414,9 +1903,10 @@ all of the key/value pairs in *first* are found in *second*. * :meth:`~unittest.TestCase.assertAlmostEqual` and :meth:`~unittest.TestCase.assertNotAlmostEqual` test - whether *first* and *second* are approximately equal by computing - their difference, rounding the result to an optionally-specified number - of *places* (the default is 7), and comparing to zero. + whether *first* and *second* are approximately equal. This method + can either round their difference to an optionally-specified number + of *places* (the default is 7) and compare it to zero, or require + the difference to be smaller than a supplied *delta* value. * :meth:`~unittest.TestLoader.loadTestsFromName` properly honors the :attr:`~unittest.TestLoader.suiteClass` attribute of @@ -1428,20 +1918,13 @@ objects being compared are of the specified type. This function should compare the two objects and raise an exception if they don't match; it's a good idea for the function to provide additional - information about why the two objects are matching, much as the new + information about why the two objects aren't matching, much as the new sequence comparison methods do. :func:`unittest.main` now takes an optional ``exit`` argument. If -False, :func:`~unittest.main` doesn't call :func:`sys.exit`, allowing it to be -used from the interactive interpreter. (Contributed by J. Pablo -Fern??ndez; :issue:`3379`.) - -A new command-line switch, :option:`-f` or :option:`--failfast`, makes -test execution stop immediately when a test fails instead of -continuing to execute further tests. (Suggested by Cliff Dyer and -implemented by Michael Foord; :issue:`8074`.) - -.. XXX document the other new switches +False, :func:`~unittest.main` doesn't call :func:`sys.exit`, allowing +:func:`main` to be used from the interactive interpreter. +(Contributed by J. Pablo Fern??ndez; :issue:`3379`.) :class:`~unittest.TestResult` has new :meth:`~unittest.TestResult.startTestRun` and :meth:`~unittest.TestResult.stopTestRun` methods that are called immediately before @@ -1450,70 +1933,98 @@ With all these changes, the :file:`unittest.py` was becoming awkwardly large, so the module was turned into a package and the code split into several files (by Benjamin Peterson). This doesn't affect how the -module is imported. - - -.. _importlib-section: - -importlib: Importing Modules ------------------------------- +module is imported or used. -Python 3.1 includes the :mod:`importlib` package, a re-implementation -of the logic underlying Python's :keyword:`import` statement. -:mod:`importlib` is useful for implementors of Python interpreters and -to users who wish to write new importers that can participate in the -import process. Python 2.7 doesn't contain the complete -:mod:`importlib` package, but instead has a tiny subset that contains -a single function, :func:`~importlib.import_module`. - -``import_module(name, package=None)`` imports a module. *name* is -a string containing the module or package's name. It's possible to do -relative imports by providing a string that begins with a ``.`` -character, such as ``..utils.errors``. For relative imports, the -*package* argument must be provided and is the name of the package that -will be used as the anchor for -the relative import. :func:`~importlib.import_module` both inserts the imported -module into ``sys.modules`` and returns the module object. - -Here are some examples:: - - >>> from importlib import import_module - >>> anydbm = import_module('anydbm') # Standard absolute import - >>> anydbm - - >>> # Relative import - >>> sysconfig = import_module('..sysconfig', 'distutils.command') - >>> sysconfig - - -:mod:`importlib` was implemented by Brett Cannon and introduced in -Python 3.1. - - -ttk: Themed Widgets for Tk --------------------------- - -Tcl/Tk 8.5 includes a set of themed widgets that re-implement basic Tk -widgets but have a more customizable appearance and can therefore more -closely resemble the native platform's widgets. This widget -set was originally called Tile, but was renamed to Ttk (for "themed Tk") -on being added to Tcl/Tck release 8.5. +.. seealso:: -XXX write a brief discussion and an example here. + http://www.voidspace.org.uk/python/articles/unittest2.shtml + Describes the new features, how to use them, and the + rationale for various design decisions. (By Michael Foord.) -The :mod:`ttk` module was written by Guilherme Polo and added in -:issue:`2983`. An alternate version called ``Tile.py``, written by -Martin Franklin and maintained by Kevin Walzer, was proposed for -inclusion in :issue:`2618`, but the authors argued that Guilherme -Polo's work was more comprehensive. +.. _elementtree-section: +Updated module: ElementTree 1.3 +--------------------------------- -Deprecations and Removals -========================= +The version of the ElementTree library included with Python was updated to +version 1.3. Some of the new features are: -* :func:`contextlib.nested`, which allows handling more than one context manager - with one :keyword:`with` statement, has been deprecated; :keyword:`with` - supports multiple context managers syntactically now. +* The various parsing functions now take a *parser* keyword argument + giving an :class:`XMLParser` instance that will + be used. This makes it possible to override the file's internal encoding:: + + p = ET.XMLParser(encoding='utf-8') + t = ET.XML("""""", parser=p) + + Errors in parsing XML now raise a :exc:`ParseError` exception, whose + instances have a :attr:`position` attribute + containing a (*line*, *column*) tuple giving the location of the problem. + +* ElementTree's code for converting trees to a string has been + significantly reworked, making it roughly twice as fast in many + cases. The :class:`ElementTree` :meth:`write` and :class:`Element` + :meth:`write` methods now have a *method* parameter that can be + "xml" (the default), "html", or "text". HTML mode will output empty + elements as ```` instead of ````, and text + mode will skip over elements and only output the text chunks. If + you set the :attr:`tag` attribute of an element to ``None`` but + leave its children in place, the element will be omitted when the + tree is written out, so you don't need to do more extensive rearrangement + to remove a single element. + + Namespace handling has also been improved. All ``xmlns:`` + declarations are now output on the root element, not scattered throughout + the resulting XML. You can set the default namespace for a tree + by setting the :attr:`default_namespace` attribute and can + register new prefixes with :meth:`register_namespace`. In XML mode, + you can use the true/false *xml_declaration* parameter to suppress the + XML declaration. + +* New :class:`Element` method: :meth:`extend` appends the items from a + sequence to the element's children. Elements themselves behave like + sequences, so it's easy to move children from one element to + another:: + + from xml.etree import ElementTree as ET + + t = ET.XML(""" + 1 2 3 + """) + new = ET.XML('') + new.extend(t) + + # Outputs 1... + print ET.tostring(new) + +* New :class:`Element` method: :meth:`iter` yields the children of the + element as a generator. It's also possible to write ``for child in + elem:`` to loop over an element's children. The existing method + :meth:`getiterator` is now deprecated, as is :meth:`getchildren` + which constructs and returns a list of children. + +* New :class:`Element` method: :meth:`itertext` yields all chunks of + text that are descendants of the element. For example:: + + t = ET.XML(""" + 1 2 3 + """) + + # Outputs ['\n ', '1', ' ', '2', ' ', '3', '\n'] + print list(t.itertext()) + +* Deprecated: using an element as a Boolean (i.e., ``if elem:``) would + return true if the element had any children, or false if there were + no children. This behaviour is confusing -- ``None`` is false, but + so is a childless element? -- so it will now trigger a + :exc:`FutureWarning`. In your code, you should be explicit: write + ``len(elem) != 0`` if you're interested in the number of children, + or ``elem is not None``. + +Fredrik Lundh develops ElementTree and produced the 1.3 version; +you can read his article describing 1.3 at +http://effbot.org/zone/elementtree-13-intro.htm. +Florent Xicluna updated the version included with +Python, after discussions on python-dev and in :issue:`6472`.) .. ====================================================================== @@ -1528,9 +2039,9 @@ `__. When you begin debugging an executable program P, GDB will look for a file named ``P-gdb.py`` and automatically read it. Dave Malcolm - contributed a :file:`python-gdb.py` that adds a number of useful - commands when debugging Python itself. For example, there are - ``py-up`` and ``py-down`` that go up or down one Python stack frame, + contributed a :file:`python-gdb.py` that adds a number of + commands useful when debugging Python itself. For example, + ``py-up`` and ``py-down`` go up or down one Python stack frame, which usually corresponds to several C stack frames. ``py-print`` prints the value of a Python variable, and ``py-bt`` prints the Python stack trace. (Added as a result of :issue:`8032`.) @@ -1543,11 +2054,11 @@ * :cfunc:`Py_AddPendingCall` is now thread-safe, letting any worker thread submit notifications to the main Python thread. This is particularly useful for asynchronous IO operations. - (Contributed by Kristjan Valur Jonsson; :issue:`4293`.) + (Contributed by Kristj??n Valur J??nsson; :issue:`4293`.) * New function: :cfunc:`PyCode_NewEmpty` creates an empty code object; only the filename, function name, and first line number are required. - This is useful to extension modules that are attempting to + This is useful for extension modules that are attempting to construct a more useful traceback stack. Previously such extensions needed to call :cfunc:`PyCode_New`, which had many more arguments. (Added by Jeffrey Yasskin.) @@ -1555,7 +2066,7 @@ * New function: :cfunc:`PyErr_NewExceptionWithDoc` creates a new exception class, just as the existing :cfunc:`PyErr_NewException` does, but takes an extra ``char *`` argument containing the docstring for the - new exception class. (Added by the 'lekma' user on the Python bug tracker; + new exception class. (Added by 'lekma' on the Python bug tracker; :issue:`7033`.) * New function: :cfunc:`PyFrame_GetLineNumber` takes a frame object @@ -1576,6 +2087,28 @@ :cfunc:`PyOS_ascii_strtod` and :cfunc:`PyOS_ascii_atof` functions are now deprecated. +* New function: :cfunc:`PySys_SetArgvEx` sets the value of + ``sys.argv`` and can optionally update ``sys.path`` to include the + directory containing the script named by ``sys.argv[0]`` depending + on the value of an *updatepath* parameter. + + This function was added to close a security hole for applications + that embed Python. The old function, :cfunc:`PySys_SetArgv`, would + always update ``sys.path``, and sometimes it would add the current + directory. This meant that, if you ran an application embedding + Python in a directory controlled by someone else, attackers could + put a Trojan-horse module in the directory (say, a file named + :file:`os.py`) that your application would then import and run. + + If you maintain a C/C++ application that embeds Python, check + whether you're calling :cfunc:`PySys_SetArgv` and carefully consider + whether the application should be using :cfunc:`PySys_SetArgvEx` + with *updatepath* set to false. + + Security issue reported as `CVE-2008-5983 + `_; + discussed in :issue:`5753`, and fixed by Antoine Pitrou. + * New macros: the Python header files now define the following macros: :cmacro:`Py_ISALNUM`, :cmacro:`Py_ISALPHA`, @@ -1594,9 +2127,14 @@ .. XXX these macros don't seem to be described in the c-api docs. +* Removed function: :cmacro:`PyEval_CallObject` is now only available + as a macro. A function version was being kept around to preserve + ABI linking compatibility, but that was in 1997; it can certainly be + deleted by now. (Removed by Antoine Pitrou; :issue:`8276`.) + * New format codes: the :cfunc:`PyFormat_FromString`, - :cfunc:`PyFormat_FromStringV`, and :cfunc:`PyErr_Format` now - accepts ``%lld`` and ``%llu`` format codes for displaying values of + :cfunc:`PyFormat_FromStringV`, and :cfunc:`PyErr_Format` functions now + accept ``%lld`` and ``%llu`` format codes for displaying C's :ctype:`long long` types. (Contributed by Mark Dickinson; :issue:`7228`.) @@ -1610,7 +2148,7 @@ ever release the lock, since the other threads weren't replicated, and the child process would no longer be able to perform imports. - Python 2.7 now acquires the import lock before performing an + Python 2.7 acquires the import lock before performing an :func:`os.fork`, and will also clean up any locks created using the :mod:`threading` module. C extension modules that have internal locks, or that call :cfunc:`fork()` themselves, will not benefit @@ -1623,6 +2161,12 @@ being raised when an interpreter shuts down. (Patch by Adam Olsen; :issue:`1722344`.) +* When using the :ctype:`PyMemberDef` structure to define attributes + of a type, Python will no longer let you try to delete or set a + :const:`T_STRING_INPLACE` attribute. + + .. rev 79644 + * Global symbols defined by the :mod:`ctypes` module are now prefixed with ``Py``, or with ``_ctypes``. (Implemented by Thomas Heller; :issue:`3102`.) @@ -1631,15 +2175,15 @@ building the :mod:`pyexpat` module to use the system Expat library. (Contributed by Arfrever Frehtes Taifersar Arahesis; :issue:`7609`.) -* New configure option: compiling Python with the +* New configure option: the :option:`--with-valgrind` option will now disable the pymalloc allocator, which is difficult for the Valgrind memory-error detector to analyze correctly. Valgrind will therefore be better at detecting memory leaks and overruns. (Contributed by James Henstridge; :issue:`2422`.) -* New configure option: you can now supply no arguments to - :option:`--with-dbmliborder=` in order to build none of the various +* New configure option: you can now supply an empty string to + :option:`--with-dbmliborder=` in order to disable all of the various DBM modules. (Added by Arfrever Frehtes Taifersar Arahesis; :issue:`6491`.) @@ -1660,6 +2204,52 @@ Arfrever Frehtes Taifersar Arahesis; :issue:`6094`.) +.. _whatsnew27-capsules: + +Capsules +------------------- + +Python 3.1 adds a new C datatype, :ctype:`PyCapsule`, for providing a +C API to an extension module. A capsule is essentially the holder of +a C ``void *`` pointer, and is made available as a module attribute; for +example, the :mod:`socket` module's API is exposed as ``socket.CAPI``, +and :mod:`unicodedata` exposes ``ucnhash_CAPI``. Other extensions +can import the module, access its dictionary to get the capsule +object, and then get the ``void *`` pointer, which will usually point +to an array of pointers to the module's various API functions. + +There is an existing data type already used for this, +:ctype:`PyCObject`, but it doesn't provide type safety. Evil code +written in pure Python could cause a segmentation fault by taking a +:ctype:`PyCObject` from module A and somehow substituting it for the +:ctype:`PyCObject` in module B. Capsules know their own name, +and getting the pointer requires providing the name:: + + void *vtable; + + if (!PyCapsule_IsValid(capsule, "mymodule.CAPI") { + PyErr_SetString(PyExc_ValueError, "argument type invalid"); + return NULL; + } + + vtable = PyCapsule_GetPointer(capsule, "mymodule.CAPI"); + +You are assured that ``vtable`` points to whatever you're expecting. +If a different capsule was passed in, :cfunc:`PyCapsule_IsValid` would +detect the mismatched name and return false. Refer to +:ref:`using-capsules` for more information on using these objects. + +Python 2.7 now uses capsules internally to provide various +extension-module APIs, but the :cfunc:`PyCObject_AsVoidPtr` was +modified to handle capsules, preserving compile-time compatibility +with the :ctype:`CObject` interface. Use of +:cfunc:`PyCObject_AsVoidPtr` will signal a +:exc:`PendingDeprecationWarning`, which is silent by default. + +Implemented in Python 3.1 and backported to 2.7 by Larry Hastings; +discussed in :issue:`5630`. + + .. ====================================================================== Port-Specific Changes: Windows @@ -1672,16 +2262,24 @@ and :data:`LIBRARIES_ASSEMBLY_NAME_PREFIX`. (Contributed by David Cournapeau; :issue:`4365`.) +* The :mod:`_winreg` module for accessing the registry now implements + the :func:`CreateKeyEx` and :func:`DeleteKeyEx` functions, extended + versions of previously-supported functions that take several extra + arguments. The :func:`DisableReflectionKey`, + :func:`EnableReflectionKey`, and :func:`QueryReflectionKey` were also + tested and documented. + (Implemented by Brian Curtin: :issue:`7347`.) + * The new :cfunc:`_beginthreadex` API is used to start threads, and the native thread-local storage functions are now used. - (Contributed by Kristjan Valur Jonsson; :issue:`3582`.) + (Contributed by Kristj??n Valur J??nsson; :issue:`3582`.) * The :func:`os.kill` function now works on Windows. The signal value can be the constants :const:`CTRL_C_EVENT`, - :const:`CTRL_BREAK_EVENT`, or any integer. The Control-C and - Control-Break keystroke events can be sent to subprocesses; any - other value will use the :cfunc:`TerminateProcess` API. - (Contributed by Miki Tebeka; :issue:`1220212`.) + :const:`CTRL_BREAK_EVENT`, or any integer. The first two constants + will send Control-C and Control-Break keystroke events to + subprocesses; any other value will use the :cfunc:`TerminateProcess` + API. (Contributed by Miki Tebeka; :issue:`1220212`.) * The :func:`os.listdir` function now correctly fails for an empty path. (Fixed by Hirokazu Yamamoto; :issue:`5913`.) @@ -1700,18 +2298,29 @@ installation and a user-installed copy of the same version. (Changed by Ronald Oussoren; :issue:`4865`.) +Port-Specific Changes: FreeBSD +----------------------------------- + +* FreeBSD 7.1's :const:`SO_SETFIB` constant, used with + :func:`~socket.getsockopt`/:func:`~socket.setsockopt` to select an + alternate routing table, is now available in the :mod:`socket` + module. (Added by Kyle VanderBeek; :issue:`8235`.) Other Changes and Fixes ======================= * Two benchmark scripts, :file:`iobench` and :file:`ccbench`, were added to the :file:`Tools` directory. :file:`iobench` measures the - speed of built-in file I/O objects (as returned by :func:`open`) + speed of the built-in file I/O objects returned by :func:`open` while performing various operations, and :file:`ccbench` is a concurrency benchmark that tries to measure computing throughput, thread switching latency, and IO processing bandwidth when performing several tasks using a varying number of threads. +* The :file:`Tools/i18n/msgfmt.py` script now understands plural + forms in :file:`.po` files. (Fixed by Martin von L??wis; + :issue:`5464`.) + * When importing a module from a :file:`.pyc` or :file:`.pyo` file with an existing :file:`.py` counterpart, the :attr:`co_filename` attributes of the resulting code objects are overwritten when the @@ -1747,14 +2356,13 @@ This section lists previously described changes and other bugfixes that may require changes to your code: -* When using :class:`Decimal` instances with a string's - :meth:`format` method, the default alignment was previously - left-alignment. This has been changed to right-alignment, which might - change the output of your programs. - (Changed by Mark Dickinson; :issue:`6857`.) +* The :func:`range` function processes its arguments more + consistently; it will now call :meth:`__int__` on non-float, + non-integer arguments that are supplied to it. (Fixed by Alexander + Belopolsky; :issue:`1533`.) - Another :meth:`format`-related change: the default precision used - for floating-point and complex numbers was changed from 6 decimal +* The string :meth:`format` method changed the default precision used + for floating-point and complex numbers from 6 decimal places to 12, which matches the precision used by :func:`str`. (Changed by Eric Smith; :issue:`5920`.) @@ -1764,18 +2372,79 @@ affects new-style classes (derived from :class:`object`) and C extension types. (:issue:`6101`.) -* The :meth:`readline` method of :class:`StringIO` objects now does - nothing when a negative length is requested, as other file-like - objects do. (:issue:`7348`). +* Due to a bug in Python 2.6, the *exc_value* parameter to + :meth:`__exit__` methods was often the string representation of the + exception, not an instance. This was fixed in 2.7, so *exc_value* + will be an instance as expected. (Fixed by Florent Xicluna; + :issue:`7853`.) + +* When a restricted set of attributes were set using ``__slots__``, + deleting an unset attribute would not raise :exc:`AttributeError` + as you would expect. Fixed by Benjamin Peterson; :issue:`7604`.) In the standard library: +* Operations with :class:`datetime` instances that resulted in a year + falling outside the supported range didn't always raise + :exc:`OverflowError`. Such errors are now checked more carefully + and will now raise the exception. (Reported by Mark Leander, patch + by Anand B. Pillai and Alexander Belopolsky; :issue:`7150`.) + +* When using :class:`Decimal` instances with a string's + :meth:`format` method, the default alignment was previously + left-alignment. This has been changed to right-alignment, which might + change the output of your programs. + (Changed by Mark Dickinson; :issue:`6857`.) + + Comparisons involving a signaling NaN value (or ``sNAN``) now signal + :const:`InvalidOperation` instead of silently returning a true or + false value depending on the comparison operator. Quiet NaN values + (or ``NaN``) are now hashable. (Fixed by Mark Dickinson; + :issue:`7279`.) + * The ElementTree library, :mod:`xml.etree`, no longer escapes ampersands and angle brackets when outputting an XML processing instruction (which looks like ``) or comment (which looks like ``). (Patch by Neil Muller; :issue:`2746`.) +* The :meth:`readline` method of :class:`StringIO` objects now does + nothing when a negative length is requested, as other file-like + objects do. (:issue:`7348`). + +* The :mod:`syslog` module will now use the value of ``sys.argv[0]`` as the + identifier instead of the previous default value of ``'python'``. + (Changed by Sean Reifschneider; :issue:`8451`.) + +* The :mod:`tarfile` module's default error handling has changed, to + no longer suppress fatal errors. The default error level was previously 0, + which meant that errors would only result in a message being written to the + debug log, but because the debug log is not activated by default, + these errors go unnoticed. The default error level is now 1, + which raises an exception if there's an error. + (Changed by Lars Gust??bel; :issue:`7357`.) + +* The :mod:`urlparse` module's :func:`~urlparse.urlsplit` now handles + unknown URL schemes in a fashion compliant with :rfc:`3986`: if the + URL is of the form ``"://..."``, the text before the + ``://`` is treated as the scheme, even if it's a made-up scheme that + the module doesn't know about. This change may break code that + worked around the old behaviour. For example, Python 2.6.4 or 2.5 + will return the following: + + >>> import urlparse + >>> urlparse.urlsplit('invented://host/filename?query') + ('invented', '', '//host/filename?query', '', '') + + Python 2.7 (and Python 2.6.5) will return: + + >>> import urlparse + >>> urlparse.urlsplit('invented://host/filename?query') + ('invented', 'host', '/filename?query', '', '') + + (Python 2.7 actually produces slightly different output, since it + returns a named tuple instead of a standard tuple.) + For C extensions: * C extensions that use integer format codes with the ``PyArg_Parse*`` @@ -1786,6 +2455,14 @@ :cfunc:`PyOS_ascii_strtod` and :cfunc:`PyOS_ascii_atof` functions, which are now deprecated. +For applications that embed Python: + +* The :cfunc:`PySys_SetArgvEx` function was added, letting + applications close a security hole when the existing + :cfunc:`PySys_SetArgv` function was used. Check whether you're + calling :cfunc:`PySys_SetArgv` and carefully consider whether the + application should be using :cfunc:`PySys_SetArgvEx` with + *updatepath* set to false. .. ====================================================================== @@ -1797,5 +2474,6 @@ The author would like to thank the following people for offering suggestions, corrections and assistance with various drafts of this -article: Ryan Lovett, R. David Murray, Hugh Secker-Walker. +article: Nick Coghlan, Philip Jenvey, Ryan Lovett, R. David Murray, +Hugh Secker-Walker. Modified: python/branches/py3k-dtoa/Doc/whatsnew/3.0.rst ============================================================================== --- python/branches/py3k-dtoa/Doc/whatsnew/3.0.rst (original) +++ python/branches/py3k-dtoa/Doc/whatsnew/3.0.rst Tue Jul 6 17:55:27 2010 @@ -798,6 +798,15 @@ * A new built-in function :func:`next` was added to call the :meth:`__next__` method on an object. +* The :func:`round` function rounding strategy and return type have + changed. Exact halfway cases are now rounded to the nearest even + result instead of away from zero. (For example, ``round(2.5)`` now + returns ``2`` rather than ``3``.) :func:`round(x[, n])` now + delegates to ``x.__round__([n])`` instead of always returning a + float. It generally returns an integer when called with a single + argument and a value of the same type as ``x`` when called with two + arguments. + * Moved :func:`intern` to :func:`sys.intern`. * Removed: :func:`apply`. Instead of ``apply(f, args)`` use Modified: python/branches/py3k-dtoa/Doc/whatsnew/3.2.rst ============================================================================== --- python/branches/py3k-dtoa/Doc/whatsnew/3.2.rst (original) +++ python/branches/py3k-dtoa/Doc/whatsnew/3.2.rst Tue Jul 6 17:55:27 2010 @@ -173,7 +173,8 @@ * bytearray objects cannot be used anymore as filenames: convert them to bytes -* "t#" format of PyArg_Parse*() functions has been removed: use "s#" or "s*" - instead +* PyArg_Parse*() functions: + + * "t#" format has been removed: use "s#" or "s*" instead + * "w" and "w#" formats has been removed: use "w*" instead -* Stub Modified: python/branches/py3k-dtoa/Grammar/Grammar ============================================================================== --- python/branches/py3k-dtoa/Grammar/Grammar (original) +++ python/branches/py3k-dtoa/Grammar/Grammar Tue Jul 6 17:55:27 2010 @@ -11,9 +11,9 @@ # "How to Change Python's Grammar" # Start symbols for the grammar: -# single_input is a single interactive statement; -# file_input is a module or sequence of commands read from an input file; -# eval_input is the input for the eval() and input() functions. +# single_input is a single interactive statement; +# file_input is a module or sequence of commands read from an input file; +# eval_input is the input for the eval() and input() functions. # NB: compound_stmt in single_input is followed by extra NEWLINE! single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE file_input: (NEWLINE | stmt)* ENDMARKER @@ -71,9 +71,9 @@ for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite] try_stmt: ('try' ':' suite ((except_clause ':' suite)+ - ['else' ':' suite] - ['finally' ':' suite] | - 'finally' ':' suite)) + ['else' ':' suite] + ['finally' ':' suite] | + 'finally' ':' suite)) with_stmt: 'with' with_item (',' with_item)* ':' suite with_item: test ['as' expr] # NB compile.c makes sure that the default except clause is last Modified: python/branches/py3k-dtoa/Include/longobject.h ============================================================================== --- python/branches/py3k-dtoa/Include/longobject.h (original) +++ python/branches/py3k-dtoa/Include/longobject.h Tue Jul 6 17:55:27 2010 @@ -58,7 +58,7 @@ #error "sizeof(pid_t) is neither sizeof(int), sizeof(long) or sizeof(long long)" #endif /* SIZEOF_PID_T */ -/* For use by intobject.c only */ +/* Used by Python/mystrtoul.c. */ PyAPI_DATA(unsigned char) _PyLong_DigitValue[256]; /* _PyLong_Frexp returns a double x and an exponent e such that the Modified: python/branches/py3k-dtoa/Include/pyctype.h ============================================================================== --- python/branches/py3k-dtoa/Include/pyctype.h (original) +++ python/branches/py3k-dtoa/Include/pyctype.h Tue Jul 6 17:55:27 2010 @@ -11,6 +11,9 @@ extern const unsigned int _Py_ctype_table[256]; +/* Unlike their C counterparts, the following macros are not meant to + * handle an int with any of the values [EOF, 0-UCHAR_MAX]. The argument + * must be a signed/unsigned char. */ #define Py_ISLOWER(c) (_Py_ctype_table[Py_CHARMASK(c)] & PY_CTF_LOWER) #define Py_ISUPPER(c) (_Py_ctype_table[Py_CHARMASK(c)] & PY_CTF_UPPER) #define Py_ISALPHA(c) (_Py_ctype_table[Py_CHARMASK(c)] & PY_CTF_ALPHA) Modified: python/branches/py3k-dtoa/Include/traceback.h ============================================================================== --- python/branches/py3k-dtoa/Include/traceback.h (original) +++ python/branches/py3k-dtoa/Include/traceback.h Tue Jul 6 17:55:27 2010 @@ -10,16 +10,16 @@ /* Traceback interface */ typedef struct _traceback { - PyObject_HEAD - struct _traceback *tb_next; - struct _frame *tb_frame; - int tb_lasti; - int tb_lineno; + PyObject_HEAD + struct _traceback *tb_next; + struct _frame *tb_frame; + int tb_lasti; + int tb_lineno; } PyTracebackObject; PyAPI_FUNC(int) PyTraceBack_Here(struct _frame *); PyAPI_FUNC(int) PyTraceBack_Print(PyObject *, PyObject *); -PyAPI_FUNC(int) _Py_DisplaySourceLine(PyObject *, const char *, int, int); +PyAPI_FUNC(int) _Py_DisplaySourceLine(PyObject *, PyObject *, int, int); /* Reveal traceback type so we can typecheck traceback objects */ PyAPI_DATA(PyTypeObject) PyTraceBack_Type; Modified: python/branches/py3k-dtoa/Include/unicodeobject.h ============================================================================== --- python/branches/py3k-dtoa/Include/unicodeobject.h (original) +++ python/branches/py3k-dtoa/Include/unicodeobject.h Tue Jul 6 17:55:27 2010 @@ -498,14 +498,14 @@ Py_ssize_t size /* size of buffer */ ); -/* Similar to PyUnicode_FromUnicode(), but u points to Latin-1 encoded bytes */ +/* Similar to PyUnicode_FromUnicode(), but u points to UTF-8 encoded bytes */ PyAPI_FUNC(PyObject*) PyUnicode_FromStringAndSize( const char *u, /* char buffer */ Py_ssize_t size /* size of buffer */ ); /* Similar to PyUnicode_FromUnicode(), but u points to null-terminated - Latin-1 encoded bytes */ + UTF-8 encoded bytes */ PyAPI_FUNC(PyObject*) PyUnicode_FromString( const char *u /* string */ ); @@ -550,7 +550,7 @@ Coercion is done in the following way: - 1. String and other char buffer compatible objects are decoded + 1. bytes, bytearray and other char buffer compatible objects are decoded under the assumptions that they contain data using the current default encoding. Decoding is done in "strict" mode. @@ -574,7 +574,7 @@ Unicode objects are passed back as-is (subclasses are converted to true Unicode objects), all other objects are delegated to PyUnicode_FromEncodedObject(obj, NULL, "strict") which results in - using the default encoding as basis for decoding the object. + using UTF-8 encoding as basis for decoding the object. The API returns NULL in case of an error. The caller is responsible for decref'ing the returned objects. @@ -606,7 +606,7 @@ #ifdef HAVE_WCHAR_H -/* Create a Unicode Object from the whcar_t buffer w of the given +/* Create a Unicode Object from the wchar_t buffer w of the given size. The buffer is copied into the new object. */ @@ -665,7 +665,7 @@ parameters encoding and errors have the same semantics as the ones of the builtin unicode() API. - Setting encoding to NULL causes the default encoding to be used. + Setting encoding to NULL causes the default encoding (UTF-8) to be used. Error handling is set by errors which may also be set to NULL meaning to use the default handling defined for the codec. Default Modified: python/branches/py3k-dtoa/Lib/_strptime.py ============================================================================== --- python/branches/py3k-dtoa/Lib/_strptime.py (original) +++ python/branches/py3k-dtoa/Lib/_strptime.py Tue Jul 6 17:55:27 2010 @@ -16,7 +16,9 @@ from re import compile as re_compile from re import IGNORECASE, ASCII from re import escape as re_escape -from datetime import date as datetime_date +from datetime import (date as datetime_date, + timedelta as datetime_timedelta, + timezone as datetime_timezone) try: from _thread import allocate_lock as _thread_allocate_lock except: @@ -204,6 +206,7 @@ #XXX: Does 'Y' need to worry about having less or more than # 4 digits? 'Y': r"(?P\d\d\d\d)", + 'z': r"(?P[+-]\d\d[0-5]\d)", 'A': self.__seqToRE(self.locale_time.f_weekday, 'A'), 'a': self.__seqToRE(self.locale_time.a_weekday, 'a'), 'B': self.__seqToRE(self.locale_time.f_month[1:], 'B'), @@ -293,7 +296,9 @@ def _strptime(data_string, format="%a %b %d %H:%M:%S %Y"): - """Return a time struct based on the input string and the format string.""" + """Return a 2-tuple consisting of a time struct and an int containing + the number of microseconds based on the input string and the + format string.""" for index, arg in enumerate([data_string, format]): if not isinstance(arg, str): @@ -333,10 +338,12 @@ if len(data_string) != found.end(): raise ValueError("unconverted data remains: %s" % data_string[found.end():]) + year = 1900 month = day = 1 hour = minute = second = fraction = 0 tz = -1 + tzoffset = None # Default to -1 to signify that values not known; not critical to have, # though week_of_year = -1 @@ -417,6 +424,11 @@ else: # W starts week on Monday. week_of_year_start = 0 + elif group_key == 'z': + z = found_dict['z'] + tzoffset = int(z[1:3]) * 60 + int(z[3:5]) + if z.startswith("-"): + tzoffset = -tzoffset elif group_key == 'Z': # Since -1 is default value only need to worry about setting tz if # it can be something other than -1. @@ -453,9 +465,35 @@ day = datetime_result.day if weekday == -1: weekday = datetime_date(year, month, day).weekday() - return (time.struct_time((year, month, day, - hour, minute, second, - weekday, julian, tz)), fraction) + # Add timezone info + tzname = found_dict.get("Z") + if tzoffset is not None: + gmtoff = tzoffset * 60 + else: + gmtoff = None + + return (year, month, day, + hour, minute, second, + weekday, julian, tz, gmtoff, tzname), fraction def _strptime_time(data_string, format="%a %b %d %H:%M:%S %Y"): - return _strptime(data_string, format)[0] + """Return a time struct based on the input string and the + format string.""" + tt = _strptime(data_string, format)[0] + return time.struct_time(tt[:9]) + +def _strptime_datetime(class_, data_string, format="%a %b %d %H:%M:%S %Y"): + """Return a class_ instance based on the input string and the + format string.""" + tt, fraction = _strptime(data_string, format) + gmtoff, tzname = tt[-2:] + args = tt[:6] + (fraction,) + if gmtoff is not None: + tzdelta = datetime_timedelta(seconds=gmtoff) + if tzname: + tz = datetime_timezone(tzdelta, tzname) + else: + tz = datetime_timezone(tzdelta) + args += (tz,) + + return class_(*args) Modified: python/branches/py3k-dtoa/Lib/contextlib.py ============================================================================== --- python/branches/py3k-dtoa/Lib/contextlib.py (original) +++ python/branches/py3k-dtoa/Lib/contextlib.py Tue Jul 6 17:55:27 2010 @@ -4,9 +4,20 @@ from functools import wraps from warnings import warn -__all__ = ["contextmanager", "closing"] +__all__ = ["contextmanager", "closing", "ContextDecorator"] -class GeneratorContextManager(object): + +class ContextDecorator(object): + "A base class or mixin that enables context managers to work as decorators." + def __call__(self, func): + @wraps(func) + def inner(*args, **kwds): + with self: + return func(*args, **kwds) + return inner + + +class GeneratorContextManager(ContextDecorator): """Helper for @contextmanager decorator.""" def __init__(self, gen): Modified: python/branches/py3k-dtoa/Lib/ctypes/__init__.py ============================================================================== --- python/branches/py3k-dtoa/Lib/ctypes/__init__.py (original) +++ python/branches/py3k-dtoa/Lib/ctypes/__init__.py Tue Jul 6 17:55:27 2010 @@ -265,7 +265,7 @@ pass else: if _os.name in ("nt", "ce"): - set_conversion_mode("mbcs", "ignore") + set_conversion_mode("mbcs", "strict") else: set_conversion_mode("ascii", "strict") Modified: python/branches/py3k-dtoa/Lib/ctypes/test/test_callbacks.py ============================================================================== --- python/branches/py3k-dtoa/Lib/ctypes/test/test_callbacks.py (original) +++ python/branches/py3k-dtoa/Lib/ctypes/test/test_callbacks.py Tue Jul 6 17:55:27 2010 @@ -166,6 +166,41 @@ self.assertTrue(diff < 0.01, "%s not less than 0.01" % diff) + def test_issue_8959_a(self): + from ctypes.util import find_library + libc_path = find_library("c") + if not libc_path: + return # cannot test + libc = CDLL(libc_path) + + @CFUNCTYPE(c_int, POINTER(c_int), POINTER(c_int)) + def cmp_func(a, b): + return a[0] - b[0] + + array = (c_int * 5)(5, 1, 99, 7, 33) + + libc.qsort(array, len(array), sizeof(c_int), cmp_func) + self.assertEqual(array[:], [1, 5, 7, 33, 99]) + + try: + WINFUNCTYPE + except NameError: + pass + else: + def test_issue_8959_b(self): + from ctypes.wintypes import BOOL, HWND, LPARAM + global windowCount + windowCount = 0 + + @WINFUNCTYPE(BOOL, HWND, LPARAM) + def EnumWindowsCallbackFunc(hwnd, lParam): + global windowCount + windowCount += 1 + return True #Allow windows to keep enumerating + + windll.user32.EnumWindows(EnumWindowsCallbackFunc, 0) + self.assertFalse(windowCount == 0) + ################################################################ if __name__ == '__main__': Modified: python/branches/py3k-dtoa/Lib/ctypes/test/test_win32.py ============================================================================== --- python/branches/py3k-dtoa/Lib/ctypes/test/test_win32.py (original) +++ python/branches/py3k-dtoa/Lib/ctypes/test/test_win32.py Tue Jul 6 17:55:27 2010 @@ -6,6 +6,32 @@ import _ctypes_test +if sys.platform == "win32" and sizeof(c_void_p) == sizeof(c_int): + # Only windows 32-bit has different calling conventions. + + class WindowsTestCase(unittest.TestCase): + def test_callconv_1(self): + # Testing stdcall function + + IsWindow = windll.user32.IsWindow + # ValueError: Procedure probably called with not enough arguments (4 bytes missing) + self.assertRaises(ValueError, IsWindow) + + # This one should succeeed... + self.assertEqual(0, IsWindow(0)) + + # ValueError: Procedure probably called with too many arguments (8 bytes in excess) + self.assertRaises(ValueError, IsWindow, 0, 0, 0) + + def test_callconv_2(self): + # Calling stdcall function as cdecl + + IsWindow = cdll.user32.IsWindow + + # ValueError: Procedure called with not enough arguments (4 bytes missing) + # or wrong calling convention + self.assertRaises(ValueError, IsWindow, None) + if sys.platform == "win32": class FunctionCallTestCase(unittest.TestCase): Modified: python/branches/py3k-dtoa/Lib/dis.py ============================================================================== --- python/branches/py3k-dtoa/Lib/dis.py (original) +++ python/branches/py3k-dtoa/Lib/dis.py Tue Jul 6 17:55:27 2010 @@ -12,6 +12,22 @@ _have_code = (types.MethodType, types.FunctionType, types.CodeType, type) +def _try_compile(source, name): + """Attempts to compile the given source, first as an expression and + then as a statement if the first approach fails. + + Utility function to accept strings in functions that otherwise + expect code objects + """ + # ncoghlan: currently only used by dis(), but plan to add an + # equivalent for show_code() as well (but one that returns a + # string rather than printing directly to the console) + try: + c = compile(source, name, 'eval') + except SyntaxError: + c = compile(source, name, 'exec') + return c + def dis(x=None): """Disassemble classes, methods, functions, or code. @@ -38,7 +54,9 @@ elif hasattr(x, 'co_code'): disassemble(x) elif isinstance(x, (bytes, bytearray)): - disassemble_string(x) + _disassemble_bytes(x) + elif isinstance(x, str): + _disassemble_str(x) else: raise TypeError("don't know how to disassemble %s objects" % type(x).__name__) @@ -157,7 +175,7 @@ print('(' + free[oparg] + ')', end=' ') print() -def disassemble_string(code, lasti=-1, varnames=None, names=None, +def _disassemble_bytes(code, lasti=-1, varnames=None, names=None, constants=None): labels = findlabels(code) n = len(code) @@ -196,6 +214,10 @@ print('(' + cmp_op[oparg] + ')', end=' ') print() +def _disassemble_str(source): + """Compile the source string, then disassemble the code object.""" + disassemble(_try_compile(source, '')) + disco = disassemble # XXX For backwards compatibility def findlabels(code): Modified: python/branches/py3k-dtoa/Lib/distutils/msvc9compiler.py ============================================================================== --- python/branches/py3k-dtoa/Lib/distutils/msvc9compiler.py (original) +++ python/branches/py3k-dtoa/Lib/distutils/msvc9compiler.py Tue Jul 6 17:55:27 2010 @@ -37,9 +37,18 @@ winreg.HKEY_LOCAL_MACHINE, winreg.HKEY_CLASSES_ROOT) -VS_BASE = r"Software\Microsoft\VisualStudio\%0.1f" -WINSDK_BASE = r"Software\Microsoft\Microsoft SDKs\Windows" -NET_BASE = r"Software\Microsoft\.NETFramework" +NATIVE_WIN64 = (sys.platform == 'win32' and sys.maxsize > 2**32) +if NATIVE_WIN64: + # Visual C++ is a 32-bit application, so we need to look in + # the corresponding registry branch, if we're running a + # 64-bit Python on Win64 + VS_BASE = r"Software\Wow6432Node\Microsoft\VisualStudio\%0.1f" + WINSDK_BASE = r"Software\Wow6432Node\Microsoft\Microsoft SDKs\Windows" + NET_BASE = r"Software\Wow6432Node\Microsoft\.NETFramework" +else: + VS_BASE = r"Software\Microsoft\VisualStudio\%0.1f" + WINSDK_BASE = r"Software\Microsoft\Microsoft SDKs\Windows" + NET_BASE = r"Software\Microsoft\.NETFramework" # A map keyed by get_platform() return values to values accepted by # 'vcvarsall.bat'. Note a cross-compile may combine these (eg, 'x86_amd64' is Modified: python/branches/py3k-dtoa/Lib/distutils/unixccompiler.py ============================================================================== --- python/branches/py3k-dtoa/Lib/distutils/unixccompiler.py (original) +++ python/branches/py3k-dtoa/Lib/distutils/unixccompiler.py Tue Jul 6 17:55:27 2010 @@ -340,7 +340,9 @@ static = os.path.join(dir, static_f) if sys.platform == 'darwin' and ( - dir.startswith('/System/') or dir.startswith('/usr/')): + dir.startswith('/System/') or ( + dir.startswith('/usr/') and not dir.startswith('/usr/local/'))): + shared = os.path.join(sysroot, dir[1:], shared_f) dylib = os.path.join(sysroot, dir[1:], dylib_f) static = os.path.join(sysroot, dir[1:], static_f) Modified: python/branches/py3k-dtoa/Lib/encodings/aliases.py ============================================================================== --- python/branches/py3k-dtoa/Lib/encodings/aliases.py (original) +++ python/branches/py3k-dtoa/Lib/encodings/aliases.py Tue Jul 6 17:55:27 2010 @@ -146,6 +146,11 @@ 'csibm857' : 'cp857', 'ibm857' : 'cp857', + # cp858 codec + '858' : 'cp858', + 'csibm858' : 'cp858', + 'ibm858' : 'cp858', + # cp860 codec '860' : 'cp860', 'csibm860' : 'cp860', Modified: python/branches/py3k-dtoa/Lib/heapq.py ============================================================================== --- python/branches/py3k-dtoa/Lib/heapq.py (original) +++ python/branches/py3k-dtoa/Lib/heapq.py Tue Jul 6 17:55:27 2010 @@ -1,5 +1,3 @@ -# -*- coding: latin-1 -*- - """Heap queue algorithm (a.k.a. priority queue). Heaps are arrays for which a[k] <= a[2*k+1] and a[k] <= a[2*k+2] for @@ -34,7 +32,7 @@ __about__ = """Heap queues -[explanation by Fran?ois Pinard] +[explanation by Fran??ois Pinard] Heaps are arrays for which a[k] <= a[2*k+1] and a[k] <= a[2*k+2] for all k, counting elements from 0. For the sake of comparison, Modified: python/branches/py3k-dtoa/Lib/http/cookiejar.py ============================================================================== --- python/branches/py3k-dtoa/Lib/http/cookiejar.py (original) +++ python/branches/py3k-dtoa/Lib/http/cookiejar.py Tue Jul 6 17:55:27 2010 @@ -436,6 +436,13 @@ if attr: headers.append("; ".join(attr)) return ", ".join(headers) +def strip_quotes(text): + if text.startswith('"'): + text = text[1:] + if text.endswith('"'): + text = text[:-1] + return text + def parse_ns_headers(ns_headers): """Ad-hoc parser for Netscape protocol cookie-attributes. @@ -453,7 +460,7 @@ """ known_attrs = ("expires", "domain", "path", "secure", # RFC 2109 attrs (may turn up in Netscape cookies, too) - "port", "max-age") + "version", "port", "max-age") result = [] for ns_header in ns_headers: @@ -473,12 +480,11 @@ k = lc if k == "version": # This is an RFC 2109 cookie. + v = strip_quotes(v) version_set = True if k == "expires": # convert expires date to seconds since epoch - if v.startswith('"'): v = v[1:] - if v.endswith('"'): v = v[:-1] - v = http2time(v) # None if invalid + v = http2time(strip_quotes(v)) # None if invalid pairs.append((k, v)) if pairs: @@ -1446,7 +1452,11 @@ # set the easy defaults version = standard.get("version", None) - if version is not None: version = int(version) + if version is not None: + try: + version = int(version) + except ValueError: + return None # invalid version, ignore cookie secure = standard.get("secure", False) # (discard is also set if expires is Absent) discard = standard.get("discard", False) Modified: python/branches/py3k-dtoa/Lib/idlelib/textView.py ============================================================================== --- python/branches/py3k-dtoa/Lib/idlelib/textView.py (original) +++ python/branches/py3k-dtoa/Lib/idlelib/textView.py Tue Jul 6 17:55:27 2010 @@ -62,11 +62,7 @@ def view_file(parent, title, filename, encoding=None): try: - if encoding: - import codecs - textFile = codecs.open(filename, 'r') - else: - textFile = open(filename, 'r') + textFile = open(filename, 'r', encoding=encoding) except IOError: import tkinter.messagebox as tkMessageBox tkMessageBox.showerror(title='File Load Error', Modified: python/branches/py3k-dtoa/Lib/importlib/__init__.py ============================================================================== --- python/branches/py3k-dtoa/Lib/importlib/__init__.py (original) +++ python/branches/py3k-dtoa/Lib/importlib/__init__.py Tue Jul 6 17:55:27 2010 @@ -36,7 +36,7 @@ """ if 'PYTHONCASEOK' in os.environ: return True - elif check in os.listdir(directory): + elif check in os.listdir(directory if directory else os.getcwd()): return True return False Modified: python/branches/py3k-dtoa/Lib/importlib/_bootstrap.py ============================================================================== --- python/branches/py3k-dtoa/Lib/importlib/_bootstrap.py (original) +++ python/branches/py3k-dtoa/Lib/importlib/_bootstrap.py Tue Jul 6 17:55:27 2010 @@ -22,7 +22,7 @@ def _path_join(*args): """Replacement for os.path.join.""" return path_sep.join(x[:-len(path_sep)] if x.endswith(path_sep) else x - for x in args) + for x in args if x) def _path_exists(path): @@ -53,6 +53,8 @@ # XXX Could also expose Modules/getpath.c:isdir() def _path_isdir(path): """Replacement for os.path.isdir.""" + if not path: + path = _os.getcwd() return _path_is_mode_type(path, 0o040000) @@ -99,6 +101,8 @@ new.__dict__.update(old.__dict__) +code_type = type(_wrap.__code__) + # Finder/loader utility code ################################################## def set_package(fxn): @@ -138,7 +142,7 @@ the second argument. """ - def decorated(self, fullname): + def decorated(self, fullname, *args, **kwargs): module = sys.modules.get(fullname) is_reload = bool(module) if not is_reload: @@ -148,7 +152,7 @@ module = imp.new_module(fullname) sys.modules[fullname] = module try: - return fxn(self, module) + return fxn(self, module, *args, **kwargs) except: if not is_reload: del sys.modules[fullname] @@ -301,258 +305,227 @@ return imp.is_frozen_package(fullname) -class PyLoader: +class _LoaderBasics: - """Loader base class for Python source code. + """Base class of common code needed by both SourceLoader and + _SourcelessFileLoader.""" - Subclasses need to implement the methods: + def is_package(self, fullname): + """Concrete implementation of InspectLoader.is_package by checking if + the path returned by get_filename has a filename of '__init__.py'.""" + filename = self.get_filename(fullname).rpartition(path_sep)[2] + return filename.rsplit('.', 1)[0] == '__init__' + + def _bytes_from_bytecode(self, fullname, data, source_mtime): + """Return the marshalled bytes from bytecode, verifying the magic + number and timestamp alon the way. - - source_path - - get_data - - is_package + If source_mtime is None then skip the timestamp check. - """ + """ + magic = data[:4] + raw_timestamp = data[4:8] + if len(magic) != 4 or magic != imp.get_magic(): + raise ImportError("bad magic number in {}".format(fullname)) + elif len(raw_timestamp) != 4: + raise EOFError("bad timestamp in {}".format(fullname)) + elif source_mtime is not None: + if marshal._r_long(raw_timestamp) != source_mtime: + raise ImportError("bytecode is stale for {}".format(fullname)) + # Can't return the code object as errors from marshal loading need to + # propagate even when source is available. + return data[8:] @module_for_loader - def load_module(self, module): - """Initialize the module.""" + def _load_module(self, module, *, sourceless=False): + """Helper for load_module able to handle either source or sourceless + loading.""" name = module.__name__ - code_object = self.get_code(module.__name__) + code_object = self.get_code(name) module.__file__ = self.get_filename(name) + if not sourceless: + module.__cached__ = imp.cache_from_source(module.__file__) + else: + module.__cached__ = module.__file__ + module.__package__ = name if self.is_package(name): - module.__path__ = [module.__file__.rsplit(path_sep, 1)[0]] - module.__package__ = module.__name__ - if not hasattr(module, '__path__'): + module.__path__ = [module.__file__.rsplit(path_sep, 1)[0]] + else: module.__package__ = module.__package__.rpartition('.')[0] module.__loader__ = self exec(code_object, module.__dict__) return module - def get_filename(self, fullname): - """Return the path to the source file, else raise ImportError.""" - path = self.source_path(fullname) - if path is not None: - return path - else: - raise ImportError("no source path available for " - "{0!r}".format(fullname)) - def get_code(self, fullname): - """Get a code object from source.""" - source_path = self.source_path(fullname) - if source_path is None: - message = "a source path must exist to load {0}".format(fullname) - raise ImportError(message) - source = self.get_data(source_path) - return compile(source, source_path, 'exec', dont_inherit=True) +class SourceLoader(_LoaderBasics): - # Never use in implementing import! Imports code within the method. - def get_source(self, fullname): - """Return the source code for a module. + def path_mtime(self, path:str) -> int: + """Optional method that returns the modification time for the specified + path. - self.source_path() and self.get_data() are used to implement this - method. + Implementing this method allows the loader to read bytecode files. """ - path = self.source_path(fullname) - if path is None: - return None - try: - source_bytes = self.get_data(path) - except IOError: - return ImportError("source not available through get_data()") - import io - import tokenize - encoding = tokenize.detect_encoding(io.BytesIO(source_bytes).readline) - return source_bytes.decode(encoding[0]) + raise NotImplementedError + def set_data(self, path:str, data:bytes) -> None: + """Optional method which writes data to a file path. -class PyPycLoader(PyLoader): + Implementing this method allows for the writing of bytecode files. - """Loader base class for Python source and bytecode. + """ + raise NotImplementedError - Requires implementing the methods needed for PyLoader as well as - source_mtime, bytecode_path, and write_bytecode. - """ - - def get_filename(self, fullname): - """Return the source or bytecode file path.""" - path = self.source_path(fullname) - if path is not None: - return path - path = self.bytecode_path(fullname) - if path is not None: - return path - raise ImportError("no source or bytecode path available for " - "{0!r}".format(fullname)) + def get_source(self, fullname): + """Concrete implementation of InspectLoader.get_source.""" + import tokenize + path = self.get_filename(fullname) + try: + source_bytes = self.get_data(path) + except IOError: + raise ImportError("source not available through get_data()") + encoding = tokenize.detect_encoding(_io.BytesIO(source_bytes).readline) + newline_decoder = _io.IncrementalNewlineDecoder(None, True) + return newline_decoder.decode(source_bytes.decode(encoding[0])) def get_code(self, fullname): - """Get a code object from source or bytecode.""" - # XXX Care enough to make sure this call does not happen if the magic - # number is bad? - source_timestamp = self.source_mtime(fullname) - # Try to use bytecode if it is available. - bytecode_path = self.bytecode_path(fullname) - if bytecode_path: - data = self.get_data(bytecode_path) + """Concrete implementation of InspectLoader.get_code. + + Reading of bytecode requires path_mtime to be implemented. To write + bytecode, set_data must also be implemented. + + """ + source_path = self.get_filename(fullname) + bytecode_path = imp.cache_from_source(source_path) + source_mtime = None + if bytecode_path is not None: try: - magic = data[:4] - if len(magic) < 4: - raise ImportError("bad magic number in {}".format(fullname)) - raw_timestamp = data[4:8] - if len(raw_timestamp) < 4: - raise EOFError("bad timestamp in {}".format(fullname)) - pyc_timestamp = marshal._r_long(raw_timestamp) - bytecode = data[8:] - # Verify that the magic number is valid. - if imp.get_magic() != magic: - raise ImportError("bad magic number in {}".format(fullname)) - # Verify that the bytecode is not stale (only matters when - # there is source to fall back on. - if source_timestamp: - if pyc_timestamp < source_timestamp: - raise ImportError("bytecode is stale") - except (ImportError, EOFError): - # If source is available give it a shot. - if source_timestamp is not None: + source_mtime = self.path_mtime(source_path) + except NotImplementedError: + pass + else: + try: + data = self.get_data(bytecode_path) + except IOError: pass else: - raise - else: - # Bytecode seems fine, so try to use it. - # XXX If the bytecode is ill-formed, would it be beneficial to - # try for using source if available and issue a warning? - return marshal.loads(bytecode) - elif source_timestamp is None: - raise ImportError("no source or bytecode available to create code " - "object for {0!r}".format(fullname)) - # Use the source. - code_object = super().get_code(fullname) - # Generate bytecode and write it out. - if not sys.dont_write_bytecode: + try: + bytes_data = self._bytes_from_bytecode(fullname, data, + source_mtime) + except (ImportError, EOFError): + pass + else: + found = marshal.loads(bytes_data) + if isinstance(found, code_type): + return found + else: + msg = "Non-code object in {}" + raise ImportError(msg.format(bytecode_path)) + source_bytes = self.get_data(source_path) + code_object = compile(source_bytes, source_path, 'exec', + dont_inherit=True) + if (not sys.dont_write_bytecode and bytecode_path is not None and + source_mtime is not None): + # If e.g. Jython ever implements imp.cache_from_source to have + # their own cached file format, this block of code will most likely + # throw an exception. data = bytearray(imp.get_magic()) - data.extend(marshal._w_long(source_timestamp)) + data.extend(marshal._w_long(source_mtime)) data.extend(marshal.dumps(code_object)) - self.write_bytecode(fullname, data) + try: + self.set_data(bytecode_path, data) + except NotImplementedError: + pass return code_object + def load_module(self, fullname): + """Concrete implementation of Loader.load_module. -class _PyFileLoader(PyLoader): + Requires ExecutionLoader.get_filename and ResourceLoader.get_data to be + implemented to load source code. Use of bytecode is dictated by whether + get_code uses/writes bytecode. - """Load a Python source file.""" + """ + return self._load_module(fullname) - def __init__(self, name, path, is_pkg): - self._name = name - self._is_pkg = is_pkg - # Figure out the base path based on whether it was source or bytecode - # that was found. - try: - self._base_path = _path_without_ext(path, imp.PY_SOURCE) - except ValueError: - self._base_path = _path_without_ext(path, imp.PY_COMPILED) - - def _find_path(self, ext_type): - """Find a path from the base path and the specified extension type that - exists, returning None if one is not found.""" - for suffix in _suffix_list(ext_type): - path = self._base_path + suffix - if _path_exists(path): - return path - else: - return None + +class _FileLoader: + + """Base file loader class which implements the loader protocol methods that + require file system usage.""" + + def __init__(self, fullname, path): + """Cache the module name and the path to the file found by the + finder.""" + self._name = fullname + self._path = path @_check_name - def source_path(self, fullname): - """Return the path to an existing source file for the module, or None - if one cannot be found.""" - # Not a property so that it is easy to override. - return self._find_path(imp.PY_SOURCE) + def get_filename(self, fullname): + """Return the path to the source file as found by the finder.""" + return self._path def get_data(self, path): """Return the data from path as raw bytes.""" - return _io.FileIO(path, 'r').read() # Assuming bytes. + with _closing(_io.FileIO(path, 'r')) as file: + return file.read() - @_check_name - def is_package(self, fullname): - """Return a boolean based on whether the module is a package. - Raises ImportError (like get_source) if the loader cannot handle the - package. +class _SourceFileLoader(_FileLoader, SourceLoader): - """ - return self._is_pkg + """Concrete implementation of SourceLoader using the file system.""" + def path_mtime(self, path): + """Return the modification time for the path.""" + return int(_os.stat(path).st_mtime) -class _PyPycFileLoader(PyPycLoader, _PyFileLoader): + def set_data(self, path, data): + """Write bytes data to a file.""" + try: + with _closing(_io.FileIO(path, 'wb')) as file: + file.write(data) + except IOError as exc: + if exc.errno == errno.ENOENT: + directory, _, filename = path.rpartition(path_sep) + sub_directories = [] + while not _path_isdir(directory): + directory, _, sub_dir = directory.rpartition(path_sep) + sub_directories.append(sub_dir) + for part in reversed(sub_directories): + directory = _path_join(directory, part) + try: + _os.mkdir(directory) + except IOError as exc: + if exc.errno != errno.EACCES: + raise + else: + return + return self.set_data(path, data) + elif exc.errno != errno.EACCES: + raise - """Load a module from a source or bytecode file.""" - def _find_path(self, ext_type): - """Return PEP 3147 path if ext_type is PY_COMPILED, otherwise - super()._find_path() is called.""" - if ext_type == imp.PY_COMPILED: - # We don't really care what the extension on self._base_path is, - # as long as it has exactly one dot. - source_path = self._base_path + '.py' - pycache_path = imp.cache_from_source(source_path) - legacy_path = self._base_path + '.pyc' - # The rule is: if the source file exists, then Python always uses - # the __pycache__/foo..pyc file. If the source file does not - # exist, then Python uses the legacy path. - pyc_path = (pycache_path - if _path_exists(source_path) - else legacy_path) - return (pyc_path if _path_exists(pyc_path) else None) - return super()._find_path(ext_type) +class _SourcelessFileLoader(_FileLoader, _LoaderBasics): - @_check_name - def source_mtime(self, name): - """Return the modification time of the source for the specified - module.""" - source_path = self.source_path(name) - if not source_path: - return None - return int(_os.stat(source_path).st_mtime) + """Loader which handles sourceless file imports.""" - @_check_name - def bytecode_path(self, fullname): - """Return the path to a bytecode file, or None if one does not - exist.""" - # Not a property for easy overriding. - return self._find_path(imp.PY_COMPILED) - - @_check_name - def write_bytecode(self, name, data): - """Write out 'data' for the specified module, returning a boolean - signifying if the write-out actually occurred. + def load_module(self, fullname): + return self._load_module(fullname, sourceless=True) - Raises ImportError (just like get_source) if the specified module - cannot be handled by the loader. + def get_code(self, fullname): + path = self.get_filename(fullname) + data = self.get_data(path) + bytes_data = self._bytes_from_bytecode(fullname, data, None) + found = marshal.loads(bytes_data) + if isinstance(found, code_type): + return found + else: + raise ImportError("Non-code object in {}".format(path)) - """ - bytecode_path = self.bytecode_path(name) - if not bytecode_path: - source_path = self.source_path(name) - bytecode_path = imp.cache_from_source(source_path) - # Ensure that the __pycache__ directory exists. We can't use - # os.path.dirname() here. - dirname, sep, basename = bytecode_path.rpartition(path_sep) - try: - _os.mkdir(dirname) - except OSError as error: - if error.errno != errno.EEXIST: - raise - try: - # Assuming bytes. - with _closing(_io.FileIO(bytecode_path, 'w')) as bytecode_file: - bytecode_file.write(data) - return True - except IOError as exc: - if exc.errno == errno.EACCES: - return False - else: - raise + def get_source(self, fullname): + """Return None as there is no source code.""" + return None class _ExtensionFileLoader: @@ -563,7 +536,7 @@ """ - def __init__(self, name, path, is_pkg): + def __init__(self, name, path): """Initialize the loader. If is_pkg is True then an exception is raised as extension modules @@ -572,8 +545,6 @@ """ self._name = name self._path = path - if is_pkg: - raise ValueError("extension modules cannot be packages") @_check_name @set_package @@ -671,147 +642,88 @@ return None -class _ChainedFinder: - - """Finder that sequentially calls other finders.""" - - def __init__(self, *finders): - self._finders = finders - - def find_module(self, fullname, path=None): - for finder in self._finders: - result = finder.find_module(fullname, path) - if result: - return result - else: - return None - - class _FileFinder: - """Base class for file finders. - - Subclasses are expected to define the following attributes: - - * _suffixes - Sequence of file suffixes whose order will be followed. + """File-based finder. - * _possible_package - True if importer should check for packages. - - * _loader - A callable that takes the module name, a file path, and whether - the path points to a package and returns a loader for the module - found at that path. + Constructor takes a list of objects detailing what file extensions their + loader supports along with whether it can be used for a package. """ - def __init__(self, path_entry): - """Initialize an importer for the passed-in sys.path entry (which is - assumed to have already been verified as an existing directory). - - Can be used as an entry on sys.path_hook. + def __init__(self, path, *details): + """Initialize with finder details.""" + packages = [] + modules = [] + for detail in details: + modules.extend((suffix, detail.loader) for suffix in detail.suffixes) + if detail.supports_packages: + packages.extend((suffix, detail.loader) + for suffix in detail.suffixes) + self.packages = packages + self.modules = modules + self.path = path - """ - absolute_path = _path_absolute(path_entry) - if not _path_isdir(absolute_path): - raise ImportError("only directories are supported") - self._path_entry = absolute_path - - def find_module(self, fullname, path=None): + def find_module(self, fullname): + """Try to find a loader for the specified module.""" tail_module = fullname.rpartition('.')[2] - package_directory = None - if self._possible_package: - for ext in self._suffixes: - package_directory = _path_join(self._path_entry, tail_module) - init_filename = '__init__' + ext - package_init = _path_join(package_directory, init_filename) - if (_path_isfile(package_init) and - _case_ok(self._path_entry, tail_module) and - _case_ok(package_directory, init_filename)): - return self._loader(fullname, package_init, True) - for ext in self._suffixes: - file_name = tail_module + ext - file_path = _path_join(self._path_entry, file_name) - if (_path_isfile(file_path) and - _case_ok(self._path_entry, file_name)): - return self._loader(fullname, file_path, False) - else: - # Raise a warning if it matches a directory w/o an __init__ file. - if (package_directory is not None and - _path_isdir(package_directory) and - _case_ok(self._path_entry, tail_module)): - _warnings.warn("Not importing directory %s: missing __init__" - % package_directory, ImportWarning) - return None - - -class _PyFileFinder(_FileFinder): - - """Importer for source/bytecode files.""" - - _possible_package = True - _loader = _PyFileLoader - - def __init__(self, path_entry): - # Lack of imp during class creation means _suffixes is set here. - # Make sure that Python source files are listed first! Needed for an - # optimization by the loader. - self._suffixes = _suffix_list(imp.PY_SOURCE) - super().__init__(path_entry) - - -class _PyPycFileFinder(_PyFileFinder): + base_path = _path_join(self.path, tail_module) + if _path_isdir(base_path) and _case_ok(self.path, tail_module): + for suffix, loader in self.packages: + init_filename = '__init__' + suffix + full_path = _path_join(base_path, init_filename) + if (_path_isfile(full_path) and + _case_ok(base_path, init_filename)): + return loader(fullname, full_path) + else: + msg = "Not importing directory {}: missing __init__" + _warnings.warn(msg.format(base_path), ImportWarning) + for suffix, loader in self.modules: + mod_filename = tail_module + suffix + full_path = _path_join(self.path, mod_filename) + if _path_isfile(full_path) and _case_ok(self.path, mod_filename): + return loader(fullname, full_path) + return None - """Finder for source and bytecode files.""" +class _SourceFinderDetails: - _loader = _PyPycFileLoader + loader = _SourceFileLoader + supports_packages = True - def __init__(self, path_entry): - super().__init__(path_entry) - self._suffixes += _suffix_list(imp.PY_COMPILED) + def __init__(self): + self.suffixes = _suffix_list(imp.PY_SOURCE) +class _SourcelessFinderDetails: + loader = _SourcelessFileLoader + supports_packages = True + def __init__(self): + self.suffixes = _suffix_list(imp.PY_COMPILED) -class _ExtensionFileFinder(_FileFinder): - """Importer for extension files.""" +class _ExtensionFinderDetails: - _possible_package = False - _loader = _ExtensionFileLoader + loader = _ExtensionFileLoader + supports_packages = False - def __init__(self, path_entry): - # Assigning to _suffixes here instead of at the class level because - # imp is not imported at the time of class creation. - self._suffixes = _suffix_list(imp.C_EXTENSION) - super().__init__(path_entry) + def __init__(self): + self.suffixes = _suffix_list(imp.C_EXTENSION) # Import itself ############################################################### -def _chained_path_hook(*path_hooks): - """Create a closure which sequentially checks path hooks to see which ones - (if any) can work with a path.""" - def path_hook(entry): - """Check to see if 'entry' matches any of the enclosed path hooks.""" - finders = [] - for hook in path_hooks: - try: - finder = hook(entry) - except ImportError: - continue - else: - finders.append(finder) - if not finders: - raise ImportError("no finder found") - else: - return _ChainedFinder(*finders) - - return path_hook +def _file_path_hook(path): + """If the path is a directory, return a file-based finder.""" + if _path_isdir(path): + return _FileFinder(path, _ExtensionFinderDetails(), + _SourceFinderDetails(), + _SourcelessFinderDetails()) + else: + raise ImportError("only directories are supported") -_DEFAULT_PATH_HOOK = _chained_path_hook(_ExtensionFileFinder, _PyPycFileFinder) +_DEFAULT_PATH_HOOK = _file_path_hook class _DefaultPathFinder(PathFinder): Modified: python/branches/py3k-dtoa/Lib/importlib/abc.py ============================================================================== --- python/branches/py3k-dtoa/Lib/importlib/abc.py (original) +++ python/branches/py3k-dtoa/Lib/importlib/abc.py Tue Jul 6 17:55:27 2010 @@ -1,8 +1,16 @@ """Abstract base classes related to import.""" from . import _bootstrap from . import machinery +from . import util import abc +import imp +import io +import marshal +import os.path +import sys +import tokenize import types +import warnings class Loader(metaclass=abc.ABCMeta): @@ -58,19 +66,19 @@ def is_package(self, fullname:str) -> bool: """Abstract method which when implemented should return whether the module is a package.""" - return NotImplementedError + raise NotImplementedError @abc.abstractmethod def get_code(self, fullname:str) -> types.CodeType: """Abstract method which when implemented should return the code object for the module""" - return NotImplementedError + raise NotImplementedError @abc.abstractmethod def get_source(self, fullname:str) -> str: """Abstract method which should return the source code for the module.""" - return NotImplementedError + raise NotImplementedError InspectLoader.register(machinery.BuiltinImporter) InspectLoader.register(machinery.FrozenImporter) @@ -92,33 +100,170 @@ raise NotImplementedError -class PyLoader(_bootstrap.PyLoader, ResourceLoader, ExecutionLoader): +class SourceLoader(_bootstrap.SourceLoader, ResourceLoader, ExecutionLoader): - """Abstract base class to assist in loading source code by requiring only - back-end storage methods to be implemented. + """Abstract base class for loading source code (and optionally any + corresponding bytecode). + + To support loading from source code, the abstractmethods inherited from + ResourceLoader and ExecutionLoader need to be implemented. To also support + loading from bytecode, the optional methods specified directly by this ABC + is required. + + Inherited abstractmethods not implemented in this ABC: + + * ResourceLoader.get_data + * ExecutionLoader.get_filename + + """ - The methods get_code, get_source, and load_module are implemented for the - user. + +class PyLoader(SourceLoader): + + """Implement the deprecated PyLoader ABC in terms of SourceLoader. + + This class has been deprecated! It is slated for removal in Python 3.4. + If compatibility with Python 3.1 is not needed then implement the + SourceLoader ABC instead of this class. If Python 3.1 compatibility is + needed, then use the following idiom to have a single class that is + compatible with Python 3.1 onwards:: + + try: + from importlib.abc import SourceLoader + except ImportError: + from importlib.abc import PyLoader as SourceLoader + + + class CustomLoader(SourceLoader): + def get_filename(self, fullname): + # Implement ... + + def source_path(self, fullname): + '''Implement source_path in terms of get_filename.''' + try: + return self.get_filename(fullname) + except ImportError: + return None + + def is_package(self, fullname): + filename = os.path.basename(self.get_filename(fullname)) + return os.path.splitext(filename)[0] == '__init__' """ @abc.abstractmethod + def is_package(self, fullname): + raise NotImplementedError + + @abc.abstractmethod def source_path(self, fullname:str) -> object: """Abstract method which when implemented should return the path to the - sourced code for the module.""" + source code for the module.""" raise NotImplementedError + def get_filename(self, fullname): + """Implement get_filename in terms of source_path. + + As get_filename should only return a source file path there is no + chance of the path not existing but loading still being possible, so + ImportError should propagate instead of being turned into returning + None. + + """ + warnings.warn("importlib.abc.PyLoader is deprecated and is " + "slated for removal in Python 3.4; " + "use SourceLoader instead. " + "See the importlib documentation on how to be " + "compatible with Python 3.1 onwards.", + PendingDeprecationWarning) + path = self.source_path(fullname) + if path is None: + raise ImportError + else: + return path + -class PyPycLoader(_bootstrap.PyPycLoader, PyLoader): +class PyPycLoader(PyLoader): """Abstract base class to assist in loading source and bytecode by requiring only back-end storage methods to be implemented. + This class has been deprecated! Removal is slated for Python 3.4. Implement + the SourceLoader ABC instead. If Python 3.1 compatibility is needed, see + PyLoader. + The methods get_code, get_source, and load_module are implemented for the user. """ + def get_filename(self, fullname): + """Return the source or bytecode file path.""" + path = self.source_path(fullname) + if path is not None: + return path + path = self.bytecode_path(fullname) + if path is not None: + return path + raise ImportError("no source or bytecode path available for " + "{0!r}".format(fullname)) + + def get_code(self, fullname): + """Get a code object from source or bytecode.""" + warnings.warn("importlib.abc.PyPycLoader is deprecated and slated for " + "removal in Python 3.4; use SourceLoader instead. " + "If Python 3.1 compatibility is required, see the " + "latest documentation for PyLoader.", + PendingDeprecationWarning) + source_timestamp = self.source_mtime(fullname) + # Try to use bytecode if it is available. + bytecode_path = self.bytecode_path(fullname) + if bytecode_path: + data = self.get_data(bytecode_path) + try: + magic = data[:4] + if len(magic) < 4: + raise ImportError("bad magic number in {}".format(fullname)) + raw_timestamp = data[4:8] + if len(raw_timestamp) < 4: + raise EOFError("bad timestamp in {}".format(fullname)) + pyc_timestamp = marshal._r_long(raw_timestamp) + bytecode = data[8:] + # Verify that the magic number is valid. + if imp.get_magic() != magic: + raise ImportError("bad magic number in {}".format(fullname)) + # Verify that the bytecode is not stale (only matters when + # there is source to fall back on. + if source_timestamp: + if pyc_timestamp < source_timestamp: + raise ImportError("bytecode is stale") + except (ImportError, EOFError): + # If source is available give it a shot. + if source_timestamp is not None: + pass + else: + raise + else: + # Bytecode seems fine, so try to use it. + return marshal.loads(bytecode) + elif source_timestamp is None: + raise ImportError("no source or bytecode available to create code " + "object for {0!r}".format(fullname)) + # Use the source. + source_path = self.source_path(fullname) + if source_path is None: + message = "a source path must exist to load {0}".format(fullname) + raise ImportError(message) + source = self.get_data(source_path) + code_object = compile(source, source_path, 'exec', dont_inherit=True) + # Generate bytecode and write it out. + if not sys.dont_write_bytecode: + data = bytearray(imp.get_magic()) + data.extend(marshal._w_long(source_timestamp)) + data.extend(marshal.dumps(code_object)) + self.write_bytecode(fullname, data) + return code_object + @abc.abstractmethod def source_mtime(self, fullname:str) -> int: """Abstract method which when implemented should return the Modified: python/branches/py3k-dtoa/Lib/importlib/test/extension/test_case_sensitivity.py ============================================================================== --- python/branches/py3k-dtoa/Lib/importlib/test/extension/test_case_sensitivity.py (original) +++ python/branches/py3k-dtoa/Lib/importlib/test/extension/test_case_sensitivity.py Tue Jul 6 17:55:27 2010 @@ -13,7 +13,8 @@ good_name = ext_util.NAME bad_name = good_name.upper() assert good_name != bad_name - finder = _bootstrap._ExtensionFileFinder(ext_util.PATH) + finder = _bootstrap._FileFinder(ext_util.PATH, + _bootstrap._ExtensionFinderDetails()) return finder.find_module(bad_name) def test_case_sensitive(self): Modified: python/branches/py3k-dtoa/Lib/importlib/test/extension/test_finder.py ============================================================================== --- python/branches/py3k-dtoa/Lib/importlib/test/extension/test_finder.py (original) +++ python/branches/py3k-dtoa/Lib/importlib/test/extension/test_finder.py Tue Jul 6 17:55:27 2010 @@ -9,7 +9,8 @@ """Test the finder for extension modules.""" def find_module(self, fullname): - importer = _bootstrap._ExtensionFileFinder(util.PATH) + importer = _bootstrap._FileFinder(util.PATH, + _bootstrap._ExtensionFinderDetails()) return importer.find_module(fullname) def test_module(self): Modified: python/branches/py3k-dtoa/Lib/importlib/test/extension/test_loader.py ============================================================================== --- python/branches/py3k-dtoa/Lib/importlib/test/extension/test_loader.py (original) +++ python/branches/py3k-dtoa/Lib/importlib/test/extension/test_loader.py Tue Jul 6 17:55:27 2010 @@ -13,7 +13,7 @@ def load_module(self, fullname): loader = _bootstrap._ExtensionFileLoader(ext_util.NAME, - ext_util.FILEPATH, False) + ext_util.FILEPATH) return loader.load_module(fullname) def test_module(self): Modified: python/branches/py3k-dtoa/Lib/importlib/test/extension/test_path_hook.py ============================================================================== --- python/branches/py3k-dtoa/Lib/importlib/test/extension/test_path_hook.py (original) +++ python/branches/py3k-dtoa/Lib/importlib/test/extension/test_path_hook.py Tue Jul 6 17:55:27 2010 @@ -14,7 +14,7 @@ # XXX Should it only work for directories containing an extension module? def hook(self, entry): - return _bootstrap._ExtensionFileFinder(entry) + return _bootstrap._file_path_hook(entry) def test_success(self): # Path hook should handle a directory where a known extension module Modified: python/branches/py3k-dtoa/Lib/importlib/test/import_/test_path.py ============================================================================== --- python/branches/py3k-dtoa/Lib/importlib/test/import_/test_path.py (original) +++ python/branches/py3k-dtoa/Lib/importlib/test/import_/test_path.py Tue Jul 6 17:55:27 2010 @@ -5,6 +5,7 @@ import imp import os import sys +import tempfile from test import support from types import MethodType import unittest @@ -80,23 +81,28 @@ def test_implicit_hooks(self): # Test that the implicit path hooks are used. - existing_path = os.path.dirname(support.TESTFN) bad_path = '' module = '' assert not os.path.exists(bad_path) - with util.import_state(): - nothing = _bootstrap._DefaultPathFinder.find_module(module, - path=[existing_path]) - self.assertTrue(nothing is None) - self.assertTrue(existing_path in sys.path_importer_cache) - self.assertTrue(not isinstance(sys.path_importer_cache[existing_path], - imp.NullImporter)) - nothing = _bootstrap._DefaultPathFinder.find_module(module, - path=[bad_path]) - self.assertTrue(nothing is None) - self.assertTrue(bad_path in sys.path_importer_cache) - self.assertTrue(isinstance(sys.path_importer_cache[bad_path], - imp.NullImporter)) + existing_path = tempfile.mkdtemp() + try: + with util.import_state(): + nothing = _bootstrap._DefaultPathFinder.find_module(module, + path=[existing_path]) + self.assertTrue(nothing is None) + self.assertTrue(existing_path in sys.path_importer_cache) + result = isinstance(sys.path_importer_cache[existing_path], + imp.NullImporter) + self.assertFalse(result) + nothing = _bootstrap._DefaultPathFinder.find_module(module, + path=[bad_path]) + self.assertTrue(nothing is None) + self.assertTrue(bad_path in sys.path_importer_cache) + self.assertTrue(isinstance(sys.path_importer_cache[bad_path], + imp.NullImporter)) + finally: + os.rmdir(existing_path) + def test_path_importer_cache_has_None(self): # Test that the default hook is used when sys.path_importer_cache Modified: python/branches/py3k-dtoa/Lib/importlib/test/regrtest.py ============================================================================== --- python/branches/py3k-dtoa/Lib/importlib/test/regrtest.py (original) +++ python/branches/py3k-dtoa/Lib/importlib/test/regrtest.py Tue Jul 6 17:55:27 2010 @@ -6,9 +6,11 @@ this script. XXX FAILING - test_import - execution bit + * test_import + - test_incorrect_code_name file name differing between __file__ and co_filename (r68360 on trunk) + - test_import_by_filename + exception for trying to import by file name does not match """ import importlib Modified: python/branches/py3k-dtoa/Lib/importlib/test/source/test_abc_loader.py ============================================================================== --- python/branches/py3k-dtoa/Lib/importlib/test/source/test_abc_loader.py (original) +++ python/branches/py3k-dtoa/Lib/importlib/test/source/test_abc_loader.py Tue Jul 6 17:55:27 2010 @@ -1,14 +1,68 @@ import importlib from importlib import abc + from .. import abc as testing_abc from .. import util from . import util as source_util + import imp +import inspect +import io import marshal import os import sys import types import unittest +import warnings + + +class SourceOnlyLoaderMock(abc.SourceLoader): + + # Globals that should be defined for all modules. + source = (b"_ = '::'.join([__name__, __file__, __cached__, __package__, " + b"repr(__loader__)])") + + def __init__(self, path): + self.path = path + + def get_data(self, path): + assert self.path == path + return self.source + + def get_filename(self, fullname): + return self.path + + +class SourceLoaderMock(SourceOnlyLoaderMock): + + source_mtime = 1 + + def __init__(self, path, magic=imp.get_magic()): + super().__init__(path) + self.bytecode_path = imp.cache_from_source(self.path) + data = bytearray(magic) + data.extend(marshal._w_long(self.source_mtime)) + code_object = compile(self.source, self.path, 'exec', + dont_inherit=True) + data.extend(marshal.dumps(code_object)) + self.bytecode = bytes(data) + self.written = {} + + def get_data(self, path): + if path == self.path: + return super().get_data(path) + elif path == self.bytecode_path: + return self.bytecode + else: + raise IOError + + def path_mtime(self, path): + assert path == self.path + return self.source_mtime + + def set_data(self, path, data): + self.written[path] = bytes(data) + return path == self.bytecode_path class PyLoaderMock(abc.PyLoader): @@ -33,17 +87,42 @@ return self.source def is_package(self, name): + filename = os.path.basename(self.get_filename(name)) + return os.path.splitext(filename)[0] == '__init__' + + def source_path(self, name): try: - return '__init__' in self.module_paths[name] + return self.module_paths[name] except KeyError: raise ImportError - def source_path(self, name): + def get_filename(self, name): + """Silence deprecation warning.""" + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always") + path = super().get_filename(name) + assert len(w) == 1 + assert issubclass(w[0].category, PendingDeprecationWarning) + return path + + +class PyLoaderCompatMock(PyLoaderMock): + + """Mock that matches what is suggested to have a loader that is compatible + from Python 3.1 onwards.""" + + def get_filename(self, fullname): try: - return self.module_paths[name] + return self.module_paths[fullname] except KeyError: raise ImportError + def source_path(self, fullname): + try: + return self.get_filename(fullname) + except ImportError: + return None + class PyPycLoaderMock(abc.PyPycLoader, PyLoaderMock): @@ -114,6 +193,13 @@ except TypeError: return '__init__' in self.bytecode_to_path[name] + def get_code(self, name): + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always") + code_object = super().get_code(name) + assert len(w) == 1 + assert issubclass(w[0].category, PendingDeprecationWarning) + return code_object class PyLoaderTests(testing_abc.LoaderTests): @@ -200,6 +286,14 @@ return mock +class PyLoaderCompatTests(PyLoaderTests): + + """Test that the suggested code to make a loader that is compatible from + Python 3.1 forward works.""" + + mocker = PyLoaderCompatMock + + class PyLoaderInterfaceTests(unittest.TestCase): """Tests for importlib.abc.PyLoader to make sure that when source_path() @@ -234,30 +328,6 @@ mock.get_filename(name) -class PyLoaderGetSourceTests(unittest.TestCase): - - """Tests for importlib.abc.PyLoader.get_source().""" - - def test_default_encoding(self): - # Should have no problems with UTF-8 text. - name = 'mod' - mock = PyLoaderMock({name: os.path.join('path', 'to', 'mod')}) - source = 'x = "??"' - mock.source = source.encode('utf-8') - returned_source = mock.get_source(name) - self.assertEqual(returned_source, source) - - def test_decoded_source(self): - # Decoding should work. - name = 'mod' - mock = PyLoaderMock({name: os.path.join('path', 'to', 'mod')}) - source = "# coding: Latin-1\nx='??'" - assert source.encode('latin-1') != source.encode('utf-8') - mock.source = source.encode('latin-1') - returned_source = mock.get_source(name) - self.assertEqual(returned_source, source) - - class PyPycLoaderTests(PyLoaderTests): """Tests for importlib.abc.PyPycLoader.""" @@ -413,7 +483,7 @@ def test_bad_bytecode(self): # Malformed code object bytecode should lead to a ValueError. name = 'mod' - bc = {name: {'path': os.path.join('path', 'to', 'mod'), 'bc': b'XXX'}} + bc = {name: {'path': os.path.join('path', 'to', 'mod'), 'bc': b'1234'}} mock = PyPycLoaderMock({name: None}, bc) with util.uncache(name), self.assertRaises(ValueError): mock.load_module(name) @@ -465,12 +535,341 @@ mock.load_module(name) +class SourceLoaderTestHarness(unittest.TestCase): + + def setUp(self, *, is_package=True, **kwargs): + self.package = 'pkg' + if is_package: + self.path = os.path.join(self.package, '__init__.py') + self.name = self.package + else: + module_name = 'mod' + self.path = os.path.join(self.package, '.'.join(['mod', 'py'])) + self.name = '.'.join([self.package, module_name]) + self.cached = imp.cache_from_source(self.path) + self.loader = self.loader_mock(self.path, **kwargs) + + def verify_module(self, module): + self.assertEqual(module.__name__, self.name) + self.assertEqual(module.__file__, self.path) + self.assertEqual(module.__cached__, self.cached) + self.assertEqual(module.__package__, self.package) + self.assertEqual(module.__loader__, self.loader) + values = module._.split('::') + self.assertEqual(values[0], self.name) + self.assertEqual(values[1], self.path) + self.assertEqual(values[2], self.cached) + self.assertEqual(values[3], self.package) + self.assertEqual(values[4], repr(self.loader)) + + def verify_code(self, code_object): + module = imp.new_module(self.name) + module.__file__ = self.path + module.__cached__ = self.cached + module.__package__ = self.package + module.__loader__ = self.loader + module.__path__ = [] + exec(code_object, module.__dict__) + self.verify_module(module) + + +class SourceOnlyLoaderTests(SourceLoaderTestHarness): + + """Test importlib.abc.SourceLoader for source-only loading. + + Reload testing is subsumed by the tests for + importlib.util.module_for_loader. + + """ + + loader_mock = SourceOnlyLoaderMock + + def test_get_source(self): + # Verify the source code is returned as a string. + # If an IOError is raised by get_data then raise ImportError. + expected_source = self.loader.source.decode('utf-8') + self.assertEqual(self.loader.get_source(self.name), expected_source) + def raise_IOError(path): + raise IOError + self.loader.get_data = raise_IOError + with self.assertRaises(ImportError): + self.loader.get_source(self.name) + + def test_is_package(self): + # Properly detect when loading a package. + self.setUp(is_package=True) + self.assertTrue(self.loader.is_package(self.name)) + self.setUp(is_package=False) + self.assertFalse(self.loader.is_package(self.name)) + + def test_get_code(self): + # Verify the code object is created. + code_object = self.loader.get_code(self.name) + self.verify_code(code_object) + + def test_load_module(self): + # Loading a module should set __name__, __loader__, __package__, + # __path__ (for packages), __file__, and __cached__. + # The module should also be put into sys.modules. + with util.uncache(self.name): + module = self.loader.load_module(self.name) + self.verify_module(module) + self.assertEqual(module.__path__, [os.path.dirname(self.path)]) + self.assertTrue(self.name in sys.modules) + + def test_package_settings(self): + # __package__ needs to be set, while __path__ is set on if the module + # is a package. + # Testing the values for a package are covered by test_load_module. + self.setUp(is_package=False) + with util.uncache(self.name): + module = self.loader.load_module(self.name) + self.verify_module(module) + self.assertTrue(not hasattr(module, '__path__')) + + def test_get_source_encoding(self): + # Source is considered encoded in UTF-8 by default unless otherwise + # specified by an encoding line. + source = "_ = '??'" + self.loader.source = source.encode('utf-8') + returned_source = self.loader.get_source(self.name) + self.assertEqual(returned_source, source) + source = "# coding: latin-1\n_ = ??" + self.loader.source = source.encode('latin-1') + returned_source = self.loader.get_source(self.name) + self.assertEqual(returned_source, source) + + + at unittest.skipIf(sys.dont_write_bytecode, "sys.dont_write_bytecode is true") +class SourceLoaderBytecodeTests(SourceLoaderTestHarness): + + """Test importlib.abc.SourceLoader's use of bytecode. + + Source-only testing handled by SourceOnlyLoaderTests. + + """ + + loader_mock = SourceLoaderMock + + def verify_code(self, code_object, *, bytecode_written=False): + super().verify_code(code_object) + if bytecode_written: + self.assertIn(self.cached, self.loader.written) + data = bytearray(imp.get_magic()) + data.extend(marshal._w_long(self.loader.source_mtime)) + data.extend(marshal.dumps(code_object)) + self.assertEqual(self.loader.written[self.cached], bytes(data)) + + def test_code_with_everything(self): + # When everything should work. + code_object = self.loader.get_code(self.name) + self.verify_code(code_object) + + def test_no_bytecode(self): + # If no bytecode exists then move on to the source. + self.loader.bytecode_path = "" + # Sanity check + with self.assertRaises(IOError): + bytecode_path = imp.cache_from_source(self.path) + self.loader.get_data(bytecode_path) + code_object = self.loader.get_code(self.name) + self.verify_code(code_object, bytecode_written=True) + + def test_code_bad_timestamp(self): + # Bytecode is only used when the timestamp matches the source EXACTLY. + for source_mtime in (0, 2): + assert source_mtime != self.loader.source_mtime + original = self.loader.source_mtime + self.loader.source_mtime = source_mtime + # If bytecode is used then EOFError would be raised by marshal. + self.loader.bytecode = self.loader.bytecode[8:] + code_object = self.loader.get_code(self.name) + self.verify_code(code_object, bytecode_written=True) + self.loader.source_mtime = original + + def test_code_bad_magic(self): + # Skip over bytecode with a bad magic number. + self.setUp(magic=b'0000') + # If bytecode is used then EOFError would be raised by marshal. + self.loader.bytecode = self.loader.bytecode[8:] + code_object = self.loader.get_code(self.name) + self.verify_code(code_object, bytecode_written=True) + + def test_dont_write_bytecode(self): + # Bytecode is not written if sys.dont_write_bytecode is true. + # Can assume it is false already thanks to the skipIf class decorator. + try: + sys.dont_write_bytecode = True + self.loader.bytecode_path = "" + code_object = self.loader.get_code(self.name) + self.assertNotIn(self.cached, self.loader.written) + finally: + sys.dont_write_bytecode = False + + def test_no_set_data(self): + # If set_data is not defined, one can still read bytecode. + self.setUp(magic=b'0000') + original_set_data = self.loader.__class__.set_data + try: + del self.loader.__class__.set_data + code_object = self.loader.get_code(self.name) + self.verify_code(code_object) + finally: + self.loader.__class__.set_data = original_set_data + + def test_set_data_raises_exceptions(self): + # Raising NotImplementedError or IOError is okay for set_data. + def raise_exception(exc): + def closure(*args, **kwargs): + raise exc + return closure + + self.setUp(magic=b'0000') + self.loader.set_data = raise_exception(NotImplementedError) + code_object = self.loader.get_code(self.name) + self.verify_code(code_object) + + +class SourceLoaderGetSourceTests(unittest.TestCase): + + """Tests for importlib.abc.SourceLoader.get_source().""" + + def test_default_encoding(self): + # Should have no problems with UTF-8 text. + name = 'mod' + mock = SourceOnlyLoaderMock('mod.file') + source = 'x = "??"' + mock.source = source.encode('utf-8') + returned_source = mock.get_source(name) + self.assertEqual(returned_source, source) + + def test_decoded_source(self): + # Decoding should work. + name = 'mod' + mock = SourceOnlyLoaderMock("mod.file") + source = "# coding: Latin-1\nx='??'" + assert source.encode('latin-1') != source.encode('utf-8') + mock.source = source.encode('latin-1') + returned_source = mock.get_source(name) + self.assertEqual(returned_source, source) + + def test_universal_newlines(self): + # PEP 302 says universal newlines should be used. + name = 'mod' + mock = SourceOnlyLoaderMock('mod.file') + source = "x = 42\r\ny = -13\r\n" + mock.source = source.encode('utf-8') + expect = io.IncrementalNewlineDecoder(None, True).decode(source) + self.assertEqual(mock.get_source(name), expect) + +class AbstractMethodImplTests(unittest.TestCase): + + """Test the concrete abstractmethod implementations.""" + + class Loader(abc.Loader): + def load_module(self, fullname): + super().load_module(fullname) + + class Finder(abc.Finder): + def find_module(self, _): + super().find_module(_) + + class ResourceLoader(Loader, abc.ResourceLoader): + def get_data(self, _): + super().get_data(_) + + class InspectLoader(Loader, abc.InspectLoader): + def is_package(self, _): + super().is_package(_) + + def get_code(self, _): + super().get_code(_) + + def get_source(self, _): + super().get_source(_) + + class ExecutionLoader(InspectLoader, abc.ExecutionLoader): + def get_filename(self, _): + super().get_filename(_) + + class SourceLoader(ResourceLoader, ExecutionLoader, abc.SourceLoader): + pass + + class PyLoader(ResourceLoader, InspectLoader, abc.PyLoader): + def source_path(self, _): + super().source_path(_) + + class PyPycLoader(PyLoader, abc.PyPycLoader): + def bytecode_path(self, _): + super().bytecode_path(_) + + def source_mtime(self, _): + super().source_mtime(_) + + def write_bytecode(self, _, _2): + super().write_bytecode(_, _2) + + def raises_NotImplementedError(self, ins, *args): + for method_name in args: + method = getattr(ins, method_name) + arg_count = len(inspect.getfullargspec(method)[0]) - 1 + args = [''] * arg_count + try: + method(*args) + except NotImplementedError: + pass + else: + msg = "{}.{} did not raise NotImplementedError" + self.fail(msg.format(ins.__class__.__name__, method_name)) + + def test_Loader(self): + self.raises_NotImplementedError(self.Loader(), 'load_module') + + # XXX misplaced; should be somewhere else + def test_Finder(self): + self.raises_NotImplementedError(self.Finder(), 'find_module') + + def test_ResourceLoader(self): + self.raises_NotImplementedError(self.ResourceLoader(), 'load_module', + 'get_data') + + def test_InspectLoader(self): + self.raises_NotImplementedError(self.InspectLoader(), 'load_module', + 'is_package', 'get_code', 'get_source') + + def test_ExecutionLoader(self): + self.raises_NotImplementedError(self.ExecutionLoader(), 'load_module', + 'is_package', 'get_code', 'get_source', + 'get_filename') + + def test_SourceLoader(self): + ins = self.SourceLoader() + # Required abstractmethods. + self.raises_NotImplementedError(ins, 'get_filename', 'get_data') + # Optional abstractmethods. + self.raises_NotImplementedError(ins,'path_mtime', 'set_data') + + def test_PyLoader(self): + self.raises_NotImplementedError(self.PyLoader(), 'source_path', + 'get_data', 'is_package') + + def test_PyPycLoader(self): + self.raises_NotImplementedError(self.PyPycLoader(), 'source_path', + 'source_mtime', 'bytecode_path', + 'write_bytecode') + + def test_main(): from test.support import run_unittest - run_unittest(PyLoaderTests, PyLoaderInterfaceTests, PyLoaderGetSourceTests, + run_unittest(PyLoaderTests, PyLoaderCompatTests, + PyLoaderInterfaceTests, PyPycLoaderTests, PyPycLoaderInterfaceTests, SkipWritingBytecodeTests, RegeneratedBytecodeTests, - BadBytecodeFailureTests, MissingPathsTests) + BadBytecodeFailureTests, MissingPathsTests, + SourceOnlyLoaderTests, + SourceLoaderBytecodeTests, + SourceLoaderGetSourceTests, + AbstractMethodImplTests) if __name__ == '__main__': Modified: python/branches/py3k-dtoa/Lib/importlib/test/source/test_case_sensitivity.py ============================================================================== --- python/branches/py3k-dtoa/Lib/importlib/test/source/test_case_sensitivity.py (original) +++ python/branches/py3k-dtoa/Lib/importlib/test/source/test_case_sensitivity.py Tue Jul 6 17:55:27 2010 @@ -19,7 +19,9 @@ assert name != name.lower() def find(self, path): - finder = _bootstrap._PyPycFileFinder(path) + finder = _bootstrap._FileFinder(path, + _bootstrap._SourceFinderDetails(), + _bootstrap._SourcelessFinderDetails()) return finder.find_module(self.name) def sensitivity_test(self): @@ -27,7 +29,7 @@ sensitive_pkg = 'sensitive.{0}'.format(self.name) insensitive_pkg = 'insensitive.{0}'.format(self.name.lower()) context = source_util.create_modules(insensitive_pkg, sensitive_pkg) - with context as mapping: + with context as mapping: sensitive_path = os.path.join(mapping['.root'], 'sensitive') insensitive_path = os.path.join(mapping['.root'], 'insensitive') return self.find(sensitive_path), self.find(insensitive_path) @@ -37,7 +39,7 @@ env.unset('PYTHONCASEOK') sensitive, insensitive = self.sensitivity_test() self.assertTrue(hasattr(sensitive, 'load_module')) - self.assertIn(self.name, sensitive._base_path) + self.assertIn(self.name, sensitive.get_filename(self.name)) self.assertIsNone(insensitive) def test_insensitive(self): @@ -45,9 +47,9 @@ env.set('PYTHONCASEOK', '1') sensitive, insensitive = self.sensitivity_test() self.assertTrue(hasattr(sensitive, 'load_module')) - self.assertIn(self.name, sensitive._base_path) + self.assertIn(self.name, sensitive.get_filename(self.name)) self.assertTrue(hasattr(insensitive, 'load_module')) - self.assertIn(self.name, insensitive._base_path) + self.assertIn(self.name, insensitive.get_filename(self.name)) def test_main(): Modified: python/branches/py3k-dtoa/Lib/importlib/test/source/test_file_loader.py ============================================================================== --- python/branches/py3k-dtoa/Lib/importlib/test/source/test_file_loader.py (original) +++ python/branches/py3k-dtoa/Lib/importlib/test/source/test_file_loader.py Tue Jul 6 17:55:27 2010 @@ -1,9 +1,11 @@ import importlib from importlib import _bootstrap from .. import abc +from .. import util from . import util as source_util import imp +import marshal import os import py_compile import stat @@ -23,8 +25,7 @@ # [basic] def test_module(self): with source_util.create_modules('_temp') as mapping: - loader = _bootstrap._PyPycFileLoader('_temp', mapping['_temp'], - False) + loader = _bootstrap._SourceFileLoader('_temp', mapping['_temp']) module = loader.load_module('_temp') self.assertTrue('_temp' in sys.modules) check = {'__name__': '_temp', '__file__': mapping['_temp'], @@ -34,9 +35,8 @@ def test_package(self): with source_util.create_modules('_pkg.__init__') as mapping: - loader = _bootstrap._PyPycFileLoader('_pkg', - mapping['_pkg.__init__'], - True) + loader = _bootstrap._SourceFileLoader('_pkg', + mapping['_pkg.__init__']) module = loader.load_module('_pkg') self.assertTrue('_pkg' in sys.modules) check = {'__name__': '_pkg', '__file__': mapping['_pkg.__init__'], @@ -48,8 +48,8 @@ def test_lacking_parent(self): with source_util.create_modules('_pkg.__init__', '_pkg.mod')as mapping: - loader = _bootstrap._PyPycFileLoader('_pkg.mod', - mapping['_pkg.mod'], False) + loader = _bootstrap._SourceFileLoader('_pkg.mod', + mapping['_pkg.mod']) module = loader.load_module('_pkg.mod') self.assertTrue('_pkg.mod' in sys.modules) check = {'__name__': '_pkg.mod', '__file__': mapping['_pkg.mod'], @@ -63,8 +63,7 @@ def test_module_reuse(self): with source_util.create_modules('_temp') as mapping: - loader = _bootstrap._PyPycFileLoader('_temp', mapping['_temp'], - False) + loader = _bootstrap._SourceFileLoader('_temp', mapping['_temp']) module = loader.load_module('_temp') module_id = id(module) module_dict_id = id(module.__dict__) @@ -74,7 +73,7 @@ # everything that has happened above can be too fast; # force an mtime on the source that is guaranteed to be different # than the original mtime. - loader.source_mtime = self.fake_mtime(loader.source_mtime) + loader.path_mtime = self.fake_mtime(loader.path_mtime) module = loader.load_module('_temp') self.assertTrue('testing_var' in module.__dict__, "'testing_var' not in " @@ -94,8 +93,7 @@ setattr(orig_module, attr, value) with open(mapping[name], 'w') as file: file.write('+++ bad syntax +++') - loader = _bootstrap._PyPycFileLoader('_temp', mapping['_temp'], - False) + loader = _bootstrap._SourceFileLoader('_temp', mapping['_temp']) with self.assertRaises(SyntaxError): loader.load_module(name) for attr in attributes: @@ -106,17 +104,32 @@ with source_util.create_modules('_temp') as mapping: with open(mapping['_temp'], 'w') as file: file.write('=') - loader = _bootstrap._PyPycFileLoader('_temp', mapping['_temp'], - False) + loader = _bootstrap._SourceFileLoader('_temp', mapping['_temp']) with self.assertRaises(SyntaxError): loader.load_module('_temp') self.assertTrue('_temp' not in sys.modules) + def test_file_from_empty_string_dir(self): + # Loading a module found from an empty string entry on sys.path should + # not only work, but keep all attributes relative. + with open('_temp.py', 'w') as file: + file.write("# test file for importlib") + try: + with util.uncache('_temp'): + loader = _bootstrap._SourceFileLoader('_temp', '_temp.py') + mod = loader.load_module('_temp') + self.assertEqual('_temp.py', mod.__file__) + self.assertEqual(imp.cache_from_source('_temp.py'), + mod.__cached__) + + finally: + os.unlink('_temp.py') + class BadBytecodeTest(unittest.TestCase): def import_(self, file, module_name): - loader = _bootstrap._PyPycFileLoader(module_name, file, False) + loader = self.loader(module_name, file) module = loader.load_module(module_name) self.assertTrue(module_name in sys.modules) @@ -129,101 +142,156 @@ except KeyError: pass py_compile.compile(mapping[name]) - bytecode_path = imp.cache_from_source(mapping[name]) - with open(bytecode_path, 'rb') as file: - bc = file.read() - new_bc = manipulator(bc) - with open(bytecode_path, 'wb') as file: - if new_bc: - file.write(new_bc) - if del_source: + if not del_source: + bytecode_path = imp.cache_from_source(mapping[name]) + else: os.unlink(mapping[name]) - make_legacy_pyc(mapping[name]) + bytecode_path = make_legacy_pyc(mapping[name]) + if manipulator: + with open(bytecode_path, 'rb') as file: + bc = file.read() + new_bc = manipulator(bc) + with open(bytecode_path, 'wb') as file: + if new_bc is not None: + file.write(new_bc) return bytecode_path - @source_util.writes_bytecode_files - def test_empty_file(self): - # When a .pyc is empty, regenerate it if possible, else raise - # ImportError. + def _test_empty_file(self, test, *, del_source=False): with source_util.create_modules('_temp') as mapping: bc_path = self.manipulate_bytecode('_temp', mapping, - lambda bc: None) - self.import_(mapping['_temp'], '_temp') - with open(bc_path, 'rb') as file: - self.assertGreater(len(file.read()), 8) - self.manipulate_bytecode('_temp', mapping, lambda bc: None, - del_source=True) - with self.assertRaises(ImportError): - self.import_(mapping['_temp'], '_temp') + lambda bc: b'', + del_source=del_source) + test('_temp', mapping, bc_path) @source_util.writes_bytecode_files - def test_partial_magic(self): + def _test_partial_magic(self, test, *, del_source=False): # When their are less than 4 bytes to a .pyc, regenerate it if # possible, else raise ImportError. with source_util.create_modules('_temp') as mapping: bc_path = self.manipulate_bytecode('_temp', mapping, - lambda bc: bc[:3]) - self.import_(mapping['_temp'], '_temp') - with open(bc_path, 'rb') as file: - self.assertGreater(len(file.read()), 8) - self.manipulate_bytecode('_temp', mapping, lambda bc: bc[:3], - del_source=True) + lambda bc: bc[:3], + del_source=del_source) + test('_temp', mapping, bc_path) + + def _test_magic_only(self, test, *, del_source=False): + with source_util.create_modules('_temp') as mapping: + bc_path = self.manipulate_bytecode('_temp', mapping, + lambda bc: bc[:4], + del_source=del_source) + test('_temp', mapping, bc_path) + + def _test_partial_timestamp(self, test, *, del_source=False): + with source_util.create_modules('_temp') as mapping: + bc_path = self.manipulate_bytecode('_temp', mapping, + lambda bc: bc[:7], + del_source=del_source) + test('_temp', mapping, bc_path) + + def _test_no_marshal(self, *, del_source=False): + with source_util.create_modules('_temp') as mapping: + bc_path = self.manipulate_bytecode('_temp', mapping, + lambda bc: bc[:8], + del_source=del_source) + file_path = mapping['_temp'] if not del_source else bc_path + with self.assertRaises(EOFError): + self.import_(file_path, '_temp') + + def _test_non_code_marshal(self, *, del_source=False): + with source_util.create_modules('_temp') as mapping: + bytecode_path = self.manipulate_bytecode('_temp', mapping, + lambda bc: bc[:8] + marshal.dumps(b'abcd'), + del_source=del_source) + file_path = mapping['_temp'] if not del_source else bytecode_path with self.assertRaises(ImportError): - self.import_(mapping['_temp'], '_temp') + self.import_(file_path, '_temp') + + def _test_bad_marshal(self, *, del_source=False): + with source_util.create_modules('_temp') as mapping: + bytecode_path = self.manipulate_bytecode('_temp', mapping, + lambda bc: bc[:8] + b'', + del_source=del_source) + file_path = mapping['_temp'] if not del_source else bytecode_path + with self.assertRaises(ValueError): + self.import_(file_path, '_temp') + + def _test_bad_magic(self, test, *, del_source=False): + with source_util.create_modules('_temp') as mapping: + bc_path = self.manipulate_bytecode('_temp', mapping, + lambda bc: b'\x00\x00\x00\x00' + bc[4:]) + test('_temp', mapping, bc_path) + + +class SourceLoaderBadBytecodeTest(BadBytecodeTest): + + loader = _bootstrap._SourceFileLoader + + @source_util.writes_bytecode_files + def test_empty_file(self): + # When a .pyc is empty, regenerate it if possible, else raise + # ImportError. + def test(name, mapping, bytecode_path): + self.import_(mapping[name], name) + with open(bytecode_path, 'rb') as file: + self.assertGreater(len(file.read()), 8) + + self._test_empty_file(test) + + def test_partial_magic(self): + def test(name, mapping, bytecode_path): + self.import_(mapping[name], name) + with open(bytecode_path, 'rb') as file: + self.assertGreater(len(file.read()), 8) + + self._test_partial_magic(test) @source_util.writes_bytecode_files def test_magic_only(self): # When there is only the magic number, regenerate the .pyc if possible, # else raise EOFError. - with source_util.create_modules('_temp') as mapping: - bc_path = self.manipulate_bytecode('_temp', mapping, - lambda bc: bc[:4]) - self.import_(mapping['_temp'], '_temp') - with open(bc_path, 'rb') as file: + def test(name, mapping, bytecode_path): + self.import_(mapping[name], name) + with open(bytecode_path, 'rb') as file: self.assertGreater(len(file.read()), 8) - self.manipulate_bytecode('_temp', mapping, lambda bc: bc[:4], - del_source=True) - with self.assertRaises(EOFError): - self.import_(mapping['_temp'], '_temp') + + @source_util.writes_bytecode_files + def test_bad_magic(self): + # When the magic number is different, the bytecode should be + # regenerated. + def test(name, mapping, bytecode_path): + self.import_(mapping[name], name) + with open(bytecode_path, 'rb') as bytecode_file: + self.assertEqual(bytecode_file.read(4), imp.get_magic()) + + self._test_bad_magic(test) @source_util.writes_bytecode_files def test_partial_timestamp(self): # When the timestamp is partial, regenerate the .pyc, else # raise EOFError. - with source_util.create_modules('_temp') as mapping: - bc_path = self.manipulate_bytecode('_temp', mapping, - lambda bc: bc[:7]) - self.import_(mapping['_temp'], '_temp') + def test(name, mapping, bc_path): + self.import_(mapping[name], name) with open(bc_path, 'rb') as file: self.assertGreater(len(file.read()), 8) - self.manipulate_bytecode('_temp', mapping, lambda bc: bc[:7], - del_source=True) - with self.assertRaises(EOFError): - self.import_(mapping['_temp'], '_temp') @source_util.writes_bytecode_files def test_no_marshal(self): # When there is only the magic number and timestamp, raise EOFError. - with source_util.create_modules('_temp') as mapping: - bc_path = self.manipulate_bytecode('_temp', mapping, - lambda bc: bc[:8]) - with self.assertRaises(EOFError): - self.import_(mapping['_temp'], '_temp') + self._test_no_marshal() @source_util.writes_bytecode_files - def test_bad_magic(self): - # When the magic number is different, the bytecode should be - # regenerated. - with source_util.create_modules('_temp') as mapping: - bc_path = self.manipulate_bytecode('_temp', mapping, - lambda bc: b'\x00\x00\x00\x00' + bc[4:]) - self.import_(mapping['_temp'], '_temp') - with open(bc_path, 'rb') as bytecode_file: - self.assertEqual(bytecode_file.read(4), imp.get_magic()) + def test_non_code_marshal(self): + self._test_non_code_marshal() + # XXX ImportError when sourceless + + # [bad marshal] + @source_util.writes_bytecode_files + def test_bad_marshal(self): + # Bad marshal data should raise a ValueError. + self._test_bad_marshal() # [bad timestamp] @source_util.writes_bytecode_files - def test_bad_bytecode(self): + def test_old_timestamp(self): # When the timestamp is older than the source, bytecode should be # regenerated. zeros = b'\x00\x00\x00\x00' @@ -240,23 +308,6 @@ bytecode_file.seek(4) self.assertEqual(bytecode_file.read(4), source_timestamp) - # [bad marshal] - @source_util.writes_bytecode_files - def test_bad_marshal(self): - # Bad marshal data should raise a ValueError. - with source_util.create_modules('_temp') as mapping: - bytecode_path = imp.cache_from_source(mapping['_temp']) - source_mtime = os.path.getmtime(mapping['_temp']) - source_timestamp = importlib._w_long(source_mtime) - source_util.ensure_bytecode_path(bytecode_path) - with open(bytecode_path, 'wb') as bytecode_file: - bytecode_file.write(imp.get_magic()) - bytecode_file.write(source_timestamp) - bytecode_file.write(b'AAAA') - with self.assertRaises(ValueError): - self.import_(mapping['_temp'], '_temp') - self.assertTrue('_temp' not in sys.modules) - # [bytecode read-only] @source_util.writes_bytecode_files def test_read_only_bytecode(self): @@ -279,9 +330,57 @@ os.chmod(bytecode_path, stat.S_IWUSR) +class SourcelessLoaderBadBytecodeTest(BadBytecodeTest): + + loader = _bootstrap._SourcelessFileLoader + + def test_empty_file(self): + def test(name, mapping, bytecode_path): + with self.assertRaises(ImportError): + self.import_(bytecode_path, name) + + self._test_empty_file(test, del_source=True) + + def test_partial_magic(self): + def test(name, mapping, bytecode_path): + with self.assertRaises(ImportError): + self.import_(bytecode_path, name) + self._test_partial_magic(test, del_source=True) + + def test_magic_only(self): + def test(name, mapping, bytecode_path): + with self.assertRaises(EOFError): + self.import_(bytecode_path, name) + + self._test_magic_only(test, del_source=True) + + def test_bad_magic(self): + def test(name, mapping, bytecode_path): + with self.assertRaises(ImportError): + self.import_(bytecode_path, name) + + self._test_bad_magic(test, del_source=True) + + def test_partial_timestamp(self): + def test(name, mapping, bytecode_path): + with self.assertRaises(EOFError): + self.import_(bytecode_path, name) + + self._test_partial_timestamp(test, del_source=True) + + def test_no_marshal(self): + self._test_no_marshal(del_source=True) + + def test_non_code_marshal(self): + self._test_non_code_marshal(del_source=True) + + def test_main(): from test.support import run_unittest - run_unittest(SimpleTest, BadBytecodeTest) + run_unittest(SimpleTest, + SourceLoaderBadBytecodeTest, + SourcelessLoaderBadBytecodeTest + ) if __name__ == '__main__': Modified: python/branches/py3k-dtoa/Lib/importlib/test/source/test_finder.py ============================================================================== --- python/branches/py3k-dtoa/Lib/importlib/test/source/test_finder.py (original) +++ python/branches/py3k-dtoa/Lib/importlib/test/source/test_finder.py Tue Jul 6 17:55:27 2010 @@ -34,7 +34,9 @@ """ def import_(self, root, module): - finder = _bootstrap._PyPycFileFinder(root) + finder = _bootstrap._FileFinder(root, + _bootstrap._SourceFinderDetails(), + _bootstrap._SourcelessFinderDetails()) return finder.find_module(module) def run_test(self, test, create=None, *, compile_=None, unlink=None): @@ -113,10 +115,9 @@ # [package over modules] def test_package_over_module(self): - # XXX This is not a blackbox test! name = '_temp' loader = self.run_test(name, {'{0}.__init__'.format(name), name}) - self.assertTrue('__init__' in loader._base_path) + self.assertTrue('__init__' in loader.get_filename(name)) def test_failure(self): @@ -131,6 +132,17 @@ with self.assertRaises(ImportWarning): self.run_test('pkg', {'pkg.__init__'}, unlink={'pkg.__init__'}) + def test_empty_string_for_dir(self): + # The empty string from sys.path means to search in the cwd. + finder = _bootstrap._FileFinder('', _bootstrap._SourceFinderDetails()) + with open('mod.py', 'w') as file: + file.write("# test file for importlib") + try: + loader = finder.find_module('mod') + self.assertTrue(hasattr(loader, 'load_module')) + finally: + os.unlink('mod.py') + def test_main(): from test.support import run_unittest Modified: python/branches/py3k-dtoa/Lib/importlib/test/source/test_path_hook.py ============================================================================== --- python/branches/py3k-dtoa/Lib/importlib/test/source/test_path_hook.py (original) +++ python/branches/py3k-dtoa/Lib/importlib/test/source/test_path_hook.py Tue Jul 6 17:55:27 2010 @@ -8,11 +8,14 @@ """Test the path hook for source.""" def test_success(self): - # XXX Only work on existing directories? with source_util.create_modules('dummy') as mapping: - self.assertTrue(hasattr(_bootstrap._FileFinder(mapping['.root']), + self.assertTrue(hasattr(_bootstrap._file_path_hook(mapping['.root']), 'find_module')) + def test_empty_string(self): + # The empty string represents the cwd. + self.assertTrue(hasattr(_bootstrap._file_path_hook(''), 'find_module')) + def test_main(): from test.support import run_unittest Modified: python/branches/py3k-dtoa/Lib/importlib/test/source/test_source_encoding.py ============================================================================== --- python/branches/py3k-dtoa/Lib/importlib/test/source/test_source_encoding.py (original) +++ python/branches/py3k-dtoa/Lib/importlib/test/source/test_source_encoding.py Tue Jul 6 17:55:27 2010 @@ -35,8 +35,8 @@ with source_util.create_modules(self.module_name) as mapping: with open(mapping[self.module_name], 'wb') as file: file.write(source) - loader = _bootstrap._PyPycFileLoader(self.module_name, - mapping[self.module_name], False) + loader = _bootstrap._SourceFileLoader(self.module_name, + mapping[self.module_name]) return loader.load_module(self.module_name) def create_source(self, encoding): @@ -97,8 +97,8 @@ with source_util.create_modules(module_name) as mapping: with open(mapping[module_name], 'wb') as file: file.write(source) - loader = _bootstrap._PyPycFileLoader(module_name, - mapping[module_name], False) + loader = _bootstrap._SourceFileLoader(module_name, + mapping[module_name]) return loader.load_module(module_name) # [cr] Modified: python/branches/py3k-dtoa/Lib/importlib/test/test_abc.py ============================================================================== --- python/branches/py3k-dtoa/Lib/importlib/test/test_abc.py (original) +++ python/branches/py3k-dtoa/Lib/importlib/test/test_abc.py Tue Jul 6 17:55:27 2010 @@ -59,6 +59,11 @@ subclasses = [abc.PyLoader] +class SourceLoader(InheritanceTests, unittest.TestCase): + + superclasses = [abc.ResourceLoader, abc.ExecutionLoader] + + class PyLoader(InheritanceTests, unittest.TestCase): superclasses = [abc.Loader, abc.ResourceLoader, abc.ExecutionLoader] Modified: python/branches/py3k-dtoa/Lib/importlib/test/test_api.py ============================================================================== --- python/branches/py3k-dtoa/Lib/importlib/test/test_api.py (original) +++ python/branches/py3k-dtoa/Lib/importlib/test/test_api.py Tue Jul 6 17:55:27 2010 @@ -27,7 +27,7 @@ self.assertEqual(module.__name__, name) def test_shallow_relative_package_import(self): - # Test importing a module from a package through a relatve import. + # Test importing a module from a package through a relative import. pkg_name = 'pkg' pkg_long_name = '{0}.__init__'.format(pkg_name) module_name = 'mod' Modified: python/branches/py3k-dtoa/Lib/importlib/test/test_util.py ============================================================================== --- python/branches/py3k-dtoa/Lib/importlib/test/test_util.py (original) +++ python/branches/py3k-dtoa/Lib/importlib/test/test_util.py Tue Jul 6 17:55:27 2010 @@ -40,7 +40,7 @@ with test_util.uncache(name): sys.modules[name] = module returned_module = self.return_module(name) - self.assertTrue(sys.modules[name] is returned_module) + self.assertIs(returned_module, sys.modules[name]) def test_new_module_failure(self): # Test that a module is removed from sys.modules if added but an @@ -57,7 +57,7 @@ with test_util.uncache(name): sys.modules[name] = module self.raise_exception(name) - self.assertTrue(sys.modules[name] is module) + self.assertIs(module, sys.modules[name]) class SetPackageTests(unittest.TestCase): Modified: python/branches/py3k-dtoa/Lib/inspect.py ============================================================================== --- python/branches/py3k-dtoa/Lib/inspect.py (original) +++ python/branches/py3k-dtoa/Lib/inspect.py Tue Jul 6 17:55:27 2010 @@ -437,7 +437,9 @@ if info: return info[0] def getsourcefile(object): - """Return the Python source file an object was defined in, if it exists.""" + """Return the filename that can be used to locate an object's source. + Return None if no way can be identified to get the source. + """ filename = getfile(object) if filename[-4:].lower() in ('.pyc', '.pyo'): filename = filename[:-4] + '.py' @@ -450,6 +452,9 @@ # only return a non-existent filename if the module has a PEP 302 loader if hasattr(getmodule(object, filename), '__loader__'): return filename + # or it is in the linecache + if filename in linecache.cache: + return filename def getabsfile(object, _filename=None): """Return an absolute path to the source or compiled file for an object. @@ -954,7 +959,7 @@ else: arg2value[varargs] = () elif 0 < num_args < num_pos: - raise TypeError('%s() takes %s %d %s (%d given)' % ( + raise TypeError('%s() takes %s %d positional %s (%d given)' % ( f_name, 'at most' if defaults else 'exactly', num_args, 'arguments' if num_args > 1 else 'argument', num_total)) elif num_args == 0 and num_total: Modified: python/branches/py3k-dtoa/Lib/lib2to3/fixes/fix_itertools_imports.py ============================================================================== --- python/branches/py3k-dtoa/Lib/lib2to3/fixes/fix_itertools_imports.py (original) +++ python/branches/py3k-dtoa/Lib/lib2to3/fixes/fix_itertools_imports.py Tue Jul 6 17:55:27 2010 @@ -20,6 +20,9 @@ if child.type == token.NAME: member = child.value name_node = child + elif child.type == token.STAR: + # Just leave the import as is. + return else: assert child.type == syms.import_as_name name_node = child.children[0] @@ -44,8 +47,8 @@ children[-1].remove() # If there are no imports left, just get rid of the entire statement - if not (imports.children or getattr(imports, 'value', None)) or \ - imports.parent is None: + if (not (imports.children or getattr(imports, 'value', None)) or + imports.parent is None): p = node.prefix node = BlankLine() node.prefix = p Modified: python/branches/py3k-dtoa/Lib/lib2to3/tests/test_fixers.py ============================================================================== --- python/branches/py3k-dtoa/Lib/lib2to3/tests/test_fixers.py (original) +++ python/branches/py3k-dtoa/Lib/lib2to3/tests/test_fixers.py Tue Jul 6 17:55:27 2010 @@ -3670,6 +3670,10 @@ a = "from itertools import bar, filterfalse, foo" self.check(b, a) + def test_import_star(self): + s = "from itertools import *" + self.unchanged(s) + def test_unchanged(self): s = "from itertools import foo" Modified: python/branches/py3k-dtoa/Lib/logging/config.py ============================================================================== --- python/branches/py3k-dtoa/Lib/logging/config.py (original) +++ python/branches/py3k-dtoa/Lib/logging/config.py Tue Jul 6 17:55:27 2010 @@ -386,15 +386,21 @@ """ name = s.split('.') used = name.pop(0) - found = self.importer(used) - for frag in name: - used += '.' + frag - try: - found = getattr(found, frag) - except AttributeError: - self.importer(used) - found = getattr(found, frag) - return found + try: + found = self.importer(used) + for frag in name: + used += '.' + frag + try: + found = getattr(found, frag) + except AttributeError: + self.importer(used) + found = getattr(found, frag) + return found + except ImportError: + e, tb = sys.exc_info()[1:] + v = ValueError('Cannot resolve %r: %s' % (s, e)) + v.__cause__, v.__traceback__ = e, tb + raise v def ext_convert(self, value): """Default converter for the ext:// protocol.""" @@ -873,6 +879,8 @@ def run(self): server = self.rcvr(port=self.port, handler=self.hdlr, ready=self.ready) + if self.port == 0: + self.port = server.server_address[1] self.ready.set() global _listener logging._acquireLock() Modified: python/branches/py3k-dtoa/Lib/macpath.py ============================================================================== --- python/branches/py3k-dtoa/Lib/macpath.py (original) +++ python/branches/py3k-dtoa/Lib/macpath.py Tue Jul 6 17:55:27 2010 @@ -32,6 +32,9 @@ # Normalize the case of a pathname. Dummy in Posix, but .lower() here. def normcase(path): + if not isinstance(path, (bytes, str)): + raise TypeError("normcase() argument must be str or bytes, " + "not '{}'".format(path.__class__.__name__)) return path.lower() Modified: python/branches/py3k-dtoa/Lib/ntpath.py ============================================================================== --- python/branches/py3k-dtoa/Lib/ntpath.py (original) +++ python/branches/py3k-dtoa/Lib/ntpath.py Tue Jul 6 17:55:27 2010 @@ -78,6 +78,9 @@ """Normalize case of pathname. Makes all characters lowercase and all slashes into backslashes.""" + if not isinstance(s, (bytes, str)): + raise TypeError("normcase() argument must be str or bytes, " + "not '{}'".format(s.__class__.__name__)) return s.replace(_get_altsep(s), _get_sep(s)).lower() Modified: python/branches/py3k-dtoa/Lib/os2emxpath.py ============================================================================== --- python/branches/py3k-dtoa/Lib/os2emxpath.py (original) +++ python/branches/py3k-dtoa/Lib/os2emxpath.py Tue Jul 6 17:55:27 2010 @@ -36,6 +36,9 @@ """Normalize case of pathname. Makes all characters lowercase and all altseps into seps.""" + if not isinstance(s, (bytes, str)): + raise TypeError("normcase() argument must be str or bytes, " + "not '{}'".format(s.__class__.__name__)) return s.replace('\\', '/').lower() Modified: python/branches/py3k-dtoa/Lib/pdb.doc ============================================================================== --- python/branches/py3k-dtoa/Lib/pdb.doc (original) +++ python/branches/py3k-dtoa/Lib/pdb.doc Tue Jul 6 17:55:27 2010 @@ -68,13 +68,13 @@ An arrow indicates the "current frame", which determines the context of most commands. -d(own) - Move the current frame one level down in the stack trace - (to a newer frame). - -u(p) - Move the current frame one level up in the stack trace - (to an older frame). +d(own) [ count ] + Move the current frame count (default one) levels down in the + stack trace (to a newer frame). + +u(p) [ count ] + Move the current frame count (default one) levels up in the + stack trace (to an older frame). b(reak) [ ([filename:]lineno | function) [, condition] ] With a filename:line number argument, set a break there. If @@ -138,8 +138,8 @@ run [args...] Restart the debugged python program. If a string is supplied it is splitted with "shlex", and the result is used as the new sys.argv. - History, breakpoints, actions and debugger options are preserved. - "restart" is an alias for "run". + History, breakpoints, actions and debugger options are preserved. + "restart" is an alias for "run". c(ont(inue)) Continue execution, only stop when a breakpoint is encountered. Modified: python/branches/py3k-dtoa/Lib/pdb.py ============================================================================== --- python/branches/py3k-dtoa/Lib/pdb.py (original) +++ python/branches/py3k-dtoa/Lib/pdb.py Tue Jul 6 17:55:27 2010 @@ -618,26 +618,44 @@ do_w = do_where do_bt = do_where + def _select_frame(self, number): + assert 0 <= number < len(self.stack) + self.curindex = number + self.curframe = self.stack[self.curindex][0] + self.curframe_locals = self.curframe.f_locals + self.print_stack_entry(self.stack[self.curindex]) + self.lineno = None + def do_up(self, arg): if self.curindex == 0: print('*** Oldest frame', file=self.stdout) + return + try: + count = int(arg or 1) + except ValueError: + print('*** Invalid frame count (%s)' % arg, file=self.stdout) + return + if count < 0: + newframe = 0 else: - self.curindex = self.curindex - 1 - self.curframe = self.stack[self.curindex][0] - self.curframe_locals = self.curframe.f_locals - self.print_stack_entry(self.stack[self.curindex]) - self.lineno = None + newframe = max(0, self.curindex - count) + self._select_frame(newframe) do_u = do_up def do_down(self, arg): if self.curindex + 1 == len(self.stack): print('*** Newest frame', file=self.stdout) + return + try: + count = int(arg or 1) + except ValueError: + print('*** Invalid frame count (%s)' % arg, file=self.stdout) + return + if count < 0: + newframe = len(self.stack) - 1 else: - self.curindex = self.curindex + 1 - self.curframe = self.stack[self.curindex][0] - self.curframe_locals = self.curframe.f_locals - self.print_stack_entry(self.stack[self.curindex]) - self.lineno = None + newframe = min(len(self.stack) - 1, self.curindex + count) + self._select_frame(newframe) do_d = do_down def do_until(self, arg): Modified: python/branches/py3k-dtoa/Lib/pickletools.py ============================================================================== --- python/branches/py3k-dtoa/Lib/pickletools.py (original) +++ python/branches/py3k-dtoa/Lib/pickletools.py Tue Jul 6 17:55:27 2010 @@ -2330,4 +2330,43 @@ return doctest.testmod() if __name__ == "__main__": - _test() + import sys, argparse + parser = argparse.ArgumentParser( + description='disassemble one or more pickle files') + parser.add_argument( + 'pickle_file', type=argparse.FileType('br'), + nargs='*', help='the pickle file') + parser.add_argument( + '-o', '--output', default=sys.stdout, type=argparse.FileType('w'), + help='the file where the output should be written') + parser.add_argument( + '-m', '--memo', action='store_true', + help='preserve memo between disassemblies') + parser.add_argument( + '-l', '--indentlevel', default=4, type=int, + help='the number of blanks by which to indent a new MARK level') + parser.add_argument( + '-p', '--preamble', default="==> {name} <==", + help='if more than one pickle file is specified, print this before' + ' each disassembly') + parser.add_argument( + '-t', '--test', action='store_true', + help='run self-test suite') + parser.add_argument( + '-v', action='store_true', + help='run verbosely; only affects self-test run') + args = parser.parse_args() + if args.test: + _test() + else: + if not args.pickle_file: + parser.print_help() + elif len(args.pickle_file) == 1: + dis(args.pickle_file[0], args.output, + indentlevel=args.indentlevel) + else: + memo = {} if args.memo else None + for f in args.pickle_file: + preamble = args.preamble.format(name=f.name) + args.output.write(preamble + '\n') + dis(f, args.output, memo, args.indentlevel) Modified: python/branches/py3k-dtoa/Lib/posixpath.py ============================================================================== --- python/branches/py3k-dtoa/Lib/posixpath.py (original) +++ python/branches/py3k-dtoa/Lib/posixpath.py Tue Jul 6 17:55:27 2010 @@ -49,6 +49,9 @@ def normcase(s): """Normalize case of pathname. Has no effect under Posix""" # TODO: on Mac OS X, this should really return s.lower(). + if not isinstance(s, (bytes, str)): + raise TypeError("normcase() argument must be str or bytes, " + "not '{}'".format(s.__class__.__name__)) return s Modified: python/branches/py3k-dtoa/Lib/pydoc.py ============================================================================== --- python/branches/py3k-dtoa/Lib/pydoc.py (original) +++ python/branches/py3k-dtoa/Lib/pydoc.py Tue Jul 6 17:55:27 2010 @@ -1705,8 +1705,9 @@ return '' return '' - def __call__(self, request=None): - if request is not None: + _GoInteractive = object() + def __call__(self, request=_GoInteractive): + if request is not self._GoInteractive: self.help(request) else: self.intro() Modified: python/branches/py3k-dtoa/Lib/site.py ============================================================================== --- python/branches/py3k-dtoa/Lib/site.py (original) +++ python/branches/py3k-dtoa/Lib/site.py Tue Jul 6 17:55:27 2010 @@ -273,12 +273,12 @@ environment, and will return a list of full paths. """ sitepackages = [] - seen = [] + seen = set() for prefix in PREFIXES: if not prefix or prefix in seen: continue - seen.append(prefix) + seen.add(prefix) if sys.platform in ('os2emx', 'riscos'): sitepackages.append(os.path.join(prefix, "Lib", "site-packages")) Modified: python/branches/py3k-dtoa/Lib/smtpd.py ============================================================================== --- python/branches/py3k-dtoa/Lib/smtpd.py (original) +++ python/branches/py3k-dtoa/Lib/smtpd.py Tue Jul 6 17:55:27 2010 @@ -274,14 +274,19 @@ self._localaddr = localaddr self._remoteaddr = remoteaddr asyncore.dispatcher.__init__(self) - self.create_socket(socket.AF_INET, socket.SOCK_STREAM) - # try to re-use a server port if possible - self.set_reuse_addr() - self.bind(localaddr) - self.listen(5) - print('%s started at %s\n\tLocal addr: %s\n\tRemote addr:%s' % ( - self.__class__.__name__, time.ctime(time.time()), - localaddr, remoteaddr), file=DEBUGSTREAM) + try: + self.create_socket(socket.AF_INET, socket.SOCK_STREAM) + # try to re-use a server port if possible + self.set_reuse_addr() + self.bind(localaddr) + self.listen(5) + except: + self.close() + raise + else: + print('%s started at %s\n\tLocal addr: %s\n\tRemote addr:%s' % ( + self.__class__.__name__, time.ctime(time.time()), + localaddr, remoteaddr), file=DEBUGSTREAM) def handle_accept(self): conn, addr = self.accept() Modified: python/branches/py3k-dtoa/Lib/subprocess.py ============================================================================== --- python/branches/py3k-dtoa/Lib/subprocess.py (original) +++ python/branches/py3k-dtoa/Lib/subprocess.py Tue Jul 6 17:55:27 2010 @@ -500,8 +500,8 @@ 2) A string surrounded by double quotation marks is interpreted as a single argument, regardless of white space - or pipe characters contained within. A quoted string can be - embedded in an argument. + contained within. A quoted string can be embedded in an + argument. 3) A double quotation mark preceded by a backslash is interpreted as a literal double quotation mark. @@ -529,7 +529,7 @@ if result: result.append(' ') - needquote = (" " in arg) or ("\t" in arg) or ("|" in arg) or not arg + needquote = (" " in arg) or ("\t" in arg) or not arg if needquote: result.append('"') Modified: python/branches/py3k-dtoa/Lib/test/test_audioop.py ============================================================================== --- python/branches/py3k-dtoa/Lib/test/test_audioop.py (original) +++ python/branches/py3k-dtoa/Lib/test/test_audioop.py Tue Jul 6 17:55:27 2010 @@ -20,6 +20,12 @@ data = [gendata1(), gendata2(), gendata4()] +INVALID_DATA = [ + ('abc', 0), + ('abc', 2), + ('abc', 4), +] + class TestAudioop(unittest.TestCase): @@ -168,6 +174,33 @@ self.assertRaises(audioop.error, audioop.findmax, ''.join(chr(x) for x in range(256)), -2392392) + def test_issue7673(self): + state = None + for data, size in INVALID_DATA: + size2 = size + self.assertRaises(audioop.error, audioop.getsample, data, size, 0) + self.assertRaises(audioop.error, audioop.max, data, size) + self.assertRaises(audioop.error, audioop.minmax, data, size) + self.assertRaises(audioop.error, audioop.avg, data, size) + self.assertRaises(audioop.error, audioop.rms, data, size) + self.assertRaises(audioop.error, audioop.avgpp, data, size) + self.assertRaises(audioop.error, audioop.maxpp, data, size) + self.assertRaises(audioop.error, audioop.cross, data, size) + self.assertRaises(audioop.error, audioop.mul, data, size, 1.0) + self.assertRaises(audioop.error, audioop.tomono, data, size, 0.5, 0.5) + self.assertRaises(audioop.error, audioop.tostereo, data, size, 0.5, 0.5) + self.assertRaises(audioop.error, audioop.add, data, data, size) + self.assertRaises(audioop.error, audioop.bias, data, size, 0) + self.assertRaises(audioop.error, audioop.reverse, data, size) + self.assertRaises(audioop.error, audioop.lin2lin, data, size, size2) + self.assertRaises(audioop.error, audioop.ratecv, data, size, 1, 1, 1, state) + self.assertRaises(audioop.error, audioop.lin2ulaw, data, size) + self.assertRaises(audioop.error, audioop.ulaw2lin, data, size) + self.assertRaises(audioop.error, audioop.lin2alaw, data, size) + self.assertRaises(audioop.error, audioop.alaw2lin, data, size) + self.assertRaises(audioop.error, audioop.lin2adpcm, data, size, state) + self.assertRaises(audioop.error, audioop.adpcm2lin, data, size, state) + def test_main(): run_unittest(TestAudioop) Modified: python/branches/py3k-dtoa/Lib/test/test_codeccallbacks.py ============================================================================== --- python/branches/py3k-dtoa/Lib/test/test_codeccallbacks.py (original) +++ python/branches/py3k-dtoa/Lib/test/test_codeccallbacks.py Tue Jul 6 17:55:27 2010 @@ -153,28 +153,30 @@ sout += bytes("\\U%08x" % sys.maxunicode, "ascii") self.assertEqual(sin.encode("iso-8859-15", "backslashreplace"), sout) - def test_decoderelaxedutf8(self): - # This is the test for a decoding callback handler, - # that relaxes the UTF-8 minimal encoding restriction. - # A null byte that is encoded as "\xc0\x80" will be - # decoded as a null byte. All other illegal sequences - # will be handled strictly. + def test_decoding_callbacks(self): + # This is a test for a decoding callback handler + # that allows the decoding of the invalid sequence + # "\xc0\x80" and returns "\x00" instead of raising an error. + # All other illegal sequences will be handled strictly. def relaxedutf8(exc): if not isinstance(exc, UnicodeDecodeError): raise TypeError("don't know how to handle %r" % exc) - if exc.object[exc.start:exc.end].startswith(b"\xc0\x80"): + if exc.object[exc.start:exc.start+2] == b"\xc0\x80": return ("\x00", exc.start+2) # retry after two bytes else: raise exc - codecs.register_error( - "test.relaxedutf8", relaxedutf8) + codecs.register_error("test.relaxedutf8", relaxedutf8) + # all the "\xc0\x80" will be decoded to "\x00" sin = b"a\x00b\xc0\x80c\xc3\xbc\xc0\x80\xc0\x80" sout = "a\x00b\x00c\xfc\x00\x00" self.assertEqual(sin.decode("utf-8", "test.relaxedutf8"), sout) + + # "\xc0\x81" is not valid and a UnicodeDecodeError will be raised sin = b"\xc0\x80\xc0\x81" - self.assertRaises(UnicodeError, sin.decode, "utf-8", "test.relaxedutf8") + self.assertRaises(UnicodeDecodeError, sin.decode, + "utf-8", "test.relaxedutf8") def test_charmapencode(self): # For charmap encodings the replacement string will be Modified: python/branches/py3k-dtoa/Lib/test/test_codecs.py ============================================================================== --- python/branches/py3k-dtoa/Lib/test/test_codecs.py (original) +++ python/branches/py3k-dtoa/Lib/test/test_codecs.py Tue Jul 6 17:55:27 2010 @@ -1263,6 +1263,7 @@ "cp424", "cp437", "cp500", + "cp720", "cp737", "cp775", "cp850", @@ -1270,6 +1271,7 @@ "cp855", "cp856", "cp857", + "cp858", "cp860", "cp861", "cp862", @@ -1358,11 +1360,6 @@ "idna", ] -# The following encodings only support "strict" mode -only_strict_mode = [ - "idna", -] - class BasicUnicodeTest(unittest.TestCase, MixInCheckStateHandling): def test_basics(self): s = "abc123" # all codecs should be able to encode these @@ -1437,7 +1434,7 @@ result = "".join(codecs.iterdecode(codecs.iterencode("", encoding), encoding)) self.assertEqual(result, "") - if encoding not in only_strict_mode: + if encoding not in ("idna", "mbcs"): # check incremental decoder/encoder with errors argument try: encoder = codecs.getincrementalencoder(encoding)("ignore") Modified: python/branches/py3k-dtoa/Lib/test/test_complex.py ============================================================================== --- python/branches/py3k-dtoa/Lib/test/test_complex.py (original) +++ python/branches/py3k-dtoa/Lib/test/test_complex.py Tue Jul 6 17:55:27 2010 @@ -437,6 +437,23 @@ @unittest.skipUnless(float.__getformat__("double").startswith("IEEE"), "test requires IEEE 754 doubles") + def test_negated_imaginary_literal(self): + z0 = -0j + z1 = -7j + z2 = -1e1000j + # Note: In versions of Python < 3.2, a negated imaginary literal + # accidentally ended up with real part 0.0 instead of -0.0, thanks to a + # modification during CST -> AST translation (see issue #9011). That's + # fixed in Python 3.2. + self.assertFloatsAreIdentical(z0.real, -0.0) + self.assertFloatsAreIdentical(z0.imag, -0.0) + self.assertFloatsAreIdentical(z1.real, -0.0) + self.assertFloatsAreIdentical(z1.imag, -7.0) + self.assertFloatsAreIdentical(z2.real, -0.0) + self.assertFloatsAreIdentical(z2.imag, -INF) + + @unittest.skipUnless(float.__getformat__("double").startswith("IEEE"), + "test requires IEEE 754 doubles") def test_overflow(self): self.assertEqual(complex("1e500"), complex(INF, 0.0)) self.assertEqual(complex("-1e500j"), complex(0.0, -INF)) Modified: python/branches/py3k-dtoa/Lib/test/test_contextlib.py ============================================================================== --- python/branches/py3k-dtoa/Lib/test/test_contextlib.py (original) +++ python/branches/py3k-dtoa/Lib/test/test_contextlib.py Tue Jul 6 17:55:27 2010 @@ -202,6 +202,169 @@ return True self.boilerPlate(lock, locked) + +class mycontext(ContextDecorator): + started = False + exc = None + catch = False + + def __enter__(self): + self.started = True + return self + + def __exit__(self, *exc): + self.exc = exc + return self.catch + + +class TestContextDecorator(unittest.TestCase): + + def test_contextdecorator(self): + context = mycontext() + with context as result: + self.assertIs(result, context) + self.assertTrue(context.started) + + self.assertEqual(context.exc, (None, None, None)) + + + def test_contextdecorator_with_exception(self): + context = mycontext() + + with self.assertRaisesRegexp(NameError, 'foo'): + with context: + raise NameError('foo') + self.assertIsNotNone(context.exc) + self.assertIs(context.exc[0], NameError) + + context = mycontext() + context.catch = True + with context: + raise NameError('foo') + self.assertIsNotNone(context.exc) + self.assertIs(context.exc[0], NameError) + + + def test_decorator(self): + context = mycontext() + + @context + def test(): + self.assertIsNone(context.exc) + self.assertTrue(context.started) + test() + self.assertEqual(context.exc, (None, None, None)) + + + def test_decorator_with_exception(self): + context = mycontext() + + @context + def test(): + self.assertIsNone(context.exc) + self.assertTrue(context.started) + raise NameError('foo') + + with self.assertRaisesRegexp(NameError, 'foo'): + test() + self.assertIsNotNone(context.exc) + self.assertIs(context.exc[0], NameError) + + + def test_decorating_method(self): + context = mycontext() + + class Test(object): + + @context + def method(self, a, b, c=None): + self.a = a + self.b = b + self.c = c + + # these tests are for argument passing when used as a decorator + test = Test() + test.method(1, 2) + self.assertEqual(test.a, 1) + self.assertEqual(test.b, 2) + self.assertEqual(test.c, None) + + test = Test() + test.method('a', 'b', 'c') + self.assertEqual(test.a, 'a') + self.assertEqual(test.b, 'b') + self.assertEqual(test.c, 'c') + + test = Test() + test.method(a=1, b=2) + self.assertEqual(test.a, 1) + self.assertEqual(test.b, 2) + + + def test_typo_enter(self): + class mycontext(ContextDecorator): + def __unter__(self): + pass + def __exit__(self, *exc): + pass + + with self.assertRaises(AttributeError): + with mycontext(): + pass + + + def test_typo_exit(self): + class mycontext(ContextDecorator): + def __enter__(self): + pass + def __uxit__(self, *exc): + pass + + with self.assertRaises(AttributeError): + with mycontext(): + pass + + + def test_contextdecorator_as_mixin(self): + class somecontext(object): + started = False + exc = None + + def __enter__(self): + self.started = True + return self + + def __exit__(self, *exc): + self.exc = exc + + class mycontext(somecontext, ContextDecorator): + pass + + context = mycontext() + @context + def test(): + self.assertIsNone(context.exc) + self.assertTrue(context.started) + test() + self.assertEqual(context.exc, (None, None, None)) + + + def test_contextmanager_as_decorator(self): + state = [] + @contextmanager + def woohoo(y): + state.append(y) + yield + state.append(999) + + @woohoo(1) + def test(x): + self.assertEqual(state, [1]) + state.append(x) + test('something') + self.assertEqual(state, [1, 'something', 999]) + + # This is needed to make the test actually run under regrtest.py! def test_main(): support.run_unittest(__name__) Modified: python/branches/py3k-dtoa/Lib/test/test_datetime.py ============================================================================== --- python/branches/py3k-dtoa/Lib/test/test_datetime.py (original) +++ python/branches/py3k-dtoa/Lib/test/test_datetime.py Tue Jul 6 17:55:27 2010 @@ -17,9 +17,11 @@ from datetime import time from datetime import timezone from datetime import date, datetime +import time as _time -pickle_choices = [(pickle, pickle, proto) for proto in range(3)] -assert len(pickle_choices) == 3 +pickle_choices = [(pickle, pickle, proto) + for proto in range(pickle.HIGHEST_PROTOCOL + 1)] +assert len(pickle_choices) == pickle.HIGHEST_PROTOCOL + 1 # An arbitrary collection of objects of non-datetime types, for testing # mixed-type comparisons. @@ -121,18 +123,23 @@ def test_pickling_subclass(self): # Make sure we can pickle/unpickle an instance of a subclass. offset = timedelta(minutes=-300) - orig = PicklableFixedOffset(offset, 'cookie') - self.assertIsInstance(orig, tzinfo) - self.assertTrue(type(orig) is PicklableFixedOffset) - self.assertEqual(orig.utcoffset(None), offset) - self.assertEqual(orig.tzname(None), 'cookie') - for pickler, unpickler, proto in pickle_choices: - green = pickler.dumps(orig, proto) - derived = unpickler.loads(green) - self.assertIsInstance(derived, tzinfo) - self.assertTrue(type(derived) is PicklableFixedOffset) - self.assertEqual(derived.utcoffset(None), offset) - self.assertEqual(derived.tzname(None), 'cookie') + for otype, args in [ + (PicklableFixedOffset, (offset, 'cookie')), + (timezone, (offset,)), + (timezone, (offset, "EST"))]: + orig = otype(*args) + oname = orig.tzname(None) + self.assertIsInstance(orig, tzinfo) + self.assertIs(type(orig), otype) + self.assertEqual(orig.utcoffset(None), offset) + self.assertEqual(orig.tzname(None), oname) + for pickler, unpickler, proto in pickle_choices: + green = pickler.dumps(orig, proto) + derived = unpickler.loads(green) + self.assertIsInstance(derived, tzinfo) + self.assertIs(type(derived), otype) + self.assertEqual(derived.utcoffset(None), offset) + self.assertEqual(derived.tzname(None), oname) class TestTimeZone(unittest.TestCase): @@ -165,6 +172,7 @@ with self.assertRaises(TypeError): timezone(42) with self.assertRaises(TypeError): timezone(ZERO, None) with self.assertRaises(TypeError): timezone(ZERO, 42) + with self.assertRaises(TypeError): timezone(ZERO, 'ABC', 'extra') def test_inheritance(self): self.assertIsInstance(timezone.utc, tzinfo) @@ -200,6 +208,8 @@ def test_fromutc(self): with self.assertRaises(ValueError): timezone.utc.fromutc(self.DT) + with self.assertRaises(TypeError): + timezone.utc.fromutc('not datetime') for tz in [self.EST, self.ACDT, Eastern]: utctime = self.DT.replace(tzinfo=tz) local = tz.fromutc(utctime) @@ -300,6 +310,7 @@ c = td(0, 0, 1000) # One millisecond eq(a+b+c, td(7, 60, 1000)) eq(a-b, td(6, 24*3600 - 60)) + eq(b.__rsub__(a), td(6, 24*3600 - 60)) eq(-a, td(-7)) eq(+a, td(7)) eq(-b, td(-1, 24*3600 - 60)) @@ -377,6 +388,7 @@ self.assertRaises(ZeroDivisionError, lambda: a // zero) self.assertRaises(ZeroDivisionError, lambda: a / zero) self.assertRaises(ZeroDivisionError, lambda: a / 0.0) + self.assertRaises(TypeError, lambda: a / '') @requires_IEEE_754 def test_disallowed_special(self): @@ -502,10 +514,20 @@ microseconds=999999)), "999999999 days, 23:59:59.999999") + def test_repr(self): + name = 'datetime.' + self.theclass.__name__ + self.assertEqual(repr(self.theclass(1)), + "%s(1)" % name) + self.assertEqual(repr(self.theclass(10, 2)), + "%s(10, 2)" % name) + self.assertEqual(repr(self.theclass(-10, 2, 400000)), + "%s(-10, 2, 400000)" % name) + def test_roundtrip(self): for td in (timedelta(days=999999999, hours=23, minutes=59, seconds=59, microseconds=999999), timedelta(days=-999999999), + timedelta(days=-999999999, seconds=1), timedelta(days=1, seconds=2, microseconds=3)): # Verify td -> string -> td identity. @@ -859,6 +881,7 @@ def test_computations(self): a = self.theclass(2002, 1, 31) b = self.theclass(1956, 1, 31) + c = self.theclass(2001,2,1) diff = a-b self.assertEqual(diff.days, 46*365 + len(range(1956, 2002, 4))) @@ -884,6 +907,7 @@ self.assertEqual(a - (a + day), -day) self.assertEqual(a - (a - week), week) self.assertEqual(a - (a - day), day) + self.assertEqual(c - (c - day), day) # Add/sub ints or floats should be illegal for i in 1, 1.0: @@ -1099,8 +1123,13 @@ self.assertEqual(b.__format__(fmt), 'B') def test_resolution_info(self): - self.assertIsInstance(self.theclass.min, self.theclass) - self.assertIsInstance(self.theclass.max, self.theclass) + # XXX: Should min and max respect subclassing? + if issubclass(self.theclass, datetime): + expected_class = datetime + else: + expected_class = date + self.assertIsInstance(self.theclass.min, expected_class) + self.assertIsInstance(self.theclass.max, expected_class) self.assertIsInstance(self.theclass.resolution, timedelta) self.assertTrue(self.theclass.max > self.theclass.min) @@ -1320,6 +1349,10 @@ for month_byte in b'9', b'\0', b'\r', b'\xff': self.assertRaises(TypeError, self.theclass, base[:2] + month_byte + base[3:]) + # Good bytes, but bad tzinfo: + self.assertRaises(TypeError, self.theclass, + bytes([1] * len(base)), 'EST') + for ord_byte in range(1, 13): # This shouldn't blow up because of the month byte alone. If # the implementation changes to do more-careful checking, it may @@ -1731,10 +1764,42 @@ string = '2004-12-01 13:02:47.197' format = '%Y-%m-%d %H:%M:%S.%f' - result, frac = _strptime._strptime(string, format) - expected = self.theclass(*(result[0:6]+(frac,))) + expected = _strptime._strptime_datetime(self.theclass, string, format) got = self.theclass.strptime(string, format) self.assertEqual(expected, got) + self.assertIs(type(expected), self.theclass) + self.assertIs(type(got), self.theclass) + + strptime = self.theclass.strptime + self.assertEqual(strptime("+0002", "%z").utcoffset(), 2 * MINUTE) + self.assertEqual(strptime("-0002", "%z").utcoffset(), -2 * MINUTE) + # Only local timezone and UTC are supported + for tzseconds, tzname in ((0, 'UTC'), (0, 'GMT'), + (-_time.timezone, _time.tzname[0])): + if tzseconds < 0: + sign = '-' + seconds = -tzseconds + else: + sign ='+' + seconds = tzseconds + hours, minutes = divmod(seconds//60, 60) + dtstr = "{}{:02d}{:02d} {}".format(sign, hours, minutes, tzname) + dt = strptime(dtstr, "%z %Z") + self.assertEqual(dt.utcoffset(), timedelta(seconds=tzseconds)) + self.assertEqual(dt.tzname(), tzname) + # Can produce inconsistent datetime + dtstr, fmt = "+1234 UTC", "%z %Z" + dt = strptime(dtstr, fmt) + self.assertEqual(dt.utcoffset(), 12 * HOUR + 34 * MINUTE) + self.assertEqual(dt.tzname(), 'UTC') + # yet will roundtrip + self.assertEqual(dt.strftime(fmt), dtstr) + + # Produce naive datetime if no %z is provided + self.assertEqual(strptime("UTC", "%Z").tzinfo, None) + + with self.assertRaises(ValueError): strptime("-2400", "%z") + with self.assertRaises(ValueError): strptime("-000", "%z") def test_more_timetuple(self): # This tests fields beyond those tested by the TestDate.test_timetuple. @@ -1789,6 +1854,8 @@ self.assertRaises(TypeError, combine, t, d) # args reversed self.assertRaises(TypeError, combine, d, t, 1) # too many args self.assertRaises(TypeError, combine, "date", "time") # wrong types + self.assertRaises(TypeError, combine, d, "time") # wrong type + self.assertRaises(TypeError, combine, "date", t) # wrong type def test_replace(self): cls = self.theclass @@ -1831,6 +1898,8 @@ def dst(self, dt): return timedelta(0) bog = Bogus() self.assertRaises(ValueError, dt.astimezone, bog) # naive + self.assertRaises(ValueError, + dt.replace(tzinfo=bog).astimezone, f) class AlsoBogus(tzinfo): def utcoffset(self, dt): return timedelta(0) @@ -1865,6 +1934,12 @@ self.assertEqual(dt2.newmeth(-7), dt1.year + dt1.month + dt1.second - 7) +class TestSubclassDateTime(TestDateTime): + theclass = SubclassDatetime + # Override tests not designed for subclass + def test_roundtrip(self): + pass + class SubclassTime(time): sub_var = 1 @@ -2801,6 +2876,11 @@ maxdiff = max - min self.assertEqual(maxdiff, self.theclass.max - self.theclass.min + timedelta(minutes=2*1439)) + # Different tzinfo, but the same offset + tza = timezone(HOUR, 'A') + tzb = timezone(HOUR, 'B') + delta = min.replace(tzinfo=tza) - max.replace(tzinfo=tzb) + self.assertEqual(delta, self.theclass.min - self.theclass.max) def test_tzinfo_now(self): meth = self.theclass.now @@ -2934,7 +3014,7 @@ def test_utctimetuple(self): class DST(tzinfo): - def __init__(self, dstvalue): + def __init__(self, dstvalue=0): if isinstance(dstvalue, int): dstvalue = timedelta(minutes=dstvalue) self.dstvalue = dstvalue @@ -2953,8 +3033,6 @@ def utcoffset(self, dt): return self.uofs - # Ensure tm_isdst is 0 regardless of what dst() says: DST is never - # in effect for a UTC time. for dstvalue in -33, 33, 0, None: d = cls(1, 2, 3, 10, 20, 30, 40, tzinfo=UOFS(-53, dstvalue)) t = d.utctimetuple() @@ -2967,34 +3045,52 @@ self.assertEqual(d.weekday(), t.tm_wday) self.assertEqual(d.toordinal() - date(1, 1, 1).toordinal() + 1, t.tm_yday) + # Ensure tm_isdst is 0 regardless of what dst() says: DST + # is never in effect for a UTC time. self.assertEqual(0, t.tm_isdst) - # At the edges, UTC adjustment can normalize into years out-of-range - # for a datetime object. Ensure that a correct timetuple is - # created anyway. + # For naive datetime, utctimetuple == timetuple except for isdst + d = cls(1, 2, 3, 10, 20, 30, 40) + t = d.utctimetuple() + self.assertEqual(t[:-1], d.timetuple()[:-1]) + self.assertEqual(0, t.tm_isdst) + # Same if utcoffset is None + class NOFS(DST): + def utcoffset(self, dt): + return None + d = cls(1, 2, 3, 10, 20, 30, 40, tzinfo=NOFS()) + t = d.utctimetuple() + self.assertEqual(t[:-1], d.timetuple()[:-1]) + self.assertEqual(0, t.tm_isdst) + # Check that bad tzinfo is detected + class BOFS(DST): + def utcoffset(self, dt): + return "EST" + d = cls(1, 2, 3, 10, 20, 30, 40, tzinfo=BOFS()) + self.assertRaises(TypeError, d.utctimetuple) + + # Check that utctimetuple() is the same as + # astimezone(utc).timetuple() + d = cls(2010, 11, 13, 14, 15, 16, 171819) + for tz in [timezone.min, timezone.utc, timezone.max]: + dtz = d.replace(tzinfo=tz) + self.assertEqual(dtz.utctimetuple()[:-1], + dtz.astimezone(timezone.utc).timetuple()[:-1]) + # At the edges, UTC adjustment can produce years out-of-range + # for a datetime object. Ensure that an OverflowError is + # raised. tiny = cls(MINYEAR, 1, 1, 0, 0, 37, tzinfo=UOFS(1439)) # That goes back 1 minute less than a full day. - t = tiny.utctimetuple() - self.assertEqual(t.tm_year, MINYEAR-1) - self.assertEqual(t.tm_mon, 12) - self.assertEqual(t.tm_mday, 31) - self.assertEqual(t.tm_hour, 0) - self.assertEqual(t.tm_min, 1) - self.assertEqual(t.tm_sec, 37) - self.assertEqual(t.tm_yday, 366) # "year 0" is a leap year - self.assertEqual(t.tm_isdst, 0) + self.assertRaises(OverflowError, tiny.utctimetuple) huge = cls(MAXYEAR, 12, 31, 23, 59, 37, 999999, tzinfo=UOFS(-1439)) # That goes forward 1 minute less than a full day. - t = huge.utctimetuple() - self.assertEqual(t.tm_year, MAXYEAR+1) - self.assertEqual(t.tm_mon, 1) - self.assertEqual(t.tm_mday, 1) - self.assertEqual(t.tm_hour, 23) - self.assertEqual(t.tm_min, 58) - self.assertEqual(t.tm_sec, 37) - self.assertEqual(t.tm_yday, 1) - self.assertEqual(t.tm_isdst, 0) + self.assertRaises(OverflowError, huge.utctimetuple) + # More overflow cases + tiny = cls.min.replace(tzinfo=timezone(MINUTE)) + self.assertRaises(OverflowError, tiny.utctimetuple) + huge = cls.max.replace(tzinfo=timezone(-MINUTE)) + self.assertRaises(OverflowError, huge.utctimetuple) def test_tzinfo_isoformat(self): zero = FixedOffset(0, "+00:00") @@ -3196,6 +3292,7 @@ return dt ZERO = timedelta(0) +MINUTE = timedelta(minutes=1) HOUR = timedelta(hours=1) DAY = timedelta(days=1) # In the US, DST starts at 2am (standard time) on the first Sunday in April. @@ -3439,6 +3536,19 @@ def dst(self, dt): return None self.assertRaises(ValueError, now.astimezone, notok()) + # Sometimes blow up. In the following, tzinfo.dst() + # implementation may return None or not None depending on + # whether DST is assumed to be in effect. In this situation, + # a ValueError should be raised by astimezone(). + class tricky_notok(ok): + def dst(self, dt): + if dt.year == 2000: + return None + else: + return 10*HOUR + dt = self.theclass(2001, 1, 1).replace(tzinfo=utc_real) + self.assertRaises(ValueError, dt.astimezone, tricky_notok()) + def test_fromutc(self): self.assertRaises(TypeError, Eastern.fromutc) # not enough args now = datetime.utcnow().replace(tzinfo=utc_real) Modified: python/branches/py3k-dtoa/Lib/test/test_descr.py ============================================================================== --- python/branches/py3k-dtoa/Lib/test/test_descr.py (original) +++ python/branches/py3k-dtoa/Lib/test/test_descr.py Tue Jul 6 17:55:27 2010 @@ -1,6 +1,7 @@ import builtins import sys import types +import math import unittest from copy import deepcopy @@ -1578,6 +1579,9 @@ ("__exit__", run_context, swallow, set(), {"__enter__" : iden}), ("__complex__", complex, complex_num, set(), {}), ("__format__", format, format_impl, set(), {}), + ("__floor__", math.floor, zero, set(), {}), + ("__trunc__", math.trunc, zero, set(), {}), + ("__ceil__", math.ceil, zero, set(), {}), ] class Checker(object): Modified: python/branches/py3k-dtoa/Lib/test/test_dict.py ============================================================================== --- python/branches/py3k-dtoa/Lib/test/test_dict.py (original) +++ python/branches/py3k-dtoa/Lib/test/test_dict.py Tue Jul 6 17:55:27 2010 @@ -664,6 +664,7 @@ gc.collect() self.assertTrue(gc.is_tracked(t), t) + @support.cpython_only def test_track_literals(self): # Test GC-optimization of dict literals x, y, z, w = 1.5, "a", (1, None), [] @@ -681,6 +682,7 @@ self._tracked({1: {}}) self._tracked({1: set()}) + @support.cpython_only def test_track_dynamic(self): # Test GC-optimization of dynamically-created dicts class MyObject(object): @@ -744,6 +746,7 @@ d.update([(x, y), (z, w)]) self._tracked(d) + @support.cpython_only def test_track_subtypes(self): # Dict subtypes are always tracked class MyDict(dict): Modified: python/branches/py3k-dtoa/Lib/test/test_dis.py ============================================================================== --- python/branches/py3k-dtoa/Lib/test/test_dis.py (original) +++ python/branches/py3k-dtoa/Lib/test/test_dis.py Tue Jul 6 17:55:27 2010 @@ -96,6 +96,46 @@ """ +expr_str = "x + 1" + +dis_expr_str = """\ + 1 0 LOAD_NAME 0 (x) + 3 LOAD_CONST 0 (1) + 6 BINARY_ADD + 7 RETURN_VALUE +""" + +simple_stmt_str = "x = x + 1" + +dis_simple_stmt_str = """\ + 1 0 LOAD_NAME 0 (x) + 3 LOAD_CONST 0 (1) + 6 BINARY_ADD + 7 STORE_NAME 0 (x) + 10 LOAD_CONST 1 (None) + 13 RETURN_VALUE +""" + +compound_stmt_str = """\ +x = 0 +while 1: + x += 1""" +# Trailing newline has been deliberately omitted + +dis_compound_stmt_str = """\ + 1 0 LOAD_CONST 0 (0) + 3 STORE_NAME 0 (x) + + 2 6 SETUP_LOOP 13 (to 22) + + 3 >> 9 LOAD_NAME 0 (x) + 12 LOAD_CONST 1 (1) + 15 INPLACE_ADD + 16 STORE_NAME 0 (x) + 19 JUMP_ABSOLUTE 9 + >> 22 LOAD_CONST 2 (None) + 25 RETURN_VALUE +""" class DisTests(unittest.TestCase): def do_disassembly_test(self, func, expected): @@ -166,6 +206,11 @@ from test import dis_module self.do_disassembly_test(dis_module, dis_module_expected_results) + def test_disassemble_str(self): + self.do_disassembly_test(expr_str, dis_expr_str) + self.do_disassembly_test(simple_stmt_str, dis_simple_stmt_str) + self.do_disassembly_test(compound_stmt_str, dis_compound_stmt_str) + def test_main(): run_unittest(DisTests) Modified: python/branches/py3k-dtoa/Lib/test/test_enumerate.py ============================================================================== --- python/branches/py3k-dtoa/Lib/test/test_enumerate.py (original) +++ python/branches/py3k-dtoa/Lib/test/test_enumerate.py Tue Jul 6 17:55:27 2010 @@ -103,6 +103,7 @@ self.assertRaises(TypeError, self.enum, 'abc', 'a') # wrong type self.assertRaises(TypeError, self.enum, 'abc', 2, 3) # too many arguments + @support.cpython_only def test_tuple_reuse(self): # Tests an implementation detail where tuple is reused # whenever nothing else holds a reference to it @@ -145,6 +146,7 @@ x = range(1) self.assertEqual(type(reversed(x)), type(iter(x))) + @support.cpython_only def test_len(self): # This is an implementation detail, not an interface requirement from test.test_iterlen import len Modified: python/branches/py3k-dtoa/Lib/test/test_exceptions.py ============================================================================== --- python/branches/py3k-dtoa/Lib/test/test_exceptions.py (original) +++ python/branches/py3k-dtoa/Lib/test/test_exceptions.py Tue Jul 6 17:55:27 2010 @@ -7,7 +7,7 @@ import weakref from test.support import (TESTFN, unlink, run_unittest, captured_output, - gc_collect) + gc_collect, cpython_only) # XXX This is not really enough, each *operation* should be tested! @@ -137,6 +137,7 @@ ckmsg(s, "'continue' not properly in loop") ckmsg("continue\n", "'continue' not properly in loop") + @cpython_only def testSettingException(self): # test that setting an exception at the C level works even if the # exception object can't be constructed. @@ -669,6 +670,7 @@ tb2 = raiseMemError() self.assertEqual(tb1, tb2) + @cpython_only def test_exception_with_doc(self): import _testcapi doc2 = "This is a test docstring." Modified: python/branches/py3k-dtoa/Lib/test/test_extcall.py ============================================================================== --- python/branches/py3k-dtoa/Lib/test/test_extcall.py (original) +++ python/branches/py3k-dtoa/Lib/test/test_extcall.py Tue Jul 6 17:55:27 2010 @@ -279,13 +279,13 @@ >>> f(6, a=4, *(1, 2, 3)) Traceback (most recent call last): ... - TypeError: f() takes exactly 1 argument (5 given) + TypeError: f() takes exactly 1 positional argument (5 given) >>> def f(a, *, kw): ... pass >>> f(6, 4, kw=4) Traceback (most recent call last): ... - TypeError: f() takes exactly 2 arguments (3 given) + TypeError: f() takes exactly 1 positional argument (3 given) """ import sys Modified: python/branches/py3k-dtoa/Lib/test/test_float.py ============================================================================== --- python/branches/py3k-dtoa/Lib/test/test_float.py (original) +++ python/branches/py3k-dtoa/Lib/test/test_float.py Tue Jul 6 17:55:27 2010 @@ -7,13 +7,17 @@ from math import isinf, isnan, copysign, ldexp import operator import random, fractions -import re INF = float("inf") NAN = float("nan") +have_getformat = hasattr(float, "__getformat__") +requires_getformat = unittest.skipUnless(have_getformat, + "requires __getformat__") +requires_setformat = unittest.skipUnless(hasattr(float, "__setformat__"), + "requires __setformat__") # decorator for skipping tests on non-IEEE 754 platforms -requires_IEEE_754 = unittest.skipUnless( +requires_IEEE_754 = unittest.skipUnless(have_getformat and float.__getformat__("double").startswith("IEEE"), "test requires IEEE 754 doubles") @@ -21,74 +25,6 @@ test_dir = os.path.dirname(__file__) or os.curdir format_testfile = os.path.join(test_dir, 'formatfloat_testcases.txt') -finite_decimal_parser = re.compile(r""" # A numeric string consists of: - (?P[-+])? # an optional sign, followed by - (?=\d|\.\d) # a number with at least one digit - (?P\d*) # having a (possibly empty) integer part - (?:\.(?P\d*))? # followed by an optional fractional part - (?:E(?P[-+]?\d+))? # and an optional exponent - \Z -""", re.VERBOSE | re.IGNORECASE | re.UNICODE).match - -# Pure Python version of correctly rounded string->float conversion. -# Avoids any use of floating-point by returning the result as a hex string. -def strtod(s, mant_dig=53, min_exp = -1021, max_exp = 1024): - """Convert a finite decimal string to a hex string representing an - IEEE 754 binary64 float. Return 'inf' or '-inf' on overflow. - This function makes no use of floating-point arithmetic at any - stage.""" - - # parse string into a pair of integers 'a' and 'b' such that - # abs(decimal value) = a/b, and a boolean 'negative'. - m = finite_decimal_parser(s) - if m is None: - raise ValueError('invalid numeric string') - fraction = m.group('frac') or '' - intpart = int(m.group('int') + fraction) - exp = int(m.group('exp') or '0') - len(fraction) - negative = m.group('sign') == '-' - a, b = intpart*10**max(exp, 0), 10**max(0, -exp) - - # quick return for zeros - if not a: - return '-0x0.0p+0' if negative else '0x0.0p+0' - - # compute exponent e for result; may be one too small in the case - # that the rounded value of a/b lies in a different binade from a/b - d = a.bit_length() - b.bit_length() - d += (a >> d if d >= 0 else a << -d) >= b - e = max(d, min_exp) - mant_dig - - # approximate a/b by number of the form q * 2**e; adjust e if necessary - a, b = a << max(-e, 0), b << max(e, 0) - q, r = divmod(a, b) - if 2*r > b or 2*r == b and q & 1: - q += 1 - if q.bit_length() == mant_dig+1: - q //= 2 - e += 1 - - # double check that (q, e) has the right form - assert q.bit_length() <= mant_dig and e >= min_exp - mant_dig - assert q.bit_length() == mant_dig or e == min_exp - mant_dig - - # check for overflow and underflow - if e + q.bit_length() > max_exp: - return '-inf' if negative else 'inf' - if not q: - return '-0x0.0p+0' if negative else '0x0.0p+0' - - # for hex representation, shift so # bits after point is a multiple of 4 - hexdigs = 1 + (mant_dig-2)//4 - shift = 3 - (mant_dig-2)%4 - q, e = q << shift, e - shift - return '{}0x{:x}.{:0{}x}p{:+d}'.format( - '-' if negative else '', - q // 16**hexdigs, - q % 16**hexdigs, - hexdigs, - e + 4*hexdigs) - class GeneralFloatCases(unittest.TestCase): def test_float(self): @@ -446,6 +382,7 @@ #self.assertTrue(0.0 > pow_op(-2.0, -1047) > -1e-315) + at requires_setformat class FormatFunctionsTestCase(unittest.TestCase): def setUp(self): @@ -496,6 +433,7 @@ # on non-IEEE platforms, attempting to unpack a bit pattern # representing an infinity or a NaN should raise an exception. + at requires_setformat class UnknownFormatTestCase(unittest.TestCase): def setUp(self): self.save_formats = {'double':float.__getformat__('double'), @@ -528,36 +466,25 @@ # let's also try to guarantee that -0.0 and 0.0 don't get confused. class IEEEFormatTestCase(unittest.TestCase): - if float.__getformat__("double").startswith("IEEE"): - def test_double_specials_do_unpack(self): - for fmt, data in [('>d', BE_DOUBLE_INF), - ('>d', BE_DOUBLE_NAN), - ('f', BE_FLOAT_INF), - ('>f', BE_FLOAT_NAN), - ('d', BE_DOUBLE_INF), + ('>d', BE_DOUBLE_NAN), + ('f', BE_FLOAT_INF), + ('>f', BE_FLOAT_NAN), + ('float conversion for " - "{}: expected {}, got {}".format(s, expected, got)) - - @unittest.skipUnless(getattr(sys, 'float_repr_style', '') == 'short', - "applies only when using short float repr style") - def test_bug7632(self): - # check a few particular values that gave incorrectly rounded - # results with previous versions of dtoa.c - test_strings = [ - '94393431193180696942841837085033647913224148539854e-358', - '12579816049008305546974391768996369464963024663104e-357', - '17489628565202117263145367596028389348922981857013e-357', - '18487398785991994634182916638542680759613590482273e-357', - '32002864200581033134358724675198044527469366773928e-358', - '73608278998966969345824653500136787876436005957953e-358', - '64774478836417299491718435234611299336288082136054e-358', - '13704940134126574534878641876947980878824688451169e-357', - '46697445774047060960624497964425416610480524760471e-358', - ] - for s in test_strings: - self.check_string(s) - def test_main(): support.run_unittest( @@ -1378,7 +1264,6 @@ RoundTestCase, InfNanTest, HexFloatTestCase, - StrtodTestCase, ) if __name__ == '__main__': Modified: python/branches/py3k-dtoa/Lib/test/test_genericpath.py ============================================================================== --- python/branches/py3k-dtoa/Lib/test/test_genericpath.py (original) +++ python/branches/py3k-dtoa/Lib/test/test_genericpath.py Tue Jul 6 17:55:27 2010 @@ -194,14 +194,18 @@ ] def test_normcase(self): - # Check that normcase() is idempotent - p = "FoO/./BaR" - p = self.pathmodule.normcase(p) - self.assertEqual(p, self.pathmodule.normcase(p)) - - p = b"FoO/./BaR" - p = self.pathmodule.normcase(p) - self.assertEqual(p, self.pathmodule.normcase(p)) + normcase = self.pathmodule.normcase + # check that normcase() is idempotent + for p in ["FoO/./BaR", b"FoO/./BaR"]: + p = normcase(p) + self.assertEqual(p, normcase(p)) + + self.assertEqual(normcase(''), '') + self.assertEqual(normcase(b''), b'') + + # check that normcase raises a TypeError for invalid types + for path in (None, True, 0, 2.5, [], bytearray(b''), {'o','o'}): + self.assertRaises(TypeError, normcase, path) def test_splitdrive(self): # splitdrive for non-NT paths Modified: python/branches/py3k-dtoa/Lib/test/test_getargs2.py ============================================================================== --- python/branches/py3k-dtoa/Lib/test/test_getargs2.py (original) +++ python/branches/py3k-dtoa/Lib/test/test_getargs2.py Tue Jul 6 17:55:27 2010 @@ -325,7 +325,7 @@ from _testcapi import getargs_z self.assertEqual(getargs_z('abc\xe9'), b'abc\xc3\xa9') self.assertRaises(TypeError, getargs_z, 'nul:\0') - self.assertEqual(getargs_z(b'bytes'), b'bytes') + self.assertRaises(TypeError, getargs_z, b'bytes') self.assertRaises(TypeError, getargs_z, bytearray(b'bytearray')) self.assertRaises(TypeError, getargs_z, memoryview(b'memoryview')) self.assertIsNone(getargs_z(None)) @@ -375,6 +375,16 @@ self.assertRaises(TypeError, getargs_y_hash, memoryview(b'memoryview')) self.assertRaises(TypeError, getargs_y_hash, None) + def test_w_star(self): + # getargs_w_star() modifies first and last byte + from _testcapi import getargs_w_star + self.assertRaises(TypeError, getargs_w_star, 'abc\xe9') + self.assertRaises(TypeError, getargs_w_star, b'bytes') + self.assertRaises(TypeError, getargs_w_star, b'nul:\0') + self.assertEqual(getargs_w_star(bytearray(b'bytearray')), b'[ytearra]') + self.assertEqual(getargs_w_star(memoryview(b'memoryview')), b'[emoryvie]') + self.assertRaises(TypeError, getargs_w_star, None) + class Unicode_TestCase(unittest.TestCase): def test_u(self): Modified: python/branches/py3k-dtoa/Lib/test/test_http_cookiejar.py ============================================================================== --- python/branches/py3k-dtoa/Lib/test/test_http_cookiejar.py (original) +++ python/branches/py3k-dtoa/Lib/test/test_http_cookiejar.py Tue Jul 6 17:55:27 2010 @@ -97,6 +97,7 @@ class HeaderTests(TestCase): + def test_parse_ns_headers(self): # quotes should be stripped expected = [[('foo', 'bar'), ('expires', 2209069412), ('version', '0')]] @@ -106,6 +107,16 @@ ]: self.assertEquals(parse_ns_headers([hdr]), expected) + def test_parse_ns_headers_version(self): + + # quotes should be stripped + expected = [[('foo', 'bar'), ('version', '1')]] + for hdr in [ + 'foo=bar; version="1"', + 'foo=bar; Version="1"', + ]: + self.assertEquals(parse_ns_headers([hdr]), expected) + def test_parse_ns_headers_special_names(self): # names such as 'expires' are not special in first name=value pair # of Set-Cookie: header @@ -1020,6 +1031,8 @@ ["Set-Cookie2: a=foo; path=/; Version=1; domain"], # bad max-age ["Set-Cookie: b=foo; max-age=oops"], + # bad version + ["Set-Cookie: b=foo; version=spam"], ]: c = cookiejar_from_cookie_headers(headers) # these bad cookies shouldn't be set Modified: python/branches/py3k-dtoa/Lib/test/test_imp.py ============================================================================== --- python/branches/py3k-dtoa/Lib/test/test_imp.py (original) +++ python/branches/py3k-dtoa/Lib/test/test_imp.py Tue Jul 6 17:55:27 2010 @@ -44,7 +44,7 @@ class ImportTests(unittest.TestCase): def test_find_module_encoding(self): - fd = imp.find_module("heapq")[0] + fd = imp.find_module("pydoc")[0] self.assertEqual(fd.encoding, "iso-8859-1") def test_issue1267(self): Modified: python/branches/py3k-dtoa/Lib/test/test_import.py ============================================================================== --- python/branches/py3k-dtoa/Lib/test/test_import.py (original) +++ python/branches/py3k-dtoa/Lib/test/test_import.py Tue Jul 6 17:55:27 2010 @@ -147,22 +147,24 @@ filename = module + '.py' # Create a file with a list of 65000 elements. - with open(filename, 'w+') as f: + with open(filename, 'w') as f: f.write('d = [\n') for i in range(65000): f.write('"",\n') f.write(']') - # Compile & remove .py file; we only need .pyc (or .pyo). - # Bytecode must be relocated from the PEP 3147 bytecode-only location. - py_compile.compile(filename) - unlink(filename) - make_legacy_pyc(filename) + try: + # Compile & remove .py file; we only need .pyc (or .pyo). + # Bytecode must be relocated from the PEP 3147 bytecode-only location. + py_compile.compile(filename) + finally: + unlink(filename) # Need to be able to load from current dir. sys.path.append('') try: + make_legacy_pyc(filename) # This used to crash. exec('import ' + module) finally: @@ -468,6 +470,17 @@ ns = dict(__package__=object()) self.assertRaises(ValueError, check_relative) + def test_absolute_import_without_future(self): + # If absolute import syntax is used, then do not try to perform + # a relative import in the face of failure. + # Issue #7902. + try: + from .os import sep + except ImportError: + pass + else: + self.fail("explicit relative import triggered an " + "implicit relative import") class OverridingImportBuiltinTests(unittest.TestCase): def test_override_builtin(self): Modified: python/branches/py3k-dtoa/Lib/test/test_inspect.py ============================================================================== --- python/branches/py3k-dtoa/Lib/test/test_inspect.py (original) +++ python/branches/py3k-dtoa/Lib/test/test_inspect.py Tue Jul 6 17:55:27 2010 @@ -3,6 +3,7 @@ import types import unittest import inspect +import linecache import datetime import collections from os.path import normcase @@ -275,6 +276,11 @@ def test_getsourcefile(self): self.assertEqual(normcase(inspect.getsourcefile(mod.spam)), modfile) self.assertEqual(normcase(inspect.getsourcefile(git.abuse)), modfile) + fn = "_non_existing_filename_used_for_sourcefile_test.py" + co = compile("None", fn, "exec") + self.assertEqual(inspect.getsourcefile(co), None) + linecache.cache[co.co_filename] = (1, None, "None", co.co_filename) + self.assertEqual(normcase(inspect.getsourcefile(co)), fn) def test_getfile(self): self.assertEqual(inspect.getfile(mod.StupidGit), mod.__file__) @@ -373,6 +379,15 @@ self.assertRaises(IOError, inspect.getsource, unicodedata) self.assertRaises(IOError, inspect.findsource, unicodedata) + def test_findsource_code_in_linecache(self): + lines = ["x=1"] + co = compile(lines[0], "_dynamically_created_file", "exec") + self.assertRaises(IOError, inspect.findsource, co) + self.assertRaises(IOError, inspect.getsource, co) + linecache.cache[co.co_filename] = (1, None, lines, co.co_filename) + self.assertEquals(inspect.findsource(co), (lines,0)) + self.assertEquals(inspect.getsource(co), lines[0]) + # Helper for testing classify_class_attrs. def attrs_wo_objs(cls): return [t[:3] for t in inspect.classify_class_attrs(cls)] Modified: python/branches/py3k-dtoa/Lib/test/test_iter.py ============================================================================== --- python/branches/py3k-dtoa/Lib/test/test_iter.py (original) +++ python/branches/py3k-dtoa/Lib/test/test_iter.py Tue Jul 6 17:55:27 2010 @@ -1,7 +1,7 @@ # Test iterators. import unittest -from test.support import run_unittest, TESTFN, unlink +from test.support import run_unittest, TESTFN, unlink, cpython_only # Test result of triple loop (too big to inline) TRIPLETS = [(0, 0, 0), (0, 0, 1), (0, 0, 2), @@ -761,8 +761,9 @@ (a, b), (c,) = IteratingSequenceClass(2), {42: 24} self.assertEqual((a, b, c), (0, 1, 42)) - # Test reference count behavior + @cpython_only + def test_ref_counting_behavior(self): class C(object): count = 0 def __new__(cls): Modified: python/branches/py3k-dtoa/Lib/test/test_keywordonlyarg.py ============================================================================== --- python/branches/py3k-dtoa/Lib/test/test_keywordonlyarg.py (original) +++ python/branches/py3k-dtoa/Lib/test/test_keywordonlyarg.py Tue Jul 6 17:55:27 2010 @@ -73,6 +73,14 @@ fundef3 += "lastarg):\n pass\n" compile(fundef3, "", "single") + def testTooManyPositionalErrorMessage(self): + def f(a, b=None, *, c=None): + pass + with self.assertRaises(TypeError) as exc: + f(1, 2, 3) + expected = "f() takes at most 2 positional arguments (3 given)" + self.assertEqual(str(exc.exception), expected) + def testSyntaxErrorForFunctionCall(self): self.assertRaisesSyntaxError("f(p, k=1, p2)") self.assertRaisesSyntaxError("f(p, k1=50, *(1,2), k1=100)") Modified: python/branches/py3k-dtoa/Lib/test/test_logging.py ============================================================================== --- python/branches/py3k-dtoa/Lib/test/test_logging.py (original) +++ python/branches/py3k-dtoa/Lib/test/test_logging.py Tue Jul 6 17:55:27 2010 @@ -1670,6 +1670,8 @@ t = logging.config.listen(port) t.start() t.ready.wait() + # Now get the port allocated + port = t.port t.ready.clear() try: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) Modified: python/branches/py3k-dtoa/Lib/test/test_math.py ============================================================================== --- python/branches/py3k-dtoa/Lib/test/test_math.py (original) +++ python/branches/py3k-dtoa/Lib/test/test_math.py Tue Jul 6 17:55:27 2010 @@ -923,13 +923,6 @@ self.assertRaises(TypeError, math.trunc, 1, 2) self.assertRaises(TypeError, math.trunc, TestNoTrunc()) - # XXX Doesn't work because the method is looked up on - # the type only. - #t = TestNoTrunc() - #t.__trunc__ = lambda *args: args - #self.assertEquals((), math.trunc(t)) - #self.assertRaises(TypeError, math.trunc, t, 0) - def testIsnan(self): self.assertTrue(math.isnan(float("nan"))) self.assertTrue(math.isnan(float("inf")* 0.)) Modified: python/branches/py3k-dtoa/Lib/test/test_optparse.py ============================================================================== --- python/branches/py3k-dtoa/Lib/test/test_optparse.py (original) +++ python/branches/py3k-dtoa/Lib/test/test_optparse.py Tue Jul 6 17:55:27 2010 @@ -754,6 +754,11 @@ {'a': "-b3", 'boo': None, 'foo': None}, []) + def test_combined_single_invalid_option(self): + self.parser.add_option("-t", action="store_true") + self.assertParseFail(["-test"], + "no such option: -e") + class TestBool(BaseTest): def setUp(self): options = [make_option("-v", Modified: python/branches/py3k-dtoa/Lib/test/test_os.py ============================================================================== --- python/branches/py3k-dtoa/Lib/test/test_os.py (original) +++ python/branches/py3k-dtoa/Lib/test/test_os.py Tue Jul 6 17:55:27 2010 @@ -58,6 +58,7 @@ os.closerange(first, first + 2) self.assertRaises(OSError, os.write, first, b"a") + @support.cpython_only def test_rename(self): path = support.TESTFN old = sys.getrefcount(path) Modified: python/branches/py3k-dtoa/Lib/test/test_parser.py ============================================================================== --- python/branches/py3k-dtoa/Lib/test/test_parser.py (original) +++ python/branches/py3k-dtoa/Lib/test/test_parser.py Tue Jul 6 17:55:27 2010 @@ -149,6 +149,13 @@ def test_class_defs(self): self.check_suite("class foo():pass") self.check_suite("class foo(object):pass") + self.check_suite("@class_decorator\n" + "class foo():pass") + self.check_suite("@class_decorator(arg)\n" + "class foo():pass") + self.check_suite("@decorator1\n" + "@decorator2\n" + "class foo():pass") def test_import_from_statement(self): self.check_suite("from sys.path import *") @@ -182,6 +189,18 @@ self.check_suite("import sys as system, math") self.check_suite("import sys, math as my_math") + def test_relative_imports(self): + self.check_suite("from . import name") + self.check_suite("from .. import name") + # check all the way up to '....', since '...' is tokenized + # differently from '.' (it's an ellipsis token). + self.check_suite("from ... import name") + self.check_suite("from .... import name") + self.check_suite("from .pkg import name") + self.check_suite("from ..pkg import name") + self.check_suite("from ...pkg import name") + self.check_suite("from ....pkg import name") + def test_pep263(self): self.check_suite("# -*- coding: iso-8859-1 -*-\n" "pass\n") @@ -457,6 +476,20 @@ (0, '')) self.check_bad_tree(tree, "malformed global ast") + def test_missing_import_source(self): + # from import fred + tree = \ + (257, + (268, + (269, + (270, + (282, + (284, (1, 'from'), (1, 'import'), + (287, (285, (1, 'fred')))))), + (4, ''))), + (4, ''), (0, '')) + self.check_bad_tree(tree, "from import fred") + class CompileTestCase(unittest.TestCase): @@ -484,8 +517,18 @@ st = parser.suite('a = "\\u1"') self.assertRaises(SyntaxError, parser.compilest, st) + def test_issue_9011(self): + # Issue 9011: compilation of an unary minus expression changed + # the meaning of the ST, so that a second compilation produced + # incorrect results. + st = parser.expr('-3') + code1 = parser.compilest(st) + self.assertEqual(eval(code1), -3) + code2 = parser.compilest(st) + self.assertEqual(eval(code2), -3) + class ParserStackLimitTestCase(unittest.TestCase): - """try to push the parser to/over it's limits. + """try to push the parser to/over its limits. see http://bugs.python.org/issue1881 for a discussion """ def _nested_expression(self, level): Modified: python/branches/py3k-dtoa/Lib/test/test_property.py ============================================================================== --- python/branches/py3k-dtoa/Lib/test/test_property.py (original) +++ python/branches/py3k-dtoa/Lib/test/test_property.py Tue Jul 6 17:55:27 2010 @@ -118,7 +118,7 @@ self.assertEqual(base.__class__.spam.__doc__, "spam spam spam") self.assertEqual(sub.__class__.spam.__doc__, "spam spam spam") - @unittest.skipIf(sys.flags.optimize >= 1, + @unittest.skipIf(sys.flags.optimize >= 2, "Docstrings are omitted with -O2 and above") def test_property_getter_doc_override(self): newgettersub = PropertySubNewGetter() Modified: python/branches/py3k-dtoa/Lib/test/test_pyexpat.py ============================================================================== --- python/branches/py3k-dtoa/Lib/test/test_pyexpat.py (original) +++ python/branches/py3k-dtoa/Lib/test/test_pyexpat.py Tue Jul 6 17:55:27 2010 @@ -184,7 +184,7 @@ self.fail() except TypeError as e: self.assertEquals(str(e), - 'ParserCreate() argument 2 must be string or None, not int') + 'ParserCreate() argument 2 must be str or None, not int') try: expat.ParserCreate(namespace_separator='too long') Modified: python/branches/py3k-dtoa/Lib/test/test_runpy.py ============================================================================== --- python/branches/py3k-dtoa/Lib/test/test_runpy.py (original) +++ python/branches/py3k-dtoa/Lib/test/test_runpy.py Tue Jul 6 17:55:27 2010 @@ -6,7 +6,7 @@ import re import tempfile import py_compile -from test.support import forget, make_legacy_pyc, run_unittest, verbose +from test.support import forget, make_legacy_pyc, run_unittest, unload, verbose from test.script_helper import ( make_pkg, make_script, make_zip_pkg, make_zip_script, temp_dir) @@ -174,6 +174,7 @@ __import__(mod_name) os.remove(mod_fname) make_legacy_pyc(mod_fname) + unload(mod_name) # In case loader caches paths if verbose: print("Running from compiled:", mod_name) d2 = run_module(mod_name) # Read from bytecode self.assertIn("x", d2) @@ -197,6 +198,7 @@ __import__(mod_name) os.remove(mod_fname) make_legacy_pyc(mod_fname) + unload(mod_name) # In case loader caches paths if verbose: print("Running from compiled:", pkg_name) d2 = run_module(pkg_name) # Read from bytecode self.assertIn("x", d2) @@ -252,6 +254,7 @@ __import__(mod_name) os.remove(mod_fname) make_legacy_pyc(mod_fname) + unload(mod_name) # In case the loader caches paths if verbose: print("Running from compiled:", mod_name) d2 = run_module(mod_name, run_name=run_name) # Read from bytecode self.assertIn("__package__", d2) @@ -405,7 +408,11 @@ def test_main(): - run_unittest(RunModuleCodeTest, RunModuleTest, RunPathTest) + run_unittest( + RunModuleCodeTest, + RunModuleTest, + RunPathTest + ) if __name__ == "__main__": test_main() Modified: python/branches/py3k-dtoa/Lib/test/test_strtod.py ============================================================================== --- python/branches/py3k-dtoa/Lib/test/test_strtod.py (original) +++ python/branches/py3k-dtoa/Lib/test/test_strtod.py Tue Jul 6 17:55:27 2010 @@ -23,6 +23,8 @@ \Z """, re.VERBOSE | re.IGNORECASE).match +# Pure Python version of correctly rounded string->float conversion. +# Avoids any use of floating-point by returning the result as a hex string. def strtod(s, mant_dig=53, min_exp = -1021, max_exp = 1024): """Convert a finite decimal string to a hex string representing an IEEE 754 binary64 float. Return 'inf' or '-inf' on overflow. @@ -330,6 +332,10 @@ '18487398785991994634182916638542680759613590482273e-357', '32002864200581033134358724675198044527469366773928e-358', '94393431193180696942841837085033647913224148539854e-358', + '73608278998966969345824653500136787876436005957953e-358', + '64774478836417299491718435234611299336288082136054e-358', + '13704940134126574534878641876947980878824688451169e-357', + '46697445774047060960624497964425416610480524760471e-358', # failing case for bug introduced by METD in r77451 (attempted # fix for issue 7632, bug 2), and fixed in r77482. '28639097178261763178489759107321392745108491825303e-311', Modified: python/branches/py3k-dtoa/Lib/test/test_subprocess.py ============================================================================== --- python/branches/py3k-dtoa/Lib/test/test_subprocess.py (original) +++ python/branches/py3k-dtoa/Lib/test/test_subprocess.py Tue Jul 6 17:55:27 2010 @@ -478,8 +478,6 @@ '"a\\\\b\\ c" d e') self.assertEqual(subprocess.list2cmdline(['ab', '']), 'ab ""') - self.assertEqual(subprocess.list2cmdline(['echo', 'foo|bar']), - 'echo "foo|bar"') def test_poll(self): Modified: python/branches/py3k-dtoa/Lib/test/test_syntax.py ============================================================================== --- python/branches/py3k-dtoa/Lib/test/test_syntax.py (original) +++ python/branches/py3k-dtoa/Lib/test/test_syntax.py Tue Jul 6 17:55:27 2010 @@ -478,10 +478,12 @@ >>> del () Traceback (most recent call last): - ... - File "", line 1 SyntaxError: can't delete () +>>> {1, 2, 3} = 42 +Traceback (most recent call last): +SyntaxError: can't assign to literal + """ import re Modified: python/branches/py3k-dtoa/Lib/test/test_tokenize.py ============================================================================== --- python/branches/py3k-dtoa/Lib/test/test_tokenize.py (original) +++ python/branches/py3k-dtoa/Lib/test/test_tokenize.py Tue Jul 6 17:55:27 2010 @@ -42,7 +42,7 @@ ... IndentationError: unindent does not match any outer indentation level -There are some standard formattig practises that are easy to get right. +There are some standard formatting practices that are easy to get right. >>> roundtrip("if x == 1:\\n" ... " print(x)\\n") Modified: python/branches/py3k-dtoa/Lib/test/test_tuple.py ============================================================================== --- python/branches/py3k-dtoa/Lib/test/test_tuple.py (original) +++ python/branches/py3k-dtoa/Lib/test/test_tuple.py Tue Jul 6 17:55:27 2010 @@ -96,6 +96,7 @@ gc.collect() self.assertTrue(gc.is_tracked(t), t) + @support.cpython_only def test_track_literals(self): # Test GC-optimization of tuple literals x, y, z = 1.5, "a", [] @@ -136,16 +137,19 @@ self._tracked(tp(tuple([obj]) for obj in [x, y, z])) self._tracked(tuple(tp([obj]) for obj in [x, y, z])) + @support.cpython_only def test_track_dynamic(self): # Test GC-optimization of dynamically constructed tuples. self.check_track_dynamic(tuple, False) + @support.cpython_only def test_track_subtypes(self): # Tuple subtypes must always be tracked class MyTuple(tuple): pass self.check_track_dynamic(MyTuple, True) + @support.cpython_only def test_bug7466(self): # Trying to untrack an unfinished tuple could crash Python self._not_tracked(tuple(gc.collect() for i in range(101))) Modified: python/branches/py3k-dtoa/Lib/test/test_unicode.py ============================================================================== --- python/branches/py3k-dtoa/Lib/test/test_unicode.py (original) +++ python/branches/py3k-dtoa/Lib/test/test_unicode.py Tue Jul 6 17:55:27 2010 @@ -942,6 +942,159 @@ # * strict decoding testing for all of the # UTF8_ERROR cases in PyUnicode_DecodeUTF8 + def test_utf8_decode_valid_sequences(self): + sequences = [ + # single byte + (b'\x00', '\x00'), (b'a', 'a'), (b'\x7f', '\x7f'), + # 2 bytes + (b'\xc2\x80', '\x80'), (b'\xdf\xbf', '\u07ff'), + # 3 bytes + (b'\xe0\xa0\x80', '\u0800'), (b'\xed\x9f\xbf', '\ud7ff'), + (b'\xee\x80\x80', '\uE000'), (b'\xef\xbf\xbf', '\uffff'), + # 4 bytes + (b'\xF0\x90\x80\x80', '\U00010000'), + (b'\xf4\x8f\xbf\xbf', '\U0010FFFF') + ] + for seq, res in sequences: + self.assertEqual(seq.decode('utf-8'), res) + + + def test_utf8_decode_invalid_sequences(self): + # continuation bytes in a sequence of 2, 3, or 4 bytes + continuation_bytes = [bytes([x]) for x in range(0x80, 0xC0)] + # start bytes of a 2-byte sequence equivalent to codepoints < 0x7F + invalid_2B_seq_start_bytes = [bytes([x]) for x in range(0xC0, 0xC2)] + # start bytes of a 4-byte sequence equivalent to codepoints > 0x10FFFF + invalid_4B_seq_start_bytes = [bytes([x]) for x in range(0xF5, 0xF8)] + invalid_start_bytes = ( + continuation_bytes + invalid_2B_seq_start_bytes + + invalid_4B_seq_start_bytes + [bytes([x]) for x in range(0xF7, 0x100)] + ) + + for byte in invalid_start_bytes: + self.assertRaises(UnicodeDecodeError, byte.decode, 'utf-8') + + for sb in invalid_2B_seq_start_bytes: + for cb in continuation_bytes: + self.assertRaises(UnicodeDecodeError, (sb+cb).decode, 'utf-8') + + for sb in invalid_4B_seq_start_bytes: + for cb1 in continuation_bytes[:3]: + for cb3 in continuation_bytes[:3]: + self.assertRaises(UnicodeDecodeError, + (sb+cb1+b'\x80'+cb3).decode, 'utf-8') + + for cb in [bytes([x]) for x in range(0x80, 0xA0)]: + self.assertRaises(UnicodeDecodeError, + (b'\xE0'+cb+b'\x80').decode, 'utf-8') + self.assertRaises(UnicodeDecodeError, + (b'\xE0'+cb+b'\xBF').decode, 'utf-8') + # surrogates + for cb in [bytes([x]) for x in range(0xA0, 0xC0)]: + self.assertRaises(UnicodeDecodeError, + (b'\xED'+cb+b'\x80').decode, 'utf-8') + self.assertRaises(UnicodeDecodeError, + (b'\xED'+cb+b'\xBF').decode, 'utf-8') + for cb in [bytes([x]) for x in range(0x80, 0x90)]: + self.assertRaises(UnicodeDecodeError, + (b'\xF0'+cb+b'\x80\x80').decode, 'utf-8') + self.assertRaises(UnicodeDecodeError, + (b'\xF0'+cb+b'\xBF\xBF').decode, 'utf-8') + for cb in [bytes([x]) for x in range(0x90, 0xC0)]: + self.assertRaises(UnicodeDecodeError, + (b'\xF4'+cb+b'\x80\x80').decode, 'utf-8') + self.assertRaises(UnicodeDecodeError, + (b'\xF4'+cb+b'\xBF\xBF').decode, 'utf-8') + + def test_issue8271(self): + # Issue #8271: during the decoding of an invalid UTF-8 byte sequence, + # only the start byte and the continuation byte(s) are now considered + # invalid, instead of the number of bytes specified by the start byte. + # See http://www.unicode.org/versions/Unicode5.2.0/ch03.pdf (page 95, + # table 3-8, Row 2) for more information about the algorithm used. + FFFD = '\ufffd' + sequences = [ + # invalid start bytes + (b'\x80', FFFD), # continuation byte + (b'\x80\x80', FFFD*2), # 2 continuation bytes + (b'\xc0', FFFD), + (b'\xc0\xc0', FFFD*2), + (b'\xc1', FFFD), + (b'\xc1\xc0', FFFD*2), + (b'\xc0\xc1', FFFD*2), + # with start byte of a 2-byte sequence + (b'\xc2', FFFD), # only the start byte + (b'\xc2\xc2', FFFD*2), # 2 start bytes + (b'\xc2\xc2\xc2', FFFD*3), # 2 start bytes + (b'\xc2\x41', FFFD+'A'), # invalid continuation byte + # with start byte of a 3-byte sequence + (b'\xe1', FFFD), # only the start byte + (b'\xe1\xe1', FFFD*2), # 2 start bytes + (b'\xe1\xe1\xe1', FFFD*3), # 3 start bytes + (b'\xe1\xe1\xe1\xe1', FFFD*4), # 4 start bytes + (b'\xe1\x80', FFFD), # only 1 continuation byte + (b'\xe1\x41', FFFD+'A'), # invalid continuation byte + (b'\xe1\x41\x80', FFFD+'A'+FFFD), # invalid cb followed by valid cb + (b'\xe1\x41\x41', FFFD+'AA'), # 2 invalid continuation bytes + (b'\xe1\x80\x41', FFFD+'A'), # only 1 valid continuation byte + (b'\xe1\x80\xe1\x41', FFFD*2+'A'), # 1 valid and the other invalid + (b'\xe1\x41\xe1\x80', FFFD+'A'+FFFD), # 1 invalid and the other valid + # with start byte of a 4-byte sequence + (b'\xf1', FFFD), # only the start byte + (b'\xf1\xf1', FFFD*2), # 2 start bytes + (b'\xf1\xf1\xf1', FFFD*3), # 3 start bytes + (b'\xf1\xf1\xf1\xf1', FFFD*4), # 4 start bytes + (b'\xf1\xf1\xf1\xf1\xf1', FFFD*5), # 5 start bytes + (b'\xf1\x80', FFFD), # only 1 continuation bytes + (b'\xf1\x80\x80', FFFD), # only 2 continuation bytes + (b'\xf1\x80\x41', FFFD+'A'), # 1 valid cb and 1 invalid + (b'\xf1\x80\x41\x41', FFFD+'AA'), # 1 valid cb and 1 invalid + (b'\xf1\x80\x80\x41', FFFD+'A'), # 2 valid cb and 1 invalid + (b'\xf1\x41\x80', FFFD+'A'+FFFD), # 1 invalid cv and 1 valid + (b'\xf1\x41\x80\x80', FFFD+'A'+FFFD*2), # 1 invalid cb and 2 invalid + (b'\xf1\x41\x80\x41', FFFD+'A'+FFFD+'A'), # 2 invalid cb and 1 invalid + (b'\xf1\x41\x41\x80', FFFD+'AA'+FFFD), # 1 valid cb and 1 invalid + (b'\xf1\x41\xf1\x80', FFFD+'A'+FFFD), + (b'\xf1\x41\x80\xf1', FFFD+'A'+FFFD*2), + (b'\xf1\xf1\x80\x41', FFFD*2+'A'), + (b'\xf1\x41\xf1\xf1', FFFD+'A'+FFFD*2), + # with invalid start byte of a 4-byte sequence (rfc2279) + (b'\xf5', FFFD), # only the start byte + (b'\xf5\xf5', FFFD*2), # 2 start bytes + (b'\xf5\x80', FFFD*2), # only 1 continuation byte + (b'\xf5\x80\x80', FFFD*3), # only 2 continuation byte + (b'\xf5\x80\x80\x80', FFFD*4), # 3 continuation bytes + (b'\xf5\x80\x41', FFFD*2+'A'), # 1 valid cb and 1 invalid + (b'\xf5\x80\x41\xf5', FFFD*2+'A'+FFFD), + (b'\xf5\x41\x80\x80\x41', FFFD+'A'+FFFD*2+'A'), + # with invalid start byte of a 5-byte sequence (rfc2279) + (b'\xf8', FFFD), # only the start byte + (b'\xf8\xf8', FFFD*2), # 2 start bytes + (b'\xf8\x80', FFFD*2), # only one continuation byte + (b'\xf8\x80\x41', FFFD*2 + 'A'), # 1 valid cb and 1 invalid + (b'\xf8\x80\x80\x80\x80', FFFD*5), # invalid 5 bytes seq with 5 bytes + # with invalid start byte of a 6-byte sequence (rfc2279) + (b'\xfc', FFFD), # only the start byte + (b'\xfc\xfc', FFFD*2), # 2 start bytes + (b'\xfc\x80\x80', FFFD*3), # only 2 continuation bytes + (b'\xfc\x80\x80\x80\x80\x80', FFFD*6), # 6 continuation bytes + # invalid start byte + (b'\xfe', FFFD), + (b'\xfe\x80\x80', FFFD*3), + # other sequences + (b'\xf1\x80\x41\x42\x43', '\ufffd\x41\x42\x43'), + (b'\xf1\x80\xff\x42\x43', '\ufffd\ufffd\x42\x43'), + (b'\xf1\x80\xc2\x81\x43', '\ufffd\x81\x43'), + (b'\x61\xF1\x80\x80\xE1\x80\xC2\x62\x80\x63\x80\xBF\x64', + '\x61\uFFFD\uFFFD\uFFFD\x62\uFFFD\x63\uFFFD\uFFFD\x64'), + ] + for n, (seq, res) in enumerate(sequences): + self.assertRaises(UnicodeDecodeError, seq.decode, 'utf-8', 'strict') + self.assertEqual(seq.decode('utf-8', 'replace'), res) + self.assertEqual((seq+b'b').decode('utf-8', 'replace'), res+'b') + self.assertEqual(seq.decode('utf-8', 'ignore'), + res.replace('\uFFFD', '')) + def test_codecs_idna(self): # Test whether trailing dot is preserved self.assertEqual("www.python.org.".encode("idna"), b"www.python.org.") @@ -1039,8 +1192,8 @@ s = bytes(range(128)) for encoding in ( 'cp037', 'cp1026', - 'cp437', 'cp500', 'cp737', 'cp775', 'cp850', - 'cp852', 'cp855', 'cp860', 'cp861', 'cp862', + 'cp437', 'cp500', 'cp720', 'cp737', 'cp775', 'cp850', + 'cp852', 'cp855', 'cp858', 'cp860', 'cp861', 'cp862', 'cp863', 'cp865', 'cp866', 'iso8859_10', 'iso8859_13', 'iso8859_14', 'iso8859_15', 'iso8859_2', 'iso8859_3', 'iso8859_4', 'iso8859_5', 'iso8859_6', @@ -1067,8 +1220,8 @@ s = bytes(range(128, 256)) for encoding in ( 'cp037', 'cp1026', - 'cp437', 'cp500', 'cp737', 'cp775', 'cp850', - 'cp852', 'cp855', 'cp860', 'cp861', 'cp862', + 'cp437', 'cp500', 'cp720', 'cp737', 'cp775', 'cp850', + 'cp852', 'cp855', 'cp858', 'cp860', 'cp861', 'cp862', 'cp863', 'cp865', 'cp866', 'iso8859_10', 'iso8859_13', 'iso8859_14', 'iso8859_15', 'iso8859_2', 'iso8859_4', 'iso8859_5', Modified: python/branches/py3k-dtoa/Lib/test/test_urllib.py ============================================================================== --- python/branches/py3k-dtoa/Lib/test/test_urllib.py (original) +++ python/branches/py3k-dtoa/Lib/test/test_urllib.py Tue Jul 6 17:55:27 2010 @@ -795,6 +795,116 @@ self.assertEqual("a=a&a=b", urllib.parse.urlencode({"a": {"a": 1, "b": 1}}, True)) + def test_urlencode_encoding(self): + # ASCII encoding. Expect %3F with errors="replace' + given = (('\u00a0', '\u00c1'),) + expect = '%3F=%3F' + result = urllib.parse.urlencode(given, encoding="ASCII", errors="replace") + self.assertEqual(expect, result) + + # Default is UTF-8 encoding. + given = (('\u00a0', '\u00c1'),) + expect = '%C2%A0=%C3%81' + result = urllib.parse.urlencode(given) + self.assertEqual(expect, result) + + # Latin-1 encoding. + given = (('\u00a0', '\u00c1'),) + expect = '%A0=%C1' + result = urllib.parse.urlencode(given, encoding="latin-1") + self.assertEqual(expect, result) + + def test_urlencode_encoding_doseq(self): + # ASCII Encoding. Expect %3F with errors="replace' + given = (('\u00a0', '\u00c1'),) + expect = '%3F=%3F' + result = urllib.parse.urlencode(given, doseq=True, + encoding="ASCII", errors="replace") + self.assertEqual(expect, result) + + # ASCII Encoding. On a sequence of values. + given = (("\u00a0", (1, "\u00c1")),) + expect = '%3F=1&%3F=%3F' + result = urllib.parse.urlencode(given, True, + encoding="ASCII", errors="replace") + self.assertEqual(expect, result) + + # Utf-8 + given = (("\u00a0", "\u00c1"),) + expect = '%C2%A0=%C3%81' + result = urllib.parse.urlencode(given, True) + self.assertEqual(expect, result) + + given = (("\u00a0", (42, "\u00c1")),) + expect = '%C2%A0=42&%C2%A0=%C3%81' + result = urllib.parse.urlencode(given, True) + self.assertEqual(expect, result) + + # latin-1 + given = (("\u00a0", "\u00c1"),) + expect = '%A0=%C1' + result = urllib.parse.urlencode(given, True, encoding="latin-1") + self.assertEqual(expect, result) + + given = (("\u00a0", (42, "\u00c1")),) + expect = '%A0=42&%A0=%C1' + result = urllib.parse.urlencode(given, True, encoding="latin-1") + self.assertEqual(expect, result) + + def test_urlencode_bytes(self): + given = ((b'\xa0\x24', b'\xc1\x24'),) + expect = '%A0%24=%C1%24' + result = urllib.parse.urlencode(given) + self.assertEqual(expect, result) + result = urllib.parse.urlencode(given, True) + self.assertEqual(expect, result) + + # Sequence of values + given = ((b'\xa0\x24', (42, b'\xc1\x24')),) + expect = '%A0%24=42&%A0%24=%C1%24' + result = urllib.parse.urlencode(given, True) + self.assertEqual(expect, result) + + def test_urlencode_encoding_safe_parameter(self): + + # Send '$' (\x24) as safe character + # Default utf-8 encoding + + given = ((b'\xa0\x24', b'\xc1\x24'),) + result = urllib.parse.urlencode(given, safe=":$") + expect = '%A0$=%C1$' + self.assertEqual(expect, result) + + given = ((b'\xa0\x24', b'\xc1\x24'),) + result = urllib.parse.urlencode(given, doseq=True, safe=":$") + expect = '%A0$=%C1$' + self.assertEqual(expect, result) + + # Safe parameter in sequence + given = ((b'\xa0\x24', (b'\xc1\x24', 0xd, 42)),) + expect = '%A0$=%C1$&%A0$=13&%A0$=42' + result = urllib.parse.urlencode(given, True, safe=":$") + self.assertEqual(expect, result) + + # Test all above in latin-1 encoding + + given = ((b'\xa0\x24', b'\xc1\x24'),) + result = urllib.parse.urlencode(given, safe=":$", + encoding="latin-1") + expect = '%A0$=%C1$' + self.assertEqual(expect, result) + + given = ((b'\xa0\x24', b'\xc1\x24'),) + expect = '%A0$=%C1$' + result = urllib.parse.urlencode(given, doseq=True, safe=":$", + encoding="latin-1") + + given = ((b'\xa0\x24', (b'\xc1\x24', 0xd, 42)),) + expect = '%A0$=%C1$&%A0$=13&%A0$=42' + result = urllib.parse.urlencode(given, True, safe=":$", + encoding="latin-1") + self.assertEqual(expect, result) + class Pathname_Tests(unittest.TestCase): """Test pathname2url() and url2pathname()""" Modified: python/branches/py3k-dtoa/Lib/test/test_xmlrpc_net.py ============================================================================== --- python/branches/py3k-dtoa/Lib/test/test_xmlrpc_net.py (original) +++ python/branches/py3k-dtoa/Lib/test/test_xmlrpc_net.py Tue Jul 6 17:55:27 2010 @@ -48,7 +48,7 @@ # Perform a minimal sanity check on the result, just to be sure # the request means what we think it means. self.assertIsInstance(builders, collections.Sequence) - self.assertTrue([x for x in builders if "trunk" in x], builders) + self.assertTrue([x for x in builders if "3.x" in x], builders) def test_main(): Modified: python/branches/py3k-dtoa/Lib/urllib/parse.py ============================================================================== --- python/branches/py3k-dtoa/Lib/urllib/parse.py (original) +++ python/branches/py3k-dtoa/Lib/urllib/parse.py Tue Jul 6 17:55:27 2010 @@ -8,21 +8,22 @@ RFC 2732 : "Format for Literal IPv6 Addresses in URL's by R.Hinden, B.Carpenter and L.Masinter, December 1999. -RFC2396: "Uniform Resource Identifiers (URI)": Generic Syntax by T. +RFC 2396: "Uniform Resource Identifiers (URI)": Generic Syntax by T. Berners-Lee, R. Fielding, and L. Masinter, August 1998. -RFC2368: "The mailto URL scheme", by P.Hoffman , L Masinter, J. Zwinski, July 1998. +RFC 2368: "The mailto URL scheme", by P.Hoffman , L Masinter, J. Zwinski, July 1998. RFC 1808: "Relative Uniform Resource Locators", by R. Fielding, UC Irvine, June 1995. -RFC1738: "Uniform Resource Locators (URL)" by T. Berners-Lee, L. Masinter, M. +RFC 1738: "Uniform Resource Locators (URL)" by T. Berners-Lee, L. Masinter, M. McCahill, December 1994 -RFC 3986 is considered the current standard and any changes to urlparse module -should conform to this. urlparse module is not entirely compliant with this. -The defacto scenarios of parsing are considered sometimes and for backward -compatiblity purposes, older RFC uses of parsing are retained. The testcases in +RFC 3986 is considered the current standard and any future changes to +urlparse module should conform with it. The urlparse module is +currently not entirely compliant with this RFC due to defacto +scenarios for parsing, and for backward compatibility purposes, some +parsing quirks from older RFCs are retained. The testcases in test_urlparse.py provides a good indicator of parsing behavior. """ @@ -220,6 +221,11 @@ return urlunsplit((scheme, netloc, url, query, fragment)) def urlunsplit(components): + """Combine the elements of a tuple as returned by urlsplit() into a + complete URL as a string. The data argument can be any five-item iterable. + This may result in a slightly different, but equivalent URL, if the URL that + was parsed originally had unnecessary delimiters (for example, a ? with an + empty query; the RFC states that these are equivalent).""" scheme, netloc, url, query, fragment = components if netloc or (scheme and scheme in uses_netloc and url[:2] != '//'): if url and url[:1] != '/': url = '/' + url @@ -553,7 +559,7 @@ _safe_quoters[safe] = quoter = Quoter(safe).__getitem__ return ''.join([quoter(char) for char in bs]) -def urlencode(query, doseq=False): +def urlencode(query, doseq=False, safe='', encoding=None, errors=None): """Encode a sequence of two-element tuples or dictionary into a URL query string. If any values in the query arg are sequences and doseq is true, each @@ -562,6 +568,10 @@ If the query arg is a sequence of two-element tuples, the order of the parameters in the output will match the order of parameters in the input. + + The query arg may be either a string or a bytes type. When query arg is a + string, the safe, encoding and error parameters are sent the quote_plus for + encoding. """ if hasattr(query, "items"): @@ -586,14 +596,28 @@ l = [] if not doseq: for k, v in query: - k = quote_plus(str(k)) - v = quote_plus(str(v)) + if isinstance(k, bytes): + k = quote_plus(k, safe) + else: + k = quote_plus(str(k), safe, encoding, errors) + + if isinstance(v, bytes): + v = quote_plus(v, safe) + else: + v = quote_plus(str(v), safe, encoding, errors) l.append(k + '=' + v) else: for k, v in query: - k = quote_plus(str(k)) - if isinstance(v, str): - v = quote_plus(v) + if isinstance(k, bytes): + k = quote_plus(k, safe) + else: + k = quote_plus(str(k), safe, encoding, errors) + + if isinstance(v, bytes): + v = quote_plus(v, safe) + l.append(k + '=' + v) + elif isinstance(v, str): + v = quote_plus(v, safe, encoding, errors) l.append(k + '=' + v) else: try: @@ -601,12 +625,16 @@ x = len(v) except TypeError: # not a sequence - v = quote_plus(str(v)) + v = quote_plus(str(v), safe, encoding, errors) l.append(k + '=' + v) else: # loop over the sequence for elt in v: - l.append(k + '=' + quote_plus(str(elt))) + if isinstance(elt, bytes): + elt = quote_plus(elt, safe) + else: + elt = quote_plus(str(elt), safe, encoding, errors) + l.append(k + '=' + elt) return '&'.join(l) # Utilities to parse URLs (most of these return None for missing parts): Modified: python/branches/py3k-dtoa/Lib/urllib/request.py ============================================================================== --- python/branches/py3k-dtoa/Lib/urllib/request.py (original) +++ python/branches/py3k-dtoa/Lib/urllib/request.py Tue Jul 6 17:55:27 2010 @@ -1866,7 +1866,8 @@ else: return self.http_error_default(url, fp, errcode, errmsg, headers) - def http_error_401(self, url, fp, errcode, errmsg, headers, data=None): + def http_error_401(self, url, fp, errcode, errmsg, headers, data=None, + retry=False): """Error 401 -- authentication required. This function supports Basic authentication only.""" if not 'www-authenticate' in headers: @@ -1882,13 +1883,17 @@ if scheme.lower() != 'basic': URLopener.http_error_default(self, url, fp, errcode, errmsg, headers) + if not retry: + URLopener.http_error_default(self, url, fp, errcode, errmsg, + headers) name = 'retry_' + self.type + '_basic_auth' if data is None: return getattr(self,name)(url, realm) else: return getattr(self,name)(url, realm, data) - def http_error_407(self, url, fp, errcode, errmsg, headers, data=None): + def http_error_407(self, url, fp, errcode, errmsg, headers, data=None, + retry=False): """Error 407 -- proxy authentication required. This function supports Basic authentication only.""" if not 'proxy-authenticate' in headers: @@ -1904,6 +1909,9 @@ if scheme.lower() != 'basic': URLopener.http_error_default(self, url, fp, errcode, errmsg, headers) + if not retry: + URLopener.http_error_default(self, url, fp, errcode, errmsg, + headers) name = 'retry_proxy_' + self.type + '_basic_auth' if data is None: return getattr(self,name)(url, realm) @@ -2196,8 +2204,13 @@ continue base = ip2num(m.group(1)) - mask = int(m.group(2)[1:]) - mask = 32 - mask + mask = m.group(2) + if mask is None: + mask = 8 * (m.group(1).count('.') + 1) + + else: + mask = int(mask[1:]) + mask = 32 - mask if (hostIP >> mask) == (base >> mask): return True Modified: python/branches/py3k-dtoa/Lib/uuid.py ============================================================================== --- python/branches/py3k-dtoa/Lib/uuid.py (original) +++ python/branches/py3k-dtoa/Lib/uuid.py Tue Jul 6 17:55:27 2010 @@ -427,17 +427,17 @@ if hasattr(lib, 'uuid_generate_time'): _uuid_generate_time = lib.uuid_generate_time - # The uuid_generate_* functions are broken on MacOS X 10.6, as noted + # The uuid_generate_* functions are broken on MacOS X 10.5, as noted # in issue #8621 the function generates the same sequence of values # in the parent process and all children created using fork (unless # those children use exec as well). # - # Assume that the uuid_generate functions are broken from 10.6 onward, + # Assume that the uuid_generate functions are broken from 10.5 onward, # the test can be adjusted when a later version is fixed. import sys if sys.platform == 'darwin': import os - if int(os.uname()[2].split('.')[0]) >= 10: + if int(os.uname()[2].split('.')[0]) >= 9: _uuid_generate_random = _uuid_generate_time = None # On Windows prior to 2000, UuidCreate gives a UUID containing the Modified: python/branches/py3k-dtoa/Lib/warnings.py ============================================================================== --- python/branches/py3k-dtoa/Lib/warnings.py (original) +++ python/branches/py3k-dtoa/Lib/warnings.py Tue Jul 6 17:55:27 2010 @@ -371,8 +371,10 @@ # Module initialization _processoptions(sys.warnoptions) if not _warnings_defaults: - simplefilter("ignore", category=PendingDeprecationWarning, append=1) - simplefilter("ignore", category=ImportWarning, append=1) + silence = [ImportWarning, PendingDeprecationWarning] + silence.append(DeprecationWarning) + for cls in silence: + simplefilter("ignore", category=cls) bytes_warning = sys.flags.bytes_warning if bytes_warning > 1: bytes_action = "error" Modified: python/branches/py3k-dtoa/Misc/ACKS ============================================================================== --- python/branches/py3k-dtoa/Misc/ACKS (original) +++ python/branches/py3k-dtoa/Misc/ACKS Tue Jul 6 17:55:27 2010 @@ -797,6 +797,7 @@ Eren T??rkay Lionel Ulmer Roger Upole +Daniel Urban Michael Urman Hector Urtubia Andi Vajda Modified: python/branches/py3k-dtoa/Misc/NEWS ============================================================================== --- python/branches/py3k-dtoa/Misc/NEWS (original) +++ python/branches/py3k-dtoa/Misc/NEWS Tue Jul 6 17:55:27 2010 @@ -12,6 +12,40 @@ Core and Builtins ----------------- +- Issue #8271: during the decoding of an invalid UTF-8 byte sequence, only the + start byte and the continuation byte(s) are now considered invalid, instead + of the number of bytes specified by the start byte. + E.g.: '\xf1\x80AB'.decode('utf-8', 'replace') now returns u'\ufffdAB' and + replaces with U+FFFD only the start byte ('\xf1') and the continuation byte + ('\x80') even if '\xf1' is the start byte of a 4-bytes sequence. + Previous versions returned a single u'\ufffd'. + +- Issue #9011: A negated imaginary literal (e.g., "-7j") now has real + part -0.0 rather than 0.0. So "-7j" is now exactly equivalent to + "-(7j)". + +- Be more specific in error messages about positional arguments. + +- Issue #8949: "z" format of PyArg_Parse*() functions doesn't accept bytes + objects, as described in the documentation. + +- Issue #6543: Write the traceback in the terminal encoding instead of utf-8. + Fix the encoding of the modules filename. Patch written by Amaury Forgeot + d'Arc. + +- Issue #9011: Remove buggy and unnecessary (in 3.x) ST->AST + compilation code dealing with unary minus applied to a constant. + The removed code was mutating the ST, causing a second compilation + to fail. + +- Issue #850997: mbcs encoding (Windows only) handles errors argument: strict + mode raises unicode errors. The encoder only supports "strict" and "replace" + error handlers, the decoder only supports "strict" and "ignore" error + handlers. Patch written by Mark Hammond. + +- Issue #8850: Remove "w" and "w#" formats from PyArg_Parse*() functions, use + "w*" format instead. Add tests for "w*" format. + - Issue #8592: PyArg_Parse*() functions raise a TypeError for "y", "u" and "Z" formats if the string contains a null byte/character. Write unit tests for string formats. @@ -23,6 +57,8 @@ - Issue #8969: On Windows, use mbcs codec in strict mode to encode and decode filenames and enable os.fsencode(). +- Issue #9058: Remove assertions about INT_MAX in UnicodeDecodeError. + - Issue #8941: decoding big endian UTF-32 data in UCS-2 builds could crash the interpreter with characters outside the Basic Multilingual Plane (higher than 0x10000). @@ -432,6 +468,55 @@ Library ------- +- Issue #9130: Fix validation of relative imports in parser module. + +- Issue #9128: Fix validation of class decorators in parser module. + +- Issue #9094: python -m pickletools will now disassemble pickle files + listed in the command line arguments. See output of python -m + pickletools -h for more details. + +- Issue #5468: urlencode to handle bytes type and other encodings in its query + parameter. Patch by Dan Mahn. + +- Issue #7673: Fix security vulnerability (CVE-2010-2089) in the audioop + module, ensure that the input string length is a multiple of the frame size + +- Issue #6507: Accept source strings in dis.dis(). Original patch by + Daniel Urban. + +- Issue #7829: Clearly document that the dis module is exposing an + implementation detail that is not stable between Python VMs or releases. + +- Issue #6589: cleanup asyncore.socket_map in case smtpd.SMTPServer constructor + raises an exception. + +- Issue #9110: Addition of ContextDecorator to contextlib, for creating APIs + that act as both context managers and decorators. contextmanager changes + to use ContextDecorator. + +- Implement importlib.abc.SourceLoader and deprecate PyLoader and PyPycLoader + for removal in Python 3.4. + +- Issue #9064: pdb's "up" and "down" commands now accept an optional argument. + +- Issue #9018: os.path.normcase() now raises a TypeError if the argument is + not ``str`` or ``bytes``. + +- Issue #9075: In the ssl module, remove the setting of a ``debug`` flag + on an OpenSSL structure. + +- Issue #8682: The ssl module now temporary increments the reference count of + a socket object got through ``PyWeakref_GetObject``, so as to avoid possible + deallocation while the object is still being used. + +- Issue #1368368: FancyURLOpener class changed to throw an Exception on wrong + password instead of presenting an interactive prompt. Older behavior can be + obtained by passing retry=True to http_error_xxx methods of FancyURLOpener. + +- Issue #8720: fix regression caused by fix for #4050 by making getsourcefile + smart enough to find source files in the linecache. + - Issue #5610: feedparser no longer eats extra characters at the end of a body part if the body part ends with a \r\n. @@ -1309,6 +1394,22 @@ Extension Modules ----------------- +- In the math module, correctly lookup __trunc__, __ceil__, and __floor__ as + special methods. + +- Issue #9005: Prevent utctimetuple() from producing year 0 or year + 10,000. Prior to this change, timezone adjustment in utctimetuple() + could produce tm_year value of 0 or 10,000. Now an OverflowError is + raised in these edge cases. + +- Issue #6641: The ``datetime.strptime`` method now supports the + ``%z`` directive. When the ``%z`` directive is present in the + format string, an aware ``datetime`` object is returned with + ``tzinfo`` bound to a ``datetime.timezone`` instance constructed + from the parsed offset. If both ``%z`` and ``%Z`` are present, the + data in ``%Z`` field is used for timezone name, but ``%Z`` data + without ``%z`` is discarded. + - Issue #5094: The ``datetime`` module now has a simple concrete class implementing ``datetime.tzinfo`` interface. Instances of the new class, ``datetime.timezone``, return fixed name and UTC offset from @@ -1407,6 +1508,8 @@ Build ----- +- Issue #8854: Fix finding Visual Studio 2008 on Windows x64. + - Issue #1759169, #8864: Drop _XOPEN_SOURCE on Solaris, define it for multiprocessing only. @@ -2026,6 +2129,8 @@ Library ------- +- Issue #8203: Fix IDLE Credits dialog: view_file() uses its encoding argument. + - Issue #5311: bdist_msi can now build packages that do not depend on a specific Python version. Modified: python/branches/py3k-dtoa/Misc/Vim/vimrc ============================================================================== --- python/branches/py3k-dtoa/Misc/Vim/vimrc (original) +++ python/branches/py3k-dtoa/Misc/Vim/vimrc Tue Jul 6 17:55:27 2010 @@ -43,7 +43,7 @@ " Display tabs at the beginning of a line in Python mode as bad. au BufRead,BufNewFile *.py,*.pyw match BadWhitespace /^\t\+/ " Make trailing whitespace be flagged as bad. -au BufRead,BufNewFile *.py,*.pyw,*.c,*.h match BadWhitespace /\s\+$/ +au BufRead,BufNewFile *.py,*.pyw,*.c,*.h,*.rst match BadWhitespace /\s\+$/ " Wrap text after a certain number of characters " Python: 79 Modified: python/branches/py3k-dtoa/Modules/_ctypes/callproc.c ============================================================================== --- python/branches/py3k-dtoa/Modules/_ctypes/callproc.c (original) +++ python/branches/py3k-dtoa/Modules/_ctypes/callproc.c Tue Jul 6 17:55:27 2010 @@ -761,6 +761,7 @@ ffi_cif cif; int cc; #ifdef MS_WIN32 + int delta; #ifndef DONT_USE_SEH DWORD dwExceptionCode = 0; EXCEPTION_RECORD record; @@ -811,8 +812,9 @@ #ifndef DONT_USE_SEH __try { #endif + delta = #endif - ffi_call(&cif, (void *)pProc, resmem, avalues); + ffi_call(&cif, (void *)pProc, resmem, avalues); #ifdef MS_WIN32 #ifndef DONT_USE_SEH } @@ -844,6 +846,35 @@ return -1; } #endif +#ifdef MS_WIN64 + if (delta != 0) { + PyErr_Format(PyExc_RuntimeError, + "ffi_call failed with code %d", + delta); + return -1; + } +#else + if (delta < 0) { + if (flags & FUNCFLAG_CDECL) + PyErr_Format(PyExc_ValueError, + "Procedure called with not enough " + "arguments (%d bytes missing) " + "or wrong calling convention", + -delta); + else + PyErr_Format(PyExc_ValueError, + "Procedure probably called with not enough " + "arguments (%d bytes missing)", + -delta); + return -1; + } else if (delta > 0) { + PyErr_Format(PyExc_ValueError, + "Procedure probably called with too many " + "arguments (%d bytes in excess)", + delta); + return -1; + } +#endif #endif if ((flags & FUNCFLAG_PYTHONAPI) && PyErr_Occurred()) return -1; @@ -1116,7 +1147,11 @@ } for (i = 0; i < argcount; ++i) { atypes[i] = args[i].ffi_type; - if (atypes[i]->type == FFI_TYPE_STRUCT) + if (atypes[i]->type == FFI_TYPE_STRUCT +#ifdef _WIN64 + && atypes[i]->size <= sizeof(void *) +#endif + ) avalues[i] = (void *)args[i].value.p; else avalues[i] = (void *)&args[i].value; Modified: python/branches/py3k-dtoa/Modules/_ctypes/libffi/fficonfig.py.in ============================================================================== --- python/branches/py3k-dtoa/Modules/_ctypes/libffi/fficonfig.py.in (original) +++ python/branches/py3k-dtoa/Modules/_ctypes/libffi/fficonfig.py.in Tue Jul 6 17:55:27 2010 @@ -6,7 +6,7 @@ 'MIPS_IRIX': ['src/mips/ffi.c', 'src/mips/o32.S', 'src/mips/n32.S'], 'MIPS_LINUX': ['src/mips/ffi.c', 'src/mips/o32.S'], 'X86': ['src/x86/ffi.c', 'src/x86/sysv.S'], - 'X86_FREEBSD': ['src/x86/ffi.c', 'src/x86/sysv.S'], + 'X86_FREEBSD': ['src/x86/ffi.c', 'src/x86/freebsd.S'], 'X86_WIN32': ['src/x86/ffi.c', 'src/x86/win32.S'], 'SPARC': ['src/sparc/ffi.c', 'src/sparc/v8.S', 'src/sparc/v9.S'], 'ALPHA': ['src/alpha/ffi.c', 'src/alpha/osf.S'], Modified: python/branches/py3k-dtoa/Modules/_ctypes/libffi_msvc/ffi.h ============================================================================== --- python/branches/py3k-dtoa/Modules/_ctypes/libffi_msvc/ffi.h (original) +++ python/branches/py3k-dtoa/Modules/_ctypes/libffi_msvc/ffi.h Tue Jul 6 17:55:27 2010 @@ -1,5 +1,5 @@ /* -----------------------------------------------------------------*-C-*- - libffi @VERSION@ - Copyright (c) 1996-2003, 2007, 2008 Red Hat, Inc. + libffi 2.00-beta - Copyright (c) 1996-2003 Red Hat, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -12,14 +12,13 @@ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. + THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR + OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. ----------------------------------------------------------------------- */ @@ -57,7 +56,7 @@ #endif /* Specify which architecture libffi is configured for. */ -/* #define @TARGET@ */ +//XXX #define X86 /* ---- System configuration information --------------------------------- */ @@ -65,10 +64,6 @@ #ifndef LIBFFI_ASM -#ifdef _MSC_VER -#define __attribute__(X) -#endif - #include #include @@ -84,21 +79,12 @@ # ifdef __GNUC__ # define FFI_LONG_LONG_MAX __LONG_LONG_MAX__ # endif +# ifdef _MSC_VER +# define FFI_LONG_LONG_MAX _I64_MAX +# endif # endif #endif -/* The closure code assumes that this works on pointers, i.e. a size_t */ -/* can hold a pointer. */ - -typedef struct _ffi_type -{ - size_t size; - unsigned short alignment; - unsigned short type; - struct _ffi_type **elements; -} ffi_type; - -#ifndef LIBFFI_HIDE_BASIC_TYPES #if SCHAR_MAX == 127 # define ffi_type_uchar ffi_type_uint8 # define ffi_type_schar ffi_type_sint8 @@ -129,23 +115,26 @@ #error "int size not supported" #endif +#define ffi_type_ulong ffi_type_uint64 +#define ffi_type_slong ffi_type_sint64 #if LONG_MAX == 2147483647 # if FFI_LONG_LONG_MAX != 9223372036854775807 - #error "no 64-bit data type supported" + #error "no 64-bit data type supported" # endif #elif LONG_MAX != 9223372036854775807 #error "long size not supported" #endif -#if LONG_MAX == 2147483647 -# define ffi_type_ulong ffi_type_uint32 -# define ffi_type_slong ffi_type_sint32 -#elif LONG_MAX == 9223372036854775807 -# define ffi_type_ulong ffi_type_uint64 -# define ffi_type_slong ffi_type_sint64 -#else - #error "long size not supported" -#endif +/* The closure code assumes that this works on pointers, i.e. a size_t */ +/* can hold a pointer. */ + +typedef struct _ffi_type +{ + size_t size; + unsigned short alignment; + unsigned short type; + /*@null@*/ struct _ffi_type **elements; +} ffi_type; /* These are defined in types.c */ extern ffi_type ffi_type_void; @@ -159,19 +148,14 @@ extern ffi_type ffi_type_sint64; extern ffi_type ffi_type_float; extern ffi_type ffi_type_double; +extern ffi_type ffi_type_longdouble; extern ffi_type ffi_type_pointer; -#if HAVE_LONG_DOUBLE -extern ffi_type ffi_type_longdouble; -#else -#define ffi_type_longdouble ffi_type_double -#endif -#endif /* LIBFFI_HIDE_BASIC_TYPES */ typedef enum { FFI_OK = 0, FFI_BAD_TYPEDEF, - FFI_BAD_ABI + FFI_BAD_ABI } ffi_status; typedef unsigned FFI_TYPE; @@ -179,8 +163,8 @@ typedef struct { ffi_abi abi; unsigned nargs; - ffi_type **arg_types; - ffi_type *rtype; + /*@dependent@*/ ffi_type **arg_types; + /*@dependent@*/ ffi_type *rtype; unsigned bytes; unsigned flags; #ifdef FFI_EXTRA_CIF_FIELDS @@ -190,16 +174,10 @@ /* ---- Definitions for the raw API -------------------------------------- */ -#ifndef FFI_SIZEOF_ARG -# if LONG_MAX == 2147483647 -# define FFI_SIZEOF_ARG 4 -# elif LONG_MAX == 9223372036854775807 -# define FFI_SIZEOF_ARG 8 -# endif -#endif - -#ifndef FFI_SIZEOF_JAVA_RAW -# define FFI_SIZEOF_JAVA_RAW FFI_SIZEOF_ARG +#ifdef _WIN64 +#define FFI_SIZEOF_ARG 8 +#else +#define FFI_SIZEOF_ARG 4 #endif typedef union { @@ -210,25 +188,10 @@ void* ptr; } ffi_raw; -#if FFI_SIZEOF_JAVA_RAW == 4 && FFI_SIZEOF_ARG == 8 -/* This is a special case for mips64/n32 ABI (and perhaps others) where - sizeof(void *) is 4 and FFI_SIZEOF_ARG is 8. */ -typedef union { - signed int sint; - unsigned int uint; - float flt; - char data[FFI_SIZEOF_JAVA_RAW]; - void* ptr; -} ffi_java_raw; -#else -typedef ffi_raw ffi_java_raw; -#endif - - -void ffi_raw_call (ffi_cif *cif, - void (*fn)(void), - void *rvalue, - ffi_raw *avalue); +void ffi_raw_call (/*@dependent@*/ ffi_cif *cif, + void (*fn)(), + /*@out@*/ void *rvalue, + /*@dependent@*/ ffi_raw *avalue); void ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw); void ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args); @@ -238,35 +201,25 @@ /* packing, even on 64-bit machines. I.e. on 64-bit machines */ /* longs and doubles are followed by an empty 64-bit word. */ -void ffi_java_raw_call (ffi_cif *cif, - void (*fn)(void), - void *rvalue, - ffi_java_raw *avalue); +void ffi_java_raw_call (/*@dependent@*/ ffi_cif *cif, + void (*fn)(), + /*@out@*/ void *rvalue, + /*@dependent@*/ ffi_raw *avalue); -void ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_java_raw *raw); -void ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_java_raw *raw, void **args); +void ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw); +void ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args); size_t ffi_java_raw_size (ffi_cif *cif); /* ---- Definitions for closures ----------------------------------------- */ #if FFI_CLOSURES -#ifdef _MSC_VER -__declspec(align(8)) -#endif typedef struct { char tramp[FFI_TRAMPOLINE_SIZE]; ffi_cif *cif; void (*fun)(ffi_cif*,void*,void**,void*); void *user_data; -#ifdef __GNUC__ -} ffi_closure __attribute__((aligned (8))); -#else } ffi_closure; -#endif - -void *ffi_closure_alloc (size_t size, void **code); -void ffi_closure_free (void *); ffi_status ffi_prep_closure (ffi_closure*, @@ -274,13 +227,6 @@ void (*fun)(ffi_cif*,void*,void**,void*), void *user_data); -ffi_status -ffi_prep_closure_loc (ffi_closure*, - ffi_cif *, - void (*fun)(ffi_cif*,void*,void**,void*), - void *user_data, - void*codeloc); - typedef struct { char tramp[FFI_TRAMPOLINE_SIZE]; @@ -302,27 +248,6 @@ } ffi_raw_closure; -typedef struct { - char tramp[FFI_TRAMPOLINE_SIZE]; - - ffi_cif *cif; - -#if !FFI_NATIVE_RAW_API - - /* if this is enabled, then a raw closure has the same layout - as a regular closure. We use this to install an intermediate - handler to do the transaltion, void** -> ffi_raw*. */ - - void (*translate_args)(ffi_cif*,void*,void**,void*); - void *this_closure; - -#endif - - void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*); - void *user_data; - -} ffi_java_raw_closure; - ffi_status ffi_prep_raw_closure (ffi_raw_closure*, ffi_cif *cif, @@ -330,42 +255,29 @@ void *user_data); ffi_status -ffi_prep_raw_closure_loc (ffi_raw_closure*, - ffi_cif *cif, - void (*fun)(ffi_cif*,void*,ffi_raw*,void*), - void *user_data, - void *codeloc); - -ffi_status -ffi_prep_java_raw_closure (ffi_java_raw_closure*, +ffi_prep_java_raw_closure (ffi_raw_closure*, ffi_cif *cif, - void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*), + void (*fun)(ffi_cif*,void*,ffi_raw*,void*), void *user_data); -ffi_status -ffi_prep_java_raw_closure_loc (ffi_java_raw_closure*, - ffi_cif *cif, - void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*), - void *user_data, - void *codeloc); - #endif /* FFI_CLOSURES */ /* ---- Public interface definition -------------------------------------- */ -ffi_status ffi_prep_cif(ffi_cif *cif, +ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif, ffi_abi abi, - unsigned int nargs, - ffi_type *rtype, - ffi_type **atypes); - -void ffi_call(ffi_cif *cif, - void (*fn)(void), - void *rvalue, - void **avalue); + unsigned int nargs, + /*@dependent@*/ /*@out@*/ /*@partial@*/ ffi_type *rtype, + /*@dependent@*/ ffi_type **atypes); + +int +ffi_call(/*@dependent@*/ ffi_cif *cif, + void (*fn)(), + /*@out@*/ void *rvalue, + /*@dependent@*/ void **avalue); /* Useful for eliminating compiler warnings */ -#define FFI_FN(f) ((void (*)(void))f) +#define FFI_FN(f) ((void (*)())f) /* ---- Definitions shared with assembly code ---------------------------- */ @@ -376,7 +288,7 @@ #define FFI_TYPE_INT 1 #define FFI_TYPE_FLOAT 2 #define FFI_TYPE_DOUBLE 3 -#if HAVE_LONG_DOUBLE +#if 1 #define FFI_TYPE_LONGDOUBLE 4 #else #define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE @@ -400,3 +312,4 @@ #endif #endif + Modified: python/branches/py3k-dtoa/Modules/_ctypes/libffi_msvc/fficonfig.h ============================================================================== --- python/branches/py3k-dtoa/Modules/_ctypes/libffi_msvc/fficonfig.h (original) +++ python/branches/py3k-dtoa/Modules/_ctypes/libffi_msvc/fficonfig.h Tue Jul 6 17:55:27 2010 @@ -1,186 +1,96 @@ /* fficonfig.h. Originally created by configure, now hand_maintained for MSVC. */ -/* fficonfig.h.in. Generated from configure.ac by autoheader. */ +/* fficonfig.h. Generated automatically by configure. */ +/* fficonfig.h.in. Generated automatically from configure.in by autoheader. */ -/* Define if building universal (internal helper macro) */ -/* #undef AC_APPLE_UNIVERSAL_BUILD */ +/* Define this for MSVC, but not for mingw32! */ +#ifdef _MSC_VER +#define __attribute__(x) /* */ +#endif +#define alloca _alloca -/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP - systems. This function is required for `alloca.c' support on those systems. - */ -/* #undef CRAY_STACKSEG_END */ +/*----------------------------------------------------------------*/ -/* Define to 1 if using `alloca.c'. */ +/* Define if using alloca.c. */ /* #undef C_ALLOCA */ -/* Define to the flags needed for the .section .eh_frame directive. */ -/* #undef EH_FRAME_FLAGS */ - -/* Define this if you want extra debugging. */ -/* #undef FFI_DEBUG */ - -/* Cannot use malloc on this target, so, we revert to alternative means */ -/* #undef FFI_MMAP_EXEC_WRIT */ - -/* Define this is you do not want support for the raw API. */ -#define FFI_NO_RAW_API 1 - -/* Define this is you do not want support for aggregate types. */ -/* #undef FFI_NO_STRUCTS */ +/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems. + This function is required for alloca.c support on those systems. */ +/* #undef CRAY_STACKSEG_END */ -/* Define to 1 if you have `alloca', as a function or macro. */ +/* Define if you have alloca, as a function or macro. */ #define HAVE_ALLOCA 1 -/* Define to 1 if you have and it should be used (not on Ultrix). - */ -/* #undef HAVE_ALLOCA_H */ - -/* Define if your assembler supports .cfi_* directives. */ -/* #undef HAVE_AS_CFI_PSEUDO_OP */ +/* Define if you have and it should be used (not on Ultrix). */ +/* #define HAVE_ALLOCA_H 1 */ -/* Define if your assembler supports .register. */ -/* #undef HAVE_AS_REGISTER_PSEUDO_OP */ - -/* Define if your assembler and linker support unaligned PC relative relocs. - */ -/* #undef HAVE_AS_SPARC_UA_PCREL */ - -/* Define if your assembler supports PC relative relocs. */ -/* #undef HAVE_AS_X86_PCREL */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_DLFCN_H */ - -/* Define if __attribute__((visibility("hidden"))) is supported. */ -/* #undef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_INTTYPES_H */ +/* If using the C implementation of alloca, define if you know the + direction of stack growth for your system; otherwise it will be + automatically deduced at run-time. + STACK_DIRECTION > 0 => grows toward higher addresses + STACK_DIRECTION < 0 => grows toward lower addresses + STACK_DIRECTION = 0 => direction of growth unknown + */ +/* #undef STACK_DIRECTION */ -/* Define if you have the long double type and it is bigger than a double */ -/* #undef HAVE_LONG_DOUBLE */ +/* Define if you have the ANSI C header files. */ +#define STDC_HEADERS 1 -/* Define to 1 if you have the `memcpy' function. */ +/* Define if you have the memcpy function. */ #define HAVE_MEMCPY 1 -/* Define to 1 if you have the header file. */ -/* #undef HAVE_MEMORY_H */ - -/* Define to 1 if you have the `mmap' function. */ -/* #undef HAVE_MMAP */ - -/* Define if mmap with MAP_ANON(YMOUS) works. */ -/* #undef HAVE_MMAP_ANON */ - -/* Define if mmap of /dev/zero works. */ -/* #undef HAVE_MMAP_DEV_ZERO */ - /* Define if read-only mmap of a plain file works. */ -/* #undef HAVE_MMAP_FILE */ - -/* Define if .eh_frame sections should be read-only. */ -/* #undef HAVE_RO_EH_FRAME */ - -/* Define to 1 if you have the header file. */ -#undef HAVE_STDINT_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STDLIB_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STRINGS_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STRING_H +//#define HAVE_MMAP_FILE 1 -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_MMAN_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_STAT_H */ +/* Define if mmap of /dev/zero works. */ +//#define HAVE_MMAP_DEV_ZERO 1 -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_TYPES_H */ +/* Define if mmap with MAP_ANON(YMOUS) works. */ +//#define HAVE_MMAP_ANON 1 -/* Define to 1 if you have the header file. */ -/* #undef HAVE_UNISTD_H */ +/* The number of bytes in type double */ +#define SIZEOF_DOUBLE 8 -/* Define to the sub-directory in which libtool stores uninstalled libraries. - */ -/* #undef LT_OBJDIR */ +/* The number of bytes in type long double */ +#define SIZEOF_LONG_DOUBLE 12 -/* Define to 1 if your C compiler doesn't accept -c and -o together. */ -/* #undef NO_MINUS_C_MINUS_O */ +/* Define if you have the long double type and it is bigger than a double */ +#define HAVE_LONG_DOUBLE 1 -/* Name of package */ -/* #undef PACKAGE */ +/* whether byteorder is bigendian */ +/* #undef WORDS_BIGENDIAN */ -/* Define to the address where bug reports for this package should be sent. */ -/* #undef PACKAGE_BUGREPORT */ +/* Define if the host machine stores words of multi-word integers in + big-endian order. */ +/* #undef HOST_WORDS_BIG_ENDIAN */ -/* Define to the full name of this package. */ -/* #undef PACKAGE_NAME */ +/* 1234 = LIL_ENDIAN, 4321 = BIGENDIAN */ +#define BYTEORDER 1234 -/* Define to the full name and version of this package. */ -/* #undef PACKAGE_STRING */ +/* Define if your assembler and linker support unaligned PC relative relocs. */ +/* #undef HAVE_AS_SPARC_UA_PCREL */ -/* Define to the one symbol short name of this package. */ -/* #undef PACKAGE_TARNAME */ +/* Define if your assembler supports .register. */ +/* #undef HAVE_AS_REGISTER_PSEUDO_OP */ -/* Define to the home page for this package. */ -/* #undef PACKAGE_URL */ +/* Define if .eh_frame sections should be read-only. */ +/* #undef HAVE_RO_EH_FRAME */ -/* Define to the version of this package. */ -/* #undef PACKAGE_VERSION */ +/* Define to the flags needed for the .section .eh_frame directive. */ +/* #define EH_FRAME_FLAGS "aw" */ -/* The size of `double', as computed by sizeof. */ -#define SIZEOF_DOUBLE 8 +/* Define to the flags needed for the .section .eh_frame directive. */ +/* #define EH_FRAME_FLAGS "aw" */ -/* The size of `long double', as computed by sizeof. */ -#undef SIZEOF_LONG_DOUBLE +/* Define this if you want extra debugging. */ +/* #undef FFI_DEBUG */ -/* If using the C implementation of alloca, define if you know the - direction of stack growth for your system; otherwise it will be - automatically deduced at runtime. - STACK_DIRECTION > 0 => grows toward higher addresses - STACK_DIRECTION < 0 => grows toward lower addresses - STACK_DIRECTION = 0 => direction of growth unknown */ -/* #undef STACK_DIRECTION */ +/* Define this is you do not want support for aggregate types. */ +/* #undef FFI_NO_STRUCTS */ -/* Define to 1 if you have the ANSI C header files. */ -#define STDC_HEADERS 1 +/* Define this is you do not want support for the raw API. */ +/* #undef FFI_NO_RAW_API */ -/* Define this if you are using Purify and want to suppress spurious messages. - */ +/* Define this if you are using Purify and want to suppress spurious messages. */ /* #undef USING_PURIFY */ -/* Version number of package */ -/* #undef VERSION */ - -/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most - significant byte first (like Motorola and SPARC, unlike Intel). */ -#if defined AC_APPLE_UNIVERSAL_BUILD -# if defined __BIG_ENDIAN__ -# define WORDS_BIGENDIAN 1 -# endif -#else -# ifndef WORDS_BIGENDIAN -# undef WORDS_BIGENDIAN -# endif -#endif - - -#ifdef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE -#ifdef LIBFFI_ASM -#define FFI_HIDDEN(name) .hidden name -#else -#define FFI_HIDDEN __attribute__ ((visibility ("hidden"))) -#endif -#else -#ifdef LIBFFI_ASM -#define FFI_HIDDEN(name) -#else -#define FFI_HIDDEN -#endif -#endif - Modified: python/branches/py3k-dtoa/Modules/_math.c ============================================================================== --- python/branches/py3k-dtoa/Modules/_math.c (original) +++ python/branches/py3k-dtoa/Modules/_math.c Tue Jul 6 17:55:27 2010 @@ -55,14 +55,15 @@ else if (x >= two_pow_p28) { /* x > 2**28 */ if (Py_IS_INFINITY(x)) { return x+x; - } else { - return log(x)+ln2; /* acosh(huge)=log(2x) */ + } + else { + return log(x)+ln2; /* acosh(huge)=log(2x) */ } } else if (x == 1.) { - return 0.0; /* acosh(1) = 0 */ + return 0.0; /* acosh(1) = 0 */ } - else if (x > 2.) { /* 2 < x < 2**28 */ + else if (x > 2.) { /* 2 < x < 2**28 */ double t = x*x; return log(2.0*x - 1.0 / (x + sqrt(t - 1.0))); } @@ -94,7 +95,7 @@ return x+x; } if (absx < two_pow_m28) { /* |x| < 2**-28 */ - return x; /* return x inexact except 0 */ + return x; /* return x inexact except 0 */ } if (absx > two_pow_p28) { /* |x| > 2**28 */ w = log(absx)+ln2; @@ -114,9 +115,9 @@ * Method : * 1.Reduced x to positive by atanh(-x) = -atanh(x) * 2.For x>=0.5 - * 1 2x x - * atanh(x) = --- * log(1 + -------) = 0.5 * log1p(2 * --------) - * 2 1 - x 1 - x + * 1 2x x + * atanh(x) = --- * log(1 + -------) = 0.5 * log1p(2 * -------) + * 2 1 - x 1 - x * * For x<0.5 * atanh(x) = 0.5*log1p(2x+2x*x/(1-x)) @@ -173,15 +174,15 @@ */ if (fabs(x) < 0.7) { - double u; - u = exp(x); - if (u == 1.0) - return x; - else - return (u - 1.0) * x / log(u); + double u; + u = exp(x); + if (u == 1.0) + return x; + else + return (u - 1.0) * x / log(u); } else - return exp(x) - 1.0; + return exp(x) - 1.0; } /* log1p(x) = log(1+x). The log1p function is designed to avoid the @@ -194,7 +195,7 @@ /* For x small, we use the following approach. Let y be the nearest float to 1+x, then - 1+x = y * (1 - (y-1-x)/y) + 1+x = y * (1 - (y-1-x)/y) so log(1+x) = log(y) + log(1-(y-1-x)/y). Since (y-1-x)/y is tiny, the second term is well approximated by (y-1-x)/y. If abs(x) >= @@ -213,17 +214,19 @@ double y; if (fabs(x) < DBL_EPSILON/2.) { - return x; - } else if (-0.5 <= x && x <= 1.) { - /* WARNING: it's possible than an overeager compiler - will incorrectly optimize the following two lines - to the equivalent of "return log(1.+x)". If this - happens, then results from log1p will be inaccurate - for small x. */ - y = 1.+x; - return log(y)-((y-1.)-x)/y; - } else { - /* NaNs and infinities should end up here */ - return log(1.+x); + return x; + } + else if (-0.5 <= x && x <= 1.) { + /* WARNING: it's possible than an overeager compiler + will incorrectly optimize the following two lines + to the equivalent of "return log(1.+x)". If this + happens, then results from log1p will be inaccurate + for small x. */ + y = 1.+x; + return log(y)-((y-1.)-x)/y; + } + else { + /* NaNs and infinities should end up here */ + return log(1.+x); } } Modified: python/branches/py3k-dtoa/Modules/_scproxy.c ============================================================================== --- python/branches/py3k-dtoa/Modules/_scproxy.c (original) +++ python/branches/py3k-dtoa/Modules/_scproxy.c Tue Jul 6 17:55:27 2010 @@ -75,7 +75,7 @@ aNum = CFDictionaryGetValue(proxyDict, kSCPropNetProxiesExcludeSimpleHostnames); if (aNum == NULL) { - v = PyBool_FromLong(1); + v = PyBool_FromLong(0); } else { v = PyBool_FromLong(cfnum_to_int32(aNum)); } Modified: python/branches/py3k-dtoa/Modules/_ssl.c ============================================================================== --- python/branches/py3k-dtoa/Modules/_ssl.c (original) +++ python/branches/py3k-dtoa/Modules/_ssl.c Tue Jul 6 17:55:27 2010 @@ -212,8 +212,11 @@ errstr = "EOF occurred in violation of protocol"; } else if (ret == -1) { /* underlying BIO reported an I/O error */ + Py_INCREF(s); ERR_clear_error(); - return s->errorhandler(); + v = s->errorhandler(); + Py_DECREF(s); + return v; } else { /* possible? */ p = PY_SSL_ERROR_SYSCALL; errstr = "Some I/O error occurred"; @@ -334,6 +337,7 @@ PY_SSL_ERROR_NO_SOCKET, __FILE__, __LINE__); return NULL; } + Py_INCREF(sock); /* just in case the blocking state of the socket has been changed */ nonblocking = (sock->sock_timeout >= 0.0); @@ -348,9 +352,8 @@ ret = SSL_do_handshake(self->ssl); err = SSL_get_error(self->ssl, ret); PySSL_END_ALLOW_THREADS - if(PyErr_CheckSignals()) { - return NULL; - } + if (PyErr_CheckSignals()) + goto error; if (err == SSL_ERROR_WANT_READ) { sockstate = check_socket_and_wait_for_timeout(sock, 0); } else if (err == SSL_ERROR_WANT_WRITE) { @@ -361,22 +364,22 @@ if (sockstate == SOCKET_HAS_TIMED_OUT) { PyErr_SetString(PySSLErrorObject, ERRSTR("The handshake operation timed out")); - return NULL; + goto error; } else if (sockstate == SOCKET_HAS_BEEN_CLOSED) { PyErr_SetString(PySSLErrorObject, ERRSTR("Underlying socket has been closed.")); - return NULL; + goto error; } else if (sockstate == SOCKET_TOO_LARGE_FOR_SELECT) { PyErr_SetString(PySSLErrorObject, ERRSTR("Underlying socket too large for select().")); - return NULL; + goto error; } else if (sockstate == SOCKET_IS_NONBLOCKING) { break; } } while (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE); + Py_DECREF(sock); if (ret < 1) return PySSL_SetError(self, ret, __FILE__, __LINE__); - self->ssl->debug = 1; if (self->peer_cert) X509_free (self->peer_cert); @@ -386,6 +389,10 @@ Py_INCREF(Py_None); return Py_None; + +error: + Py_DECREF(sock); + return NULL; } static PyObject * @@ -1051,9 +1058,12 @@ PY_SSL_ERROR_NO_SOCKET, __FILE__, __LINE__); return NULL; } + Py_INCREF(sock); - if (!PyArg_ParseTuple(args, "y*:write", &buf)) + if (!PyArg_ParseTuple(args, "y*:write", &buf)) { + Py_DECREF(sock); return NULL; + } /* just in case the blocking state of the socket has been changed */ nonblocking = (sock->sock_timeout >= 0.0); @@ -1103,6 +1113,7 @@ } } while (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE); + Py_DECREF(sock); PyBuffer_Release(&buf); if (len > 0) return PyLong_FromLong(len); @@ -1110,6 +1121,7 @@ return PySSL_SetError(self, len, __FILE__, __LINE__); error: + Py_DECREF(sock); PyBuffer_Release(&buf); return NULL; } @@ -1159,21 +1171,23 @@ PY_SSL_ERROR_NO_SOCKET, __FILE__, __LINE__); return NULL; } + Py_INCREF(sock); if (!PyArg_ParseTuple(args, "|Oi:read", &dest, &count)) - return NULL; + goto error; + if ((dest == NULL) || (dest == Py_None)) { if (!(dest = PyByteArray_FromStringAndSize((char *) 0, len))) - return NULL; + goto error; mem = PyByteArray_AS_STRING(dest); } else if (PyLong_Check(dest)) { len = PyLong_AS_LONG(dest); if (!(dest = PyByteArray_FromStringAndSize((char *) 0, len))) - return NULL; + goto error; mem = PyByteArray_AS_STRING(dest); } else { if (PyObject_GetBuffer(dest, &buf, PyBUF_CONTIG) < 0) - return NULL; + goto error; mem = buf.buf; len = buf.len; if ((count > 0) && (count <= len)) @@ -1240,6 +1254,7 @@ goto error; } done: + Py_DECREF(sock); if (!buf_passed) { PyObject *res = PyBytes_FromStringAndSize(mem, count); Py_DECREF(dest); @@ -1249,8 +1264,9 @@ return PyLong_FromLong(count); } error: + Py_DECREF(sock); if (!buf_passed) { - Py_DECREF(dest); + Py_XDECREF(dest); } else { PyBuffer_Release(&buf); } @@ -1275,6 +1291,7 @@ PY_SSL_ERROR_NO_SOCKET, __FILE__, __LINE__); return NULL; } + Py_INCREF(sock); /* Just in case the blocking state of the socket has been changed */ nonblocking = (sock->sock_timeout >= 0.0); @@ -1324,24 +1341,29 @@ else PyErr_SetString(PySSLErrorObject, "The write operation timed out"); - return NULL; + goto error; } else if (sockstate == SOCKET_TOO_LARGE_FOR_SELECT) { PyErr_SetString(PySSLErrorObject, "Underlying socket too large for select()."); - return NULL; + goto error; } else if (sockstate != SOCKET_OPERATION_OK) /* Retain the SSL error code */ break; } - if (err < 0) + if (err < 0) { + Py_DECREF(sock); return PySSL_SetError(self, err, __FILE__, __LINE__); - else { - Py_INCREF(sock); - return (PyObject *) sock; } + else + /* It's already INCREF'ed */ + return (PyObject *) sock; + +error: + Py_DECREF(sock); + return NULL; } PyDoc_STRVAR(PySSL_SSLshutdown_doc, Modified: python/branches/py3k-dtoa/Modules/_testcapimodule.c ============================================================================== --- python/branches/py3k-dtoa/Modules/_testcapimodule.c (original) +++ python/branches/py3k-dtoa/Modules/_testcapimodule.c Tue Jul 6 17:55:27 2010 @@ -1386,6 +1386,28 @@ } static PyObject * +getargs_w_star(PyObject *self, PyObject *args) +{ + Py_buffer buffer; + PyObject *result; + char *str; + + if (!PyArg_ParseTuple(args, "w*:getargs_w_star", &buffer)) + return NULL; + + if (2 <= buffer.len) { + str = buffer.buf; + str[0] = '['; + str[buffer.len-1] = ']'; + } + + result = PyBytes_FromStringAndSize(buffer.buf, buffer.len); + PyBuffer_Release(&buffer); + return result; +} + + +static PyObject * test_empty_argparse(PyObject *self) { /* Test that formats can begin with '|'. See issue #4720. */ @@ -2227,6 +2249,7 @@ {"getargs_u_hash", getargs_u_hash, METH_VARARGS}, {"getargs_Z", getargs_Z, METH_VARARGS}, {"getargs_Z_hash", getargs_Z_hash, METH_VARARGS}, + {"getargs_w_star", getargs_w_star, METH_VARARGS}, {"codec_incrementalencoder", (PyCFunction)codec_incrementalencoder, METH_VARARGS}, {"codec_incrementaldecoder", Modified: python/branches/py3k-dtoa/Modules/audioop.c ============================================================================== --- python/branches/py3k-dtoa/Modules/audioop.c (original) +++ python/branches/py3k-dtoa/Modules/audioop.c Tue Jul 6 17:55:27 2010 @@ -297,6 +297,29 @@ static PyObject *AudioopError; +static int +audioop_check_size(int size) +{ + if (size != 1 && size != 2 && size != 4) { + PyErr_SetString(AudioopError, "Size should be 1, 2 or 4"); + return 0; + } + else + return 1; +} + +static int +audioop_check_parameters(int len, int size) +{ + if (!audioop_check_size(size)) + return 0; + if (len % size != 0) { + PyErr_SetString(AudioopError, "not a whole number of frames"); + return 0; + } + return 1; +} + static PyObject * audioop_getsample(PyObject *self, PyObject *args) { @@ -306,10 +329,8 @@ if ( !PyArg_ParseTuple(args, "s#in:getsample", &cp, &len, &size, &i) ) return 0; - if ( size != 1 && size != 2 && size != 4 ) { - PyErr_SetString(AudioopError, "Size should be 1, 2 or 4"); - return 0; - } + if (!audioop_check_parameters(len, size)) + return NULL; if ( i < 0 || i >= len/size ) { PyErr_SetString(AudioopError, "Index out of range"); return 0; @@ -330,10 +351,8 @@ if ( !PyArg_ParseTuple(args, "s#i:max", &cp, &len, &size) ) return 0; - if ( size != 1 && size != 2 && size != 4 ) { - PyErr_SetString(AudioopError, "Size should be 1, 2 or 4"); - return 0; - } + if (!audioop_check_parameters(len, size)) + return NULL; for ( i=0; i 0,1 */ for ( i=0; i PY_SSIZE_T_MAX/size2) { PyErr_SetString(PyExc_MemoryError, @@ -1086,10 +1104,8 @@ &nchannels, &inrate, &outrate, &state, &weightA, &weightB)) return NULL; - if (size != 1 && size != 2 && size != 4) { - PyErr_SetString(AudioopError, "Size should be 1, 2 or 4"); + if (!audioop_check_size(size)) return NULL; - } if (nchannels < 1) { PyErr_SetString(AudioopError, "# of channels should be >= 1"); return NULL; @@ -1265,10 +1281,8 @@ &cp, &len, &size) ) return 0 ; - if ( size != 1 && size != 2 && size != 4) { - PyErr_SetString(AudioopError, "Size should be 1, 2 or 4"); - return 0; - } + if (!audioop_check_parameters(len, size)) + return NULL; rv = PyBytes_FromStringAndSize(NULL, len/size); if ( rv == 0 ) @@ -1299,10 +1313,8 @@ &cp, &len, &size) ) return 0; - if ( size != 1 && size != 2 && size != 4) { - PyErr_SetString(AudioopError, "Size should be 1, 2 or 4"); - return 0; - } + if (!audioop_check_parameters(len, size)) + return NULL; if (len > PY_SSIZE_T_MAX/size) { PyErr_SetString(PyExc_MemoryError, @@ -1338,10 +1350,8 @@ &cp, &len, &size) ) return 0; - if ( size != 1 && size != 2 && size != 4) { - PyErr_SetString(AudioopError, "Size should be 1, 2 or 4"); - return 0; - } + if (!audioop_check_parameters(len, size)) + return NULL; rv = PyBytes_FromStringAndSize(NULL, len/size); if ( rv == 0 ) @@ -1372,10 +1382,8 @@ &cp, &len, &size) ) return 0; - if ( size != 1 && size != 2 && size != 4) { - PyErr_SetString(AudioopError, "Size should be 1, 2 or 4"); - return 0; - } + if (!audioop_check_parameters(len, size)) + return NULL; if (len > PY_SSIZE_T_MAX/size) { PyErr_SetString(PyExc_MemoryError, @@ -1413,11 +1421,8 @@ &cp, &len, &size, &state) ) return 0; - - if ( size != 1 && size != 2 && size != 4) { - PyErr_SetString(AudioopError, "Size should be 1, 2 or 4"); - return 0; - } + if (!audioop_check_parameters(len, size)) + return NULL; str = PyBytes_FromStringAndSize(NULL, len/(size*2)); if ( str == 0 ) @@ -1522,10 +1527,8 @@ &cp, &len, &size, &state) ) return 0; - if ( size != 1 && size != 2 && size != 4) { - PyErr_SetString(AudioopError, "Size should be 1, 2 or 4"); - return 0; - } + if (!audioop_check_parameters(len, size)) + return NULL; /* Decode state, should have (value, step) */ if ( state == Py_None ) { Modified: python/branches/py3k-dtoa/Modules/datetimemodule.c ============================================================================== --- python/branches/py3k-dtoa/Modules/datetimemodule.c (original) +++ python/branches/py3k-dtoa/Modules/datetimemodule.c Tue Jul 6 17:55:27 2010 @@ -1023,11 +1023,6 @@ Py_DECREF(result); result = NULL; } - else if (!PyUnicode_Check(result)) { - PyObject *temp = PyUnicode_FromObject(result); - Py_DECREF(result); - result = temp; - } } return result; } @@ -3469,6 +3464,14 @@ return add_datetime_timedelta(dt, (PyDateTime_Delta *)self->offset, 1); } +static PyObject * +timezone_getinitargs(PyDateTime_TimeZone *self) +{ + if (self->name == NULL) + return Py_BuildValue("(O)", self->offset); + return Py_BuildValue("(OO)", self->offset, self->name); +} + static PyMethodDef timezone_methods[] = { {"tzname", (PyCFunction)timezone_tzname, METH_O, PyDoc_STR("If name is specified when timezone is created, returns the name." @@ -3483,6 +3486,9 @@ {"fromutc", (PyCFunction)timezone_fromutc, METH_O, PyDoc_STR("datetime in UTC -> datetime in local time.")}, + {"__getinitargs__", (PyCFunction)timezone_getinitargs, METH_NOARGS, + PyDoc_STR("pickle support")}, + {NULL, NULL} }; @@ -4362,82 +4368,23 @@ return result; } -/* Return new datetime from time.strptime(). */ +/* Return new datetime from _strptime.strptime_datetime(). */ static PyObject * datetime_strptime(PyObject *cls, PyObject *args) { static PyObject *module = NULL; - PyObject *result = NULL, *obj, *st = NULL, *frac = NULL; const Py_UNICODE *string, *format; if (!PyArg_ParseTuple(args, "uu:strptime", &string, &format)) return NULL; - if (module == NULL && - (module = PyImport_ImportModuleNoBlock("_strptime")) == NULL) - return NULL; - - /* _strptime._strptime returns a two-element tuple. The first - element is a time.struct_time object. The second is the - microseconds (which are not defined for time.struct_time). */ - obj = PyObject_CallMethod(module, "_strptime", "uu", string, format); - if (obj != NULL) { - int i, good_timetuple = 1; - long int ia[7]; - if (PySequence_Check(obj) && PySequence_Size(obj) == 2) { - st = PySequence_GetItem(obj, 0); - frac = PySequence_GetItem(obj, 1); - if (st == NULL || frac == NULL) - good_timetuple = 0; - /* copy y/m/d/h/m/s values out of the - time.struct_time */ - if (good_timetuple && - PySequence_Check(st) && - PySequence_Size(st) >= 6) { - for (i=0; i < 6; i++) { - PyObject *p = PySequence_GetItem(st, i); - if (p == NULL) { - good_timetuple = 0; - break; - } - if (PyLong_Check(p)) - ia[i] = PyLong_AsLong(p); - else - good_timetuple = 0; - Py_DECREF(p); - } -/* if (PyLong_CheckExact(p)) { - ia[i] = PyLong_AsLongAndOverflow(p, &overflow); - if (overflow) - good_timetuple = 0; - } - else - good_timetuple = 0; - Py_DECREF(p); -*/ } - else - good_timetuple = 0; - /* follow that up with a little dose of microseconds */ - if (PyLong_Check(frac)) - ia[6] = PyLong_AsLong(frac); - else - good_timetuple = 0; - } - else - good_timetuple = 0; - if (good_timetuple) - result = PyObject_CallFunction(cls, "iiiiiii", - ia[0], ia[1], ia[2], - ia[3], ia[4], ia[5], - ia[6]); - else - PyErr_SetString(PyExc_ValueError, - "unexpected value from _strptime._strptime"); + if (module == NULL) { + module = PyImport_ImportModuleNoBlock("_strptime"); + if (module == NULL) + return NULL; } - Py_XDECREF(obj); - Py_XDECREF(st); - Py_XDECREF(frac); - return result; + return PyObject_CallMethod(module, "_strptime_datetime", "Ouu", + cls, string, format); } /* Return new datetime from date/datetime and time arguments. */ @@ -4991,15 +4938,9 @@ mm -= offset; stat = normalize_datetime(&y, &m, &d, &hh, &mm, &ss, &us); - if (stat < 0) { - /* At the edges, it's possible we overflowed - * beyond MINYEAR or MAXYEAR. - */ - if (PyErr_ExceptionMatches(PyExc_OverflowError)) - PyErr_Clear(); - else - return NULL; - } + /* OverflowError may be raised in the edge cases. */ + if (stat < 0) + return NULL; } return build_struct_time(y, m, d, hh, mm, ss, 0); } Modified: python/branches/py3k-dtoa/Modules/mathmodule.c ============================================================================== --- python/branches/py3k-dtoa/Modules/mathmodule.c (original) +++ python/branches/py3k-dtoa/Modules/mathmodule.c Tue Jul 6 17:55:27 2010 @@ -841,19 +841,17 @@ static PyObject * math_ceil(PyObject *self, PyObject *number) { static PyObject *ceil_str = NULL; - PyObject *method; + PyObject *method, *result; - if (ceil_str == NULL) { - ceil_str = PyUnicode_InternFromString("__ceil__"); - if (ceil_str == NULL) + method = _PyObject_LookupSpecial(number, "__ceil__", &ceil_str); + if (method == NULL) { + if (PyErr_Occurred()) return NULL; - } - - method = _PyType_Lookup(Py_TYPE(number), ceil_str); - if (method == NULL) return math_1_to_int(number, ceil, 0); - else - return PyObject_CallFunction(method, "O", number); + } + result = PyObject_CallFunctionObjArgs(method, NULL); + Py_DECREF(method); + return result; } PyDoc_STRVAR(math_ceil_doc, @@ -881,19 +879,17 @@ static PyObject * math_floor(PyObject *self, PyObject *number) { static PyObject *floor_str = NULL; - PyObject *method; + PyObject *method, *result; - if (floor_str == NULL) { - floor_str = PyUnicode_InternFromString("__floor__"); - if (floor_str == NULL) + method = _PyObject_LookupSpecial(number, "__floor__", &floor_str); + if (method == NULL) { + if (PyErr_Occurred()) return NULL; - } - - method = _PyType_Lookup(Py_TYPE(number), floor_str); - if (method == NULL) return math_1_to_int(number, floor, 0); - else - return PyObject_CallFunction(method, "O", number); + } + result = PyObject_CallFunctionObjArgs(method, NULL); + Py_DECREF(method); + return result; } PyDoc_STRVAR(math_floor_doc, @@ -989,17 +985,17 @@ def msum(iterable): partials = [] # sorted, non-overlapping partial sums for x in iterable: - i = 0 - for y in partials: - if abs(x) < abs(y): - x, y = y, x - hi = x + y - lo = y - (hi - x) - if lo: - partials[i] = lo - i += 1 - x = hi - partials[i:] = [x] + i = 0 + for y in partials: + if abs(x) < abs(y): + x, y = y, x + hi = x + y + lo = y - (hi - x) + if lo: + partials[i] = lo + i += 1 + x = hi + partials[i:] = [x] return sum_exact(partials) Rounded x+y stored in hi with the roundoff stored in lo. Together hi+lo @@ -1420,27 +1416,24 @@ math_trunc(PyObject *self, PyObject *number) { static PyObject *trunc_str = NULL; - PyObject *trunc; + PyObject *trunc, *result; if (Py_TYPE(number)->tp_dict == NULL) { if (PyType_Ready(Py_TYPE(number)) < 0) return NULL; } - if (trunc_str == NULL) { - trunc_str = PyUnicode_InternFromString("__trunc__"); - if (trunc_str == NULL) - return NULL; - } - - trunc = _PyType_Lookup(Py_TYPE(number), trunc_str); + trunc = _PyObject_LookupSpecial(number, "__trunc__", &trunc_str); if (trunc == NULL) { - PyErr_Format(PyExc_TypeError, - "type %.100s doesn't define __trunc__ method", - Py_TYPE(number)->tp_name); + if (!PyErr_Occurred()) + PyErr_Format(PyExc_TypeError, + "type %.100s doesn't define __trunc__ method", + Py_TYPE(number)->tp_name); return NULL; } - return PyObject_CallFunctionObjArgs(trunc, number, NULL); + result = PyObject_CallFunctionObjArgs(trunc, NULL); + Py_DECREF(trunc); + return result; } PyDoc_STRVAR(math_trunc_doc, Modified: python/branches/py3k-dtoa/Modules/parsermodule.c ============================================================================== --- python/branches/py3k-dtoa/Modules/parsermodule.c (original) +++ python/branches/py3k-dtoa/Modules/parsermodule.c Tue Jul 6 17:55:27 2010 @@ -1754,21 +1754,21 @@ && validate_dotted_as_names(CHILD(tree, 1))); } -/* Helper function to count the number of leading dots in +/* Helper function to count the number of leading dots (or ellipsis tokens) in * 'from ...module import name' */ static int count_from_dots(node *tree) { - int i; - for (i = 1; i < NCH(tree); i++) - if (TYPE(CHILD(tree, i)) != DOT) - break; - return i-1; + int i; + for (i = 1; i < NCH(tree); i++) + if (TYPE(CHILD(tree, i)) != DOT && TYPE(CHILD(tree, i)) != ELLIPSIS) + break; + return i - 1; } -/* 'from' ('.'* dotted_name | '.') 'import' ('*' | '(' import_as_names ')' | - * import_as_names +/* import_from: ('from' ('.'* dotted_name | '.'+) + * 'import' ('*' | '(' import_as_names ')' | import_as_names)) */ static int validate_import_from(node *tree) @@ -1778,7 +1778,8 @@ int havename = (TYPE(CHILD(tree, ndots + 1)) == dotted_name); int offset = ndots + havename; int res = validate_ntype(tree, import_from) - && (nch >= 4 + ndots) + && (offset >= 1) + && (nch >= 3 + offset) && validate_name(CHILD(tree, 0), "from") && (!havename || validate_dotted_name(CHILD(tree, ndots + 1))) && validate_name(CHILD(tree, offset + 1), "import"); @@ -2509,14 +2510,15 @@ static int validate_decorated(node *tree) { - int nch = NCH(tree); - int ok = (validate_ntype(tree, decorated) - && (nch == 2) - && validate_decorators(RCHILD(tree, -2)) - && (validate_funcdef(RCHILD(tree, -1)) - || validate_class(RCHILD(tree, -1))) - ); - return ok; + int nch = NCH(tree); + int ok = (validate_ntype(tree, decorated) + && (nch == 2) + && validate_decorators(RCHILD(tree, -2))); + if (TYPE(RCHILD(tree, -1)) == funcdef) + ok = ok && validate_funcdef(RCHILD(tree, -1)); + else + ok = ok && validate_class(RCHILD(tree, -1)); + return ok; } static int Modified: python/branches/py3k-dtoa/Modules/posixmodule.c ============================================================================== --- python/branches/py3k-dtoa/Modules/posixmodule.c (original) +++ python/branches/py3k-dtoa/Modules/posixmodule.c Tue Jul 6 17:55:27 2010 @@ -3925,7 +3925,7 @@ #ifdef HAVE_SETPGRP PyDoc_STRVAR(posix_setpgrp__doc__, "setpgrp()\n\n\ -Make this process a session leader."); +Make this process the process group leader."); static PyObject * posix_setpgrp(PyObject *self, PyObject *noargs) Modified: python/branches/py3k-dtoa/Modules/selectmodule.c ============================================================================== --- python/branches/py3k-dtoa/Modules/selectmodule.c (original) +++ python/branches/py3k-dtoa/Modules/selectmodule.c Tue Jul 6 17:55:27 2010 @@ -91,7 +91,7 @@ fd2obj[0].obj = (PyObject*)0; /* set list to zero size */ FD_ZERO(set); - fast_seq=PySequence_Fast(seq, "arguments 1-3 must be sequences"); + fast_seq = PySequence_Fast(seq, "arguments 1-3 must be sequences"); if (!fast_seq) return -1; Modified: python/branches/py3k-dtoa/Modules/timemodule.c ============================================================================== --- python/branches/py3k-dtoa/Modules/timemodule.c (original) +++ python/branches/py3k-dtoa/Modules/timemodule.c Tue Jul 6 17:55:27 2010 @@ -90,32 +90,6 @@ /* For Y2K check */ static PyObject *moddict; -/* Exposed in timefuncs.h. */ -time_t -_PyTime_DoubleToTimet(double x) -{ - time_t result; - double diff; - - result = (time_t)x; - /* How much info did we lose? time_t may be an integral or - * floating type, and we don't know which. If it's integral, - * we don't know whether C truncates, rounds, returns the floor, - * etc. If we lost a second or more, the C rounding is - * unreasonable, or the input just doesn't fit in a time_t; - * call it an error regardless. Note that the original cast to - * time_t can cause a C error too, but nothing we can do to - * worm around that. - */ - diff = x - (double)result; - if (diff <= -1.0 || diff >= 1.0) { - PyErr_SetString(PyExc_ValueError, - "timestamp out of range for platform time_t"); - result = (time_t)-1; - } - return result; -} - static PyObject * time_time(PyObject *self, PyObject *unused) { Modified: python/branches/py3k-dtoa/Modules/xxmodule.c ============================================================================== --- python/branches/py3k-dtoa/Modules/xxmodule.c (original) +++ python/branches/py3k-dtoa/Modules/xxmodule.c Tue Jul 6 17:55:27 2010 @@ -10,7 +10,7 @@ your own types of attributes instead. Maybe you want to name your local variables other than 'self'. If your object type is needed in other files, you'll have to create a file "foobarobject.h"; see - intobject.h for an example. */ + floatobject.h for an example. */ /* Xxo objects */ Modified: python/branches/py3k-dtoa/Objects/abstract.c ============================================================================== --- python/branches/py3k-dtoa/Objects/abstract.c (original) +++ python/branches/py3k-dtoa/Objects/abstract.c Tue Jul 6 17:55:27 2010 @@ -2522,8 +2522,7 @@ } else { if (!check_class(cls, - "isinstance() arg 2 must be a class, type," - " or tuple of classes and types")) + "isinstance() arg 2 must be a type or tuple of types")) return -1; icls = PyObject_GetAttr(inst, __class__); if (icls == NULL) { Modified: python/branches/py3k-dtoa/Objects/bytes_methods.c ============================================================================== --- python/branches/py3k-dtoa/Objects/bytes_methods.c (original) +++ python/branches/py3k-dtoa/Objects/bytes_methods.c Tue Jul 6 17:55:27 2010 @@ -332,7 +332,8 @@ PyDoc_STRVAR_shared(_Py_capitalize__doc__, "B.capitalize() -> copy of B\n\ \n\ -Return a copy of B with only its first character capitalized (ASCII)."); +Return a copy of B with only its first character capitalized (ASCII)\n\ +and the rest lower-cased."); void _Py_bytes_capitalize(char *result, char *s, Py_ssize_t len) Modified: python/branches/py3k-dtoa/Objects/descrobject.c ============================================================================== --- python/branches/py3k-dtoa/Objects/descrobject.c (original) +++ python/branches/py3k-dtoa/Objects/descrobject.c Tue Jul 6 17:55:27 2010 @@ -1115,7 +1115,7 @@ } propertyobject; static PyObject * property_copy(PyObject *, PyObject *, PyObject *, - PyObject *, PyObject *); + PyObject *); static PyMemberDef property_members[] = { {"fget", T_OBJECT, offsetof(propertyobject, prop_get), READONLY}, @@ -1132,7 +1132,7 @@ static PyObject * property_getter(PyObject *self, PyObject *getter) { - return property_copy(self, getter, NULL, NULL, NULL); + return property_copy(self, getter, NULL, NULL); } @@ -1142,7 +1142,7 @@ static PyObject * property_setter(PyObject *self, PyObject *setter) { - return property_copy(self, NULL, setter, NULL, NULL); + return property_copy(self, NULL, setter, NULL); } @@ -1152,7 +1152,7 @@ static PyObject * property_deleter(PyObject *self, PyObject *deleter) { - return property_copy(self, NULL, NULL, deleter, NULL); + return property_copy(self, NULL, NULL, deleter); } @@ -1221,11 +1221,10 @@ } static PyObject * -property_copy(PyObject *old, PyObject *get, PyObject *set, PyObject *del, - PyObject *doc) +property_copy(PyObject *old, PyObject *get, PyObject *set, PyObject *del) { propertyobject *pold = (propertyobject *)old; - PyObject *new, *type; + PyObject *new, *type, *doc; type = PyObject_Type(old); if (type == NULL) @@ -1243,15 +1242,12 @@ Py_XDECREF(del); del = pold->prop_del ? pold->prop_del : Py_None; } - if (doc == NULL || doc == Py_None) { - Py_XDECREF(doc); - if (pold->getter_doc && get != Py_None) { - /* make _init use __doc__ from getter */ - doc = Py_None; - } - else { - doc = pold->prop_doc ? pold->prop_doc : Py_None; - } + if (pold->getter_doc && get != Py_None) { + /* make _init use __doc__ from getter */ + doc = Py_None; + } + else { + doc = pold->prop_doc ? pold->prop_doc : Py_None; } new = PyObject_CallFunction(type, "OOOO", get, set, del, doc); Modified: python/branches/py3k-dtoa/Objects/enumobject.c ============================================================================== --- python/branches/py3k-dtoa/Objects/enumobject.c (original) +++ python/branches/py3k-dtoa/Objects/enumobject.c Tue Jul 6 17:55:27 2010 @@ -159,12 +159,13 @@ } PyDoc_STRVAR(enum_doc, -"enumerate(iterable) -> iterator for index, value of iterable\n" +"enumerate(iterable[, start]) -> iterator for index, value of iterable\n" "\n" "Return an enumerate object. iterable must be another object that supports\n" "iteration. The enumerate object yields pairs containing a count (from\n" -"zero) and a value yielded by the iterable argument. enumerate is useful\n" -"for obtaining an indexed list: (0, seq[0]), (1, seq[1]), (2, seq[2]), ..."); +"start, which defaults to zero) and a value yielded by the iterable argument.\n" +"enumerate is useful for obtaining an indexed list:\n" +" (0, seq[0]), (1, seq[1]), (2, seq[2]), ..."); PyTypeObject PyEnum_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) Modified: python/branches/py3k-dtoa/Objects/exceptions.c ============================================================================== --- python/branches/py3k-dtoa/Objects/exceptions.c (original) +++ python/branches/py3k-dtoa/Objects/exceptions.c Tue Jul 6 17:55:27 2010 @@ -1622,9 +1622,6 @@ const char *encoding, const char *object, Py_ssize_t length, Py_ssize_t start, Py_ssize_t end, const char *reason) { - assert(length < INT_MAX); - assert(start < INT_MAX); - assert(end < INT_MAX); return PyObject_CallFunction(PyExc_UnicodeDecodeError, "sy#nns", encoding, object, length, start, end, reason); } Modified: python/branches/py3k-dtoa/Objects/floatobject.c ============================================================================== --- python/branches/py3k-dtoa/Objects/floatobject.c (original) +++ python/branches/py3k-dtoa/Objects/floatobject.c Tue Jul 6 17:55:27 2010 @@ -21,7 +21,22 @@ extern int finite(double); #endif -/* Special free list -- see comments for same code in intobject.c. */ +/* Special free list + + Since some Python programs can spend much of their time allocating + and deallocating floats, these operations should be very fast. + Therefore we use a dedicated allocation scheme with a much lower + overhead (in space and time) than straight malloc(): a simple + dedicated free list, filled when necessary with memory from malloc(). + + block_list is a singly-linked list of all PyFloatBlocks ever allocated, + linked via their next members. PyFloatBlocks are never returned to the + system before shutdown (PyFloat_Fini). + + free_list is a singly-linked list of available PyFloatObjects, linked + via abuse of their ob_type members. +*/ + #define BLOCK_SIZE 1000 /* 1K less typical malloc overhead */ #define BHEAD_SIZE 8 /* Enough for a 64-bit pointer */ #define N_FLOATOBJECTS ((BLOCK_SIZE - BHEAD_SIZE) / sizeof(PyFloatObject)) @@ -1157,7 +1172,7 @@ return float_str((PyFloatObject *)v); if (x == 0.0) { - if(copysign(1.0, x) == -1.0) + if (copysign(1.0, x) == -1.0) return PyUnicode_FromString("-0x0.0p+0"); else return PyUnicode_FromString("0x0.0p+0"); @@ -1407,7 +1422,7 @@ round_up = 1; break; } - if (round_up == 1) { + if (round_up) { x += 2*half_eps; if (top_exp == DBL_MAX_EXP && x == ldexp((double)(2*half_eps), DBL_MANT_DIG)) Modified: python/branches/py3k-dtoa/Objects/frameobject.c ============================================================================== --- python/branches/py3k-dtoa/Objects/frameobject.c (original) +++ python/branches/py3k-dtoa/Objects/frameobject.c Tue Jul 6 17:55:27 2010 @@ -391,7 +391,7 @@ the local variables in f_localsplus are NULL. 2. We also maintain a separate free list of stack frames (just like - integers are allocated in a special way -- see intobject.c). When + floats are allocated in a special way -- see floatobject.c). When a stack frame is on the free list, only the following members have a meaning: ob_type == &Frametype Modified: python/branches/py3k-dtoa/Objects/typeobject.c ============================================================================== --- python/branches/py3k-dtoa/Objects/typeobject.c (original) +++ python/branches/py3k-dtoa/Objects/typeobject.c Tue Jul 6 17:55:27 2010 @@ -3476,11 +3476,8 @@ static void inherit_special(PyTypeObject *type, PyTypeObject *base) { - Py_ssize_t oldsize, newsize; /* Copying basicsize is connected to the GC flags */ - oldsize = base->tp_basicsize; - newsize = type->tp_basicsize ? type->tp_basicsize : oldsize; if (!(type->tp_flags & Py_TPFLAGS_HAVE_GC) && (base->tp_flags & Py_TPFLAGS_HAVE_GC) && (!type->tp_traverse && !type->tp_clear)) { @@ -3507,7 +3504,8 @@ type->tp_new = base->tp_new; } } - type->tp_basicsize = newsize; + if (type->tp_basicsize == 0) + type->tp_basicsize = base->tp_basicsize; /* Copy other non-function slots */ Modified: python/branches/py3k-dtoa/Objects/unicodeobject.c ============================================================================== --- python/branches/py3k-dtoa/Objects/unicodeobject.c (original) +++ python/branches/py3k-dtoa/Objects/unicodeobject.c Tue Jul 6 17:55:27 2010 @@ -1273,7 +1273,7 @@ case of a TypeError. */ if (PyErr_ExceptionMatches(PyExc_TypeError)) PyErr_Format(PyExc_TypeError, - "coercing to str: need string or buffer, " + "coercing to str: need bytes, bytearray or char buffer, " "%.80s found", Py_TYPE(obj)->tp_name); goto onError; @@ -1767,6 +1767,33 @@ return 0; } +/* create or adjust a UnicodeDecodeError */ +static void +make_decode_exception(PyObject **exceptionObject, + const char *encoding, + const char *input, Py_ssize_t length, + Py_ssize_t startpos, Py_ssize_t endpos, + const char *reason) +{ + if (*exceptionObject == NULL) { + *exceptionObject = PyUnicodeDecodeError_Create( + encoding, input, length, startpos, endpos, reason); + } + else { + if (PyUnicodeDecodeError_SetStart(*exceptionObject, startpos)) + goto onError; + if (PyUnicodeDecodeError_SetEnd(*exceptionObject, endpos)) + goto onError; + if (PyUnicodeDecodeError_SetReason(*exceptionObject, reason)) + goto onError; + } + return; + +onError: + Py_DECREF(*exceptionObject); + *exceptionObject = NULL; +} + /* error handling callback helper: build arguments, call the callback and check the arguments, if no exception occurred, copy the replacement to the output @@ -1800,20 +1827,13 @@ goto onError; } - if (*exceptionObject == NULL) { - *exceptionObject = PyUnicodeDecodeError_Create( - encoding, *input, *inend-*input, *startinpos, *endinpos, reason); - if (*exceptionObject == NULL) - goto onError; - } - else { - if (PyUnicodeDecodeError_SetStart(*exceptionObject, *startinpos)) - goto onError; - if (PyUnicodeDecodeError_SetEnd(*exceptionObject, *endinpos)) - goto onError; - if (PyUnicodeDecodeError_SetReason(*exceptionObject, reason)) - goto onError; - } + make_decode_exception(exceptionObject, + encoding, + *input, *inend - *input, + *startinpos, *endinpos, + reason); + if (*exceptionObject == NULL) + goto onError; restuple = PyObject_CallFunctionObjArgs(*errorHandler, *exceptionObject, NULL); if (restuple == NULL) @@ -2265,24 +2285,24 @@ static char utf8_code_length[256] = { - /* Map UTF-8 encoded prefix byte to sequence length. zero means - illegal prefix. see RFC 2279 for details */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + /* Map UTF-8 encoded prefix byte to sequence length. Zero means + illegal prefix. See RFC 3629 for details */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 00-0F */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 70-7F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80-8F */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* B0-BF */ + 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* C0-C1 + C2-CF */ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* D0-DF */ + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* E0-EF */ + 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* F0-F4 + F5-FF */ }; PyObject *PyUnicode_DecodeUTF8(const char *s, @@ -2312,6 +2332,7 @@ { const char *starts = s; int n; + int k; Py_ssize_t startinpos; Py_ssize_t endinpos; Py_ssize_t outpos; @@ -2395,7 +2416,9 @@ else { errmsg = "unexpected end of data"; startinpos = s-starts; - endinpos = size; + endinpos = startinpos+1; + for (k=1; (k < size-startinpos) && ((s[k]&0xC0) == 0x80); k++) + endinpos++; goto utf8Error; } } @@ -2403,7 +2426,7 @@ switch (n) { case 0: - errmsg = "unexpected code byte"; + errmsg = "invalid start byte"; startinpos = s-starts; endinpos = startinpos+1; goto utf8Error; @@ -2416,63 +2439,67 @@ case 2: if ((s[1] & 0xc0) != 0x80) { - errmsg = "invalid data"; + errmsg = "invalid continuation byte"; startinpos = s-starts; - endinpos = startinpos+2; + endinpos = startinpos + 1; goto utf8Error; } ch = ((s[0] & 0x1f) << 6) + (s[1] & 0x3f); - if (ch < 0x80) { - startinpos = s-starts; - endinpos = startinpos+2; - errmsg = "illegal encoding"; - goto utf8Error; - } - else - *p++ = (Py_UNICODE)ch; + assert ((ch > 0x007F) && (ch <= 0x07FF)); + *p++ = (Py_UNICODE)ch; break; case 3: + /* Decoding UTF-8 sequences in range \xed\xa0\x80-\xed\xbf\xbf + will result in surrogates in range d800-dfff. Surrogates are + not valid UTF-8 so they are rejected. + See http://www.unicode.org/versions/Unicode5.2.0/ch03.pdf + (table 3-7) and http://www.rfc-editor.org/rfc/rfc3629.txt */ if ((s[1] & 0xc0) != 0x80 || - (s[2] & 0xc0) != 0x80) { - errmsg = "invalid data"; + (s[2] & 0xc0) != 0x80 || + ((unsigned char)s[0] == 0xE0 && + (unsigned char)s[1] < 0xA0) || + ((unsigned char)s[0] == 0xED && + (unsigned char)s[1] > 0x9F)) { + errmsg = "invalid continuation byte"; startinpos = s-starts; - endinpos = startinpos+3; + endinpos = startinpos + 1; + + /* if s[1] first two bits are 1 and 0, then the invalid + continuation byte is s[2], so increment endinpos by 1, + if not, s[1] is invalid and endinpos doesn't need to + be incremented. */ + if ((s[1] & 0xC0) == 0x80) + endinpos++; goto utf8Error; } ch = ((s[0] & 0x0f) << 12) + ((s[1] & 0x3f) << 6) + (s[2] & 0x3f); - if (ch < 0x0800 || (ch >= 0xd800 && ch <= 0xDFFF)) { - errmsg = "illegal encoding"; - startinpos = s-starts; - endinpos = startinpos+3; - goto utf8Error; - } - else - *p++ = (Py_UNICODE)ch; + assert ((ch > 0x07FF) && (ch <= 0xFFFF)); + *p++ = (Py_UNICODE)ch; break; case 4: if ((s[1] & 0xc0) != 0x80 || (s[2] & 0xc0) != 0x80 || - (s[3] & 0xc0) != 0x80) { - errmsg = "invalid data"; + (s[3] & 0xc0) != 0x80 || + ((unsigned char)s[0] == 0xF0 && + (unsigned char)s[1] < 0x90) || + ((unsigned char)s[0] == 0xF4 && + (unsigned char)s[1] > 0x8F)) { + errmsg = "invalid continuation byte"; startinpos = s-starts; - endinpos = startinpos+4; + endinpos = startinpos + 1; + if ((s[1] & 0xC0) == 0x80) { + endinpos++; + if ((s[2] & 0xC0) == 0x80) + endinpos++; + } goto utf8Error; } ch = ((s[0] & 0x7) << 18) + ((s[1] & 0x3f) << 12) + - ((s[2] & 0x3f) << 6) + (s[3] & 0x3f); - /* validate and convert to UTF-16 */ - if ((ch < 0x10000) /* minimum value allowed for 4 - byte encoding */ - || (ch > 0x10ffff)) /* maximum value allowed for - UTF-16 */ - { - errmsg = "illegal encoding"; - startinpos = s-starts; - endinpos = startinpos+4; - goto utf8Error; - } + ((s[2] & 0x3f) << 6) + (s[3] & 0x3f); + assert ((ch > 0xFFFF) && (ch <= 0x10ffff)); + #ifdef Py_UNICODE_WIDE *p++ = (Py_UNICODE)ch; #else @@ -2488,13 +2515,6 @@ *p++ = (Py_UNICODE)(0xDC00 + (ch & 0x03FF)); #endif break; - - default: - /* Other sizes are only needed for UCS-4 */ - errmsg = "unsupported Unicode code range"; - startinpos = s-starts; - endinpos = startinpos+n; - goto utf8Error; } s += n; continue; @@ -4552,32 +4572,46 @@ static int decode_mbcs(PyUnicodeObject **v, const char *s, /* MBCS string */ int size, /* sizeof MBCS string */ - int final) + int final, + const char *errors) { Py_UNICODE *p; - Py_ssize_t n = 0; - int usize = 0; + Py_ssize_t n; + DWORD usize; + DWORD flags; assert(size >= 0); + /* check and handle 'errors' arg */ + if (errors==NULL || strcmp(errors, "strict")==0) + flags = MB_ERR_INVALID_CHARS; + else if (strcmp(errors, "ignore")==0) + flags = 0; + else { + PyErr_Format(PyExc_ValueError, + "mbcs encoding does not support errors='%s'", + errors); + return -1; + } + /* Skip trailing lead-byte unless 'final' is set */ if (!final && size >= 1 && is_dbcs_lead_byte(s, size - 1)) --size; /* First get the size of the result */ if (size > 0) { - usize = MultiByteToWideChar(CP_ACP, 0, s, size, NULL, 0); - if (usize == 0) { - PyErr_SetFromWindowsErrWithFilename(0, NULL); - return -1; - } - } + usize = MultiByteToWideChar(CP_ACP, flags, s, size, NULL, 0); + if (usize==0) + goto mbcs_decode_error; + } else + usize = 0; if (*v == NULL) { /* Create unicode object */ *v = _PyUnicode_New(usize); if (*v == NULL) return -1; + n = 0; } else { /* Extend unicode object */ @@ -4587,15 +4621,35 @@ } /* Do the conversion */ - if (size > 0) { + if (usize > 0) { p = PyUnicode_AS_UNICODE(*v) + n; - if (0 == MultiByteToWideChar(CP_ACP, 0, s, size, p, usize)) { - PyErr_SetFromWindowsErrWithFilename(0, NULL); - return -1; + if (0 == MultiByteToWideChar(CP_ACP, flags, s, size, p, usize)) { + goto mbcs_decode_error; } } - return size; + +mbcs_decode_error: + /* If the last error was ERROR_NO_UNICODE_TRANSLATION, then + we raise a UnicodeDecodeError - else it is a 'generic' + windows error + */ + if (GetLastError()==ERROR_NO_UNICODE_TRANSLATION) { + /* Ideally, we should get reason from FormatMessage - this + is the Windows 2000 English version of the message + */ + PyObject *exc = NULL; + const char *reason = "No mapping for the Unicode character exists " + "in the target multi-byte code page."; + make_decode_exception(&exc, "mbcs", s, size, 0, 0, reason); + if (exc != NULL) { + PyCodec_StrictErrors(exc); + Py_DECREF(exc); + } + } else { + PyErr_SetFromWindowsErrWithFilename(0, NULL); + } + return -1; } PyObject *PyUnicode_DecodeMBCSStateful(const char *s, @@ -4612,10 +4666,10 @@ #ifdef NEED_RETRY retry: if (size > INT_MAX) - done = decode_mbcs(&v, s, INT_MAX, 0); + done = decode_mbcs(&v, s, INT_MAX, 0, errors); else #endif - done = decode_mbcs(&v, s, (int)size, !consumed); + done = decode_mbcs(&v, s, (int)size, !consumed, errors); if (done < 0) { Py_XDECREF(v); @@ -4649,20 +4703,45 @@ */ static int encode_mbcs(PyObject **repr, const Py_UNICODE *p, /* unicode */ - int size) /* size of unicode */ + int size, /* size of unicode */ + const char* errors) { - int mbcssize = 0; - Py_ssize_t n = 0; + BOOL usedDefaultChar = FALSE; + BOOL *pusedDefaultChar; + int mbcssize; + Py_ssize_t n; + PyObject *exc = NULL; + DWORD flags; assert(size >= 0); + /* check and handle 'errors' arg */ + if (errors==NULL || strcmp(errors, "strict")==0) { + flags = WC_NO_BEST_FIT_CHARS; + pusedDefaultChar = &usedDefaultChar; + } else if (strcmp(errors, "replace")==0) { + flags = 0; + pusedDefaultChar = NULL; + } else { + PyErr_Format(PyExc_ValueError, + "mbcs encoding does not support errors='%s'", + errors); + return -1; + } + /* First get the size of the result */ if (size > 0) { - mbcssize = WideCharToMultiByte(CP_ACP, 0, p, size, NULL, 0, NULL, NULL); + mbcssize = WideCharToMultiByte(CP_ACP, flags, p, size, NULL, 0, + NULL, pusedDefaultChar); if (mbcssize == 0) { PyErr_SetFromWindowsErrWithFilename(0, NULL); return -1; } + /* If we used a default char, then we failed! */ + if (pusedDefaultChar && *pusedDefaultChar) + goto mbcs_encode_error; + } else { + mbcssize = 0; } if (*repr == NULL) { @@ -4670,6 +4749,7 @@ *repr = PyBytes_FromStringAndSize(NULL, mbcssize); if (*repr == NULL) return -1; + n = 0; } else { /* Extend string object */ @@ -4681,13 +4761,20 @@ /* Do the conversion */ if (size > 0) { char *s = PyBytes_AS_STRING(*repr) + n; - if (0 == WideCharToMultiByte(CP_ACP, 0, p, size, s, mbcssize, NULL, NULL)) { + if (0 == WideCharToMultiByte(CP_ACP, flags, p, size, s, mbcssize, + NULL, pusedDefaultChar)) { PyErr_SetFromWindowsErrWithFilename(0, NULL); return -1; } + if (pusedDefaultChar && *pusedDefaultChar) + goto mbcs_encode_error; } - return 0; + +mbcs_encode_error: + raise_encode_exception(&exc, "mbcs", p, size, 0, 0, "invalid character"); + Py_XDECREF(exc); + return -1; } PyObject *PyUnicode_EncodeMBCS(const Py_UNICODE *p, @@ -4700,10 +4787,10 @@ #ifdef NEED_RETRY retry: if (size > INT_MAX) - ret = encode_mbcs(&repr, p, INT_MAX); + ret = encode_mbcs(&repr, p, INT_MAX, errors); else #endif - ret = encode_mbcs(&repr, p, (int)size); + ret = encode_mbcs(&repr, p, (int)size, errors); if (ret < 0) { Py_XDECREF(repr); @@ -6618,7 +6705,7 @@ "S.capitalize() -> str\n\ \n\ Return a capitalized version of S, i.e. make the first character\n\ -have upper case."); +have upper case and the rest lower case."); static PyObject* unicode_capitalize(PyUnicodeObject *self) @@ -7890,7 +7977,7 @@ } PyDoc_STRVAR(replace__doc__, - "S.replace (old, new[, count]) -> str\n\ + "S.replace(old, new[, count]) -> str\n\ \n\ Return a copy of S with all occurrences of substring\n\ old replaced by new. If the optional argument count is\n\ Modified: python/branches/py3k-dtoa/PC/VS8.0/pythoncore.vcproj ============================================================================== --- python/branches/py3k-dtoa/PC/VS8.0/pythoncore.vcproj (original) +++ python/branches/py3k-dtoa/PC/VS8.0/pythoncore.vcproj Tue Jul 6 17:55:27 2010 @@ -759,10 +759,6 @@ > - - Modified: python/branches/py3k-dtoa/PCbuild/_ctypes.vcproj ============================================================================== --- python/branches/py3k-dtoa/PCbuild/_ctypes.vcproj (original) +++ python/branches/py3k-dtoa/PCbuild/_ctypes.vcproj Tue Jul 6 17:55:27 2010 @@ -1,7 +1,7 @@ @@ -583,23 +575,15 @@ > - - - - - - - - - - - - - - - Modified: python/branches/py3k-dtoa/PCbuild/pythoncore.vcproj ============================================================================== --- python/branches/py3k-dtoa/PCbuild/pythoncore.vcproj (original) +++ python/branches/py3k-dtoa/PCbuild/pythoncore.vcproj Tue Jul 6 17:55:27 2010 @@ -755,10 +755,6 @@ > - - @@ -1040,6 +1036,14 @@ > + + + + Modified: python/branches/py3k-dtoa/Parser/Python.asdl ============================================================================== --- python/branches/py3k-dtoa/Parser/Python.asdl (original) +++ python/branches/py3k-dtoa/Parser/Python.asdl Tue Jul 6 17:55:27 2010 @@ -17,7 +17,7 @@ expr? starargs, expr? kwargs, stmt* body, - expr *decorator_list) + expr* decorator_list) | Return(expr? value) | Delete(expr* targets) Modified: python/branches/py3k-dtoa/Parser/asdl_c.py ============================================================================== --- python/branches/py3k-dtoa/Parser/asdl_c.py (original) +++ python/branches/py3k-dtoa/Parser/asdl_c.py Tue Jul 6 17:55:27 2010 @@ -732,8 +732,9 @@ { int i, result; PyObject *s, *l = PyTuple_New(num_fields); - if (!l) return 0; - for(i = 0; i < num_fields; i++) { + if (!l) + return 0; + for (i = 0; i < num_fields; i++) { s = PyUnicode_FromString(attrs[i]); if (!s) { Py_DECREF(l); Modified: python/branches/py3k-dtoa/Python/Python-ast.c ============================================================================== --- python/branches/py3k-dtoa/Python/Python-ast.c (original) +++ python/branches/py3k-dtoa/Python/Python-ast.c Tue Jul 6 17:55:27 2010 @@ -2,7 +2,7 @@ /* - __version__ 73626. + __version__ 82163. This module must be committed separately after each AST grammar change; The __version__ number is set to the revision number of the commit @@ -537,8 +537,9 @@ { int i, result; PyObject *s, *l = PyTuple_New(num_fields); - if (!l) return 0; - for(i = 0; i < num_fields; i++) { + if (!l) + return 0; + for (i = 0; i < num_fields; i++) { s = PyUnicode_FromString(attrs[i]); if (!s) { Py_DECREF(l); @@ -6773,7 +6774,7 @@ NULL; if (PyModule_AddIntConstant(m, "PyCF_ONLY_AST", PyCF_ONLY_AST) < 0) return NULL; - if (PyModule_AddStringConstant(m, "__version__", "73626") < 0) + if (PyModule_AddStringConstant(m, "__version__", "82163") < 0) return NULL; if (PyDict_SetItemString(d, "mod", (PyObject*)mod_type) < 0) return NULL; Modified: python/branches/py3k-dtoa/Python/_warnings.c ============================================================================== --- python/branches/py3k-dtoa/Python/_warnings.c (original) +++ python/branches/py3k-dtoa/Python/_warnings.c Tue Jul 6 17:55:27 2010 @@ -251,7 +251,7 @@ name = PyObject_GetAttrString(category, "__name__"); if (name == NULL) /* XXX Can an object lack a '__name__' attribute? */ - return; + return; f_stderr = PySys_GetObject("stderr"); if (f_stderr == NULL) { @@ -282,8 +282,7 @@ PyFile_WriteString("\n", f_stderr); } else - if (_Py_DisplaySourceLine(f_stderr, _PyUnicode_AsString(filename), - lineno, 2) < 0) + if (_Py_DisplaySourceLine(f_stderr, filename, lineno, 2) < 0) return; PyErr_Clear(); } @@ -847,28 +846,35 @@ static PyObject * init_filters(void) { - PyObject *filters = PyList_New(3); + /* Don't silence DeprecationWarning if -3 was used. */ + PyObject *filters = PyList_New(4); + unsigned int pos = 0; /* Post-incremented in each use. */ + unsigned int x; const char *bytes_action; + if (filters == NULL) return NULL; - PyList_SET_ITEM(filters, 0, + PyList_SET_ITEM(filters, pos++, + create_filter(PyExc_DeprecationWarning, "ignore")); + PyList_SET_ITEM(filters, pos++, create_filter(PyExc_PendingDeprecationWarning, "ignore")); - PyList_SET_ITEM(filters, 1, create_filter(PyExc_ImportWarning, "ignore")); + PyList_SET_ITEM(filters, pos++, + create_filter(PyExc_ImportWarning, "ignore")); if (Py_BytesWarningFlag > 1) bytes_action = "error"; else if (Py_BytesWarningFlag) bytes_action = "default"; else bytes_action = "ignore"; - PyList_SET_ITEM(filters, 2, create_filter(PyExc_BytesWarning, + PyList_SET_ITEM(filters, pos++, create_filter(PyExc_BytesWarning, bytes_action)); - if (PyList_GET_ITEM(filters, 0) == NULL || - PyList_GET_ITEM(filters, 1) == NULL || - PyList_GET_ITEM(filters, 2) == NULL) { - Py_DECREF(filters); - return NULL; + for (x = 0; x < pos; x += 1) { + if (PyList_GET_ITEM(filters, x) == NULL) { + Py_DECREF(filters); + return NULL; + } } return filters; Modified: python/branches/py3k-dtoa/Python/ast.c ============================================================================== --- python/branches/py3k-dtoa/Python/ast.c (original) +++ python/branches/py3k-dtoa/Python/ast.c Tue Jul 6 17:55:27 2010 @@ -1678,34 +1678,8 @@ static expr_ty ast_for_factor(struct compiling *c, const node *n) { - node *pfactor, *ppower, *patom, *pnum; expr_ty expression; - /* If the unary - operator is applied to a constant, don't generate - a UNARY_NEGATIVE opcode. Just store the approriate value as a - constant. The peephole optimizer already does something like - this but it doesn't handle the case where the constant is - (sys.maxint - 1). In that case, we want a PyIntObject, not a - PyLongObject. - */ - if (TYPE(CHILD(n, 0)) == MINUS - && NCH(n) == 2 - && TYPE((pfactor = CHILD(n, 1))) == factor - && NCH(pfactor) == 1 - && TYPE((ppower = CHILD(pfactor, 0))) == power - && NCH(ppower) == 1 - && TYPE((patom = CHILD(ppower, 0))) == atom - && TYPE((pnum = CHILD(patom, 0))) == NUMBER) { - char *s = PyObject_MALLOC(strlen(STR(pnum)) + 2); - if (s == NULL) - return NULL; - s[0] = '-'; - strcpy(s + 1, STR(pnum)); - PyObject_FREE(STR(pnum)); - STR(pnum) = s; - return ast_for_atom(c, patom); - } - expression = ast_for_expr(c, CHILD(n, 1)); if (!expression) return NULL; Modified: python/branches/py3k-dtoa/Python/ceval.c ============================================================================== --- python/branches/py3k-dtoa/Python/ceval.c (original) +++ python/branches/py3k-dtoa/Python/ceval.c Tue Jul 6 17:55:27 2010 @@ -87,7 +87,7 @@ inst = inst1 - inst0 - intr; loop = loop1 - loop0 - intr; fprintf(stderr, "opcode=%03d t=%d inst=%06lld loop=%06lld\n", - opcode, ticked, inst, loop); + opcode, ticked, inst, loop); } #endif @@ -126,10 +126,10 @@ static int call_trace(Py_tracefunc, PyObject *, PyFrameObject *, int, PyObject *); static int call_trace_protected(Py_tracefunc, PyObject *, - PyFrameObject *, int, PyObject *); + PyFrameObject *, int, PyObject *); static void call_exc_trace(Py_tracefunc, PyObject *, PyFrameObject *); static int maybe_call_line_trace(Py_tracefunc, PyObject *, - PyFrameObject *, int *, int *, int *); + PyFrameObject *, int *, int *, int *); static PyObject * cmp_outcome(int, PyObject *, PyObject *); static PyObject * import_from(PyObject *, PyObject *); @@ -718,14 +718,14 @@ /* Status code for main loop (reason for stack unwind) */ enum why_code { - WHY_NOT = 0x0001, /* No error */ - WHY_EXCEPTION = 0x0002, /* Exception occurred */ - WHY_RERAISE = 0x0004, /* Exception re-raised by 'finally' */ - WHY_RETURN = 0x0008, /* 'return' statement */ - WHY_BREAK = 0x0010, /* 'break' statement */ - WHY_CONTINUE = 0x0020, /* 'continue' statement */ - WHY_YIELD = 0x0040, /* 'yield' operator */ - WHY_SILENCED = 0x0080 /* Exception silenced by 'with' */ + WHY_NOT = 0x0001, /* No error */ + WHY_EXCEPTION = 0x0002, /* Exception occurred */ + WHY_RERAISE = 0x0004, /* Exception re-raised by 'finally' */ + WHY_RETURN = 0x0008, /* 'return' statement */ + WHY_BREAK = 0x0010, /* 'break' statement */ + WHY_CONTINUE = 0x0020, /* 'continue' statement */ + WHY_YIELD = 0x0040, /* 'yield' operator */ + WHY_SILENCED = 0x0080 /* Exception silenced by 'with' */ }; static enum why_code do_raise(PyObject *, PyObject *); @@ -1005,38 +1005,38 @@ /* The stack can grow at most MAXINT deep, as co_nlocals and co_stacksize are ints. */ -#define STACK_LEVEL() ((int)(stack_pointer - f->f_valuestack)) -#define EMPTY() (STACK_LEVEL() == 0) -#define TOP() (stack_pointer[-1]) -#define SECOND() (stack_pointer[-2]) -#define THIRD() (stack_pointer[-3]) -#define FOURTH() (stack_pointer[-4]) -#define PEEK(n) (stack_pointer[-(n)]) -#define SET_TOP(v) (stack_pointer[-1] = (v)) -#define SET_SECOND(v) (stack_pointer[-2] = (v)) -#define SET_THIRD(v) (stack_pointer[-3] = (v)) -#define SET_FOURTH(v) (stack_pointer[-4] = (v)) -#define SET_VALUE(n, v) (stack_pointer[-(n)] = (v)) -#define BASIC_STACKADJ(n) (stack_pointer += n) -#define BASIC_PUSH(v) (*stack_pointer++ = (v)) -#define BASIC_POP() (*--stack_pointer) +#define STACK_LEVEL() ((int)(stack_pointer - f->f_valuestack)) +#define EMPTY() (STACK_LEVEL() == 0) +#define TOP() (stack_pointer[-1]) +#define SECOND() (stack_pointer[-2]) +#define THIRD() (stack_pointer[-3]) +#define FOURTH() (stack_pointer[-4]) +#define PEEK(n) (stack_pointer[-(n)]) +#define SET_TOP(v) (stack_pointer[-1] = (v)) +#define SET_SECOND(v) (stack_pointer[-2] = (v)) +#define SET_THIRD(v) (stack_pointer[-3] = (v)) +#define SET_FOURTH(v) (stack_pointer[-4] = (v)) +#define SET_VALUE(n, v) (stack_pointer[-(n)] = (v)) +#define BASIC_STACKADJ(n) (stack_pointer += n) +#define BASIC_PUSH(v) (*stack_pointer++ = (v)) +#define BASIC_POP() (*--stack_pointer) #ifdef LLTRACE #define PUSH(v) { (void)(BASIC_PUSH(v), \ - lltrace && prtrace(TOP(), "push")); \ - assert(STACK_LEVEL() <= co->co_stacksize); } + lltrace && prtrace(TOP(), "push")); \ + assert(STACK_LEVEL() <= co->co_stacksize); } #define POP() ((void)(lltrace && prtrace(TOP(), "pop")), \ - BASIC_POP()) + BASIC_POP()) #define STACKADJ(n) { (void)(BASIC_STACKADJ(n), \ - lltrace && prtrace(TOP(), "stackadj")); \ - assert(STACK_LEVEL() <= co->co_stacksize); } + lltrace && prtrace(TOP(), "stackadj")); \ + assert(STACK_LEVEL() <= co->co_stacksize); } #define EXT_POP(STACK_POINTER) ((void)(lltrace && \ - prtrace((STACK_POINTER)[-1], "ext_pop")), \ - *--(STACK_POINTER)) + prtrace((STACK_POINTER)[-1], "ext_pop")), \ + *--(STACK_POINTER)) #else -#define PUSH(v) BASIC_PUSH(v) -#define POP() BASIC_POP() -#define STACKADJ(n) BASIC_STACKADJ(n) +#define PUSH(v) BASIC_PUSH(v) +#define POP() BASIC_POP() +#define STACKADJ(n) BASIC_STACKADJ(n) #define EXT_POP(STACK_POINTER) (*--(STACK_POINTER)) #endif @@ -1051,8 +1051,8 @@ accessed by other code (e.g. a __del__ method or gc.collect()) and the variable would be pointing to already-freed memory. */ #define SETLOCAL(i, value) do { PyObject *tmp = GETLOCAL(i); \ - GETLOCAL(i) = value; \ - Py_XDECREF(tmp); } while (0) + GETLOCAL(i) = value; \ + Py_XDECREF(tmp); } while (0) #define UNWIND_BLOCK(b) \ @@ -1318,7 +1318,7 @@ it doesn't have to be remembered across a full loop */ if (HAS_ARG(opcode)) oparg = NEXTARG(); - dispatch_opcode: + dispatch_opcode: #ifdef DYNAMIC_EXECUTION_PROFILE #ifdef DXPAIRS dxpairs[lastopcode][opcode]++; @@ -2174,8 +2174,8 @@ break; if (oparg < PyTuple_GET_SIZE(co->co_cellvars)) { v = PyTuple_GET_ITEM(co->co_cellvars, - oparg); - format_exc_check_arg( + oparg); + format_exc_check_arg( PyExc_UnboundLocalError, UNBOUNDLOCAL_ERROR_MSG, v); @@ -2695,7 +2695,7 @@ func = *pfunc; if (PyMethod_Check(func) - && PyMethod_GET_SELF(func) != NULL) { + && PyMethod_GET_SELF(func) != NULL) { PyObject *self = PyMethod_GET_SELF(func); Py_INCREF(self); func = PyMethod_GET_FUNCTION(func); @@ -3100,11 +3100,11 @@ if (!(co->co_flags & CO_VARARGS)) { PyErr_Format(PyExc_TypeError, "%U() takes %s %d " - "argument%s (%d given)", + "positional argument%s (%d given)", co->co_name, defcount ? "at most" : "exactly", - total_args, - total_args == 1 ? "" : "s", + co->co_argcount, + co->co_argcount == 1 ? "" : "s", argcount + kwcount); goto fail; } Modified: python/branches/py3k-dtoa/Python/compile.c ============================================================================== --- python/branches/py3k-dtoa/Python/compile.c (original) +++ python/branches/py3k-dtoa/Python/compile.c Tue Jul 6 17:55:27 2010 @@ -968,7 +968,7 @@ { int arg = compiler_add_o(c, dict, o); if (arg < 0) - return 0; + return 0; return compiler_addop_i(c, opcode, arg); } @@ -979,11 +979,11 @@ int arg; PyObject *mangled = _Py_Mangle(c->u->u_private, o); if (!mangled) - return 0; + return 0; arg = compiler_add_o(c, dict, mangled); Py_DECREF(mangled); if (arg < 0) - return 0; + return 0; return compiler_addop_i(c, opcode, arg); } @@ -1134,7 +1134,7 @@ compiler_isdocstring(stmt_ty s) { if (s->kind != Expr_kind) - return 0; + return 0; return s->v.Expr.value->kind == Str_kind; } @@ -1240,11 +1240,11 @@ PyObject *k, *v; k = PyTuple_Pack(2, name, name->ob_type); if (k == NULL) - return -1; + return -1; v = PyDict_GetItem(dict, k); Py_DECREF(k); if (v == NULL) - return -1; + return -1; return PyLong_AS_LONG(v); } @@ -3073,7 +3073,7 @@ block = compiler_new_block(c); finally = compiler_new_block(c); if (!block || !finally) - return 0; + return 0; /* Evaluate EXPR */ VISIT(c, expr, s->v.With.context_expr); @@ -3082,15 +3082,15 @@ /* SETUP_WITH pushes a finally block. */ compiler_use_next_block(c, block); if (!compiler_push_fblock(c, FINALLY_TRY, block)) { - return 0; + return 0; } if (s->v.With.optional_vars) { - VISIT(c, expr, s->v.With.optional_vars); + VISIT(c, expr, s->v.With.optional_vars); } else { /* Discard result from context.__enter__() */ - ADDOP(c, POP_TOP); + ADDOP(c, POP_TOP); } /* BLOCK code */ @@ -3103,7 +3103,7 @@ ADDOP_O(c, LOAD_CONST, Py_None, consts); compiler_use_next_block(c, finally); if (!compiler_push_fblock(c, FINALLY_END, finally)) - return 0; + return 0; /* Finally block starts; context.__exit__ is on the stack under the exception or return information. Just issue our magic @@ -3942,7 +3942,7 @@ freevars = dict_keys_inorder(c->u->u_freevars, PyTuple_Size(cellvars)); if (!freevars) goto error; - filename = PyUnicode_DecodeFSDefault(c->c_filename); + filename = PyUnicode_FromString(c->c_filename); if (!filename) goto error; Modified: python/branches/py3k-dtoa/Python/getargs.c ============================================================================== --- python/branches/py3k-dtoa/Python/getargs.c (original) +++ python/branches/py3k-dtoa/Python/getargs.c Tue Jul 6 17:55:27 2010 @@ -853,70 +853,6 @@ /* XXX WAAAAH! 's', 'y', 'z', 'u', 'Z', 'e', 'w' codes all need to be cleaned up! */ - case 's': {/* text string */ - if (*format == '*') { - Py_buffer *p = (Py_buffer *)va_arg(*p_va, Py_buffer *); - - if (PyUnicode_Check(arg)) { - uarg = UNICODE_DEFAULT_ENCODING(arg); - if (uarg == NULL) - return converterr(CONV_UNICODE, - arg, msgbuf, bufsize); - PyBuffer_FillInfo(p, arg, - PyBytes_AS_STRING(uarg), PyBytes_GET_SIZE(uarg), - 1, 0); - } - else { /* any buffer-like object */ - char *buf; - if (getbuffer(arg, p, &buf) < 0) - return converterr(buf, arg, msgbuf, bufsize); - } - if (addcleanup(p, freelist, cleanup_buffer)) { - return converterr( - "(cleanup problem)", - arg, msgbuf, bufsize); - } - format++; - } else if (*format == '#') { - void **p = (void **)va_arg(*p_va, char **); - FETCH_SIZE; - - if (PyUnicode_Check(arg)) { - uarg = UNICODE_DEFAULT_ENCODING(arg); - if (uarg == NULL) - return converterr(CONV_UNICODE, - arg, msgbuf, bufsize); - *p = PyBytes_AS_STRING(uarg); - STORE_SIZE(PyBytes_GET_SIZE(uarg)); - } - else { /* any buffer-like object */ - /* XXX Really? */ - char *buf; - Py_ssize_t count = convertbuffer(arg, p, &buf); - if (count < 0) - return converterr(buf, arg, msgbuf, bufsize); - STORE_SIZE(count); - } - format++; - } else { - char **p = va_arg(*p_va, char **); - - if (PyUnicode_Check(arg)) { - uarg = UNICODE_DEFAULT_ENCODING(arg); - if (uarg == NULL) - return converterr(CONV_UNICODE, - arg, msgbuf, bufsize); - *p = PyBytes_AS_STRING(uarg); - } - else - return converterr("string", arg, msgbuf, bufsize); - if ((Py_ssize_t) strlen(*p) != PyBytes_GET_SIZE(uarg)) - return converterr("string without null bytes", - arg, msgbuf, bufsize); - } - break; - } - case 'y': {/* any buffer-like object, but not PyUnicode */ void **p = (void **)va_arg(*p_va, char **); char *buf; @@ -948,11 +884,14 @@ break; } - case 'z': {/* like 's' or 's#', but None is okay, stored as NULL */ + case 's': /* text string */ + case 'z': /* text string or None */ + { if (*format == '*') { + /* "s*" or "z*" */ Py_buffer *p = (Py_buffer *)va_arg(*p_va, Py_buffer *); - if (arg == Py_None) + if (c == 'z' && arg == Py_None) PyBuffer_FillInfo(p, NULL, NULL, 0, 1, 0); else if (PyUnicode_Check(arg)) { uarg = UNICODE_DEFAULT_ENCODING(arg); @@ -975,11 +914,12 @@ } format++; } else if (*format == '#') { /* any buffer-like object */ + /* "s#" or "z#" */ void **p = (void **)va_arg(*p_va, char **); FETCH_SIZE; - if (arg == Py_None) { - *p = 0; + if (c == 'z' && arg == Py_None) { + *p = NULL; STORE_SIZE(0); } else if (PyUnicode_Check(arg)) { @@ -1000,16 +940,12 @@ } format++; } else { + /* "s" or "z" */ char **p = va_arg(*p_va, char **); uarg = NULL; - if (arg == Py_None) - *p = 0; - else if (PyBytes_Check(arg)) { - /* Enable null byte check below */ - uarg = arg; - *p = PyBytes_AS_STRING(arg); - } + if (c == 'z' && arg == Py_None) + *p = NULL; else if (PyUnicode_Check(arg)) { uarg = UNICODE_DEFAULT_ENCODING(arg); if (uarg == NULL) @@ -1018,24 +954,28 @@ *p = PyBytes_AS_STRING(uarg); } else - return converterr("string or None", + return converterr(c == 'z' ? "str or None" : "str", arg, msgbuf, bufsize); if (*p != NULL && uarg != NULL && (Py_ssize_t) strlen(*p) != PyBytes_GET_SIZE(uarg)) return converterr( - "string without null bytes or None", + c == 'z' ? "str without null bytes or None" + : "str without null bytes", arg, msgbuf, bufsize); } break; } - case 'Z': {/* unicode, may be NULL (None) */ + case 'u': /* raw unicode buffer (Py_UNICODE *) */ + case 'Z': /* raw unicode buffer or None */ + { if (*format == '#') { /* any buffer-like object */ + /* "s#" or "Z#" */ Py_UNICODE **p = va_arg(*p_va, Py_UNICODE **); FETCH_SIZE; - if (arg == Py_None) { - *p = 0; + if (c == 'Z' && arg == Py_None) { + *p = NULL; STORE_SIZE(0); } else if (PyUnicode_Check(arg)) { @@ -1046,10 +986,11 @@ return converterr("str or None", arg, msgbuf, bufsize); format++; } else { + /* "s" or "Z" */ Py_UNICODE **p = va_arg(*p_va, Py_UNICODE **); - if (arg == Py_None) - *p = 0; + if (c == 'Z' && arg == Py_None) + *p = NULL; else if (PyUnicode_Check(arg)) { *p = PyUnicode_AS_UNICODE(arg); if (Py_UNICODE_strlen(*p) != PyUnicode_GET_SIZE(arg)) @@ -1057,7 +998,8 @@ "str without null character or None", arg, msgbuf, bufsize); } else - return converterr("str or None", arg, msgbuf, bufsize); + return converterr(c == 'Z' ? "str or None" : "str", + arg, msgbuf, bufsize); } break; } @@ -1227,24 +1169,6 @@ break; } - case 'u': {/* raw unicode buffer (Py_UNICODE *) */ - Py_UNICODE **p = va_arg(*p_va, Py_UNICODE **); - if (!PyUnicode_Check(arg)) - return converterr("str", arg, msgbuf, bufsize); - *p = PyUnicode_AS_UNICODE(arg); - if (*format == '#') { /* store pointer and size */ - FETCH_SIZE; - STORE_SIZE(PyUnicode_GET_SIZE(arg)); - format++; - } else { - if (Py_UNICODE_strlen(*p) != PyUnicode_GET_SIZE(arg)) - return converterr( - "str without null character", - arg, msgbuf, bufsize); - } - break; - } - case 'S': { /* PyBytes object */ PyObject **p = va_arg(*p_va, PyObject **); if (PyBytes_Check(arg)) @@ -1307,58 +1231,28 @@ } - case 'w': { /* memory buffer, read-write access */ + case 'w': { /* "w*": memory buffer, read-write access */ void **p = va_arg(*p_va, void **); - PyBufferProcs *pb = arg->ob_type->tp_as_buffer; - Py_ssize_t count; - int temp=-1; - Py_buffer view; - if (pb && pb->bf_releasebuffer && *format != '*') - /* Buffer must be released, yet caller does not use - the Py_buffer protocol. */ - return converterr("pinned buffer", arg, msgbuf, bufsize); - - - if (pb && pb->bf_getbuffer && *format == '*') { - /* Caller is interested in Py_buffer, and the object - supports it directly. */ - format++; - if (PyObject_GetBuffer(arg, (Py_buffer*)p, PyBUF_WRITABLE) < 0) { - PyErr_Clear(); - return converterr("read-write buffer", arg, msgbuf, bufsize); - } - if (addcleanup(p, freelist, cleanup_buffer)) { - return converterr( - "(cleanup problem)", - arg, msgbuf, bufsize); - } - if (!PyBuffer_IsContiguous((Py_buffer*)p, 'C')) - return converterr("contiguous buffer", arg, msgbuf, bufsize); - break; - } + if (*format != '*') + return converterr( + "invalid use of 'w' format character", + arg, msgbuf, bufsize); + format++; - /* Here we have processed w*, only w and w# remain. */ - if (pb == NULL || - pb->bf_getbuffer == NULL || - ((temp = PyObject_GetBuffer(arg, &view, - PyBUF_SIMPLE)) != 0) || - view.readonly == 1) { - if (temp==0) { - PyBuffer_Release(&view); - } - return converterr("single-segment read-write buffer", - arg, msgbuf, bufsize); + /* Caller is interested in Py_buffer, and the object + supports it directly. */ + if (PyObject_GetBuffer(arg, (Py_buffer*)p, PyBUF_WRITABLE) < 0) { + PyErr_Clear(); + return converterr("read-write buffer", arg, msgbuf, bufsize); } - - if ((count = view.len) < 0) - return converterr("(unspecified)", arg, msgbuf, bufsize); - *p = view.buf; - if (*format == '#') { - FETCH_SIZE; - STORE_SIZE(count); - format++; + if (addcleanup(p, freelist, cleanup_buffer)) { + return converterr( + "(cleanup problem)", + arg, msgbuf, bufsize); } + if (!PyBuffer_IsContiguous((Py_buffer*)p, 'C')) + return converterr("contiguous buffer", arg, msgbuf, bufsize); break; } @@ -1416,6 +1310,7 @@ return -1; } if (!PyBuffer_IsContiguous(view, 'C')) { + PyBuffer_Release(view); *errmsg = "contiguous buffer"; return -1; } Modified: python/branches/py3k-dtoa/Python/import.c ============================================================================== --- python/branches/py3k-dtoa/Python/import.c (original) +++ python/branches/py3k-dtoa/Python/import.c Tue Jul 6 17:55:27 2010 @@ -558,10 +558,10 @@ copy can be retrieved from there by calling _PyImport_FindExtension(). - Modules which do support multiple multiple initialization set - their m_size field to a non-negative number (indicating the size - of the module-specific state). They are still recorded in the - extensions dictionary, to avoid loading shared libraries twice. + Modules which do support multiple initialization set their m_size + field to a non-negative number (indicating the size of the + module-specific state). They are still recorded in the extensions + dictionary, to avoid loading shared libraries twice. */ int @@ -2385,7 +2385,8 @@ if (parent == NULL) return NULL; - head = load_next(parent, Py_None, &name, buf, &buflen); + head = load_next(parent, level < 0 ? Py_None : parent, &name, buf, + &buflen); if (head == NULL) return NULL; Modified: python/branches/py3k-dtoa/Python/pythonrun.c ============================================================================== --- python/branches/py3k-dtoa/Python/pythonrun.c (original) +++ python/branches/py3k-dtoa/Python/pythonrun.c Tue Jul 6 17:55:27 2010 @@ -1190,7 +1190,7 @@ d = PyModule_GetDict(m); if (PyDict_GetItemString(d, "__file__") == NULL) { PyObject *f; - f = PyUnicode_DecodeFSDefault(filename); + f = PyUnicode_FromString(filename); if (f == NULL) return -1; if (PyDict_SetItemString(d, "__file__", f) < 0) { Modified: python/branches/py3k-dtoa/Python/sysmodule.c ============================================================================== --- python/branches/py3k-dtoa/Python/sysmodule.c (original) +++ python/branches/py3k-dtoa/Python/sysmodule.c Tue Jul 6 17:55:27 2010 @@ -595,7 +595,7 @@ 5, }; -PyObject * +static PyObject * get_hash_info(void) { PyObject *hash_info; Modified: python/branches/py3k-dtoa/Python/traceback.c ============================================================================== --- python/branches/py3k-dtoa/Python/traceback.c (original) +++ python/branches/py3k-dtoa/Python/traceback.c Tue Jul 6 17:55:27 2010 @@ -133,33 +133,38 @@ return 0; } -static int -_Py_FindSourceFile(const char* filename, char* namebuf, size_t namelen, int open_flags) +static PyObject * +_Py_FindSourceFile(PyObject *filename, char* namebuf, size_t namelen, PyObject *io) { - int i; - int fd = -1; + Py_ssize_t i; + PyObject *binary; PyObject *v; - Py_ssize_t _npath; - int npath; + Py_ssize_t npath; size_t taillen; PyObject *syspath; const char* path; const char* tail; + const char* filepath; Py_ssize_t len; + filepath = _PyUnicode_AsString(filename); + if (filepath == NULL) { + PyErr_Clear(); + return NULL; + } + /* Search tail of filename in sys.path before giving up */ - tail = strrchr(filename, SEP); + tail = strrchr(filepath, SEP); if (tail == NULL) - tail = filename; + tail = filepath; else tail++; taillen = strlen(tail); syspath = PySys_GetObject("path"); if (syspath == NULL || !PyList_Check(syspath)) - return -1; - _npath = PyList_Size(syspath); - npath = Py_SAFE_DOWNCAST(_npath, Py_ssize_t, int); + return NULL; + npath = PyList_Size(syspath); for (i = 0; i < npath; i++) { v = PyList_GetItem(syspath, i); @@ -170,6 +175,10 @@ if (!PyUnicode_Check(v)) continue; path = _PyUnicode_AsStringAndSize(v, &len); + if (path == NULL) { + PyErr_Clear(); + continue; + } if (len + 1 + (Py_ssize_t)taillen >= (Py_ssize_t)namelen - 1) continue; /* Too long */ strcpy(namebuf, path); @@ -178,31 +187,27 @@ if (len > 0 && namebuf[len-1] != SEP) namebuf[len++] = SEP; strcpy(namebuf+len, tail); - Py_BEGIN_ALLOW_THREADS - fd = open(namebuf, open_flags); - Py_END_ALLOW_THREADS - if (0 <= fd) { - return fd; - } + + binary = PyObject_CallMethod(io, "open", "ss", namebuf, "rb"); + if (binary != NULL) + return binary; + PyErr_Clear(); } - return -1; + return NULL; } int -_Py_DisplaySourceLine(PyObject *f, const char *filename, int lineno, int indent) +_Py_DisplaySourceLine(PyObject *f, PyObject *filename, int lineno, int indent) { int err = 0; int fd; int i; char *found_encoding; char *encoding; + PyObject *io; + PyObject *binary; PyObject *fob = NULL; PyObject *lineobj = NULL; -#ifdef O_BINARY - const int open_flags = O_RDONLY | O_BINARY; /* necessary for Windows */ -#else - const int open_flags = O_RDONLY; -#endif char buf[MAXPATHLEN+1]; Py_UNICODE *u, *p; Py_ssize_t len; @@ -210,27 +215,32 @@ /* open the file */ if (filename == NULL) return 0; - Py_BEGIN_ALLOW_THREADS - fd = open(filename, open_flags); - Py_END_ALLOW_THREADS - if (fd < 0) { - fd = _Py_FindSourceFile(filename, buf, sizeof(buf), open_flags); - if (fd < 0) + + io = PyImport_ImportModuleNoBlock("io"); + if (io == NULL) + return -1; + binary = PyObject_CallMethod(io, "open", "Os", filename, "rb"); + + if (binary == NULL) { + binary = _Py_FindSourceFile(filename, buf, sizeof(buf), io); + if (binary == NULL) { + Py_DECREF(io); return 0; - filename = buf; + } } /* use the right encoding to decode the file as unicode */ + fd = PyObject_AsFileDescriptor(binary); found_encoding = PyTokenizer_FindEncoding(fd); - encoding = (found_encoding != NULL) ? found_encoding : - (char*)PyUnicode_GetDefaultEncoding(); + encoding = (found_encoding != NULL) ? found_encoding : "utf-8"; lseek(fd, 0, 0); /* Reset position */ - fob = PyFile_FromFd(fd, (char*)filename, "r", -1, (char*)encoding, - NULL, NULL, 1); + fob = PyObject_CallMethod(io, "TextIOWrapper", "Os", binary, encoding); + Py_DECREF(io); + Py_DECREF(binary); PyMem_FREE(found_encoding); + if (fob == NULL) { PyErr_Clear(); - close(fd); return 0; } @@ -287,17 +297,19 @@ } static int -tb_displayline(PyObject *f, const char *filename, int lineno, const char *name) +tb_displayline(PyObject *f, PyObject *filename, int lineno, PyObject *name) { - int err = 0; - char linebuf[2000]; + int err; + PyObject *line; if (filename == NULL || name == NULL) return -1; - /* This is needed by Emacs' compile command */ -#define FMT " File \"%.500s\", line %d, in %.500s\n" - PyOS_snprintf(linebuf, sizeof(linebuf), FMT, filename, lineno, name); - err = PyFile_WriteString(linebuf, f); + line = PyUnicode_FromFormat(" File \"%U\", line %d, in %U\n", + filename, lineno, name); + if (line == NULL) + return -1; + err = PyFile_WriteObject(line, f, Py_PRINT_RAW); + Py_DECREF(line); if (err != 0) return err; return _Py_DisplaySourceLine(f, filename, lineno, 4); @@ -316,10 +328,9 @@ while (tb != NULL && err == 0) { if (depth <= limit) { err = tb_displayline(f, - _PyUnicode_AsString( - tb->tb_frame->f_code->co_filename), - tb->tb_lineno, - _PyUnicode_AsString(tb->tb_frame->f_code->co_name)); + tb->tb_frame->f_code->co_filename, + tb->tb_lineno, + tb->tb_frame->f_code->co_name); } depth--; tb = tb->tb_next; Modified: python/branches/py3k-dtoa/README ============================================================================== --- python/branches/py3k-dtoa/README (original) +++ python/branches/py3k-dtoa/README Tue Jul 6 17:55:27 2010 @@ -172,13 +172,13 @@ Release Schedule ---------------- -See PEP 375 for release details: http://www.python.org/dev/peps/pep-0375/ +See PEP 392 for release details: http://www.python.org/dev/peps/pep-0392/ Copyright and License Information --------------------------------- -Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 +Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Python Software Foundation. All rights reserved. Modified: python/branches/py3k-dtoa/Tools/README ============================================================================== --- python/branches/py3k-dtoa/Tools/README (original) +++ python/branches/py3k-dtoa/Tools/README Tue Jul 6 17:55:27 2010 @@ -1,18 +1,7 @@ This directory contains a number of Python programs that are useful while building or extending Python. -audiopy Audiopy is a program to control the Solaris audio - device, allowing you to choose both the input and - output devices, and to set the output volume, that can - be run either as a command-line script, or as a - Tkinter application. - -compiler Tools used to maintain the compiler package in the - standard library. - -faqwiz FAQ Wizard. - See http://www.python.org/cgi-bin/faqw.py - for a live example. +faqwiz FAQ Wizard: a CGI script for a user-editable FAQ. freeze Create a stand-alone executable from a Python program. @@ -36,8 +25,6 @@ versioncheck A tool to automate checking whether you have the latest version of a package (by Jack Jansen). -webchecker A link checker for web sites. - world Script to take a list of Internet addresses and print out where in the world those addresses originate from, based on the top-level domain country code found in Modified: python/branches/py3k-dtoa/Tools/scripts/patchcheck.py ============================================================================== --- python/branches/py3k-dtoa/Tools/scripts/patchcheck.py (original) +++ python/branches/py3k-dtoa/Tools/scripts/patchcheck.py Tue Jul 6 17:55:27 2010 @@ -5,6 +5,10 @@ import reindent +def n_files_str(count): + """Return 'N file(s)' with the proper plurality on 'file'.""" + return "{} file{}".format(count, "s" if count != 1 else "") + def status(message, modal=False, info=None): """Decorator to output status info to stdout.""" def decorated_fxn(fxn): @@ -26,7 +30,7 @@ return decorated_fxn @status("Getting the list of files that have been added/changed", - info=lambda x: "%s files" % len(x)) + info=lambda x: n_files_str(len(x))) def changed_files(): """Run ``svn status`` and return a set of files that have been changed/added.""" @@ -44,20 +48,30 @@ files.add(path) return files - at status("Fixing whitespace", info=lambda x: "%s files" % x) +def report_modified_files(file_paths): + count = len(file_paths) + if count == 0: + return n_files_str(count) + else: + lines = ["{}:".format(n_files_str(count))] + for path in file_paths: + lines.append(" {}".format(path)) + return "\n".join(lines) + + at status("Fixing whitespace", info=report_modified_files) def normalize_whitespace(file_paths): """Make sure that the whitespace for .py files have been normalized.""" reindent.makebackup = False # No need to create backups. - result = list(map(reindent.check, (x for x in file_paths if x.endswith('.py')))) - return sum(result) + fixed = [] + for path in (x for x in file_paths if x.endswith('.py')): + if reindent.check(path): + fixed.append(path) + return fixed @status("Docs modified", modal=True) def docs_modified(file_paths): - """Report if any files in the Docs directory.""" - for path in file_paths: - if path.startswith("Doc"): - return True - return False + """Report if any file in the Doc directory has been changed.""" + return bool(file_paths) @status("Misc/ACKS updated", modal=True) def credit_given(file_paths): @@ -72,14 +86,18 @@ def main(): file_paths = changed_files() - # PEP 7/8 verification. - normalize_whitespace(file_paths) + python_files = [fn for fn in file_paths if fn.endswith('.py')] + c_files = [fn for fn in file_paths if fn.endswith(('.c', '.h'))] + docs = [fn for fn in file_paths if fn.startswith('Doc')] + special_files = {'Misc/ACKS', 'Misc/NEWS'} & set(file_paths) + # PEP 8 whitespace rules enforcement. + normalize_whitespace(python_files) # Docs updated. - docs_modified(file_paths) + docs_modified(docs) # Misc/ACKS changed. - credit_given(file_paths) + credit_given(special_files) # Misc/NEWS changed. - reported_news(file_paths) + reported_news(special_files) # Test suite run and passed. print() Modified: python/branches/py3k-dtoa/configure ============================================================================== --- python/branches/py3k-dtoa/configure (original) +++ python/branches/py3k-dtoa/configure Tue Jul 6 17:55:27 2010 @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.in Revision: 81078 . +# From configure.in Revision: 82090 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.65 for python 3.2. # Modified: python/branches/py3k-dtoa/setup.py ============================================================================== --- python/branches/py3k-dtoa/setup.py (original) +++ python/branches/py3k-dtoa/setup.py Tue Jul 6 17:55:27 2010 @@ -46,7 +46,7 @@ """ Returns True if 'path' can be located in an OSX SDK """ - return path.startswith('/usr/') or path.startswith('/System/') + return (path.startswith('/usr/') and not path.startswith('/usr/local')) or path.startswith('/System/') def find_file(filename, std_dirs, paths): """Searches for the directory where a given file is located, @@ -450,9 +450,9 @@ depends=['_math.h'], libraries=math_libs) ) # time operations and variables - exts.append( Extension('time', ['timemodule.c'], + exts.append( Extension('time', ['timemodule.c', '_time.c'], libraries=math_libs) ) - exts.append( Extension('datetime', ['datetimemodule.c', 'timemodule.c'], + exts.append( Extension('datetime', ['datetimemodule.c', '_time.c'], libraries=math_libs) ) # fast iterator tools implemented in C exts.append( Extension("itertools", ["itertoolsmodule.c"]) ) @@ -862,6 +862,7 @@ else: if os.path.isdir(dn): tmp.append(dn) + db_dirs_to_check = tmp db_dirs_to_check = tmp From python-checkins at python.org Tue Jul 6 20:31:05 2010 From: python-checkins at python.org (alexander.belopolsky) Date: Tue, 6 Jul 2010 20:31:05 +0200 (CEST) Subject: [Python-checkins] r82613 - python/branches/release31-maint Message-ID: <20100706183105.D5C6D126452@mail.python.org> Author: alexander.belopolsky Date: Tue Jul 6 20:31:05 2010 New Revision: 82613 Log: Blocked revisions 82514 via svnmerge ........ r82514 | alexander.belopolsky | 2010-07-03 16:35:53 -0400 (Sat, 03 Jul 2010) | 3 lines Issue #9094: Make python -m pickletools disassemble pickles given in the command line. ........ Modified: python/branches/release31-maint/ (props changed) From python-checkins at python.org Tue Jul 6 20:52:42 2010 From: python-checkins at python.org (mark.dickinson) Date: Tue, 6 Jul 2010 20:52:42 +0200 (CEST) Subject: [Python-checkins] r82614 - in python/branches/py3k-dtoa: Lib/test/test_float.py Objects/floatobject.c configure configure.in pyconfig.h.in Message-ID: <20100706185242.4A6C612646F@mail.python.org> Author: mark.dickinson Date: Tue Jul 6 20:52:42 2010 New Revision: 82614 Log: Add float.__setround__ and float.__getround__ for rounding mode control (for test purposes only). Modified: python/branches/py3k-dtoa/Lib/test/test_float.py python/branches/py3k-dtoa/Objects/floatobject.c python/branches/py3k-dtoa/configure python/branches/py3k-dtoa/configure.in python/branches/py3k-dtoa/pyconfig.h.in Modified: python/branches/py3k-dtoa/Lib/test/test_float.py ============================================================================== --- python/branches/py3k-dtoa/Lib/test/test_float.py (original) +++ python/branches/py3k-dtoa/Lib/test/test_float.py Tue Jul 6 20:52:42 2010 @@ -16,6 +16,11 @@ "requires __getformat__") requires_setformat = unittest.skipUnless(hasattr(float, "__setformat__"), "requires __setformat__") + +have_setround = hasattr(float, "__setround__") +requires_setround = unittest.skipUnless(have_setround, + "requires __setround__") + # decorator for skipping tests on non-IEEE 754 platforms requires_IEEE_754 = unittest.skipUnless(have_getformat and float.__getformat__("double").startswith("IEEE"), @@ -382,6 +387,17 @@ #self.assertTrue(0.0 > pow_op(-2.0, -1047) > -1e-315) + at requires_setround +class RoundingModeTestCase(unittest.TestCase): + def test_roundtrip(self): + # just check that we can use __setround__ and __getround__ + # to set and get rounding mode + modes = "tonearest", "upward", "downward", "towardzero" + for mode in modes: + float.__setround__(mode) + self.assertEqual(float.__getround__(), mode) + + @requires_setformat class FormatFunctionsTestCase(unittest.TestCase): @@ -1264,6 +1280,7 @@ RoundTestCase, InfNanTest, HexFloatTestCase, + RoundingModeTestCase, ) if __name__ == '__main__': Modified: python/branches/py3k-dtoa/Objects/floatobject.c ============================================================================== --- python/branches/py3k-dtoa/Objects/floatobject.c (original) +++ python/branches/py3k-dtoa/Objects/floatobject.c Tue Jul 6 20:52:42 2010 @@ -9,6 +9,10 @@ #include #include +#if defined(HAVE_FESETROUND) && defined(HAVE_FEGETROUND) && \ + defined(HAVE_FENV_H) +#include +#endif #undef MAX #undef MIN @@ -1745,6 +1749,77 @@ "Overrides the automatic determination of C-level floating point type.\n" "This affects how floats are converted to and from binary strings."); +#if defined(HAVE_FESETROUND) && defined(HAVE_FEGETROUND) && \ + defined(HAVE_FENV_H) + +static PyObject * +float_setround(PyTypeObject *v, PyObject* arg) +{ + int mode, result; + + if (!PyUnicode_Check(arg)) { + PyErr_SetString(PyExc_TypeError, + "mode should be a string"); + return NULL; + } + + if (!PyUnicode_CompareWithASCIIString(arg, "tonearest")) + mode = FE_TONEAREST; + else if (!PyUnicode_CompareWithASCIIString(arg, "downward")) + mode = FE_DOWNWARD; + else if (!PyUnicode_CompareWithASCIIString(arg, "upward")) + mode = FE_UPWARD; + else if (!PyUnicode_CompareWithASCIIString(arg, "towardzero")) + mode = FE_TOWARDZERO; + else { + PyErr_SetString(PyExc_ValueError, + "mode should be one of 'tonearest', 'downward', " + "'upward', or 'towardzero'"); + return NULL; + } + result = fesetround(mode); + if (result) { + PyErr_SetString(PyExc_RuntimeError, + "Failed to set rounding mode"); + return NULL; + } + Py_RETURN_NONE; +} + +PyDoc_STRVAR(float_setround_doc, +"float.__setround__(mode) -> None\n" +"\n" +"You probably don't want to use this function. It exists mainly to be\n" +"used in Python's test suite.\n"); + +static PyObject * +float_getround(PyTypeObject *v) +{ + int i; + i = fegetround(); + + switch(i) { + case FE_TONEAREST: + return PyUnicode_FromString("tonearest"); + case FE_DOWNWARD: + return PyUnicode_FromString("downward"); + case FE_UPWARD: + return PyUnicode_FromString("upward"); + case FE_TOWARDZERO: + return PyUnicode_FromString("towardzero"); + default: + return PyUnicode_FromString("unknown"); + } +} + +PyDoc_STRVAR(float_getround_doc, +"float.__getround__() -> str\n" +"\n" +"You probably don't want to use this function. It exists mainly to be\n" +"used in Python's test suite.\n"); + +#endif /* defined(HAVE_FESETROUND) && defined(HAVE_FEGETROUND) && ... */ + static PyObject * float_getzero(PyObject *v, void *closure) { @@ -1798,6 +1873,13 @@ METH_O|METH_CLASS, float_getformat_doc}, {"__setformat__", (PyCFunction)float_setformat, METH_VARARGS|METH_CLASS, float_setformat_doc}, +#if defined(HAVE_FESETROUND) && defined(HAVE_FEGETROUND) && \ + defined(HAVE_FENV_H) + {"__setround__", (PyCFunction)float_setround, + METH_O|METH_CLASS, float_setround_doc}, + {"__getround__", (PyCFunction)float_getround, + METH_NOARGS|METH_CLASS, float_getround_doc}, +#endif {"__format__", (PyCFunction)float__format__, METH_VARARGS, float__format__doc}, {NULL, NULL} /* sentinel */ Modified: python/branches/py3k-dtoa/configure ============================================================================== --- python/branches/py3k-dtoa/configure (original) +++ python/branches/py3k-dtoa/configure Tue Jul 6 20:52:42 2010 @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.in Revision: 82090 . +# From configure.in Revision: 81583 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.65 for python 3.2. # @@ -1929,11 +1929,11 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default + enum { N = $2 / 2 - 1 }; int main () { -static int test_array [1 - 2 * !(enum { N = $2 / 2 - 1 }; - 0 < ($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 1))]; +static int test_array [1 - 2 * !(0 < ($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 1))]; test_array [0] = 0 ; @@ -1944,11 +1944,11 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default + enum { N = $2 / 2 - 1 }; int main () { -static int test_array [1 - 2 * !(enum { N = $2 / 2 - 1 }; - ($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 1) +static int test_array [1 - 2 * !(($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 1) < ($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 2))]; test_array [0] = 0 @@ -5995,7 +5995,7 @@ fi for ac_header in asm/types.h conio.h curses.h direct.h dlfcn.h errno.h \ -fcntl.h grp.h \ +fcntl.h fenv.h grp.h \ ieeefp.h io.h langinfo.h libintl.h ncurses.h poll.h process.h pthread.h \ shadow.h signal.h stdint.h stropts.h termios.h thread.h \ unistd.h utime.h \ @@ -11818,6 +11818,19 @@ fi done +for ac_func in fesetround fegetround +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +eval as_val=\$$as_ac_var + if test "x$as_val" = x""yes; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + ac_fn_c_check_decl "$LINENO" "isinf" "ac_cv_have_decl_isinf" "#include " if test "x$ac_cv_have_decl_isinf" = x""yes; then : Modified: python/branches/py3k-dtoa/configure.in ============================================================================== --- python/branches/py3k-dtoa/configure.in (original) +++ python/branches/py3k-dtoa/configure.in Tue Jul 6 20:52:42 2010 @@ -1299,7 +1299,7 @@ # checks for header files AC_HEADER_STDC AC_CHECK_HEADERS(asm/types.h conio.h curses.h direct.h dlfcn.h errno.h \ -fcntl.h grp.h \ +fcntl.h fenv.h grp.h \ ieeefp.h io.h langinfo.h libintl.h ncurses.h poll.h process.h pthread.h \ shadow.h signal.h stdint.h stropts.h termios.h thread.h \ unistd.h utime.h \ @@ -3433,6 +3433,7 @@ AC_CHECK_FUNCS([acosh asinh atanh copysign erf erfc expm1 finite gamma]) AC_CHECK_FUNCS([hypot lgamma log1p round tgamma]) +AC_CHECK_FUNCS([fesetround fegetround]) AC_CHECK_DECLS([isinf, isnan, isfinite], [], [], [[#include ]]) LIBS=$LIBS_SAVE Modified: python/branches/py3k-dtoa/pyconfig.h.in ============================================================================== --- python/branches/py3k-dtoa/pyconfig.h.in (original) +++ python/branches/py3k-dtoa/pyconfig.h.in Tue Jul 6 20:52:42 2010 @@ -208,6 +208,15 @@ /* Define if you have the 'fdatasync' function. */ #undef HAVE_FDATASYNC +/* Define to 1 if you have the `fegetround' function. */ +#undef HAVE_FEGETROUND + +/* Define to 1 if you have the header file. */ +#undef HAVE_FENV_H + +/* Define to 1 if you have the `fesetround' function. */ +#undef HAVE_FESETROUND + /* Define to 1 if you have the `finite' function. */ #undef HAVE_FINITE From python-checkins at python.org Wed Jul 7 00:58:50 2010 From: python-checkins at python.org (georg.brandl) Date: Wed, 7 Jul 2010 00:58:50 +0200 (CEST) Subject: [Python-checkins] r82615 - python/branches/py3k/Doc/using/cmdline.rst Message-ID: <20100706225850.71E8EEEA86@mail.python.org> Author: georg.brandl Date: Wed Jul 7 00:58:50 2010 New Revision: 82615 Log: Fix typo. Modified: python/branches/py3k/Doc/using/cmdline.rst Modified: python/branches/py3k/Doc/using/cmdline.rst ============================================================================== --- python/branches/py3k/Doc/using/cmdline.rst (original) +++ python/branches/py3k/Doc/using/cmdline.rst Wed Jul 7 00:58:50 2010 @@ -61,7 +61,7 @@ .. cmdoption:: -c - Execute the Python code in *command*. *command* can be one ore more + Execute the Python code in *command*. *command* can be one or more statements separated by newlines, with significant leading whitespace as in normal module code. From python-checkins at python.org Wed Jul 7 01:18:01 2010 From: python-checkins at python.org (alexander.belopolsky) Date: Wed, 7 Jul 2010 01:18:01 +0200 (CEST) Subject: [Python-checkins] r82616 - in sandbox/branches/py3k-datetime: datetime.py test_datetime.py Message-ID: <20100706231801.CBAA8EEA22@mail.python.org> Author: alexander.belopolsky Date: Wed Jul 7 01:18:01 2010 New Revision: 82616 Log: Issue #9000: datetime.timezone objects now have eval-friendly repr. Modified: sandbox/branches/py3k-datetime/datetime.py sandbox/branches/py3k-datetime/test_datetime.py Modified: sandbox/branches/py3k-datetime/datetime.py ============================================================================== --- sandbox/branches/py3k-datetime/datetime.py (original) +++ sandbox/branches/py3k-datetime/datetime.py Wed Jul 7 01:18:01 2010 @@ -705,7 +705,16 @@ # Conversions to string def __repr__(self): - "Convert to formal string, for repr()." + """Convert to formal string, for repr(). + + >>> dt = datetime(2010, 1, 1) + >>> repr(dt) + 'datetime.datetime(2010, 1, 1, 0, 0)' + + >>> dt = datetime(2010, 1, 1, tzinfo=timezone.utc) + >>> repr(dt) + 'datetime.datetime(2010, 1, 1, 0, 0, tzinfo=datetime.timezone.utc)' + """ return "%s(%d, %d, %d)" % ('datetime.' + self.__class__.__name__, self._year, self._month, @@ -1524,7 +1533,7 @@ return s def __repr__(self): - "Convert to formal string, for repr()." + """Convert to formal string, for repr().""" L = [self._year, self._month, self._day, # These are never zero self._hour, self._minute, self._second, self._microsecond] if L[-1] == 0: @@ -1813,6 +1822,24 @@ def __hash__(self): return hash(self._offset) + def __repr__(self): + """Convert to formal string, for repr(). + + >>> tz = timezone.utc + >>> repr(tz) + 'datetime.timezone.utc' + >>> tz = timezone(timedelta(hours=-5), 'EST') + >>> repr(tz) + "datetime.timezone(datetime.timedelta(-1, 68400), 'EST')" + """ + if self is self.utc: + return 'datetime.timezone.utc' + if self._name is None: + return "%s(%r)" % ('datetime.' + self.__class__.__name__, + self._offset) + return "%s(%r, %r)" % ('datetime.' + self.__class__.__name__, + self._offset, self._name) + def __str__(self): return self.tzname(None) Modified: sandbox/branches/py3k-datetime/test_datetime.py ============================================================================== --- sandbox/branches/py3k-datetime/test_datetime.py (original) +++ sandbox/branches/py3k-datetime/test_datetime.py Wed Jul 7 01:18:01 2010 @@ -153,6 +153,15 @@ timezone.min, timezone.max]: self.assertEqual(str(tz), tz.tzname(None)) + def test_repr(self): + import datetime + for tz in [self.ACDT, self.EST, timezone.utc, + timezone.min, timezone.max]: + # test round-trip + tzrep = repr(tz) + self.assertEqual(tz, eval(tzrep)) + + def test_class_members(self): limit = timedelta(hours=23, minutes=59) self.assertEqual(timezone.utc.utcoffset(None), ZERO) From python-checkins at python.org Wed Jul 7 01:19:45 2010 From: python-checkins at python.org (alexander.belopolsky) Date: Wed, 7 Jul 2010 01:19:45 +0200 (CEST) Subject: [Python-checkins] r82617 - in python/branches/py3k: Lib/test/test_datetime.py Misc/NEWS Modules/datetimemodule.c Message-ID: <20100706231945.A96EAEEA90@mail.python.org> Author: alexander.belopolsky Date: Wed Jul 7 01:19:45 2010 New Revision: 82617 Log: Issue #9000: datetime.timezone objects now have eval-friendly repr. Modified: python/branches/py3k/Lib/test/test_datetime.py python/branches/py3k/Misc/NEWS python/branches/py3k/Modules/datetimemodule.c Modified: python/branches/py3k/Lib/test/test_datetime.py ============================================================================== --- python/branches/py3k/Lib/test/test_datetime.py (original) +++ python/branches/py3k/Lib/test/test_datetime.py Wed Jul 7 01:19:45 2010 @@ -153,6 +153,15 @@ timezone.min, timezone.max]: self.assertEqual(str(tz), tz.tzname(None)) + def test_repr(self): + import datetime + for tz in [self.ACDT, self.EST, timezone.utc, + timezone.min, timezone.max]: + # test round-trip + tzrep = repr(tz) + self.assertEqual(tz, eval(tzrep)) + + def test_class_members(self): limit = timedelta(hours=23, minutes=59) self.assertEqual(timezone.utc.utcoffset(None), ZERO) Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Wed Jul 7 01:19:45 2010 @@ -1394,6 +1394,8 @@ Extension Modules ----------------- +- Issue #9000: datetime.timezone objects now have eval-friendly repr. + - In the math module, correctly lookup __trunc__, __ceil__, and __floor__ as special methods. Modified: python/branches/py3k/Modules/datetimemodule.c ============================================================================== --- python/branches/py3k/Modules/datetimemodule.c (original) +++ python/branches/py3k/Modules/datetimemodule.c Wed Jul 7 01:19:45 2010 @@ -780,6 +780,8 @@ PyObject *name; } PyDateTime_TimeZone; +PyObject *PyDateTime_TimeZone_UTC; + /* Create new timezone instance checking offset range. This function does not check the name argument. Caller must assure that offset is a timedelta instance and name is either NULL @@ -3380,6 +3382,24 @@ } static PyObject * +timezone_repr(PyDateTime_TimeZone *self) +{ + /* Note that although timezone is not subclassable, it is convenient + to use Py_TYPE(self)->tp_name here. */ + const char *type_name = Py_TYPE(self)->tp_name; + + if (((PyObject *)self) == PyDateTime_TimeZone_UTC) + return PyUnicode_FromFormat("%s.utc", type_name); + + if (self->name == NULL) + return PyUnicode_FromFormat("%s(%R)", type_name, self->offset); + + return PyUnicode_FromFormat("%s(%R, %R)", type_name, self->offset, + self->name); +} + + +static PyObject * timezone_str(PyDateTime_TimeZone *self) { char buf[10]; @@ -3505,7 +3525,7 @@ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_reserved */ - 0, /* tp_repr */ + (reprfunc)timezone_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ @@ -5260,7 +5280,7 @@ Py_DECREF(delta); if (x == NULL || PyDict_SetItemString(d, "utc", x) < 0) return NULL; - Py_DECREF(x); + PyDateTime_TimeZone_UTC = x; delta = new_delta(-1, 60, 0, 1); /* -23:59 */ if (delta == NULL) From solipsis at pitrou.net Wed Jul 7 01:23:58 2010 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Wed, 7 Jul 2010 01:23:58 +0200 (CEST) Subject: [Python-checkins] Daily py3k reference leaks (r82610): sum=0 Message-ID: <20100706232358.3C4571770A@ns6635.ovh.net> py3k results for svn r82610 (hg cset c1eeefdcb39b) -------------------------------------------------- Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/py3k/refleaks/reflognbauQS', '-x'] From python-checkins at python.org Wed Jul 7 01:26:35 2010 From: python-checkins at python.org (alexander.belopolsky) Date: Wed, 7 Jul 2010 01:26:35 +0200 (CEST) Subject: [Python-checkins] r82618 - python/branches/release31-maint Message-ID: <20100706232635.9643DC9C1@mail.python.org> Author: alexander.belopolsky Date: Wed Jul 7 01:26:35 2010 New Revision: 82618 Log: Blocked revisions 82617 via svnmerge ........ r82617 | alexander.belopolsky | 2010-07-06 19:19:45 -0400 (Tue, 06 Jul 2010) | 1 line Issue #9000: datetime.timezone objects now have eval-friendly repr. ........ Modified: python/branches/release31-maint/ (props changed) From python-checkins at python.org Wed Jul 7 01:44:27 2010 From: python-checkins at python.org (alexander.belopolsky) Date: Wed, 7 Jul 2010 01:44:27 +0200 (CEST) Subject: [Python-checkins] r82619 - sandbox/branches/py3k-datetime/datetime.py Message-ID: <20100706234427.09F3FEEA01@mail.python.org> Author: alexander.belopolsky Date: Wed Jul 7 01:44:26 2010 New Revision: 82619 Log: Use custom sentinel instead of varargs in timezone() Modified: sandbox/branches/py3k-datetime/datetime.py Modified: sandbox/branches/py3k-datetime/datetime.py ============================================================================== --- sandbox/branches/py3k-datetime/datetime.py (original) +++ sandbox/branches/py3k-datetime/datetime.py Wed Jul 7 01:44:26 2010 @@ -1784,18 +1784,13 @@ class timezone(tzinfo): __slots__ = '_offset', '_name' - def __init__(self, offset, *args): - # Reproduce C behavior - n = len(args) - if n > 1: - raise TypeError("timezone() takes at most 2 arguments (%d given)" - % n) - if n == 0: + # Sentinel value to disallow None + _NoneGiven = object() + def __init__(self, offset, name=_NoneGiven): + if name is self._NoneGiven: name = None - else: - name = args[0] - if not isinstance(name, str): - raise TypeError("name must be a string") + elif not isinstance(name, str): + raise TypeError("name must be a string") if isinstance(offset, timedelta): if self._minoffset <= offset <= self._maxoffset: if (offset.microseconds != 0 or From python-checkins at python.org Wed Jul 7 13:03:50 2010 From: python-checkins at python.org (matthias.klose) Date: Wed, 7 Jul 2010 13:03:50 +0200 (CEST) Subject: [Python-checkins] r82620 - python/branches/release27-maint/Doc/whatsnew/2.7.rst Message-ID: <20100707110350.A73D8EE9C4@mail.python.org> Author: matthias.klose Date: Wed Jul 7 13:03:50 2010 New Revision: 82620 Log: Remove whatsnew item about --with-computed-gotos. Modified: python/branches/release27-maint/Doc/whatsnew/2.7.rst Modified: python/branches/release27-maint/Doc/whatsnew/2.7.rst ============================================================================== --- python/branches/release27-maint/Doc/whatsnew/2.7.rst (original) +++ python/branches/release27-maint/Doc/whatsnew/2.7.rst Wed Jul 7 13:03:50 2010 @@ -868,12 +868,6 @@ Several performance enhancements have been added: -.. * A new :program:`configure` option, :option:`--with-computed-gotos`, - compiles the main bytecode interpreter loop using a new dispatch - mechanism that gives speedups of up to 20%, depending on the system - and benchmark. The new mechanism is only supported on certain - compilers, such as gcc, SunPro, and icc. - * A new opcode was added to perform the initial setup for :keyword:`with` statements, looking up the :meth:`__enter__` and :meth:`__exit__` methods. (Contributed by Benjamin Peterson.) From python-checkins at python.org Wed Jul 7 13:06:57 2010 From: python-checkins at python.org (matthias.klose) Date: Wed, 7 Jul 2010 13:06:57 +0200 (CEST) Subject: [Python-checkins] r82621 - python/branches/release31-maint/Doc/whatsnew/2.7.rst Message-ID: <20100707110657.E1EBDEEA6A@mail.python.org> Author: matthias.klose Date: Wed Jul 7 13:06:57 2010 New Revision: 82621 Log: Remove whatsnew 2.7 item about --with-computed-gotos. Modified: python/branches/release31-maint/Doc/whatsnew/2.7.rst Modified: python/branches/release31-maint/Doc/whatsnew/2.7.rst ============================================================================== --- python/branches/release31-maint/Doc/whatsnew/2.7.rst (original) +++ python/branches/release31-maint/Doc/whatsnew/2.7.rst Wed Jul 7 13:06:57 2010 @@ -158,12 +158,6 @@ Several performance enhancements have been added: -.. * A new :program:`configure` option, :option:`--with-computed-gotos`, - compiles the main bytecode interpreter loop using a new dispatch - mechanism that gives speedups of up to 20%, depending on the system - and benchmark. The new mechanism is only supported on certain - compilers, such as gcc, SunPro, and icc. - * The garbage collector now performs better when many objects are being allocated without deallocating any. A full garbage collection pass is only performed when the middle generation has been collected From ncoghlan at gmail.com Wed Jul 7 15:46:06 2010 From: ncoghlan at gmail.com (Nick Coghlan) Date: Wed, 7 Jul 2010 23:46:06 +1000 Subject: [Python-checkins] r82619 - sandbox/branches/py3k-datetime/datetime.py In-Reply-To: <20100706234427.09F3FEEA01@mail.python.org> References: <20100706234427.09F3FEEA01@mail.python.org> Message-ID: On Wed, Jul 7, 2010 at 9:44 AM, alexander.belopolsky wrote: > + ? ?# Sentinel value to disallow None > + ? ?_NoneGiven = object() > + ? ?def __init__(self, offset, name=_NoneGiven): > + ? ? ? ?if name is self._NoneGiven: > ? ? ? ? ? ? name = None I suggest calling your sentinel value here something more like "_NothingGiven", "_NotSupplied" or "_Omitted". The current name sounds like it is meant to mean "None was given", when that is clearly not the case. Cheers, Nick. -- Nick Coghlan | ncoghlan at gmail.com | Brisbane, Australia From python-checkins at python.org Wed Jul 7 16:18:42 2010 From: python-checkins at python.org (alexander.belopolsky) Date: Wed, 7 Jul 2010 16:18:42 +0200 (CEST) Subject: [Python-checkins] r82622 - sandbox/branches/py3k-datetime/datetime.py Message-ID: <20100707141842.57C4DEE98A@mail.python.org> Author: alexander.belopolsky Date: Wed Jul 7 16:18:42 2010 New Revision: 82622 Log: Renamed the sentinel from _NoneGiven to _Omitted. Thanks Nick Coghlan. Modified: sandbox/branches/py3k-datetime/datetime.py Modified: sandbox/branches/py3k-datetime/datetime.py ============================================================================== --- sandbox/branches/py3k-datetime/datetime.py (original) +++ sandbox/branches/py3k-datetime/datetime.py Wed Jul 7 16:18:42 2010 @@ -1785,9 +1785,9 @@ __slots__ = '_offset', '_name' # Sentinel value to disallow None - _NoneGiven = object() - def __init__(self, offset, name=_NoneGiven): - if name is self._NoneGiven: + _Omitted = object() + def __init__(self, offset, name=_Omitted): + if name is self._Omitted: name = None elif not isinstance(name, str): raise TypeError("name must be a string") From python-checkins at python.org Wed Jul 7 17:51:17 2010 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 7 Jul 2010 17:51:17 +0200 (CEST) Subject: [Python-checkins] r82623 - python/branches/release27-maint/Lib/test/test_math.py Message-ID: <20100707155117.D5417EEB03@mail.python.org> Author: benjamin.peterson Date: Wed Jul 7 17:51:17 2010 New Revision: 82623 Log: these tests are the result of cpython's incorrect implementation Modified: python/branches/release27-maint/Lib/test/test_math.py Modified: python/branches/release27-maint/Lib/test/test_math.py ============================================================================== --- python/branches/release27-maint/Lib/test/test_math.py (original) +++ python/branches/release27-maint/Lib/test/test_math.py Wed Jul 7 17:51:17 2010 @@ -879,11 +879,6 @@ self.assertRaises((AttributeError, TypeError), math.trunc, TestNoTrunc()) - t = TestNoTrunc() - t.__trunc__ = lambda *args: args - self.assertEquals((), math.trunc(t)) - self.assertRaises(TypeError, math.trunc, t, 0) - def testIsnan(self): self.assertTrue(math.isnan(float("nan"))) self.assertTrue(math.isnan(float("inf")* 0.)) From python-checkins at python.org Wed Jul 7 18:10:44 2010 From: python-checkins at python.org (mark.dickinson) Date: Wed, 7 Jul 2010 18:10:44 +0200 (CEST) Subject: [Python-checkins] r82624 - python/branches/py3k/Grammar/Grammar Message-ID: <20100707161044.AD7FEEEAF6@mail.python.org> Author: mark.dickinson Date: Wed Jul 7 18:10:44 2010 New Revision: 82624 Log: Kill gratuitous space. Modified: python/branches/py3k/Grammar/Grammar Modified: python/branches/py3k/Grammar/Grammar ============================================================================== --- python/branches/py3k/Grammar/Grammar (original) +++ python/branches/py3k/Grammar/Grammar Wed Jul 7 18:10:44 2010 @@ -29,7 +29,7 @@ | tfpdef ['=' test] (',' tfpdef ['=' test])* [',']) tfpdef: NAME [':' test] varargslist: ((vfpdef ['=' test] ',')* - ('*' [vfpdef] (',' vfpdef ['=' test])* [',' '**' vfpdef] | '**' vfpdef) + ('*' [vfpdef] (',' vfpdef ['=' test])* [',' '**' vfpdef] | '**' vfpdef) | vfpdef ['=' test] (',' vfpdef ['=' test])* [',']) vfpdef: NAME From python-checkins at python.org Wed Jul 7 18:17:31 2010 From: python-checkins at python.org (mark.dickinson) Date: Wed, 7 Jul 2010 18:17:31 +0200 (CEST) Subject: [Python-checkins] r82625 - python/branches/py3k/Modules/mathmodule.c Message-ID: <20100707161731.65B33EEB0F@mail.python.org> Author: mark.dickinson Date: Wed Jul 7 18:17:31 2010 New Revision: 82625 Log: Minor refactoring in lgamma code, for clarity. Modified: python/branches/py3k/Modules/mathmodule.c Modified: python/branches/py3k/Modules/mathmodule.c ============================================================================== --- python/branches/py3k/Modules/mathmodule.c (original) +++ python/branches/py3k/Modules/mathmodule.c Wed Jul 7 18:17:31 2010 @@ -69,6 +69,7 @@ static const double pi = 3.141592653589793238462643383279502884197; static const double sqrtpi = 1.772453850905516027298167483341145182798; +static const double logpi = 1.144729885849400174143427351353058711647; static double sinpi(double x) @@ -356,20 +357,15 @@ if (absx < 1e-20) return -log(absx); - /* Lanczos' formula */ - if (x > 0.0) { - /* we could save a fraction of a ulp in accuracy by having a - second set of numerator coefficients for lanczos_sum that - absorbed the exp(-lanczos_g) term, and throwing out the - lanczos_g subtraction below; it's probably not worth it. */ - r = log(lanczos_sum(x)) - lanczos_g + - (x-0.5)*(log(x+lanczos_g-0.5)-1); - } - else { - r = log(pi) - log(fabs(sinpi(absx))) - log(absx) - - (log(lanczos_sum(absx)) - lanczos_g + - (absx-0.5)*(log(absx+lanczos_g-0.5)-1)); - } + /* Lanczos' formula. We could save a fraction of a ulp in accuracy by + having a second set of numerator coefficients for lanczos_sum that + absorbed the exp(-lanczos_g) term, and throwing out the lanczos_g + subtraction below; it's probably not worth it. */ + r = log(lanczos_sum(absx)) - lanczos_g; + r += (absx - 0.5) * (log(absx + lanczos_g - 0.5) - 1); + if (x < 0.0) + /* Use reflection formula to get value for negative x. */ + r = logpi - log(fabs(sinpi(absx))) - log(absx) - r; if (Py_IS_INFINITY(r)) errno = ERANGE; return r; From python-checkins at python.org Wed Jul 7 18:21:29 2010 From: python-checkins at python.org (mark.dickinson) Date: Wed, 7 Jul 2010 18:21:29 +0200 (CEST) Subject: [Python-checkins] r82626 - in python/branches/py3k: Lib/test/math_testcases.txt Lib/test/test_math.py Misc/NEWS Modules/mathmodule.c Message-ID: <20100707162129.96D7EEE993@mail.python.org> Author: mark.dickinson Date: Wed Jul 7 18:21:29 2010 New Revision: 82626 Log: Issue #9186: log1p(-1.0) should raise ValueError, not OverflowError. Modified: python/branches/py3k/Lib/test/math_testcases.txt python/branches/py3k/Lib/test/test_math.py python/branches/py3k/Misc/NEWS python/branches/py3k/Modules/mathmodule.c Modified: python/branches/py3k/Lib/test/math_testcases.txt ============================================================================== --- python/branches/py3k/Lib/test/math_testcases.txt (original) +++ python/branches/py3k/Lib/test/math_testcases.txt Wed Jul 7 18:21:29 2010 @@ -371,6 +371,78 @@ ----------------------------------------------------------- +-- log1p: log(1 + x), without precision loss for small x -- +----------------------------------------------------------- + +-- special values +log1p0000 log1p 0.0 -> 0.0 +log1p0001 log1p -0.0 -> -0.0 +log1p0002 log1p inf -> inf +log1p0003 log1p -inf -> nan invalid +log1p0004 log1p nan -> nan + +-- singularity at -1.0 +log1p0010 log1p -1.0 -> -inf divide-by-zero +log1p0011 log1p -0.9999999999999999 -> -36.736800569677101 + +-- finite values < 1.0 are invalid +log1p0020 log1p -1.0000000000000002 -> nan invalid +log1p0021 log1p -1.1 -> nan invalid +log1p0022 log1p -2.0 -> nan invalid +log1p0023 log1p -1e300 -> nan invalid + +-- tiny x: log1p(x) ~ x +log1p0110 log1p 5e-324 -> 5e-324 +log1p0111 log1p 1e-320 -> 1e-320 +log1p0112 log1p 1e-300 -> 1e-300 +log1p0113 log1p 1e-150 -> 1e-150 +log1p0114 log1p 1e-20 -> 1e-20 + +log1p0120 log1p -5e-324 -> -5e-324 +log1p0121 log1p -1e-320 -> -1e-320 +log1p0122 log1p -1e-300 -> -1e-300 +log1p0123 log1p -1e-150 -> -1e-150 +log1p0124 log1p -1e-20 -> -1e-20 + +-- some (mostly) random small and moderate-sized values +log1p0200 log1p -0.89156889782277482 -> -2.2216403106762863 +log1p0201 log1p -0.23858496047770464 -> -0.27257668276980057 +log1p0202 log1p -0.011641726191307515 -> -0.011710021654495657 +log1p0203 log1p -0.0090126398571693817 -> -0.0090534993825007650 +log1p0204 log1p -0.00023442805985712781 -> -0.00023445554240995693 +log1p0205 log1p -1.5672870980936349e-5 -> -1.5672993801662046e-5 +log1p0206 log1p -7.9650013274825295e-6 -> -7.9650330482740401e-6 +log1p0207 log1p -2.5202948343227410e-7 -> -2.5202951519170971e-7 +log1p0208 log1p -8.2446372820745855e-11 -> -8.2446372824144559e-11 +log1p0209 log1p -8.1663670046490789e-12 -> -8.1663670046824230e-12 +log1p0210 log1p 7.0351735084656292e-18 -> 7.0351735084656292e-18 +log1p0211 log1p 5.2732161907375226e-12 -> 5.2732161907236188e-12 +log1p0212 log1p 1.0000000000000000e-10 -> 9.9999999995000007e-11 +log1p0213 log1p 2.1401273266000197e-9 -> 2.1401273243099470e-9 +log1p0214 log1p 1.2668914653979560e-8 -> 1.2668914573728861e-8 +log1p0215 log1p 1.6250007816299069e-6 -> 1.6249994613175672e-6 +log1p0216 log1p 8.3740495645839399e-6 -> 8.3740145024266269e-6 +log1p0217 log1p 3.0000000000000001e-5 -> 2.9999550008999799e-5 +log1p0218 log1p 0.0070000000000000001 -> 0.0069756137364252423 +log1p0219 log1p 0.013026235315053002 -> 0.012942123564008787 +log1p0220 log1p 0.013497160797236184 -> 0.013406885521915038 +log1p0221 log1p 0.027625599078135284 -> 0.027250897463483054 +log1p0222 log1p 0.14179687245544870 -> 0.13260322540908789 + +-- large values +log1p0300 log1p 1.7976931348623157e+308 -> 709.78271289338397 +log1p0301 log1p 1.0000000000000001e+300 -> 690.77552789821368 +log1p0302 log1p 1.0000000000000001e+70 -> 161.18095650958321 +log1p0303 log1p 10000000000.000000 -> 23.025850930040455 + +-- other values transferred from testLog1p in test_math +log1p0400 log1p -0.63212055882855767 -> -1.0000000000000000 +log1p0401 log1p 1.7182818284590451 -> 1.0000000000000000 +log1p0402 log1p 1.0000000000000000 -> 0.69314718055994529 +log1p0403 log1p 1.2379400392853803e+27 -> 62.383246250395075 + + +----------------------------------------------------------- -- expm1: exp(x) - 1, without precision loss for small x -- ----------------------------------------------------------- Modified: python/branches/py3k/Lib/test/test_math.py ============================================================================== --- python/branches/py3k/Lib/test/test_math.py (original) +++ python/branches/py3k/Lib/test/test_math.py Wed Jul 7 18:21:29 2010 @@ -647,15 +647,7 @@ def testLog1p(self): self.assertRaises(TypeError, math.log1p) - self.ftest('log1p(1/e -1)', math.log1p(1/math.e-1), -1) - self.ftest('log1p(0)', math.log1p(0), 0) - self.ftest('log1p(e-1)', math.log1p(math.e-1), 1) - self.ftest('log1p(1)', math.log1p(1), math.log(2)) - self.assertEquals(math.log1p(INF), INF) - self.assertRaises(ValueError, math.log1p, NINF) - self.assertTrue(math.isnan(math.log1p(NAN))) n= 2**90 - self.assertAlmostEquals(math.log1p(n), 62.383246250395075) self.assertAlmostEquals(math.log1p(n), math.log1p(float(n))) def testLog10(self): Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Wed Jul 7 18:21:29 2010 @@ -468,6 +468,8 @@ Library ------- +- Issue #9186: Fix math.log1p(-1.0) to raise ValueError, not OverflowError. + - Issue #9130: Fix validation of relative imports in parser module. - Issue #9128: Fix validation of class decorators in parser module. Modified: python/branches/py3k/Modules/mathmodule.c ============================================================================== --- python/branches/py3k/Modules/mathmodule.c (original) +++ python/branches/py3k/Modules/mathmodule.c Wed Jul 7 18:21:29 2010 @@ -896,7 +896,7 @@ "gamma(x)\n\nGamma function at x.") FUNC1A(lgamma, m_lgamma, "lgamma(x)\n\nNatural logarithm of absolute value of Gamma function at x.") -FUNC1(log1p, m_log1p, 1, +FUNC1(log1p, m_log1p, 0, "log1p(x)\n\nReturn the natural logarithm of 1+x (base e).\n" "The result is computed in a way which is accurate for x near zero.") FUNC1(sin, sin, 0, From python-checkins at python.org Wed Jul 7 19:59:55 2010 From: python-checkins at python.org (alexander.belopolsky) Date: Wed, 7 Jul 2010 19:59:55 +0200 (CEST) Subject: [Python-checkins] r82627 - sandbox/branches/py3k-datetime/datetime.py Message-ID: <20100707175955.7E101EE981@mail.python.org> Author: alexander.belopolsky Date: Wed Jul 7 19:59:55 2010 New Revision: 82627 Log: Whitespace cleanup Modified: sandbox/branches/py3k-datetime/datetime.py Modified: sandbox/branches/py3k-datetime/datetime.py ============================================================================== --- sandbox/branches/py3k-datetime/datetime.py (original) +++ sandbox/branches/py3k-datetime/datetime.py Wed Jul 7 19:59:55 2010 @@ -13,7 +13,7 @@ Sources for time zone and DST data: http://www.twinsun.com/tz/tz-link.htm This was originally copied from the sandbox of the CPython CVS repository. -Thanks to Tim Peters for suggesting using it. +Thanks to Tim Peters for suggesting using it. """ import time as _time @@ -457,7 +457,7 @@ def total_seconds(self): """Total seconds in the duration.""" - return ((self.days * 86400 + self.seconds)*10**6 + + return ((self.days * 86400 + self.seconds)*10**6 + self.microseconds) / 10**6 # Read-only field accessors @@ -564,7 +564,7 @@ other._to_microseconds()) return q, timedelta(0, 0, r) return NotImplemented - + # Comparisons of timedelta objects with other. def __eq__(self, other): @@ -1044,7 +1044,7 @@ return self._hour @property - def minute(self): + def minute(self): """minute (0-59)""" return self._minute @@ -1052,7 +1052,7 @@ def second(self): """second (0-59)""" return self._second - + @property def microsecond(self): """microsecond (0-999999)""" @@ -1332,7 +1332,7 @@ return self._hour @property - def minute(self): + def minute(self): """minute (0-59)""" return self._minute @@ -1340,7 +1340,7 @@ def second(self): """second (0-59)""" return self._second - + @property def microsecond(self): """microsecond (0-999999)""" @@ -1539,7 +1539,7 @@ if L[-1] == 0: del L[-1] if L[-1] == 0: - del L[-1] + del L[-1] s = ", ".join(map(str, L)) s = "%s(%s)" % ('datetime.' + self.__class__.__name__, s) if self._tzinfo is not None: @@ -1813,10 +1813,10 @@ def __eq__(self, other): return self._offset == other._offset - + def __hash__(self): return hash(self._offset) - + def __repr__(self): """Convert to formal string, for repr(). @@ -1857,7 +1857,7 @@ return None raise TypeError("dst() argument must be a datetime instance" " or None") - + def fromutc(self, dt): if isinstance(dt, datetime): if dt.tzinfo is not self: @@ -2082,4 +2082,3 @@ perverse time zone returns a negative dst()). So a breaking case must be pretty bizarre, and a tzinfo subclass can override fromutc() if it is. """ - From python-checkins at python.org Wed Jul 7 20:44:05 2010 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 7 Jul 2010 20:44:05 +0200 (CEST) Subject: [Python-checkins] r82628 - python/branches/py3k/Lib/test/test_struct.py Message-ID: <20100707184405.5FB81EEB10@mail.python.org> Author: benjamin.peterson Date: Wed Jul 7 20:44:05 2010 New Revision: 82628 Log: this needn't be in the loop Modified: python/branches/py3k/Lib/test/test_struct.py Modified: python/branches/py3k/Lib/test/test_struct.py ============================================================================== --- python/branches/py3k/Lib/test/test_struct.py (original) +++ python/branches/py3k/Lib/test/test_struct.py Wed Jul 7 20:44:05 2010 @@ -503,8 +503,8 @@ self.assertFalse(prefix, msg='encoded bool is not one byte: %r' %packed) - for c in [b'\x01', b'\x7f', b'\xff', b'\x0f', b'\xf0']: - self.assertTrue(struct.unpack('>?', c)[0]) + for c in [b'\x01', b'\x7f', b'\xff', b'\x0f', b'\xf0']: + self.assertTrue(struct.unpack('>?', c)[0]) def test_count_overflow(self): hugecount = '{}b'.format(sys.maxsize+1) From python-checkins at python.org Wed Jul 7 20:51:44 2010 From: python-checkins at python.org (georg.brandl) Date: Wed, 7 Jul 2010 20:51:44 +0200 (CEST) Subject: [Python-checkins] r82629 - python/branches/py3k/Doc/distutils/sourcedist.rst Message-ID: <20100707185144.21FA9EE9EA@mail.python.org> Author: georg.brandl Date: Wed Jul 7 20:51:43 2010 New Revision: 82629 Log: Make comment out of an awkward note. Modified: python/branches/py3k/Doc/distutils/sourcedist.rst Modified: python/branches/py3k/Doc/distutils/sourcedist.rst ============================================================================== --- python/branches/py3k/Doc/distutils/sourcedist.rst (original) +++ python/branches/py3k/Doc/distutils/sourcedist.rst Wed Jul 7 20:51:43 2010 @@ -76,10 +76,10 @@ :option:`packages` options * all C source files mentioned in the :option:`ext_modules` or - :option:`libraries` options ( + :option:`libraries` options - **\*\*** getting C library sources currently broken---no - :meth:`get_source_files` method in :file:`build_clib.py`! **\*\***) + .. XXX Getting C library sources is currently broken -- no + :meth:`get_source_files` method in :file:`build_clib.py`! * scripts identified by the :option:`scripts` option See :ref:`distutils-installing-scripts`. From python-checkins at python.org Wed Jul 7 20:54:59 2010 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 7 Jul 2010 20:54:59 +0200 (CEST) Subject: [Python-checkins] r82630 - in python/branches/py3k: Lib/test/test_struct.py Modules/_struct.c Message-ID: <20100707185459.B97A6EEAFE@mail.python.org> Author: benjamin.peterson Date: Wed Jul 7 20:54:59 2010 New Revision: 82630 Log: don't ignore exceptions from PyObject_IsTrue Modified: python/branches/py3k/Lib/test/test_struct.py python/branches/py3k/Modules/_struct.c Modified: python/branches/py3k/Lib/test/test_struct.py ============================================================================== --- python/branches/py3k/Lib/test/test_struct.py (original) +++ python/branches/py3k/Lib/test/test_struct.py Wed Jul 7 20:54:59 2010 @@ -475,6 +475,9 @@ self.assertEqual(value, 0x12345678) def test_bool(self): + class ExplodingBool(object): + def __bool__(self): + raise IOError for prefix in tuple("<>!=")+('',): false = (), [], [], '', 0 true = [1], 'test', 5, -1, 0xffffffff+1, 0xffffffff/2 @@ -503,6 +506,9 @@ self.assertFalse(prefix, msg='encoded bool is not one byte: %r' %packed) + self.assertRaises(IOError, struct.pack, prefix + '?', + ExplodingBool()) + for c in [b'\x01', b'\x7f', b'\xff', b'\x0f', b'\xf0']: self.assertTrue(struct.unpack('>?', c)[0]) Modified: python/branches/py3k/Modules/_struct.c ============================================================================== --- python/branches/py3k/Modules/_struct.c (original) +++ python/branches/py3k/Modules/_struct.c Wed Jul 7 20:54:59 2010 @@ -591,9 +591,13 @@ static int np_bool(char *p, PyObject *v, const formatdef *f) { - BOOL_TYPE y; + int y; + BOOL_TYPE x; y = PyObject_IsTrue(v); - memcpy(p, (char *)&y, sizeof y); + if (y < 0) + return -1; + x = y; + memcpy(p, (char *)&x, sizeof x); return 0; } @@ -865,6 +869,8 @@ { char y; y = PyObject_IsTrue(v); + if (y < 0) + return -1; memcpy(p, (char *)&y, sizeof y); return 0; } From python-checkins at python.org Wed Jul 7 21:03:36 2010 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 7 Jul 2010 21:03:36 +0200 (CEST) Subject: [Python-checkins] r82631 - in python/branches/release27-maint: Lib/test/test_struct.py Modules/_struct.c Message-ID: <20100707190336.8AC3FC988@mail.python.org> Author: benjamin.peterson Date: Wed Jul 7 21:03:36 2010 New Revision: 82631 Log: Merged revisions 82628,82630 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ........ r82628 | benjamin.peterson | 2010-07-07 13:44:05 -0500 (Wed, 07 Jul 2010) | 1 line this needn't be in the loop ........ r82630 | benjamin.peterson | 2010-07-07 13:54:59 -0500 (Wed, 07 Jul 2010) | 1 line don't ignore exceptions from PyObject_IsTrue ........ Modified: python/branches/release27-maint/ (props changed) python/branches/release27-maint/Lib/test/test_struct.py python/branches/release27-maint/Modules/_struct.c Modified: python/branches/release27-maint/Lib/test/test_struct.py ============================================================================== --- python/branches/release27-maint/Lib/test/test_struct.py (original) +++ python/branches/release27-maint/Lib/test/test_struct.py Wed Jul 7 21:03:36 2010 @@ -491,6 +491,9 @@ self.test_unpack_from(cls=buffer) def test_bool(self): + class ExplodingBool(object): + def __nonzero__(self): + raise IOError for prefix in tuple("<>!=")+('',): false = (), [], [], '', 0 true = [1], 'test', 5, -1, 0xffffffffL+1, 0xffffffff//2 @@ -519,8 +522,11 @@ self.assertFalse(prefix, msg='encoded bool is not one byte: %r' %packed) - for c in '\x01\x7f\xff\x0f\xf0': - self.assertTrue(struct.unpack('>?', c)[0]) + self.assertRaises(IOError, struct.pack, prefix + '?', + ExplodingBool()) + + for c in [b'\x01', b'\x7f', b'\xff', b'\x0f', b'\xf0']: + self.assertTrue(struct.unpack('>?', c)[0]) @unittest.skipUnless(IS32BIT, "Specific to 32bit machines") def test_crasher(self): Modified: python/branches/release27-maint/Modules/_struct.c ============================================================================== --- python/branches/release27-maint/Modules/_struct.c (original) +++ python/branches/release27-maint/Modules/_struct.c Wed Jul 7 21:03:36 2010 @@ -636,9 +636,13 @@ static int np_bool(char *p, PyObject *v, const formatdef *f) { - BOOL_TYPE y; + int y; + BOOL_TYPE x; y = PyObject_IsTrue(v); - memcpy(p, (char *)&y, sizeof y); + if (y < 0) + return -1; + x = y; + memcpy(p, (char *)&x, sizeof x); return 0; } @@ -910,6 +914,8 @@ { char y; y = PyObject_IsTrue(v); + if (y < 0) + return -1; memcpy(p, (char *)&y, sizeof y); return 0; } From python-checkins at python.org Wed Jul 7 21:04:36 2010 From: python-checkins at python.org (georg.brandl) Date: Wed, 7 Jul 2010 21:04:36 +0200 (CEST) Subject: [Python-checkins] r82632 - in python/branches/py3k/Doc/distutils: apiref.rst builtdist.rst setupscript.rst Message-ID: <20100707190436.C43A6EE993@mail.python.org> Author: georg.brandl Date: Wed Jul 7 21:04:36 2010 New Revision: 82632 Log: Turn more notes into comments. Modified: python/branches/py3k/Doc/distutils/apiref.rst python/branches/py3k/Doc/distutils/builtdist.rst python/branches/py3k/Doc/distutils/setupscript.rst Modified: python/branches/py3k/Doc/distutils/apiref.rst ============================================================================== --- python/branches/py3k/Doc/distutils/apiref.rst (original) +++ python/branches/py3k/Doc/distutils/apiref.rst Wed Jul 7 21:04:36 2010 @@ -995,7 +995,7 @@ errors are ignored (apart from being reported to ``sys.stdout`` if *verbose* is true). -**\*\*** Some of this could be replaced with the shutil module? **\*\*** +.. XXX Some of this could be replaced with the shutil module? :mod:`distutils.file_util` --- Single file operations @@ -1311,8 +1311,7 @@ the "negative alias" of :option:`--verbose`, then :option:`--quiet` on the command line sets *verbose* to false. -**\*\*** Should be replaced with :mod:`optik` (which is also now known as -:mod:`optparse` in Python 2.3 and later). **\*\*** +.. XXX Should be replaced with :mod:`optparse`. .. function:: fancy_getopt(options, negative_opt, object, args) Modified: python/branches/py3k/Doc/distutils/builtdist.rst ============================================================================== --- python/branches/py3k/Doc/distutils/builtdist.rst (original) +++ python/branches/py3k/Doc/distutils/builtdist.rst Wed Jul 7 21:04:36 2010 @@ -146,8 +146,8 @@ Creating dumb built distributions ================================= -**\*\*** Need to document absolute vs. prefix-relative packages here, but first -I have to implement it! **\*\*** +.. XXX Need to document absolute vs. prefix-relative packages here, but first + I have to implement it! .. _creating-rpms: Modified: python/branches/py3k/Doc/distutils/setupscript.rst ============================================================================== --- python/branches/py3k/Doc/distutils/setupscript.rst (original) +++ python/branches/py3k/Doc/distutils/setupscript.rst Wed Jul 7 21:04:36 2010 @@ -207,7 +207,7 @@ SWIG on the interface file and compile the resulting C/C++ file into your extension. -**\*\*** SWIG support is rough around the edges and largely untested! **\*\*** +.. XXX SWIG support is rough around the edges and largely untested! This warning notwithstanding, options to SWIG can be currently passed like this:: @@ -326,7 +326,7 @@ (Again, this sort of non-portable construct should be avoided if you intend to distribute your code.) -**\*\*** Should mention clib libraries here or somewhere else! **\*\*** +.. XXX Should mention clib libraries here or somewhere else! Other options From python-checkins at python.org Wed Jul 7 21:04:49 2010 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 7 Jul 2010 21:04:49 +0200 (CEST) Subject: [Python-checkins] r82633 - python/branches/py3k/Misc/NEWS Message-ID: <20100707190449.126D3EEB0F@mail.python.org> Author: benjamin.peterson Date: Wed Jul 7 21:04:48 2010 New Revision: 82633 Log: add NEWS Modified: python/branches/py3k/Misc/NEWS Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Wed Jul 7 21:04:48 2010 @@ -1396,6 +1396,9 @@ Extension Modules ----------------- +- In struct.pack, correctly propogate exceptions from computing the truth of an + object in the '?' format. + - Issue #9000: datetime.timezone objects now have eval-friendly repr. - In the math module, correctly lookup __trunc__, __ceil__, and __floor__ as From python-checkins at python.org Wed Jul 7 21:05:35 2010 From: python-checkins at python.org (georg.brandl) Date: Wed, 7 Jul 2010 21:05:35 +0200 (CEST) Subject: [Python-checkins] r82634 - in python/branches/release27-maint: Doc/distutils/apiref.rst Doc/distutils/builtdist.rst Doc/distutils/setupscript.rst Doc/distutils/sourcedist.rst Message-ID: <20100707190535.D6722EEB3D@mail.python.org> Author: georg.brandl Date: Wed Jul 7 21:05:35 2010 New Revision: 82634 Log: Merged revisions 82629,82632 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ........ r82629 | georg.brandl | 2010-07-07 20:51:43 +0200 (Mi, 07 Jul 2010) | 1 line Make comment out of an awkward note. ........ r82632 | georg.brandl | 2010-07-07 21:04:36 +0200 (Mi, 07 Jul 2010) | 1 line Turn more notes into comments. ........ Modified: python/branches/release27-maint/ (props changed) python/branches/release27-maint/Doc/distutils/apiref.rst python/branches/release27-maint/Doc/distutils/builtdist.rst python/branches/release27-maint/Doc/distutils/setupscript.rst python/branches/release27-maint/Doc/distutils/sourcedist.rst Modified: python/branches/release27-maint/Doc/distutils/apiref.rst ============================================================================== --- python/branches/release27-maint/Doc/distutils/apiref.rst (original) +++ python/branches/release27-maint/Doc/distutils/apiref.rst Wed Jul 7 21:05:35 2010 @@ -995,7 +995,7 @@ errors are ignored (apart from being reported to ``sys.stdout`` if *verbose* is true). -**\*\*** Some of this could be replaced with the shutil module? **\*\*** +.. XXX Some of this could be replaced with the shutil module? :mod:`distutils.file_util` --- Single file operations @@ -1311,8 +1311,7 @@ the "negative alias" of :option:`--verbose`, then :option:`--quiet` on the command line sets *verbose* to false. -**\*\*** Should be replaced with :mod:`optik` (which is also now known as -:mod:`optparse` in Python 2.3 and later). **\*\*** +.. XXX Should be replaced with :mod:`optparse`. .. function:: fancy_getopt(options, negative_opt, object, args) Modified: python/branches/release27-maint/Doc/distutils/builtdist.rst ============================================================================== --- python/branches/release27-maint/Doc/distutils/builtdist.rst (original) +++ python/branches/release27-maint/Doc/distutils/builtdist.rst Wed Jul 7 21:05:35 2010 @@ -146,8 +146,8 @@ Creating dumb built distributions ================================= -**\*\*** Need to document absolute vs. prefix-relative packages here, but first -I have to implement it! **\*\*** +.. XXX Need to document absolute vs. prefix-relative packages here, but first + I have to implement it! .. _creating-rpms: Modified: python/branches/release27-maint/Doc/distutils/setupscript.rst ============================================================================== --- python/branches/release27-maint/Doc/distutils/setupscript.rst (original) +++ python/branches/release27-maint/Doc/distutils/setupscript.rst Wed Jul 7 21:05:35 2010 @@ -207,7 +207,7 @@ SWIG on the interface file and compile the resulting C/C++ file into your extension. -**\*\*** SWIG support is rough around the edges and largely untested! **\*\*** +.. XXX SWIG support is rough around the edges and largely untested! This warning notwithstanding, options to SWIG can be currently passed like this:: @@ -326,7 +326,7 @@ (Again, this sort of non-portable construct should be avoided if you intend to distribute your code.) -**\*\*** Should mention clib libraries here or somewhere else! **\*\*** +.. XXX Should mention clib libraries here or somewhere else! Other options Modified: python/branches/release27-maint/Doc/distutils/sourcedist.rst ============================================================================== --- python/branches/release27-maint/Doc/distutils/sourcedist.rst (original) +++ python/branches/release27-maint/Doc/distutils/sourcedist.rst Wed Jul 7 21:05:35 2010 @@ -76,10 +76,10 @@ :option:`packages` options * all C source files mentioned in the :option:`ext_modules` or - :option:`libraries` options ( + :option:`libraries` options - **\*\*** getting C library sources currently broken---no - :meth:`get_source_files` method in :file:`build_clib.py`! **\*\***) + .. XXX Getting C library sources is currently broken -- no + :meth:`get_source_files` method in :file:`build_clib.py`! * scripts identified by the :option:`scripts` option See :ref:`distutils-installing-scripts`. From python-checkins at python.org Wed Jul 7 21:09:12 2010 From: python-checkins at python.org (georg.brandl) Date: Wed, 7 Jul 2010 21:09:12 +0200 (CEST) Subject: [Python-checkins] r82635 - in python/branches/release27-maint: Doc/using/cmdline.rst Message-ID: <20100707190912.63C8AEE9C4@mail.python.org> Author: georg.brandl Date: Wed Jul 7 21:09:12 2010 New Revision: 82635 Log: Merged revisions 82615 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ........ r82615 | georg.brandl | 2010-07-07 00:58:50 +0200 (Mi, 07 Jul 2010) | 1 line Fix typo. ........ Modified: python/branches/release27-maint/ (props changed) python/branches/release27-maint/Doc/using/cmdline.rst Modified: python/branches/release27-maint/Doc/using/cmdline.rst ============================================================================== --- python/branches/release27-maint/Doc/using/cmdline.rst (original) +++ python/branches/release27-maint/Doc/using/cmdline.rst Wed Jul 7 21:09:12 2010 @@ -61,7 +61,7 @@ .. cmdoption:: -c - Execute the Python code in *command*. *command* can be one ore more + Execute the Python code in *command*. *command* can be one or more statements separated by newlines, with significant leading whitespace as in normal module code. From python-checkins at python.org Wed Jul 7 22:54:01 2010 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 7 Jul 2010 22:54:01 +0200 (CEST) Subject: [Python-checkins] r82636 - in python/branches/py3k: Include/structseq.h Misc/NEWS Objects/structseq.c Message-ID: <20100707205401.A8198F68FA@mail.python.org> Author: benjamin.peterson Date: Wed Jul 7 22:54:01 2010 New Revision: 82636 Log: make struct sequences subclass tuple; kill lots of code This fixes #8413. Modified: python/branches/py3k/Include/structseq.h python/branches/py3k/Misc/NEWS python/branches/py3k/Objects/structseq.c Modified: python/branches/py3k/Include/structseq.h ============================================================================== --- python/branches/py3k/Include/structseq.h (original) +++ python/branches/py3k/Include/structseq.h Wed Jul 7 22:54:01 2010 @@ -26,17 +26,12 @@ PyAPI_FUNC(PyObject *) PyStructSequence_New(PyTypeObject* type); -typedef struct { - PyObject_VAR_HEAD - PyObject *ob_item[1]; -} PyStructSequence; +typedef PyTupleObject PyStructSequence; /* Macro, *only* to be used to fill in brand new objects */ -#define PyStructSequence_SET_ITEM(op, i, v) \ - (((PyStructSequence *)(op))->ob_item[i] = v) +#define PyStructSequence_SET_ITEM(op, i, v) PyTuple_SET_ITEM(op, i, v) -#define PyStructSequence_GET_ITEM(op, i) \ - (((PyStructSequence *)(op))->ob_item[i]) +#define PyStructSequence_GET_ITEM(op, i) PyTuple_GET_ITEM(op, i) #ifdef __cplusplus Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Wed Jul 7 22:54:01 2010 @@ -12,6 +12,8 @@ Core and Builtins ----------------- +- Issue #8413: structsequence now subclasses tuple. + - Issue #8271: during the decoding of an invalid UTF-8 byte sequence, only the start byte and the continuation byte(s) are now considered invalid, instead of the number of bytes specified by the start byte. Modified: python/branches/py3k/Objects/structseq.c ============================================================================== --- python/branches/py3k/Objects/structseq.c (original) +++ python/branches/py3k/Objects/structseq.c Wed Jul 7 22:54:01 2010 @@ -30,113 +30,15 @@ PyStructSequence_New(PyTypeObject *type) { PyStructSequence *obj; + Py_ssize_t size = REAL_SIZE_TP(type), i; - obj = PyObject_New(PyStructSequence, type); + obj = PyObject_GC_NewVar(PyStructSequence, type, size); if (obj == NULL) return NULL; - Py_SIZE(obj) = VISIBLE_SIZE_TP(type); + for (i = 0; i < size; i++) + obj->ob_item[i] = NULL; - return (PyObject*) obj; -} - -static void -structseq_dealloc(PyStructSequence *obj) -{ - Py_ssize_t i, size; - - size = REAL_SIZE(obj); - for (i = 0; i < size; ++i) { - Py_XDECREF(obj->ob_item[i]); - } - PyObject_Del(obj); -} - -static Py_ssize_t -structseq_length(PyStructSequence *obj) -{ - return VISIBLE_SIZE(obj); -} - -static PyObject* -structseq_item(PyStructSequence *obj, Py_ssize_t i) -{ - if (i < 0 || i >= VISIBLE_SIZE(obj)) { - PyErr_SetString(PyExc_IndexError, "tuple index out of range"); - return NULL; - } - Py_INCREF(obj->ob_item[i]); - return obj->ob_item[i]; -} - -static PyObject* -structseq_slice(PyStructSequence *obj, Py_ssize_t low, Py_ssize_t high) -{ - PyTupleObject *np; - Py_ssize_t i; - - if (low < 0) - low = 0; - if (high > VISIBLE_SIZE(obj)) - high = VISIBLE_SIZE(obj); - if (high < low) - high = low; - np = (PyTupleObject *)PyTuple_New(high-low); - if (np == NULL) - return NULL; - for(i = low; i < high; ++i) { - PyObject *v = obj->ob_item[i]; - Py_INCREF(v); - PyTuple_SET_ITEM(np, i-low, v); - } - return (PyObject *) np; -} - -static PyObject * -structseq_subscript(PyStructSequence *self, PyObject *item) -{ - if (PyIndex_Check(item)) { - Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); - if (i == -1 && PyErr_Occurred()) - return NULL; - - if (i < 0) - i += VISIBLE_SIZE(self); - - if (i < 0 || i >= VISIBLE_SIZE(self)) { - PyErr_SetString(PyExc_IndexError, - "tuple index out of range"); - return NULL; - } - Py_INCREF(self->ob_item[i]); - return self->ob_item[i]; - } - else if (PySlice_Check(item)) { - Py_ssize_t start, stop, step, slicelen, cur, i; - PyObject *result; - - if (PySlice_GetIndicesEx((PySliceObject *)item, - VISIBLE_SIZE(self), &start, &stop, - &step, &slicelen) < 0) { - return NULL; - } - if (slicelen <= 0) - return PyTuple_New(0); - result = PyTuple_New(slicelen); - if (result == NULL) - return NULL; - for (cur = start, i = 0; i < slicelen; - cur += step, i++) { - PyObject *v = self->ob_item[cur]; - Py_INCREF(v); - PyTuple_SET_ITEM(result, i, v); - } - return result; - } - else { - PyErr_SetString(PyExc_TypeError, - "structseq index must be integer"); - return NULL; - } + return (PyObject*)obj; } static PyObject * @@ -223,11 +125,6 @@ return (PyObject*) res; } -static PyObject * -make_tuple(PyStructSequence *obj) -{ - return structseq_slice(obj, 0, VISIBLE_SIZE(obj)); -} static PyObject * structseq_repr(PyStructSequence *obj) @@ -236,7 +133,6 @@ #define REPR_BUFFER_SIZE 512 #define TYPE_MAXSIZE 100 - PyObject *tup; PyTypeObject *typ = Py_TYPE(obj); int i, removelast = 0; Py_ssize_t len; @@ -246,10 +142,6 @@ /* pointer to end of writeable buffer; safes space for "...)\0" */ endofbuf= &buf[REPR_BUFFER_SIZE-5]; - if ((tup = make_tuple(obj)) == NULL) { - return NULL; - } - /* "typename(", limited to TYPE_MAXSIZE */ len = strlen(typ->tp_name) > TYPE_MAXSIZE ? TYPE_MAXSIZE : strlen(typ->tp_name); @@ -262,19 +154,14 @@ char *cname, *crepr; cname = typ->tp_members[i].name; - - val = PyTuple_GetItem(tup, i); - if (cname == NULL || val == NULL) { + if (cname == NULL) return NULL; - } + val = PyStructSequence_GET_ITEM(obj, i); repr = PyObject_Repr(val); - if (repr == NULL) { - Py_DECREF(tup); + if (repr == NULL) return NULL; - } crepr = _PyUnicode_AsString(repr); if (crepr == NULL) { - Py_DECREF(tup); Py_DECREF(repr); return NULL; } @@ -300,7 +187,6 @@ break; } } - Py_DECREF(tup); if (removelast) { /* overwrite last ", " */ pbuf-=2; @@ -312,62 +198,6 @@ } static PyObject * -structseq_concat(PyStructSequence *obj, PyObject *b) -{ - PyObject *tup, *result; - tup = make_tuple(obj); - result = PySequence_Concat(tup, b); - Py_DECREF(tup); - return result; -} - -static PyObject * -structseq_repeat(PyStructSequence *obj, Py_ssize_t n) -{ - PyObject *tup, *result; - tup = make_tuple(obj); - result = PySequence_Repeat(tup, n); - Py_DECREF(tup); - return result; -} - -static int -structseq_contains(PyStructSequence *obj, PyObject *o) -{ - PyObject *tup; - int result; - tup = make_tuple(obj); - if (!tup) - return -1; - result = PySequence_Contains(tup, o); - Py_DECREF(tup); - return result; -} - -static long -structseq_hash(PyObject *obj) -{ - PyObject *tup; - long result; - tup = make_tuple((PyStructSequence*) obj); - if (!tup) - return -1; - result = PyObject_Hash(tup); - Py_DECREF(tup); - return result; -} - -static PyObject * -structseq_richcompare(PyObject *obj, PyObject *o2, int op) -{ - PyObject *tup, *result; - tup = make_tuple((PyStructSequence*) obj); - result = PyObject_RichCompare(tup, o2, op); - Py_DECREF(tup); - return result; -} - -static PyObject * structseq_reduce(PyStructSequence* self) { PyObject* tup; @@ -409,53 +239,36 @@ return result; } -static PySequenceMethods structseq_as_sequence = { - (lenfunc)structseq_length, - (binaryfunc)structseq_concat, /* sq_concat */ - (ssizeargfunc)structseq_repeat, /* sq_repeat */ - (ssizeargfunc)structseq_item, /* sq_item */ - 0, /* sq_slice */ - 0, /* sq_ass_item */ - 0, /* sq_ass_slice */ - (objobjproc)structseq_contains, /* sq_contains */ -}; - -static PyMappingMethods structseq_as_mapping = { - (lenfunc)structseq_length, - (binaryfunc)structseq_subscript, -}; - static PyMethodDef structseq_methods[] = { - {"__reduce__", (PyCFunction)structseq_reduce, - METH_NOARGS, NULL}, + {"__reduce__", (PyCFunction)structseq_reduce, METH_NOARGS, NULL}, {NULL, NULL} }; static PyTypeObject _struct_sequence_template = { PyVarObject_HEAD_INIT(&PyType_Type, 0) NULL, /* tp_name */ - 0, /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)structseq_dealloc, /* tp_dealloc */ + sizeof(PyStructSequence) - sizeof(PyObject *), /* tp_basicsize */ + sizeof(PyObject *), /* tp_itemsize */ + 0, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_reserved */ (reprfunc)structseq_repr, /* tp_repr */ 0, /* tp_as_number */ - &structseq_as_sequence, /* tp_as_sequence */ - &structseq_as_mapping, /* tp_as_mapping */ - structseq_hash, /* tp_hash */ + 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 */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ NULL, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ - structseq_richcompare, /* tp_richcompare */ + 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ @@ -494,11 +307,9 @@ n_members = i; memcpy(type, &_struct_sequence_template, sizeof(PyTypeObject)); + type->tp_base = &PyTuple_Type; type->tp_name = desc->name; type->tp_doc = desc->doc; - type->tp_basicsize = sizeof(PyStructSequence)+ - sizeof(PyObject*)*(n_members-1); - type->tp_itemsize = 0; members = PyMem_NEW(PyMemberDef, n_members-n_unnamed_members+1); if (members == NULL) From python-checkins at python.org Thu Jul 8 00:45:06 2010 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 8 Jul 2010 00:45:06 +0200 (CEST) Subject: [Python-checkins] r82637 - python/branches/py3k/Lib/test/test_struct.py Message-ID: <20100707224506.A24B4EEB68@mail.python.org> Author: benjamin.peterson Date: Thu Jul 8 00:45:06 2010 New Revision: 82637 Log: ValueError in this case is also acceptable Modified: python/branches/py3k/Lib/test/test_struct.py Modified: python/branches/py3k/Lib/test/test_struct.py ============================================================================== --- python/branches/py3k/Lib/test/test_struct.py (original) +++ python/branches/py3k/Lib/test/test_struct.py Thu Jul 8 00:45:06 2010 @@ -438,8 +438,10 @@ # Go beyond boundaries. small_buf = array.array('b', b' '*10) - self.assertRaises(struct.error, s.pack_into, small_buf, 0, test_string) - self.assertRaises(struct.error, s.pack_into, small_buf, 2, test_string) + self.assertRaises((ValueError, struct.error), s.pack_into, small_buf, 0, + test_string) + self.assertRaises((ValueError, struct.error), s.pack_into, small_buf, 2, + test_string) # Test bogus offset (issue 3694) sb = small_buf @@ -463,8 +465,10 @@ # Go beyond boundaries. small_buf = array.array('b', b' '*10) - self.assertRaises(struct.error, pack_into, small_buf, 0, test_string) - self.assertRaises(struct.error, pack_into, small_buf, 2, test_string) + self.assertRaises((ValueError, struct.error), pack_into, small_buf, 0, + test_string) + self.assertRaises((ValueError, struct.error), pack_into, small_buf, 2, + test_string) def test_unpack_with_buffer(self): # SF bug 1563759: struct.unpack doens't support buffer protocol objects From python-checkins at python.org Thu Jul 8 00:46:01 2010 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 8 Jul 2010 00:46:01 +0200 (CEST) Subject: [Python-checkins] r82638 - in python/branches/release31-maint: Lib/test/test_struct.py Modules/_struct.c Message-ID: <20100707224601.13701EEBDD@mail.python.org> Author: benjamin.peterson Date: Thu Jul 8 00:46:00 2010 New Revision: 82638 Log: Merged revisions 82628,82630 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ........ r82628 | benjamin.peterson | 2010-07-07 13:44:05 -0500 (Wed, 07 Jul 2010) | 1 line this needn't be in the loop ........ r82630 | benjamin.peterson | 2010-07-07 13:54:59 -0500 (Wed, 07 Jul 2010) | 1 line don't ignore exceptions from PyObject_IsTrue ........ Modified: python/branches/release31-maint/ (props changed) python/branches/release31-maint/Lib/test/test_struct.py python/branches/release31-maint/Modules/_struct.c Modified: python/branches/release31-maint/Lib/test/test_struct.py ============================================================================== --- python/branches/release31-maint/Lib/test/test_struct.py (original) +++ python/branches/release31-maint/Lib/test/test_struct.py Thu Jul 8 00:46:00 2010 @@ -480,6 +480,9 @@ self.assertEqual(value, 0x12345678) def test_bool(self): + class ExplodingBool(object): + def __bool__(self): + raise IOError for prefix in tuple("<>!=")+('',): false = (), [], [], '', 0 true = [1], 'test', 5, -1, 0xffffffff+1, 0xffffffff/2 @@ -508,8 +511,11 @@ self.assertFalse(prefix, msg='encoded bool is not one byte: %r' %packed) - for c in [b'\x01', b'\x7f', b'\xff', b'\x0f', b'\xf0']: - self.assertTrue(struct.unpack('>?', c)[0]) + self.assertRaises(IOError, struct.pack, prefix + '?', + ExplodingBool()) + + for c in [b'\x01', b'\x7f', b'\xff', b'\x0f', b'\xf0']: + self.assertTrue(struct.unpack('>?', c)[0]) def test_count_overflow(self): hugecount = '{}b'.format(sys.maxsize+1) Modified: python/branches/release31-maint/Modules/_struct.c ============================================================================== --- python/branches/release31-maint/Modules/_struct.c (original) +++ python/branches/release31-maint/Modules/_struct.c Thu Jul 8 00:46:00 2010 @@ -580,9 +580,13 @@ static int np_bool(char *p, PyObject *v, const formatdef *f) { - BOOL_TYPE y; + int y; + BOOL_TYPE x; y = PyObject_IsTrue(v); - memcpy(p, (char *)&y, sizeof y); + if (y < 0) + return -1; + x = y; + memcpy(p, (char *)&x, sizeof x); return 0; } @@ -854,6 +858,8 @@ { char y; y = PyObject_IsTrue(v); + if (y < 0) + return -1; memcpy(p, (char *)&y, sizeof y); return 0; } From python-checkins at python.org Thu Jul 8 00:50:58 2010 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 8 Jul 2010 00:50:58 +0200 (CEST) Subject: [Python-checkins] r82639 - in python/branches/release31-maint: Lib/test/test_struct.py Message-ID: <20100707225058.9C669EEBEE@mail.python.org> Author: benjamin.peterson Date: Thu Jul 8 00:50:58 2010 New Revision: 82639 Log: Merged revisions 82637 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ........ r82637 | benjamin.peterson | 2010-07-07 17:45:06 -0500 (Wed, 07 Jul 2010) | 1 line ValueError in this case is also acceptable ........ Modified: python/branches/release31-maint/ (props changed) python/branches/release31-maint/Lib/test/test_struct.py Modified: python/branches/release31-maint/Lib/test/test_struct.py ============================================================================== --- python/branches/release31-maint/Lib/test/test_struct.py (original) +++ python/branches/release31-maint/Lib/test/test_struct.py Thu Jul 8 00:50:58 2010 @@ -443,8 +443,10 @@ # Go beyond boundaries. small_buf = array.array('b', b' '*10) - self.assertRaises(struct.error, s.pack_into, small_buf, 0, test_string) - self.assertRaises(struct.error, s.pack_into, small_buf, 2, test_string) + self.assertRaises((ValueError, struct.error), s.pack_into, small_buf, 0, + test_string) + self.assertRaises((ValueError, struct.error), s.pack_into, small_buf, 2, + test_string) # Test bogus offset (issue 3694) sb = small_buf @@ -468,8 +470,10 @@ # Go beyond boundaries. small_buf = array.array('b', b' '*10) - self.assertRaises(struct.error, pack_into, small_buf, 0, test_string) - self.assertRaises(struct.error, pack_into, small_buf, 2, test_string) + self.assertRaises((ValueError, struct.error), pack_into, small_buf, 0, + test_string) + self.assertRaises((ValueError, struct.error), pack_into, small_buf, 2, + test_string) def test_unpack_with_buffer(self): # SF bug 1563759: struct.unpack doens't support buffer protocol objects From solipsis at pitrou.net Thu Jul 8 01:24:45 2010 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Thu, 8 Jul 2010 01:24:45 +0200 (CEST) Subject: [Python-checkins] Daily py3k reference leaks (r82636): sum=0 Message-ID: <20100707232445.726061770A@ns6635.ovh.net> py3k results for svn r82636 (hg cset b673e8062e16) -------------------------------------------------- Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/py3k/refleaks/reflog9-BDj5', '-x'] From python-checkins at python.org Thu Jul 8 01:26:57 2010 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 8 Jul 2010 01:26:57 +0200 (CEST) Subject: [Python-checkins] r82640 - in python/branches/release27-maint: Lib/test/test_struct.py Message-ID: <20100707232657.D3A22EEC07@mail.python.org> Author: benjamin.peterson Date: Thu Jul 8 01:26:57 2010 New Revision: 82640 Log: Merged revisions 82637 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ........ r82637 | benjamin.peterson | 2010-07-07 17:45:06 -0500 (Wed, 07 Jul 2010) | 1 line ValueError in this case is also acceptable ........ Modified: python/branches/release27-maint/ (props changed) python/branches/release27-maint/Lib/test/test_struct.py Modified: python/branches/release27-maint/Lib/test/test_struct.py ============================================================================== --- python/branches/release27-maint/Lib/test/test_struct.py (original) +++ python/branches/release27-maint/Lib/test/test_struct.py Thu Jul 8 01:26:57 2010 @@ -450,8 +450,10 @@ # Go beyond boundaries. small_buf = array.array('c', ' '*10) - self.assertRaises(struct.error, s.pack_into, small_buf, 0, test_string) - self.assertRaises(struct.error, s.pack_into, small_buf, 2, test_string) + self.assertRaises((ValueError, struct.error), s.pack_into, small_buf, 0, + test_string) + self.assertRaises((ValueError, struct.error), s.pack_into, small_buf, 2, + test_string) # Test bogus offset (issue 3694) sb = small_buf @@ -475,8 +477,10 @@ # Go beyond boundaries. small_buf = array.array('c', ' '*10) - self.assertRaises(struct.error, pack_into, small_buf, 0, test_string) - self.assertRaises(struct.error, pack_into, small_buf, 2, test_string) + self.assertRaises((ValueError, struct.error), pack_into, small_buf, 0, + test_string) + self.assertRaises((ValueError, struct.error), pack_into, small_buf, 2, + test_string) def test_unpack_with_buffer(self): with check_py3k_warnings(("buffer.. not supported in 3.x", From python-checkins at python.org Thu Jul 8 01:46:38 2010 From: python-checkins at python.org (alexander.belopolsky) Date: Thu, 8 Jul 2010 01:46:38 +0200 (CEST) Subject: [Python-checkins] r82641 - sandbox/branches/py3k-datetime/datetime.py Message-ID: <20100707234638.98E58EEC09@mail.python.org> Author: alexander.belopolsky Date: Thu Jul 8 01:46:38 2010 New Revision: 82641 Log: Issue #5288: Eliminated round-trips between timdelta and int offsets Modified: sandbox/branches/py3k-datetime/datetime.py Modified: sandbox/branches/py3k-datetime/datetime.py ============================================================================== --- sandbox/branches/py3k-datetime/datetime.py (original) +++ sandbox/branches/py3k-datetime/datetime.py Thu Jul 8 01:46:38 2010 @@ -176,7 +176,7 @@ if year < 1900: raise ValueError("year=%d is before 1900; the datetime strftime() " "methods require year >= 1900" % year) - # Don't call _utcoffset() or tzname() unless actually needed. + # Don't call utcoffset() or tzname() unless actually needed. freplace = None # the string to use for %f zreplace = None # the string to use for %z Zreplace = None # the string to use for %Z @@ -200,14 +200,16 @@ elif ch == 'z': if zreplace is None: zreplace = "" - if hasattr(object, "_utcoffset"): - offset = object._utcoffset() + if hasattr(object, "utcoffset"): + offset = object.utcoffset() if offset is not None: sign = '+' - if offset < 0: + if offset.days < 0: offset = -offset sign = '-' - h, m = divmod(offset, 60) + h, m = divmod(offset, timedelta(hours=1)) + assert not m % timedelta(0, 60), "whole minute" + m //= timedelta(0, 60) zreplace = '%c%02d%02d' % (sign, h, m) assert '%' not in zreplace newformat.append(zreplace) @@ -250,23 +252,17 @@ def _check_utc_offset(name, offset): assert name in ("utcoffset", "dst") if offset is None: - return None + return if not isinstance(offset, timedelta): raise TypeError("tzinfo.%s() must return None " "or timedelta, not '%s'" % (name, type(offset))) - days = offset.days - if days < -1 or days > 0: - offset = 1440 # trigger out-of-range - else: - seconds = days * 86400 + offset.seconds - minutes, seconds = divmod(seconds, 60) - if seconds or offset.microseconds: - raise ValueError("tzinfo.%s() must return a whole number " - "of minutes" % name) - offset = minutes - if -1440 < offset < 1440: - return offset - raise ValueError("%s()=%d, must be in -1439..1439" % (name, offset)) + if offset % timedelta(0, 60) or offset.microseconds: + raise ValueError("tzinfo.%s() must return a whole number " + "of minutes, got %s" % (name, offset)) + if not -timedelta(1) < offset < timedelta(1): + raise ValueError("%s()=%s, must be must be strictly between" + " -timedelta(hours=24) and timedelta(hours=24)" + % (name, offset)) def _check_date_fields(year, month, day): if not isinstance(year, int): @@ -1112,8 +1108,8 @@ if mytz is ottz: base_compare = True else: - myoff = self._utcoffset() - otoff = other._utcoffset() + myoff = self.utcoffset() + otoff = other.utcoffset() base_compare = myoff == otoff if base_compare: @@ -1123,17 +1119,20 @@ other._microsecond)) if myoff is None or otoff is None: raise TypeError("cannot compare naive and aware times") - myhhmm = self._hour * 60 + self._minute - myoff - othhmm = other._hour * 60 + other._minute - otoff + myhhmm = self._hour * 60 + self._minute - myoff//timedelta(0, 60) + othhmm = other._hour * 60 + other._minute - otoff//timedelta(0, 60) return _cmp((myhhmm, self._second, self._microsecond), (othhmm, other._second, other._microsecond)) def __hash__(self): """Hash.""" - tzoff = self._utcoffset() + tzoff = self.utcoffset() if not tzoff: # zero or None return hash(self._getstate()[0]) - h, m = divmod(self.hour * 60 + self.minute - tzoff, 60) + h, m = divmod(timedelta(hours=self.hour, minutes=self.minute) - tzoff, + timedelta(hours=1)) + assert not m % timedelta(0, 60), "whole minute" + m //= timedelta(0, 60) if 0 <= h < 24: return hash(time(h, m, self.second, self.microsecond)) return hash((h, m, self.second, self.microsecond)) @@ -1142,14 +1141,16 @@ def _tzstr(self, sep=":"): """Return formatted timezone offset (+xx:xx) or None.""" - off = self._utcoffset() + off = self.utcoffset() if off is not None: - if off < 0: + if off.days < 0: sign = "-" off = -off else: sign = "+" - hh, mm = divmod(off, 60) + hh, mm = divmod(off, timedelta(hours=1)) + assert not mm % timedelta(0, 60), "whole minute" + mm //= timedelta(0, 60) assert 0 <= hh < 24 off = "%s%02d%s%02d" % (sign, hh, sep, mm) return off @@ -1205,16 +1206,10 @@ def utcoffset(self): """Return the timezone offset in minutes east of UTC (negative west of UTC).""" - offset = _call_tzinfo_method(self._tzinfo, "utcoffset", None) - offset = _check_utc_offset("utcoffset", offset) - if offset is not None: - offset = timedelta(minutes=offset) - return offset - - # Return an integer (or None) instead of a timedelta (or None). - def _utcoffset(self): - offset = _call_tzinfo_method(self._tzinfo, "utcoffset", None) - offset = _check_utc_offset("utcoffset", offset) + if self._tzinfo is None: + return None + offset = self._tzinfo.utcoffset(None) + _check_utc_offset("utcoffset", offset) return offset def tzname(self): @@ -1224,7 +1219,9 @@ it mean anything in particular. For example, "GMT", "UTC", "-500", "-5:00", "EDT", "US/Eastern", "America/New York" are all valid replies. """ - name = _call_tzinfo_method(self._tzinfo, "tzname", None) + if self._tzinfo is None: + return None + name = self._tzinfo.tzname(None) _check_tzname(name) return name @@ -1237,10 +1234,10 @@ need to consult dst() unless you're interested in displaying the DST info. """ - offset = _call_tzinfo_method(self._tzinfo, "dst", None) - offset = _check_utc_offset("dst", offset) - if offset is not None: - offset = timedelta(minutes=offset) + if self._tzinfo is None: + return None + offset = self._tzinfo.dst(None) + _check_utc_offset("dst", offset) return offset def replace(self, hour=None, minute=None, second=None, microsecond=None, @@ -1263,8 +1260,8 @@ def __bool__(self): if self.second or self.microsecond: return True - offset = self._utcoffset() or 0 - return self.hour * 60 + self.minute - offset != 0 + offset = self.utcoffset() or timedelta(0) + return timedelta(hours=self.hour, minutes=self.minute) != offset # Pickle support. @@ -1417,11 +1414,13 @@ def timetuple(self): "Return local time tuple compatible with time.localtime()." - dst = self._dst() + dst = self.dst() if dst is None: dst = -1 elif dst: dst = 1 + else: + dst = 0 return _build_struct_time(self.year, self.month, self.day, self.hour, self.minute, self.second, dst) @@ -1521,14 +1520,16 @@ sep) + _format_time(self._hour, self._minute, self._second, self._microsecond)) - off = self._utcoffset() + off = self.utcoffset() if off is not None: - if off < 0: + if off.days < 0: sign = "-" off = -off else: sign = "+" - hh, mm = divmod(off, 60) + hh, mm = divmod(off, timedelta(hours=1)) + assert not mm % timedelta(0, 60), "whole minute" + mm //= timedelta(0, 60) s += "%s%02d:%02d" % (sign, hh, mm) return s @@ -1560,16 +1561,10 @@ def utcoffset(self): """Return the timezone offset in minutes east of UTC (negative west of UTC).""" - offset = _call_tzinfo_method(self._tzinfo, "utcoffset", self) - offset = _check_utc_offset("utcoffset", offset) - if offset is not None: - offset = timedelta(minutes=offset) - return offset - - # Return an integer (or None) instead of a timedelta (or None). - def _utcoffset(self): - offset = _call_tzinfo_method(self._tzinfo, "utcoffset", self) - offset = _check_utc_offset("utcoffset", offset) + if self._tzinfo is None: + return None + offset = self._tzinfo.utcoffset(self) + _check_utc_offset("utcoffset", offset) return offset def tzname(self): @@ -1592,16 +1587,10 @@ need to consult dst() unless you're interested in displaying the DST info. """ - offset = _call_tzinfo_method(self._tzinfo, "dst", self) - offset = _check_utc_offset("dst", offset) - if offset is not None: - offset = timedelta(minutes=offset) - return offset - - # Return an integer (or None) instead of a timedelta (or None).1573 - def _dst(self): - offset = _call_tzinfo_method(self._tzinfo, "dst", self) - offset = _check_utc_offset("dst", offset) + if self._tzinfo is None: + return None + offset = self._tzinfo.dst(self) + _check_utc_offset("dst", offset) return offset # Comparisons of datetime objects with other. @@ -1664,9 +1653,9 @@ base_compare = True else: if mytz is not None: - myoff = self._utcoffset() + myoff = self.utcoffset() if ottz is not None: - otoff = other._utcoffset() + otoff = other.utcoffset() base_compare = myoff == otoff if base_compare: @@ -1721,21 +1710,21 @@ self._microsecond - other._microsecond) if self._tzinfo is other._tzinfo: return base - myoff = self._utcoffset() - otoff = other._utcoffset() + myoff = self.utcoffset() + otoff = other.utcoffset() if myoff == otoff: return base if myoff is None or otoff is None: raise TypeError("cannot mix naive and timezone-aware time") - return base + timedelta(minutes = otoff-myoff) + return base + otoff - myoff def __hash__(self): - tzoff = self._utcoffset() + tzoff = self.utcoffset() if tzoff is None: return hash(self._getstate()[0]) days = _ymd2ord(self.year, self.month, self.day) - seconds = self.hour * 3600 + (self.minute - tzoff) * 60 + self.second - return hash(timedelta(days, seconds, self.microsecond)) + seconds = self.hour * 3600 + self.minute * 60 + self.second + return hash(timedelta(days, seconds, self.microsecond) - tzoff) # Pickle support. From python-checkins at python.org Thu Jul 8 01:56:38 2010 From: python-checkins at python.org (alexander.belopolsky) Date: Thu, 8 Jul 2010 01:56:38 +0200 (CEST) Subject: [Python-checkins] r82642 - python/branches/py3k/Modules/datetimemodule.c Message-ID: <20100707235638.DA6D2EEC1A@mail.python.org> Author: alexander.belopolsky Date: Thu Jul 8 01:56:38 2010 New Revision: 82642 Log: Issue #5288: Eliminated round-trips between timdelta and int offsets Modified: python/branches/py3k/Modules/datetimemodule.c Modified: python/branches/py3k/Modules/datetimemodule.c ============================================================================== --- python/branches/py3k/Modules/datetimemodule.c (original) +++ python/branches/py3k/Modules/datetimemodule.c Thu Jul 8 01:56:38 2010 @@ -88,8 +88,11 @@ /* p is a pointer to a time or a datetime object; HASTZINFO(p) returns * p->hastzinfo. */ -#define HASTZINFO(p) (((_PyDateTime_BaseTZInfo *)(p))->hastzinfo) - +#define HASTZINFO(p) (((_PyDateTime_BaseTZInfo *)(p))->hastzinfo) +#define GET_TIME_TZINFO(p) (HASTZINFO(p) ? \ + ((PyDateTime_Time *)(p))->tzinfo : Py_None) +#define GET_DT_TZINFO(p) (HASTZINFO(p) ? \ + ((PyDateTime_DateTime *)(p))->tzinfo : Py_None) /* M is a char or int claiming to be a valid month. The macro is equivalent * to the two-sided Python test * 1 <= M <= 12 @@ -839,25 +842,6 @@ return -1; } -/* Return tzinfo.methname(tzinfoarg), without any checking of results. - * If tzinfo is None, returns None. - */ -static PyObject * -call_tzinfo_method(PyObject *tzinfo, char *methname, PyObject *tzinfoarg) -{ - PyObject *result; - - assert(tzinfo && methname && tzinfoarg); - assert(check_tzinfo_subclass(tzinfo) >= 0); - if (tzinfo == Py_None) { - result = Py_None; - Py_INCREF(result); - } - else - result = PyObject_CallMethod(tzinfo, methname, "O", tzinfoarg); - return result; -} - /* If self has a tzinfo member, return a BORROWED reference to it. Else * return NULL, which is NOT AN ERROR. There are no error returns here, * and the caller must not decref the result. @@ -875,69 +859,53 @@ return tzinfo; } -/* Call getattr(tzinfo, name)(tzinfoarg), and extract an int from the - * result. tzinfo must be an instance of the tzinfo class. If the method - * returns None, this returns 0 and sets *none to 1. If the method doesn't - * return None or timedelta, TypeError is raised and this returns -1. If it - * returnsa timedelta and the value is out of range or isn't a whole number - * of minutes, ValueError is raised and this returns -1. - * Else *none is set to 0 and the integer method result is returned. +/* Call getattr(tzinfo, name)(tzinfoarg), and check the result. tzinfo must + * be an instance of the tzinfo class. If the method returns None, this + * returns None. If the method doesn't return None or timedelta, TypeError is + * raised and this returns NULL. If it returns a timedelta and the value is + * out of range or isn't a whole number of minutes, ValueError is raised and + * this returns NULL. Else result is returned. */ -static int -call_utc_tzinfo_method(PyObject *tzinfo, char *name, PyObject *tzinfoarg, - int *none) +static PyObject * +call_tzinfo_method(PyObject *tzinfo, char *name, PyObject *tzinfoarg) { - PyObject *u; - int result = -1; + PyObject *offset; assert(tzinfo != NULL); - assert(PyTZInfo_Check(tzinfo)); + assert(PyTZInfo_Check(tzinfo) || tzinfo == Py_None); assert(tzinfoarg != NULL); - *none = 0; - u = call_tzinfo_method(tzinfo, name, tzinfoarg); - if (u == NULL) - return -1; - - else if (u == Py_None) { - result = 0; - *none = 1; - } - else if (PyDelta_Check(u)) { - const int days = GET_TD_DAYS(u); - if (days < -1 || days > 0) - result = 24*60; /* trigger ValueError below */ - else { - /* next line can't overflow because we know days - * is -1 or 0 now - */ - int ss = days * 24 * 3600 + GET_TD_SECONDS(u); - result = divmod(ss, 60, &ss); - if (ss || GET_TD_MICROSECONDS(u)) { - PyErr_Format(PyExc_ValueError, - "tzinfo.%s() must return a " - "whole number of minutes", - name); - result = -1; - } + if (tzinfo == Py_None) + Py_RETURN_NONE; + offset = PyObject_CallMethod(tzinfo, name, "O", tzinfoarg); + if (offset == Py_None || offset == NULL) + return offset; + if (PyDelta_Check(offset)) { + if (GET_TD_MICROSECONDS(offset) != 0 || GET_TD_SECONDS(offset) % 60 != 0) { + Py_DECREF(offset); + PyErr_Format(PyExc_ValueError, "offset must be a timedelta" + " representing a whole number of minutes"); + return NULL; + } + if ((GET_TD_DAYS(offset) == -1 && GET_TD_SECONDS(offset) == 0) || + GET_TD_DAYS(offset) < -1 || GET_TD_DAYS(offset) >= 1) { + Py_DECREF(offset); + PyErr_Format(PyExc_ValueError, "offset must be a timedelta" + " strictly between -timedelta(hours=24) and" + " timedelta(hours=24)."); + return NULL; } } else { + Py_DECREF(offset); PyErr_Format(PyExc_TypeError, "tzinfo.%s() must return None or " - "timedelta, not '%s'", - name, Py_TYPE(u)->tp_name); + "timedelta, not '%.200s'", + name, Py_TYPE(offset)->tp_name); + return NULL; } - Py_DECREF(u); - if (result < -1439 || result > 1439) { - PyErr_Format(PyExc_ValueError, - "tzinfo.%s() returned %d; must be in " - "-1439 .. 1439", - name, result); - result = -1; - } - return result; + return offset; } /* Call tzinfo.utcoffset(tzinfoarg), and extract an integer from the @@ -948,37 +916,10 @@ * # of minutes), ValueError is raised and this returns -1. Else *none is * set to 0 and the offset is returned (as int # of minutes east of UTC). */ -static int -call_utcoffset(PyObject *tzinfo, PyObject *tzinfoarg, int *none) -{ - return call_utc_tzinfo_method(tzinfo, "utcoffset", tzinfoarg, none); -} - -/* Call tzinfo.name(tzinfoarg), and return the offset as a timedelta or None. - */ static PyObject * -offset_as_timedelta(PyObject *tzinfo, char *name, PyObject *tzinfoarg) { - PyObject *result; - - assert(tzinfo && name && tzinfoarg); - if (tzinfo == Py_None) { - result = Py_None; - Py_INCREF(result); - } - else { - int none; - int offset = call_utc_tzinfo_method(tzinfo, name, tzinfoarg, - &none); - if (offset < 0 && PyErr_Occurred()) - return NULL; - if (none) { - result = Py_None; - Py_INCREF(result); - } - else - result = new_delta(0, offset * 60, 0, 1); - } - return result; +call_utcoffset(PyObject *tzinfo, PyObject *tzinfoarg) +{ + return call_tzinfo_method(tzinfo, "utcoffset", tzinfoarg); } /* Call tzinfo.dst(tzinfoarg), and extract an integer from the @@ -989,10 +930,10 @@ * ValueError is raised and this returns -1. Else *none is set to 0 and * the offset is returned (as an int # of minutes east of UTC). */ -static int -call_dst(PyObject *tzinfo, PyObject *tzinfoarg, int *none) +static PyObject * +call_dst(PyObject *tzinfo, PyObject *tzinfoarg) { - return call_utc_tzinfo_method(tzinfo, "dst", tzinfoarg, none); + return call_tzinfo_method(tzinfo, "dst", tzinfoarg); } /* Call tzinfo.tzname(tzinfoarg), and return the result. tzinfo must be @@ -1010,102 +951,23 @@ assert(check_tzinfo_subclass(tzinfo) >= 0); assert(tzinfoarg != NULL); - if (tzinfo == Py_None) { - result = Py_None; - Py_INCREF(result); - } - else - result = PyObject_CallMethod(tzinfo, "tzname", "O", tzinfoarg); + if (tzinfo == Py_None) + Py_RETURN_NONE; - if (result != NULL && result != Py_None) { - if (!PyUnicode_Check(result)) { - PyErr_Format(PyExc_TypeError, "tzinfo.tzname() must " - "return None or a string, not '%s'", - Py_TYPE(result)->tp_name); - Py_DECREF(result); - result = NULL; - } - } - return result; -} + result = PyObject_CallMethod(tzinfo, "tzname", "O", tzinfoarg); -typedef enum { - /* an exception has been set; the caller should pass it on */ - OFFSET_ERROR, - - /* type isn't date, datetime, or time subclass */ - OFFSET_UNKNOWN, - - /* date, - * datetime with !hastzinfo - * datetime with None tzinfo, - * datetime where utcoffset() returns None - * time with !hastzinfo - * time with None tzinfo, - * time where utcoffset() returns None - */ - OFFSET_NAIVE, - - /* time or datetime where utcoffset() doesn't return None */ - OFFSET_AWARE -} naivety; - -/* Classify an object as to whether it's naive or offset-aware. See - * the "naivety" typedef for details. If the type is aware, *offset is set - * to minutes east of UTC (as returned by the tzinfo.utcoffset() method). - * If the type is offset-naive (or unknown, or error), *offset is set to 0. - * tzinfoarg is the argument to pass to the tzinfo.utcoffset() method. - */ -static naivety -classify_utcoffset(PyObject *op, PyObject *tzinfoarg, int *offset) -{ - int none; - PyObject *tzinfo; + if (result == NULL || result == Py_None) + return result; - assert(tzinfoarg != NULL); - *offset = 0; - tzinfo = get_tzinfo_member(op); /* NULL means no tzinfo, not error */ - if (tzinfo == Py_None) - return OFFSET_NAIVE; - if (tzinfo == NULL) { - /* note that a datetime passes the PyDate_Check test */ - return (PyTime_Check(op) || PyDate_Check(op)) ? - OFFSET_NAIVE : OFFSET_UNKNOWN; - } - *offset = call_utcoffset(tzinfo, tzinfoarg, &none); - if (*offset == -1 && PyErr_Occurred()) - return OFFSET_ERROR; - return none ? OFFSET_NAIVE : OFFSET_AWARE; -} - -/* Classify two objects as to whether they're naive or offset-aware. - * This isn't quite the same as calling classify_utcoffset() twice: for - * binary operations (comparison and subtraction), we generally want to - * ignore the tzinfo members if they're identical. This is by design, - * so that results match "naive" expectations when mixing objects from a - * single timezone. So in that case, this sets both offsets to 0 and - * both naiveties to OFFSET_NAIVE. - * The function returns 0 if everything's OK, and -1 on error. - */ -static int -classify_two_utcoffsets(PyObject *o1, int *offset1, naivety *n1, - PyObject *tzinfoarg1, - PyObject *o2, int *offset2, naivety *n2, - PyObject *tzinfoarg2) -{ - if (get_tzinfo_member(o1) == get_tzinfo_member(o2)) { - *offset1 = *offset2 = 0; - *n1 = *n2 = OFFSET_NAIVE; - } - else { - *n1 = classify_utcoffset(o1, tzinfoarg1, offset1); - if (*n1 == OFFSET_ERROR) - return -1; - *n2 = classify_utcoffset(o2, tzinfoarg2, offset2); - if (*n2 == OFFSET_ERROR) - return -1; + if (!PyUnicode_Check(result)) { + PyErr_Format(PyExc_TypeError, "tzinfo.tzname() must " + "return None or a string, not '%s'", + Py_TYPE(result)->tp_name); + Py_DECREF(result); + result = NULL; } - return 0; + + return result; } /* repr is like "someclass(arg1, arg2)". If tzinfo isn't None, @@ -1157,6 +1019,8 @@ GET_YEAR(date)); } +static PyObject *delta_negative(PyDateTime_Delta *self); + /* Add an hours & minutes UTC offset string to buf. buf has no more than * buflen bytes remaining. The UTC offset is gotten by calling * tzinfo.uctoffset(tzinfoarg). If that returns None, \0 is stored into @@ -1171,28 +1035,41 @@ format_utcoffset(char *buf, size_t buflen, const char *sep, PyObject *tzinfo, PyObject *tzinfoarg) { - int offset; - int hours; - int minutes; + PyObject *offset; + int hours, minutes, seconds; char sign; - int none; assert(buflen >= 1); - offset = call_utcoffset(tzinfo, tzinfoarg, &none); - if (offset == -1 && PyErr_Occurred()) + offset = call_utcoffset(tzinfo, tzinfoarg); + if (offset == NULL) return -1; - if (none) { + if (offset == Py_None) { + Py_DECREF(offset); *buf = '\0'; return 0; } - sign = '+'; - if (offset < 0) { + /* Offset is normalized, so it is negative if days < 0 */ + if (GET_TD_DAYS(offset) < 0) { + PyObject *temp = offset; sign = '-'; - offset = - offset; + offset = delta_negative((PyDateTime_Delta *)offset); + Py_DECREF(temp); + if (offset == NULL) + return -1; } - hours = divmod(offset, 60, &minutes); + else { + sign = '+'; + } + /* Offset is not negative here. */ + seconds = GET_TD_SECONDS(offset); + Py_DECREF(offset); + minutes = divmod(seconds, 60, &seconds); + hours = divmod(minutes, 60, &minutes); + assert(seconds == 0); + /* XXX ignore sub-minute data, curently not allowed. */ PyOS_snprintf(buf, buflen, "%c%02d%s%02d", sign, hours, sep, minutes); + return 0; } @@ -1434,7 +1311,7 @@ format = PyUnicode_FromString(PyBytes_AS_STRING(newfmt)); if (format != NULL) { result = PyObject_CallMethod(time, "strftime", "OO", - format, timetuple); + format, timetuple, NULL); Py_DECREF(format); } Py_DECREF(time); @@ -1937,17 +1814,24 @@ return result; } +static int +delta_cmp(PyObject *self, PyObject *other) +{ + int diff = GET_TD_DAYS(self) - GET_TD_DAYS(other); + if (diff == 0) { + diff = GET_TD_SECONDS(self) - GET_TD_SECONDS(other); + if (diff == 0) + diff = GET_TD_MICROSECONDS(self) - + GET_TD_MICROSECONDS(other); + } + return diff; +} + static PyObject * delta_richcompare(PyObject *self, PyObject *other, int op) { if (PyDelta_Check(other)) { - int diff = GET_TD_DAYS(self) - GET_TD_DAYS(other); - if (diff == 0) { - diff = GET_TD_SECONDS(self) - GET_TD_SECONDS(other); - if (diff == 0) - diff = GET_TD_MICROSECONDS(self) - - GET_TD_MICROSECONDS(other); - } + int diff = delta_cmp(self, other); return diff_to_bool(diff, op); } else { @@ -3119,76 +3003,73 @@ return tzinfo_nogo("dst"); } + +static PyObject *add_datetime_timedelta(PyDateTime_DateTime *date, + PyDateTime_Delta *delta, + int factor); +static PyObject *datetime_utcoffset(PyObject *self, PyObject *); +static PyObject *datetime_dst(PyObject *self, PyObject *); + static PyObject * -tzinfo_fromutc(PyDateTime_TZInfo *self, PyDateTime_DateTime *dt) +tzinfo_fromutc(PyDateTime_TZInfo *self, PyObject *dt) { - int y, m, d, hh, mm, ss, us; - - PyObject *result; - int off, dst; - int none; - int delta; + PyObject *result = NULL; + PyObject *off = NULL, *dst = NULL; + PyDateTime_Delta *delta = NULL; - if (! PyDateTime_Check(dt)) { + if (!PyDateTime_Check(dt)) { PyErr_SetString(PyExc_TypeError, "fromutc: argument must be a datetime"); return NULL; } - if (! HASTZINFO(dt) || dt->tzinfo != (PyObject *)self) { + if (GET_DT_TZINFO(dt) != (PyObject *)self) { PyErr_SetString(PyExc_ValueError, "fromutc: dt.tzinfo " "is not self"); return NULL; } - off = call_utcoffset(dt->tzinfo, (PyObject *)dt, &none); - if (off == -1 && PyErr_Occurred()) + off = datetime_utcoffset(dt, NULL); + if (off == NULL) return NULL; - if (none) { + if (off == Py_None) { PyErr_SetString(PyExc_ValueError, "fromutc: non-None " "utcoffset() result required"); - return NULL; + goto Fail; } - dst = call_dst(dt->tzinfo, (PyObject *)dt, &none); - if (dst == -1 && PyErr_Occurred()) - return NULL; - if (none) { + dst = datetime_dst(dt, NULL); + if (dst == NULL) + goto Fail; + if (dst == Py_None) { PyErr_SetString(PyExc_ValueError, "fromutc: non-None " "dst() result required"); - return NULL; + goto Fail; } - y = GET_YEAR(dt); - m = GET_MONTH(dt); - d = GET_DAY(dt); - hh = DATE_GET_HOUR(dt); - mm = DATE_GET_MINUTE(dt); - ss = DATE_GET_SECOND(dt); - us = DATE_GET_MICROSECOND(dt); - - delta = off - dst; - mm += delta; - if ((mm < 0 || mm >= 60) && - normalize_datetime(&y, &m, &d, &hh, &mm, &ss, &us) < 0) - return NULL; - result = new_datetime(y, m, d, hh, mm, ss, us, dt->tzinfo); + delta = (PyDateTime_Delta *)delta_subtract(off, dst); + if (delta == NULL) + goto Fail; + result = add_datetime_timedelta((PyDateTime_DateTime *)dt, delta, 1); if (result == NULL) - return result; - - dst = call_dst(dt->tzinfo, result, &none); - if (dst == -1 && PyErr_Occurred()) goto Fail; - if (none) - goto Inconsistent; - if (dst == 0) - return result; - mm += dst; - if ((mm < 0 || mm >= 60) && - normalize_datetime(&y, &m, &d, &hh, &mm, &ss, &us) < 0) + Py_DECREF(dst); + dst = call_dst(GET_DT_TZINFO(dt), result); + if (dst == NULL) goto Fail; - Py_DECREF(result); - result = new_datetime(y, m, d, hh, mm, ss, us, dt->tzinfo); + if (dst == Py_None) + goto Inconsistent; + if (delta_bool(delta) != 0) { + PyObject *temp = result; + result = add_datetime_timedelta((PyDateTime_DateTime *)result, + (PyDateTime_Delta *)dst, 1); + Py_DECREF(temp); + if (result == NULL) + goto Fail; + } + Py_DECREF(delta); + Py_DECREF(dst); + Py_DECREF(off); return result; Inconsistent: @@ -3197,7 +3078,10 @@ /* fall thru to failure */ Fail: - Py_DECREF(result); + Py_XDECREF(off); + Py_XDECREF(dst); + Py_XDECREF(delta); + Py_XDECREF(result); return NULL; } @@ -3464,18 +3348,14 @@ } static PyObject * -add_datetime_timedelta(PyDateTime_DateTime *date, PyDateTime_Delta *delta, - int factor); - -static PyObject * timezone_fromutc(PyDateTime_TimeZone *self, PyDateTime_DateTime *dt) { - if (! PyDateTime_Check(dt)) { + if (!PyDateTime_Check(dt)) { PyErr_SetString(PyExc_TypeError, "fromutc: argument must be a datetime"); return NULL; } - if (! HASTZINFO(dt) || dt->tzinfo != (PyObject *)self) { + if (!HASTZINFO(dt) || dt->tzinfo != (PyObject *)self) { PyErr_SetString(PyExc_ValueError, "fromutc: dt.tzinfo " "is not self"); return NULL; @@ -3689,21 +3569,18 @@ /* These are all METH_NOARGS, so don't need to check the arglist. */ static PyObject * -time_utcoffset(PyDateTime_Time *self, PyObject *unused) { - return offset_as_timedelta(HASTZINFO(self) ? self->tzinfo : Py_None, - "utcoffset", Py_None); +time_utcoffset(PyObject *self, PyObject *unused) { + return call_utcoffset(GET_TIME_TZINFO(self), Py_None); } static PyObject * -time_dst(PyDateTime_Time *self, PyObject *unused) { - return offset_as_timedelta(HASTZINFO(self) ? self->tzinfo : Py_None, - "dst", Py_None); +time_dst(PyObject *self, PyObject *unused) { + return call_dst(GET_TIME_TZINFO(self), Py_None); } static PyObject * time_tzname(PyDateTime_Time *self, PyObject *unused) { - return call_tzname(HASTZINFO(self) ? self->tzinfo : Py_None, - Py_None); + return call_tzname(GET_TIME_TZINFO(self), Py_None); } /* @@ -3758,7 +3635,7 @@ TIME_GET_MINUTE(self), TIME_GET_SECOND(self)); - if (result == NULL || ! HASTZINFO(self) || self->tzinfo == Py_None) + if (result == NULL || !HASTZINFO(self) || self->tzinfo == Py_None) return result; /* We need to append the UTC offset. */ @@ -3809,98 +3686,108 @@ static PyObject * time_richcompare(PyObject *self, PyObject *other, int op) { + PyObject *result = NULL; + PyObject *offset1, *offset2; int diff; - naivety n1, n2; - int offset1, offset2; if (! PyTime_Check(other)) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } - if (classify_two_utcoffsets(self, &offset1, &n1, Py_None, - other, &offset2, &n2, Py_None) < 0) + + if (GET_TIME_TZINFO(self) == GET_TIME_TZINFO(other)) { + diff = memcmp(((PyDateTime_Time *)self)->data, + ((PyDateTime_Time *)other)->data, + _PyDateTime_TIME_DATASIZE); + return diff_to_bool(diff, op); + } + offset1 = time_utcoffset(self, NULL); + if (offset1 == NULL) return NULL; - assert(n1 != OFFSET_UNKNOWN && n2 != OFFSET_UNKNOWN); + offset2 = time_utcoffset(other, NULL); + if (offset2 == NULL) + goto done; /* If they're both naive, or both aware and have the same offsets, * we get off cheap. Note that if they're both naive, offset1 == - * offset2 == 0 at this point. + * offset2 == Py_None at this point. */ - if (n1 == n2 && offset1 == offset2) { + if ((offset1 == offset2) || + (PyDelta_Check(offset1) && PyDelta_Check(offset2) && + delta_cmp(offset1, offset2) == 0)) { diff = memcmp(((PyDateTime_Time *)self)->data, ((PyDateTime_Time *)other)->data, _PyDateTime_TIME_DATASIZE); - return diff_to_bool(diff, op); + result = diff_to_bool(diff, op); } - - if (n1 == OFFSET_AWARE && n2 == OFFSET_AWARE) { - assert(offset1 != offset2); /* else last "if" handled it */ - /* Convert everything except microseconds to seconds. These - * can't overflow (no more than the # of seconds in 2 days). - */ - offset1 = TIME_GET_HOUR(self) * 3600 + - (TIME_GET_MINUTE(self) - offset1) * 60 + - TIME_GET_SECOND(self); - offset2 = TIME_GET_HOUR(other) * 3600 + - (TIME_GET_MINUTE(other) - offset2) * 60 + - TIME_GET_SECOND(other); - diff = offset1 - offset2; + /* The hard case: both aware with different UTC offsets */ + else if (offset1 != Py_None && offset2 != Py_None) { + int offsecs1, offsecs2; + assert(offset1 != offset2); /* else last "if" handled it */ + offsecs1 = TIME_GET_HOUR(self) * 3600 + + TIME_GET_MINUTE(self) * 60 + + TIME_GET_SECOND(self) - + GET_TD_DAYS(offset1) * 86400 - + GET_TD_SECONDS(offset1); + offsecs2 = TIME_GET_HOUR(other) * 3600 + + TIME_GET_MINUTE(other) * 60 + + TIME_GET_SECOND(other) - + GET_TD_DAYS(offset2) * 86400 - + GET_TD_SECONDS(offset2); + diff = offsecs1 - offsecs2; if (diff == 0) diff = TIME_GET_MICROSECOND(self) - TIME_GET_MICROSECOND(other); - return diff_to_bool(diff, op); + result = diff_to_bool(diff, op); } - - assert(n1 != n2); - PyErr_SetString(PyExc_TypeError, - "can't compare offset-naive and " - "offset-aware times"); - return NULL; + else { + PyErr_SetString(PyExc_TypeError, + "can't compare offset-naive and " + "offset-aware times"); + } + done: + Py_DECREF(offset1); + Py_XDECREF(offset2); + return result; } static long time_hash(PyDateTime_Time *self) { if (self->hashcode == -1) { - naivety n; - int offset; - PyObject *temp; - - n = classify_utcoffset((PyObject *)self, Py_None, &offset); - assert(n != OFFSET_UNKNOWN); - if (n == OFFSET_ERROR) + PyObject *offset; + + offset = time_utcoffset((PyObject *)self, NULL); + + if (offset == NULL) return -1; /* Reduce this to a hash of another object. */ - if (offset == 0) { + if (offset == Py_None) self->hashcode = generic_hash( (unsigned char *)self->data, _PyDateTime_TIME_DATASIZE); - return self->hashcode; - } else { - int hour; - int minute; - - assert(n == OFFSET_AWARE); + PyObject *temp1, *temp2; + int seconds, microseconds; assert(HASTZINFO(self)); - hour = divmod(TIME_GET_HOUR(self) * 60 + - TIME_GET_MINUTE(self) - offset, - 60, - &minute); - if (0 <= hour && hour < 24) - temp = new_time(hour, minute, - TIME_GET_SECOND(self), - TIME_GET_MICROSECOND(self), - Py_None); - else - temp = Py_BuildValue("iiii", - hour, minute, - TIME_GET_SECOND(self), - TIME_GET_MICROSECOND(self)); - } - if (temp != NULL) { - self->hashcode = PyObject_Hash(temp); - Py_DECREF(temp); + seconds = TIME_GET_HOUR(self) * 3600 + + TIME_GET_MINUTE(self) * 60 + + TIME_GET_SECOND(self); + microseconds = TIME_GET_MICROSECOND(self); + temp1 = new_delta(0, seconds, microseconds, 1); + if (temp1 == NULL) { + Py_DECREF(offset); + return -1; + } + temp2 = delta_subtract(temp1, offset); + Py_DECREF(temp1); + if (temp2 == NULL) { + Py_DECREF(offset); + return -1; + } + self->hashcode = PyObject_Hash(temp2); + Py_DECREF(temp2); } + Py_DECREF(offset); } return self->hashcode; } @@ -3929,10 +3816,10 @@ } static int -time_bool(PyDateTime_Time *self) +time_bool(PyObject *self) { - int offset; - int none; + PyObject *offset, *tzinfo; + int offsecs = 0; if (TIME_GET_SECOND(self) || TIME_GET_MICROSECOND(self)) { /* Since utcoffset is in whole minutes, nothing can @@ -3940,13 +3827,15 @@ */ return 1; } - offset = 0; - if (HASTZINFO(self) && self->tzinfo != Py_None) { - offset = call_utcoffset(self->tzinfo, Py_None, &none); - if (offset == -1 && PyErr_Occurred()) + tzinfo = GET_TIME_TZINFO(self); + if (tzinfo != Py_None) { + offset = call_utcoffset(tzinfo, Py_None); + if (offset == NULL) return -1; + offsecs = GET_TD_DAYS(offset)*86400 + GET_TD_SECONDS(offset); + Py_DECREF(offset); } - return (TIME_GET_MINUTE(self) - offset + TIME_GET_HOUR(self)*60) != 0; + return (TIME_GET_MINUTE(self)*60 - offsecs + TIME_GET_HOUR(self)*3600) != 0; } /* Pickle support, a simple use of __reduce__. */ @@ -4455,21 +4344,18 @@ /* These are all METH_NOARGS, so don't need to check the arglist. */ static PyObject * -datetime_utcoffset(PyDateTime_DateTime *self, PyObject *unused) { - return offset_as_timedelta(HASTZINFO(self) ? self->tzinfo : Py_None, - "utcoffset", (PyObject *)self); +datetime_utcoffset(PyObject *self, PyObject *unused) { + return call_utcoffset(GET_DT_TZINFO(self), self); } static PyObject * -datetime_dst(PyDateTime_DateTime *self, PyObject *unused) { - return offset_as_timedelta(HASTZINFO(self) ? self->tzinfo : Py_None, - "dst", (PyObject *)self); +datetime_dst(PyObject *self, PyObject *unused) { + return call_dst(GET_DT_TZINFO(self), self); } static PyObject * -datetime_tzname(PyDateTime_DateTime *self, PyObject *unused) { - return call_tzname(HASTZINFO(self) ? self->tzinfo : Py_None, - (PyObject *)self); +datetime_tzname(PyObject *self, PyObject *unused) { + return call_tzname(GET_DT_TZINFO(self), self); } /* @@ -4536,21 +4422,43 @@ /* datetime - ??? */ if (PyDateTime_Check(right)) { /* datetime - datetime */ - naivety n1, n2; - int offset1, offset2; + PyObject *offset1, *offset2, *offdiff = NULL; int delta_d, delta_s, delta_us; - if (classify_two_utcoffsets(left, &offset1, &n1, left, - right, &offset2, &n2, - right) < 0) - return NULL; - assert(n1 != OFFSET_UNKNOWN && n2 != OFFSET_UNKNOWN); - if (n1 != n2) { - PyErr_SetString(PyExc_TypeError, - "can't subtract offset-naive and " - "offset-aware datetimes"); - return NULL; + if (GET_DT_TZINFO(left) == GET_DT_TZINFO(right)) { + offset2 = offset1 = Py_None; + Py_INCREF(offset1); + Py_INCREF(offset2); } + else { + offset1 = datetime_utcoffset(left, NULL); + if (offset1 == NULL) + return NULL; + offset2 = datetime_utcoffset(right, NULL); + if (offset2 == NULL) { + Py_DECREF(offset1); + return NULL; + } + if ((offset1 != Py_None) != (offset2 != Py_None)) { + PyErr_SetString(PyExc_TypeError, + "can't subtract offset-naive and " + "offset-aware datetimes"); + Py_DECREF(offset1); + Py_DECREF(offset2); + return NULL; + } + } + if ((offset1 != offset2) && + delta_cmp(offset1, offset2) != 0) { + offdiff = delta_subtract(offset1, offset2); + if (offdiff == NULL) { + Py_DECREF(offset1); + Py_DECREF(offset2); + return NULL; + } + } + Py_DECREF(offset1); + Py_DECREF(offset2); delta_d = ymd_to_ord(GET_YEAR(left), GET_MONTH(left), GET_DAY(left)) - @@ -4569,11 +4477,13 @@ DATE_GET_SECOND(right)); delta_us = DATE_GET_MICROSECOND(left) - DATE_GET_MICROSECOND(right); - /* (left - offset1) - (right - offset2) = - * (left - right) + (offset2 - offset1) - */ - delta_s += (offset2 - offset1) * 60; result = new_delta(delta_d, delta_s, delta_us, 1); + if (offdiff != NULL) { + PyObject *temp = result; + result = delta_subtract(result, offdiff); + Py_DECREF(temp); + Py_DECREF(offdiff); + } } else if (PyDelta_Check(right)) { /* datetime - delta */ @@ -4683,9 +4593,9 @@ static PyObject * datetime_richcompare(PyObject *self, PyObject *other, int op) { + PyObject *result = NULL; + PyObject *offset1, *offset2; int diff; - naivety n1, n2; - int offset1, offset2; if (! PyDateTime_Check(other)) { if (PyDate_Check(other)) { @@ -4706,85 +4616,99 @@ return Py_NotImplemented; } - if (classify_two_utcoffsets(self, &offset1, &n1, self, - other, &offset2, &n2, other) < 0) + if (GET_DT_TZINFO(self) == GET_DT_TZINFO(other)) { + diff = memcmp(((PyDateTime_DateTime *)self)->data, + ((PyDateTime_DateTime *)other)->data, + _PyDateTime_DATETIME_DATASIZE); + return diff_to_bool(diff, op); + } + offset1 = datetime_utcoffset(self, NULL); + if (offset1 == NULL) return NULL; - assert(n1 != OFFSET_UNKNOWN && n2 != OFFSET_UNKNOWN); + offset2 = datetime_utcoffset(other, NULL); + if (offset2 == NULL) + goto done; /* If they're both naive, or both aware and have the same offsets, * we get off cheap. Note that if they're both naive, offset1 == - * offset2 == 0 at this point. + * offset2 == Py_None at this point. */ - if (n1 == n2 && offset1 == offset2) { + if ((offset1 == offset2) || + (PyDelta_Check(offset1) && PyDelta_Check(offset2) && + delta_cmp(offset1, offset2) == 0)) { diff = memcmp(((PyDateTime_DateTime *)self)->data, ((PyDateTime_DateTime *)other)->data, _PyDateTime_DATETIME_DATASIZE); - return diff_to_bool(diff, op); + result = diff_to_bool(diff, op); } - - if (n1 == OFFSET_AWARE && n2 == OFFSET_AWARE) { + else if (offset1 != Py_None && offset2 != Py_None) { PyDateTime_Delta *delta; - assert(offset1 != offset2); /* else last "if" handled it */ + assert(offset1 != offset2); /* else last "if" handled it */ delta = (PyDateTime_Delta *)datetime_subtract((PyObject *)self, other); if (delta == NULL) - return NULL; + goto done; diff = GET_TD_DAYS(delta); if (diff == 0) diff = GET_TD_SECONDS(delta) | GET_TD_MICROSECONDS(delta); Py_DECREF(delta); - return diff_to_bool(diff, op); + result = diff_to_bool(diff, op); } - - assert(n1 != n2); - PyErr_SetString(PyExc_TypeError, - "can't compare offset-naive and " - "offset-aware datetimes"); - return NULL; + else { + PyErr_SetString(PyExc_TypeError, + "can't compare offset-naive and " + "offset-aware datetimes"); + } + done: + Py_DECREF(offset1); + Py_XDECREF(offset2); + return result; } static long datetime_hash(PyDateTime_DateTime *self) { if (self->hashcode == -1) { - naivety n; - int offset; - PyObject *temp; - - n = classify_utcoffset((PyObject *)self, (PyObject *)self, - &offset); - assert(n != OFFSET_UNKNOWN); - if (n == OFFSET_ERROR) + PyObject *offset; + + offset = datetime_utcoffset((PyObject *)self, NULL); + + if (offset == NULL) return -1; /* Reduce this to a hash of another object. */ - if (n == OFFSET_NAIVE) { + if (offset == Py_None) self->hashcode = generic_hash( (unsigned char *)self->data, _PyDateTime_DATETIME_DATASIZE); - return self->hashcode; - } else { - int days; - int seconds; + PyObject *temp1, *temp2; + int days, seconds; - assert(n == OFFSET_AWARE); assert(HASTZINFO(self)); days = ymd_to_ord(GET_YEAR(self), GET_MONTH(self), GET_DAY(self)); seconds = DATE_GET_HOUR(self) * 3600 + - (DATE_GET_MINUTE(self) - offset) * 60 + + DATE_GET_MINUTE(self) * 60 + DATE_GET_SECOND(self); - temp = new_delta(days, - seconds, - DATE_GET_MICROSECOND(self), - 1); - } - if (temp != NULL) { - self->hashcode = PyObject_Hash(temp); - Py_DECREF(temp); + temp1 = new_delta(days, seconds, + DATE_GET_MICROSECOND(self), + 1); + if (temp1 == NULL) { + Py_DECREF(offset); + return -1; + } + temp2 = delta_subtract(temp1, offset); + Py_DECREF(temp1); + if (temp2 == NULL) { + Py_DECREF(offset); + return -1; + } + self->hashcode = PyObject_Hash(temp2); + Py_DECREF(temp2); } + Py_DECREF(offset); } return self->hashcode; } @@ -4819,10 +4743,9 @@ static PyObject * datetime_astimezone(PyDateTime_DateTime *self, PyObject *args, PyObject *kw) { - int y, m, d, hh, mm, ss, us; PyObject *result; - int offset, none; - + PyObject *offset; + PyObject *temp; PyObject *tzinfo; static char *keywords[] = {"tz", NULL}; @@ -4840,39 +4763,35 @@ } /* Convert self to UTC. */ - offset = call_utcoffset(self->tzinfo, (PyObject *)self, &none); - if (offset == -1 && PyErr_Occurred()) + offset = datetime_utcoffset((PyObject *)self, NULL); + if (offset == NULL) return NULL; - if (none) - goto NeedAware; + if (offset == Py_None) { + Py_DECREF(offset); + NeedAware: + PyErr_SetString(PyExc_ValueError, "astimezone() cannot be applied to " + "a naive datetime"); + return NULL; + } - y = GET_YEAR(self); - m = GET_MONTH(self); - d = GET_DAY(self); - hh = DATE_GET_HOUR(self); - mm = DATE_GET_MINUTE(self); - ss = DATE_GET_SECOND(self); - us = DATE_GET_MICROSECOND(self); - - mm -= offset; - if ((mm < 0 || mm >= 60) && - normalize_datetime(&y, &m, &d, &hh, &mm, &ss, &us) < 0) + /* result = self - offset */ + result = add_datetime_timedelta(self, + (PyDateTime_Delta *)offset, -1); + Py_DECREF(offset); + if (result == NULL) return NULL; /* Attach new tzinfo and let fromutc() do the rest. */ - result = new_datetime(y, m, d, hh, mm, ss, us, tzinfo); - if (result != NULL) { - PyObject *temp = result; + temp = ((PyDateTime_DateTime *)result)->tzinfo; + ((PyDateTime_DateTime *)result)->tzinfo = tzinfo; + Py_INCREF(tzinfo); + Py_DECREF(temp); - result = PyObject_CallMethod(tzinfo, "fromutc", "O", temp); - Py_DECREF(temp); - } - return result; + temp = result; + result = PyObject_CallMethod(tzinfo, "fromutc", "O", temp); + Py_DECREF(temp); -NeedAware: - PyErr_SetString(PyExc_ValueError, "astimezone() cannot be applied to " - "a naive datetime"); - return NULL; + return result; } static PyObject * @@ -4881,17 +4800,15 @@ int dstflag = -1; if (HASTZINFO(self) && self->tzinfo != Py_None) { - int none; + PyObject * dst; - dstflag = call_dst(self->tzinfo, (PyObject *)self, &none); - if (dstflag == -1 && PyErr_Occurred()) + dst = call_dst(self->tzinfo, (PyObject *)self); + if (dst == NULL) return NULL; - if (none) - dstflag = -1; - else if (dstflag != 0) - dstflag = 1; - + if (dst != Py_None) + dstflag = delta_bool((PyDateTime_Delta *)dst); + Py_DECREF(dst); } return build_struct_time(GET_YEAR(self), GET_MONTH(self), @@ -4927,41 +4844,47 @@ DATE_GET_MINUTE(self), DATE_GET_SECOND(self), DATE_GET_MICROSECOND(self), - HASTZINFO(self) ? self->tzinfo : Py_None); + GET_DT_TZINFO(self)); } static PyObject * datetime_utctimetuple(PyDateTime_DateTime *self) { - int y = GET_YEAR(self); - int m = GET_MONTH(self); - int d = GET_DAY(self); - int hh = DATE_GET_HOUR(self); - int mm = DATE_GET_MINUTE(self); - int ss = DATE_GET_SECOND(self); - int us = 0; /* microseconds are ignored in a timetuple */ - int offset = 0; - - if (HASTZINFO(self) && self->tzinfo != Py_None) { - int none; + int y, m, d, hh, mm, ss; + PyObject *tzinfo; + PyDateTime_DateTime *utcself; - offset = call_utcoffset(self->tzinfo, (PyObject *)self, &none); - if (offset == -1 && PyErr_Occurred()) - return NULL; + tzinfo = GET_DT_TZINFO(self); + if (tzinfo == Py_None) { + utcself = self; + Py_INCREF(utcself); } - /* Even if offset is 0, don't call timetuple() -- tm_isdst should be - * 0 in a UTC timetuple regardless of what dst() says. - */ - if (offset) { - /* Subtract offset minutes & normalize. */ - int stat; - - mm -= offset; - stat = normalize_datetime(&y, &m, &d, &hh, &mm, &ss, &us); - /* OverflowError may be raised in the edge cases. */ - if (stat < 0) + else { + PyObject *offset; + offset = call_utcoffset(tzinfo, (PyObject *)self); + if (offset == NULL) return NULL; + if (offset == Py_None) { + Py_DECREF(offset); + utcself = self; + Py_INCREF(utcself); + } + else { + utcself = (PyDateTime_DateTime *)add_datetime_timedelta(self, + (PyDateTime_Delta *)offset, -1); + Py_DECREF(offset); + if (utcself == NULL) + return NULL; + } } + y = GET_YEAR(utcself); + m = GET_MONTH(utcself); + d = GET_DAY(utcself); + hh = DATE_GET_HOUR(utcself); + mm = DATE_GET_MINUTE(utcself); + ss = DATE_GET_SECOND(utcself); + + Py_DECREF(utcself); return build_struct_time(y, m, d, hh, mm, ss, 0); } From python-checkins at python.org Thu Jul 8 02:13:56 2010 From: python-checkins at python.org (alexander.belopolsky) Date: Thu, 8 Jul 2010 02:13:56 +0200 (CEST) Subject: [Python-checkins] r82643 - sandbox/branches/py3k-datetime/datetime.py Message-ID: <20100708001356.90D75EEC05@mail.python.org> Author: alexander.belopolsky Date: Thu Jul 8 02:13:56 2010 New Revision: 82643 Log: Use named argument in timedelta. Modified: sandbox/branches/py3k-datetime/datetime.py Modified: sandbox/branches/py3k-datetime/datetime.py ============================================================================== --- sandbox/branches/py3k-datetime/datetime.py (original) +++ sandbox/branches/py3k-datetime/datetime.py Thu Jul 8 02:13:56 2010 @@ -208,8 +208,8 @@ offset = -offset sign = '-' h, m = divmod(offset, timedelta(hours=1)) - assert not m % timedelta(0, 60), "whole minute" - m //= timedelta(0, 60) + assert not m % timedelta(minutes=1), "whole minute" + m //= timedelta(minutes=1) zreplace = '%c%02d%02d' % (sign, h, m) assert '%' not in zreplace newformat.append(zreplace) @@ -256,7 +256,7 @@ if not isinstance(offset, timedelta): raise TypeError("tzinfo.%s() must return None " "or timedelta, not '%s'" % (name, type(offset))) - if offset % timedelta(0, 60) or offset.microseconds: + if offset % timedelta(minutes=1) or offset.microseconds: raise ValueError("tzinfo.%s() must return a whole number " "of minutes, got %s" % (name, offset)) if not -timedelta(1) < offset < timedelta(1): @@ -1119,8 +1119,8 @@ other._microsecond)) if myoff is None or otoff is None: raise TypeError("cannot compare naive and aware times") - myhhmm = self._hour * 60 + self._minute - myoff//timedelta(0, 60) - othhmm = other._hour * 60 + other._minute - otoff//timedelta(0, 60) + myhhmm = self._hour * 60 + self._minute - myoff//timedelta(minutes=1) + othhmm = other._hour * 60 + other._minute - otoff//timedelta(minutes=1) return _cmp((myhhmm, self._second, self._microsecond), (othhmm, other._second, other._microsecond)) @@ -1131,8 +1131,8 @@ return hash(self._getstate()[0]) h, m = divmod(timedelta(hours=self.hour, minutes=self.minute) - tzoff, timedelta(hours=1)) - assert not m % timedelta(0, 60), "whole minute" - m //= timedelta(0, 60) + assert not m % timedelta(minutes=1), "whole minute" + m //= timedelta(minutes=1) if 0 <= h < 24: return hash(time(h, m, self.second, self.microsecond)) return hash((h, m, self.second, self.microsecond)) @@ -1149,8 +1149,8 @@ else: sign = "+" hh, mm = divmod(off, timedelta(hours=1)) - assert not mm % timedelta(0, 60), "whole minute" - mm //= timedelta(0, 60) + assert not mm % timedelta(minutes=1), "whole minute" + mm //= timedelta(minutes=1) assert 0 <= hh < 24 off = "%s%02d%s%02d" % (sign, hh, sep, mm) return off @@ -1528,8 +1528,8 @@ else: sign = "+" hh, mm = divmod(off, timedelta(hours=1)) - assert not mm % timedelta(0, 60), "whole minute" - mm //= timedelta(0, 60) + assert not mm % timedelta(minutes=1), "whole minute" + mm //= timedelta(minutes=1) s += "%s%02d:%02d" % (sign, hh, mm) return s From nnorwitz at gmail.com Thu Jul 8 12:21:35 2010 From: nnorwitz at gmail.com (Neal Norwitz) Date: Thu, 8 Jul 2010 06:21:35 -0400 Subject: [Python-checkins] Python Regression Test Failures refleak (1) Message-ID: <20100708102135.GA16716@kbk-i386-bb.psfb.org> More important issues: ---------------------- test_bz2 leaked [-82, 0, 83] references, sum=1 Less important issues: ---------------------- From python-checkins at python.org Thu Jul 8 17:03:02 2010 From: python-checkins at python.org (ezio.melotti) Date: Thu, 8 Jul 2010 17:03:02 +0200 (CEST) Subject: [Python-checkins] r82644 - python/branches/py3k/Modules/mathmodule.c Message-ID: <20100708150302.3593BEED3B@mail.python.org> Author: ezio.melotti Date: Thu Jul 8 17:03:02 2010 New Revision: 82644 Log: Fix typo in a comment in mathmodule.c. Modified: python/branches/py3k/Modules/mathmodule.c Modified: python/branches/py3k/Modules/mathmodule.c ============================================================================== --- python/branches/py3k/Modules/mathmodule.c (original) +++ python/branches/py3k/Modules/mathmodule.c Thu Jul 8 17:03:02 2010 @@ -1170,7 +1170,7 @@ * http://www.luschny.de/math/factorial/binarysplitfact.html * * Faster algorithms exist, but they're more complicated and depend on - * a fast prime factoriazation algorithm. + * a fast prime factorization algorithm. * * Notes on the algorithm * ---------------------- From python-checkins at python.org Thu Jul 8 17:08:14 2010 From: python-checkins at python.org (ezio.melotti) Date: Thu, 8 Jul 2010 17:08:14 +0200 (CEST) Subject: [Python-checkins] r82645 - python/branches/release31-maint Message-ID: <20100708150814.DE317EED17@mail.python.org> Author: ezio.melotti Date: Thu Jul 8 17:08:14 2010 New Revision: 82645 Log: Blocked revisions 82644 via svnmerge ........ r82644 | ezio.melotti | 2010-07-08 18:03:02 +0300 (Thu, 08 Jul 2010) | 1 line Fix typo in a comment in mathmodule.c. ........ Modified: python/branches/release31-maint/ (props changed) From python-checkins at python.org Thu Jul 8 19:23:40 2010 From: python-checkins at python.org (mark.dickinson) Date: Thu, 8 Jul 2010 19:23:40 +0200 (CEST) Subject: [Python-checkins] r82646 - python/branches/py3k/Lib/test/test_decimal.py Message-ID: <20100708172340.89B91EEDB3@mail.python.org> Author: mark.dickinson Date: Thu Jul 8 19:23:40 2010 New Revision: 82646 Log: In test_decimal, convert heuristic for skipping tests into an explicit skiplist. Modified: python/branches/py3k/Lib/test/test_decimal.py Modified: python/branches/py3k/Lib/test/test_decimal.py ============================================================================== --- python/branches/py3k/Lib/test/test_decimal.py (original) +++ python/branches/py3k/Lib/test/test_decimal.py Thu Jul 8 19:23:40 2010 @@ -78,10 +78,41 @@ # list of individual .decTest test ids that correspond to tests that # we're skipping for one reason or another. -skipped_test_ids = [ - 'scbx164', # skipping apparently implementation-specific scaleb - 'scbx165', # tests, pending clarification of scaleb rules. -] +skipped_test_ids = set([ + # Skip implementation-specific scaleb tests. + 'scbx164', + 'scbx165', + + # For some operations (currently exp, ln, log10, power), the decNumber + # reference implementation imposes additional restrictions on the context + # and operands. These restrictions are not part of the specification; + # however, the effect of these restrictions does show up in some of the + # testcases. We skip testcases that violate these restrictions, since + # Decimal behaves differently from decNumber for these testcases so these + # testcases would otherwise fail. + 'expx901', + 'expx902', + 'expx903', + 'expx905', + 'lnx901', + 'lnx902', + 'lnx903', + 'lnx905', + 'logx901', + 'logx902', + 'logx903', + 'logx905', + 'powx1183', + 'powx1184', + 'powx4001', + 'powx4002', + 'powx4003', + 'powx4005', + 'powx4008', + 'powx4010', + 'powx4012', + 'powx4014', + ]) # Make sure it actually raises errors when not expected and caught in flags # Slower, since it runs some things several times. @@ -172,27 +203,6 @@ 'same_quantum', ) -# For some operations (currently exp, ln, log10, power), the decNumber -# reference implementation imposes additional restrictions on the -# context and operands. These restrictions are not part of the -# specification; however, the effect of these restrictions does show -# up in some of the testcases. We skip testcases that violate these -# restrictions, since Decimal behaves differently from decNumber for -# these testcases so these testcases would otherwise fail. - -decNumberRestricted = ('power', 'ln', 'log10', 'exp') -DEC_MAX_MATH = 999999 -def outside_decNumber_bounds(v, context): - if (context.prec > DEC_MAX_MATH or - context.Emax > DEC_MAX_MATH or - -context.Emin > DEC_MAX_MATH): - return True - if not v._is_special and v and ( - v.adjusted() > DEC_MAX_MATH or - v.adjusted() < 1-2*DEC_MAX_MATH): - return True - return False - class DecimalTest(unittest.TestCase): """Class which tests the Decimal class against the test cases. @@ -330,22 +340,6 @@ ans = FixQuotes(ans) - # skip tests that are related to bounds imposed in the decNumber - # reference implementation - if fname in decNumberRestricted: - if fname == 'power': - if not (vals[1]._isinteger() and - -1999999997 <= vals[1] <= 999999999): - if outside_decNumber_bounds(vals[0], self.context) or \ - outside_decNumber_bounds(vals[1], self.context): - #print "Skipping test %s" % s - return - else: - if outside_decNumber_bounds(vals[0], self.context): - #print "Skipping test %s" % s - return - - if EXTENDEDERRORTEST and fname not in ('to_sci_string', 'to_eng_string'): for error in theirexceptions: self.context.traps[error] = 1 From python-checkins at python.org Thu Jul 8 20:51:30 2010 From: python-checkins at python.org (antoine.pitrou) Date: Thu, 8 Jul 2010 20:51:30 +0200 (CEST) Subject: [Python-checkins] r82647 - in python/branches/py3k: Lib/test/test_gdb.py Misc/NEWS Message-ID: <20100708185130.670BCF061@mail.python.org> Author: antoine.pitrou Date: Thu Jul 8 20:51:30 2010 New Revision: 82647 Log: Issue #8605: Skip test_gdb if Python is compiled with optimizations. Modified: python/branches/py3k/Lib/test/test_gdb.py python/branches/py3k/Misc/NEWS Modified: python/branches/py3k/Lib/test/test_gdb.py ============================================================================== --- python/branches/py3k/Lib/test/test_gdb.py (original) +++ python/branches/py3k/Lib/test/test_gdb.py Thu Jul 8 20:51:30 2010 @@ -9,6 +9,7 @@ import sys import unittest import locale +import sysconfig from test.support import run_unittest, findfile @@ -664,6 +665,15 @@ r".*\na = 1\nb = 2\nc = 3\n.*") def test_main(): + cflags = sysconfig.get_config_vars()['PY_CFLAGS'] + final_opt = "" + for opt in cflags.split(): + if opt.startswith('-O'): + final_opt = opt + if final_opt and final_opt != '-O0': + raise unittest.SkipTest("Python was built with compiler optimizations, " + "tests can't reliably succeed") + run_unittest(PrettyPrintTests, PyListTests, StackNavigationTests, Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Thu Jul 8 20:51:30 2010 @@ -1614,6 +1614,8 @@ Tests ----- +- Issue #8605: Skip test_gdb if Python is compiled with optimizations. + - Issue #7449: Skip test_socketserver if threading support is disabled - Issue #8672: Add a zlib test ensuring that an incomplete stream can be From python-checkins at python.org Thu Jul 8 20:54:04 2010 From: python-checkins at python.org (antoine.pitrou) Date: Thu, 8 Jul 2010 20:54:04 +0200 (CEST) Subject: [Python-checkins] r82648 - in python/branches/release27-maint: Lib/test/test_gdb.py Misc/NEWS Message-ID: <20100708185404.46DFDF061@mail.python.org> Author: antoine.pitrou Date: Thu Jul 8 20:54:04 2010 New Revision: 82648 Log: Merged revisions 82647 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ........ r82647 | antoine.pitrou | 2010-07-08 20:51:30 +0200 (jeu., 08 juil. 2010) | 3 lines Issue #8605: Skip test_gdb if Python is compiled with optimizations. ........ Modified: python/branches/release27-maint/ (props changed) python/branches/release27-maint/Lib/test/test_gdb.py python/branches/release27-maint/Misc/NEWS Modified: python/branches/release27-maint/Lib/test/test_gdb.py ============================================================================== --- python/branches/release27-maint/Lib/test/test_gdb.py (original) +++ python/branches/release27-maint/Lib/test/test_gdb.py Thu Jul 8 20:54:04 2010 @@ -8,6 +8,7 @@ import subprocess import sys import unittest +import sysconfig from test.test_support import run_unittest, findfile @@ -678,6 +679,15 @@ r".*\na = 1\nb = 2\nc = 3\n.*") def test_main(): + cflags = sysconfig.get_config_vars()['PY_CFLAGS'] + final_opt = "" + for opt in cflags.split(): + if opt.startswith('-O'): + final_opt = opt + if final_opt and final_opt != '-O0': + raise unittest.SkipTest("Python was built with compiler optimizations, " + "tests can't reliably succeed") + run_unittest(PrettyPrintTests, PyListTests, StackNavigationTests, Modified: python/branches/release27-maint/Misc/NEWS ============================================================================== --- python/branches/release27-maint/Misc/NEWS (original) +++ python/branches/release27-maint/Misc/NEWS Thu Jul 8 20:54:04 2010 @@ -26,6 +26,11 @@ Extension Modules ----------------- +Tests +----- + +- Issue #8605: Skip test_gdb if Python is compiled with optimizations. + What's New in Python 2.7? ========================= From python-checkins at python.org Thu Jul 8 21:03:34 2010 From: python-checkins at python.org (mark.dickinson) Date: Thu, 8 Jul 2010 21:03:34 +0200 (CEST) Subject: [Python-checkins] r82649 - in python/branches/py3k: Lib/decimal.py Lib/test/decimaltestdata/extra.decTest Misc/NEWS Message-ID: <20100708190334.72A1DEE9BA@mail.python.org> Author: mark.dickinson Date: Thu Jul 8 21:03:34 2010 New Revision: 82649 Log: Fix a performance issue in Decimal.pow. Thanks Stefan Krah for finding this. Modified: python/branches/py3k/Lib/decimal.py python/branches/py3k/Lib/test/decimaltestdata/extra.decTest python/branches/py3k/Misc/NEWS Modified: python/branches/py3k/Lib/decimal.py ============================================================================== --- python/branches/py3k/Lib/decimal.py (original) +++ python/branches/py3k/Lib/decimal.py Thu Jul 8 21:03:34 2010 @@ -2047,12 +2047,14 @@ # case where xc == 1: result is 10**(xe*y), with xe*y # required to be an integer if xc == 1: - if ye >= 0: - exponent = xe*yc*10**ye - else: - exponent, remainder = divmod(xe*yc, 10**-ye) - if remainder: - return None + xe *= yc + # result is now 10**(xe * 10**ye); xe * 10**ye must be integral + while xe % 10 == 0: + xe //= 10 + ye += 1 + if ye < 0: + return None + exponent = xe * 10**ye if y.sign == 1: exponent = -exponent # if other is a nonnegative integer, use ideal exponent Modified: python/branches/py3k/Lib/test/decimaltestdata/extra.decTest ============================================================================== --- python/branches/py3k/Lib/test/decimaltestdata/extra.decTest (original) +++ python/branches/py3k/Lib/test/decimaltestdata/extra.decTest Thu Jul 8 21:03:34 2010 @@ -213,7 +213,20 @@ extr1659 shift 1234567 4 -> 0 extr1660 shift 1234567 5 -> NaN Invalid_operation +-- Cases where the power function was impossibly slow to determine that the +-- result is inexact. Thanks Stefan Krah for identifying this problem. +precision: 16 +maxExponent: 999999999 +minExponent: -999999999 +extr1700 power 10 1e-999999999 -> 1.000000000000000 Inexact Rounded +extr1701 power 100.0 -557.71e-742888888 -> 1.000000000000000 Inexact Rounded +extr1702 power 10 1e-100 -> 1.000000000000000 Inexact Rounded +-- A couple of interesting exact cases for power. Note that the specification +-- requires these to be reported as Inexact. +extr1710 power 1e375 56e-3 -> 1.000000000000000E+21 Inexact Rounded +extr1711 power 10000 0.75 -> 1000.000000000000 Inexact Rounded +extr1712 power 1e-24 0.875 -> 1.000000000000000E-21 Inexact Rounded -- Tests for the is_* boolean operations precision: 9 Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Thu Jul 8 21:03:34 2010 @@ -470,6 +470,10 @@ Library ------- +- Fix extreme speed issue in Decimal.pow when the base is an exact + power of 10 and the exponent is tiny (for example, + Decimal(10) ** Decimal('1e-999999999')). + - Issue #9186: Fix math.log1p(-1.0) to raise ValueError, not OverflowError. - Issue #9130: Fix validation of relative imports in parser module. From python-checkins at python.org Thu Jul 8 21:09:16 2010 From: python-checkins at python.org (mark.dickinson) Date: Thu, 8 Jul 2010 21:09:16 +0200 (CEST) Subject: [Python-checkins] r82650 - python/branches/py3k/Lib/decimal.py Message-ID: <20100708190916.F05BAEE9A3@mail.python.org> Author: mark.dickinson Date: Thu Jul 8 21:09:16 2010 New Revision: 82650 Log: Fix misplaced exactness check that was causing unnecessary work in Decimal.__pow__. Modified: python/branches/py3k/Lib/decimal.py Modified: python/branches/py3k/Lib/decimal.py ============================================================================== --- python/branches/py3k/Lib/decimal.py (original) +++ python/branches/py3k/Lib/decimal.py Thu Jul 8 21:09:16 2010 @@ -2327,9 +2327,10 @@ # try for an exact result with precision +1 if ans is None: ans = self._power_exact(other, context.prec + 1) - if ans is not None and result_sign == 1: - ans = _dec_from_triple(1, ans._int, ans._exp) - exact = True + if ans is not None: + if result_sign == 1: + ans = _dec_from_triple(1, ans._int, ans._exp) + exact = True # usual case: inexact result, x**y computed directly as exp(y*log(x)) if ans is None: From alexander.belopolsky at gmail.com Thu Jul 8 21:12:16 2010 From: alexander.belopolsky at gmail.com (Alexander Belopolsky) Date: Thu, 8 Jul 2010 15:12:16 -0400 Subject: [Python-checkins] r82646 - python/branches/py3k/Lib/test/test_decimal.py In-Reply-To: <20100708172340.89B91EEDB3@mail.python.org> References: <20100708172340.89B91EEDB3@mail.python.org> Message-ID: On Thu, Jul 8, 2010 at 1:23 PM, mark.dickinson wrote: .. > +skipped_test_ids = set([ .. Any reason for not using set literal here? From dickinsm at gmail.com Thu Jul 8 21:15:46 2010 From: dickinsm at gmail.com (Mark Dickinson) Date: Thu, 8 Jul 2010 20:15:46 +0100 Subject: [Python-checkins] r82646 - python/branches/py3k/Lib/test/test_decimal.py In-Reply-To: References: <20100708172340.89B91EEDB3@mail.python.org> Message-ID: On Thu, Jul 8, 2010 at 8:12 PM, Alexander Belopolsky wrote: > On Thu, Jul 8, 2010 at 1:23 PM, mark.dickinson > wrote: > .. >> +skipped_test_ids = set([ .. > > Any reason for not using set literal here? Yes; I'm planning to backport these fixes to 2.7, and it's been agreed that the 2.x version of decimal.py should remain compatible with Python 2.5. It's not 100% clear that that should also applies to test_decimal.py, but there's no point gratuitously breaking compatibility with Python 2.5 there either. I'm also considering backporting to 2.6, where set literals aren't available. :) Mark From dickinsm at gmail.com Thu Jul 8 21:19:26 2010 From: dickinsm at gmail.com (Mark Dickinson) Date: Thu, 8 Jul 2010 20:19:26 +0100 Subject: [Python-checkins] r82646 - python/branches/py3k/Lib/test/test_decimal.py In-Reply-To: References: <20100708172340.89B91EEDB3@mail.python.org> Message-ID: On Thu, Jul 8, 2010 at 8:15 PM, Mark Dickinson wrote: > with Python 2.5. ?It's not 100% clear that that should also applies to s/applies/apply/ > I'm also considering backporting to 2.6, where set literals aren't available. :) I just realised that this particular changeset looks more like a cleanup than a bugfix, so it's probably not clear to others why backporting is appropriate; my justification for the backport is that this changeset is needed to backport r82649, which *is* a bug. (The testcases for r82649 won't run without this change, since they get killed by the heuristic that this changeset removes.) Mark From python-checkins at python.org Thu Jul 8 21:21:59 2010 From: python-checkins at python.org (mark.dickinson) Date: Thu, 8 Jul 2010 21:21:59 +0200 (CEST) Subject: [Python-checkins] r82651 - in python/branches/release31-maint: Lib/decimal.py Lib/test/decimaltestdata/extra.decTest Lib/test/test_decimal.py Misc/NEWS Message-ID: <20100708192159.ABF04EEB85@mail.python.org> Author: mark.dickinson Date: Thu Jul 8 21:21:59 2010 New Revision: 82651 Log: Merged revisions 82646,82649-82650 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ........ r82646 | mark.dickinson | 2010-07-08 18:23:40 +0100 (Thu, 08 Jul 2010) | 1 line In test_decimal, convert heuristic for skipping tests into an explicit skiplist. ........ r82649 | mark.dickinson | 2010-07-08 20:03:34 +0100 (Thu, 08 Jul 2010) | 1 line Fix a performance issue in Decimal.pow. Thanks Stefan Krah for finding this. ........ r82650 | mark.dickinson | 2010-07-08 20:09:16 +0100 (Thu, 08 Jul 2010) | 1 line Fix misplaced exactness check that was causing unnecessary work in Decimal.__pow__. ........ Modified: python/branches/release31-maint/ (props changed) python/branches/release31-maint/Lib/decimal.py python/branches/release31-maint/Lib/test/decimaltestdata/extra.decTest python/branches/release31-maint/Lib/test/test_decimal.py python/branches/release31-maint/Misc/NEWS Modified: python/branches/release31-maint/Lib/decimal.py ============================================================================== --- python/branches/release31-maint/Lib/decimal.py (original) +++ python/branches/release31-maint/Lib/decimal.py Thu Jul 8 21:21:59 2010 @@ -2044,12 +2044,14 @@ # case where xc == 1: result is 10**(xe*y), with xe*y # required to be an integer if xc == 1: - if ye >= 0: - exponent = xe*yc*10**ye - else: - exponent, remainder = divmod(xe*yc, 10**-ye) - if remainder: - return None + xe *= yc + # result is now 10**(xe * 10**ye); xe * 10**ye must be integral + while xe % 10 == 0: + xe //= 10 + ye += 1 + if ye < 0: + return None + exponent = xe * 10**ye if y.sign == 1: exponent = -exponent # if other is a nonnegative integer, use ideal exponent @@ -2322,9 +2324,10 @@ # try for an exact result with precision +1 if ans is None: ans = self._power_exact(other, context.prec + 1) - if ans is not None and result_sign == 1: - ans = _dec_from_triple(1, ans._int, ans._exp) - exact = True + if ans is not None: + if result_sign == 1: + ans = _dec_from_triple(1, ans._int, ans._exp) + exact = True # usual case: inexact result, x**y computed directly as exp(y*log(x)) if ans is None: Modified: python/branches/release31-maint/Lib/test/decimaltestdata/extra.decTest ============================================================================== --- python/branches/release31-maint/Lib/test/decimaltestdata/extra.decTest (original) +++ python/branches/release31-maint/Lib/test/decimaltestdata/extra.decTest Thu Jul 8 21:21:59 2010 @@ -213,7 +213,20 @@ extr1659 shift 1234567 4 -> 0 extr1660 shift 1234567 5 -> NaN Invalid_operation +-- Cases where the power function was impossibly slow to determine that the +-- result is inexact. Thanks Stefan Krah for identifying this problem. +precision: 16 +maxExponent: 999999999 +minExponent: -999999999 +extr1700 power 10 1e-999999999 -> 1.000000000000000 Inexact Rounded +extr1701 power 100.0 -557.71e-742888888 -> 1.000000000000000 Inexact Rounded +extr1702 power 10 1e-100 -> 1.000000000000000 Inexact Rounded +-- A couple of interesting exact cases for power. Note that the specification +-- requires these to be reported as Inexact. +extr1710 power 1e375 56e-3 -> 1.000000000000000E+21 Inexact Rounded +extr1711 power 10000 0.75 -> 1000.000000000000 Inexact Rounded +extr1712 power 1e-24 0.875 -> 1.000000000000000E-21 Inexact Rounded -- Tests for the is_* boolean operations precision: 9 Modified: python/branches/release31-maint/Lib/test/test_decimal.py ============================================================================== --- python/branches/release31-maint/Lib/test/test_decimal.py (original) +++ python/branches/release31-maint/Lib/test/test_decimal.py Thu Jul 8 21:21:59 2010 @@ -71,10 +71,41 @@ # list of individual .decTest test ids that correspond to tests that # we're skipping for one reason or another. -skipped_test_ids = [ - 'scbx164', # skipping apparently implementation-specific scaleb - 'scbx165', # tests, pending clarification of scaleb rules. -] +skipped_test_ids = set([ + # Skip implementation-specific scaleb tests. + 'scbx164', + 'scbx165', + + # For some operations (currently exp, ln, log10, power), the decNumber + # reference implementation imposes additional restrictions on the context + # and operands. These restrictions are not part of the specification; + # however, the effect of these restrictions does show up in some of the + # testcases. We skip testcases that violate these restrictions, since + # Decimal behaves differently from decNumber for these testcases so these + # testcases would otherwise fail. + 'expx901', + 'expx902', + 'expx903', + 'expx905', + 'lnx901', + 'lnx902', + 'lnx903', + 'lnx905', + 'logx901', + 'logx902', + 'logx903', + 'logx905', + 'powx1183', + 'powx1184', + 'powx4001', + 'powx4002', + 'powx4003', + 'powx4005', + 'powx4008', + 'powx4010', + 'powx4012', + 'powx4014', + ]) # Make sure it actually raises errors when not expected and caught in flags # Slower, since it runs some things several times. @@ -165,27 +196,6 @@ 'same_quantum', ) -# For some operations (currently exp, ln, log10, power), the decNumber -# reference implementation imposes additional restrictions on the -# context and operands. These restrictions are not part of the -# specification; however, the effect of these restrictions does show -# up in some of the testcases. We skip testcases that violate these -# restrictions, since Decimal behaves differently from decNumber for -# these testcases so these testcases would otherwise fail. - -decNumberRestricted = ('power', 'ln', 'log10', 'exp') -DEC_MAX_MATH = 999999 -def outside_decNumber_bounds(v, context): - if (context.prec > DEC_MAX_MATH or - context.Emax > DEC_MAX_MATH or - -context.Emin > DEC_MAX_MATH): - return True - if not v._is_special and v and ( - v.adjusted() > DEC_MAX_MATH or - v.adjusted() < 1-2*DEC_MAX_MATH): - return True - return False - class DecimalTest(unittest.TestCase): """Class which tests the Decimal class against the test cases. @@ -323,22 +333,6 @@ ans = FixQuotes(ans) - # skip tests that are related to bounds imposed in the decNumber - # reference implementation - if fname in decNumberRestricted: - if fname == 'power': - if not (vals[1]._isinteger() and - -1999999997 <= vals[1] <= 999999999): - if outside_decNumber_bounds(vals[0], self.context) or \ - outside_decNumber_bounds(vals[1], self.context): - #print "Skipping test %s" % s - return - else: - if outside_decNumber_bounds(vals[0], self.context): - #print "Skipping test %s" % s - return - - if EXTENDEDERRORTEST and fname not in ('to_sci_string', 'to_eng_string'): for error in theirexceptions: self.context.traps[error] = 1 Modified: python/branches/release31-maint/Misc/NEWS ============================================================================== --- python/branches/release31-maint/Misc/NEWS (original) +++ python/branches/release31-maint/Misc/NEWS Thu Jul 8 21:21:59 2010 @@ -75,6 +75,10 @@ Library ------- +- Fix extreme speed issue in Decimal.pow when the base is an exact + power of 10 and the exponent is tiny (for example, + Decimal(10) ** Decimal('1e-999999999')). + - Issue #9130: Fix validation of relative imports in parser module. - Issue #9128: Fix validation of class decorators in parser module. From python-checkins at python.org Thu Jul 8 21:24:40 2010 From: python-checkins at python.org (mark.dickinson) Date: Thu, 8 Jul 2010 21:24:40 +0200 (CEST) Subject: [Python-checkins] r82652 - in python/branches/release27-maint: Lib/decimal.py Lib/test/decimaltestdata/extra.decTest Lib/test/test_decimal.py Misc/NEWS Message-ID: <20100708192440.DF5F3EE982@mail.python.org> Author: mark.dickinson Date: Thu Jul 8 21:24:40 2010 New Revision: 82652 Log: Merged revisions 82646,82649-82650 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ........ r82646 | mark.dickinson | 2010-07-08 18:23:40 +0100 (Thu, 08 Jul 2010) | 1 line In test_decimal, convert heuristic for skipping tests into an explicit skiplist. ........ r82649 | mark.dickinson | 2010-07-08 20:03:34 +0100 (Thu, 08 Jul 2010) | 1 line Fix a performance issue in Decimal.pow. Thanks Stefan Krah for finding this. ........ r82650 | mark.dickinson | 2010-07-08 20:09:16 +0100 (Thu, 08 Jul 2010) | 1 line Fix misplaced exactness check that was causing unnecessary work in Decimal.__pow__. ........ Modified: python/branches/release27-maint/ (props changed) python/branches/release27-maint/Lib/decimal.py python/branches/release27-maint/Lib/test/decimaltestdata/extra.decTest python/branches/release27-maint/Lib/test/test_decimal.py python/branches/release27-maint/Misc/NEWS Modified: python/branches/release27-maint/Lib/decimal.py ============================================================================== --- python/branches/release27-maint/Lib/decimal.py (original) +++ python/branches/release27-maint/Lib/decimal.py Thu Jul 8 21:24:40 2010 @@ -1990,12 +1990,14 @@ # case where xc == 1: result is 10**(xe*y), with xe*y # required to be an integer if xc == 1: - if ye >= 0: - exponent = xe*yc*10**ye - else: - exponent, remainder = divmod(xe*yc, 10**-ye) - if remainder: - return None + xe *= yc + # result is now 10**(xe * 10**ye); xe * 10**ye must be integral + while xe % 10 == 0: + xe //= 10 + ye += 1 + if ye < 0: + return None + exponent = xe * 10**ye if y.sign == 1: exponent = -exponent # if other is a nonnegative integer, use ideal exponent @@ -2268,9 +2270,10 @@ # try for an exact result with precision +1 if ans is None: ans = self._power_exact(other, context.prec + 1) - if ans is not None and result_sign == 1: - ans = _dec_from_triple(1, ans._int, ans._exp) - exact = True + if ans is not None: + if result_sign == 1: + ans = _dec_from_triple(1, ans._int, ans._exp) + exact = True # usual case: inexact result, x**y computed directly as exp(y*log(x)) if ans is None: Modified: python/branches/release27-maint/Lib/test/decimaltestdata/extra.decTest ============================================================================== --- python/branches/release27-maint/Lib/test/decimaltestdata/extra.decTest (original) +++ python/branches/release27-maint/Lib/test/decimaltestdata/extra.decTest Thu Jul 8 21:24:40 2010 @@ -213,7 +213,20 @@ extr1659 shift 1234567 4 -> 0 extr1660 shift 1234567 5 -> NaN Invalid_operation +-- Cases where the power function was impossibly slow to determine that the +-- result is inexact. Thanks Stefan Krah for identifying this problem. +precision: 16 +maxExponent: 999999999 +minExponent: -999999999 +extr1700 power 10 1e-999999999 -> 1.000000000000000 Inexact Rounded +extr1701 power 100.0 -557.71e-742888888 -> 1.000000000000000 Inexact Rounded +extr1702 power 10 1e-100 -> 1.000000000000000 Inexact Rounded +-- A couple of interesting exact cases for power. Note that the specification +-- requires these to be reported as Inexact. +extr1710 power 1e375 56e-3 -> 1.000000000000000E+21 Inexact Rounded +extr1711 power 10000 0.75 -> 1000.000000000000 Inexact Rounded +extr1712 power 1e-24 0.875 -> 1.000000000000000E-21 Inexact Rounded -- Tests for the is_* boolean operations precision: 9 Modified: python/branches/release27-maint/Lib/test/test_decimal.py ============================================================================== --- python/branches/release27-maint/Lib/test/test_decimal.py (original) +++ python/branches/release27-maint/Lib/test/test_decimal.py Thu Jul 8 21:24:40 2010 @@ -77,10 +77,41 @@ # list of individual .decTest test ids that correspond to tests that # we're skipping for one reason or another. -skipped_test_ids = [ - 'scbx164', # skipping apparently implementation-specific scaleb - 'scbx165', # tests, pending clarification of scaleb rules. -] +skipped_test_ids = set([ + # Skip implementation-specific scaleb tests. + 'scbx164', + 'scbx165', + + # For some operations (currently exp, ln, log10, power), the decNumber + # reference implementation imposes additional restrictions on the context + # and operands. These restrictions are not part of the specification; + # however, the effect of these restrictions does show up in some of the + # testcases. We skip testcases that violate these restrictions, since + # Decimal behaves differently from decNumber for these testcases so these + # testcases would otherwise fail. + 'expx901', + 'expx902', + 'expx903', + 'expx905', + 'lnx901', + 'lnx902', + 'lnx903', + 'lnx905', + 'logx901', + 'logx902', + 'logx903', + 'logx905', + 'powx1183', + 'powx1184', + 'powx4001', + 'powx4002', + 'powx4003', + 'powx4005', + 'powx4008', + 'powx4010', + 'powx4012', + 'powx4014', + ]) # Make sure it actually raises errors when not expected and caught in flags # Slower, since it runs some things several times. @@ -171,27 +202,6 @@ 'same_quantum', ) -# For some operations (currently exp, ln, log10, power), the decNumber -# reference implementation imposes additional restrictions on the -# context and operands. These restrictions are not part of the -# specification; however, the effect of these restrictions does show -# up in some of the testcases. We skip testcases that violate these -# restrictions, since Decimal behaves differently from decNumber for -# these testcases so these testcases would otherwise fail. - -decNumberRestricted = ('power', 'ln', 'log10', 'exp') -DEC_MAX_MATH = 999999 -def outside_decNumber_bounds(v, context): - if (context.prec > DEC_MAX_MATH or - context.Emax > DEC_MAX_MATH or - -context.Emin > DEC_MAX_MATH): - return True - if not v._is_special and v and ( - v.adjusted() > DEC_MAX_MATH or - v.adjusted() < 1-2*DEC_MAX_MATH): - return True - return False - class DecimalTest(unittest.TestCase): """Class which tests the Decimal class against the test cases. @@ -329,22 +339,6 @@ ans = FixQuotes(ans) - # skip tests that are related to bounds imposed in the decNumber - # reference implementation - if fname in decNumberRestricted: - if fname == 'power': - if not (vals[1]._isinteger() and - -1999999997 <= vals[1] <= 999999999): - if outside_decNumber_bounds(vals[0], self.context) or \ - outside_decNumber_bounds(vals[1], self.context): - #print "Skipping test %s" % s - return - else: - if outside_decNumber_bounds(vals[0], self.context): - #print "Skipping test %s" % s - return - - if EXTENDEDERRORTEST and fname not in ('to_sci_string', 'to_eng_string'): for error in theirexceptions: self.context.traps[error] = 1 Modified: python/branches/release27-maint/Misc/NEWS ============================================================================== --- python/branches/release27-maint/Misc/NEWS (original) +++ python/branches/release27-maint/Misc/NEWS Thu Jul 8 21:24:40 2010 @@ -515,6 +515,10 @@ - Issue #8329: Don't return the same lists from select.select when no fds are changed. +- Fix extreme speed issue in Decimal.pow when the base is an exact + power of 10 and the exponent is tiny (for example, + Decimal(10) ** Decimal('1e-999999999')). + - Issue #8259: ``1L << (2**31)`` no longer produces an 'outrageous shift error' on 64-bit machines. The shift count for either left or right shift is permitted to be up to sys.maxsize. From python-checkins at python.org Thu Jul 8 21:27:24 2010 From: python-checkins at python.org (mark.dickinson) Date: Thu, 8 Jul 2010 21:27:24 +0200 (CEST) Subject: [Python-checkins] r82653 - in python/branches/release26-maint: Lib/decimal.py Lib/test/decimaltestdata/extra.decTest Lib/test/test_decimal.py Misc/NEWS Message-ID: <20100708192724.3E568EEAF1@mail.python.org> Author: mark.dickinson Date: Thu Jul 8 21:27:24 2010 New Revision: 82653 Log: Fix Decimal speed issue; backport of r82652 from release27-maint. Modified: python/branches/release26-maint/Lib/decimal.py python/branches/release26-maint/Lib/test/decimaltestdata/extra.decTest python/branches/release26-maint/Lib/test/test_decimal.py python/branches/release26-maint/Misc/NEWS Modified: python/branches/release26-maint/Lib/decimal.py ============================================================================== --- python/branches/release26-maint/Lib/decimal.py (original) +++ python/branches/release26-maint/Lib/decimal.py Thu Jul 8 21:27:24 2010 @@ -1918,12 +1918,14 @@ # case where xc == 1: result is 10**(xe*y), with xe*y # required to be an integer if xc == 1: - if ye >= 0: - exponent = xe*yc*10**ye - else: - exponent, remainder = divmod(xe*yc, 10**-ye) - if remainder: - return None + xe *= yc + # result is now 10**(xe * 10**ye); xe * 10**ye must be integral + while xe % 10 == 0: + xe //= 10 + ye += 1 + if ye < 0: + return None + exponent = xe * 10**ye if y.sign == 1: exponent = -exponent # if other is a nonnegative integer, use ideal exponent @@ -2196,9 +2198,10 @@ # try for an exact result with precision +1 if ans is None: ans = self._power_exact(other, context.prec + 1) - if ans is not None and result_sign == 1: - ans = _dec_from_triple(1, ans._int, ans._exp) - exact = True + if ans is not None: + if result_sign == 1: + ans = _dec_from_triple(1, ans._int, ans._exp) + exact = True # usual case: inexact result, x**y computed directly as exp(y*log(x)) if ans is None: Modified: python/branches/release26-maint/Lib/test/decimaltestdata/extra.decTest ============================================================================== --- python/branches/release26-maint/Lib/test/decimaltestdata/extra.decTest (original) +++ python/branches/release26-maint/Lib/test/decimaltestdata/extra.decTest Thu Jul 8 21:27:24 2010 @@ -213,7 +213,20 @@ extr1659 shift 1234567 4 -> 0 extr1660 shift 1234567 5 -> NaN Invalid_operation +-- Cases where the power function was impossibly slow to determine that the +-- result is inexact. Thanks Stefan Krah for identifying this problem. +precision: 16 +maxExponent: 999999999 +minExponent: -999999999 +extr1700 power 10 1e-999999999 -> 1.000000000000000 Inexact Rounded +extr1701 power 100.0 -557.71e-742888888 -> 1.000000000000000 Inexact Rounded +extr1702 power 10 1e-100 -> 1.000000000000000 Inexact Rounded +-- A couple of interesting exact cases for power. Note that the specification +-- requires these to be reported as Inexact. +extr1710 power 1e375 56e-3 -> 1.000000000000000E+21 Inexact Rounded +extr1711 power 10000 0.75 -> 1000.000000000000 Inexact Rounded +extr1712 power 1e-24 0.875 -> 1.000000000000000E-21 Inexact Rounded -- Tests for the is_* boolean operations precision: 9 Modified: python/branches/release26-maint/Lib/test/test_decimal.py ============================================================================== --- python/branches/release26-maint/Lib/test/test_decimal.py (original) +++ python/branches/release26-maint/Lib/test/test_decimal.py Thu Jul 8 21:27:24 2010 @@ -72,10 +72,41 @@ # list of individual .decTest test ids that correspond to tests that # we're skipping for one reason or another. -skipped_test_ids = [ - 'scbx164', # skipping apparently implementation-specific scaleb - 'scbx165', # tests, pending clarification of scaleb rules. -] +skipped_test_ids = set([ + # Skip implementation-specific scaleb tests. + 'scbx164', + 'scbx165', + + # For some operations (currently exp, ln, log10, power), the decNumber + # reference implementation imposes additional restrictions on the context + # and operands. These restrictions are not part of the specification; + # however, the effect of these restrictions does show up in some of the + # testcases. We skip testcases that violate these restrictions, since + # Decimal behaves differently from decNumber for these testcases so these + # testcases would otherwise fail. + 'expx901', + 'expx902', + 'expx903', + 'expx905', + 'lnx901', + 'lnx902', + 'lnx903', + 'lnx905', + 'logx901', + 'logx902', + 'logx903', + 'logx905', + 'powx1183', + 'powx1184', + 'powx4001', + 'powx4002', + 'powx4003', + 'powx4005', + 'powx4008', + 'powx4010', + 'powx4012', + 'powx4014', + ]) # Make sure it actually raises errors when not expected and caught in flags # Slower, since it runs some things several times. @@ -166,27 +197,6 @@ 'same_quantum', ) -# For some operations (currently exp, ln, log10, power), the decNumber -# reference implementation imposes additional restrictions on the -# context and operands. These restrictions are not part of the -# specification; however, the effect of these restrictions does show -# up in some of the testcases. We skip testcases that violate these -# restrictions, since Decimal behaves differently from decNumber for -# these testcases so these testcases would otherwise fail. - -decNumberRestricted = ('power', 'ln', 'log10', 'exp') -DEC_MAX_MATH = 999999 -def outside_decNumber_bounds(v, context): - if (context.prec > DEC_MAX_MATH or - context.Emax > DEC_MAX_MATH or - -context.Emin > DEC_MAX_MATH): - return True - if not v._is_special and v and ( - v.adjusted() > DEC_MAX_MATH or - v.adjusted() < 1-2*DEC_MAX_MATH): - return True - return False - class DecimalTest(unittest.TestCase): """Class which tests the Decimal class against the test cases. @@ -324,22 +334,6 @@ ans = FixQuotes(ans) - # skip tests that are related to bounds imposed in the decNumber - # reference implementation - if fname in decNumberRestricted: - if fname == 'power': - if not (vals[1]._isinteger() and - -1999999997 <= vals[1] <= 999999999): - if outside_decNumber_bounds(vals[0], self.context) or \ - outside_decNumber_bounds(vals[1], self.context): - #print "Skipping test %s" % s - return - else: - if outside_decNumber_bounds(vals[0], self.context): - #print "Skipping test %s" % s - return - - if EXTENDEDERRORTEST and fname not in ('to_sci_string', 'to_eng_string'): for error in theirexceptions: self.context.traps[error] = 1 Modified: python/branches/release26-maint/Misc/NEWS ============================================================================== --- python/branches/release26-maint/Misc/NEWS (original) +++ python/branches/release26-maint/Misc/NEWS Thu Jul 8 21:27:24 2010 @@ -81,6 +81,10 @@ Library ------- +- Fix extreme speed issue in Decimal.pow when the base is an exact + power of 10 and the exponent is tiny (for example, + Decimal(10) ** Decimal('1e-999999999')). + - Issue #9130: Fix validation of relative imports in parser module. - Issue #9128: Fix validation of class decorators in parser module. From nnorwitz at gmail.com Thu Jul 8 22:58:57 2010 From: nnorwitz at gmail.com (Neal Norwitz) Date: Thu, 8 Jul 2010 16:58:57 -0400 Subject: [Python-checkins] Python Regression Test Failures opt (1) Message-ID: <20100708205857.GA3289@kbk-i386-bb.psfb.org> 346 tests OK. 1 test failed: test_subprocess 37 tests skipped: test_aepack test_al test_applesingle test_bsddb185 test_bsddb3 test_cd test_cl test_curses test_epoll test_gdb test_gl test_imgfile test_ioctl test_kqueue test_linuxaudiodev test_macos test_macostools test_multiprocessing test_ossaudiodev test_pep277 test_py3kwarn test_scriptpackages test_smtpnet test_socketserver test_startfile test_sunaudiodev test_tcl test_timeout test_tk test_ttk_guionly test_ttk_textonly test_unicode_file test_urllib2net test_urllibnet test_winreg test_winsound test_zipfile64 7 skips unexpected on linux2: test_epoll test_gdb test_ioctl test_multiprocessing test_tk test_ttk_guionly test_ttk_textonly == CPython 2.7 (trunk:82653M, Jul 8 2010, 16:04:57) [GCC 3.3.4 20040623 (Gentoo Linux 3.3.4-r1, ssp-3.3.2-2, pie-8.7.6)] == Linux-2.6.9-gentoo-r1-i686-AMD_Athlon-tm-_XP_3000+-with-gentoo-1.4.16 little-endian == /tmp/test_python_21001 test_grammar test_opcodes test_dict test_builtin test_exceptions test_types test_unittest test_doctest test_doctest2 test_MimeWriter test_SimpleHTTPServer test_StringIO test___all__ test___future__ test__locale test_abc test_abstract_numbers test_aepack test_aepack skipped -- No module named aetypes test_aifc test_al test_al skipped -- No module named al test_anydbm test_applesingle test_applesingle skipped -- No module named MacOS test_argparse test_array test_ascii_formatd test_ast test_asynchat test_asyncore test_atexit test_audioop test_augassign test_base64 test_bastion test_bigaddrspace test_bigmem test_binascii test_binhex test_binop test_bisect test_bool test_bsddb test_bsddb185 test_bsddb185 skipped -- No module named bsddb185 test_bsddb3 test_bsddb3 skipped -- Use of the `bsddb' resource not enabled test_buffer test_bufio test_bytes test_bz2 test_calendar test_call test_capi test_cd test_cd skipped -- No module named cd test_cfgparser test_cgi test_charmapcodec test_cl test_cl skipped -- No module named cl test_class test_cmath test_cmd test_cmd_line test_cmd_line_script test_code test_codeccallbacks test_codecencodings_cn test_codecencodings_hk test_codecencodings_jp test_codecencodings_kr test_codecencodings_tw test_codecmaps_cn test_codecmaps_hk test_codecmaps_jp test_codecmaps_kr test_codecmaps_tw test_codecs test_codeop test_coding test_coercion test_collections test_colorsys test_commands test_compare test_compile test_compileall test_compiler test_complex test_complex_args test_contains test_contextlib test_cookie test_cookielib test_copy test_copy_reg test_cpickle test_cprofile test_crypt test_csv test_ctypes test_curses test_curses skipped -- Use of the `curses' resource not enabled test_datetime test_dbm test_decimal test_decorators test_defaultdict test_deque test_descr test_descrtut test_dictcomps test_dictviews test_difflib test_dircache test_dis test_distutils [19646 refs] [19646 refs] [19646 refs] [19646 refs] [19643 refs] test_dl test_docxmlrpc test_dumbdbm test_dummy_thread test_dummy_threading test_email test_email_codecs test_email_renamed test_enumerate test_eof test_epoll test_epoll skipped -- kernel doesn't support epoll() test_errno test_exception_variations test_extcall test_fcntl test_file test_file2k test_filecmp test_fileinput test_fileio test_float test_fnmatch test_fork1 test_format test_fpformat test_fractions test_frozen test_ftplib test_funcattrs test_functools test_future test_future3 test_future4 test_future5 test_future_builtins test_gc test_gdb test_gdb skipped -- gdb versions before 7.0 didn't support python embedding Saw: GNU gdb 6.2.1 Copyright 2004 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i386-pc-linux-gnu". test_gdbm test_generators test_genericpath test_genexps test_getargs test_getargs2 test_getopt test_gettext test_gl test_gl skipped -- No module named gl test_glob test_global test_grp test_gzip test_hash test_hashlib test_heapq test_hmac test_hotshot test_htmllib test_htmlparser test_httplib test_httpservers [15648 refs] [15648 refs] [15648 refs] [25315 refs] test_imageop test_imaplib test_imgfile test_imgfile skipped -- No module named imgfile test_imp test_import test_importhooks test_importlib test_index test_inspect test_int test_int_literal test_io test_ioctl test_ioctl skipped -- Unable to open /dev/tty test_isinstance test_iter test_iterlen test_itertools test_json test_kqueue test_kqueue skipped -- test works only on BSD test_largefile test_lib2to3 test_linecache test_linuxaudiodev test_linuxaudiodev skipped -- Use of the `audio' resource not enabled test_list test_locale test_logging test_long test_long_future test_longexp test_macos test_macos skipped -- No module named MacOS test_macostools test_macostools skipped -- No module named MacOS test_macpath test_mailbox test_marshal test_math test_md5 test_memoryio test_memoryview test_mhlib test_mimetools test_mimetypes test_minidom test_mmap test_module test_modulefinder test_multibytecodec test_multibytecodec_support test_multifile test_multiprocessing test_multiprocessing skipped -- This platform lacks a functioning sem_open implementation, therefore, the required synchronization primitives needed will not function, see issue 3770. test_mutants test_mutex test_netrc test_new test_nis test_normalization test_ntpath test_old_mailbox test_openpty test_operator test_optparse test_os [15648 refs] [15648 refs] test_ossaudiodev test_ossaudiodev skipped -- Use of the `audio' resource not enabled test_parser Expecting 's_push: parser stack overflow' in next line s_push: parser stack overflow test_pdb test_peepholer test_pep247 test_pep263 test_pep277 test_pep277 skipped -- only NT+ and systems with Unicode-friendly filesystem encoding test_pep292 test_pep352 test_pickle test_pickletools test_pipes test_pkg test_pkgimport test_pkgutil test_platform [17044 refs] [17044 refs] test_plistlib test_poll test_popen [15653 refs] [15653 refs] [15653 refs] test_popen2 test_poplib test_posix test_posixpath test_pow test_pprint test_print test_profile test_profilehooks test_property test_pstats test_pty test_pwd test_py3kwarn test_py3kwarn skipped -- test.test_py3kwarn must be run with the -3 flag test_pyclbr test_pydoc [20862 refs] [20862 refs] [20862 refs] [20862 refs] [20862 refs] [20861 refs] [20861 refs] test_pyexpat test_queue test_quopri [18479 refs] [18479 refs] test_random test_re test_readline test_repr test_resource test_rfc822 test_richcmp test_robotparser test_runpy test_sax test_scope test_scriptpackages test_scriptpackages skipped -- No module named aetools test_select test_set test_setcomps test_sets test_sgmllib test_sha test_shelve test_shlex test_shutil test_signal test_site [15648 refs] [15648 refs] [15648 refs] [15648 refs] test_slice test_smtplib test_smtpnet test_smtpnet skipped -- Use of the `network' resource not enabled test_socket test_socketserver test_socketserver skipped -- Use of the `network' resource not enabled test_softspace test_sort test_sqlite test_ssl test_startfile test_startfile skipped -- module os has no attribute startfile test_str test_strftime test_string test_stringprep test_strop test_strptime test_strtod test_struct test_structmembers test_structseq test_subprocess [15648 refs] [15648 refs] [15648 refs] [15648 refs] [15648 refs] [15648 refs] [15648 refs] [15648 refs] [15648 refs] [15648 refs] [15648 refs] [15648 refs] [15648 refs] [15648 refs] [15863 refs] [15648 refs] [15648 refs] [15648 refs] [15648 refs] [15648 refs] . [15648 refs] [15648 refs] this bit of output is from a test of stdout in a different process ... [15648 refs] [15648 refs] [15863 refs] [15648 refs] [15648 refs] [15648 refs] p.send_signal(2,) succeeded after 2 attempts [15648 refs] [15648 refs] [15648 refs] [15648 refs] [15648 refs] [15648 refs] [15648 refs] [15648 refs] [15648 refs] [15648 refs] [15648 refs] [15648 refs] [15648 refs] [15648 refs] [15863 refs] [15648 refs] [15648 refs] [15648 refs] [15648 refs] [15648 refs] . [15648 refs] [15648 refs] this bit of output is from a test of stdout in a different process ... [15648 refs] [15648 refs] [15863 refs] test test_subprocess failed -- multiple errors occurred; run in verbose mode for details Re-running test 'test_subprocess' in verbose mode test_call_kwargs (test.test_subprocess.ProcessTestCase) ... [15648 refs] ERROR test_call_seq (test.test_subprocess.ProcessTestCase) ... [15648 refs] ERROR test_check_call_nonzero (test.test_subprocess.ProcessTestCase) ... [15648 refs] ERROR test_check_call_zero (test.test_subprocess.ProcessTestCase) ... [15648 refs] ERROR test_check_output (test.test_subprocess.ProcessTestCase) ... [15648 refs] ERROR test_check_output_nonzero (test.test_subprocess.ProcessTestCase) ... [15648 refs] ERROR test_check_output_stderr (test.test_subprocess.ProcessTestCase) ... ERROR test_check_output_stdout_arg (test.test_subprocess.ProcessTestCase) ... ERROR test_communicate (test.test_subprocess.ProcessTestCase) ... ERROR test_communicate_pipe_buf (test.test_subprocess.ProcessTestCase) ... ERROR test_communicate_pipe_fd_leak (test.test_subprocess.ProcessTestCase) ... [15648 refs] ERROR test_communicate_returns (test.test_subprocess.ProcessTestCase) ... [15648 refs] ERROR test_communicate_stderr (test.test_subprocess.ProcessTestCase) ... ERROR test_communicate_stdin (test.test_subprocess.ProcessTestCase) ... [15648 refs] ERROR test_communicate_stdout (test.test_subprocess.ProcessTestCase) ... [15648 refs] ERROR test_cwd (test.test_subprocess.ProcessTestCase) ... [15648 refs] ERROR test_env (test.test_subprocess.ProcessTestCase) ... [15648 refs] ERROR test_executable_with_cwd (test.test_subprocess.ProcessTestCase) ... [15648 refs] ERROR test_executable_without_cwd (test.test_subprocess.ProcessTestCase) ... [15648 refs] ERROR test_invalid_bufsize (test.test_subprocess.ProcessTestCase) ... ERROR test_leaking_fds_on_error (test.test_subprocess.ProcessTestCase) ... ERROR test_list2cmdline (test.test_subprocess.ProcessTestCase) ... ERROR test_no_leaking (test.test_subprocess.ProcessTestCase) ... ERROR test_poll (test.test_subprocess.ProcessTestCase) ... [15863 refs] ERROR test_stderr_filedes (test.test_subprocess.ProcessTestCase) ... ERROR test_stderr_fileobj (test.test_subprocess.ProcessTestCase) ... ERROR test_stderr_none (test.test_subprocess.ProcessTestCase) ... [15648 refs] ERROR test_stderr_pipe (test.test_subprocess.ProcessTestCase) ... ERROR test_stdin_filedes (test.test_subprocess.ProcessTestCase) ... [15648 refs] ERROR test_stdin_fileobj (test.test_subprocess.ProcessTestCase) ... [15648 refs] ERROR test_stdin_none (test.test_subprocess.ProcessTestCase) ... ERROR test_stdin_pipe (test.test_subprocess.ProcessTestCase) ... [15648 refs] ERROR test_stdout_filedes (test.test_subprocess.ProcessTestCase) ... [15648 refs] ERROR test_stdout_filedes_of_stdout (test.test_subprocess.ProcessTestCase) ... . [15648 refs] ERROR test_stdout_fileobj (test.test_subprocess.ProcessTestCase) ... [15648 refs] ERROR test_stdout_none (test.test_subprocess.ProcessTestCase) ... this bit of output is from a test of stdout in a different process ... ERROR test_stdout_pipe (test.test_subprocess.ProcessTestCase) ... [15648 refs] ERROR test_stdout_stderr_file (test.test_subprocess.ProcessTestCase) ... ERROR test_stdout_stderr_pipe (test.test_subprocess.ProcessTestCase) ... ERROR test_universal_newlines (test.test_subprocess.ProcessTestCase) ... [15648 refs] ERROR test_universal_newlines_communicate (test.test_subprocess.ProcessTestCase) ... ERROR test_wait (test.test_subprocess.ProcessTestCase) ... [15863 refs] ERROR test_writes_before_communicate (test.test_subprocess.ProcessTestCase) ... ERROR test_args_string (test.test_subprocess.POSIXProcessTestCase) ... [15648 refs] ERROR test_call_string (test.test_subprocess.POSIXProcessTestCase) ... [15648 refs] ERROR test_exceptions (test.test_subprocess.POSIXProcessTestCase) ... ERROR test_invalid_args (test.test_subprocess.POSIXProcessTestCase) ... ERROR test_kill (test.test_subprocess.POSIXProcessTestCase) ... ERROR test_preexec (test.test_subprocess.POSIXProcessTestCase) ... [15648 refs] ERROR test_run_abort (test.test_subprocess.POSIXProcessTestCase) ... ERROR test_send_signal (test.test_subprocess.POSIXProcessTestCase) ... ERROR test_shell_sequence (test.test_subprocess.POSIXProcessTestCase) ... ERROR test_shell_string (test.test_subprocess.POSIXProcessTestCase) ... ERROR test_terminate (test.test_subprocess.POSIXProcessTestCase) ... ERROR test_call_string (test.test_subprocess.Win32ProcessTestCase) ... skipped 'Windows specific tests' test_close_fds (test.test_subprocess.Win32ProcessTestCase) ... skipped 'Windows specific tests' test_creationflags (test.test_subprocess.Win32ProcessTestCase) ... skipped 'Windows specific tests' test_invalid_args (test.test_subprocess.Win32ProcessTestCase) ... skipped 'Windows specific tests' test_kill (test.test_subprocess.Win32ProcessTestCase) ... skipped 'Windows specific tests' test_send_signal (test.test_subprocess.Win32ProcessTestCase) ... skipped 'Windows specific tests' test_shell_sequence (test.test_subprocess.Win32ProcessTestCase) ... skipped 'Windows specific tests' test_shell_string (test.test_subprocess.Win32ProcessTestCase) ... skipped 'Windows specific tests' test_startupinfo (test.test_subprocess.Win32ProcessTestCase) ... skipped 'Windows specific tests' test_terminate (test.test_subprocess.Win32ProcessTestCase) ... skipped 'Windows specific tests' test_call_kwargs (test.test_subprocess.ProcessTestCaseNoPoll) ... [15648 refs] ERROR test_call_seq (test.test_subprocess.ProcessTestCaseNoPoll) ... [15648 refs] ERROR test_check_call_nonzero (test.test_subprocess.ProcessTestCaseNoPoll) ... [15648 refs] ERROR test_check_call_zero (test.test_subprocess.ProcessTestCaseNoPoll) ... [15648 refs] ERROR test_check_output (test.test_subprocess.ProcessTestCaseNoPoll) ... [15648 refs] ERROR test_check_output_nonzero (test.test_subprocess.ProcessTestCaseNoPoll) ... [15648 refs] ERROR test_check_output_stderr (test.test_subprocess.ProcessTestCaseNoPoll) ... ERROR test_check_output_stdout_arg (test.test_subprocess.ProcessTestCaseNoPoll) ... ERROR test_communicate (test.test_subprocess.ProcessTestCaseNoPoll) ... ERROR test_communicate_pipe_buf (test.test_subprocess.ProcessTestCaseNoPoll) ... ERROR test_communicate_pipe_fd_leak (test.test_subprocess.ProcessTestCaseNoPoll) ... [15648 refs] ERROR test_communicate_returns (test.test_subprocess.ProcessTestCaseNoPoll) ... [15648 refs] ERROR test_communicate_stderr (test.test_subprocess.ProcessTestCaseNoPoll) ... ERROR test_communicate_stdin (test.test_subprocess.ProcessTestCaseNoPoll) ... [15648 refs] ERROR test_communicate_stdout (test.test_subprocess.ProcessTestCaseNoPoll) ... [15648 refs] ERROR test_cwd (test.test_subprocess.ProcessTestCaseNoPoll) ... [15648 refs] ERROR test_env (test.test_subprocess.ProcessTestCaseNoPoll) ... [15648 refs] ERROR test_executable_with_cwd (test.test_subprocess.ProcessTestCaseNoPoll) ... [15648 refs] ERROR test_executable_without_cwd (test.test_subprocess.ProcessTestCaseNoPoll) ... [15648 refs] ERROR test_invalid_bufsize (test.test_subprocess.ProcessTestCaseNoPoll) ... ERROR test_leaking_fds_on_error (test.test_subprocess.ProcessTestCaseNoPoll) ... ERROR test_list2cmdline (test.test_subprocess.ProcessTestCaseNoPoll) ... ERROR test_no_leaking (test.test_subprocess.ProcessTestCaseNoPoll) ... ERROR test_poll (test.test_subprocess.ProcessTestCaseNoPoll) ... [15863 refs] ERROR test_stderr_filedes (test.test_subprocess.ProcessTestCaseNoPoll) ... ERROR test_stderr_fileobj (test.test_subprocess.ProcessTestCaseNoPoll) ... ERROR test_stderr_none (test.test_subprocess.ProcessTestCaseNoPoll) ... [15648 refs] ERROR test_stderr_pipe (test.test_subprocess.ProcessTestCaseNoPoll) ... ERROR test_stdin_filedes (test.test_subprocess.ProcessTestCaseNoPoll) ... [15648 refs] ERROR test_stdin_fileobj (test.test_subprocess.ProcessTestCaseNoPoll) ... [15648 refs] ERROR test_stdin_none (test.test_subprocess.ProcessTestCaseNoPoll) ... ERROR test_stdin_pipe (test.test_subprocess.ProcessTestCaseNoPoll) ... [15648 refs] ERROR test_stdout_filedes (test.test_subprocess.ProcessTestCaseNoPoll) ... [15648 refs] ERROR test_stdout_filedes_of_stdout (test.test_subprocess.ProcessTestCaseNoPoll) ... . [15648 refs] ERROR test_stdout_fileobj (test.test_subprocess.ProcessTestCaseNoPoll) ... [15648 refs] ERROR test_stdout_none (test.test_subprocess.ProcessTestCaseNoPoll) ... this bit of output is from a test of stdout in a different process ... ERROR test_stdout_pipe (test.test_subprocess.ProcessTestCaseNoPoll) ... [15648 refs] ERROR test_stdout_stderr_file (test.test_subprocess.ProcessTestCaseNoPoll) ... ERROR test_stdout_stderr_pipe (test.test_subprocess.ProcessTestCaseNoPoll) ... ERROR test_universal_newlines (test.test_subprocess.ProcessTestCaseNoPoll) ... [15648 refs] ERROR test_universal_newlines_communicate (test.test_subprocess.ProcessTestCaseNoPoll) ... ERROR test_wait (test.test_subprocess.ProcessTestCaseNoPoll) ... [15863 refs] ERROR test_writes_before_communicate (test.test_subprocess.ProcessTestCaseNoPoll) ... ERROR test_eintr_retry_call (test.test_subprocess.HelperFunctionTests) ... ok ====================================================================== ERROR: test_call_kwargs (test.test_subprocess.ProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_call_seq (test.test_subprocess.ProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_check_call_nonzero (test.test_subprocess.ProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_check_call_zero (test.test_subprocess.ProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_check_output (test.test_subprocess.ProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_check_output_nonzero (test.test_subprocess.ProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_check_output_stderr (test.test_subprocess.ProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_check_output_stdout_arg (test.test_subprocess.ProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_communicate (test.test_subprocess.ProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_communicate_pipe_buf (test.test_subprocess.ProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_communicate_pipe_fd_leak (test.test_subprocess.ProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_communicate_returns (test.test_subprocess.ProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_communicate_stderr (test.test_subprocess.ProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_communicate_stdin (test.test_subprocess.ProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_communicate_stdout (test.test_subprocess.ProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_cwd (test.test_subprocess.ProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_env (test.test_subprocess.ProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_executable_with_cwd (test.test_subprocess.ProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_executable_without_cwd (test.test_subprocess.ProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_invalid_bufsize (test.test_subprocess.ProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_leaking_fds_on_error (test.test_subprocess.ProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_list2cmdline (test.test_subprocess.ProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_no_leaking (test.test_subprocess.ProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_poll (test.test_subprocess.ProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_stderr_filedes (test.test_subprocess.ProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_stderr_fileobj (test.test_subprocess.ProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_stderr_none (test.test_subprocess.ProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_stderr_pipe (test.test_subprocess.ProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_stdin_filedes (test.test_subprocess.ProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_stdin_fileobj (test.test_subprocess.ProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_stdin_none (test.test_subprocess.ProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_stdin_pipe (test.test_subprocess.ProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_stdout_filedes (test.test_subprocess.ProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_stdout_filedes_of_stdout (test.test_subprocess.ProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_stdout_fileobj (test.test_subprocess.ProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_stdout_none (test.test_subprocess.ProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_stdout_pipe (test.test_subprocess.ProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_stdout_stderr_file (test.test_subprocess.ProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_stdout_stderr_pipe (test.test_subprocess.ProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_universal_newlines (test.test_subprocess.ProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_universal_newlines_communicate (test.test_subprocess.ProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_wait (test.test_subprocess.ProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_writes_before_communicate (test.test_subprocess.ProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_args_string (test.test_subprocess.POSIXProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_call_string (test.test_subprocess.POSIXProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_exceptions (test.test_subprocess.POSIXProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_invalid_args (test.test_subprocess.POSIXProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_kill (test.test_subprocess.POSIXProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_preexec (test.test_subprocess.POSIXProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_run_abort (test.test_subprocess.POSIXProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_send_signal (test.test_subprocess.POSIXProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_shell_sequence (test.test_subprocess.POSIXProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_shell_string (test.test_subprocess.POSIXProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_terminate (test.test_subprocess.POSIXProcessTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_call_kwargs (test.test_subprocess.ProcessTestCaseNoPoll) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 800, in tearDown ProcessTestCase.tearDown(self) File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_call_seq (test.test_subprocess.ProcessTestCaseNoPoll) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 800, in tearDown ProcessTestCase.tearDown(self) File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_check_call_nonzero (test.test_subprocess.ProcessTestCaseNoPoll) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 800, in tearDown ProcessTestCase.tearDown(self) File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_check_call_zero (test.test_subprocess.ProcessTestCaseNoPoll) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 800, in tearDown ProcessTestCase.tearDown(self) File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_check_output (test.test_subprocess.ProcessTestCaseNoPoll) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 800, in tearDown ProcessTestCase.tearDown(self) File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_check_output_nonzero (test.test_subprocess.ProcessTestCaseNoPoll) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 800, in tearDown ProcessTestCase.tearDown(self) File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_check_output_stderr (test.test_subprocess.ProcessTestCaseNoPoll) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 800, in tearDown ProcessTestCase.tearDown(self) File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_check_output_stdout_arg (test.test_subprocess.ProcessTestCaseNoPoll) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 800, in tearDown ProcessTestCase.tearDown(self) File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_communicate (test.test_subprocess.ProcessTestCaseNoPoll) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 800, in tearDown ProcessTestCase.tearDown(self) File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_communicate_pipe_buf (test.test_subprocess.ProcessTestCaseNoPoll) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 800, in tearDown ProcessTestCase.tearDown(self) File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_communicate_pipe_fd_leak (test.test_subprocess.ProcessTestCaseNoPoll) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 800, in tearDown ProcessTestCase.tearDown(self) File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_communicate_returns (test.test_subprocess.ProcessTestCaseNoPoll) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 800, in tearDown ProcessTestCase.tearDown(self) File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_communicate_stderr (test.test_subprocess.ProcessTestCaseNoPoll) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 800, in tearDown ProcessTestCase.tearDown(self) File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_communicate_stdin (test.test_subprocess.ProcessTestCaseNoPoll) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 800, in tearDown ProcessTestCase.tearDown(self) File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_communicate_stdout (test.test_subprocess.ProcessTestCaseNoPoll) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 800, in tearDown ProcessTestCase.tearDown(self) File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_cwd (test.test_subprocess.ProcessTestCaseNoPoll) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 800, in tearDown ProcessTestCase.tearDown(self) File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_env (test.test_subprocess.ProcessTestCaseNoPoll) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 800, in tearDown ProcessTestCase.tearDown(self) File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_executable_with_cwd (test.test_subprocess.ProcessTestCaseNoPoll) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 800, in tearDown ProcessTestCase.tearDown(self) File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_executable_without_cwd (test.test_subprocess.ProcessTestCaseNoPoll) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 800, in tearDown ProcessTestCase.tearDown(self) File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_invalid_bufsize (test.test_subprocess.ProcessTestCaseNoPoll) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 800, in tearDown ProcessTestCase.tearDown(self) File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_leaking_fds_on_error (test.test_subprocess.ProcessTestCaseNoPoll) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 800, in tearDown ProcessTestCase.tearDown(self) File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_list2cmdline (test.test_subprocess.ProcessTestCaseNoPoll) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 800, in tearDown ProcessTestCase.tearDown(self) File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_no_leaking (test.test_subprocess.ProcessTestCaseNoPoll) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 800, in tearDown ProcessTestCase.tearDown(self) File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_poll (test.test_subprocess.ProcessTestCaseNoPoll) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 800, in tearDown ProcessTestCase.tearDown(self) File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_stderr_filedes (test.test_subprocess.ProcessTestCaseNoPoll) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 800, in tearDown ProcessTestCase.tearDown(self) File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_stderr_fileobj (test.test_subprocess.ProcessTestCaseNoPoll) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 800, in tearDown ProcessTestCase.tearDown(self) File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_stderr_none (test.test_subprocess.ProcessTestCaseNoPoll) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 800, in tearDown ProcessTestCase.tearDown(self) File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_stderr_pipe (test.test_subprocess.ProcessTestCaseNoPoll) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 800, in tearDown ProcessTestCase.tearDown(self) File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_stdin_filedes (test.test_subprocess.ProcessTestCaseNoPoll) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 800, in tearDown ProcessTestCase.tearDown(self) File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_stdin_fileobj (test.test_subprocess.ProcessTestCaseNoPoll) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 800, in tearDown ProcessTestCase.tearDown(self) File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_stdin_none (test.test_subprocess.ProcessTestCaseNoPoll) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 800, in tearDown ProcessTestCase.tearDown(self) File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_stdin_pipe (test.test_subprocess.ProcessTestCaseNoPoll) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 800, in tearDown ProcessTestCase.tearDown(self) File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_stdout_filedes (test.test_subprocess.ProcessTestCaseNoPoll) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 800, in tearDown ProcessTestCase.tearDown(self) File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_stdout_filedes_of_stdout (test.test_subprocess.ProcessTestCaseNoPoll) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 800, in tearDown ProcessTestCase.tearDown(self) File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_stdout_fileobj (test.test_subprocess.ProcessTestCaseNoPoll) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 800, in tearDown ProcessTestCase.tearDown(self) File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_stdout_none (test.test_subprocess.ProcessTestCaseNoPoll) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 800, in tearDown ProcessTestCase.tearDown(self) File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_stdout_pipe (test.test_subprocess.ProcessTestCaseNoPoll) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 800, in tearDown ProcessTestCase.tearDown(self) File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_stdout_stderr_file (test.test_subprocess.ProcessTestCaseNoPoll) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 800, in tearDown ProcessTestCase.tearDown(self) File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_stdout_stderr_pipe (test.test_subprocess.ProcessTestCaseNoPoll) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 800, in tearDown ProcessTestCase.tearDown(self) File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_universal_newlines (test.test_subprocess.ProcessTestCaseNoPoll) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 800, in tearDown ProcessTestCase.tearDown(self) File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_universal_newlines_communicate (test.test_subprocess.ProcessTestCaseNoPoll) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 800, in tearDown ProcessTestCase.tearDown(self) File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_wait (test.test_subprocess.ProcessTestCaseNoPoll) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 800, in tearDown ProcessTestCase.tearDown(self) File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ====================================================================== ERROR: test_writes_before_communicate (test.test_subprocess.ProcessTestCaseNoPoll) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 800, in tearDown ProcessTestCase.tearDown(self) File "/tmp/python-test/local/lib/python2.7/test/test_subprocess.py", line 46, in tearDown self.assertFalse(subprocess._active, "subprocess._active not empty") AssertionError: subprocess._active not empty ---------------------------------------------------------------------- Ran 108 tests in 200.898s FAILED (errors=97, skipped=10) test test_subprocess failed -- multiple errors occurred test_sunaudiodev test_sunaudiodev skipped -- No module named sunaudiodev test_sundry test_symtable test_syntax test_sys [15648 refs] [15648 refs] [15648 refs] [15877 refs] [15671 refs] test_sysconfig [15648 refs] [15648 refs] test_tarfile test_tcl test_tcl skipped -- No module named _tkinter test_telnetlib test_tempfile [15648 refs] test_textwrap test_thread test_threaded_import test_threadedtempfile test_threading [18948 refs] [20223 refs] [20035 refs] [20035 refs] [20035 refs] [20035 refs] test_threading_local test_threadsignals test_time test_timeout test_timeout skipped -- Use of the `network' resource not enabled test_tk test_tk skipped -- No module named _tkinter test_tokenize test_trace test_traceback test_transformer test_ttk_guionly test_ttk_guionly skipped -- No module named _tkinter test_ttk_textonly test_ttk_textonly skipped -- No module named _tkinter test_tuple test_typechecks test_ucn test_unary test_undocumented_details test_unicode test_unicode_file test_unicode_file skipped -- No Unicode filesystem semantics on this platform. test_unicodedata test_univnewlines test_univnewlines2k test_unpack test_urllib test_urllib2 test_urllib2_localnet test_urllib2net test_urllib2net skipped -- Use of the `network' resource not enabled test_urllibnet test_urllibnet skipped -- Use of the `network' resource not enabled test_urlparse test_userdict test_userlist test_userstring test_uu test_uuid test_wait3 test_wait4 test_warnings [15679 refs] [15679 refs] [15672 refs] [15679 refs] [15679 refs] [15672 refs] test_wave test_weakref test_weakset test_whichdb test_winreg test_winreg skipped -- No module named _winreg test_winsound test_winsound skipped -- No module named winsound test_with test_wsgiref test_xdrlib test_xml_etree test_xml_etree_c test_xmllib test_xmlrpc test_xpickle test_xpickle -- skipping backwards compat tests. Use 'regrtest.py -u xpickle' to run them. test_xrange test_zipfile test_zipfile64 test_zipfile64 skipped -- test requires loads of disk-space bytes and a long time to run test_zipimport test_zipimport_support test_zlib 346 tests OK. 1 test failed: test_subprocess 37 tests skipped: test_aepack test_al test_applesingle test_bsddb185 test_bsddb3 test_cd test_cl test_curses test_epoll test_gdb test_gl test_imgfile test_ioctl test_kqueue test_linuxaudiodev test_macos test_macostools test_multiprocessing test_ossaudiodev test_pep277 test_py3kwarn test_scriptpackages test_smtpnet test_socketserver test_startfile test_sunaudiodev test_tcl test_timeout test_tk test_ttk_guionly test_ttk_textonly test_unicode_file test_urllib2net test_urllibnet test_winreg test_winsound test_zipfile64 7 skips unexpected on linux2: test_epoll test_gdb test_ioctl test_multiprocessing test_tk test_ttk_guionly test_ttk_textonly [965838 refs] From python-checkins at python.org Thu Jul 8 23:15:36 2010 From: python-checkins at python.org (mark.dickinson) Date: Thu, 8 Jul 2010 23:15:36 +0200 (CEST) Subject: [Python-checkins] r82654 - in python/branches/py3k: Lib/decimal.py Misc/NEWS Message-ID: <20100708211536.EC26DEEBB8@mail.python.org> Author: mark.dickinson Date: Thu Jul 8 23:15:36 2010 New Revision: 82654 Log: Issue #9136: Profiling Decimal gave 'dictionary changed size during iteration'. Remove the use of locals() that caused this error. Modified: python/branches/py3k/Lib/decimal.py python/branches/py3k/Misc/NEWS Modified: python/branches/py3k/Lib/decimal.py ============================================================================== --- python/branches/py3k/Lib/decimal.py (original) +++ python/branches/py3k/Lib/decimal.py Thu Jul 8 23:15:36 2010 @@ -3813,20 +3813,38 @@ Emin=None, Emax=None, capitals=None, clamp=None, _ignored_flags=None): - if flags is None: - flags = [] + # Set defaults; for everything except flags and _ignored_flags, + # inherit from DefaultContext. + try: + dc = DefaultContext + except NameError: + pass + + self.prec = prec if prec is not None else dc.prec + self.rounding = rounding if rounding is not None else dc.rounding + self.Emin = Emin if Emin is not None else dc.Emin + self.Emax = Emax if Emax is not None else dc.Emax + self.capitals = capitals if capitals is not None else dc.capitals + self.clamp = clamp if clamp is not None else dc.clamp + if _ignored_flags is None: - _ignored_flags = [] - if not isinstance(flags, dict): - flags = dict([(s, int(s in flags)) for s in _signals]) - if traps is not None and not isinstance(traps, dict): - traps = dict([(s, int(s in traps)) for s in _signals]) - for name, val in locals().items(): - if val is None: - setattr(self, name, _copy.copy(getattr(DefaultContext, name))) - else: - setattr(self, name, val) - del self.self + self._ignored_flags = [] + else: + self._ignored_flags = _ignored_flags + + if traps is None: + self.traps = dc.traps.copy() + elif not isinstance(traps, dict): + self.traps = dict((s, int(s in traps)) for s in _signals) + else: + self.traps = traps + + if flags is None: + self.flags = dict.fromkeys(_signals, 0) + elif not isinstance(flags, dict): + self.flags = dict((s, int(s in flags)) for s in _signals) + else: + self.flags = flags def __repr__(self): """Show the current context.""" Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Thu Jul 8 23:15:36 2010 @@ -470,6 +470,10 @@ Library ------- +- Issue #9136: Fix 'dictionary changed size during iteration' + RuntimeError produced when profiling the decimal module. This was + due to a dangerous iteration over 'locals()' in Context.__init__. + - Fix extreme speed issue in Decimal.pow when the base is an exact power of 10 and the exponent is tiny (for example, Decimal(10) ** Decimal('1e-999999999')). From python-checkins at python.org Thu Jul 8 23:18:21 2010 From: python-checkins at python.org (mark.dickinson) Date: Thu, 8 Jul 2010 23:18:21 +0200 (CEST) Subject: [Python-checkins] r82655 - in python/branches/release31-maint: Lib/decimal.py Misc/NEWS Message-ID: <20100708211821.9E579EEAF6@mail.python.org> Author: mark.dickinson Date: Thu Jul 8 23:18:21 2010 New Revision: 82655 Log: Merged revisions 82654 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ........ r82654 | mark.dickinson | 2010-07-08 22:15:36 +0100 (Thu, 08 Jul 2010) | 3 lines Issue #9136: Profiling Decimal gave 'dictionary changed size during iteration'. Remove the use of locals() that caused this error. ........ Modified: python/branches/release31-maint/ (props changed) python/branches/release31-maint/Lib/decimal.py python/branches/release31-maint/Misc/NEWS Modified: python/branches/release31-maint/Lib/decimal.py ============================================================================== --- python/branches/release31-maint/Lib/decimal.py (original) +++ python/branches/release31-maint/Lib/decimal.py Thu Jul 8 23:18:21 2010 @@ -3809,20 +3809,38 @@ Emin=None, Emax=None, capitals=None, _clamp=0, _ignored_flags=None): - if flags is None: - flags = [] + # Set defaults; for everything except flags and _ignored_flags, + # inherit from DefaultContext. + try: + dc = DefaultContext + except NameError: + pass + + self.prec = prec if prec is not None else dc.prec + self.rounding = rounding if rounding is not None else dc.rounding + self.Emin = Emin if Emin is not None else dc.Emin + self.Emax = Emax if Emax is not None else dc.Emax + self.capitals = capitals if capitals is not None else dc.capitals + self._clamp = _clamp if _clamp is not None else dc._clamp + if _ignored_flags is None: - _ignored_flags = [] - if not isinstance(flags, dict): - flags = dict([(s, int(s in flags)) for s in _signals]) - if traps is not None and not isinstance(traps, dict): - traps = dict([(s, int(s in traps)) for s in _signals]) - for name, val in locals().items(): - if val is None: - setattr(self, name, _copy.copy(getattr(DefaultContext, name))) - else: - setattr(self, name, val) - del self.self + self._ignored_flags = [] + else: + self._ignored_flags = _ignored_flags + + if traps is None: + self.traps = dc.traps.copy() + elif not isinstance(traps, dict): + self.traps = dict((s, int(s in traps)) for s in _signals) + else: + self.traps = traps + + if flags is None: + self.flags = dict.fromkeys(_signals, 0) + elif not isinstance(flags, dict): + self.flags = dict((s, int(s in flags)) for s in _signals) + else: + self.flags = flags def __repr__(self): """Show the current context.""" Modified: python/branches/release31-maint/Misc/NEWS ============================================================================== --- python/branches/release31-maint/Misc/NEWS (original) +++ python/branches/release31-maint/Misc/NEWS Thu Jul 8 23:18:21 2010 @@ -75,6 +75,10 @@ Library ------- +- Issue #9136: Fix 'dictionary changed size during iteration' + RuntimeError produced when profiling the decimal module. This was + due to a dangerous iteration over 'locals()' in Context.__init__. + - Fix extreme speed issue in Decimal.pow when the base is an exact power of 10 and the exponent is tiny (for example, Decimal(10) ** Decimal('1e-999999999')). From python-checkins at python.org Thu Jul 8 23:22:55 2010 From: python-checkins at python.org (mark.dickinson) Date: Thu, 8 Jul 2010 23:22:55 +0200 (CEST) Subject: [Python-checkins] r82656 - in python/branches/release27-maint: Lib/decimal.py Misc/NEWS Message-ID: <20100708212255.34EAAEEC27@mail.python.org> Author: mark.dickinson Date: Thu Jul 8 23:22:54 2010 New Revision: 82656 Log: Merged revisions 82654 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ........ r82654 | mark.dickinson | 2010-07-08 22:15:36 +0100 (Thu, 08 Jul 2010) | 3 lines Issue #9136: Profiling Decimal gave 'dictionary changed size during iteration'. Remove the use of locals() that caused this error. ........ Modified: python/branches/release27-maint/ (props changed) python/branches/release27-maint/Lib/decimal.py python/branches/release27-maint/Misc/NEWS Modified: python/branches/release27-maint/Lib/decimal.py ============================================================================== --- python/branches/release27-maint/Lib/decimal.py (original) +++ python/branches/release27-maint/Lib/decimal.py Thu Jul 8 23:22:54 2010 @@ -3756,22 +3756,38 @@ Emin=None, Emax=None, capitals=None, _clamp=0, _ignored_flags=None): - if flags is None: - flags = [] + # Set defaults; for everything except flags and _ignored_flags, + # inherit from DefaultContext. + try: + dc = DefaultContext + except NameError: + pass + + self.prec = prec if prec is not None else dc.prec + self.rounding = rounding if rounding is not None else dc.rounding + self.Emin = Emin if Emin is not None else dc.Emin + self.Emax = Emax if Emax is not None else dc.Emax + self.capitals = capitals if capitals is not None else dc.capitals + self._clamp = _clamp if _clamp is not None else dc._clamp + if _ignored_flags is None: - _ignored_flags = [] - if not isinstance(flags, dict): - flags = dict([(s, int(s in flags)) for s in _signals]) - del s - if traps is not None and not isinstance(traps, dict): - traps = dict([(s, int(s in traps)) for s in _signals]) - del s - for name, val in locals().items(): - if val is None: - setattr(self, name, _copy.copy(getattr(DefaultContext, name))) - else: - setattr(self, name, val) - del self.self + self._ignored_flags = [] + else: + self._ignored_flags = _ignored_flags + + if traps is None: + self.traps = dc.traps.copy() + elif not isinstance(traps, dict): + self.traps = dict((s, int(s in traps)) for s in _signals) + else: + self.traps = traps + + if flags is None: + self.flags = dict.fromkeys(_signals, 0) + elif not isinstance(flags, dict): + self.flags = dict((s, int(s in flags)) for s in _signals) + else: + self.flags = flags def __repr__(self): """Show the current context.""" Modified: python/branches/release27-maint/Misc/NEWS ============================================================================== --- python/branches/release27-maint/Misc/NEWS (original) +++ python/branches/release27-maint/Misc/NEWS Thu Jul 8 23:22:54 2010 @@ -510,6 +510,10 @@ Core and Builtins ----------------- +- Issue #9136: Fix 'dictionary changed size during iteration' + RuntimeError produced when profiling the decimal module. This was + due to a dangerous iteration over 'locals()' in Context.__init__. + - Issue #7301: Add environment variable $PYTHONWARNINGS. - Issue #8329: Don't return the same lists from select.select when no fds are From python-checkins at python.org Thu Jul 8 23:27:06 2010 From: python-checkins at python.org (mark.dickinson) Date: Thu, 8 Jul 2010 23:27:06 +0200 (CEST) Subject: [Python-checkins] r82657 - in python/branches/release26-maint: Lib/decimal.py Misc/NEWS Message-ID: <20100708212706.06B55EEC0E@mail.python.org> Author: mark.dickinson Date: Thu Jul 8 23:27:05 2010 New Revision: 82657 Log: Issue #9136: Fix 'dictionary changed size during iteration' RuntimeError produced when profiling the decimal module. This was due to a dangerous iteration over 'locals()' in Context.__init__. (Backport of r82656 from release27-maint.) Modified: python/branches/release26-maint/Lib/decimal.py python/branches/release26-maint/Misc/NEWS Modified: python/branches/release26-maint/Lib/decimal.py ============================================================================== --- python/branches/release26-maint/Lib/decimal.py (original) +++ python/branches/release26-maint/Lib/decimal.py Thu Jul 8 23:27:05 2010 @@ -3690,22 +3690,38 @@ Emin=None, Emax=None, capitals=None, _clamp=0, _ignored_flags=None): - if flags is None: - flags = [] + # Set defaults; for everything except flags and _ignored_flags, + # inherit from DefaultContext. + try: + dc = DefaultContext + except NameError: + pass + + self.prec = prec if prec is not None else dc.prec + self.rounding = rounding if rounding is not None else dc.rounding + self.Emin = Emin if Emin is not None else dc.Emin + self.Emax = Emax if Emax is not None else dc.Emax + self.capitals = capitals if capitals is not None else dc.capitals + self._clamp = _clamp if _clamp is not None else dc._clamp + if _ignored_flags is None: - _ignored_flags = [] - if not isinstance(flags, dict): - flags = dict([(s, int(s in flags)) for s in _signals]) - del s - if traps is not None and not isinstance(traps, dict): - traps = dict([(s, int(s in traps)) for s in _signals]) - del s - for name, val in locals().items(): - if val is None: - setattr(self, name, _copy.copy(getattr(DefaultContext, name))) - else: - setattr(self, name, val) - del self.self + self._ignored_flags = [] + else: + self._ignored_flags = _ignored_flags + + if traps is None: + self.traps = dc.traps.copy() + elif not isinstance(traps, dict): + self.traps = dict((s, int(s in traps)) for s in _signals) + else: + self.traps = traps + + if flags is None: + self.flags = dict.fromkeys(_signals, 0) + elif not isinstance(flags, dict): + self.flags = dict((s, int(s in flags)) for s in _signals) + else: + self.flags = flags def __repr__(self): """Show the current context.""" Modified: python/branches/release26-maint/Misc/NEWS ============================================================================== --- python/branches/release26-maint/Misc/NEWS (original) +++ python/branches/release26-maint/Misc/NEWS Thu Jul 8 23:27:05 2010 @@ -81,6 +81,10 @@ Library ------- +- Issue #9136: Fix 'dictionary changed size during iteration' + RuntimeError produced when profiling the decimal module. This was + due to a dangerous iteration over 'locals()' in Context.__init__. + - Fix extreme speed issue in Decimal.pow when the base is an exact power of 10 and the exponent is tiny (for example, Decimal(10) ** Decimal('1e-999999999')). From python-checkins at python.org Thu Jul 8 23:28:32 2010 From: python-checkins at python.org (mark.dickinson) Date: Thu, 8 Jul 2010 23:28:32 +0200 (CEST) Subject: [Python-checkins] r82658 - python/branches/release27-maint/Misc/NEWS Message-ID: <20100708212832.07547EEC55@mail.python.org> Author: mark.dickinson Date: Thu Jul 8 23:28:31 2010 New Revision: 82658 Log: Move Misc/NEWS entries to the right place. Modified: python/branches/release27-maint/Misc/NEWS Modified: python/branches/release27-maint/Misc/NEWS ============================================================================== --- python/branches/release27-maint/Misc/NEWS (original) +++ python/branches/release27-maint/Misc/NEWS Thu Jul 8 23:28:31 2010 @@ -16,6 +16,14 @@ Library ------- +- Issue #9136: Fix 'dictionary changed size during iteration' + RuntimeError produced when profiling the decimal module. This was + due to a dangerous iteration over 'locals()' in Context.__init__. + +- Fix extreme speed issue in Decimal.pow when the base is an exact + power of 10 and the exponent is tiny (for example, + Decimal(10) ** Decimal('1e-999999999')). + - Issue #9161: Fix regression in optparse's acceptance of unicode strings in add_option calls. @@ -510,19 +518,11 @@ Core and Builtins ----------------- -- Issue #9136: Fix 'dictionary changed size during iteration' - RuntimeError produced when profiling the decimal module. This was - due to a dangerous iteration over 'locals()' in Context.__init__. - - Issue #7301: Add environment variable $PYTHONWARNINGS. - Issue #8329: Don't return the same lists from select.select when no fds are changed. -- Fix extreme speed issue in Decimal.pow when the base is an exact - power of 10 and the exponent is tiny (for example, - Decimal(10) ** Decimal('1e-999999999')). - - Issue #8259: ``1L << (2**31)`` no longer produces an 'outrageous shift error' on 64-bit machines. The shift count for either left or right shift is permitted to be up to sys.maxsize. From python-checkins at python.org Thu Jul 8 23:39:09 2010 From: python-checkins at python.org (brian.curtin) Date: Thu, 8 Jul 2010 23:39:09 +0200 (CEST) Subject: [Python-checkins] r82659 - in python/branches/py3k: Doc/library/os.path.rst Doc/library/os.rst Lib/ntpath.py Lib/tarfile.py Lib/test/support.py Lib/test/symlink_support.py Lib/test/test_glob.py Lib/test/test_httpservers.py Lib/test/test_os.py Lib/test/test_platform.py Lib/test/test_posixpath.py Lib/test/test_shutil.py Lib/test/test_sys.py Lib/test/test_sysconfig.py Lib/test/test_tarfile.py Misc/ACKS Misc/NEWS Modules/posixmodule.c Message-ID: <20100708213909.4B34DD267@mail.python.org> Author: brian.curtin Date: Thu Jul 8 23:39:08 2010 New Revision: 82659 Log: Implement #1578269. Patch by Jason R. Coombs. Added Windows support for os.symlink when run on Windows 6.0 or greater, aka Vista. Previous Windows versions will raise NotImplementedError when trying to symlink. Includes numerous test updates and additions to test_os, including a symlink_support module because of the fact that privilege escalation is required in order to run the tests to ensure that the user is able to create symlinks. By default, accounts do not have the required privilege, so the escalation code will have to be exposed later (or documented on how to do so). I'll be following up with that work next. Note that the tests use ctypes, which was agreed on during the PyCon language summit. Added: python/branches/py3k/Lib/test/symlink_support.py (contents, props changed) Modified: python/branches/py3k/Doc/library/os.path.rst python/branches/py3k/Doc/library/os.rst python/branches/py3k/Lib/ntpath.py python/branches/py3k/Lib/tarfile.py python/branches/py3k/Lib/test/support.py python/branches/py3k/Lib/test/test_glob.py python/branches/py3k/Lib/test/test_httpservers.py python/branches/py3k/Lib/test/test_os.py python/branches/py3k/Lib/test/test_platform.py python/branches/py3k/Lib/test/test_posixpath.py python/branches/py3k/Lib/test/test_shutil.py python/branches/py3k/Lib/test/test_sys.py python/branches/py3k/Lib/test/test_sysconfig.py python/branches/py3k/Lib/test/test_tarfile.py python/branches/py3k/Misc/ACKS python/branches/py3k/Misc/NEWS python/branches/py3k/Modules/posixmodule.c Modified: python/branches/py3k/Doc/library/os.path.rst ============================================================================== --- python/branches/py3k/Doc/library/os.path.rst (original) +++ python/branches/py3k/Doc/library/os.path.rst Thu Jul 8 23:39:08 2010 @@ -231,11 +231,15 @@ .. function:: samefile(path1, path2) - Return ``True`` if both pathname arguments refer to the same file or directory - (as indicated by device number and i-node number). Raise an exception if a - :func:`os.stat` call on either pathname fails. + Return ``True`` if both pathname arguments refer to the same file or directory. + On Unix, this is determined by the device number and i-node number and raises an + exception if a :func:`os.stat` call on either pathname fails. + + On Windows, two files are the same if they resolve to the same final path + name using the Windows API call GetFinalPathNameByHandle and this function + raises an exception if handles cannot be obtained to either file. - Availability: Unix. + Availability: Windows, Unix. .. function:: sameopenfile(fp1, fp2) Modified: python/branches/py3k/Doc/library/os.rst ============================================================================== --- python/branches/py3k/Doc/library/os.rst (original) +++ python/branches/py3k/Doc/library/os.rst Thu Jul 8 23:39:08 2010 @@ -1065,7 +1065,7 @@ Like :func:`stat`, but do not follow symbolic links. This is an alias for :func:`stat` on platforms that do not support symbolic links, such as - Windows. + Windows prior to 6.0 (Vista). .. function:: mkfifo(path[, mode]) @@ -1181,7 +1181,7 @@ and the call may raise an UnicodeDecodeError. If the *path* is a bytes object, the result will be a bytes object. - Availability: Unix. + Availability: Unix, Windows. .. function:: remove(path) @@ -1341,9 +1341,25 @@ .. function:: symlink(source, link_name) - Create a symbolic link pointing to *source* named *link_name*. + Create a symbolic link pointing to *source* named *link_name*. On Windows, + symlink version takes an additional, optional parameter, + *target_is_directory*, which defaults to False. + + symlink(source, link_name, target_is_directory=False) + + On Windows, a symlink represents a file or a directory, and does not + morph to the target dynamically. For this reason, when creating a + symlink on Windows, if the target is not already present, the symlink + will default to being a file symlink. If *target_is_directory* is set to + True, the symlink will be created as a directory symlink. This + parameter is ignored if the target exists (and the symlink is created + with the same type as the target). + + Symbolic link support was introduced in Windows 6.0 (Vista). *symlink* + will raise a NotImplementedError on Windows versions earlier than 6.0. The + SeCreateSymbolicLinkPrivilege is required in order to create symlinks. - Availability: Unix. + Availability: Unix, Windows 6.0. .. function:: unlink(path) Modified: python/branches/py3k/Lib/ntpath.py ============================================================================== --- python/branches/py3k/Lib/ntpath.py (original) +++ python/branches/py3k/Lib/ntpath.py Thu Jul 8 23:39:08 2010 @@ -16,7 +16,8 @@ "getatime","getctime", "islink","exists","lexists","isdir","isfile", "ismount", "expanduser","expandvars","normpath","abspath", "splitunc","curdir","pardir","sep","pathsep","defpath","altsep", - "extsep","devnull","realpath","supports_unicode_filenames","relpath"] + "extsep","devnull","realpath","supports_unicode_filenames","relpath", + "samefile",] # strings representing various path-related bits and pieces # These are primarily for export; internally, they are hardcoded. @@ -309,16 +310,28 @@ return split(p)[0] # Is a path a symbolic link? -# This will always return false on systems where posix.lstat doesn't exist. +# This will always return false on systems where os.lstat doesn't exist. def islink(path): - """Test for symbolic link. - On WindowsNT/95 and OS/2 always returns false + """Test whether a path is a symbolic link. + This will always return false for Windows prior to 6.0 + and for OS/2. """ - return False - -# alias exists to lexists -lexists = exists + try: + st = os.lstat(path) + except (os.error, AttributeError): + return False + return stat.S_ISLNK(st.st_mode) + +# Being true for dangling symbolic links is also useful. + +def lexists(path): + """Test whether a path exists. Returns True for broken symbolic links""" + try: + st = os.lstat(path) + except (os.error, WindowsError): + return False + return True # Is a path a mount point? Either a root (with or without drive letter) # or an UNC path with at most a / or \ after the mount point. @@ -612,3 +625,17 @@ if not rel_list: return _get_dot(path) return join(*rel_list) + + +# determine if two files are in fact the same file +def samefile(f1, f2): + "Test whether two pathnames reference the same actual file" + try: + from nt import _getfinalpathname + return _getfinalpathname(f1) == _getfinalpathname(f2) + except (NotImplementedError, ImportError): + # On Windows XP and earlier, two files are the same if their + # absolute pathnames are the same. + # Also, on other operating systems, fake this method with a + # Windows-XP approximation. + return abspath(f1) == abspath(f2) Modified: python/branches/py3k/Lib/tarfile.py ============================================================================== --- python/branches/py3k/Lib/tarfile.py (original) +++ python/branches/py3k/Lib/tarfile.py Thu Jul 8 23:39:08 2010 @@ -2273,7 +2273,7 @@ (platform limitation), we try to make a copy of the referenced file instead of a link. """ - if hasattr(os, "symlink") and hasattr(os, "link"): + try: # For systems that support symbolic and hard links. if tarinfo.issym(): os.symlink(tarinfo.linkname, targetpath) @@ -2282,7 +2282,15 @@ if os.path.exists(tarinfo._link_target): os.link(tarinfo._link_target, targetpath) else: - self._extract_member(self._find_link_target(tarinfo), targetpath) + self._extract_mem + except (AttributeError, NotImplementedError, WindowsError): + # AttributeError if no os.symlink + # NotImplementedError if on Windows XP + # WindowsError (1314) if the required privilege is not held by the client + if tarinfo.issym(): + linkpath = os.path.join(os.path.dirname(tarinfo.name),tarinfo.linkname) + else: + linkpath = tarinfo.linkname else: try: self._extract_member(self._find_link_target(tarinfo), targetpath) Modified: python/branches/py3k/Lib/test/support.py ============================================================================== --- python/branches/py3k/Lib/test/support.py (original) +++ python/branches/py3k/Lib/test/support.py Thu Jul 8 23:39:08 2010 @@ -17,6 +17,7 @@ import importlib import collections import re +import subprocess import imp import time try: @@ -38,8 +39,7 @@ "set_memlimit", "bigmemtest", "bigaddrspacetest", "BasicTestRunner", "run_unittest", "run_doctest", "threading_setup", "threading_cleanup", "reap_children", "cpython_only", "check_impl_detail", "get_attribute", - "swap_item", "swap_attr", - ] + "swap_item", "swap_attr", "can_symlink", "skip_unless_symlink"] class Error(Exception): @@ -1169,6 +1169,27 @@ except: break +try: + from .symlink_support import enable_symlink_privilege +except: + enable_symlink_privilege = lambda: True + +def can_symlink(): + """It's no longer sufficient to test for the presence of symlink in the + os module - on Windows XP and earlier, os.symlink exists but a + NotImplementedError is thrown. + """ + has_symlink = hasattr(os, 'symlink') + is_old_windows = sys.platform == "win32" and sys.getwindowsversion().major < 6 + has_privilege = False if is_old_windows else enable_symlink_privilege() + return has_symlink and (not is_old_windows) and has_privilege + +def skip_unless_symlink(test): + """Skip decorator for tests that require functional symlink""" + selector = can_symlink() + msg = "Requires functional symlink implementation" + return [unittest.skip(msg)(test), test][selector] + @contextlib.contextmanager def swap_attr(obj, attr, new_val): """Temporary swap out an attribute with a new object. Added: python/branches/py3k/Lib/test/symlink_support.py ============================================================================== --- (empty file) +++ python/branches/py3k/Lib/test/symlink_support.py Thu Jul 8 23:39:08 2010 @@ -0,0 +1,203 @@ +""" +A module built to test if the current process has the privilege to +create symlinks on Windows. +""" + +# allow script to run natively under python 2.6+ +from __future__ import print_function + +import ctypes +from ctypes import wintypes + +GetCurrentProcess = ctypes.windll.kernel32.GetCurrentProcess +GetCurrentProcess.restype = wintypes.HANDLE +OpenProcessToken = ctypes.windll.advapi32.OpenProcessToken +OpenProcessToken.argtypes = (wintypes.HANDLE, wintypes.DWORD, ctypes.POINTER(wintypes.HANDLE)) +OpenProcessToken.restype = wintypes.BOOL + +class LUID(ctypes.Structure): + _fields_ = [ + ('low_part', wintypes.DWORD), + ('high_part', wintypes.LONG), + ] + + def __eq__(self, other): + return ( + self.high_part == other.high_part and + self.low_part == other.low_part + ) + + def __ne__(self, other): + return not (self==other) + +LookupPrivilegeValue = ctypes.windll.advapi32.LookupPrivilegeValueW +LookupPrivilegeValue.argtypes = ( + wintypes.LPWSTR, # system name + wintypes.LPWSTR, # name + ctypes.POINTER(LUID), + ) +LookupPrivilegeValue.restype = wintypes.BOOL + +class TOKEN_INFORMATION_CLASS: + TokenUser = 1 + TokenGroups = 2 + TokenPrivileges = 3 + # ... see http://msdn.microsoft.com/en-us/library/aa379626%28VS.85%29.aspx + +SE_PRIVILEGE_ENABLED_BY_DEFAULT = (0x00000001) +SE_PRIVILEGE_ENABLED = (0x00000002) +SE_PRIVILEGE_REMOVED = (0x00000004) +SE_PRIVILEGE_USED_FOR_ACCESS = (0x80000000) + +class LUID_AND_ATTRIBUTES(ctypes.Structure): + _fields_ = [ + ('LUID', LUID), + ('attributes', wintypes.DWORD), + ] + + def is_enabled(self): + return bool(self.attributes & SE_PRIVILEGE_ENABLED) + + def enable(self): + self.attributes |= SE_PRIVILEGE_ENABLED + + def get_name(self): + size = wintypes.DWORD(10240) + buf = ctypes.create_unicode_buffer(size.value) + res = LookupPrivilegeName(None, self.LUID, buf, size) + if res == 0: + raise RuntimeError + return buf[:size.value] + + def __str__(self): + name = self.name + fmt = ['{name}', '{name} (enabled)'][self.is_enabled()] + return fmt.format(**vars()) + +LookupPrivilegeName = ctypes.windll.advapi32.LookupPrivilegeNameW +LookupPrivilegeName.argtypes = ( + wintypes.LPWSTR, # lpSystemName + ctypes.POINTER(LUID), # lpLuid + wintypes.LPWSTR, # lpName + ctypes.POINTER(wintypes.DWORD), #cchName + ) +LookupPrivilegeName.restype = wintypes.BOOL + +class TOKEN_PRIVILEGES(ctypes.Structure): + _fields_ = [ + ('count', wintypes.DWORD), + ('privileges', LUID_AND_ATTRIBUTES*0), + ] + + def get_array(self): + array_type = LUID_AND_ATTRIBUTES*self.count + privileges = ctypes.cast(self.privileges, ctypes.POINTER(array_type)).contents + return privileges + + def __iter__(self): + return iter(self.get_array()) + +PTOKEN_PRIVILEGES = ctypes.POINTER(TOKEN_PRIVILEGES) + +GetTokenInformation = ctypes.windll.advapi32.GetTokenInformation +GetTokenInformation.argtypes = [ + wintypes.HANDLE, # TokenHandle + ctypes.c_uint, # TOKEN_INFORMATION_CLASS value + ctypes.c_void_p, # TokenInformation + wintypes.DWORD, # TokenInformationLength + ctypes.POINTER(wintypes.DWORD), # ReturnLength + ] +GetTokenInformation.restype = wintypes.BOOL + +# http://msdn.microsoft.com/en-us/library/aa375202%28VS.85%29.aspx +AdjustTokenPrivileges = ctypes.windll.advapi32.AdjustTokenPrivileges +AdjustTokenPrivileges.restype = wintypes.BOOL +AdjustTokenPrivileges.argtypes = [ + wintypes.HANDLE, # TokenHandle + wintypes.BOOL, # DisableAllPrivileges + PTOKEN_PRIVILEGES, # NewState (optional) + wintypes.DWORD, # BufferLength of PreviousState + PTOKEN_PRIVILEGES, # PreviousState (out, optional) + ctypes.POINTER(wintypes.DWORD), # ReturnLength + ] + +def get_process_token(): + "Get the current process token" + token = wintypes.HANDLE() + TOKEN_ALL_ACCESS = 0xf01ff + res = OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, token) + if not res > 0: + raise RuntimeError("Couldn't get process token") + return token + +def get_symlink_luid(): + "Get the LUID for the SeCreateSymbolicLinkPrivilege" + symlink_luid = LUID() + res = LookupPrivilegeValue(None, "SeCreateSymbolicLinkPrivilege", symlink_luid) + if not res > 0: + raise RuntimeError("Couldn't lookup privilege value") + return symlink_luid + +def get_privilege_information(): + "Get all privileges associated with the current process." + # first call with zero length to determine what size buffer we need + + return_length = wintypes.DWORD() + params = [ + get_process_token(), + TOKEN_INFORMATION_CLASS.TokenPrivileges, + None, + 0, + return_length, + ] + + res = GetTokenInformation(*params) + + # assume we now have the necessary length in return_length + + buffer = ctypes.create_string_buffer(return_length.value) + params[2] = buffer + params[3] = return_length.value + + res = GetTokenInformation(*params) + assert res > 0, "Error in second GetTokenInformation (%d)" % res + + privileges = ctypes.cast(buffer, ctypes.POINTER(TOKEN_PRIVILEGES)).contents + return privileges + +def report_privilege_information(): + "Report all privilege information assigned to the current process." + privileges = get_privilege_information() + print("found {0} privileges".format(privileges.count)) + tuple(map(print, privileges)) + +def enable_symlink_privilege(): + """ + Try to assign the symlink privilege to the current process token. + Return True if the assignment is successful. + """ + # create a space in memory for a TOKEN_PRIVILEGES structure + # with one element + size = ctypes.sizeof(TOKEN_PRIVILEGES) + size += ctypes.sizeof(LUID_AND_ATTRIBUTES) + buffer = ctypes.create_string_buffer(size) + tp = ctypes.cast(buffer, ctypes.POINTER(TOKEN_PRIVILEGES)).contents + tp.count = 1 + tp.get_array()[0].enable() + tp.get_array()[0].LUID = get_symlink_luid() + token = get_process_token() + res = AdjustTokenPrivileges(token, False, tp, 0, None, None) + if res == 0: + raise RuntimeError("Error in AdjustTokenPrivileges") + + ERROR_NOT_ALL_ASSIGNED = 1300 + return ctypes.windll.kernel32.GetLastError() != ERROR_NOT_ALL_ASSIGNED + +def main(): + assigned = enable_symlink_privilege() + msg = ['failure', 'success'][assigned] + + print("Symlink privilege assignment completed with {0}".format(msg)) + +if __name__ == '__main__': + main() Modified: python/branches/py3k/Lib/test/test_glob.py ============================================================================== --- python/branches/py3k/Lib/test/test_glob.py (original) +++ python/branches/py3k/Lib/test/test_glob.py Thu Jul 8 23:39:08 2010 @@ -1,5 +1,5 @@ import unittest -from test.support import run_unittest, TESTFN +from test.support import run_unittest, TESTFN, skip_unless_symlink, can_symlink import glob import os import shutil @@ -25,7 +25,7 @@ self.mktemp('ZZZ') self.mktemp('a', 'bcd', 'EF') self.mktemp('a', 'bcd', 'efg', 'ha') - if hasattr(os, 'symlink'): + if can_symlink(): os.symlink(self.norm('broken'), self.norm('sym1')) os.symlink(self.norm('broken'), self.norm('sym2')) @@ -98,12 +98,12 @@ # either of these results are reasonable self.assertIn(res[0], [self.tempdir, self.tempdir + os.sep]) + @skip_unless_symlink def test_glob_broken_symlinks(self): - if hasattr(os, 'symlink'): - eq = self.assertSequencesEqual_noorder - eq(self.glob('sym*'), [self.norm('sym1'), self.norm('sym2')]) - eq(self.glob('sym1'), [self.norm('sym1')]) - eq(self.glob('sym2'), [self.norm('sym2')]) + eq = self.assertSequencesEqual_noorder + eq(self.glob('sym*'), [self.norm('sym1'), self.norm('sym2')]) + eq(self.glob('sym1'), [self.norm('sym1')]) + eq(self.glob('sym2'), [self.norm('sym2')]) def test_main(): Modified: python/branches/py3k/Lib/test/test_httpservers.py ============================================================================== --- python/branches/py3k/Lib/test/test_httpservers.py (original) +++ python/branches/py3k/Lib/test/test_httpservers.py Thu Jul 8 23:39:08 2010 @@ -299,7 +299,7 @@ # The shebang line should be pure ASCII: use symlink if possible. # See issue #7668. - if hasattr(os, 'symlink'): + if support.can_symlink(): self.pythonexe = os.path.join(self.parent_dir, 'python') os.symlink(sys.executable, self.pythonexe) else: Modified: python/branches/py3k/Lib/test/test_os.py ============================================================================== --- python/branches/py3k/Lib/test/test_os.py (original) +++ python/branches/py3k/Lib/test/test_os.py Thu Jul 8 23:39:08 2010 @@ -520,7 +520,7 @@ f = open(path, "w") f.write("I'm " + path + " and proud of it. Blame test_os.\n") f.close() - if hasattr(os, "symlink"): + if support.can_symlink(): os.symlink(os.path.abspath(t2_path), link_path) sub2_tree = (sub2_path, ["link"], ["tmp3"]) else: @@ -564,7 +564,7 @@ self.assertEqual(all[flipped + 1], (sub1_path, ["SUB11"], ["tmp2"])) self.assertEqual(all[2 - 2 * flipped], sub2_tree) - if hasattr(os, "symlink"): + if support.can_symlink(): # Walk, following symlinks. for root, dirs, files in os.walk(walk_path, followlinks=True): if root == link_path: @@ -1033,6 +1033,83 @@ self._kill_with_event(signal.CTRL_BREAK_EVENT, "CTRL_BREAK_EVENT") +def skipUnlessWindows6(test): + if hasattr(sys, 'getwindowsversion') and sys.getwindowsversion().major >= 6: + return test + return unittest.skip("Requires Windows Vista or later")(test) + + at unittest.skipUnless(sys.platform == "win32", "Win32 specific tests") + at support.skip_unless_symlink +class Win32SymlinkTests(unittest.TestCase): + filelink = 'filelinktest' + filelink_target = os.path.abspath(__file__) + dirlink = 'dirlinktest' + dirlink_target = os.path.dirname(filelink_target) + missing_link = 'missing link' + + def setUp(self): + assert os.path.exists(self.dirlink_target) + assert os.path.exists(self.filelink_target) + assert not os.path.exists(self.dirlink) + assert not os.path.exists(self.filelink) + assert not os.path.exists(self.missing_link) + + def tearDown(self): + if os.path.exists(self.filelink): + os.remove(self.filelink) + if os.path.exists(self.dirlink): + os.rmdir(self.dirlink) + if os.path.lexists(self.missing_link): + os.remove(self.missing_link) + + def test_directory_link(self): + os.symlink(self.dirlink_target, self.dirlink) + self.assertTrue(os.path.exists(self.dirlink)) + self.assertTrue(os.path.isdir(self.dirlink)) + self.assertTrue(os.path.islink(self.dirlink)) + self.check_stat(self.dirlink, self.dirlink_target) + + def test_file_link(self): + os.symlink(self.filelink_target, self.filelink) + self.assertTrue(os.path.exists(self.filelink)) + self.assertTrue(os.path.isfile(self.filelink)) + self.assertTrue(os.path.islink(self.filelink)) + self.check_stat(self.filelink, self.filelink_target) + + def _create_missing_dir_link(self): + 'Create a "directory" link to a non-existent target' + linkname = self.missing_link + if os.path.lexists(linkname): + os.remove(linkname) + target = r'c:\\target does not exist.29r3c740' + assert not os.path.exists(target) + target_is_dir = True + os.symlink(target, linkname, target_is_dir) + + def test_remove_directory_link_to_missing_target(self): + self._create_missing_dir_link() + # For compatibility with Unix, os.remove will check the + # directory status and call RemoveDirectory if the symlink + # was created with target_is_dir==True. + os.remove(self.missing_link) + + @unittest.skip("currently fails; consider for improvement") + def test_isdir_on_directory_link_to_missing_target(self): + self._create_missing_dir_link() + # consider having isdir return true for directory links + self.assertTrue(os.path.isdir(self.missing_link)) + + @unittest.skip("currently fails; consider for improvement") + def test_rmdir_on_directory_link_to_missing_target(self): + self._create_missing_dir_link() + # consider allowing rmdir to remove directory links + os.rmdir(self.missing_link) + + def check_stat(self, link, target): + self.assertEqual(os.stat(link), os.stat(target)) + self.assertNotEqual(os.lstat(link), os.stat(link)) + + class MiscTests(unittest.TestCase): @unittest.skipIf(os.name == "nt", "POSIX specific test") @@ -1056,6 +1133,7 @@ PosixUidGidTests, Pep383Tests, Win32KillTests, + Win32SymlinkTests, MiscTests, ) Modified: python/branches/py3k/Lib/test/test_platform.py ============================================================================== --- python/branches/py3k/Lib/test/test_platform.py (original) +++ python/branches/py3k/Lib/test/test_platform.py Thu Jul 8 23:39:08 2010 @@ -10,20 +10,26 @@ def test_architecture(self): res = platform.architecture() - if hasattr(os, "symlink"): - def test_architecture_via_symlink(self): # issue3762 - def get(python): - cmd = [python, '-c', - 'import platform; print(platform.architecture())'] - p = subprocess.Popen(cmd, stdout=subprocess.PIPE) - return p.communicate() - real = os.path.realpath(sys.executable) - link = os.path.abspath(support.TESTFN) - os.symlink(real, link) - try: - self.assertEqual(get(real), get(link)) - finally: - os.remove(link) + @support.skip_unless_symlink + def test_architecture_via_symlink(self): # issue3762 + # On Windows, the EXE needs to know where pythonXY.dll is at so we have + # to add the directory to the path. + if sys.platform == "win32": + os.environ["Path"] = "{};{}".format(os.path.dirname(sys.executable), + os.environ["Path"]) + + def get(python): + cmd = [python, '-c', + 'import platform; print(platform.architecture())'] + p = subprocess.Popen(cmd, stdout=subprocess.PIPE) + return p.communicate() + real = os.path.realpath(sys.executable) + link = os.path.abspath(support.TESTFN) + os.symlink(real, link) + try: + self.assertEqual(get(real), get(link)) + finally: + os.remove(link) def test_platform(self): for aliased in (False, True): Modified: python/branches/py3k/Lib/test/test_posixpath.py ============================================================================== --- python/branches/py3k/Lib/test/test_posixpath.py (original) +++ python/branches/py3k/Lib/test/test_posixpath.py Thu Jul 8 23:39:08 2010 @@ -1,7 +1,9 @@ import unittest from test import support, test_genericpath -import posixpath, os +import posixpath +import os +import sys from posixpath import realpath, abspath, dirname, basename # An absolute path to a temporary filename for testing. We can't rely on TESTFN @@ -9,6 +11,16 @@ ABSTFN = abspath(support.TESTFN) +def skip_if_ABSTFN_contains_backslash(test): + """ + On Windows, posixpath.abspath still returns paths with backslashes + instead of posix forward slashes. If this is the case, several tests + fail, so skip them. + """ + found_backslash = '\\' in ABSTFN + msg = "ABSTFN is not a posix path - tests fail" + return [test, unittest.skip(msg)(test)][found_backslash] + def safe_rmdir(dirname): try: os.rmdir(dirname) @@ -143,7 +155,7 @@ f.write(b"foo") f.close() self.assertIs(posixpath.islink(support.TESTFN + "1"), False) - if hasattr(os, "symlink"): + if support.can_symlink(): os.symlink(support.TESTFN + "1", support.TESTFN + "2") self.assertIs(posixpath.islink(support.TESTFN + "2"), True) os.remove(support.TESTFN + "1") @@ -154,85 +166,59 @@ if not f.close(): f.close() + @staticmethod + def _create_file(filename): + with open(filename, 'wb') as f: + f.write(b'foo') + def test_samefile(self): - f = open(support.TESTFN + "1", "wb") - try: - f.write(b"foo") - f.close() - self.assertIs( - posixpath.samefile( - support.TESTFN + "1", - support.TESTFN + "1" - ), - True - ) - # If we don't have links, assume that os.stat doesn't return resonable - # inode information and thus, that samefile() doesn't work - if hasattr(os, "symlink"): - os.symlink( - support.TESTFN + "1", - support.TESTFN + "2" - ) - self.assertIs( - posixpath.samefile( - support.TESTFN + "1", - support.TESTFN + "2" - ), - True - ) - os.remove(support.TESTFN + "2") - f = open(support.TESTFN + "2", "wb") - f.write(b"bar") - f.close() - self.assertIs( - posixpath.samefile( - support.TESTFN + "1", - support.TESTFN + "2" - ), - False - ) - finally: - if not f.close(): - f.close() + test_fn = support.TESTFN + "1" + self._create_file(test_fn) + self.assertTrue(posixpath.samefile(test_fn, test_fn)) + self.assertRaises(TypeError, posixpath.samefile) + + @unittest.skipIf( + sys.platform.startswith('win'), + "posixpath.samefile does not work on links in Windows") + @support.skip_unless_symlink + def test_samefile_on_links(self): + test_fn1 = support.TESTFN + "1" + test_fn2 = support.TESTFN + "2" + self._create_file(test_fn1) + + os.symlink(test_fn1, test_fn2) + self.assertTrue(posixpath.samefile(test_fn1, test_fn2)) + os.remove(test_fn2) + + self._create_file(test_fn2) + self.assertFalse(posixpath.samefile(test_fn1, test_fn2)) + def test_samestat(self): - f = open(support.TESTFN + "1", "wb") - try: - f.write(b"foo") - f.close() - self.assertIs( - posixpath.samestat( - os.stat(support.TESTFN + "1"), - os.stat(support.TESTFN + "1") - ), - True - ) - # If we don't have links, assume that os.stat() doesn't return resonable - # inode information and thus, that samefile() doesn't work - if hasattr(os, "symlink"): - if hasattr(os, "symlink"): - os.symlink(support.TESTFN + "1", support.TESTFN + "2") - self.assertIs( - posixpath.samestat( - os.stat(support.TESTFN + "1"), - os.stat(support.TESTFN + "2") - ), - True - ) - os.remove(support.TESTFN + "2") - f = open(support.TESTFN + "2", "wb") - f.write(b"bar") - f.close() - self.assertIs( - posixpath.samestat( - os.stat(support.TESTFN + "1"), - os.stat(support.TESTFN + "2") - ), - False - ) - finally: - if not f.close(): - f.close() + test_fn = support.TESTFN + "1" + self._create_file(test_fn) + test_fns = [test_fn]*2 + stats = map(os.stat, test_fns) + self.assertTrue(posixpath.samestat(*stats)) + + @unittest.skipIf( + sys.platform.startswith('win'), + "posixpath.samestat does not work on links in Windows") + @support.skip_unless_symlink + def test_samestat_on_links(self): + test_fn1 = support.TESTFN + "1" + test_fn2 = support.TESTFN + "2" + test_fns = (test_fn1, test_fn2) + os.symlink(*test_fns) + stats = map(os.stat, test_fns) + self.assertTrue(posixpath.samestat(*stats)) + os.remove(test_fn2) + + self._create_file(test_fn2) + stats = map(os.stat, test_fns) + self.assertFalse(posixpath.samestat(*stats)) + + self.assertRaises(TypeError, posixpath.samestat) def test_ismount(self): self.assertIs(posixpath.ismount("/"), True) @@ -286,103 +272,112 @@ self.assertEqual(posixpath.normpath(b"///..//./foo/.//bar"), b"/foo/bar") - if hasattr(os, "symlink"): - def test_realpath_basic(self): - # Basic operation. - try: - os.symlink(ABSTFN+"1", ABSTFN) - self.assertEqual(realpath(ABSTFN), ABSTFN+"1") - finally: - support.unlink(ABSTFN) - - def test_realpath_symlink_loops(self): - # Bug #930024, return the path unchanged if we get into an infinite - # symlink loop. - try: - old_path = abspath('.') - os.symlink(ABSTFN, ABSTFN) - self.assertEqual(realpath(ABSTFN), ABSTFN) - - os.symlink(ABSTFN+"1", ABSTFN+"2") - os.symlink(ABSTFN+"2", ABSTFN+"1") - self.assertEqual(realpath(ABSTFN+"1"), ABSTFN+"1") - self.assertEqual(realpath(ABSTFN+"2"), ABSTFN+"2") - - # Test using relative path as well. - os.chdir(dirname(ABSTFN)) - self.assertEqual(realpath(basename(ABSTFN)), ABSTFN) - finally: - os.chdir(old_path) - support.unlink(ABSTFN) - support.unlink(ABSTFN+"1") - support.unlink(ABSTFN+"2") - - def test_realpath_resolve_parents(self): - # We also need to resolve any symlinks in the parents of a relative - # path passed to realpath. E.g.: current working directory is - # /usr/doc with 'doc' being a symlink to /usr/share/doc. We call - # realpath("a"). This should return /usr/share/doc/a/. - try: - old_path = abspath('.') - os.mkdir(ABSTFN) - os.mkdir(ABSTFN + "/y") - os.symlink(ABSTFN + "/y", ABSTFN + "/k") - - os.chdir(ABSTFN + "/k") - self.assertEqual(realpath("a"), ABSTFN + "/y/a") - finally: - os.chdir(old_path) - support.unlink(ABSTFN + "/k") - safe_rmdir(ABSTFN + "/y") - safe_rmdir(ABSTFN) - - def test_realpath_resolve_before_normalizing(self): - # Bug #990669: Symbolic links should be resolved before we - # normalize the path. E.g.: if we have directories 'a', 'k' and 'y' - # in the following hierarchy: - # a/k/y - # - # and a symbolic link 'link-y' pointing to 'y' in directory 'a', - # then realpath("link-y/..") should return 'k', not 'a'. - try: - old_path = abspath('.') - os.mkdir(ABSTFN) - os.mkdir(ABSTFN + "/k") - os.mkdir(ABSTFN + "/k/y") - os.symlink(ABSTFN + "/k/y", ABSTFN + "/link-y") - - # Absolute path. - self.assertEqual(realpath(ABSTFN + "/link-y/.."), ABSTFN + "/k") - # Relative path. - os.chdir(dirname(ABSTFN)) - self.assertEqual(realpath(basename(ABSTFN) + "/link-y/.."), - ABSTFN + "/k") - finally: - os.chdir(old_path) - support.unlink(ABSTFN + "/link-y") - safe_rmdir(ABSTFN + "/k/y") - safe_rmdir(ABSTFN + "/k") - safe_rmdir(ABSTFN) - - def test_realpath_resolve_first(self): - # Bug #1213894: The first component of the path, if not absolute, - # must be resolved too. - - try: - old_path = abspath('.') - os.mkdir(ABSTFN) - os.mkdir(ABSTFN + "/k") - os.symlink(ABSTFN, ABSTFN + "link") - os.chdir(dirname(ABSTFN)) - - base = basename(ABSTFN) - self.assertEqual(realpath(base + "link"), ABSTFN) - self.assertEqual(realpath(base + "link/k"), ABSTFN + "/k") - finally: - os.chdir(old_path) - support.unlink(ABSTFN + "link") - safe_rmdir(ABSTFN + "/k") - safe_rmdir(ABSTFN) + @support.skip_unless_symlink + @skip_if_ABSTFN_contains_backslash + def test_realpath_basic(self): + # Basic operation. + try: + os.symlink(ABSTFN+"1", ABSTFN) + self.assertEqual(realpath(ABSTFN), ABSTFN+"1") + finally: + support.unlink(ABSTFN) + + @support.skip_unless_symlink + @skip_if_ABSTFN_contains_backslash + def test_realpath_symlink_loops(self): + # Bug #930024, return the path unchanged if we get into an infinite + # symlink loop. + try: + old_path = abspath('.') + os.symlink(ABSTFN, ABSTFN) + self.assertEqual(realpath(ABSTFN), ABSTFN) + + os.symlink(ABSTFN+"1", ABSTFN+"2") + os.symlink(ABSTFN+"2", ABSTFN+"1") + self.assertEqual(realpath(ABSTFN+"1"), ABSTFN+"1") + self.assertEqual(realpath(ABSTFN+"2"), ABSTFN+"2") + + # Test using relative path as well. + os.chdir(dirname(ABSTFN)) + self.assertEqual(realpath(basename(ABSTFN)), ABSTFN) + finally: + os.chdir(old_path) + support.unlink(ABSTFN) + support.unlink(ABSTFN+"1") + support.unlink(ABSTFN+"2") + + @support.skip_unless_symlink + @skip_if_ABSTFN_contains_backslash + def test_realpath_resolve_parents(self): + # We also need to resolve any symlinks in the parents of a relative + # path passed to realpath. E.g.: current working directory is + # /usr/doc with 'doc' being a symlink to /usr/share/doc. We call + # realpath("a"). This should return /usr/share/doc/a/. + try: + old_path = abspath('.') + os.mkdir(ABSTFN) + os.mkdir(ABSTFN + "/y") + os.symlink(ABSTFN + "/y", ABSTFN + "/k") + + os.chdir(ABSTFN + "/k") + self.assertEqual(realpath("a"), ABSTFN + "/y/a") + finally: + os.chdir(old_path) + support.unlink(ABSTFN + "/k") + safe_rmdir(ABSTFN + "/y") + safe_rmdir(ABSTFN) + + @support.skip_unless_symlink + @skip_if_ABSTFN_contains_backslash + def test_realpath_resolve_before_normalizing(self): + # Bug #990669: Symbolic links should be resolved before we + # normalize the path. E.g.: if we have directories 'a', 'k' and 'y' + # in the following hierarchy: + # a/k/y + # + # and a symbolic link 'link-y' pointing to 'y' in directory 'a', + # then realpath("link-y/..") should return 'k', not 'a'. + try: + old_path = abspath('.') + os.mkdir(ABSTFN) + os.mkdir(ABSTFN + "/k") + os.mkdir(ABSTFN + "/k/y") + os.symlink(ABSTFN + "/k/y", ABSTFN + "/link-y") + + # Absolute path. + self.assertEqual(realpath(ABSTFN + "/link-y/.."), ABSTFN + "/k") + # Relative path. + os.chdir(dirname(ABSTFN)) + self.assertEqual(realpath(basename(ABSTFN) + "/link-y/.."), + ABSTFN + "/k") + finally: + os.chdir(old_path) + support.unlink(ABSTFN + "/link-y") + safe_rmdir(ABSTFN + "/k/y") + safe_rmdir(ABSTFN + "/k") + safe_rmdir(ABSTFN) + + @support.skip_unless_symlink + @skip_if_ABSTFN_contains_backslash + def test_realpath_resolve_first(self): + # Bug #1213894: The first component of the path, if not absolute, + # must be resolved too. + + try: + old_path = abspath('.') + os.mkdir(ABSTFN) + os.mkdir(ABSTFN + "/k") + os.symlink(ABSTFN, ABSTFN + "link") + os.chdir(dirname(ABSTFN)) + + base = basename(ABSTFN) + self.assertEqual(realpath(base + "link"), ABSTFN) + self.assertEqual(realpath(base + "link/k"), ABSTFN + "/k") + finally: + os.chdir(old_path) + support.unlink(ABSTFN + "link") + safe_rmdir(ABSTFN + "/k") + safe_rmdir(ABSTFN) def test_relpath(self): (real_getcwd, os.getcwd) = (os.getcwd, lambda: r"/home/user/bar") Modified: python/branches/py3k/Lib/test/test_shutil.py ============================================================================== --- python/branches/py3k/Lib/test/test_shutil.py (original) +++ python/branches/py3k/Lib/test/test_shutil.py Thu Jul 8 23:39:08 2010 @@ -271,7 +271,7 @@ shutil.rmtree(src_dir) shutil.rmtree(os.path.dirname(dst_dir)) - @unittest.skipUnless(hasattr(os, 'symlink'), 'requires os.symlink') + @support.skip_unless_symlink def test_dont_copy_file_onto_link_to_itself(self): # bug 851123. os.mkdir(TESTFN) @@ -282,10 +282,11 @@ f.write('cheddar') f.close() - os.link(src, dst) - self.assertRaises(shutil.Error, shutil.copyfile, src, dst) - self.assertEqual(open(src,'r').read(), 'cheddar') - os.remove(dst) + if hasattr(os, "link"): + os.link(src, dst) + self.assertRaises(shutil.Error, shutil.copyfile, src, dst) + self.assertEqual(open(src,'r').read(), 'cheddar') + os.remove(dst) # Using `src` here would mean we end up with a symlink pointing # to TESTFN/TESTFN/cheese, while it should point at @@ -300,30 +301,30 @@ except OSError: pass - @unittest.skipUnless(hasattr(os, 'symlink'), 'requires os.symlink') - def test_rmtree_on_symlink(self): - # bug 1669. - os.mkdir(TESTFN) + @support.skip_unless_symlink + def test_rmtree_on_symlink(self): + # bug 1669. + os.mkdir(TESTFN) + try: + src = os.path.join(TESTFN, 'cheese') + dst = os.path.join(TESTFN, 'shop') + os.mkdir(src) + os.symlink(src, dst) + self.assertRaises(OSError, shutil.rmtree, dst) + finally: + shutil.rmtree(TESTFN, ignore_errors=True) + + if hasattr(os, "mkfifo"): + # Issue #3002: copyfile and copytree block indefinitely on named pipes + def test_copyfile_named_pipe(self): + os.mkfifo(TESTFN) try: - src = os.path.join(TESTFN, 'cheese') - dst = os.path.join(TESTFN, 'shop') - os.mkdir(src) - os.symlink(src, dst) - self.assertRaises(OSError, shutil.rmtree, dst) + self.assertRaises(shutil.SpecialFileError, + shutil.copyfile, TESTFN, TESTFN2) + self.assertRaises(shutil.SpecialFileError, + shutil.copyfile, __file__, TESTFN) finally: - shutil.rmtree(TESTFN, ignore_errors=True) - - @unittest.skipUnless(hasattr(os, 'mkfifo'), 'requires os.mkfifo') - # Issue #3002: copyfile and copytree block indefinitely on named pipes - def test_copyfile_named_pipe(self): - os.mkfifo(TESTFN) - try: - self.assertRaises(shutil.SpecialFileError, - shutil.copyfile, TESTFN, TESTFN2) - self.assertRaises(shutil.SpecialFileError, - shutil.copyfile, __file__, TESTFN) - finally: - os.remove(TESTFN) + os.remove(TESTFN) @unittest.skipUnless(hasattr(os, 'mkfifo'), 'requires os.mkfifo') def test_copytree_named_pipe(self): @@ -361,7 +362,7 @@ shutil.copytree(src_dir, dst_dir, copy_function=_copy) self.assertEquals(len(copied), 2) - @unittest.skipUnless(hasattr(os, 'symlink'), 'requires os.symlink') + @support.skip_unless_symlink def test_copytree_dangling_symlinks(self): # a dangling symlink raises an error at the end Modified: python/branches/py3k/Lib/test/test_sys.py ============================================================================== --- python/branches/py3k/Lib/test/test_sys.py (original) +++ python/branches/py3k/Lib/test/test_sys.py Thu Jul 8 23:39:08 2010 @@ -263,7 +263,7 @@ # Raise SkipTest if sys doesn't have getwindowsversion attribute test.support.get_attribute(sys, "getwindowsversion") v = sys.getwindowsversion() - self.assertEqual(len(v), 5) + self.assertEqual(len(v), 9) self.assertIsInstance(v[0], int) self.assertIsInstance(v[1], int) self.assertIsInstance(v[2], int) Modified: python/branches/py3k/Lib/test/test_sysconfig.py ============================================================================== --- python/branches/py3k/Lib/test/test_sysconfig.py (original) +++ python/branches/py3k/Lib/test/test_sysconfig.py Thu Jul 8 23:39:08 2010 @@ -12,7 +12,7 @@ from copy import copy, deepcopy from test.support import (run_unittest, TESTFN, unlink, get_attribute, - captured_stdout) + captured_stdout, skip_unless_symlink) import sysconfig from sysconfig import (get_paths, get_platform, get_config_vars, @@ -239,17 +239,23 @@ 'posix_home', 'posix_prefix', 'posix_user') self.assertEquals(get_scheme_names(), wanted) + @skip_unless_symlink def test_symlink(self): + # On Windows, the EXE needs to know where pythonXY.dll is at so we have + # to add the directory to the path. + if sys.platform == "win32": + os.environ["Path"] = "{};{}".format(os.path.dirname(sys.executable), + os.environ["Path"]) + # Issue 7880 - symlink = get_attribute(os, "symlink") def get(python): cmd = [python, '-c', 'import sysconfig; print(sysconfig.get_platform())'] - p = subprocess.Popen(cmd, stdout=subprocess.PIPE) + p = subprocess.Popen(cmd, stdout=subprocess.PIPE, env=os.environ) return p.communicate() real = os.path.realpath(sys.executable) link = os.path.abspath(TESTFN) - symlink(real, link) + os.symlink(real, link) try: self.assertEqual(get(real), get(link)) finally: Modified: python/branches/py3k/Lib/test/test_tarfile.py ============================================================================== --- python/branches/py3k/Lib/test/test_tarfile.py (original) +++ python/branches/py3k/Lib/test/test_tarfile.py Thu Jul 8 23:39:08 2010 @@ -291,6 +291,8 @@ self.assertTrue(self.tar.getmembers()[-1].name == "misc/eof", "could not find all members") + @unittest.skipUnless(hasattr(os, "link"), "Missing hardlink implementation") + @support.skip_unless_symlink def test_extract_hardlink(self): # Test hardlink extraction (e.g. bug #857297). tar = tarfile.open(tarname, errorlevel=1, encoding="iso8859-1") @@ -695,16 +697,16 @@ os.remove(target) os.remove(link) + @support.skip_unless_symlink def test_symlink_size(self): - if hasattr(os, "symlink"): - path = os.path.join(TEMPDIR, "symlink") - os.symlink("link_target", path) - try: - tar = tarfile.open(tmpname, self.mode) - tarinfo = tar.gettarinfo(path) - self.assertEqual(tarinfo.size, 0) - finally: - os.remove(path) + path = os.path.join(TEMPDIR, "symlink") + os.symlink("link_target", path) + try: + tar = tarfile.open(tmpname, self.mode) + tarinfo = tar.gettarinfo(path) + self.assertEqual(tarinfo.size, 0) + finally: + os.remove(path) def test_add_self(self): # Test for #1257255. @@ -1408,15 +1410,24 @@ data = open(os.path.join(TEMPDIR, name), "rb").read() self.assertEqual(md5sum(data), md5_regtype) + # When 8879 gets fixed, this will need to change. Currently on Windows + # we have os.path.islink but no os.link, so these tests fail without the + # following skip until link is completed. + @unittest.skipIf(hasattr(os.path, "islink"), + "Skip emulation - has os.path.islink but not os.link") def test_hardlink_extraction1(self): self._test_link_extraction("ustar/lnktype") + @unittest.skipIf(hasattr(os.path, "islink"), + "Skip emulation - has os.path.islink but not os.link") def test_hardlink_extraction2(self): self._test_link_extraction("./ustar/linktest2/lnktype") + @unittest.skipIf(hasattr(os, "symlink"), "Skip emulation if symlink exists") def test_symlink_extraction1(self): self._test_link_extraction("ustar/symtype") + @unittest.skipIf(hasattr(os, "symlink"), "Skip emulation if symlink exists") def test_symlink_extraction2(self): self._test_link_extraction("./ustar/linktest2/symtype") Modified: python/branches/py3k/Misc/ACKS ============================================================================== --- python/branches/py3k/Misc/ACKS (original) +++ python/branches/py3k/Misc/ACKS Thu Jul 8 23:39:08 2010 @@ -154,6 +154,7 @@ Jeffery Collins Robert Collins Paul Colomiets +Jason R. Coombs Geremy Condra Juan Jos? Conti Matt Conway Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Thu Jul 8 23:39:08 2010 @@ -1406,6 +1406,9 @@ Extension Modules ----------------- +- Issue #1578269: Implement os.symlink for Windows 6.0+. Patch by + Jason R. Coombs + - In struct.pack, correctly propogate exceptions from computing the truth of an object in the '?' format. Modified: python/branches/py3k/Modules/posixmodule.c ============================================================================== --- python/branches/py3k/Modules/posixmodule.c (original) +++ python/branches/py3k/Modules/posixmodule.c Thu Jul 8 23:39:08 2010 @@ -571,7 +571,7 @@ #ifdef MS_WINDOWS static PyObject * -win32_error(char* function, char* filename) +win32_error(char* function, const char* filename) { /* XXX We should pass the function name along in the future. (winreg.c also wants to pass the function name.) @@ -978,12 +978,28 @@ return TRUE; } -static int -win32_stat(const char* path, struct win32_stat *result) +/* About the following functions: win32_lstat, win32_lstat_w, win32_stat, + win32_stat_w + + In Posix, stat automatically traverses symlinks and returns the stat + structure for the target. In Windows, the equivalent GetFileAttributes by + default does not traverse symlinks and instead returns attributes for + the symlink. + + Therefore, win32_lstat will get the attributes traditionally, and + win32_stat will first explicitly resolve the symlink target and then will + call win32_lstat on that result. + + The _w represent Unicode equivalents of the aformentioned ANSI functions. */ + +static int +win32_lstat(const char* path, struct win32_stat *result) { WIN32_FILE_ATTRIBUTE_DATA info; int code; char *dot; + WIN32_FIND_DATAA find_data; + HANDLE find_data_handle; if (!GetFileAttributesExA(path, GetFileExInfoStandard, &info)) { if (GetLastError() != ERROR_SHARING_VIOLATION) { /* Protocol violation: we explicitly clear errno, instead of @@ -1000,27 +1016,44 @@ } } } + code = attribute_data_to_stat(&info, result); if (code != 0) return code; + + /* Get WIN32_FIND_DATA structure for the path to determine if + it is a symlink */ + if(info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { + find_data_handle = FindFirstFileA(path, &find_data); + if(find_data_handle != INVALID_HANDLE_VALUE) { + if(find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK) { + /* first clear the S_IFMT bits */ + result->st_mode ^= (result->st_mode & 0170000); + /* now set the bits that make this a symlink */ + result->st_mode |= 0120000; + } + FindClose(find_data_handle); + } + } + /* Set S_IFEXEC if it is an .exe, .bat, ... */ dot = strrchr(path, '.'); if (dot) { - if (stricmp(dot, ".bat") == 0 || - stricmp(dot, ".cmd") == 0 || - stricmp(dot, ".exe") == 0 || - stricmp(dot, ".com") == 0) + if (stricmp(dot, ".bat") == 0 || stricmp(dot, ".cmd") == 0 || + stricmp(dot, ".exe") == 0 || stricmp(dot, ".com") == 0) result->st_mode |= 0111; } return code; } static int -win32_wstat(const wchar_t* path, struct win32_stat *result) +win32_lstat_w(const wchar_t* path, struct win32_stat *result) { int code; const wchar_t *dot; WIN32_FILE_ATTRIBUTE_DATA info; + WIN32_FIND_DATAW find_data; + HANDLE find_data_handle; if (!GetFileAttributesExW(path, GetFileExInfoStandard, &info)) { if (GetLastError() != ERROR_SHARING_VIOLATION) { /* Protocol violation: we explicitly clear errno, instead of @@ -1028,8 +1061,8 @@ errno = 0; return -1; } else { - /* Could not get attributes on open file. Fall back to - reading the directory. */ + /* Could not get attributes on open file. Fall back to reading + the directory. */ if (!attributes_from_dir_w(path, &info)) { /* Very strange. This should not fail now */ errno = 0; @@ -1040,18 +1073,198 @@ code = attribute_data_to_stat(&info, result); if (code < 0) return code; + + /* Get WIN32_FIND_DATA structure for the path to determine if + it is a symlink */ + if(info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { + find_data_handle = FindFirstFileW(path, &find_data); + if(find_data_handle != INVALID_HANDLE_VALUE) { + if(find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK) { + /* first clear the S_IFMT bits */ + result->st_mode ^= (result->st_mode & 0170000); + /* now set the bits that make this a symlink */ + result->st_mode |= 0120000; + } + FindClose(find_data_handle); + } + } + /* Set IFEXEC if it is an .exe, .bat, ... */ dot = wcsrchr(path, '.'); if (dot) { - if (_wcsicmp(dot, L".bat") == 0 || - _wcsicmp(dot, L".cmd") == 0 || - _wcsicmp(dot, L".exe") == 0 || - _wcsicmp(dot, L".com") == 0) + if (_wcsicmp(dot, L".bat") == 0 || _wcsicmp(dot, L".cmd") == 0 || + _wcsicmp(dot, L".exe") == 0 || _wcsicmp(dot, L".com") == 0) result->st_mode |= 0111; } return code; } +/* Grab GetFinalPathNameByHandle dynamically from kernel32 */ +static int has_GetFinalPathNameByHandle = 0; +static DWORD (CALLBACK *Py_GetFinalPathNameByHandleA)(HANDLE, LPSTR, DWORD, + DWORD); +static DWORD (CALLBACK *Py_GetFinalPathNameByHandleW)(HANDLE, LPWSTR, DWORD, + DWORD); +static int +check_GetFinalPathNameByHandle() +{ + HINSTANCE hKernel32; + /* only recheck */ + if (!has_GetFinalPathNameByHandle) + { + hKernel32 = GetModuleHandle("KERNEL32"); + *(FARPROC*)&Py_GetFinalPathNameByHandleA = GetProcAddress(hKernel32, + "GetFinalPathNameByHandleA"); + *(FARPROC*)&Py_GetFinalPathNameByHandleW = GetProcAddress(hKernel32, + "GetFinalPathNameByHandleW"); + has_GetFinalPathNameByHandle = Py_GetFinalPathNameByHandleA && Py_GetFinalPathNameByHandleW; + } + return has_GetFinalPathNameByHandle; +} + +static int +win32_stat(const char* path, struct win32_stat *result) +{ + /* Traverse the symlink to the target using + GetFinalPathNameByHandle() + */ + int code; + HANDLE hFile; + int buf_size; + char *target_path; + int result_length; + WIN32_FILE_ATTRIBUTE_DATA info; + + if(!check_GetFinalPathNameByHandle()) { + /* if the OS doesn't have GetFinalPathNameByHandle, it doesn't + have symlinks, so just fall back to the traditional behavior + found in lstat. */ + return win32_lstat(path, result); + } + + hFile = CreateFileA( + path, + 0, /* desired access */ + 0, /* share mode */ + NULL, /* security attributes */ + OPEN_EXISTING, + /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */ + FILE_FLAG_BACKUP_SEMANTICS, + NULL); + + if(hFile == INVALID_HANDLE_VALUE) { + /* Either the target doesn't exist, or we don't have access to + get a handle to it. If the former, we need to return an error. + If the latter, we can use attributes_from_dir. */ + if (GetLastError() != ERROR_SHARING_VIOLATION) { + /* Protocol violation: we explicitly clear errno, instead of + setting it to a POSIX error. Callers should use GetLastError. */ + errno = 0; + return -1; + } else { + /* Could not get attributes on open file. Fall back to + reading the directory. */ + if (!attributes_from_dir(path, &info)) { + /* Very strange. This should not fail now */ + errno = 0; + return -1; + } + } + code = attribute_data_to_stat(&info, result); + } + + buf_size = Py_GetFinalPathNameByHandleA(hFile, 0, 0, VOLUME_NAME_DOS); + if(!buf_size) return -1; + target_path = (char *)malloc((buf_size+1)*sizeof(char)); + result_length = Py_GetFinalPathNameByHandleA(hFile, target_path, + buf_size, VOLUME_NAME_DOS); + + if(!result_length) + return -1; + + if(!CloseHandle(hFile)) + return -1; + + target_path[result_length] = 0; + code = win32_lstat(target_path, result); + free(target_path); + + return code; +} + +static int +win32_stat_w(const wchar_t* path, struct win32_stat *result) +{ + /* Traverse the symlink to the target using GetFinalPathNameByHandle() */ + int code; + HANDLE hFile; + int buf_size; + wchar_t *target_path; + int result_length; + WIN32_FILE_ATTRIBUTE_DATA info; + + if(!check_GetFinalPathNameByHandle()) { + /* If the OS doesn't have GetFinalPathNameByHandle, it doesn't have + symlinks, so just fall back to the traditional behavior found + in lstat. */ + return win32_lstat_w(path, result); + } + + hFile = CreateFileW( + path, + 0, /* desired access */ + 0, /* share mode */ + NULL, /* security attributes */ + OPEN_EXISTING, + /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */ + FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS, + NULL); + + if(hFile == INVALID_HANDLE_VALUE) { + /* Either the target doesn't exist, or we don't have access to + get a handle to it. If the former, we need to return an error. + If the latter, we can use attributes_from_dir. */ + if (GetLastError() != ERROR_SHARING_VIOLATION) { + /* Protocol violation: we explicitly clear errno, instead of + setting it to a POSIX error. Callers should use GetLastError. */ + errno = 0; + return -1; + } else { + /* Could not get attributes on open file. Fall back to + reading the directory. */ + if (!attributes_from_dir_w(path, &info)) { + /* Very strange. This should not fail now */ + errno = 0; + return -1; + } + } + code = attribute_data_to_stat(&info, result); + } + else { + /* We have a good handle to the target, use it to determine the target + path name (then we'll call lstat on it). */ + buf_size = Py_GetFinalPathNameByHandleW(hFile, 0, 0, VOLUME_NAME_DOS); + if(!buf_size) + return -1; + + target_path = (wchar_t *)malloc((buf_size+1)*sizeof(wchar_t)); + result_length = Py_GetFinalPathNameByHandleW(hFile, target_path, + buf_size, VOLUME_NAME_DOS); + + if(!result_length) + return -1; + + if(!CloseHandle(hFile)) + return -1; + + target_path[result_length] = 0; + code = win32_lstat_w(target_path, result); + free(target_path); + } + + return code; +} + static int win32_fstat(int file_number, struct win32_stat *result) { @@ -2443,6 +2656,69 @@ } return PyBytes_FromString(outbuf); } /* end of posix__getfullpathname */ + +/* A helper function for samepath on windows */ +static PyObject * +posix__getfinalpathname(PyObject *self, PyObject *args) +{ + HANDLE hFile; + int buf_size; + wchar_t *target_path; + int result_length; + PyObject *result; + wchar_t *path; + + if (!PyArg_ParseTuple(args, "u|:_getfullpathname", &path)) { + return NULL; + } + + if(!check_GetFinalPathNameByHandle()) { + /* If the OS doesn't have GetFinalPathNameByHandle, return a + NotImplementedError. */ + return PyErr_Format(PyExc_NotImplementedError, + "GetFinalPathNameByHandle not available on this platform"); + } + + hFile = CreateFileW( + path, + 0, /* desired access */ + 0, /* share mode */ + NULL, /* security attributes */ + OPEN_EXISTING, + /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */ + FILE_FLAG_BACKUP_SEMANTICS, + NULL); + + if(hFile == INVALID_HANDLE_VALUE) { + return win32_error_unicode("GetFinalPathNamyByHandle", path); + return PyErr_Format(PyExc_RuntimeError, "Could not get a handle to file."); + } + + /* We have a good handle to the target, use it to determine the + target path name. */ + buf_size = Py_GetFinalPathNameByHandleW(hFile, 0, 0, VOLUME_NAME_NT); + + if(!buf_size) + return win32_error_unicode("GetFinalPathNameByHandle", path); + + target_path = (wchar_t *)malloc((buf_size+1)*sizeof(wchar_t)); + if(!target_path) + return PyErr_NoMemory(); + + result_length = Py_GetFinalPathNameByHandleW(hFile, target_path, + buf_size, VOLUME_NAME_DOS); + if(!result_length) + return win32_error_unicode("GetFinalPathNamyByHandle", path); + + if(!CloseHandle(hFile)) + return win32_error_unicode("GetFinalPathNameByHandle", path); + + target_path[result_length] = 0; + result = PyUnicode_FromUnicode(target_path, result_length); + free(target_path); + return result; + +} /* end of posix__getfinalpathname */ #endif /* MS_WINDOWS */ PyDoc_STRVAR(posix_mkdir__doc__, @@ -2623,7 +2899,7 @@ posix_stat(PyObject *self, PyObject *args) { #ifdef MS_WINDOWS - return posix_do_stat(self, args, "O&:stat", STAT, "U:stat", win32_wstat); + return posix_do_stat(self, args, "O&:stat", STAT, "U:stat", win32_stat_w); #else return posix_do_stat(self, args, "O&:stat", STAT, NULL, NULL); #endif @@ -2681,6 +2957,41 @@ return PyLong_FromLong((long)i); } +#ifdef MS_WINDOWS + +/* override the default DeleteFileW behavior so that directory +symlinks can be removed with this function, the same as with +Unix symlinks */ +BOOL WINAPI Py_DeleteFileW(LPCWSTR lpFileName) +{ + WIN32_FILE_ATTRIBUTE_DATA info; + WIN32_FIND_DATAW find_data; + HANDLE find_data_handle; + int is_directory = 0; + int is_link = 0; + + if (GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &info)) { + is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY; + + /* Get WIN32_FIND_DATA structure for the path to determine if + it is a symlink */ + if(is_directory && + info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { + find_data_handle = FindFirstFileW(lpFileName, &find_data); + + if(find_data_handle != INVALID_HANDLE_VALUE) { + is_link = find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK; + FindClose(find_data_handle); + } + } + } + + if (is_directory && is_link) + return RemoveDirectoryW(lpFileName); + + return DeleteFileW(lpFileName); +} +#endif /* MS_WINDOWS */ PyDoc_STRVAR(posix_unlink__doc__, "unlink(path)\n\n\ @@ -2694,7 +3005,7 @@ posix_unlink(PyObject *self, PyObject *args) { #ifdef MS_WINDOWS - return win32_1str(args, "remove", "y:remove", DeleteFileA, "U:remove", DeleteFileW); + return win32_1str(args, "remove", "y:remove", DeleteFileA, "U:remove", Py_DeleteFileW); #else return posix_1str(args, "O&:remove", unlink); #endif @@ -4544,7 +4855,8 @@ return posix_do_stat(self, args, "O&:lstat", lstat, NULL, NULL); #else /* !HAVE_LSTAT */ #ifdef MS_WINDOWS - return posix_do_stat(self, args, "O&:lstat", STAT, "U:lstat", win32_wstat); + return posix_do_stat(self, args, "O&:lstat", STAT, "U:lstat", + win32_lstat_w); #else return posix_do_stat(self, args, "O&:lstat", STAT, NULL, NULL); #endif @@ -4609,6 +4921,193 @@ } #endif /* HAVE_SYMLINK */ +#if !defined(HAVE_READLINK) && defined(MS_WINDOWS) + +PyDoc_STRVAR(win_readlink__doc__, +"readlink(path) -> path\n\n\ +Return a string representing the path to which the symbolic link points."); + +/* The following structure was copied from + http://msdn.microsoft.com/en-us/library/ms791514.aspx as the required + include doesn't seem to be present in the Windows SDK (at least as included + with Visual Studio Express). */ +typedef struct _REPARSE_DATA_BUFFER { + ULONG ReparseTag; + USHORT ReparseDataLength; + USHORT Reserved; + union { + struct { + USHORT SubstituteNameOffset; + USHORT SubstituteNameLength; + USHORT PrintNameOffset; + USHORT PrintNameLength; + ULONG Flags; + WCHAR PathBuffer[1]; + } SymbolicLinkReparseBuffer; + + struct { + USHORT SubstituteNameOffset; + USHORT SubstituteNameLength; + USHORT PrintNameOffset; + USHORT PrintNameLength; + WCHAR PathBuffer[1]; + } MountPointReparseBuffer; + + struct { + UCHAR DataBuffer[1]; + } GenericReparseBuffer; + }; +} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER; + +#define REPARSE_DATA_BUFFER_HEADER_SIZE FIELD_OFFSET(REPARSE_DATA_BUFFER, GenericReparseBuffer) + +#define MAXIMUM_REPARSE_DATA_BUFFER_SIZE ( 16 * 1024 ) + +/* Windows readlink implementation */ +static PyObject * +win_readlink(PyObject *self, PyObject *args) +{ + wchar_t *path; + DWORD n_bytes_returned; + DWORD io_result; + PyObject *result; + HANDLE reparse_point_handle; + + char target_buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; + REPARSE_DATA_BUFFER *rdb = (REPARSE_DATA_BUFFER *)target_buffer; + wchar_t *print_name; + + if (!PyArg_ParseTuple(args, + "u:readlink", + &path)) + return NULL; + + /* First get a handle to the reparse point */ + Py_BEGIN_ALLOW_THREADS + reparse_point_handle = CreateFileW( + path, + 0, + 0, + 0, + OPEN_EXISTING, + FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS, + 0); + Py_END_ALLOW_THREADS + + if (reparse_point_handle==INVALID_HANDLE_VALUE) + { + return win32_error_unicode("readlink", path); + } + + Py_BEGIN_ALLOW_THREADS + /* New call DeviceIoControl to read the reparse point */ + io_result = DeviceIoControl( + reparse_point_handle, + FSCTL_GET_REPARSE_POINT, + 0, 0, /* in buffer */ + target_buffer, sizeof(target_buffer), + &n_bytes_returned, + 0 /* we're not using OVERLAPPED_IO */ + ); + CloseHandle(reparse_point_handle); + Py_END_ALLOW_THREADS + + if (io_result==0) + { + return win32_error_unicode("readlink", path); + } + + if (rdb->ReparseTag != IO_REPARSE_TAG_SYMLINK) + { + PyErr_SetString(PyExc_ValueError, + "not a symbolic link"); + return NULL; + } + print_name = rdb->SymbolicLinkReparseBuffer.PathBuffer + rdb->SymbolicLinkReparseBuffer.PrintNameOffset; + result = PyUnicode_FromWideChar(print_name, rdb->SymbolicLinkReparseBuffer.PrintNameLength/2); + return result; +} + +#endif /* !defined(HAVE_READLINK) && defined(MS_WINDOWS) */ + +#if !defined(HAVE_SYMLINK) && defined(MS_WINDOWS) + +/* Grab CreateSymbolicLinkW dynamically from kernel32 */ +static int has_CreateSymbolicLinkW = 0; +static DWORD (CALLBACK *Py_CreateSymbolicLinkW)(LPWSTR, LPWSTR, DWORD); +static int +check_CreateSymbolicLinkW() +{ + HINSTANCE hKernel32; + /* only recheck */ + if (has_CreateSymbolicLinkW) + return has_CreateSymbolicLinkW; + hKernel32 = GetModuleHandle("KERNEL32"); + *(FARPROC*)&Py_CreateSymbolicLinkW = GetProcAddress(hKernel32, "CreateSymbolicLinkW"); + if (Py_CreateSymbolicLinkW) + has_CreateSymbolicLinkW = 1; + return has_CreateSymbolicLinkW; +} + +PyDoc_STRVAR(win_symlink__doc__, +"symlink(src, dst, target_is_directory=False)\n\n\ +Create a symbolic link pointing to src named dst.\n\ +target_is_directory is required if the target is to be interpreted as\n\ +a directory.\n\ +This function requires Windows 6.0 or greater, and raises a\n\ +NotImplementedError otherwise."); + +static PyObject * +win_symlink(PyObject *self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = {"src", "dest", "target_is_directory", NULL}; + PyObject *src, *dest; + int target_is_directory = 0; + DWORD res; + WIN32_FILE_ATTRIBUTE_DATA src_info; + + if (!check_CreateSymbolicLinkW()) + { + /* raise NotImplementedError */ + return PyErr_Format(PyExc_NotImplementedError, + "CreateSymbolicLinkW not found"); + } + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:symlink", + kwlist, &src, &dest, &target_is_directory)) + return NULL; + if (!convert_to_unicode(&src)) { return NULL; } + if (!convert_to_unicode(&dest)) { + Py_DECREF(src); + return NULL; + } + + /* if src is a directory, ensure target_is_directory==1 */ + if( + GetFileAttributesExW( + PyUnicode_AsUnicode(src), GetFileExInfoStandard, &src_info + )) + { + target_is_directory = target_is_directory || + (src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY); + } + + Py_BEGIN_ALLOW_THREADS + res = Py_CreateSymbolicLinkW( + PyUnicode_AsUnicode(dest), + PyUnicode_AsUnicode(src), + target_is_directory); + Py_END_ALLOW_THREADS + Py_DECREF(src); + Py_DECREF(dest); + if (!res) + { + return win32_error_unicode("symlink", PyUnicode_AsUnicode(src)); + } + + Py_INCREF(Py_None); + return Py_None; +} +#endif /* !defined(HAVE_SYMLINK) && defined(MS_WINDOWS) */ #ifdef HAVE_TIMES #if defined(PYCC_VACPP) && defined(PYOS_OS2) @@ -7076,13 +7575,19 @@ #ifdef HAVE_READLINK {"readlink", posix_readlink, METH_VARARGS, posix_readlink__doc__}, #endif /* HAVE_READLINK */ - {"rename", posix_rename, METH_VARARGS, posix_rename__doc__}, - {"rmdir", posix_rmdir, METH_VARARGS, posix_rmdir__doc__}, - {"stat", posix_stat, METH_VARARGS, posix_stat__doc__}, +#if !defined(HAVE_READLINK) && defined(MS_WINDOWS) + {"readlink", win_readlink, METH_VARARGS, win_readlink__doc__}, +#endif /* !defined(HAVE_READLINK) && defined(MS_WINDOWS) */ + {"rename", posix_rename, METH_VARARGS, posix_rename__doc__}, + {"rmdir", posix_rmdir, METH_VARARGS, posix_rmdir__doc__}, + {"stat", posix_stat, METH_VARARGS, posix_stat__doc__}, {"stat_float_times", stat_float_times, METH_VARARGS, stat_float_times__doc__}, #ifdef HAVE_SYMLINK {"symlink", posix_symlink, METH_VARARGS, posix_symlink__doc__}, #endif /* HAVE_SYMLINK */ +#if !defined(HAVE_SYMLINK) && defined(MS_WINDOWS) + {"symlink", (PyCFunction)win_symlink, METH_VARARGS | METH_KEYWORDS, win_symlink__doc__}, +#endif /* !defined(HAVE_SYMLINK) && defined(MS_WINDOWS) */ #ifdef HAVE_SYSTEM {"system", posix_system, METH_VARARGS, posix_system__doc__}, #endif @@ -7307,6 +7812,7 @@ {"abort", posix_abort, METH_NOARGS, posix_abort__doc__}, #ifdef MS_WINDOWS {"_getfullpathname", posix__getfullpathname, METH_VARARGS, NULL}, + {"_getfinalpathname", posix__getfinalpathname, METH_VARARGS, NULL}, #endif #ifdef HAVE_GETLOADAVG {"getloadavg", posix_getloadavg, METH_NOARGS, posix_getloadavg__doc__}, From python-checkins at python.org Fri Jul 9 00:13:25 2010 From: python-checkins at python.org (brian.curtin) Date: Fri, 9 Jul 2010 00:13:25 +0200 (CEST) Subject: [Python-checkins] r82661 - python/branches/py3k/Lib/test/test_sys.py Message-ID: <20100708221325.AD9DBEEC46@mail.python.org> Author: brian.curtin Date: Fri Jul 9 00:13:25 2010 New Revision: 82661 Log: Undo inadvertant checkin. Modified: python/branches/py3k/Lib/test/test_sys.py Modified: python/branches/py3k/Lib/test/test_sys.py ============================================================================== --- python/branches/py3k/Lib/test/test_sys.py (original) +++ python/branches/py3k/Lib/test/test_sys.py Fri Jul 9 00:13:25 2010 @@ -263,7 +263,7 @@ # Raise SkipTest if sys doesn't have getwindowsversion attribute test.support.get_attribute(sys, "getwindowsversion") v = sys.getwindowsversion() - self.assertEqual(len(v), 9) + self.assertEqual(len(v), 5) self.assertIsInstance(v[0], int) self.assertIsInstance(v[1], int) self.assertIsInstance(v[2], int) From python-checkins at python.org Fri Jul 9 00:16:05 2010 From: python-checkins at python.org (benjamin.peterson) Date: Fri, 9 Jul 2010 00:16:05 +0200 (CEST) Subject: [Python-checkins] r82662 - python/branches/py3k/Lib/test/test_structseq.py Message-ID: <20100708221605.89A3BEEBA0@mail.python.org> Author: benjamin.peterson Date: Fri Jul 9 00:16:05 2010 New Revision: 82662 Log: assert tuple inheritance Modified: python/branches/py3k/Lib/test/test_structseq.py Modified: python/branches/py3k/Lib/test/test_structseq.py ============================================================================== --- python/branches/py3k/Lib/test/test_structseq.py (original) +++ python/branches/py3k/Lib/test/test_structseq.py Fri Jul 9 00:16:05 2010 @@ -7,6 +7,7 @@ def test_tuple(self): t = time.gmtime() + assert isinstance(t, tuple) astuple = tuple(t) self.assertEqual(len(t), len(astuple)) self.assertEqual(t, astuple) From python-checkins at python.org Fri Jul 9 00:33:03 2010 From: python-checkins at python.org (benjamin.peterson) Date: Fri, 9 Jul 2010 00:33:03 +0200 (CEST) Subject: [Python-checkins] r82663 - in python/branches/py3k: Lib/test/test_structseq.py Objects/structseq.c Message-ID: <20100708223303.E17E7EEAF6@mail.python.org> Author: benjamin.peterson Date: Fri Jul 9 00:33:03 2010 New Revision: 82663 Log: fix repr of complicated structseqs #9206 Modified: python/branches/py3k/Lib/test/test_structseq.py python/branches/py3k/Objects/structseq.c Modified: python/branches/py3k/Lib/test/test_structseq.py ============================================================================== --- python/branches/py3k/Lib/test/test_structseq.py (original) +++ python/branches/py3k/Lib/test/test_structseq.py Fri Jul 9 00:33:03 2010 @@ -1,7 +1,8 @@ +import os +import time import unittest from test import support -import time class StructSeqTest(unittest.TestCase): @@ -34,6 +35,13 @@ self.assertEqual(repr(t), "time.struct_time(tm_year=1970, tm_mon=1, tm_mday=1, tm_hour=0, " "tm_min=0, tm_sec=0, tm_wday=3, tm_yday=1, tm_isdst=0)") + # os.stat() gives a complicated struct sequence. + st = os.stat(__file__) + rep = repr(st) + self.assertTrue(rep.startswith("posix.stat_result")) + self.assertIn("st_mode=", rep) + self.assertIn("st_ino=", rep) + self.assertIn("st_dev=", rep) def test_concat(self): t1 = time.gmtime() Modified: python/branches/py3k/Objects/structseq.c ============================================================================== --- python/branches/py3k/Objects/structseq.c (original) +++ python/branches/py3k/Objects/structseq.c Fri Jul 9 00:33:03 2010 @@ -35,12 +35,27 @@ obj = PyObject_GC_NewVar(PyStructSequence, type, size); if (obj == NULL) return NULL; + /* Hack the size of the variable object, so invisible fields don't appear + to Python code. */ + Py_SIZE(obj) = VISIBLE_SIZE_TP(type); for (i = 0; i < size; i++) obj->ob_item[i] = NULL; return (PyObject*)obj; } +static void +structseq_dealloc(PyStructSequence *obj) +{ + Py_ssize_t i, size; + + size = REAL_SIZE(obj); + for (i = 0; i < size; ++i) { + Py_XDECREF(obj->ob_item[i]); + } + PyObject_GC_Del(obj); +} + static PyObject * structseq_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { @@ -154,8 +169,11 @@ char *cname, *crepr; cname = typ->tp_members[i].name; - if (cname == NULL) + if (cname == NULL) { + PyErr_Format(PyExc_SystemError, "In structseq_repr(), member %d name is NULL" + " for type %.500s", i, typ->tp_name); return NULL; + } val = PyStructSequence_GET_ITEM(obj, i); repr = PyObject_Repr(val); if (repr == NULL) @@ -249,7 +267,7 @@ NULL, /* tp_name */ sizeof(PyStructSequence) - sizeof(PyObject *), /* tp_basicsize */ sizeof(PyObject *), /* tp_itemsize */ - 0, /* tp_dealloc */ + (destructor)structseq_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ From python-checkins at python.org Fri Jul 9 01:13:57 2010 From: python-checkins at python.org (victor.stinner) Date: Fri, 9 Jul 2010 01:13:57 +0200 (CEST) Subject: [Python-checkins] r82664 - python/branches/import_unicode Message-ID: <20100708231357.24E90EE987@mail.python.org> Author: victor.stinner Date: Fri Jul 9 01:13:57 2010 New Revision: 82664 Log: create import_unicode branch, based on py3k Added: python/branches/import_unicode/ - copied from r82663, /python/branches/py3k/ From solipsis at pitrou.net Fri Jul 9 01:25:51 2010 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Fri, 9 Jul 2010 01:25:51 +0200 (CEST) Subject: [Python-checkins] Daily py3k reference leaks (r82650): sum=0 Message-ID: <20100708232551.CA56E1775C@ns6635.ovh.net> py3k results for svn r82650 (hg cset 6f69451a1dd0) -------------------------------------------------- Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/py3k/refleaks/reflogoVdiKd', '-x'] From python-checkins at python.org Fri Jul 9 01:32:12 2010 From: python-checkins at python.org (victor.stinner) Date: Fri, 9 Jul 2010 01:32:12 +0200 (CEST) Subject: [Python-checkins] r82665 - in python/branches/import_unicode: Include/fileobject.h Objects/fileobject.c Python/import.c Message-ID: <20100708233212.CE5C7EE995@mail.python.org> Author: victor.stinner Date: Fri Jul 9 01:32:12 2010 New Revision: 82665 Log: Create _PyFile_FromFdUnicode() private function Modified: python/branches/import_unicode/Include/fileobject.h python/branches/import_unicode/Objects/fileobject.c python/branches/import_unicode/Python/import.c Modified: python/branches/import_unicode/Include/fileobject.h ============================================================================== --- python/branches/import_unicode/Include/fileobject.h (original) +++ python/branches/import_unicode/Include/fileobject.h Fri Jul 9 01:32:12 2010 @@ -8,8 +8,24 @@ #define PY_STDIOTEXTMODE "b" -PyAPI_FUNC(PyObject *) PyFile_FromFd(int, char *, char *, int, char *, char *, - char *, int); +PyAPI_FUNC(PyObject *) PyFile_FromFd( + int fd, + char *name, + char *mode, + int buffering, + char *encoding, + char *errors, + char *newline, + int closefd); +PyAPI_FUNC(PyObject *) _PyFile_FromFdUnicode( + int fd, + PyObject *name, + char *mode, + int buffering, + char *encoding, + char *errors, + char *newline, + int closefd); PyAPI_FUNC(PyObject *) PyFile_GetLine(PyObject *, int); PyAPI_FUNC(int) PyFile_WriteObject(PyObject *, PyObject *, int); PyAPI_FUNC(int) PyFile_WriteString(const char *, PyObject *); Modified: python/branches/import_unicode/Objects/fileobject.c ============================================================================== --- python/branches/import_unicode/Objects/fileobject.c (original) +++ python/branches/import_unicode/Objects/fileobject.c Fri Jul 9 01:32:12 2010 @@ -26,10 +26,10 @@ /* External C interface */ PyObject * -PyFile_FromFd(int fd, char *name, char *mode, int buffering, char *encoding, - char *errors, char *newline, int closefd) +_PyFile_FromFdUnicode(int fd, PyObject *name, char *mode, int buffering, + char *encoding, char *errors, char *newline, int closefd) { - PyObject *io, *stream, *nameobj = NULL; + PyObject *io, *stream; io = PyImport_ImportModule("io"); if (io == NULL) @@ -41,18 +41,30 @@ if (stream == NULL) return NULL; if (name != NULL) { - nameobj = PyUnicode_DecodeFSDefault(name); - if (nameobj == NULL) + if (PyObject_SetAttrString(stream, "name", name) < 0) PyErr_Clear(); - else { - if (PyObject_SetAttrString(stream, "name", nameobj) < 0) - PyErr_Clear(); - Py_DECREF(nameobj); - } } return stream; } + +PyObject * +PyFile_FromFd(int fd, char *name, char *mode, int buffering, char *encoding, + char *errors, char *newline, int closefd) +{ + PyObject *nameobj, *file; + if (name != NULL) { + nameobj = PyUnicode_DecodeFSDefault(name); + if (nameobj == NULL) + PyErr_Clear(); + } else + nameobj = NULL; + file = _PyFile_FromFdUnicode(fd, nameobj, mode, buffering, + encoding, errors, newline, closefd); + Py_XDECREF(nameobj); + return file; +} + PyObject * PyFile_GetLine(PyObject *f, int n) { Modified: python/branches/import_unicode/Python/import.c ============================================================================== --- python/branches/import_unicode/Python/import.c (original) +++ python/branches/import_unicode/Python/import.c Fri Jul 9 01:32:12 2010 @@ -3121,6 +3121,9 @@ fdp = find_module(NULL, name, path, pathname, MAXPATHLEN+1, &fp, NULL); if (fdp == NULL) return NULL; + pathobj = PyUnicode_DecodeFSDefault(pathname); + if (pathobj == NULL) + return NULL; if (fp != NULL) { fd = fileno(fp); if (fd != -1) @@ -3139,8 +3142,8 @@ encoding = (found_encoding != NULL) ? found_encoding : (char*)PyUnicode_GetDefaultEncoding(); } - fob = PyFile_FromFd(fd, pathname, fdp->mode, -1, - (char*)encoding, NULL, NULL, 1); + fob = _PyFile_FromFdUnicode(fd, pathobj, fdp->mode, -1, + encoding, NULL, NULL, 1); if (fob == NULL) { close(fd); PyMem_FREE(found_encoding); @@ -3151,9 +3154,9 @@ fob = Py_None; Py_INCREF(fob); } - pathobj = PyUnicode_DecodeFSDefault(pathname); ret = Py_BuildValue("NN(ssi)", - fob, pathobj, fdp->suffix, fdp->mode, fdp->type); + fob, pathobj, + fdp->suffix, fdp->mode, fdp->type); PyMem_FREE(found_encoding); return ret; From python-checkins at python.org Fri Jul 9 01:32:14 2010 From: python-checkins at python.org (victor.stinner) Date: Fri, 9 Jul 2010 01:32:14 +0200 (CEST) Subject: [Python-checkins] r82666 - python/branches/import_unicode/Python/pythonrun.c Message-ID: <20100708233214.4C449EE9BC@mail.python.org> Author: victor.stinner Date: Fri Jul 9 01:32:14 2010 New Revision: 82666 Log: initialize GIL earlier in Py_InitializeEx() Modified: python/branches/import_unicode/Python/pythonrun.c Modified: python/branches/import_unicode/Python/pythonrun.c ============================================================================== --- python/branches/import_unicode/Python/pythonrun.c (original) +++ python/branches/import_unicode/Python/pythonrun.c Fri Jul 9 01:32:14 2010 @@ -206,6 +206,11 @@ Py_FatalError("Py_Initialize: can't make first thread"); (void) PyThreadState_Swap(tstate); + /* auto-thread-state API, if available */ +#ifdef WITH_THREAD + _PyGILState_Init(interp, tstate); +#endif /* WITH_THREAD */ + _Py_ReadyTypes(); if (!_PyFrame_Init()) @@ -286,11 +291,6 @@ Py_FatalError( "Py_Initialize: can't initialize sys standard streams"); - /* auto-thread-state API, if available */ -#ifdef WITH_THREAD - _PyGILState_Init(interp, tstate); -#endif /* WITH_THREAD */ - if (!Py_NoSiteFlag) initsite(); /* Module site */ } From python-checkins at python.org Fri Jul 9 01:32:15 2010 From: python-checkins at python.org (victor.stinner) Date: Fri, 9 Jul 2010 01:32:15 +0200 (CEST) Subject: [Python-checkins] r82667 - python/branches/import_unicode/Python/import.c Message-ID: <20100708233215.AA280EEB20@mail.python.org> Author: victor.stinner Date: Fri Jul 9 01:32:15 2010 New Revision: 82667 Log: update_compiled_module() pathname is an object not a char* Modified: python/branches/import_unicode/Python/import.c Modified: python/branches/import_unicode/Python/import.c ============================================================================== --- python/branches/import_unicode/Python/import.c (original) +++ python/branches/import_unicode/Python/import.c Fri Jul 9 01:32:15 2010 @@ -1218,24 +1218,17 @@ } static int -update_compiled_module(PyCodeObject *co, char *pathname) +update_compiled_module(PyCodeObject *co, PyObject *newname) { - PyObject *oldname, *newname; + PyObject *oldname; - newname = PyUnicode_DecodeFSDefault(pathname); - if (newname == NULL) - return -1; - - if (!PyUnicode_Compare(co->co_filename, newname)) { - Py_DECREF(newname); + if (!PyUnicode_Compare(co->co_filename, newname)) return 0; - } oldname = co->co_filename; Py_INCREF(oldname); update_code_filenames(co, oldname, newname); Py_DECREF(oldname); - Py_DECREF(newname); return 1; } @@ -1252,6 +1245,7 @@ char *cpathname; PyCodeObject *co; PyObject *m; + PyObject *pathobj; if (fstat(fileno(fp), &st) != 0) { PyErr_Format(PyExc_RuntimeError, @@ -1278,8 +1272,12 @@ fclose(fpc); if (co == NULL) return NULL; - if (update_compiled_module(co, pathname) < 0) + pathobj = PyUnicode_DecodeFSDefault(pathname); + if (pathobj == NULL) + return NULL; + if (update_compiled_module(co, pathobj) < 0) return NULL; + Py_DECREF(pathobj); if (Py_VerboseFlag) PySys_WriteStderr("import %s # precompiled from %s\n", name, cpathname); From python-checkins at python.org Fri Jul 9 01:32:17 2010 From: python-checkins at python.org (victor.stinner) Date: Fri, 9 Jul 2010 01:32:17 +0200 (CEST) Subject: [Python-checkins] r82668 - python/branches/import_unicode/Python/import.c Message-ID: <20100708233217.1B1E9EEB49@mail.python.org> Author: victor.stinner Date: Fri Jul 9 01:32:16 2010 New Revision: 82668 Log: load_source_module(): path is now an object instead of a char* Modified: python/branches/import_unicode/Python/import.c Modified: python/branches/import_unicode/Python/import.c ============================================================================== --- python/branches/import_unicode/Python/import.c (original) +++ python/branches/import_unicode/Python/import.c Fri Jul 9 01:32:16 2010 @@ -1237,15 +1237,18 @@ byte-compiled file, use that instead. */ static PyObject * -load_source_module(char *name, char *pathname, FILE *fp) +load_source_module(char *name, PyObject *pathobj, FILE *fp) { struct stat st; FILE *fpc; char buf[MAXPATHLEN+1]; + char *pathname; char *cpathname; PyCodeObject *co; PyObject *m; - PyObject *pathobj; + + /* FIXME: don't use _PyUnicode_AsString */ + pathname = _PyUnicode_AsString(pathobj); if (fstat(fileno(fp), &st) != 0) { PyErr_Format(PyExc_RuntimeError, @@ -1266,21 +1269,21 @@ #endif cpathname = make_compiled_pathname( pathname, buf, (size_t)MAXPATHLEN + 1, !Py_OptimizeFlag); - if (cpathname != NULL && - (fpc = check_compiled_module(pathname, st.st_mtime, cpathname))) { + if (cpathname != NULL) + fpc = check_compiled_module(pathname, st.st_mtime, cpathname); + else + fpc = NULL; + if (fpc) { co = read_compiled_module(cpathname, fpc); fclose(fpc); if (co == NULL) return NULL; - pathobj = PyUnicode_DecodeFSDefault(pathname); - if (pathobj == NULL) - return NULL; if (update_compiled_module(co, pathobj) < 0) return NULL; - Py_DECREF(pathobj); if (Py_VerboseFlag) PySys_WriteStderr("import %s # precompiled from %s\n", name, cpathname); + pathobj = NULL; pathname = cpathname; } else { @@ -2035,9 +2038,14 @@ switch (type) { - case PY_SOURCE: - m = load_source_module(name, pathname, fp); + case PY_SOURCE: { + PyObject *pathobj = PyUnicode_DecodeFSDefault(pathname); + if (pathobj == NULL) + return NULL; + m = load_source_module(name, pathobj, fp); + Py_DECREF(pathobj); break; + } case PY_COMPILED: m = load_compiled_module(name, pathname, fp); @@ -3343,22 +3351,18 @@ imp_load_source(PyObject *self, PyObject *args) { char *name; - char *pathname; + PyObject *pathname; PyObject *fob = NULL; PyObject *m; FILE *fp; - if (!PyArg_ParseTuple(args, "ses|O:load_source", - &name, - Py_FileSystemDefaultEncoding, &pathname, - &fob)) + if (!PyArg_ParseTuple(args, "sU|O:load_source", + &name, &pathname, &fob)) return NULL; - fp = get_file(pathname, fob, "r"); - if (fp == NULL) { - PyMem_Free(pathname); + /* FIXME: don't use _PyUnicode_AsString */ + fp = get_file(_PyUnicode_AsString(pathname), fob, "r"); + if (fp == NULL) return NULL; - } m = load_source_module(name, pathname, fp); - PyMem_Free(pathname); fclose(fp); return m; } From python-checkins at python.org Fri Jul 9 01:32:18 2010 From: python-checkins at python.org (victor.stinner) Date: Fri, 9 Jul 2010 01:32:18 +0200 (CEST) Subject: [Python-checkins] r82669 - in python/branches/import_unicode: Include/import.h Python/import.c Python/importdl.c Python/importdl.h Message-ID: <20100708233218.AC151EEB35@mail.python.org> Author: victor.stinner Date: Fri Jul 9 01:32:18 2010 New Revision: 82669 Log: _PyImport_LoadDynamicModule() path is an object ... instead of a char* * Create _PyImport_FindExtensionUnicode() and _PyImport_FixupExtensionUnicode() functions Modified: python/branches/import_unicode/Include/import.h python/branches/import_unicode/Python/import.c python/branches/import_unicode/Python/importdl.c python/branches/import_unicode/Python/importdl.h Modified: python/branches/import_unicode/Include/import.h ============================================================================== --- python/branches/import_unicode/Include/import.h (original) +++ python/branches/import_unicode/Include/import.h Fri Jul 9 01:32:18 2010 @@ -44,7 +44,9 @@ PyAPI_FUNC(void) _PyImport_ReInitLock(void); PyAPI_FUNC(PyObject *)_PyImport_FindExtension(char *, char *); +PyAPI_FUNC(PyObject *)_PyImport_FindExtensionUnicode(char *, PyObject *); PyAPI_FUNC(int)_PyImport_FixupExtension(PyObject*, char *, char *); +PyAPI_FUNC(int)_PyImport_FixupExtensionUnicode(PyObject*, char *, PyObject *); struct _inittab { char *name; Modified: python/branches/import_unicode/Python/import.c ============================================================================== --- python/branches/import_unicode/Python/import.c (original) +++ python/branches/import_unicode/Python/import.c Fri Jul 9 01:32:18 2010 @@ -565,7 +565,7 @@ */ int -_PyImport_FixupExtension(PyObject *mod, char *name, char *filename) +_PyImport_FixupExtensionUnicode(PyObject *mod, char *name, PyObject *filename) { PyObject *modules, *dict; struct PyModuleDef *def; @@ -605,18 +605,32 @@ if (def->m_base.m_copy == NULL) return -1; } - PyDict_SetItemString(extensions, filename, (PyObject*)def); + PyDict_SetItem(extensions, filename, (PyObject*)def); return 0; } +int +_PyImport_FixupExtension(PyObject *mod, char *name, char *filename) +{ + PyObject *fileobj; + int result; + fileobj = PyUnicode_FromString(filename); + if (fileobj == NULL) + return -1; + result = _PyImport_FixupExtensionUnicode(mod, name, fileobj); + Py_DECREF(fileobj); + return result; +} + + PyObject * -_PyImport_FindExtension(char *name, char *filename) +_PyImport_FindExtensionUnicode(char *name, PyObject *filename) { PyObject *mod, *mdict; PyModuleDef* def; if (extensions == NULL) return NULL; - def = (PyModuleDef*)PyDict_GetItemString(extensions, filename); + def = (PyModuleDef*)PyDict_GetItem(extensions, filename); if (def == NULL) return NULL; if (def->m_size == -1) { @@ -648,9 +662,20 @@ } if (Py_VerboseFlag) PySys_WriteStderr("import %s # previously loaded (%s)\n", - name, filename); + name, + /* FIXME: don't use _PyUnicode_AsString */ + _PyUnicode_AsString(filename)); return mod; +} +PyObject * +_PyImport_FindExtension(char *name, char *filename) +{ + PyObject *fileobj, *mod; + fileobj = PyUnicode_DecodeFSDefault(filename); + mod = _PyImport_FindExtensionUnicode(name, fileobj); + Py_DECREF(fileobj); + return mod; } @@ -2052,9 +2077,14 @@ break; #ifdef HAVE_DYNAMIC_LOADING - case C_EXTENSION: - m = _PyImport_LoadDynamicModule(name, pathname, fp); + case C_EXTENSION: { + PyObject *pathobj = PyUnicode_DecodeFSDefault(pathname); + if (pathobj == NULL) + return NULL; + m = _PyImport_LoadDynamicModule(name, pathobj, fp); + Py_DECREF(pathobj); break; + } #endif case PKG_DIRECTORY: @@ -2123,9 +2153,13 @@ init_builtin(char *name) { struct _inittab *p; + PyObject *path; - if (_PyImport_FindExtension(name, name) != NULL) + path = PyUnicode_FromString(name); + if (_PyImport_FindExtensionUnicode(name, path) != NULL) { + Py_DECREF(path); return 1; + } for (p = PyImport_Inittab; p->name != NULL; p++) { PyObject *mod; @@ -2134,21 +2168,28 @@ PyErr_Format(PyExc_ImportError, "Cannot re-init internal module %.200s", name); + Py_DECREF(path); return -1; } if (Py_VerboseFlag) PySys_WriteStderr("import %s # builtin\n", name); mod = (*p->initfunc)(); - if (mod == 0) + if (mod == 0) { + Py_DECREF(path); return -1; - if (_PyImport_FixupExtension(mod, name, name) < 0) + } + if (_PyImport_FixupExtensionUnicode(mod, name, path) < 0) { + Py_DECREF(path); return -1; + } + Py_DECREF(path); /* FixupExtension has put the module into sys.modules, so we can release our own reference. */ Py_DECREF(mod); return 1; } } + Py_DECREF(path); return 0; } @@ -3322,24 +3363,22 @@ imp_load_dynamic(PyObject *self, PyObject *args) { char *name; - char *pathname; + PyObject *pathname; PyObject *fob = NULL; PyObject *m; FILE *fp = NULL; - if (!PyArg_ParseTuple(args, "ses|O:load_dynamic", + if (!PyArg_ParseTuple(args, "sU|O:load_dynamic", &name, - Py_FileSystemDefaultEncoding, &pathname, + &pathname, &fob)) return NULL; if (fob) { - fp = get_file(pathname, fob, "r"); - if (fp == NULL) { - PyMem_Free(pathname); + /* FIXME: don't use _PyUnicode_AsString */ + fp = get_file(_PyUnicode_AsString(pathname), fob, "r"); + if (fp == NULL) return NULL; - } } m = _PyImport_LoadDynamicModule(name, pathname, fp); - PyMem_Free(pathname); if (fp) fclose(fp); return m; Modified: python/branches/import_unicode/Python/importdl.c ============================================================================== --- python/branches/import_unicode/Python/importdl.c (original) +++ python/branches/import_unicode/Python/importdl.c Fri Jul 9 01:32:18 2010 @@ -19,16 +19,19 @@ PyObject * -_PyImport_LoadDynamicModule(char *name, char *pathname, FILE *fp) +_PyImport_LoadDynamicModule(char *name, PyObject *path, FILE *fp) { PyObject *m; - PyObject *path; + char *pathname; char *lastdot, *shortname, *packagecontext, *oldcontext; dl_funcptr p0; PyObject* (*p)(void); struct PyModuleDef *def; - if ((m = _PyImport_FindExtension(name, pathname)) != NULL) { + /* FIXME: don't use _PyUnicode_AsString */ + pathname = _PyUnicode_AsString(path); + + if ((m = _PyImport_FindExtensionUnicode(name, path)) != NULL) { Py_INCREF(m); return m; } @@ -72,11 +75,13 @@ def->m_base.m_init = p; /* Remember the filename as the __file__ attribute */ - path = PyUnicode_DecodeFSDefault(pathname); - if (PyModule_AddObject(m, "__file__", path) < 0) + Py_INCREF(path); + if (PyModule_AddObject(m, "__file__", path) < 0) { PyErr_Clear(); /* Not important enough to report */ + Py_DECREF(path); + } - if (_PyImport_FixupExtension(m, name, pathname) < 0) + if (_PyImport_FixupExtensionUnicode(m, name, path) < 0) return NULL; if (Py_VerboseFlag) PySys_WriteStderr( Modified: python/branches/import_unicode/Python/importdl.h ============================================================================== --- python/branches/import_unicode/Python/importdl.h (original) +++ python/branches/import_unicode/Python/importdl.h Fri Jul 9 01:32:18 2010 @@ -28,7 +28,7 @@ extern struct filedescr * _PyImport_Filetab; extern const struct filedescr _PyImport_DynLoadFiletab[]; -extern PyObject *_PyImport_LoadDynamicModule(char *name, char *pathname, +extern PyObject *_PyImport_LoadDynamicModule(char *name, PyObject *pathname, FILE *); /* Max length of module suffix searched for -- accommodates "module.slb" */ From python-checkins at python.org Fri Jul 9 01:32:20 2010 From: python-checkins at python.org (victor.stinner) Date: Fri, 9 Jul 2010 01:32:20 +0200 (CEST) Subject: [Python-checkins] r82670 - python/branches/import_unicode/Python/import.c Message-ID: <20100708233220.25D31EEAF0@mail.python.org> Author: victor.stinner Date: Fri Jul 9 01:32:20 2010 New Revision: 82670 Log: load_package() path is an object instead of a char* Modified: python/branches/import_unicode/Python/import.c Modified: python/branches/import_unicode/Python/import.c ============================================================================== --- python/branches/import_unicode/Python/import.c (original) +++ python/branches/import_unicode/Python/import.c Fri Jul 9 01:32:20 2010 @@ -1381,7 +1381,7 @@ REFERENCE COUNT */ static PyObject * -load_package(char *name, char *pathname) +load_package(char *name, PyObject *pathobj) { PyObject *m, *d; PyObject *file = NULL; @@ -1390,6 +1390,10 @@ char buf[MAXPATHLEN+1]; FILE *fp = NULL; struct filedescr *fdp; + char *pathname; + + /* FIXME: don't use _PyUnicode_AsString */ + pathname = _PyUnicode_AsString(pathobj); m = PyImport_AddModule(name); if (m == NULL) @@ -2087,9 +2091,14 @@ } #endif - case PKG_DIRECTORY: - m = load_package(name, pathname); + case PKG_DIRECTORY: { + PyObject *pathobj = PyUnicode_DecodeFSDefault(pathname); + if (pathobj == NULL) + return NULL; + m = load_package(name, pathobj); + Py_DECREF(pathobj); break; + } case C_BUILTIN: case PY_FROZEN: @@ -3455,14 +3464,11 @@ imp_load_package(PyObject *self, PyObject *args) { char *name; - char *pathname; - PyObject * ret; - if (!PyArg_ParseTuple(args, "ses:load_package", - &name, Py_FileSystemDefaultEncoding, &pathname)) + PyObject *pathname; + if (!PyArg_ParseTuple(args, "sU:load_package", + &name, &pathname)) return NULL; - ret = load_package(name, pathname); - PyMem_Free(pathname); - return ret; + return load_package(name, pathname); } static PyObject * From python-checkins at python.org Fri Jul 9 01:32:21 2010 From: python-checkins at python.org (victor.stinner) Date: Fri, 9 Jul 2010 01:32:21 +0200 (CEST) Subject: [Python-checkins] r82671 - python/branches/import_unicode/Python/import.c Message-ID: <20100708233221.9BF52EEAF3@mail.python.org> Author: victor.stinner Date: Fri Jul 9 01:32:21 2010 New Revision: 82671 Log: get_sourcefile(): path argument is an object instead of char* Modified: python/branches/import_unicode/Python/import.c Modified: python/branches/import_unicode/Python/import.c ============================================================================== --- python/branches/import_unicode/Python/import.c (original) +++ python/branches/import_unicode/Python/import.c Fri Jul 9 01:32:21 2010 @@ -718,7 +718,7 @@ "sys.modules failed"); } -static PyObject * get_sourcefile(char *file); +static PyObject * get_sourcefile(PyObject *file); static char *make_source_pathname(char *pathname, char *buf); static char *make_compiled_pathname(char *pathname, char *buf, size_t buflen, int debug); @@ -768,7 +768,10 @@ /* Remember the filename as the __file__ attribute */ v = NULL; if (pathname != NULL) { - v = get_sourcefile(pathname); + PyObject *pathobj = PyUnicode_DecodeFSDefault(pathname); + /* FIXME: check pathobj != NULL */ + v = get_sourcefile(pathobj); + Py_DECREF(pathobj); if (v == NULL) PyErr_Clear(); } @@ -1335,12 +1338,20 @@ * Returns the path to the py file if available, else the given path */ static PyObject * -get_sourcefile(char *file) +get_sourcefile(PyObject *fileobj) { + /* FIXME: use Py_UNICODE* instead of char* */ char py[MAXPATHLEN + 1]; Py_ssize_t len; - PyObject *u; struct stat statbuf; + char *file; + + if (!fileobj) { + Py_RETURN_NONE; + } + + /* FIXME: don't use _PyUnicode_AsString */ + file = _PyUnicode_AsString(fileobj); if (!file || !*file) { Py_RETURN_NONE; @@ -1349,7 +1360,8 @@ len = strlen(file); /* match '*.py?' */ if (len > MAXPATHLEN || PyOS_strnicmp(&file[len-4], ".py", 3) != 0) { - return PyUnicode_DecodeFSDefault(file); + Py_INCREF(fileobj); + return fileobj; } /* Start by trying to turn PEP 3147 path into source path. If that @@ -1363,12 +1375,12 @@ if (stat(py, &statbuf) == 0 && S_ISREG(statbuf.st_mode)) { - u = PyUnicode_DecodeFSDefault(py); + return PyUnicode_DecodeFSDefault(py); } else { - u = PyUnicode_DecodeFSDefault(file); + Py_INCREF(fileobj); + return fileobj; } - return u; } /* Forward */ @@ -1402,7 +1414,7 @@ PySys_WriteStderr("import %s # directory %s\n", name, pathname); d = PyModule_GetDict(m); - file = get_sourcefile(pathname); + file = get_sourcefile(pathobj); if (file == NULL) goto error; path = Py_BuildValue("[O]", file); From python-checkins at python.org Fri Jul 9 01:32:23 2010 From: python-checkins at python.org (victor.stinner) Date: Fri, 9 Jul 2010 01:32:23 +0200 (CEST) Subject: [Python-checkins] r82672 - python/branches/import_unicode/Include/import.h Message-ID: <20100708233223.021C8EEBA6@mail.python.org> Author: victor.stinner Date: Fri Jul 9 01:32:22 2010 New Revision: 82672 Log: replace tabs by spaces Modified: python/branches/import_unicode/Include/import.h Modified: python/branches/import_unicode/Include/import.h ============================================================================== --- python/branches/import_unicode/Include/import.h (original) +++ python/branches/import_unicode/Include/import.h Fri Jul 9 01:32:22 2010 @@ -11,18 +11,21 @@ PyAPI_FUNC(const char *) PyImport_GetMagicTag(void); PyAPI_FUNC(PyObject *) PyImport_ExecCodeModule(char *name, PyObject *co); PyAPI_FUNC(PyObject *) PyImport_ExecCodeModuleEx( - char *name, PyObject *co, char *pathname); + char *name, PyObject *co, char *pathname); PyAPI_FUNC(PyObject *) PyImport_ExecCodeModuleWithPathnames( - char *name, PyObject *co, char *pathname, char *cpathname); + char *name, + PyObject *co, + char *pathname, + char *cpathname); PyAPI_FUNC(PyObject *) PyImport_GetModuleDict(void); PyAPI_FUNC(PyObject *) PyImport_AddModule(const char *name); PyAPI_FUNC(PyObject *) PyImport_ImportModule(const char *name); PyAPI_FUNC(PyObject *) PyImport_ImportModuleNoBlock(const char *); PyAPI_FUNC(PyObject *) PyImport_ImportModuleLevel(char *name, - PyObject *globals, PyObject *locals, PyObject *fromlist, int level); + PyObject *globals, PyObject *locals, PyObject *fromlist, int level); #define PyImport_ImportModuleEx(n, g, l, f) \ - PyImport_ImportModuleLevel(n, g, l, f, -1) + PyImport_ImportModuleLevel(n, g, l, f, -1) PyAPI_FUNC(PyObject *) PyImport_GetImporter(PyObject *path); PyAPI_FUNC(PyObject *) PyImport_Import(PyObject *name); @@ -39,7 +42,7 @@ #endif PyAPI_FUNC(struct filedescr *) _PyImport_FindModule( - const char *, PyObject *, char *, size_t, FILE **, PyObject **); + const char *, PyObject *, char *, size_t, FILE **, PyObject **); PyAPI_FUNC(int) _PyImport_IsScript(struct filedescr *); PyAPI_FUNC(void) _PyImport_ReInitLock(void); From python-checkins at python.org Fri Jul 9 01:32:24 2010 From: python-checkins at python.org (victor.stinner) Date: Fri, 9 Jul 2010 01:32:24 +0200 (CEST) Subject: [Python-checkins] r82673 - in python/branches/import_unicode: Include/import.h Python/import.c Message-ID: <20100708233224.8A02BEEB83@mail.python.org> Author: victor.stinner Date: Fri Jul 9 01:32:24 2010 New Revision: 82673 Log: Create PyImport_ExecCodeModuleWithUnicodePathnames() I love long function names! Modified: python/branches/import_unicode/Include/import.h python/branches/import_unicode/Python/import.c Modified: python/branches/import_unicode/Include/import.h ============================================================================== --- python/branches/import_unicode/Include/import.h (original) +++ python/branches/import_unicode/Include/import.h Fri Jul 9 01:32:24 2010 @@ -17,6 +17,11 @@ PyObject *co, char *pathname, char *cpathname); +PyAPI_FUNC(PyObject *) PyImport_ExecCodeModuleWithUnicodePathnames( + char *name, + PyObject *co, + PyObject *pathname, + PyObject *cpathname); PyAPI_FUNC(PyObject *) PyImport_GetModuleDict(void); PyAPI_FUNC(PyObject *) PyImport_AddModule(const char *name); PyAPI_FUNC(PyObject *) PyImport_ImportModule(const char *name); Modified: python/branches/import_unicode/Python/import.c ============================================================================== --- python/branches/import_unicode/Python/import.c (original) +++ python/branches/import_unicode/Python/import.c Fri Jul 9 01:32:24 2010 @@ -736,8 +736,8 @@ PyObject * PyImport_ExecCodeModule(char *name, PyObject *co) { - return PyImport_ExecCodeModuleWithPathnames( - name, co, (char *)NULL, (char *)NULL); + return PyImport_ExecCodeModuleWithUnicodePathnames( + name, co, NULL, NULL); } PyObject * @@ -748,8 +748,8 @@ } PyObject * -PyImport_ExecCodeModuleWithPathnames(char *name, PyObject *co, char *pathname, - char *cpathname) +PyImport_ExecCodeModuleWithUnicodePathnames(char *name, PyObject *co, + PyObject *pathobj, PyObject *cpathobj) { PyObject *modules = PyImport_GetModuleDict(); PyObject *m, *d, *v; @@ -767,11 +767,8 @@ } /* Remember the filename as the __file__ attribute */ v = NULL; - if (pathname != NULL) { - PyObject *pathobj = PyUnicode_DecodeFSDefault(pathname); - /* FIXME: check pathobj != NULL */ + if (pathobj != NULL) { v = get_sourcefile(pathobj); - Py_DECREF(pathobj); if (v == NULL) PyErr_Clear(); } @@ -784,18 +781,12 @@ Py_DECREF(v); /* Remember the pyc path name as the __cached__ attribute. */ - if (cpathname == NULL) { - v = Py_None; - Py_INCREF(v); - } - else if ((v = PyUnicode_FromString(cpathname)) == NULL) { - PyErr_Clear(); /* Not important enough to report */ + if (cpathobj != NULL) + v = cpathobj; + else v = Py_None; - Py_INCREF(v); - } if (PyDict_SetItemString(d, "__cached__", v) != 0) PyErr_Clear(); /* Not important enough to report */ - Py_DECREF(v); v = PyEval_EvalCode((PyCodeObject *)co, d, d); if (v == NULL) @@ -818,6 +809,29 @@ return NULL; } +PyObject * +PyImport_ExecCodeModuleWithPathnames(char *name, PyObject *co, char *pathname, + char *cpathname) +{ + PyObject *m, *pathobj, *cpathobj; + if (pathname != NULL) { + pathobj = PyUnicode_DecodeFSDefault(pathname); + if (pathobj == NULL) + return NULL; + } else + pathobj = NULL; + if (cpathname != NULL) { + cpathobj = PyUnicode_DecodeFSDefault(cpathname); + if (cpathobj == NULL) + PyErr_Clear(); /* Not important enough to report */ + } else + cpathobj = NULL; + m = PyImport_ExecCodeModuleWithUnicodePathnames(name, co, pathobj, cpathobj); + Py_XDECREF(pathobj); + Py_XDECREF(cpathobj); + return m; +} + /* Like strrchr(string, '/') but searches for the rightmost of either SEP or ALTSEP, if the latter is defined. @@ -1068,6 +1082,7 @@ long magic; PyCodeObject *co; PyObject *m; + PyObject *cpathobj; magic = PyMarshal_ReadLongFromFile(fp); if (magic != pyc_magic) { @@ -1082,8 +1097,10 @@ if (Py_VerboseFlag) PySys_WriteStderr("import %s # precompiled from %s\n", name, cpathname); - m = PyImport_ExecCodeModuleWithPathnames( - name, (PyObject *)co, cpathname, cpathname); + cpathobj = PyUnicode_DecodeFSDefault(cpathname); + m = PyImport_ExecCodeModuleWithUnicodePathnames( + name, (PyObject *)co, cpathobj, cpathobj); + Py_DECREF(cpathobj); Py_DECREF(co); return m; From python-checkins at python.org Fri Jul 9 01:32:26 2010 From: python-checkins at python.org (victor.stinner) Date: Fri, 9 Jul 2010 01:32:26 +0200 (CEST) Subject: [Python-checkins] r82674 - python/branches/import_unicode/Python/import.c Message-ID: <20100708233226.01B70EEB39@mail.python.org> Author: victor.stinner Date: Fri Jul 9 01:32:25 2010 New Revision: 82674 Log: load_source_module() uses PyImport_ExecCodeModuleWithUnicodePathnames instead of PyImport_ExecCodeModuleWithPathnames Modified: python/branches/import_unicode/Python/import.c Modified: python/branches/import_unicode/Python/import.c ============================================================================== --- python/branches/import_unicode/Python/import.c (original) +++ python/branches/import_unicode/Python/import.c Fri Jul 9 01:32:25 2010 @@ -859,6 +859,7 @@ for the compiled file, or NULL if there's no space in the buffer. Doesn't set an exception. */ +/* FIXME: use Py_UNICODE*, not char* */ static char * make_compiled_pathname(char *pathname, char *buf, size_t buflen, int debug) { @@ -1289,6 +1290,7 @@ char buf[MAXPATHLEN+1]; char *pathname; char *cpathname; + PyObject *cpathobj; PyCodeObject *co; PyObject *m; @@ -1313,28 +1315,40 @@ } #endif cpathname = make_compiled_pathname( - pathname, buf, (size_t)MAXPATHLEN + 1, !Py_OptimizeFlag); - if (cpathname != NULL) + pathname, buf, sizeof(buf), !Py_OptimizeFlag); + if (cpathname != NULL) { + cpathobj = PyUnicode_DecodeFSDefault(cpathname); + if (cpathobj == NULL) + return NULL; fpc = check_compiled_module(pathname, st.st_mtime, cpathname); - else + } + else { + cpathobj = NULL; fpc = NULL; + } if (fpc) { co = read_compiled_module(cpathname, fpc); fclose(fpc); - if (co == NULL) + if (co == NULL) { + Py_XDECREF(cpathobj); return NULL; - if (update_compiled_module(co, pathobj) < 0) + } + if (update_compiled_module(co, pathobj) < 0) { + Py_XDECREF(cpathobj); return NULL; + } if (Py_VerboseFlag) PySys_WriteStderr("import %s # precompiled from %s\n", name, cpathname); - pathobj = NULL; - pathname = cpathname; + m = PyImport_ExecCodeModuleWithUnicodePathnames( + name, (PyObject *)co, cpathobj, cpathobj); } else { co = parse_source_module(pathname, fp); - if (co == NULL) + if (co == NULL) { + Py_XDECREF(cpathobj); return NULL; + } if (Py_VerboseFlag) PySys_WriteStderr("import %s # from %s\n", name, pathname); @@ -1343,9 +1357,10 @@ if (ro == NULL || !PyObject_IsTrue(ro)) write_compiled_module(co, cpathname, &st); } + m = PyImport_ExecCodeModuleWithUnicodePathnames( + name, (PyObject *)co, pathobj, cpathobj); } - m = PyImport_ExecCodeModuleWithPathnames( - name, (PyObject *)co, pathname, cpathname); + Py_XDECREF(cpathobj); Py_DECREF(co); return m; @@ -3539,7 +3554,7 @@ if ((debug = PyObject_IsTrue(debug_override)) < 0) return NULL; - cpathname = make_compiled_pathname(pathname, buf, MAXPATHLEN+1, debug); + cpathname = make_compiled_pathname(pathname, buf, sizeof(buf), debug); PyMem_Free(pathname); if (cpathname == NULL) { From python-checkins at python.org Fri Jul 9 01:32:27 2010 From: python-checkins at python.org (victor.stinner) Date: Fri, 9 Jul 2010 01:32:27 +0200 (CEST) Subject: [Python-checkins] r82675 - python/branches/import_unicode/Python/import.c Message-ID: <20100708233227.68104EEB79@mail.python.org> Author: victor.stinner Date: Fri Jul 9 01:32:27 2010 New Revision: 82675 Log: load_compiled_module(): use object for the path instead of char* Modified: python/branches/import_unicode/Python/import.c Modified: python/branches/import_unicode/Python/import.c ============================================================================== --- python/branches/import_unicode/Python/import.c (original) +++ python/branches/import_unicode/Python/import.c Fri Jul 9 01:32:27 2010 @@ -1078,12 +1078,15 @@ module object WITH INCREMENTED REFERENCE COUNT */ static PyObject * -load_compiled_module(char *name, char *cpathname, FILE *fp) +load_compiled_module(char *name, PyObject *cpathobj, FILE *fp) { long magic; PyCodeObject *co; PyObject *m; - PyObject *cpathobj; + char *cpathname; + + /* FIXME: don't use _PyUnicode_AsString */ + cpathname = _PyUnicode_AsString(cpathobj); magic = PyMarshal_ReadLongFromFile(fp); if (magic != pyc_magic) { @@ -1098,10 +1101,8 @@ if (Py_VerboseFlag) PySys_WriteStderr("import %s # precompiled from %s\n", name, cpathname); - cpathobj = PyUnicode_DecodeFSDefault(cpathname); m = PyImport_ExecCodeModuleWithUnicodePathnames( name, (PyObject *)co, cpathobj, cpathobj); - Py_DECREF(cpathobj); Py_DECREF(co); return m; @@ -2120,9 +2121,14 @@ break; } - case PY_COMPILED: - m = load_compiled_module(name, pathname, fp); + case PY_COMPILED: { + PyObject *pathobj = PyUnicode_DecodeFSDefault(pathname); + if (pathobj == NULL) + return NULL; + m = load_compiled_module(name, pathobj, fp); + Py_DECREF(pathobj); break; + } #ifdef HAVE_DYNAMIC_LOADING case C_EXTENSION: { @@ -3390,23 +3396,20 @@ imp_load_compiled(PyObject *self, PyObject *args) { char *name; - char *pathname; + PyObject *pathname; PyObject *fob = NULL; PyObject *m; FILE *fp; - if (!PyArg_ParseTuple(args, "ses|O:load_compiled", - &name, - Py_FileSystemDefaultEncoding, &pathname, - &fob)) + if (!PyArg_ParseTuple(args, "sU|O:load_compiled", + &name, &pathname, &fob)) return NULL; - fp = get_file(pathname, fob, "rb"); + /* FIXME: don't use _PyUnicode_AsString */ + fp = get_file(_PyUnicode_AsString(pathname), fob, "rb"); if (fp == NULL) { - PyMem_Free(pathname); return NULL; } m = load_compiled_module(name, pathname, fp); fclose(fp); - PyMem_Free(pathname); return m; } From python-checkins at python.org Fri Jul 9 01:32:28 2010 From: python-checkins at python.org (victor.stinner) Date: Fri, 9 Jul 2010 01:32:28 +0200 (CEST) Subject: [Python-checkins] r82676 - python/branches/import_unicode/Python/import.c Message-ID: <20100708233228.CD6FCEEBA0@mail.python.org> Author: victor.stinner Date: Fri Jul 9 01:32:28 2010 New Revision: 82676 Log: get_file() path is now an object instead of char* Modified: python/branches/import_unicode/Python/import.c Modified: python/branches/import_unicode/Python/import.c ============================================================================== --- python/branches/import_unicode/Python/import.c (original) +++ python/branches/import_unicode/Python/import.c Fri Jul 9 01:32:28 2010 @@ -3363,12 +3363,17 @@ } static FILE * -get_file(char *pathname, PyObject *fob, char *mode) +get_file(PyObject *pathobj, PyObject *fob, char *mode) { FILE *fp; + char *pathname; if (mode[0] == 'U') mode = "r" PY_STDIOTEXTMODE; if (fob == NULL) { + /* FIXME: don't use _PyUnicode_AsString */ + pathname = _PyUnicode_AsString(pathobj); + if (pathname == NULL) + return NULL; fp = fopen(pathname, mode); } else { @@ -3403,8 +3408,7 @@ if (!PyArg_ParseTuple(args, "sU|O:load_compiled", &name, &pathname, &fob)) return NULL; - /* FIXME: don't use _PyUnicode_AsString */ - fp = get_file(_PyUnicode_AsString(pathname), fob, "rb"); + fp = get_file(pathname, fob, "rb"); if (fp == NULL) { return NULL; } @@ -3429,8 +3433,7 @@ &fob)) return NULL; if (fob) { - /* FIXME: don't use _PyUnicode_AsString */ - fp = get_file(_PyUnicode_AsString(pathname), fob, "r"); + fp = get_file(pathname, fob, "r"); if (fp == NULL) return NULL; } @@ -3453,8 +3456,7 @@ if (!PyArg_ParseTuple(args, "sU|O:load_source", &name, &pathname, &fob)) return NULL; - /* FIXME: don't use _PyUnicode_AsString */ - fp = get_file(_PyUnicode_AsString(pathname), fob, "r"); + fp = get_file(pathname, fob, "r"); if (fp == NULL) return NULL; m = load_source_module(name, pathname, fp); From python-checkins at python.org Fri Jul 9 01:32:30 2010 From: python-checkins at python.org (victor.stinner) Date: Fri, 9 Jul 2010 01:32:30 +0200 (CEST) Subject: [Python-checkins] r82677 - python/branches/import_unicode/Python/import.c Message-ID: <20100708233230.384F9EEB83@mail.python.org> Author: victor.stinner Date: Fri Jul 9 01:32:30 2010 New Revision: 82677 Log: create load_builtin() static function Modified: python/branches/import_unicode/Python/import.c Modified: python/branches/import_unicode/Python/import.c ============================================================================== --- python/branches/import_unicode/Python/import.c (original) +++ python/branches/import_unicode/Python/import.c Fri Jul 9 01:32:30 2010 @@ -2088,15 +2088,51 @@ static int init_builtin(char *); /* Forward */ +static PyObject* +load_builtin(char *name, char *pathname, int type) +{ + int err; + PyObject *m; + PyObject *modules; + + if (pathname != NULL && pathname[0] != '\0') + name = pathname; + if (type == C_BUILTIN) + err = init_builtin(name); + else + err = PyImport_ImportFrozenModule(name); + if (err < 0) + return NULL; + if (err == 0) { + PyErr_Format(PyExc_ImportError, + "Purported %s module %.200s not found", + type == C_BUILTIN ? + "builtin" : "frozen", + name); + return NULL; + } + modules = PyImport_GetModuleDict(); + m = PyDict_GetItemString(modules, name); + if (m == NULL) { + PyErr_Format( + PyExc_ImportError, + "%s module %.200s not properly initialized", + type == C_BUILTIN ? + "builtin" : "frozen", + name); + return NULL; + } + Py_INCREF(m); + return m; +} + /* Load an external module using the default search path and return its module object WITH INCREMENTED REFERENCE COUNT */ static PyObject * load_module(char *name, FILE *fp, char *pathname, int type, PyObject *loader) { - PyObject *modules; PyObject *m; - int err; /* First check that there's an open file (if we need one) */ switch (type) { @@ -2152,34 +2188,7 @@ case C_BUILTIN: case PY_FROZEN: - if (pathname != NULL && pathname[0] != '\0') - name = pathname; - if (type == C_BUILTIN) - err = init_builtin(name); - else - err = PyImport_ImportFrozenModule(name); - if (err < 0) - return NULL; - if (err == 0) { - PyErr_Format(PyExc_ImportError, - "Purported %s module %.200s not found", - type == C_BUILTIN ? - "builtin" : "frozen", - name); - return NULL; - } - modules = PyImport_GetModuleDict(); - m = PyDict_GetItemString(modules, name); - if (m == NULL) { - PyErr_Format( - PyExc_ImportError, - "%s module %.200s not properly initialized", - type == C_BUILTIN ? - "builtin" : "frozen", - name); - return NULL; - } - Py_INCREF(m); + m = load_builtin(name, pathname, type); break; case IMP_HOOK: { From python-checkins at python.org Fri Jul 9 01:32:31 2010 From: python-checkins at python.org (victor.stinner) Date: Fri, 9 Jul 2010 01:32:31 +0200 (CEST) Subject: [Python-checkins] r82678 - python/branches/import_unicode/Python/import.c Message-ID: <20100708233231.B74E6EEB20@mail.python.org> Author: victor.stinner Date: Fri Jul 9 01:32:31 2010 New Revision: 82678 Log: simplify load_source() Modified: python/branches/import_unicode/Python/import.c Modified: python/branches/import_unicode/Python/import.c ============================================================================== --- python/branches/import_unicode/Python/import.c (original) +++ python/branches/import_unicode/Python/import.c Fri Jul 9 01:32:31 2010 @@ -2094,7 +2094,7 @@ int err; PyObject *m; PyObject *modules; - + if (pathname != NULL && pathname[0] != '\0') name = pathname; if (type == C_BUILTIN) @@ -2133,6 +2133,7 @@ load_module(char *name, FILE *fp, char *pathname, int type, PyObject *loader) { PyObject *m; + PyObject *pathobj; /* First check that there's an open file (if we need one) */ switch (type) { @@ -2146,45 +2147,29 @@ } } + pathobj = PyUnicode_DecodeFSDefault(pathname); + if (pathobj == NULL) + return NULL; + switch (type) { - case PY_SOURCE: { - PyObject *pathobj = PyUnicode_DecodeFSDefault(pathname); - if (pathobj == NULL) - return NULL; + case PY_SOURCE: m = load_source_module(name, pathobj, fp); - Py_DECREF(pathobj); break; - } - case PY_COMPILED: { - PyObject *pathobj = PyUnicode_DecodeFSDefault(pathname); - if (pathobj == NULL) - return NULL; + case PY_COMPILED: m = load_compiled_module(name, pathobj, fp); - Py_DECREF(pathobj); break; - } #ifdef HAVE_DYNAMIC_LOADING - case C_EXTENSION: { - PyObject *pathobj = PyUnicode_DecodeFSDefault(pathname); - if (pathobj == NULL) - return NULL; + case C_EXTENSION: m = _PyImport_LoadDynamicModule(name, pathobj, fp); - Py_DECREF(pathobj); break; - } #endif - case PKG_DIRECTORY: { - PyObject *pathobj = PyUnicode_DecodeFSDefault(pathname); - if (pathobj == NULL) - return NULL; + case PKG_DIRECTORY: m = load_package(name, pathobj); - Py_DECREF(pathobj); break; - } case C_BUILTIN: case PY_FROZEN: @@ -2195,6 +2180,7 @@ if (loader == NULL) { PyErr_SetString(PyExc_ImportError, "import hook without loader"); + Py_DECREF(pathobj); return NULL; } m = PyObject_CallMethod(loader, "load_module", "s", name); @@ -2208,6 +2194,7 @@ m = NULL; } + Py_DECREF(pathobj); return m; } From python-checkins at python.org Fri Jul 9 01:32:33 2010 From: python-checkins at python.org (victor.stinner) Date: Fri, 9 Jul 2010 01:32:33 +0200 (CEST) Subject: [Python-checkins] r82679 - python/branches/import_unicode/Python/import.c Message-ID: <20100708233233.2B534EEB04@mail.python.org> Author: victor.stinner Date: Fri Jul 9 01:32:33 2010 New Revision: 82679 Log: load_builtin() path is an object Modified: python/branches/import_unicode/Python/import.c Modified: python/branches/import_unicode/Python/import.c ============================================================================== --- python/branches/import_unicode/Python/import.c (original) +++ python/branches/import_unicode/Python/import.c Fri Jul 9 01:32:33 2010 @@ -2089,14 +2089,21 @@ static int init_builtin(char *); /* Forward */ static PyObject* -load_builtin(char *name, char *pathname, int type) +load_builtin(char *name, PyObject *pathobj, int type) { int err; PyObject *m; PyObject *modules; + char *pathname; - if (pathname != NULL && pathname[0] != '\0') - name = pathname; + if (pathobj != NULL) { + /* FIXME: don't use _PyUnicode_AsString */ + pathname = _PyUnicode_AsString(pathobj); + if (pathname == NULL) + return NULL; + if (pathname[0] != '\0') + name = pathname; + } if (type == C_BUILTIN) err = init_builtin(name); else @@ -2173,7 +2180,7 @@ case C_BUILTIN: case PY_FROZEN: - m = load_builtin(name, pathname, type); + m = load_builtin(name, pathobj, type); break; case IMP_HOOK: { From python-checkins at python.org Fri Jul 9 01:32:34 2010 From: python-checkins at python.org (victor.stinner) Date: Fri, 9 Jul 2010 01:32:34 +0200 (CEST) Subject: [Python-checkins] r82680 - python/branches/import_unicode/Python/import.c Message-ID: <20100708233234.D176FEEB79@mail.python.org> Author: victor.stinner Date: Fri Jul 9 01:32:34 2010 New Revision: 82680 Log: load_module() path is an object Modified: python/branches/import_unicode/Python/import.c Modified: python/branches/import_unicode/Python/import.c ============================================================================== --- python/branches/import_unicode/Python/import.c (original) +++ python/branches/import_unicode/Python/import.c Fri Jul 9 01:32:34 2010 @@ -1417,7 +1417,7 @@ } /* Forward */ -static PyObject *load_module(char *, FILE *, char *, int, PyObject *); +static PyObject *load_module(char *, FILE *, PyObject *, int, PyObject *); static struct filedescr *find_module(char *, char *, PyObject *, char *, size_t, FILE **, PyObject **); static struct _frozen * find_frozen(char *); @@ -1436,6 +1436,7 @@ FILE *fp = NULL; struct filedescr *fdp; char *pathname; + PyObject *bufobj; /* FIXME: don't use _PyUnicode_AsString */ pathname = _PyUnicode_AsString(pathobj); @@ -1469,7 +1470,11 @@ m = NULL; goto cleanup; } - m = load_module(name, fp, buf, fdp->type, NULL); + bufobj = PyUnicode_DecodeFSDefault(buf); + if (bufobj != NULL) + m = load_module(name, fp, bufobj, fdp->type, NULL); + else + m = NULL; if (fp != NULL) fclose(fp); goto cleanup; @@ -2137,10 +2142,9 @@ its module object WITH INCREMENTED REFERENCE COUNT */ static PyObject * -load_module(char *name, FILE *fp, char *pathname, int type, PyObject *loader) +load_module(char *name, FILE *fp, PyObject *pathobj, int type, PyObject *loader) { PyObject *m; - PyObject *pathobj; /* First check that there's an open file (if we need one) */ switch (type) { @@ -2154,10 +2158,6 @@ } } - pathobj = PyUnicode_DecodeFSDefault(pathname); - if (pathobj == NULL) - return NULL; - switch (type) { case PY_SOURCE: @@ -2201,7 +2201,6 @@ m = NULL; } - Py_DECREF(pathobj); return m; } @@ -2929,6 +2928,7 @@ { PyObject *modules = PyImport_GetModuleDict(); PyObject *m = NULL; + PyObject *pathobj; /* Require: if mod == None: subname == fullname @@ -2966,7 +2966,11 @@ Py_INCREF(Py_None); return Py_None; } - m = load_module(fullname, fp, buf, fdp->type, loader); + pathobj = PyUnicode_DecodeFSDefault(buf); + if (pathobj != NULL) + m = load_module(fullname, fp, pathobj, fdp->type, loader); + else + m = NULL; Py_XDECREF(loader); if (fp) fclose(fp); @@ -2994,6 +2998,7 @@ char buf[MAXPATHLEN+1]; struct filedescr *fdp; FILE *fp = NULL; + PyObject *pathobj; PyObject *newm; if (modules_reloading == NULL) { @@ -3061,7 +3066,11 @@ return NULL; } - newm = load_module(name, fp, buf, fdp->type, loader); + pathobj = PyUnicode_DecodeFSDefault(buf); + if (pathobj != NULL) + newm = load_module(name, fp, pathobj, fdp->type, loader); + else + newm = NULL; Py_XDECREF(loader); if (fp) @@ -3472,16 +3481,16 @@ { char *name; PyObject *fob; - char *pathname; + PyObject *pathname; PyObject * ret; char *suffix; /* Unused */ char *mode; int type; FILE *fp; - if (!PyArg_ParseTuple(args, "sOes(ssi):load_module", + if (!PyArg_ParseTuple(args, "sOU(ssi):load_module", &name, &fob, - Py_FileSystemDefaultEncoding, &pathname, + &pathname, &suffix, &mode, &type)) return NULL; if (*mode) { @@ -3492,7 +3501,6 @@ if (!(*mode == 'r' || *mode == 'U') || strchr(mode, '+')) { PyErr_Format(PyExc_ValueError, "invalid file open mode %.200s", mode); - PyMem_Free(pathname); return NULL; } } @@ -3500,13 +3508,10 @@ fp = NULL; else { fp = get_file(NULL, fob, mode); - if (fp == NULL) { - PyMem_Free(pathname); + if (fp == NULL) return NULL; - } } ret = load_module(name, fp, pathname, type, NULL); - PyMem_Free(pathname); if (fp) fclose(fp); return ret; From python-checkins at python.org Fri Jul 9 01:32:36 2010 From: python-checkins at python.org (victor.stinner) Date: Fri, 9 Jul 2010 01:32:36 +0200 (CEST) Subject: [Python-checkins] r82681 - python/branches/import_unicode/Python/import.c Message-ID: <20100708233236.61414EEAF0@mail.python.org> Author: victor.stinner Date: Fri Jul 9 01:32:36 2010 New Revision: 82681 Log: change make_compiled_pathname() API but not the code Modified: python/branches/import_unicode/Python/import.c Modified: python/branches/import_unicode/Python/import.c ============================================================================== --- python/branches/import_unicode/Python/import.c (original) +++ python/branches/import_unicode/Python/import.c Fri Jul 9 01:32:36 2010 @@ -720,8 +720,8 @@ static PyObject * get_sourcefile(PyObject *file); static char *make_source_pathname(char *pathname, char *buf); -static char *make_compiled_pathname(char *pathname, char *buf, size_t buflen, - int debug); +static PyObject *make_compiled_pathname(PyObject *pathname, char *buf, + size_t buflen, int debug); /* Execute a code object in a module and return the module object * WITH INCREMENTED REFERENCE COUNT. If an error occurs, name is @@ -861,7 +861,7 @@ /* FIXME: use Py_UNICODE*, not char* */ static char * -make_compiled_pathname(char *pathname, char *buf, size_t buflen, int debug) +_make_compiled_pathname(char *pathname, char *buf, size_t buflen, int debug) { /* foo.py -> __pycache__/foo..pyc */ size_t len = strlen(pathname); @@ -963,6 +963,21 @@ return buf; } +static PyObject* +make_compiled_pathname(PyObject *pathobj, char *buf, size_t buflen, int debug) +{ + char *pathname, *cpathname; + + /* FIXME: don't use _PyUnicode_AsString */ + pathname = _PyUnicode_AsString(pathobj); + + cpathname = _make_compiled_pathname(pathname, buf, buflen, debug); + if (cpathname != NULL) + return PyUnicode_DecodeFSDefault(cpathname); + else + return NULL; +} + /* Given a pathname to a Python byte compiled file, return the path to the source file, if the path matches the PEP 3147 format. This does not check @@ -1315,16 +1330,21 @@ return NULL; } #endif - cpathname = make_compiled_pathname( - pathname, buf, sizeof(buf), !Py_OptimizeFlag); - if (cpathname != NULL) { - cpathobj = PyUnicode_DecodeFSDefault(cpathname); - if (cpathobj == NULL) + cpathobj = make_compiled_pathname( + pathobj, buf, sizeof(buf), !Py_OptimizeFlag); + if (cpathobj != NULL) { + /* FIXME: don't use _PyUnicode_AsString */ + cpathname = _PyUnicode_AsString(cpathobj); + if (cpathobj == NULL) { + Py_DECREF(cpathobj); return NULL; + } fpc = check_compiled_module(pathname, st.st_mtime, cpathname); } else { - cpathobj = NULL; + if (PyErr_Occurred()) + return NULL; + cpathname = NULL; fpc = NULL; } if (fpc) { @@ -3554,13 +3574,14 @@ static char *kwlist[] = {"path", "debug_override", NULL}; char buf[MAXPATHLEN+1]; - char *pathname, *cpathname; + PyObject *pathname; PyObject *debug_override = Py_None; int debug = !Py_OptimizeFlag; + PyObject *cpathname; if (!PyArg_ParseTupleAndKeywords( - args, kws, "es|O", kwlist, - Py_FileSystemDefaultEncoding, &pathname, &debug_override)) + args, kws, "U|O", kwlist, + &pathname, &debug_override)) return NULL; if (debug_override != Py_None) @@ -3568,13 +3589,11 @@ return NULL; cpathname = make_compiled_pathname(pathname, buf, sizeof(buf), debug); - PyMem_Free(pathname); - if (cpathname == NULL) { PyErr_Format(PyExc_SystemError, "path buffer too short"); return NULL; } - return PyUnicode_FromString(buf); + return cpathname; } PyDoc_STRVAR(doc_cache_from_source, From python-checkins at python.org Fri Jul 9 01:32:37 2010 From: python-checkins at python.org (victor.stinner) Date: Fri, 9 Jul 2010 01:32:37 +0200 (CEST) Subject: [Python-checkins] r82682 - python/branches/import_unicode/Python/import.c Message-ID: <20100708233237.D199FEEAF3@mail.python.org> Author: victor.stinner Date: Fri Jul 9 01:32:37 2010 New Revision: 82682 Log: change make_source_pathname(): use objects and not char* Modified: python/branches/import_unicode/Python/import.c Modified: python/branches/import_unicode/Python/import.c ============================================================================== --- python/branches/import_unicode/Python/import.c (original) +++ python/branches/import_unicode/Python/import.c Fri Jul 9 01:32:37 2010 @@ -719,7 +719,7 @@ } static PyObject * get_sourcefile(PyObject *file); -static char *make_source_pathname(char *pathname, char *buf); +static PyObject *make_source_pathname(PyObject *pathname, char *buf); static PyObject *make_compiled_pathname(PyObject *pathname, char *buf, size_t buflen, int debug); @@ -986,7 +986,7 @@ the resulting path will always be shorter. */ static char * -make_source_pathname(char *pathname, char *buf) +_make_source_pathname(char *pathname, char *buf) { /* __pycache__/foo..pyc -> foo.py */ size_t i, j; @@ -1032,6 +1032,21 @@ return buf; } +static PyObject* +make_source_pathname(PyObject *pathobj, char *buf) +{ + char *pathname, *cpathname; + + /* FIXME: don't use _PyUnicode_AsString */ + pathname = _PyUnicode_AsString(pathobj); + + cpathname = _make_source_pathname(pathname, buf); + if (cpathname != NULL) + return PyUnicode_DecodeFSDefault(cpathname); + else + return NULL; +} + /* Given a pathname for a Python source file, its time of last modification, and a pathname for a compiled file, check whether the compiled file represents the same version of the source. If so, @@ -1394,19 +1409,20 @@ get_sourcefile(PyObject *fileobj) { /* FIXME: use Py_UNICODE* instead of char* */ - char py[MAXPATHLEN + 1]; + char buf[MAXPATHLEN + 1]; + char *py; + PyObject *pyobj; Py_ssize_t len; struct stat statbuf; char *file; - if (!fileobj) { + if (fileobj == NULL) { Py_RETURN_NONE; } /* FIXME: don't use _PyUnicode_AsString */ file = _PyUnicode_AsString(fileobj); - - if (!file || !*file) { + if (file == NULL || !*file) { Py_RETURN_NONE; } @@ -1421,16 +1437,25 @@ * fails, just chop off the trailing character, i.e. legacy pyc path * to py. */ - if (make_source_pathname(file, py) == NULL) { - strncpy(py, file, len-1); - py[len-1] = '\0'; + pyobj = make_source_pathname(fileobj, buf); + if (pyobj == NULL) { + if (PyErr_Occurred()) + return NULL; + pyobj = PyUnicode_FromStringAndSize(file, len - 1); + if (pyobj == NULL) + return NULL; } + /* FIXME: don't use _PyUnicode_AsString */ + py = _PyUnicode_AsString(pyobj); + if (py == NULL) + return NULL; if (stat(py, &statbuf) == 0 && S_ISREG(statbuf.st_mode)) { - return PyUnicode_DecodeFSDefault(py); + return pyobj; } else { + Py_DECREF(pyobj); Py_INCREF(fileobj); return fileobj; } @@ -3611,22 +3636,23 @@ { static char *kwlist[] = {"path", NULL}; - char *pathname; + PyObject *pathname; char buf[MAXPATHLEN+1]; + PyObject *result; if (!PyArg_ParseTupleAndKeywords( - args, kws, "es", kwlist, - Py_FileSystemDefaultEncoding, &pathname)) + args, kws, "U", kwlist, + &pathname)) return NULL; - if (make_source_pathname(pathname, buf) == NULL) { - PyErr_Format(PyExc_ValueError, "Not a PEP 3147 pyc path: %s", - pathname); - PyMem_Free(pathname); + result = make_source_pathname(pathname, buf); + if (result == NULL) { + if (!PyErr_Occurred()) + PyErr_Format(PyExc_ValueError, "Not a PEP 3147 pyc path: %U", + pathname); return NULL; } - PyMem_Free(pathname); - return PyUnicode_FromString(buf); + return result; } PyDoc_STRVAR(doc_source_from_cache, From python-checkins at python.org Fri Jul 9 01:32:39 2010 From: python-checkins at python.org (victor.stinner) Date: Fri, 9 Jul 2010 01:32:39 +0200 (CEST) Subject: [Python-checkins] r82683 - python/branches/import_unicode/Python/import.c Message-ID: <20100708233239.82BD2EEBCA@mail.python.org> Author: victor.stinner Date: Fri Jul 9 01:32:39 2010 New Revision: 82683 Log: get_sourcefile() uses Py_UNICODE* for file Move buf into make_source_pathname() Modified: python/branches/import_unicode/Python/import.c Modified: python/branches/import_unicode/Python/import.c ============================================================================== --- python/branches/import_unicode/Python/import.c (original) +++ python/branches/import_unicode/Python/import.c Fri Jul 9 01:32:39 2010 @@ -719,7 +719,7 @@ } static PyObject * get_sourcefile(PyObject *file); -static PyObject *make_source_pathname(PyObject *pathname, char *buf); +static PyObject *make_source_pathname(PyObject *pathname); static PyObject *make_compiled_pathname(PyObject *pathname, char *buf, size_t buflen, int debug); @@ -1033,8 +1033,10 @@ } static PyObject* -make_source_pathname(PyObject *pathobj, char *buf) +make_source_pathname(PyObject *pathobj) { + /* FIXME: use Py_UNICODE* instead of char* */ + char buf[MAXPATHLEN + 1]; char *pathname, *cpathname; /* FIXME: don't use _PyUnicode_AsString */ @@ -1408,27 +1410,26 @@ static PyObject * get_sourcefile(PyObject *fileobj) { - /* FIXME: use Py_UNICODE* instead of char* */ - char buf[MAXPATHLEN + 1]; char *py; PyObject *pyobj; + Py_UNICODE *file; Py_ssize_t len; struct stat statbuf; - char *file; if (fileobj == NULL) { Py_RETURN_NONE; } - /* FIXME: don't use _PyUnicode_AsString */ - file = _PyUnicode_AsString(fileobj); - if (file == NULL || !*file) { + len = PyUnicode_GET_SIZE(fileobj); + if (len == 0) Py_RETURN_NONE; - } + file = PyUnicode_AS_UNICODE(fileobj); - len = strlen(file); /* match '*.py?' */ - if (len > MAXPATHLEN || PyOS_strnicmp(&file[len-4], ".py", 3) != 0) { + if (4 <= len + && file[len-3] == '.' + && (file[len-2] == 'p' || file[len-2] == 'P') + && (file[len-1] == 'y' || file[len-1] == 'Y')) { Py_INCREF(fileobj); return fileobj; } @@ -1437,11 +1438,11 @@ * fails, just chop off the trailing character, i.e. legacy pyc path * to py. */ - pyobj = make_source_pathname(fileobj, buf); + pyobj = make_source_pathname(fileobj); if (pyobj == NULL) { if (PyErr_Occurred()) return NULL; - pyobj = PyUnicode_FromStringAndSize(file, len - 1); + pyobj = PyUnicode_FromUnicode(file, len - 1); if (pyobj == NULL) return NULL; } @@ -3637,7 +3638,6 @@ static char *kwlist[] = {"path", NULL}; PyObject *pathname; - char buf[MAXPATHLEN+1]; PyObject *result; if (!PyArg_ParseTupleAndKeywords( @@ -3645,7 +3645,7 @@ &pathname)) return NULL; - result = make_source_pathname(pathname, buf); + result = make_source_pathname(pathname); if (result == NULL) { if (!PyErr_Occurred()) PyErr_Format(PyExc_ValueError, "Not a PEP 3147 pyc path: %U", From python-checkins at python.org Fri Jul 9 01:32:41 2010 From: python-checkins at python.org (victor.stinner) Date: Fri, 9 Jul 2010 01:32:41 +0200 (CEST) Subject: [Python-checkins] r82684 - in python/branches/import_unicode: Include/sysmodule.h Python/sysmodule.c Message-ID: <20100708233241.0F420EEBC1@mail.python.org> Author: victor.stinner Date: Fri Jul 9 01:32:40 2010 New Revision: 82684 Log: Create PySys_FormatStderr() function Similar to PySys_WriteStderr() but use PyUnicode_FromFormatV() instead of PyOS_snprintf() Modified: python/branches/import_unicode/Include/sysmodule.h python/branches/import_unicode/Python/sysmodule.c Modified: python/branches/import_unicode/Include/sysmodule.h ============================================================================== --- python/branches/import_unicode/Include/sysmodule.h (original) +++ python/branches/import_unicode/Include/sysmodule.h Fri Jul 9 01:32:40 2010 @@ -14,9 +14,10 @@ PyAPI_FUNC(void) PySys_SetPath(const wchar_t *); PyAPI_FUNC(void) PySys_WriteStdout(const char *format, ...) - Py_GCC_ATTRIBUTE((format(printf, 1, 2))); + Py_GCC_ATTRIBUTE((format(printf, 1, 2))); PyAPI_FUNC(void) PySys_WriteStderr(const char *format, ...) - Py_GCC_ATTRIBUTE((format(printf, 1, 2))); + Py_GCC_ATTRIBUTE((format(printf, 1, 2))); +PyAPI_FUNC(void) PySys_FormatStderr(const char *format, ...); PyAPI_DATA(PyObject *) _PySys_TraceFunc, *_PySys_ProfileFunc; Modified: python/branches/import_unicode/Python/sysmodule.c ============================================================================== --- python/branches/import_unicode/Python/sysmodule.c (original) +++ python/branches/import_unicode/Python/sysmodule.c Fri Jul 9 01:32:40 2010 @@ -1834,18 +1834,14 @@ PyErr_CheckSignals(): avoid the call to PyObject_Str(). */ static int -sys_pyfile_write(const char *text, PyObject *file) +sys_pyfile_write_unicode(PyObject *unicode, PyObject *file) { - PyObject *unicode = NULL, *writer = NULL, *args = NULL, *result = NULL; + PyObject *writer = NULL, *args = NULL, *result = NULL; int err; if (file == NULL) return -1; - unicode = PyUnicode_FromString(text); - if (unicode == NULL) - goto error; - writer = PyObject_GetAttrString(file, "write"); if (writer == NULL) goto error; @@ -1865,13 +1861,29 @@ error: err = -1; finally: - Py_XDECREF(unicode); Py_XDECREF(writer); Py_XDECREF(args); Py_XDECREF(result); return err; } +static int +sys_pyfile_write(const char *text, PyObject *file) +{ + PyObject *unicode = NULL; + int err; + + if (file == NULL) + return -1; + + unicode = PyUnicode_FromString(text); + if (unicode == NULL) + return -1; + + err = sys_pyfile_write_unicode(unicode, file); + Py_DECREF(unicode); + return err; +} /* APIs to write to sys.stdout or sys.stderr using a printf-like interface. Adapted from code submitted by Just van Rossum. @@ -1918,10 +1930,28 @@ } if (written < 0 || (size_t)written >= sizeof(buffer)) { const char *truncated = "... truncated"; - if (sys_pyfile_write(truncated, file) != 0) { - PyErr_Clear(); + if (sys_pyfile_write(truncated, file) != 0) fputs(truncated, fp); - } + } + PyErr_Restore(error_type, error_value, error_traceback); +} + +static void +myformat(char *name, FILE *fp, const char *format, va_list va) +{ + PyObject *file; + PyObject *error_type, *error_value, *error_traceback; + PyObject *unicode; + char *str; + + PyErr_Fetch(&error_type, &error_value, &error_traceback); + file = PySys_GetObject(name); + unicode = PyUnicode_FromFormatV(format, va); + if (sys_pyfile_write_unicode(unicode, file) != 0) { + PyErr_Clear(); + str = _PyUnicode_AsString(unicode); + if (str != NULL) + fputs(str, fp); } PyErr_Restore(error_type, error_value, error_traceback); } @@ -1945,3 +1975,13 @@ mywrite("stderr", stderr, format, va); va_end(va); } + +void +PySys_FormatStderr(const char *format, ...) +{ + va_list va; + + va_start(va, format); + myformat("stderr", stderr, format, va); + va_end(va); +} From python-checkins at python.org Fri Jul 9 01:32:42 2010 From: python-checkins at python.org (victor.stinner) Date: Fri, 9 Jul 2010 01:32:42 +0200 (CEST) Subject: [Python-checkins] r82685 - python/branches/import_unicode/Python/import.c Message-ID: <20100708233242.7BA43EEB62@mail.python.org> Author: victor.stinner Date: Fri Jul 9 01:32:42 2010 New Revision: 82685 Log: move the buffer into make_compiled_pathname() Modified: python/branches/import_unicode/Python/import.c Modified: python/branches/import_unicode/Python/import.c ============================================================================== --- python/branches/import_unicode/Python/import.c (original) +++ python/branches/import_unicode/Python/import.c Fri Jul 9 01:32:42 2010 @@ -720,8 +720,7 @@ static PyObject * get_sourcefile(PyObject *file); static PyObject *make_source_pathname(PyObject *pathname); -static PyObject *make_compiled_pathname(PyObject *pathname, char *buf, - size_t buflen, int debug); +static PyObject *make_compiled_pathname(PyObject *pathname, int debug); /* Execute a code object in a module and return the module object * WITH INCREMENTED REFERENCE COUNT. If an error occurs, name is @@ -964,14 +963,15 @@ } static PyObject* -make_compiled_pathname(PyObject *pathobj, char *buf, size_t buflen, int debug) +make_compiled_pathname(PyObject *pathobj, int debug) { + char buf[MAXPATHLEN+1]; char *pathname, *cpathname; /* FIXME: don't use _PyUnicode_AsString */ pathname = _PyUnicode_AsString(pathobj); - cpathname = _make_compiled_pathname(pathname, buf, buflen, debug); + cpathname = _make_compiled_pathname(pathname, buf, sizeof(buf), debug); if (cpathname != NULL) return PyUnicode_DecodeFSDefault(cpathname); else @@ -1347,8 +1347,7 @@ return NULL; } #endif - cpathobj = make_compiled_pathname( - pathobj, buf, sizeof(buf), !Py_OptimizeFlag); + cpathobj = make_compiled_pathname(pathobj, !Py_OptimizeFlag); if (cpathobj != NULL) { /* FIXME: don't use _PyUnicode_AsString */ cpathname = _PyUnicode_AsString(cpathobj); @@ -3598,8 +3597,6 @@ imp_cache_from_source(PyObject *self, PyObject *args, PyObject *kws) { static char *kwlist[] = {"path", "debug_override", NULL}; - - char buf[MAXPATHLEN+1]; PyObject *pathname; PyObject *debug_override = Py_None; int debug = !Py_OptimizeFlag; @@ -3614,7 +3611,7 @@ if ((debug = PyObject_IsTrue(debug_override)) < 0) return NULL; - cpathname = make_compiled_pathname(pathname, buf, sizeof(buf), debug); + cpathname = make_compiled_pathname(pathname, debug); if (cpathname == NULL) { PyErr_Format(PyExc_SystemError, "path buffer too short"); return NULL; From python-checkins at python.org Fri Jul 9 01:32:43 2010 From: python-checkins at python.org (victor.stinner) Date: Fri, 9 Jul 2010 01:32:43 +0200 (CEST) Subject: [Python-checkins] r82686 - python/branches/import_unicode/Python/import.c Message-ID: <20100708233243.E0F03EEBC1@mail.python.org> Author: victor.stinner Date: Fri Jul 9 01:32:43 2010 New Revision: 82686 Log: use PySys_FormatStderr() Modified: python/branches/import_unicode/Python/import.c Modified: python/branches/import_unicode/Python/import.c ============================================================================== --- python/branches/import_unicode/Python/import.c (original) +++ python/branches/import_unicode/Python/import.c Fri Jul 9 01:32:43 2010 @@ -661,10 +661,8 @@ return NULL; } if (Py_VerboseFlag) - PySys_WriteStderr("import %s # previously loaded (%s)\n", - name, - /* FIXME: don't use _PyUnicode_AsString */ - _PyUnicode_AsString(filename)); + PySys_FormatStderr("import %s # previously loaded (%U)\n", + name, filename); return mod; } @@ -1131,8 +1129,8 @@ if (co == NULL) return NULL; if (Py_VerboseFlag) - PySys_WriteStderr("import %s # precompiled from %s\n", - name, cpathname); + PySys_FormatStderr("import %s # precompiled from %U\n", + name, cpathobj); m = PyImport_ExecCodeModuleWithUnicodePathnames( name, (PyObject *)co, cpathobj, cpathobj); Py_DECREF(co); @@ -1320,7 +1318,6 @@ { struct stat st; FILE *fpc; - char buf[MAXPATHLEN+1]; char *pathname; char *cpathname; PyObject *cpathobj; @@ -1375,8 +1372,8 @@ return NULL; } if (Py_VerboseFlag) - PySys_WriteStderr("import %s # precompiled from %s\n", - name, cpathname); + PySys_FormatStderr("import %s # precompiled from %U\n", + name, cpathobj); m = PyImport_ExecCodeModuleWithUnicodePathnames( name, (PyObject *)co, cpathobj, cpathobj); } @@ -1387,8 +1384,7 @@ return NULL; } if (Py_VerboseFlag) - PySys_WriteStderr("import %s # from %s\n", - name, pathname); + PySys_FormatStderr("import %s # from %U\n", name, pathobj); if (cpathname) { PyObject *ro = PySys_GetObject("dont_write_bytecode"); if (ro == NULL || !PyObject_IsTrue(ro)) @@ -1490,8 +1486,7 @@ if (m == NULL) return NULL; if (Py_VerboseFlag) - PySys_WriteStderr("import %s # directory %s\n", - name, pathname); + PySys_FormatStderr("import %s # directory %U\n", name, pathobj); d = PyModule_GetDict(m); file = get_sourcefile(pathobj); if (file == NULL) From python-checkins at python.org Fri Jul 9 01:32:45 2010 From: python-checkins at python.org (victor.stinner) Date: Fri, 9 Jul 2010 01:32:45 +0200 (CEST) Subject: [Python-checkins] r82687 - python/branches/import_unicode/Python/import.c Message-ID: <20100708233245.58D0FEEB79@mail.python.org> Author: victor.stinner Date: Fri Jul 9 01:32:45 2010 New Revision: 82687 Log: use object in error message Modified: python/branches/import_unicode/Python/import.c Modified: python/branches/import_unicode/Python/import.c ============================================================================== --- python/branches/import_unicode/Python/import.c (original) +++ python/branches/import_unicode/Python/import.c Fri Jul 9 01:32:45 2010 @@ -1329,8 +1329,8 @@ if (fstat(fileno(fp), &st) != 0) { PyErr_Format(PyExc_RuntimeError, - "unable to get file status from '%s'", - pathname); + "unable to get file status from '%U'", + pathobj); return NULL; } #if SIZEOF_TIME_T > 4 From python-checkins at python.org Fri Jul 9 01:32:46 2010 From: python-checkins at python.org (victor.stinner) Date: Fri, 9 Jul 2010 01:32:46 +0200 (CEST) Subject: [Python-checkins] r82688 - python/branches/import_unicode/Python/import.c Message-ID: <20100708233246.BB2B4EEB30@mail.python.org> Author: victor.stinner Date: Fri Jul 9 01:32:46 2010 New Revision: 82688 Log: parse_source_module() uses object not char* Modified: python/branches/import_unicode/Python/import.c Modified: python/branches/import_unicode/Python/import.c ============================================================================== --- python/branches/import_unicode/Python/import.c (original) +++ python/branches/import_unicode/Python/import.c Fri Jul 9 01:32:46 2010 @@ -1141,15 +1141,22 @@ /* Parse a source file and return the corresponding code object */ static PyCodeObject * -parse_source_module(const char *pathname, FILE *fp) +parse_source_module(PyObject *pathobj, FILE *fp) { PyCodeObject *co = NULL; mod_ty mod; PyCompilerFlags flags; + char *pathname; + PyArena *arena = PyArena_New(); if (arena == NULL) return NULL; + /* FIXME: use PyUnicode_EncodeFSDefault() */ + pathname = _PyUnicode_AsString(pathobj); + if (pathname == NULL) + return NULL; + flags.cf_flags = 0; mod = PyParser_ASTFromFile(fp, pathname, NULL, Py_file_input, 0, 0, &flags, @@ -1324,8 +1331,10 @@ PyCodeObject *co; PyObject *m; - /* FIXME: don't use _PyUnicode_AsString */ + /* FIXME: use PyUnicode_EncodeFSDefault() */ pathname = _PyUnicode_AsString(pathobj); + if (pathname == NULL) + return NULL; if (fstat(fileno(fp), &st) != 0) { PyErr_Format(PyExc_RuntimeError, @@ -1378,7 +1387,7 @@ name, (PyObject *)co, cpathobj, cpathobj); } else { - co = parse_source_module(pathname, fp); + co = parse_source_module(pathobj, fp); if (co == NULL) { Py_XDECREF(cpathobj); return NULL; @@ -1442,7 +1451,7 @@ return NULL; } - /* FIXME: don't use _PyUnicode_AsString */ + /* FIXME: use PyUnicode_EncodeFSDefault() */ py = _PyUnicode_AsString(pyobj); if (py == NULL) return NULL; @@ -1476,12 +1485,8 @@ char buf[MAXPATHLEN+1]; FILE *fp = NULL; struct filedescr *fdp; - char *pathname; PyObject *bufobj; - /* FIXME: don't use _PyUnicode_AsString */ - pathname = _PyUnicode_AsString(pathobj); - m = PyImport_AddModule(name); if (m == NULL) return NULL; From python-checkins at python.org Fri Jul 9 01:32:48 2010 From: python-checkins at python.org (victor.stinner) Date: Fri, 9 Jul 2010 01:32:48 +0200 (CEST) Subject: [Python-checkins] r82689 - python/branches/import_unicode/Python/import.c Message-ID: <20100708233248.39D72EE9BE@mail.python.org> Author: victor.stinner Date: Fri Jul 9 01:32:48 2010 New Revision: 82689 Log: check_compiled_module() and read_compiled_module() use objects Modified: python/branches/import_unicode/Python/import.c Modified: python/branches/import_unicode/Python/import.c ============================================================================== --- python/branches/import_unicode/Python/import.c (original) +++ python/branches/import_unicode/Python/import.c Fri Jul 9 01:32:48 2010 @@ -1055,11 +1055,17 @@ Doesn't set an exception. */ static FILE * -check_compiled_module(char *pathname, time_t mtime, char *cpathname) +check_compiled_module(PyObject *pathobj, time_t mtime, PyObject *cpathobj) { FILE *fp; long magic; long pyc_mtime; + char *cpathname; + + /* FIXME: use PyUnicode_EncodeFSDefault() */ + cpathname = _PyUnicode_AsString(cpathobj); + if (cpathname == NULL) + return NULL; fp = fopen(cpathname, "rb"); if (fp == NULL) @@ -1067,19 +1073,19 @@ magic = PyMarshal_ReadLongFromFile(fp); if (magic != pyc_magic) { if (Py_VerboseFlag) - PySys_WriteStderr("# %s has bad magic\n", cpathname); + PySys_FormatStderr("# %U has bad magic\n", cpathobj); fclose(fp); return NULL; } pyc_mtime = PyMarshal_ReadLongFromFile(fp); if (pyc_mtime != mtime) { if (Py_VerboseFlag) - PySys_WriteStderr("# %s has bad mtime\n", cpathname); + PySys_FormatStderr("# %s has bad mtime\n", cpathobj); fclose(fp); return NULL; } if (Py_VerboseFlag) - PySys_WriteStderr("# %s matches %s\n", cpathname, pathname); + PySys_FormatStderr("# %U matches %U\n", cpathobj, pathobj); return fp; } @@ -1087,7 +1093,7 @@ /* Read a code object from a file and check it for validity */ static PyCodeObject * -read_compiled_module(char *cpathname, FILE *fp) +read_compiled_module(PyObject *cpathobj, FILE *fp) { PyObject *co; @@ -1096,7 +1102,7 @@ return NULL; if (!PyCode_Check(co)) { PyErr_Format(PyExc_ImportError, - "Non-code object in %.200s", cpathname); + "Non-code object in %U", cpathobj); Py_DECREF(co); return NULL; } @@ -1113,19 +1119,15 @@ long magic; PyCodeObject *co; PyObject *m; - char *cpathname; - - /* FIXME: don't use _PyUnicode_AsString */ - cpathname = _PyUnicode_AsString(cpathobj); magic = PyMarshal_ReadLongFromFile(fp); if (magic != pyc_magic) { PyErr_Format(PyExc_ImportError, - "Bad magic number in %.200s", cpathname); + "Bad magic number in %U", cpathobj); return NULL; } (void) PyMarshal_ReadLongFromFile(fp); - co = read_compiled_module(cpathname, fp); + co = read_compiled_module(cpathobj, fp); if (co == NULL) return NULL; if (Py_VerboseFlag) @@ -1325,17 +1327,11 @@ { struct stat st; FILE *fpc; - char *pathname; char *cpathname; PyObject *cpathobj; PyCodeObject *co; PyObject *m; - /* FIXME: use PyUnicode_EncodeFSDefault() */ - pathname = _PyUnicode_AsString(pathobj); - if (pathname == NULL) - return NULL; - if (fstat(fileno(fp), &st) != 0) { PyErr_Format(PyExc_RuntimeError, "unable to get file status from '%U'", @@ -1361,7 +1357,7 @@ Py_DECREF(cpathobj); return NULL; } - fpc = check_compiled_module(pathname, st.st_mtime, cpathname); + fpc = check_compiled_module(pathobj, st.st_mtime, cpathobj); } else { if (PyErr_Occurred()) @@ -1370,7 +1366,7 @@ fpc = NULL; } if (fpc) { - co = read_compiled_module(cpathname, fpc); + co = read_compiled_module(cpathobj, fpc); fclose(fpc); if (co == NULL) { Py_XDECREF(cpathobj); From python-checkins at python.org Fri Jul 9 01:32:49 2010 From: python-checkins at python.org (victor.stinner) Date: Fri, 9 Jul 2010 01:32:49 +0200 (CEST) Subject: [Python-checkins] r82690 - python/branches/import_unicode/Python/import.c Message-ID: <20100708233249.9DD0CEEB49@mail.python.org> Author: victor.stinner Date: Fri Jul 9 01:32:49 2010 New Revision: 82690 Log: write_compiled_module() uses an object for the path Modified: python/branches/import_unicode/Python/import.c Modified: python/branches/import_unicode/Python/import.c ============================================================================== --- python/branches/import_unicode/Python/import.c (original) +++ python/branches/import_unicode/Python/import.c Fri Jul 9 01:32:49 2010 @@ -1211,7 +1211,8 @@ remove the file. */ static void -write_compiled_module(PyCodeObject *co, char *cpathname, struct stat *srcstat) +write_compiled_module(PyCodeObject *co, PyObject *cpathobj, + struct stat *srcstat) { FILE *fp; char *dirpath; @@ -1228,6 +1229,14 @@ S_IWUSR | S_IWGRP | S_IWOTH); #endif int saved; + char *cpathname; + + /* FIXME: use PyUnicode_EncodeFSDefault() */ + cpathname = _PyUnicode_AsString(cpathobj); + if (cpathname == NULL) { + PyErr_Clear(); + return; + } /* Ensure that the __pycache__ directory exists. */ dirpath = rightmost_sep(cpathname); @@ -1327,7 +1336,6 @@ { struct stat st; FILE *fpc; - char *cpathname; PyObject *cpathobj; PyCodeObject *co; PyObject *m; @@ -1350,19 +1358,11 @@ } #endif cpathobj = make_compiled_pathname(pathobj, !Py_OptimizeFlag); - if (cpathobj != NULL) { - /* FIXME: don't use _PyUnicode_AsString */ - cpathname = _PyUnicode_AsString(cpathobj); - if (cpathobj == NULL) { - Py_DECREF(cpathobj); - return NULL; - } + if (cpathobj != NULL) fpc = check_compiled_module(pathobj, st.st_mtime, cpathobj); - } else { if (PyErr_Occurred()) return NULL; - cpathname = NULL; fpc = NULL; } if (fpc) { @@ -1390,10 +1390,10 @@ } if (Py_VerboseFlag) PySys_FormatStderr("import %s # from %U\n", name, pathobj); - if (cpathname) { + if (cpathobj != NULL) { PyObject *ro = PySys_GetObject("dont_write_bytecode"); if (ro == NULL || !PyObject_IsTrue(ro)) - write_compiled_module(co, cpathname, &st); + write_compiled_module(co, cpathobj, &st); } m = PyImport_ExecCodeModuleWithUnicodePathnames( name, (PyObject *)co, pathobj, cpathobj); From python-checkins at python.org Fri Jul 9 01:32:51 2010 From: python-checkins at python.org (victor.stinner) Date: Fri, 9 Jul 2010 01:32:51 +0200 (CEST) Subject: [Python-checkins] r82691 - in python/branches/import_unicode: Include/import.h Python/import.c Message-ID: <20100708233251.257D7EEB20@mail.python.org> Author: victor.stinner Date: Fri Jul 9 01:32:50 2010 New Revision: 82691 Log: Remove unused private function _PyImport_FindModule() Modified: python/branches/import_unicode/Include/import.h python/branches/import_unicode/Python/import.c Modified: python/branches/import_unicode/Include/import.h ============================================================================== --- python/branches/import_unicode/Include/import.h (original) +++ python/branches/import_unicode/Include/import.h Fri Jul 9 01:32:50 2010 @@ -46,8 +46,7 @@ #define _PyImport_ReleaseLock() 1 #endif -PyAPI_FUNC(struct filedescr *) _PyImport_FindModule( - const char *, PyObject *, char *, size_t, FILE **, PyObject **); +struct filedescr; PyAPI_FUNC(int) _PyImport_IsScript(struct filedescr *); PyAPI_FUNC(void) _PyImport_ReInitLock(void); Modified: python/branches/import_unicode/Python/import.c ============================================================================== --- python/branches/import_unicode/Python/import.c (original) +++ python/branches/import_unicode/Python/import.c Fri Jul 9 01:32:50 2010 @@ -983,6 +983,7 @@ 3147 style, NULL is returned. buf must be at least as big as pathname; the resulting path will always be shorter. */ +/* FIXME: use Py_UNICODE* instead of char* */ static char * _make_source_pathname(char *pathname, char *buf) { @@ -1914,14 +1915,6 @@ /* Helpers for main.c * Find the source file corresponding to a named module */ -struct filedescr * -_PyImport_FindModule(const char *name, PyObject *path, char *buf, - size_t buflen, FILE **p_fp, PyObject **p_loader) -{ - return find_module((char *) name, (char *) name, path, - buf, buflen, p_fp, p_loader); -} - PyAPI_FUNC(int) _PyImport_IsScript(struct filedescr * fd) { return fd->type == PY_SOURCE || fd->type == PY_COMPILED; From python-checkins at python.org Fri Jul 9 01:32:52 2010 From: python-checkins at python.org (victor.stinner) Date: Fri, 9 Jul 2010 01:32:52 +0200 (CEST) Subject: [Python-checkins] r82692 - python/branches/import_unicode/Python/import.c Message-ID: <20100708233252.9737DEEB83@mail.python.org> Author: victor.stinner Date: Fri Jul 9 01:32:52 2010 New Revision: 82692 Log: change find_module() API: path is stored as an object fix also refleaks in functions calling find_module() Modified: python/branches/import_unicode/Python/import.c Modified: python/branches/import_unicode/Python/import.c ============================================================================== --- python/branches/import_unicode/Python/import.c (original) +++ python/branches/import_unicode/Python/import.c Fri Jul 9 01:32:52 2010 @@ -1466,7 +1466,7 @@ /* Forward */ static PyObject *load_module(char *, FILE *, PyObject *, int, PyObject *); static struct filedescr *find_module(char *, char *, PyObject *, - char *, size_t, FILE **, PyObject **); + PyObject **, FILE **, PyObject **); static struct _frozen * find_frozen(char *); /* Load a package and return its module object WITH INCREMENTED @@ -1479,7 +1479,6 @@ PyObject *file = NULL; PyObject *path = NULL; int err; - char buf[MAXPATHLEN+1]; FILE *fp = NULL; struct filedescr *fdp; PyObject *bufobj; @@ -1501,8 +1500,7 @@ err = PyDict_SetItemString(d, "__path__", path); if (err != 0) goto error; - buf[0] = '\0'; - fdp = find_module(name, "__init__", path, buf, sizeof(buf), &fp, NULL); + fdp = find_module(name, "__init__", path, &bufobj, &fp, NULL); if (fdp == NULL) { if (PyErr_ExceptionMatches(PyExc_ImportError)) { PyErr_Clear(); @@ -1512,11 +1510,7 @@ m = NULL; goto cleanup; } - bufobj = PyUnicode_DecodeFSDefault(buf); - if (bufobj != NULL) - m = load_module(name, fp, bufobj, fdp->type, NULL); - else - m = NULL; + m = load_module(name, fp, bufobj, fdp->type, NULL); if (fp != NULL) fclose(fp); goto cleanup; @@ -1640,7 +1634,7 @@ static struct filedescr importhookdescr = {"", "", IMP_HOOK}; static struct filedescr * -find_module(char *fullname, char *subname, PyObject *path, char *buf, +_find_module(char *fullname, char *subname, PyObject *path, char *buf, size_t buflen, FILE **p_fp, PyObject **p_loader) { Py_ssize_t i, npath; @@ -1912,6 +1906,28 @@ return fdp; } +static struct filedescr * +find_module(char *fullname, char *subname, PyObject *path, PyObject **result, + FILE **p_fp, PyObject **p_loader) +{ + char buf[MAXPATHLEN+1]; + struct filedescr *fd; + buf[0] = '\0'; + fd = _find_module(fullname, subname, path, + buf, sizeof(buf), + p_fp, p_loader); + if (fd != NULL) { + *result = PyUnicode_DecodeFSDefault(buf); + if (*result == NULL) { + if (*p_fp != NULL) + fclose(*p_fp); + return NULL; + } + } else + *result = NULL; + return fd; +} + /* Helpers for main.c * Find the source file corresponding to a named module */ @@ -2974,7 +2990,6 @@ } else { PyObject *path, *loader = NULL; - char buf[MAXPATHLEN+1]; struct filedescr *fdp; FILE *fp = NULL; @@ -2989,8 +3004,7 @@ } } - buf[0] = '\0'; - fdp = find_module(fullname, subname, path, buf, MAXPATHLEN+1, + fdp = find_module(fullname, subname, path, &pathobj, &fp, &loader); Py_XDECREF(path); if (fdp == NULL) { @@ -3000,11 +3014,8 @@ Py_INCREF(Py_None); return Py_None; } - pathobj = PyUnicode_DecodeFSDefault(buf); - if (pathobj != NULL) - m = load_module(fullname, fp, pathobj, fdp->type, loader); - else - m = NULL; + m = load_module(fullname, fp, pathobj, fdp->type, loader); + Py_DECREF(pathobj); Py_XDECREF(loader); if (fp) fclose(fp); @@ -3029,7 +3040,6 @@ PyObject *modules = PyImport_GetModuleDict(); PyObject *path = NULL, *loader = NULL, *existing_m = NULL; char *name, *subname; - char buf[MAXPATHLEN+1]; struct filedescr *fdp; FILE *fp = NULL; PyObject *pathobj; @@ -3090,8 +3100,7 @@ if (path == NULL) PyErr_Clear(); } - buf[0] = '\0'; - fdp = find_module(name, subname, path, buf, MAXPATHLEN+1, &fp, &loader); + fdp = find_module(name, subname, path, &pathobj, &fp, &loader); Py_XDECREF(path); if (fdp == NULL) { @@ -3100,11 +3109,8 @@ return NULL; } - pathobj = PyUnicode_DecodeFSDefault(buf); - if (pathobj != NULL) - newm = load_module(name, fp, pathobj, fdp->type, loader); - else - newm = NULL; + newm = load_module(name, fp, pathobj, fdp->type, loader); + Py_DECREF(pathobj); Py_XDECREF(loader); if (fp) @@ -3261,21 +3267,16 @@ PyObject *fob, *ret; PyObject *pathobj; struct filedescr *fdp; - char pathname[MAXPATHLEN+1]; FILE *fp = NULL; int fd = -1; char *found_encoding = NULL; char *encoding = NULL; - pathname[0] = '\0'; if (path == Py_None) path = NULL; - fdp = find_module(NULL, name, path, pathname, MAXPATHLEN+1, &fp, NULL); + fdp = find_module(NULL, name, path, &pathobj, &fp, NULL); if (fdp == NULL) return NULL; - pathobj = PyUnicode_DecodeFSDefault(pathname); - if (pathobj == NULL) - return NULL; if (fp != NULL) { fd = fileno(fp); if (fd != -1) @@ -3289,8 +3290,10 @@ memory. */ found_encoding = PyTokenizer_FindEncoding(fd); lseek(fd, 0, 0); /* Reset position */ - if (found_encoding == NULL && PyErr_Occurred()) + if (found_encoding == NULL && PyErr_Occurred()) { + Py_DECREF(pathobj); return NULL; + } encoding = (found_encoding != NULL) ? found_encoding : (char*)PyUnicode_GetDefaultEncoding(); } @@ -3298,6 +3301,7 @@ encoding, NULL, NULL, 1); if (fob == NULL) { close(fd); + Py_DECREF(pathobj); PyMem_FREE(found_encoding); return NULL; } From python-checkins at python.org Fri Jul 9 01:32:54 2010 From: python-checkins at python.org (victor.stinner) Date: Fri, 9 Jul 2010 01:32:54 +0200 (CEST) Subject: [Python-checkins] r82693 - in python/branches/import_unicode: Include/warnings.h Objects/moduleobject.c Objects/typeobject.c Objects/unicodeobject.c Python/_warnings.c Python/import.c Message-ID: <20100708233254.65116EEB20@mail.python.org> Author: victor.stinner Date: Fri Jul 9 01:32:54 2010 New Revision: 82693 Log: Create PyErr_WarnUnicode() and PyErr_WarnFormat() Modified: python/branches/import_unicode/Include/warnings.h python/branches/import_unicode/Objects/moduleobject.c python/branches/import_unicode/Objects/typeobject.c python/branches/import_unicode/Objects/unicodeobject.c python/branches/import_unicode/Python/_warnings.c python/branches/import_unicode/Python/import.c Modified: python/branches/import_unicode/Include/warnings.h ============================================================================== --- python/branches/import_unicode/Include/warnings.h (original) +++ python/branches/import_unicode/Include/warnings.h Fri Jul 9 01:32:54 2010 @@ -7,6 +7,8 @@ PyAPI_FUNC(PyObject*) _PyWarnings_Init(void); PyAPI_FUNC(int) PyErr_WarnEx(PyObject *, const char *, Py_ssize_t); +PyAPI_FUNC(int) PyErr_WarnUnicode(PyObject *, PyObject *, Py_ssize_t); +PyAPI_FUNC(int) PyErr_WarnFormat(PyObject *, Py_ssize_t, const char *, ...); PyAPI_FUNC(int) PyErr_WarnExplicit(PyObject *, const char *, const char *, int, const char *, PyObject *); Modified: python/branches/import_unicode/Objects/moduleobject.c ============================================================================== --- python/branches/import_unicode/Objects/moduleobject.c (original) +++ python/branches/import_unicode/Objects/moduleobject.c Fri Jul 9 01:32:54 2010 @@ -56,10 +56,6 @@ return NULL; } -static char api_version_warning[] = -"Python C API version mismatch for module %.100s:\ - This Python has API version %d, module %.100s has version %d."; - PyObject * PyModule_Create2(struct PyModuleDef* module, int module_api_version) { @@ -79,12 +75,13 @@ } name = module->m_name; if (module_api_version != PYTHON_API_VERSION) { - char message[512]; - PyOS_snprintf(message, sizeof(message), - api_version_warning, name, - PYTHON_API_VERSION, name, - module_api_version); - if (PyErr_WarnEx(PyExc_RuntimeWarning, message, 1)) + int err; + err = PyErr_WarnFormat(PyExc_RuntimeWarning, 1, + "Python C API version mismatch for module %.100s: " + "This Python has API version %d, module %.100s has version %d.", + name, + PYTHON_API_VERSION, name, module_api_version); + if (err) return NULL; } /* Make sure name is fully qualified. Modified: python/branches/import_unicode/Objects/typeobject.c ============================================================================== --- python/branches/import_unicode/Objects/typeobject.c (original) +++ python/branches/import_unicode/Objects/typeobject.c Fri Jul 9 01:32:54 2010 @@ -3892,13 +3892,11 @@ tp_reserved) but not tp_richcompare. */ if (type->tp_reserved && !type->tp_richcompare) { int error; - char msg[240]; - PyOS_snprintf(msg, sizeof(msg), - "Type %.100s defines tp_reserved (formerly " - "tp_compare) but not tp_richcompare. " - "Comparisons may not behave as intended.", - type->tp_name); - error = PyErr_WarnEx(PyExc_DeprecationWarning, msg, 1); + error = PyErr_WarnFormat(PyExc_DeprecationWarning, 1, + "Type %.100s defines tp_reserved (formerly " + "tp_compare) but not tp_richcompare. " + "Comparisons may not behave as intended.", + type->tp_name); if (error == -1) goto error; } Modified: python/branches/import_unicode/Objects/unicodeobject.c ============================================================================== --- python/branches/import_unicode/Objects/unicodeobject.c (original) +++ python/branches/import_unicode/Objects/unicodeobject.c Fri Jul 9 01:32:54 2010 @@ -1558,12 +1558,13 @@ /* If the codec returns a buffer, raise a warning and convert to bytes */ if (PyByteArray_Check(v)) { - char msg[100]; + int error; PyObject *b; - PyOS_snprintf(msg, sizeof(msg), - "encoder %s returned buffer instead of bytes", - encoding); - if (PyErr_WarnEx(PyExc_RuntimeWarning, msg, 1) < 0) { + + error = PyErr_WarnFormat(PyExc_RuntimeWarning, 1, + "encoder %s returned buffer instead of bytes", + encoding); + if (error) { Py_DECREF(v); return NULL; } Modified: python/branches/import_unicode/Python/_warnings.c ============================================================================== --- python/branches/import_unicode/Python/_warnings.c (original) +++ python/branches/import_unicode/Python/_warnings.c Fri Jul 9 01:32:54 2010 @@ -710,21 +710,18 @@ registry, NULL); } - /* Function to issue a warning message; may raise an exception. */ + int -PyErr_WarnEx(PyObject *category, const char *text, Py_ssize_t stack_level) +PyErr_WarnUnicode(PyObject *category, PyObject *message, + Py_ssize_t stack_level) { PyObject *res; - PyObject *message = PyUnicode_FromString(text); - if (message == NULL) - return -1; if (category == NULL) category = PyExc_RuntimeWarning; res = do_warn(message, category, stack_level); - Py_DECREF(message); if (res == NULL) return -1; Py_DECREF(res); @@ -732,6 +729,42 @@ return 0; } +int +PyErr_WarnFormat(PyObject *category, Py_ssize_t stack_level, + const char *format, ...) +{ + int ret; + PyObject *unicode; + va_list vargs; + +#ifdef HAVE_STDARG_PROTOTYPES + va_start(vargs, format); +#else + va_start(vargs); +#endif + unicode = PyUnicode_FromFormatV(format, vargs); + if (unicode != NULL) { + ret = PyErr_WarnUnicode(category, unicode, stack_level); + Py_DECREF(unicode); + } + else + ret = -1; + va_end(vargs); + return ret; +} + +int +PyErr_WarnEx(PyObject *category, const char *text, Py_ssize_t stack_level) +{ + int ret; + PyObject *message = PyUnicode_FromString(text); + if (message == NULL) + return -1; + ret = PyErr_WarnUnicode(category, message, stack_level); + Py_DECREF(message); + return ret; +} + /* PyErr_Warn is only for backwards compatability and will be removed. Use PyErr_WarnEx instead. */ Modified: python/branches/import_unicode/Python/import.c ============================================================================== --- python/branches/import_unicode/Python/import.c (original) +++ python/branches/import_unicode/Python/import.c Fri Jul 9 01:32:54 2010 @@ -2756,19 +2756,16 @@ parent = PyDict_GetItemString(modules, buf); if (parent == NULL) { if (orig_level < 1) { - PyObject *err_msg = PyBytes_FromFormat( + int err; + err = PyErr_WarnFormat(PyExc_RuntimeWarning, 1, "Parent module '%.200s' not found " - "while handling absolute import", buf); - if (err_msg == NULL) { - return NULL; - } - if (!PyErr_WarnEx(PyExc_RuntimeWarning, - PyBytes_AsString(err_msg), 1)) { + "while handling absolute import", + buf); + if (!err) { *buf = '\0'; *p_buflen = 0; parent = Py_None; } - Py_DECREF(err_msg); } else { PyErr_Format(PyExc_SystemError, "Parent module '%.200s' not loaded, " From python-checkins at python.org Fri Jul 9 01:32:55 2010 From: python-checkins at python.org (victor.stinner) Date: Fri, 9 Jul 2010 01:32:55 +0200 (CEST) Subject: [Python-checkins] r82694 - python/branches/import_unicode/Python/import.c Message-ID: <20100708233255.E651CEEB39@mail.python.org> Author: victor.stinner Date: Fri Jul 9 01:32:55 2010 New Revision: 82694 Log: use PyErr_WarnFormat() Modified: python/branches/import_unicode/Python/import.c Modified: python/branches/import_unicode/Python/import.c ============================================================================== --- python/branches/import_unicode/Python/import.c (original) +++ python/branches/import_unicode/Python/import.c Fri Jul 9 01:32:55 2010 @@ -1819,14 +1819,12 @@ return &fd_package; } else { - char warnstr[MAXPATHLEN+80]; - sprintf(warnstr, "Not importing directory " - "'%.*s': missing __init__.py", - MAXPATHLEN, buf); - if (PyErr_WarnEx(PyExc_ImportWarning, - warnstr, 1)) { + int warnerr; + warnerr = PyErr_WarnFormat(PyExc_ImportWarning, 1, + "Not importing directory '%s': missing __init__.py", + buf); + if (warnerr) return NULL; - } } } #endif @@ -1866,7 +1864,7 @@ #endif /* PYOS_OS2 */ strcpy(buf+len, fdp->suffix); if (Py_VerboseFlag > 1) - PySys_WriteStderr("# trying %s\n", buf); + PySys_FormatStderr("# trying %s\n", buf); filemode = fdp->mode; if (filemode[0] == 'U') filemode = "r" PY_STDIOTEXTMODE; From python-checkins at python.org Fri Jul 9 01:32:57 2010 From: python-checkins at python.org (victor.stinner) Date: Fri, 9 Jul 2010 01:32:57 +0200 (CEST) Subject: [Python-checkins] r82695 - in python/branches/import_unicode: Doc/library/sys.rst Python/import.c Message-ID: <20100708233257.8D264EEB39@mail.python.org> Author: victor.stinner Date: Fri Jul 9 01:32:57 2010 New Revision: 82695 Log: _find_module() fills directly path argument * find_module(): rename "path" argument to "search_path" * find_module(): result can be NULL * reject bytes path * fix refleak Modified: python/branches/import_unicode/Doc/library/sys.rst python/branches/import_unicode/Python/import.c Modified: python/branches/import_unicode/Doc/library/sys.rst ============================================================================== --- python/branches/import_unicode/Doc/library/sys.rst (original) +++ python/branches/import_unicode/Doc/library/sys.rst Fri Jul 9 01:32:57 2010 @@ -599,9 +599,9 @@ .. index:: triple: module; search; path - A list of strings that specifies the search path for modules. Initialized from - the environment variable :envvar:`PYTHONPATH`, plus an installation-dependent - default. + A list of unicode strings that specifies the search path for modules. + Initialized from the environment variable :envvar:`PYTHONPATH`, plus an + installation-dependent default. As initialized upon program startup, the first item of this list, ``path[0]``, is the directory containing the script that was used to invoke the Python Modified: python/branches/import_unicode/Python/import.c ============================================================================== --- python/branches/import_unicode/Python/import.c (original) +++ python/branches/import_unicode/Python/import.c Fri Jul 9 01:32:57 2010 @@ -1477,7 +1477,7 @@ { PyObject *m, *d; PyObject *file = NULL; - PyObject *path = NULL; + PyObject *search_path = NULL; int err; FILE *fp = NULL; struct filedescr *fdp; @@ -1492,15 +1492,15 @@ file = get_sourcefile(pathobj); if (file == NULL) goto error; - path = Py_BuildValue("[O]", file); - if (path == NULL) + search_path = Py_BuildValue("[O]", file); + if (search_path == NULL) goto error; err = PyDict_SetItemString(d, "__file__", file); if (err == 0) - err = PyDict_SetItemString(d, "__path__", path); + err = PyDict_SetItemString(d, "__path__", search_path); if (err != 0) goto error; - fdp = find_module(name, "__init__", path, &bufobj, &fp, NULL); + fdp = find_module(name, "__init__", search_path, &bufobj, &fp, NULL); if (fdp == NULL) { if (PyErr_ExceptionMatches(PyExc_ImportError)) { PyErr_Clear(); @@ -1511,6 +1511,7 @@ goto cleanup; } m = load_module(name, fp, bufobj, fdp->type, NULL); + Py_XDECREF(bufobj); if (fp != NULL) fclose(fp); goto cleanup; @@ -1518,7 +1519,7 @@ error: m = NULL; cleanup: - Py_XDECREF(path); + Py_XDECREF(search_path); Py_XDECREF(file); return m; } @@ -1634,8 +1635,9 @@ static struct filedescr importhookdescr = {"", "", IMP_HOOK}; static struct filedescr * -_find_module(char *fullname, char *subname, PyObject *path, char *buf, - size_t buflen, FILE **p_fp, PyObject **p_loader) +_find_module(char *fullname, char *subname, PyObject *search_path, + char *buf, size_t buflen, PyObject **path, + FILE **p_fp, PyObject **p_loader) { Py_ssize_t i, npath; size_t len, namelen; @@ -1653,6 +1655,8 @@ size_t saved_namelen; char *saved_buf = NULL; #endif + + *path = NULL; if (p_loader != NULL) *p_loader = NULL; @@ -1681,8 +1685,8 @@ PyObject *hook = PyList_GetItem(meta_path, i); loader = PyObject_CallMethod(hook, "find_module", "sO", fullname, - path != NULL ? - path : Py_None); + search_path != NULL ? + search_path : Py_None); if (loader == NULL) { Py_DECREF(meta_path); return NULL; /* true error */ @@ -1699,26 +1703,35 @@ } if (find_frozen(fullname) != NULL) { - strcpy(buf, fullname); + *path = PyUnicode_DecodeFSDefault(fullname); + if (*path == NULL) + return NULL; return &fd_frozen; } - if (path == NULL) { + if (search_path == NULL) { if (is_builtin(name)) { - strcpy(buf, name); + *path = PyUnicode_DecodeFSDefault(name); + if (*path == NULL) + return NULL; return &fd_builtin; } #ifdef MS_COREDLL fp = PyWin_FindRegisteredModule(name, &fdp, buf, buflen); if (fp != NULL) { + *path = PyUnicode_DecodeFSDefault(buf); + if (*path == NULL) { + fclose(fp); + return NULL; + } *p_fp = fp; return fdp; } #endif - path = PySys_GetObject("path"); + search_path = PySys_GetObject("path"); } - if (path == NULL || !PyList_Check(path)) { + if (search_path == NULL || !PyList_Check(search_path)) { PyErr_SetString(PyExc_ImportError, "sys.path must be a list of directory names"); return NULL; @@ -1739,10 +1752,10 @@ return NULL; } - npath = PyList_Size(path); + npath = PyList_Size(search_path); namelen = strlen(name); for (i = 0; i < npath; i++) { - PyObject *v = PyList_GetItem(path, i); + PyObject *v = PyList_GetItem(search_path, i); PyObject *origv = v; const char *base; Py_ssize_t size; @@ -1753,10 +1766,8 @@ if (v == NULL) return NULL; } - else if (!PyBytes_Check(v)) - continue; else - Py_INCREF(v); + continue; base = PyBytes_AS_STRING(v); size = PyBytes_GET_SIZE(v); @@ -1816,6 +1827,9 @@ S_ISDIR(statbuf.st_mode) && /* it's a directory */ case_ok(buf, len, namelen, name)) { /* case matches */ if (find_init_module(buf)) { /* and has __init__.py */ + *path = PyUnicode_DecodeFSDefault(buf); + if (*path == NULL) + return NULL; return &fd_package; } else { @@ -1900,29 +1914,25 @@ "No module named %.200s", name); return NULL; } + *path = PyUnicode_DecodeFSDefault(buf); + if (*path == NULL) { + fclose(fp); + return NULL; + } *p_fp = fp; return fdp; } static struct filedescr * -find_module(char *fullname, char *subname, PyObject *path, PyObject **result, +find_module(char *fullname, char *subname, PyObject *search_path, PyObject **path, FILE **p_fp, PyObject **p_loader) { char buf[MAXPATHLEN+1]; struct filedescr *fd; buf[0] = '\0'; - fd = _find_module(fullname, subname, path, - buf, sizeof(buf), + fd = _find_module(fullname, subname, search_path, + buf, sizeof(buf), path, p_fp, p_loader); - if (fd != NULL) { - *result = PyUnicode_DecodeFSDefault(buf); - if (*result == NULL) { - if (*p_fp != NULL) - fclose(*p_fp); - return NULL; - } - } else - *result = NULL; return fd; } @@ -2206,6 +2216,11 @@ } } + if (pathobj == NULL && type != IMP_HOOK) { + PyErr_BadInternalCall(); + return NULL; + } + switch (type) { case PY_SOURCE: @@ -2235,7 +2250,7 @@ if (loader == NULL) { PyErr_SetString(PyExc_ImportError, "import hook without loader"); - Py_DECREF(pathobj); + Py_XDECREF(pathobj); return NULL; } m = PyObject_CallMethod(loader, "load_module", "s", name); @@ -2984,24 +2999,24 @@ Py_INCREF(m); } else { - PyObject *path, *loader = NULL; + PyObject *search_path, *loader = NULL; struct filedescr *fdp; FILE *fp = NULL; if (mod == Py_None) - path = NULL; + search_path = NULL; else { - path = PyObject_GetAttrString(mod, "__path__"); - if (path == NULL) { + search_path = PyObject_GetAttrString(mod, "__path__"); + if (search_path == NULL) { PyErr_Clear(); Py_INCREF(Py_None); return Py_None; } } - fdp = find_module(fullname, subname, path, &pathobj, + fdp = find_module(fullname, subname, search_path, &pathobj, &fp, &loader); - Py_XDECREF(path); + Py_XDECREF(search_path); if (fdp == NULL) { if (!PyErr_ExceptionMatches(PyExc_ImportError)) return NULL; @@ -3010,7 +3025,7 @@ return Py_None; } m = load_module(fullname, fp, pathobj, fdp->type, loader); - Py_DECREF(pathobj); + Py_XDECREF(pathobj); Py_XDECREF(loader); if (fp) fclose(fp); @@ -3033,7 +3048,7 @@ PyInterpreterState *interp = PyThreadState_Get()->interp; PyObject *modules_reloading = interp->modules_reloading; PyObject *modules = PyImport_GetModuleDict(); - PyObject *path = NULL, *loader = NULL, *existing_m = NULL; + PyObject *search_path = NULL, *loader = NULL, *existing_m = NULL; char *name, *subname; struct filedescr *fdp; FILE *fp = NULL; @@ -3091,12 +3106,12 @@ } Py_DECREF(parentname); subname++; - path = PyObject_GetAttrString(parent, "__path__"); - if (path == NULL) + search_path = PyObject_GetAttrString(parent, "__path__"); + if (search_path == NULL) PyErr_Clear(); } - fdp = find_module(name, subname, path, &pathobj, &fp, &loader); - Py_XDECREF(path); + fdp = find_module(name, subname, search_path, &pathobj, &fp, &loader); + Py_XDECREF(search_path); if (fdp == NULL) { Py_XDECREF(loader); @@ -3105,7 +3120,7 @@ } newm = load_module(name, fp, pathobj, fdp->type, loader); - Py_DECREF(pathobj); + Py_XDECREF(pathobj); Py_XDECREF(loader); if (fp) @@ -3256,7 +3271,7 @@ } static PyObject * -call_find_module(char *name, PyObject *path) +call_find_module(char *name, PyObject *search_path) { extern int fclose(FILE *); PyObject *fob, *ret; @@ -3267,9 +3282,9 @@ char *found_encoding = NULL; char *encoding = NULL; - if (path == Py_None) - path = NULL; - fdp = find_module(NULL, name, path, &pathobj, &fp, NULL); + if (search_path == Py_None) + search_path = NULL; + fdp = find_module(NULL, name, search_path, &pathobj, &fp, NULL); if (fdp == NULL) return NULL; if (fp != NULL) { @@ -3286,7 +3301,7 @@ found_encoding = PyTokenizer_FindEncoding(fd); lseek(fd, 0, 0); /* Reset position */ if (found_encoding == NULL && PyErr_Occurred()) { - Py_DECREF(pathobj); + Py_XDECREF(pathobj); return NULL; } encoding = (found_encoding != NULL) ? found_encoding : @@ -3296,7 +3311,7 @@ encoding, NULL, NULL, 1); if (fob == NULL) { close(fd); - Py_DECREF(pathobj); + Py_XDECREF(pathobj); PyMem_FREE(found_encoding); return NULL; } @@ -3306,7 +3321,7 @@ Py_INCREF(fob); } ret = Py_BuildValue("NN(ssi)", - fob, pathobj, + fob, (pathobj != NULL) ? pathobj : Py_None, fdp->suffix, fdp->mode, fdp->type); PyMem_FREE(found_encoding); From python-checkins at python.org Fri Jul 9 01:32:59 2010 From: python-checkins at python.org (victor.stinner) Date: Fri, 9 Jul 2010 01:32:59 +0200 (CEST) Subject: [Python-checkins] r82696 - python/branches/import_unicode/Python/import.c Message-ID: <20100708233259.029EBEEBCA@mail.python.org> Author: victor.stinner Date: Fri Jul 9 01:32:58 2010 New Revision: 82696 Log: PyWin_FindRegisteredModule() uses its own buffer Modified: python/branches/import_unicode/Python/import.c Modified: python/branches/import_unicode/Python/import.c ============================================================================== --- python/branches/import_unicode/Python/import.c (original) +++ python/branches/import_unicode/Python/import.c Fri Jul 9 01:32:58 2010 @@ -1710,6 +1710,10 @@ } if (search_path == NULL) { +#ifdef MS_COREDLL + /* FIXME: use buf buffer */ + char bbuf[MAXPATHLEN+1]; +#endif if (is_builtin(name)) { *path = PyUnicode_DecodeFSDefault(name); if (*path == NULL) @@ -1717,9 +1721,9 @@ return &fd_builtin; } #ifdef MS_COREDLL - fp = PyWin_FindRegisteredModule(name, &fdp, buf, buflen); + fp = PyWin_FindRegisteredModule(name, &fdp, bbuf, sizeof(bbuf)); if (fp != NULL) { - *path = PyUnicode_DecodeFSDefault(buf); + *path = PyUnicode_DecodeFSDefault(bbuf); if (*path == NULL) { fclose(fp); return NULL; From python-checkins at python.org Fri Jul 9 01:33:00 2010 From: python-checkins at python.org (victor.stinner) Date: Fri, 9 Jul 2010 01:33:00 +0200 (CEST) Subject: [Python-checkins] r82697 - python/branches/import_unicode/Python/import.c Message-ID: <20100708233300.6A8F2EEB39@mail.python.org> Author: victor.stinner Date: Fri Jul 9 01:33:00 2010 New Revision: 82697 Log: create unicode object Modified: python/branches/import_unicode/Python/import.c Modified: python/branches/import_unicode/Python/import.c ============================================================================== --- python/branches/import_unicode/Python/import.c (original) +++ python/branches/import_unicode/Python/import.c Fri Jul 9 01:33:00 2010 @@ -1655,6 +1655,7 @@ size_t saved_namelen; char *saved_buf = NULL; #endif + PyObject *unicode; *path = NULL; if (p_loader != NULL) @@ -1827,24 +1828,28 @@ /* Check for package import (buf holds a directory name, and there's an __init__ module in that directory */ #ifdef HAVE_STAT + unicode = PyUnicode_DecodeFSDefault(buf); + if (unicode == NULL) + return NULL; if (stat(buf, &statbuf) == 0 && /* it exists */ S_ISDIR(statbuf.st_mode) && /* it's a directory */ case_ok(buf, len, namelen, name)) { /* case matches */ if (find_init_module(buf)) { /* and has __init__.py */ - *path = PyUnicode_DecodeFSDefault(buf); - if (*path == NULL) - return NULL; + *path = unicode; return &fd_package; } else { int warnerr; warnerr = PyErr_WarnFormat(PyExc_ImportWarning, 1, - "Not importing directory '%s': missing __init__.py", - buf); - if (warnerr) + "Not importing directory '%U': missing __init__.py", + unicode); + if (warnerr) { + Py_DECREF(unicode); return NULL; + } } } + Py_DECREF(unicode); #endif #if defined(PYOS_OS2) /* take a snapshot of the module spec for restoration From python-checkins at python.org Fri Jul 9 01:33:01 2010 From: python-checkins at python.org (victor.stinner) Date: Fri, 9 Jul 2010 01:33:01 +0200 (CEST) Subject: [Python-checkins] r82698 - python/branches/import_unicode/Python/import.c Message-ID: <20100708233301.E44C7EEB62@mail.python.org> Author: victor.stinner Date: Fri Jul 9 01:33:01 2010 New Revision: 82698 Log: create stat_unicode() NullImporter does now support unicode path Modified: python/branches/import_unicode/Python/import.c Modified: python/branches/import_unicode/Python/import.c ============================================================================== --- python/branches/import_unicode/Python/import.c (original) +++ python/branches/import_unicode/Python/import.c Fri Jul 9 01:33:01 2010 @@ -1632,6 +1632,7 @@ static int case_ok(char *, Py_ssize_t, Py_ssize_t, char *); static int find_init_module(char *); /* Forward */ +static int stat_unicode(PyObject *unicode, struct stat *statbuf); static struct filedescr importhookdescr = {"", "", IMP_HOOK}; static struct filedescr * @@ -1831,7 +1832,7 @@ unicode = PyUnicode_DecodeFSDefault(buf); if (unicode == NULL) return NULL; - if (stat(buf, &statbuf) == 0 && /* it exists */ + if (stat_unicode(unicode, &statbuf) == 0 && /* it exists */ S_ISDIR(statbuf.st_mode) && /* it's a directory */ case_ok(buf, len, namelen, name)) { /* case matches */ if (find_init_module(buf)) { /* and has __init__.py */ @@ -2109,6 +2110,15 @@ #ifdef HAVE_STAT +static int +stat_unicode(PyObject *unicode, struct stat *statbuf) +{ + char *pathstr = _PyUnicode_AsString(unicode); + if (pathstr == NULL) + return 1; + return stat(pathstr, statbuf); +} + /* Helper to look for __init__.py or __init__.py[co] in potential package */ static int find_init_module(char *buf) @@ -3774,19 +3784,16 @@ static int NullImporter_init(NullImporter *self, PyObject *args, PyObject *kwds) { - char *path; - Py_ssize_t pathlen; + PyObject *pathobj; if (!_PyArg_NoKeywords("NullImporter()", kwds)) return -1; - if (!PyArg_ParseTuple(args, "es:NullImporter", - Py_FileSystemDefaultEncoding, &path)) + if (!PyArg_ParseTuple(args, "U:NullImporter", + &pathobj)) return -1; - pathlen = strlen(path); - if (pathlen == 0) { - PyMem_Free(path); + if (PyUnicode_GET_SIZE(pathobj) == 0) { PyErr_SetString(PyExc_ImportError, "empty pathname"); return -1; } else { @@ -3794,8 +3801,7 @@ struct stat statbuf; int rv; - rv = stat(path, &statbuf); - PyMem_Free(path); + rv = stat_unicode(pathobj, &statbuf); if (rv == 0) { /* it exists */ if (S_ISDIR(statbuf.st_mode)) { @@ -3807,12 +3813,14 @@ } #else /* MS_WINDOWS */ DWORD rv; + char *path; + /* FIXME: use PyUnicode_AsWideChar() and GetFileAttributesW() */ + path = _PyUnicode_AsString(pathobj); /* see issue1293 and issue3677: * stat() on Windows doesn't recognise paths like * "e:\\shared\\" and "\\\\whiterab-c2znlh\\shared" as dirs. */ rv = GetFileAttributesA(path); - PyMem_Free(path); if (rv != INVALID_FILE_ATTRIBUTES) { /* it exists */ if (rv & FILE_ATTRIBUTE_DIRECTORY) { From python-checkins at python.org Fri Jul 9 01:33:03 2010 From: python-checkins at python.org (victor.stinner) Date: Fri, 9 Jul 2010 01:33:03 +0200 (CEST) Subject: [Python-checkins] r82699 - python/branches/import_unicode/Python/import.c Message-ID: <20100708233303.65C70D6C1@mail.python.org> Author: victor.stinner Date: Fri Jul 9 01:33:03 2010 New Revision: 82699 Log: create fopen_unicode() Modified: python/branches/import_unicode/Python/import.c Modified: python/branches/import_unicode/Python/import.c ============================================================================== --- python/branches/import_unicode/Python/import.c (original) +++ python/branches/import_unicode/Python/import.c Fri Jul 9 01:33:03 2010 @@ -136,6 +136,13 @@ {0, 0} }; +/* Forward */ +static FILE* fopen_unicode(PyObject *unicode, const char *mode); +#ifdef HAVE_STAT +static int stat_unicode(PyObject *unicode, struct stat *statbuf); +static int find_init_module(char *); +#endif + /* Initialize things */ @@ -1061,14 +1068,8 @@ FILE *fp; long magic; long pyc_mtime; - char *cpathname; - - /* FIXME: use PyUnicode_EncodeFSDefault() */ - cpathname = _PyUnicode_AsString(cpathobj); - if (cpathname == NULL) - return NULL; - fp = fopen(cpathname, "rb"); + fp = fopen_unicode(cpathobj, "rb"); if (fp == NULL) return NULL; magic = PyMarshal_ReadLongFromFile(fp); @@ -1411,7 +1412,6 @@ static PyObject * get_sourcefile(PyObject *fileobj) { - char *py; PyObject *pyobj; Py_UNICODE *file; Py_ssize_t len; @@ -1448,11 +1448,7 @@ return NULL; } - /* FIXME: use PyUnicode_EncodeFSDefault() */ - py = _PyUnicode_AsString(pyobj); - if (py == NULL) - return NULL; - if (stat(py, &statbuf) == 0 && + if (stat_unicode(pyobj, &statbuf) == 0 && S_ISREG(statbuf.st_mode)) { return pyobj; } @@ -1631,8 +1627,6 @@ #endif static int case_ok(char *, Py_ssize_t, Py_ssize_t, char *); -static int find_init_module(char *); /* Forward */ -static int stat_unicode(PyObject *unicode, struct stat *statbuf); static struct filedescr importhookdescr = {"", "", IMP_HOOK}; static struct filedescr * @@ -1887,20 +1881,23 @@ } #endif /* PYOS_OS2 */ strcpy(buf+len, fdp->suffix); + unicode = PyUnicode_DecodeFSDefault(buf); if (Py_VerboseFlag > 1) - PySys_FormatStderr("# trying %s\n", buf); + PySys_FormatStderr("# trying %U\n", unicode); filemode = fdp->mode; if (filemode[0] == 'U') filemode = "r" PY_STDIOTEXTMODE; - fp = fopen(buf, filemode); + fp = fopen_unicode(unicode, filemode); if (fp != NULL) { - if (case_ok(buf, len, namelen, name)) + if (case_ok(buf, len, namelen, name)) { + Py_DECREF(unicode); break; - else { /* continue search */ + } else { /* continue search */ fclose(fp); fp = NULL; } } + Py_DECREF(unicode); #if defined(PYOS_OS2) /* restore the saved snapshot */ strcpy(buf, saved_buf); @@ -2108,11 +2105,22 @@ #endif } +static FILE* +fopen_unicode(PyObject *unicode, const char *mode) +{ + /* FIXME: use PyUnicode_EncodeFSDefault() */ + char *pathstr = _PyUnicode_AsString(unicode); + if (pathstr == NULL) + return NULL; + return fopen(pathstr, mode); +} + #ifdef HAVE_STAT static int stat_unicode(PyObject *unicode, struct stat *statbuf) { + /* FIXME: use PyUnicode_EncodeFSDefault() */ char *pathstr = _PyUnicode_AsString(unicode); if (pathstr == NULL) return 1; @@ -2127,6 +2135,7 @@ size_t i = save_len; char *pname; /* pointer to start of __init__ */ struct stat statbuf; + PyObject *unicode; /* For calling case_ok(buf, len, namelen, name): * /a/b/c/d/e/f/g/h/i/j/k/some_long_module_name.py\0 @@ -2141,26 +2150,32 @@ buf[i++] = SEP; pname = buf + i; strcpy(pname, "__init__.py"); - if (stat(buf, &statbuf) == 0) { + unicode = PyUnicode_DecodeFSDefault(buf); + if (stat_unicode(unicode, &statbuf) == 0) { if (case_ok(buf, save_len + 9, /* len("/__init__") */ 8, /* len("__init__") */ pname)) { buf[save_len] = '\0'; + Py_DECREF(unicode); return 1; } } + Py_DECREF(unicode); i += strlen(pname); strcpy(buf+i, Py_OptimizeFlag ? "o" : "c"); - if (stat(buf, &statbuf) == 0) { + unicode = PyUnicode_DecodeFSDefault(buf); + if (stat_unicode(unicode, &statbuf) == 0) { if (case_ok(buf, save_len + 9, /* len("/__init__") */ 8, /* len("__init__") */ pname)) { buf[save_len] = '\0'; + Py_DECREF(unicode); return 1; } } + Py_DECREF(unicode); buf[save_len] = '\0'; return 0; } @@ -3445,15 +3460,10 @@ get_file(PyObject *pathobj, PyObject *fob, char *mode) { FILE *fp; - char *pathname; if (mode[0] == 'U') mode = "r" PY_STDIOTEXTMODE; if (fob == NULL) { - /* FIXME: don't use _PyUnicode_AsString */ - pathname = _PyUnicode_AsString(pathobj); - if (pathname == NULL) - return NULL; - fp = fopen(pathname, mode); + fp = fopen_unicode(pathobj, mode); } else { int fd = PyObject_AsFileDescriptor(fob); From python-checkins at python.org Fri Jul 9 01:33:04 2010 From: python-checkins at python.org (victor.stinner) Date: Fri, 9 Jul 2010 01:33:04 +0200 (CEST) Subject: [Python-checkins] r82700 - python/branches/import_unicode/Python/import.c Message-ID: <20100708233304.DBF8BEEB20@mail.python.org> Author: victor.stinner Date: Fri Jul 9 01:33:04 2010 New Revision: 82700 Log: find_init_module() uses unicode Modified: python/branches/import_unicode/Python/import.c Modified: python/branches/import_unicode/Python/import.c ============================================================================== --- python/branches/import_unicode/Python/import.c (original) +++ python/branches/import_unicode/Python/import.c Fri Jul 9 01:33:04 2010 @@ -140,7 +140,7 @@ static FILE* fopen_unicode(PyObject *unicode, const char *mode); #ifdef HAVE_STAT static int stat_unicode(PyObject *unicode, struct stat *statbuf); -static int find_init_module(char *); +static int find_init_module(PyObject *); #endif @@ -1829,7 +1829,7 @@ if (stat_unicode(unicode, &statbuf) == 0 && /* it exists */ S_ISDIR(statbuf.st_mode) && /* it's a directory */ case_ok(buf, len, namelen, name)) { /* case matches */ - if (find_init_module(buf)) { /* and has __init__.py */ + if (find_init_module(unicode)) { /* and has __init__.py */ *path = unicode; return &fd_package; } @@ -2129,54 +2129,37 @@ /* Helper to look for __init__.py or __init__.py[co] in potential package */ static int -find_init_module(char *buf) +find_init_module(PyObject *bufobj) { - const size_t save_len = strlen(buf); - size_t i = save_len; - char *pname; /* pointer to start of __init__ */ struct stat statbuf; PyObject *unicode; + char *_buf; -/* For calling case_ok(buf, len, namelen, name): - * /a/b/c/d/e/f/g/h/i/j/k/some_long_module_name.py\0 - * ^ ^ ^ ^ - * |--------------------- buf ---------------------| - * |------------------- len ------------------| - * |------ name -------| - * |----- namelen -----| - */ - if (save_len + 13 >= MAXPATHLEN) - return 0; - buf[i++] = SEP; - pname = buf + i; - strcpy(pname, "__init__.py"); - unicode = PyUnicode_DecodeFSDefault(buf); + unicode = PyUnicode_FromFormat("%U%c__init__.py", bufobj, SEP); if (stat_unicode(unicode, &statbuf) == 0) { - if (case_ok(buf, - save_len + 9, /* len("/__init__") */ - 8, /* len("__init__") */ - pname)) { - buf[save_len] = '\0'; + /* FIXME: don't use _PyUnicode_AsString */ + _buf = _PyUnicode_AsString(unicode); + if (case_ok(_buf, + strlen(_buf) - 3, /* length without .py suffix */ + 8, "__init__")) { Py_DECREF(unicode); return 1; } } Py_DECREF(unicode); - i += strlen(pname); - strcpy(buf+i, Py_OptimizeFlag ? "o" : "c"); - unicode = PyUnicode_DecodeFSDefault(buf); + + unicode = PyUnicode_FromFormat("%U%c__init__.py%c", bufobj, SEP, Py_OptimizeFlag ? "o" : "c"); if (stat_unicode(unicode, &statbuf) == 0) { - if (case_ok(buf, - save_len + 9, /* len("/__init__") */ - 8, /* len("__init__") */ - pname)) { - buf[save_len] = '\0'; + /* FIXME: don't use _PyUnicode_AsString */ + _buf = _PyUnicode_AsString(unicode); + if (case_ok(_buf, + strlen(_buf) - 3, /* length without .pyc/.pyo suffix */ + 8, "__init__")) { Py_DECREF(unicode); return 1; } } Py_DECREF(unicode); - buf[save_len] = '\0'; return 0; } From python-checkins at python.org Fri Jul 9 01:33:06 2010 From: python-checkins at python.org (victor.stinner) Date: Fri, 9 Jul 2010 01:33:06 +0200 (CEST) Subject: [Python-checkins] r82701 - python/branches/import_unicode/Python/import.c Message-ID: <20100708233306.51DB1EEB62@mail.python.org> Author: victor.stinner Date: Fri Jul 9 01:33:06 2010 New Revision: 82701 Log: case_ok() now accepts an object Modified: python/branches/import_unicode/Python/import.c Modified: python/branches/import_unicode/Python/import.c ============================================================================== --- python/branches/import_unicode/Python/import.c (original) +++ python/branches/import_unicode/Python/import.c Fri Jul 9 01:33:06 2010 @@ -1626,7 +1626,7 @@ char *, Py_ssize_t); #endif -static int case_ok(char *, Py_ssize_t, Py_ssize_t, char *); +static int case_ok(PyObject *, Py_ssize_t, Py_ssize_t, char *); static struct filedescr importhookdescr = {"", "", IMP_HOOK}; static struct filedescr * @@ -1828,7 +1828,7 @@ return NULL; if (stat_unicode(unicode, &statbuf) == 0 && /* it exists */ S_ISDIR(statbuf.st_mode) && /* it's a directory */ - case_ok(buf, len, namelen, name)) { /* case matches */ + case_ok(unicode, 0, namelen, name)) { /* case matches */ if (find_init_module(unicode)) { /* and has __init__.py */ *path = unicode; return &fd_package; @@ -1889,7 +1889,7 @@ filemode = "r" PY_STDIOTEXTMODE; fp = fopen_unicode(unicode, filemode); if (fp != NULL) { - if (case_ok(buf, len, namelen, name)) { + if (case_ok(unicode, strlen(fdp->suffix), namelen, name)) { Py_DECREF(unicode); break; } else { /* continue search */ @@ -1996,8 +1996,12 @@ #endif static int -case_ok(char *buf, Py_ssize_t len, Py_ssize_t namelen, char *name) +case_ok(PyObject *bufobj, Py_ssize_t lendelta, Py_ssize_t namelen, char *name) { + /* FIXME: don't use _PyUnicode_AsString */ + char *buf = _PyUnicode_AsString(bufobj); + Py_ssize_t len = strlen(buf) - lendelta; + /* Pick a platform-specific implementation; the sequence of #if's here should * match the sequence just above. */ @@ -2133,14 +2137,11 @@ { struct stat statbuf; PyObject *unicode; - char *_buf; unicode = PyUnicode_FromFormat("%U%c__init__.py", bufobj, SEP); if (stat_unicode(unicode, &statbuf) == 0) { - /* FIXME: don't use _PyUnicode_AsString */ - _buf = _PyUnicode_AsString(unicode); - if (case_ok(_buf, - strlen(_buf) - 3, /* length without .py suffix */ + if (case_ok(unicode, + 3, /* ignore ".py" suffix */ 8, "__init__")) { Py_DECREF(unicode); return 1; @@ -2150,10 +2151,8 @@ unicode = PyUnicode_FromFormat("%U%c__init__.py%c", bufobj, SEP, Py_OptimizeFlag ? "o" : "c"); if (stat_unicode(unicode, &statbuf) == 0) { - /* FIXME: don't use _PyUnicode_AsString */ - _buf = _PyUnicode_AsString(unicode); - if (case_ok(_buf, - strlen(_buf) - 3, /* length without .pyc/.pyo suffix */ + if (case_ok(unicode, + 4, /* ignore ".pyc" / ".pyo" suffix */ 8, "__init__")) { Py_DECREF(unicode); return 1; From python-checkins at python.org Fri Jul 9 01:33:07 2010 From: python-checkins at python.org (victor.stinner) Date: Fri, 9 Jul 2010 01:33:07 +0200 (CEST) Subject: [Python-checkins] r82702 - in python/branches/import_unicode: PC/import_nt.c Python/import.c Message-ID: <20100708233307.C8DCAEEBCF@mail.python.org> Author: victor.stinner Date: Fri Jul 9 01:33:07 2010 New Revision: 82702 Log: Move buffer into PyWin_FindRegisteredModule() The function now returns the path as a PyUnicodeObject* Modified: python/branches/import_unicode/PC/import_nt.c python/branches/import_unicode/Python/import.c Modified: python/branches/import_unicode/PC/import_nt.c ============================================================================== --- python/branches/import_unicode/PC/import_nt.c (original) +++ python/branches/import_unicode/PC/import_nt.c Fri Jul 9 01:33:07 2010 @@ -17,9 +17,11 @@ FILE *PyWin_FindRegisteredModule(const char *moduleName, struct filedescr **ppFileDesc, - char *pathBuf, - Py_ssize_t pathLen) + PyObject **pathobj) { + /* FIXME: use wchar_t* type */ + char pathBuf[MAXPATHLEN+1]; + Py_ssize_t pathLen = sizeof(pathBuf); char *moduleKey; const char keyPrefix[] = "Software\\Python\\PythonCore\\"; const char keySuffix[] = "\\Modules\\"; @@ -45,6 +47,9 @@ sizeof(keySuffix) + strlen(moduleName) + sizeof(debugString) - 1; + + *pathobj = NULL; + /* alloca == no free required, but memory only local to fn, * also no heap fragmentation! */ @@ -80,7 +85,14 @@ if (fdp->suffix == NULL) return NULL; fp = fopen(pathBuf, fdp->mode); - if (fp != NULL) + if (fp == NULL) + return NULL; + *pathobj = PyUnicode_DecodeFSDefault(pathBuf); + if (*pathobj != NULL) *ppFileDesc = fdp; + else { + fclose(fp); + fp = NULL; + } return fp; } Modified: python/branches/import_unicode/Python/import.c ============================================================================== --- python/branches/import_unicode/Python/import.c (original) +++ python/branches/import_unicode/Python/import.c Fri Jul 9 01:33:07 2010 @@ -1623,7 +1623,7 @@ #ifdef MS_COREDLL extern FILE *PyWin_FindRegisteredModule(const char *, struct filedescr **, - char *, Py_ssize_t); + PyObject **); #endif static int case_ok(PyObject *, Py_ssize_t, Py_ssize_t, char *); @@ -1707,8 +1707,7 @@ if (search_path == NULL) { #ifdef MS_COREDLL - /* FIXME: use buf buffer */ - char bbuf[MAXPATHLEN+1]; + PyObject *winpath; #endif if (is_builtin(name)) { *path = PyUnicode_DecodeFSDefault(name); @@ -1717,16 +1716,14 @@ return &fd_builtin; } #ifdef MS_COREDLL - fp = PyWin_FindRegisteredModule(name, &fdp, bbuf, sizeof(bbuf)); + fp = PyWin_FindRegisteredModule(name, &fdp, &winpath); if (fp != NULL) { - *path = PyUnicode_DecodeFSDefault(bbuf); - if (*path == NULL) { - fclose(fp); - return NULL; - } *p_fp = fp; + *path = winpath; return fdp; } + else if (PyErr_Occurred()) + return NULL; #endif search_path = PySys_GetObject("path"); } From python-checkins at python.org Fri Jul 9 01:33:09 2010 From: python-checkins at python.org (victor.stinner) Date: Fri, 9 Jul 2010 01:33:09 +0200 (CEST) Subject: [Python-checkins] r82703 - python/branches/import_unicode/Python/import.c Message-ID: <20100708233309.3E990EEB83@mail.python.org> Author: victor.stinner Date: Fri Jul 9 01:33:09 2010 New Revision: 82703 Log: fix compiler warning (unused variable) Modified: python/branches/import_unicode/Python/import.c Modified: python/branches/import_unicode/Python/import.c ============================================================================== --- python/branches/import_unicode/Python/import.c (original) +++ python/branches/import_unicode/Python/import.c Fri Jul 9 01:33:09 2010 @@ -1995,9 +1995,12 @@ static int case_ok(PyObject *bufobj, Py_ssize_t lendelta, Py_ssize_t namelen, char *name) { +#if defined(MS_WINDOWS) || defined(DJGPP) || (defined(__MACH__) && defined(__APPLE__) \ + || defined(__CYGWIN__)) && defined(HAVE_DIRENT_H) || defined(PYOS_OS2) /* FIXME: don't use _PyUnicode_AsString */ char *buf = _PyUnicode_AsString(bufobj); Py_ssize_t len = strlen(buf) - lendelta; +#endif /* Pick a platform-specific implementation; the sequence of #if's here should * match the sequence just above. From python-checkins at python.org Fri Jul 9 01:33:10 2010 From: python-checkins at python.org (victor.stinner) Date: Fri, 9 Jul 2010 01:33:10 +0200 (CEST) Subject: [Python-checkins] r82704 - python/branches/import_unicode/Python/import.c Message-ID: <20100708233310.B5E12EEBC1@mail.python.org> Author: victor.stinner Date: Fri Jul 9 01:33:10 2010 New Revision: 82704 Log: only use unicode in find_module() Modified: python/branches/import_unicode/Python/import.c Modified: python/branches/import_unicode/Python/import.c ============================================================================== --- python/branches/import_unicode/Python/import.c (original) +++ python/branches/import_unicode/Python/import.c Fri Jul 9 01:33:10 2010 @@ -1630,12 +1630,12 @@ static struct filedescr importhookdescr = {"", "", IMP_HOOK}; static struct filedescr * -_find_module(char *fullname, char *subname, PyObject *search_path, - char *buf, size_t buflen, PyObject **path, +find_module(char *fullname, char *subname, PyObject *search_path, + PyObject **path, FILE **p_fp, PyObject **p_loader) { Py_ssize_t i, npath; - size_t len, namelen; + size_t namelen; struct filedescr *fdp = NULL; char *filemode; FILE *fp = NULL; @@ -1646,11 +1646,11 @@ static struct filedescr fd_package = {"", "", PKG_DIRECTORY}; char name[MAXPATHLEN+1]; #if defined(PYOS_OS2) - size_t saved_len; + PyObject *unicode_saved; size_t saved_namelen; - char *saved_buf = NULL; #endif PyObject *unicode; + PyObject *unicode_without_suffix; *path = NULL; if (p_loader != NULL) @@ -1752,40 +1752,25 @@ npath = PyList_Size(search_path); namelen = strlen(name); for (i = 0; i < npath; i++) { - PyObject *v = PyList_GetItem(search_path, i); - PyObject *origv = v; - const char *base; - Py_ssize_t size; - if (!v) - return NULL; - if (PyUnicode_Check(v)) { - v = PyUnicode_EncodeFSDefault(v); - if (v == NULL) - return NULL; - } - else - continue; + PyObject *v; + Py_UNICODE *unicode_buf; + Py_ssize_t unicode_len; - base = PyBytes_AS_STRING(v); - size = PyBytes_GET_SIZE(v); - len = size; - if (len + 2 + namelen + MAXSUFFIXSIZE >= buflen) { - Py_DECREF(v); - continue; /* Too long */ - } - strcpy(buf, base); - Py_DECREF(v); + v = PyList_GetItem(search_path, i); + if (v == NULL) + return NULL; + if (!PyUnicode_Check(v)) + continue; - if (strlen(buf) != len) { - continue; /* v contains '\0' */ - } + unicode_buf = PyUnicode_AS_UNICODE(v); + unicode_len = PyUnicode_GET_SIZE(v); /* sys.path_hooks import hook */ if (p_loader != NULL) { PyObject *importer; importer = get_path_importer(path_importer_cache, - path_hooks, origv); + path_hooks, v); if (importer == NULL) { return NULL; } @@ -1808,21 +1793,20 @@ } /* no hook was found, use builtin import */ - if (len > 0 && buf[len-1] != SEP + if (unicode_len > 0 && unicode_buf[unicode_len-1] != SEP #ifdef ALTSEP - && buf[len-1] != ALTSEP + && unicode_buf[unicode_len-1] != ALTSEP #endif ) - buf[len++] = SEP; - strcpy(buf+len, name); - len += namelen; + unicode = PyUnicode_FromFormat("%U%c%s", v, SEP, name); + else + unicode = PyUnicode_FromFormat("%U%s", v, name); + if (unicode == NULL) + return NULL; /* Check for package import (buf holds a directory name, and there's an __init__ module in that directory */ #ifdef HAVE_STAT - unicode = PyUnicode_DecodeFSDefault(buf); - if (unicode == NULL) - return NULL; if (stat_unicode(unicode, &statbuf) == 0 && /* it exists */ S_ISDIR(statbuf.st_mode) && /* it's a directory */ case_ok(unicode, 0, namelen, name)) { /* case matches */ @@ -1841,16 +1825,18 @@ } } } - Py_DECREF(unicode); #endif + Py_INCREF(unicode); + unicode_without_suffix = unicode; #if defined(PYOS_OS2) /* take a snapshot of the module spec for restoration * after the 8 character DLL hackery */ - saved_buf = strdup(buf); - saved_len = len; + Py_INCREF(unicode_without_suffix); + saved_unicode = unicode_without_suffix; saved_namelen = namelen; #endif /* PYOS_OS2 */ + Py_CLEAR(unicode); for (fdp = _PyImport_Filetab; fdp->suffix != NULL; fdp++) { #if defined(PYOS_OS2) && defined(HAVE_DYNAMIC_LOADING) /* OS/2 limits DLLs to 8 character names (w/o @@ -1870,15 +1856,18 @@ scan++; } if (scan->suffix != NULL) { + PyObject* truncated; /* yes, so truncate the name */ namelen = 8; - len -= strlen(subname) - namelen; - buf[len] = '\0'; + truncated = PyUnicode_FromUnicode( + PyUnicode_AS_UNICODE(unicode_without_suffix); + PyUnicode_GET_SIZE(unicode_without_suffix) - (strlen(subname) - namelen)); + Py_DECREF(unicode_without_suffix); + unicode_without_suffix = truncated; } } #endif /* PYOS_OS2 */ - strcpy(buf+len, fdp->suffix); - unicode = PyUnicode_DecodeFSDefault(buf); + unicode = PyUnicode_FromFormat("%U%s", unicode_without_suffix, fdp->suffix); if (Py_VerboseFlag > 1) PySys_FormatStderr("# trying %U\n", unicode); filemode = fdp->mode; @@ -1887,59 +1876,39 @@ fp = fopen_unicode(unicode, filemode); if (fp != NULL) { if (case_ok(unicode, strlen(fdp->suffix), namelen, name)) { - Py_DECREF(unicode); break; } else { /* continue search */ fclose(fp); fp = NULL; } } - Py_DECREF(unicode); #if defined(PYOS_OS2) /* restore the saved snapshot */ - strcpy(buf, saved_buf); - len = saved_len; + Py_DECREF(unicode_without_suffix); + Py_INCREF(saved_unicode); + unicode_without_suffix = saved_unicode; namelen = saved_namelen; #endif } + Py_CLEAR(unicode_without_suffix); #if defined(PYOS_OS2) - /* don't need/want the module name snapshot anymore */ - if (saved_buf) - { - free(saved_buf); - saved_buf = NULL; - } + Py_DECREF(saved_unicode); #endif if (fp != NULL) break; + Py_DECREF(unicode); } + Py_XDECREF(unicode_without_suffix); if (fp == NULL) { PyErr_Format(PyExc_ImportError, "No module named %.200s", name); return NULL; } - *path = PyUnicode_DecodeFSDefault(buf); - if (*path == NULL) { - fclose(fp); - return NULL; - } + *path = unicode; *p_fp = fp; return fdp; } -static struct filedescr * -find_module(char *fullname, char *subname, PyObject *search_path, PyObject **path, - FILE **p_fp, PyObject **p_loader) -{ - char buf[MAXPATHLEN+1]; - struct filedescr *fd; - buf[0] = '\0'; - fd = _find_module(fullname, subname, search_path, - buf, sizeof(buf), path, - p_fp, p_loader); - return fd; -} - /* Helpers for main.c * Find the source file corresponding to a named module */ From python-checkins at python.org Fri Jul 9 01:33:12 2010 From: python-checkins at python.org (victor.stinner) Date: Fri, 9 Jul 2010 01:33:12 +0200 (CEST) Subject: [Python-checkins] r82705 - python/branches/import_unicode/Python/import.c Message-ID: <20100708233312.3F77FF1C8@mail.python.org> Author: victor.stinner Date: Fri Jul 9 01:33:12 2010 New Revision: 82705 Log: remove useless name buffer in find_module() add const to fullname and name arguments of find_module() Modified: python/branches/import_unicode/Python/import.c Modified: python/branches/import_unicode/Python/import.c ============================================================================== --- python/branches/import_unicode/Python/import.c (original) +++ python/branches/import_unicode/Python/import.c Fri Jul 9 01:33:12 2010 @@ -1461,9 +1461,9 @@ /* Forward */ static PyObject *load_module(char *, FILE *, PyObject *, int, PyObject *); -static struct filedescr *find_module(char *, char *, PyObject *, +static struct filedescr *find_module(const char *, const char *, PyObject *, PyObject **, FILE **, PyObject **); -static struct _frozen * find_frozen(char *); +static struct _frozen * find_frozen(const char *); /* Load a package and return its module object WITH INCREMENTED REFERENCE COUNT */ @@ -1524,7 +1524,7 @@ /* Helper to test for built-in module */ static int -is_builtin(char *name) +is_builtin(const char *name) { int i; for (i = 0; PyImport_Inittab[i].name != NULL; i++) { @@ -1626,11 +1626,11 @@ PyObject **); #endif -static int case_ok(PyObject *, Py_ssize_t, Py_ssize_t, char *); +static int case_ok(PyObject *, Py_ssize_t, Py_ssize_t, const char *); static struct filedescr importhookdescr = {"", "", IMP_HOOK}; static struct filedescr * -find_module(char *fullname, char *subname, PyObject *search_path, +find_module(const char *fullname, const char *name, PyObject *search_path, PyObject **path, FILE **p_fp, PyObject **p_loader) { @@ -1644,7 +1644,6 @@ static struct filedescr fd_frozen = {"", "", PY_FROZEN}; static struct filedescr fd_builtin = {"", "", C_BUILTIN}; static struct filedescr fd_package = {"", "", PKG_DIRECTORY}; - char name[MAXPATHLEN+1]; #if defined(PYOS_OS2) PyObject *unicode_saved; size_t saved_namelen; @@ -1656,12 +1655,11 @@ if (p_loader != NULL) *p_loader = NULL; - if (strlen(subname) > MAXPATHLEN) { + if (strlen(name) > MAXPATHLEN) { PyErr_SetString(PyExc_OverflowError, "module name is too long"); return NULL; } - strcpy(name, subname); /* sys.meta_path import hook */ if (p_loader != NULL) { @@ -1845,7 +1843,7 @@ * dynamically loaded module we're going to try, * truncate the name before trying */ - if (strlen(subname) > 8) { + if (strlen(name) > 8) { /* is this an attempt to load a C extension? */ const struct filedescr *scan; scan = _PyImport_DynLoadFiletab; @@ -1861,7 +1859,7 @@ namelen = 8; truncated = PyUnicode_FromUnicode( PyUnicode_AS_UNICODE(unicode_without_suffix); - PyUnicode_GET_SIZE(unicode_without_suffix) - (strlen(subname) - namelen)); + PyUnicode_GET_SIZE(unicode_without_suffix) - (strlen(name) - namelen)); Py_DECREF(unicode_without_suffix); unicode_without_suffix = truncated; } @@ -1962,7 +1960,7 @@ #endif static int -case_ok(PyObject *bufobj, Py_ssize_t lendelta, Py_ssize_t namelen, char *name) +case_ok(PyObject *bufobj, Py_ssize_t lendelta, Py_ssize_t namelen, const char *name) { #if defined(MS_WINDOWS) || defined(DJGPP) || (defined(__MACH__) && defined(__APPLE__) \ || defined(__CYGWIN__)) && defined(HAVE_DIRENT_H) || defined(PYOS_OS2) @@ -2306,7 +2304,7 @@ /* Frozen modules */ static struct _frozen * -find_frozen(char *name) +find_frozen(const char *name) { struct _frozen *p; @@ -2685,6 +2683,7 @@ int error; modname_str = _PyUnicode_AsStringAndSize(modname, &len); + /* FIXME: don't use _PyUnicode_AsStringAndSize or check that modname_str is not NULL */ if (len > MAXPATHLEN) { PyErr_SetString(PyExc_ValueError, "Module name too long"); From python-checkins at python.org Fri Jul 9 01:33:13 2010 From: python-checkins at python.org (victor.stinner) Date: Fri, 9 Jul 2010 01:33:13 +0200 (CEST) Subject: [Python-checkins] r82706 - python/branches/import_unicode/Python/import.c Message-ID: <20100708233313.A5101EEBCA@mail.python.org> Author: victor.stinner Date: Fri Jul 9 01:33:13 2010 New Revision: 82706 Log: add FIXME Modified: python/branches/import_unicode/Python/import.c Modified: python/branches/import_unicode/Python/import.c ============================================================================== --- python/branches/import_unicode/Python/import.c (original) +++ python/branches/import_unicode/Python/import.c Fri Jul 9 01:33:13 2010 @@ -970,6 +970,7 @@ static PyObject* make_compiled_pathname(PyObject *pathobj, int debug) { + /* FIXME: use Py_UNICODE* instead of char* */ char buf[MAXPATHLEN+1]; char *pathname, *cpathname; @@ -2521,6 +2522,7 @@ import_module_level(char *name, PyObject *globals, PyObject *locals, PyObject *fromlist, int level) { + /* FIXME: use unicode */ char buf[MAXPATHLEN+1]; Py_ssize_t buflen = 0; PyObject *parent, *head, *next, *tail; From python-checkins at python.org Fri Jul 9 01:33:15 2010 From: python-checkins at python.org (victor.stinner) Date: Fri, 9 Jul 2010 01:33:15 +0200 (CEST) Subject: [Python-checkins] r82707 - python/branches/import_unicode/Python/import.c Message-ID: <20100708233315.2CEFAEEB79@mail.python.org> Author: victor.stinner Date: Fri Jul 9 01:33:14 2010 New Revision: 82707 Log: use PyUnicode_EncodeFSDefault() in fopen_unicode() and stat_unicode() Cleanup case_ok() Modified: python/branches/import_unicode/Python/import.c Modified: python/branches/import_unicode/Python/import.c ============================================================================== --- python/branches/import_unicode/Python/import.c (original) +++ python/branches/import_unicode/Python/import.c Fri Jul 9 01:33:14 2010 @@ -1963,30 +1963,27 @@ static int case_ok(PyObject *bufobj, Py_ssize_t lendelta, Py_ssize_t namelen, const char *name) { -#if defined(MS_WINDOWS) || defined(DJGPP) || (defined(__MACH__) && defined(__APPLE__) \ - || defined(__CYGWIN__)) && defined(HAVE_DIRENT_H) || defined(PYOS_OS2) - /* FIXME: don't use _PyUnicode_AsString */ - char *buf = _PyUnicode_AsString(bufobj); - Py_ssize_t len = strlen(buf) - lendelta; -#endif - /* Pick a platform-specific implementation; the sequence of #if's here should * match the sequence just above. */ /* MS_WINDOWS */ #if defined(MS_WINDOWS) + char *buf; WIN32_FIND_DATA data; HANDLE h; if (Py_GETENV("PYTHONCASEOK") != NULL) return 1; + /* FIXME: use PyUnicode_AsWideChar() and FindFirstFileW() */ + buf = _PyUnicode_AsString(bufobj); + h = FindFirstFile(buf, &data); if (h == INVALID_HANDLE_VALUE) { PyErr_Format(PyExc_NameError, - "Can't find file for module %.100s\n(filename %.300s)", - name, buf); + "Can't find file for module %.100s\n(filename %U)", + name, bufobj); return 0; } FindClose(h); @@ -1994,31 +1991,42 @@ /* DJGPP */ #elif defined(DJGPP) + char *buf; struct ffblk ffblk; int done; if (Py_GETENV("PYTHONCASEOK") != NULL) return 1; + /* FIXME: use PyUnicode_EncodeFSDefault() */ + buf = _PyUnicode_AsString(bufobj); + done = findfirst(buf, &ffblk, FA_ARCH|FA_RDONLY|FA_HIDDEN|FA_DIREC); if (done) { PyErr_Format(PyExc_NameError, - "Can't find file for module %.100s\n(filename %.300s)", - name, buf); + "Can't find file for module %.100s\n(filename %U)", + name, bufobj); return 0; } return strncmp(ffblk.ff_name, name, namelen) == 0; /* new-fangled macintosh (macosx) or Cygwin */ #elif (defined(__MACH__) && defined(__APPLE__) || defined(__CYGWIN__)) && defined(HAVE_DIRENT_H) + char *buf; + Py_ssize_t len; DIR *dirp; struct dirent *dp; char dirname[MAXPATHLEN + 1]; - const int dirlen = len - namelen - 1; /* don't want trailing SEP */ + int dirlen; if (Py_GETENV("PYTHONCASEOK") != NULL) return 1; + /* FIXME: use PyUnicode_EncodeFSDefault() */ + buf = _PyUnicode_AsString(bufobj); + len = strlen(buf) - lendelta; + dirlen = len - namelen - 1; /* don't want trailing SEP */ + /* Copy the dir component into dirname; substitute "." if empty */ if (dirlen <= 0) { dirname[0] = '.'; @@ -2052,6 +2060,7 @@ /* OS/2 */ #elif defined(PYOS_OS2) + char *buf; HDIR hdir = 1; ULONG srchcnt = 1; FILEFINDBUF3 ffbuf; @@ -2060,6 +2069,9 @@ if (Py_GETENV("PYTHONCASEOK") != NULL) return 1; + /* FIXME: use PyUnicode_EncodeFSDefault() */ + buf = _PyUnicode_AsString(bufobj); + rc = DosFindFirst(buf, &hdir, FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM | FILE_DIRECTORY, @@ -2080,11 +2092,13 @@ static FILE* fopen_unicode(PyObject *unicode, const char *mode) { - /* FIXME: use PyUnicode_EncodeFSDefault() */ - char *pathstr = _PyUnicode_AsString(unicode); - if (pathstr == NULL) - return NULL; - return fopen(pathstr, mode); + FILE *f; + PyObject *bytes = PyUnicode_EncodeFSDefault(unicode); + if (bytes == NULL) + return NULL; + f = fopen(PyBytes_AS_STRING(bytes), mode); + Py_DECREF(bytes); + return f; } @@ -2092,11 +2106,13 @@ static int stat_unicode(PyObject *unicode, struct stat *statbuf) { - /* FIXME: use PyUnicode_EncodeFSDefault() */ - char *pathstr = _PyUnicode_AsString(unicode); - if (pathstr == NULL) - return 1; - return stat(pathstr, statbuf); + int ret; + PyObject *bytes = PyUnicode_EncodeFSDefault(unicode); + if (bytes == NULL) + return -1; + ret = stat(PyBytes_AS_STRING(bytes), statbuf); + Py_DECREF(bytes); + return ret; } /* Helper to look for __init__.py or __init__.py[co] in potential package */ From python-checkins at python.org Fri Jul 9 01:33:16 2010 From: python-checkins at python.org (victor.stinner) Date: Fri, 9 Jul 2010 01:33:16 +0200 (CEST) Subject: [Python-checkins] r82708 - python/branches/import_unicode/Python/import.c Message-ID: <20100708233316.99D43EEBA0@mail.python.org> Author: victor.stinner Date: Fri Jul 9 01:33:16 2010 New Revision: 82708 Log: write_compiled_module() uses PyUnicode_EncodeFSDefault() Modified: python/branches/import_unicode/Python/import.c Modified: python/branches/import_unicode/Python/import.c ============================================================================== --- python/branches/import_unicode/Python/import.c (original) +++ python/branches/import_unicode/Python/import.c Fri Jul 9 01:33:16 2010 @@ -1232,14 +1232,15 @@ S_IWUSR | S_IWGRP | S_IWOTH); #endif int saved; + PyObject *cpathbytes; char *cpathname; - /* FIXME: use PyUnicode_EncodeFSDefault() */ - cpathname = _PyUnicode_AsString(cpathobj); - if (cpathname == NULL) { + cpathbytes = PyUnicode_EncodeFSDefault(cpathobj); + if (cpathbytes == NULL) { PyErr_Clear(); return; } + cpathname = PyBytes_AS_STRING(cpathbytes); /* Ensure that the __pycache__ directory exists. */ dirpath = rightmost_sep(cpathname); @@ -1248,6 +1249,7 @@ PySys_WriteStderr( "# no %s path found %s\n", CACHEDIR, cpathname); + Py_DECREF(cpathbytes); return; } saved = *dirpath; @@ -1258,6 +1260,7 @@ if (Py_VerboseFlag) PySys_WriteStderr( "# cannot create cache dir %s\n", cpathname); + Py_DECREF(cpathbytes); return; } *dirpath = saved; @@ -1267,6 +1270,7 @@ if (Py_VerboseFlag) PySys_WriteStderr( "# can't create %s\n", cpathname); + Py_DECREF(cpathbytes); return; } PyMarshal_WriteLongToFile(pyc_magic, fp, Py_MARSHAL_VERSION); @@ -1279,6 +1283,7 @@ /* Don't keep partial file */ fclose(fp); (void) unlink(cpathname); + Py_DECREF(cpathbytes); return; } /* Now write the true mtime */ @@ -1289,6 +1294,7 @@ fclose(fp); if (Py_VerboseFlag) PySys_WriteStderr("# wrote %s\n", cpathname); + Py_DECREF(cpathbytes); } static void From python-checkins at python.org Fri Jul 9 01:33:18 2010 From: python-checkins at python.org (victor.stinner) Date: Fri, 9 Jul 2010 01:33:18 +0200 (CEST) Subject: [Python-checkins] r82709 - python/branches/import_unicode/Python/import.c Message-ID: <20100708233318.139C2EE9BE@mail.python.org> Author: victor.stinner Date: Fri Jul 9 01:33:17 2010 New Revision: 82709 Log: parse_source_module() uses PyUnicode_EncodeFSDefault() Modified: python/branches/import_unicode/Python/import.c Modified: python/branches/import_unicode/Python/import.c ============================================================================== --- python/branches/import_unicode/Python/import.c (original) +++ python/branches/import_unicode/Python/import.c Fri Jul 9 01:33:17 2010 @@ -1151,16 +1151,17 @@ PyCodeObject *co = NULL; mod_ty mod; PyCompilerFlags flags; + PyObject *pathbytes; char *pathname; PyArena *arena = PyArena_New(); if (arena == NULL) return NULL; - /* FIXME: use PyUnicode_EncodeFSDefault() */ - pathname = _PyUnicode_AsString(pathobj); - if (pathname == NULL) + pathbytes = PyUnicode_EncodeFSDefault(pathobj); + if (pathbytes == NULL) return NULL; + pathname = PyBytes_AS_STRING(pathbytes); flags.cf_flags = 0; mod = PyParser_ASTFromFile(fp, pathname, NULL, @@ -1169,6 +1170,7 @@ if (mod) { co = PyAST_Compile(mod, pathname, NULL, arena); } + Py_DECREF(pathbytes); PyArena_Free(arena); return co; } From python-checkins at python.org Fri Jul 9 01:33:19 2010 From: python-checkins at python.org (victor.stinner) Date: Fri, 9 Jul 2010 01:33:19 +0200 (CEST) Subject: [Python-checkins] r82710 - python/branches/import_unicode/Python/import.c Message-ID: <20100708233319.7AF9DEEB83@mail.python.org> Author: victor.stinner Date: Fri Jul 9 01:33:19 2010 New Revision: 82710 Log: initialize unicode_without_suffix to NULL Modified: python/branches/import_unicode/Python/import.c Modified: python/branches/import_unicode/Python/import.c ============================================================================== --- python/branches/import_unicode/Python/import.c (original) +++ python/branches/import_unicode/Python/import.c Fri Jul 9 01:33:19 2010 @@ -1658,7 +1658,7 @@ size_t saved_namelen; #endif PyObject *unicode; - PyObject *unicode_without_suffix; + PyObject *unicode_without_suffix = NULL; *path = NULL; if (p_loader != NULL) From python-checkins at python.org Fri Jul 9 01:33:21 2010 From: python-checkins at python.org (victor.stinner) Date: Fri, 9 Jul 2010 01:33:21 +0200 (CEST) Subject: [Python-checkins] r82711 - in python/branches/import_unicode: Include/Python.h Modules/main.c Message-ID: <20100708233321.2F196EEBA0@mail.python.org> Author: victor.stinner Date: Fri Jul 9 01:33:21 2010 New Revision: 82711 Log: create _Py_wchar2char() Use it in _wfopen() (implementation for non Windows OS) Modified: python/branches/import_unicode/Include/Python.h python/branches/import_unicode/Modules/main.c Modified: python/branches/import_unicode/Include/Python.h ============================================================================== --- python/branches/import_unicode/Include/Python.h (original) +++ python/branches/import_unicode/Include/Python.h Fri Jul 9 01:33:21 2010 @@ -128,8 +128,10 @@ /* _Py_Mangle is defined in compile.c */ PyAPI_FUNC(PyObject*) _Py_Mangle(PyObject *p, PyObject *name); -/* _Py_char2wchar lives in main.c */ +/* _Py_char2wchar and _Py_wchar2char lives in main.c */ PyAPI_FUNC(wchar_t *) _Py_char2wchar(char *); +PyAPI_FUNC(char*) _Py_wchar2char(const wchar_t *text); + #ifdef __cplusplus } #endif Modified: python/branches/import_unicode/Modules/main.c ============================================================================== --- python/branches/import_unicode/Modules/main.c (original) +++ python/branches/import_unicode/Modules/main.c Fri Jul 9 01:33:21 2010 @@ -105,20 +105,21 @@ static FILE* _wfopen(const wchar_t *path, const wchar_t *mode) { - char cpath[PATH_MAX]; + FILE *f; + char *cpath; char cmode[10]; size_t r; - r = wcstombs(cpath, path, PATH_MAX); - if (r == (size_t)-1 || r >= PATH_MAX) { - errno = EINVAL; + cpath = _Py_wchar2char(path); + if (cpath == NULL) return NULL; - } r = wcstombs(cmode, mode, 10); if (r == (size_t)-1 || r >= 10) { errno = EINVAL; return NULL; } - return fopen(cpath, cmode); + f = fopen(cpath, cmode); + PyMem_Free(cpath); + return f; } #endif @@ -711,6 +712,43 @@ *argv = orig_argv; } +char* +_Py_wchar2char(const wchar_t *text) +{ + char *result, *bytes; + size_t i, len, converted, size; + wchar_t c; + + len = wcslen(text); + /* FIXME: use better heuristic for the buffer size */ + size = len * 10 + 1; /* +1 for the nul byte at the end */ + result = PyMem_Malloc(size); + if (result == NULL) + return NULL; + + bytes = result; + for (i=0; i < len; i++) { + c = text[i]; + if (c >= 0xd800 && c <= 0xdfff) { + /* Surrogate character */ + *bytes++ = c - 0xdc00; + size--; + continue; + } else { + wchar_t buf[2]; + buf[0] = c; + buf[1] = 0; + converted = wcstombs(bytes, buf, size); + if (converted == (size_t)-1 || converted == 0) { + PyMem_Free(result); + return NULL; + } + bytes += converted; + size -= converted; + } + } + return result; +} wchar_t* _Py_char2wchar(char* arg) From python-checkins at python.org Fri Jul 9 01:33:22 2010 From: python-checkins at python.org (victor.stinner) Date: Fri, 9 Jul 2010 01:33:22 +0200 (CEST) Subject: [Python-checkins] r82712 - python/branches/import_unicode/Lib/test/test_import.py Message-ID: <20100708233322.DFC53EEBCA@mail.python.org> Author: victor.stinner Date: Fri Jul 9 01:33:22 2010 New Revision: 82712 Log: Fix test_import for non ASCII path Skip test_import_by_filename is the path is not encodable to the file system encoding Modified: python/branches/import_unicode/Lib/test/test_import.py Modified: python/branches/import_unicode/Lib/test/test_import.py ============================================================================== --- python/branches/import_unicode/Lib/test/test_import.py (original) +++ python/branches/import_unicode/Lib/test/test_import.py Fri Jul 9 01:33:22 2010 @@ -289,6 +289,13 @@ def test_import_by_filename(self): path = os.path.abspath(TESTFN) + encoding = sys.getfilesystemencoding() + try: + path.encode(encoding) + except UnicodeEncodeError: + self.skipTest('path is not encodable to {}'.format(encoding)) + else: + pass with self.assertRaises(ImportError) as c: __import__(path) self.assertEqual("Import by filename is not supported.", From python-checkins at python.org Fri Jul 9 01:33:24 2010 From: python-checkins at python.org (victor.stinner) Date: Fri, 9 Jul 2010 01:33:24 +0200 (CEST) Subject: [Python-checkins] r82713 - python/branches/import_unicode/Python/_warnings.c Message-ID: <20100708233324.66D12EEAF0@mail.python.org> Author: victor.stinner Date: Fri Jul 9 01:33:24 2010 New Revision: 82713 Log: warnings: use unicode for the filename Modified: python/branches/import_unicode/Python/_warnings.c Modified: python/branches/import_unicode/Python/_warnings.c ============================================================================== --- python/branches/import_unicode/Python/_warnings.c (original) +++ python/branches/import_unicode/Python/_warnings.c Fri Jul 9 01:33:24 2010 @@ -498,23 +498,21 @@ *filename = PyDict_GetItemString(globals, "__file__"); if (*filename != NULL) { Py_ssize_t len = PyUnicode_GetSize(*filename); - const char *file_str = _PyUnicode_AsString(*filename); - if (file_str == NULL || (len < 0 && PyErr_Occurred())) - goto handle_error; + Py_UNICODE *unicode = PyUnicode_AS_UNICODE(*filename); /* if filename.lower().endswith((".pyc", ".pyo")): */ if (len >= 4 && - file_str[len-4] == '.' && - tolower(file_str[len-3]) == 'p' && - tolower(file_str[len-2]) == 'y' && - (tolower(file_str[len-1]) == 'c' || - tolower(file_str[len-1]) == 'o')) + unicode[len-4] == '.' && + Py_UNICODE_TOLOWER(unicode[len-3]) == 'p' && + Py_UNICODE_TOLOWER(unicode[len-2]) == 'y' && + (Py_UNICODE_TOLOWER(unicode[len-1]) == 'c' || + Py_UNICODE_TOLOWER(unicode[len-1]) == 'o')) { - *filename = PyUnicode_FromStringAndSize(file_str, len-1); - if (*filename == NULL) - goto handle_error; - } - else + *filename = PyUnicode_FromUnicode(unicode, len-1); + if (*filename == NULL) + goto handle_error; + } + else Py_INCREF(*filename); } else { From python-checkins at python.org Fri Jul 9 01:33:25 2010 From: python-checkins at python.org (victor.stinner) Date: Fri, 9 Jul 2010 01:33:25 +0200 (CEST) Subject: [Python-checkins] r82714 - python/branches/import_unicode/Python/importdl.c Message-ID: <20100708233325.D65B4EE9A2@mail.python.org> Author: victor.stinner Date: Fri Jul 9 01:33:25 2010 New Revision: 82714 Log: importdl: use PyUnicode_EncodeFSDefault() Instead of the evil _PyUnicode_AsString() Modified: python/branches/import_unicode/Python/importdl.c Modified: python/branches/import_unicode/Python/importdl.c ============================================================================== --- python/branches/import_unicode/Python/importdl.c (original) +++ python/branches/import_unicode/Python/importdl.c Fri Jul 9 01:33:25 2010 @@ -22,15 +22,12 @@ _PyImport_LoadDynamicModule(char *name, PyObject *path, FILE *fp) { PyObject *m; - char *pathname; + PyObject *pathbytes; char *lastdot, *shortname, *packagecontext, *oldcontext; dl_funcptr p0; PyObject* (*p)(void); struct PyModuleDef *def; - /* FIXME: don't use _PyUnicode_AsString */ - pathname = _PyUnicode_AsString(path); - if ((m = _PyImport_FindExtensionUnicode(name, path)) != NULL) { Py_INCREF(m); return m; @@ -45,7 +42,12 @@ shortname = lastdot+1; } - p0 = _PyImport_GetDynLoadFunc(name, shortname, pathname, fp); + /* FIXME: pass path, not pathname, at least to the Windows implementation */ + pathbytes = PyUnicode_EncodeFSDefault(path); + if (pathbytes == NULL) + return NULL; + p0 = _PyImport_GetDynLoadFunc(name, shortname, PyBytes_AsString(pathbytes), fp); + Py_DECREF(pathbytes); p = (PyObject*(*)(void))p0; if (PyErr_Occurred()) return NULL; @@ -84,9 +86,9 @@ if (_PyImport_FixupExtensionUnicode(m, name, path) < 0) return NULL; if (Py_VerboseFlag) - PySys_WriteStderr( - "import %s # dynamically loaded from %s\n", - name, pathname); + PySys_FormatStderr( + "import %s # dynamically loaded from %U\n", + name, path); return m; } From python-checkins at python.org Fri Jul 9 01:33:27 2010 From: python-checkins at python.org (victor.stinner) Date: Fri, 9 Jul 2010 01:33:27 +0200 (CEST) Subject: [Python-checkins] r82715 - python/branches/import_unicode/Python/import.c Message-ID: <20100708233327.4A6EBEE995@mail.python.org> Author: victor.stinner Date: Fri Jul 9 01:33:27 2010 New Revision: 82715 Log: Use PyUnicode_EncodeFSDefault() in make_xxx_pathname() instead of _PyUnicode_AsString() Modified: python/branches/import_unicode/Python/import.c Modified: python/branches/import_unicode/Python/import.c ============================================================================== --- python/branches/import_unicode/Python/import.c (original) +++ python/branches/import_unicode/Python/import.c Fri Jul 9 01:33:27 2010 @@ -972,12 +972,18 @@ { /* FIXME: use Py_UNICODE* instead of char* */ char buf[MAXPATHLEN+1]; + PyObject *pathbytes; char *pathname, *cpathname; - /* FIXME: don't use _PyUnicode_AsString */ - pathname = _PyUnicode_AsString(pathobj); + pathbytes = PyUnicode_EncodeFSDefault(pathobj); + if (pathbytes == NULL) + return NULL; + + pathname = strdup(PyBytes_AsString(pathbytes)); + Py_DECREF(pathbytes); cpathname = _make_compiled_pathname(pathname, buf, sizeof(buf), debug); + free(pathname); if (cpathname != NULL) return PyUnicode_DecodeFSDefault(cpathname); else @@ -1044,12 +1050,20 @@ { /* FIXME: use Py_UNICODE* instead of char* */ char buf[MAXPATHLEN + 1]; + PyObject *pathbytes; char *pathname, *cpathname; - /* FIXME: don't use _PyUnicode_AsString */ - pathname = _PyUnicode_AsString(pathobj); + pathbytes = PyUnicode_EncodeFSDefault(pathobj); + if (pathbytes == NULL) + return NULL; + + pathname = strdup(PyBytes_AsString(pathbytes)); + Py_DECREF(pathbytes); + if (pathname == NULL) + return NULL; cpathname = _make_source_pathname(pathname, buf); + free(pathname); if (cpathname != NULL) return PyUnicode_DecodeFSDefault(cpathname); else From python-checkins at python.org Fri Jul 9 01:33:28 2010 From: python-checkins at python.org (victor.stinner) Date: Fri, 9 Jul 2010 01:33:28 +0200 (CEST) Subject: [Python-checkins] r82716 - python/branches/import_unicode/Python/ceval.c Message-ID: <20100708233328.AC29EEEBA6@mail.python.org> Author: victor.stinner Date: Fri Jul 9 01:33:28 2010 New Revision: 82716 Log: ceval: remove filename debug variable _PyUnicode_AsString() may raise an exception Modified: python/branches/import_unicode/Python/ceval.c Modified: python/branches/import_unicode/Python/ceval.c ============================================================================== --- python/branches/import_unicode/Python/ceval.c (original) +++ python/branches/import_unicode/Python/ceval.c Fri Jul 9 01:33:28 2010 @@ -796,10 +796,6 @@ unsigned char *first_instr; PyObject *names; PyObject *consts; -#if defined(Py_DEBUG) || defined(LLTRACE) - /* Make it easier to find out where we are with a debugger */ - char *filename; -#endif /* Computed GOTOs, or the-optimization-commonly-but-improperly-known-as-"threaded code" @@ -1199,9 +1195,6 @@ #ifdef LLTRACE lltrace = PyDict_GetItemString(f->f_globals, "__lltrace__") != NULL; #endif -#if defined(Py_DEBUG) || defined(LLTRACE) - filename = _PyUnicode_AsString(co->co_filename); -#endif why = WHY_NOT; err = 0; From python-checkins at python.org Fri Jul 9 01:33:30 2010 From: python-checkins at python.org (victor.stinner) Date: Fri, 9 Jul 2010 01:33:30 +0200 (CEST) Subject: [Python-checkins] r82717 - python/branches/import_unicode/Parser/tokenizer.c Message-ID: <20100708233330.14872EEB2A@mail.python.org> Author: victor.stinner Date: Fri Jul 9 01:33:29 2010 New Revision: 82717 Log: tokenizer uses unicode filename Modified: python/branches/import_unicode/Parser/tokenizer.c Modified: python/branches/import_unicode/Parser/tokenizer.c ============================================================================== --- python/branches/import_unicode/Parser/tokenizer.c (original) +++ python/branches/import_unicode/Parser/tokenizer.c Fri Jul 9 01:33:29 2010 @@ -467,10 +467,14 @@ if (io == NULL) goto cleanup; - if (tok->filename) - stream = PyObject_CallMethod(io, "open", "ssis", - tok->filename, "r", -1, enc); - else + if (tok->filename) { + PyObject *filename = PyUnicode_DecodeFSDefault(tok->filename); + if (filename == NULL) + goto cleanup; + stream = PyObject_CallMethod(io, "open", "Osis", + filename, "r", -1, enc); + Py_DECREF(filename); + } else stream = PyObject_CallMethod(io, "open", "isisOOO", fileno(tok->fp), "r", -1, enc, Py_None, Py_None, Py_False); if (stream == NULL) From python-checkins at python.org Fri Jul 9 01:33:31 2010 From: python-checkins at python.org (victor.stinner) Date: Fri, 9 Jul 2010 01:33:31 +0200 (CEST) Subject: [Python-checkins] r82718 - python/branches/import_unicode/Modules/zipimport.c Message-ID: <20100708233331.95A43EEB35@mail.python.org> Author: victor.stinner Date: Fri Jul 9 01:33:31 2010 New Revision: 82718 Log: zipimporter uses PyUnicode_FSConverter() to use the file system encoding, not utf-8 Modified: python/branches/import_unicode/Modules/zipimport.c Modified: python/branches/import_unicode/Modules/zipimport.c ============================================================================== --- python/branches/import_unicode/Modules/zipimport.c (original) +++ python/branches/import_unicode/Modules/zipimport.c Fri Jul 9 01:33:31 2010 @@ -60,26 +60,31 @@ static int zipimporter_init(ZipImporter *self, PyObject *args, PyObject *kwds) { + PyObject *pathbytes; char *path, *p, *prefix, buf[MAXPATHLEN+2]; size_t len; if (!_PyArg_NoKeywords("zipimporter()", kwds)) return -1; - if (!PyArg_ParseTuple(args, "s:zipimporter", &path)) + if (!PyArg_ParseTuple(args, "O&:zipimporter", PyUnicode_FSConverter, &pathbytes)) return -1; - len = strlen(path); + len = PyBytes_GET_SIZE(pathbytes); if (len == 0) { PyErr_SetString(ZipImportError, "archive path is empty"); + Py_DECREF(pathbytes); return -1; } + path = PyBytes_AsString(pathbytes); if (len >= MAXPATHLEN) { PyErr_SetString(ZipImportError, "archive path too long"); + Py_DECREF(pathbytes); return -1; } strcpy(buf, path); + Py_DECREF(pathbytes); #ifdef ALTSEP for (p = buf; *p; p++) { From python-checkins at python.org Fri Jul 9 01:33:33 2010 From: python-checkins at python.org (victor.stinner) Date: Fri, 9 Jul 2010 01:33:33 +0200 (CEST) Subject: [Python-checkins] r82719 - python/branches/import_unicode/Modules/getpath.c Message-ID: <20100708233333.2DC22EEAF6@mail.python.org> Author: victor.stinner Date: Fri Jul 9 01:33:32 2010 New Revision: 82719 Log: fix calculate_path() to use surrogates Modified: python/branches/import_unicode/Modules/getpath.c Modified: python/branches/import_unicode/Modules/getpath.c ============================================================================== --- python/branches/import_unicode/Modules/getpath.c (original) +++ python/branches/import_unicode/Modules/getpath.c Fri Jul 9 01:33:32 2010 @@ -139,58 +139,58 @@ static int _wstat(const wchar_t* path, struct stat *buf) { - char fname[PATH_MAX]; - size_t res = wcstombs(fname, path, sizeof(fname)); - if (res == (size_t)-1) { - errno = EINVAL; + int ret; + char *fname; + fname = _Py_wchar2char(path); + if (fname == NULL) return -1; - } - return stat(fname, buf); + ret = stat(fname, buf); + PyMem_Free(fname); + return ret; } #endif -#ifndef MS_WINDOWS static wchar_t* -_wgetcwd(wchar_t *buf, size_t size) +_Py_wgetcwd(wchar_t *buf, size_t size) { +#ifdef MS_WINDOWS + wchar_t buffer[MAXPATHLEN + 1]; + wchar_t *ret, *result; + size_t len; + ret = _wgetcwd(buffer, MAXPATHLEN); + if (ret == NULL) + return NULL; + len = wcslen(buffer); + result = PyMem_Malloc(len + 1); + if (result == NULL) + return NULL; + wcscpy(result, buffer); + return result; +#else char fname[PATH_MAX]; if (getcwd(fname, PATH_MAX) == NULL) return NULL; - if (mbstowcs(buf, fname, size) >= size) { - errno = ERANGE; - return NULL; - } - return buf; -} + return _Py_char2wchar(fname); #endif +} #ifdef HAVE_READLINK -int -_Py_wreadlink(const wchar_t *path, wchar_t *buf, size_t bufsiz) +wchar_t* +_Py_wreadlink(const wchar_t *path) { char cbuf[PATH_MAX]; char cpath[PATH_MAX]; int res; size_t r1 = wcstombs(cpath, path, PATH_MAX); - if (r1 == (size_t)-1 || r1 >= PATH_MAX) { - errno = EINVAL; - return -1; - } + if (r1 == (size_t)-1 || r1 >= PATH_MAX) + return NULL; res = (int)readlink(cpath, cbuf, PATH_MAX); if (res == -1) - return -1; - if (res == PATH_MAX) { - errno = EINVAL; - return -1; - } + return NULL; + if (res == PATH_MAX) + return NULL; cbuf[res] = '\0'; /* buf will be null terminated */ - r1 = mbstowcs(buf, cbuf, bufsiz); - if (r1 == -1) { - errno = EINVAL; - return -1; - } - return (int)r1; - + return _Py_char2wchar(cbuf); } #endif @@ -295,11 +295,19 @@ if (p[0] == SEP) wcscpy(path, p); else { - _wgetcwd(path, MAXPATHLEN); + wchar_t *cwd; + cwd = _Py_wgetcwd(path, MAXPATHLEN); + if (cwd == NULL) + return /* FIXME: return an error */; + if (wcslen(cwd) >= MAXPATHLEN) + return /* FIXME: return an error */; + wcscpy(path, cwd); + PyMem_Free(cwd); if (p[0] == '.' && p[1] == SEP) p += 2; joinpath(path, p); } + return /* FIXME: return ok */; } /* absolutize() requires that path be allocated at least MAXPATHLEN+1 bytes. */ @@ -563,19 +571,20 @@ #if HAVE_READLINK { - wchar_t tmpbuffer[MAXPATHLEN+1]; - int linklen = _Py_wreadlink(progpath, tmpbuffer, MAXPATHLEN); - while (linklen != -1) { - if (tmpbuffer[0] == SEP) - /* tmpbuffer should never be longer than MAXPATHLEN, + wchar_t *link; + link = _Py_wreadlink(progpath); + while (link != NULL) { + if (link[0] == SEP) + /* link should never be longer than MAXPATHLEN, but extra check does not hurt */ - wcsncpy(argv0_path, tmpbuffer, MAXPATHLEN); + wcsncpy(argv0_path, link, MAXPATHLEN); else { /* Interpret relative to progpath */ reduce(argv0_path); - joinpath(argv0_path, tmpbuffer); + joinpath(argv0_path, link); } - linklen = _Py_wreadlink(argv0_path, tmpbuffer, MAXPATHLEN); + PyMem_Free(link); + link = _Py_wreadlink(argv0_path); } } #endif /* HAVE_READLINK */ From python-checkins at python.org Fri Jul 9 01:33:34 2010 From: python-checkins at python.org (victor.stinner) Date: Fri, 9 Jul 2010 01:33:34 +0200 (CEST) Subject: [Python-checkins] r82720 - python/branches/import_unicode/Python/bltinmodule.c Message-ID: <20100708233334.C4409EE9CB@mail.python.org> Author: victor.stinner Date: Fri Jul 9 01:33:34 2010 New Revision: 82720 Log: compile() uses PyUnicode_FSConverter Modified: python/branches/import_unicode/Python/bltinmodule.c Modified: python/branches/import_unicode/Python/bltinmodule.c ============================================================================== --- python/branches/import_unicode/Python/bltinmodule.c (original) +++ python/branches/import_unicode/Python/bltinmodule.c Fri Jul 9 01:33:34 2010 @@ -542,7 +542,9 @@ static PyObject * builtin_compile(PyObject *self, PyObject *args, PyObject *kwds) { + PyObject *code; char *str; + PyObject *fileobj; char *filename; char *startstr; int mode = -1; @@ -555,11 +557,13 @@ "dont_inherit", NULL}; int start[] = {Py_file_input, Py_eval_input, Py_single_input}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "Oss|ii:compile", - kwlist, &cmd, &filename, &startstr, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO&s|ii:compile", kwlist, + &cmd, PyUnicode_FSConverter, &fileobj, &startstr, &supplied_flags, &dont_inherit)) return NULL; + filename = PyBytes_AsString(fileobj); + cf.cf_flags = supplied_flags | PyCF_SOURCE_IS_UTF8; if (supplied_flags & @@ -567,6 +571,7 @@ { PyErr_SetString(PyExc_ValueError, "compile(): unrecognised flags"); + Py_DECREF(fileobj); return NULL; } /* XXX Warn if (supplied_flags & PyCF_MASK_OBSOLETE) != 0? */ @@ -584,12 +589,15 @@ else { PyErr_SetString(PyExc_ValueError, "compile() arg 3 must be 'exec', 'eval' or 'single'"); + Py_DECREF(fileobj); return NULL; } is_ast = PyAST_Check(cmd); - if (is_ast == -1) + if (is_ast == -1) { + Py_DECREF(fileobj); return NULL; + } if (is_ast) { PyObject *result; if (supplied_flags & PyCF_ONLY_AST) { @@ -604,20 +612,26 @@ mod = PyAST_obj2mod(cmd, arena, mode); if (mod == NULL) { PyArena_Free(arena); + Py_DECREF(fileobj); return NULL; } result = (PyObject*)PyAST_Compile(mod, filename, &cf, arena); PyArena_Free(arena); } + Py_DECREF(fileobj); return result; } str = source_as_string(cmd, "compile", "string, bytes, AST or code", &cf); - if (str == NULL) + if (str == NULL) { + Py_DECREF(fileobj); return NULL; + } - return Py_CompileStringFlags(str, filename, start[mode], &cf); + code = Py_CompileStringFlags(str, filename, start[mode], &cf); + Py_DECREF(fileobj); + return code; } PyDoc_STRVAR(compile_doc, From python-checkins at python.org Fri Jul 9 01:33:36 2010 From: python-checkins at python.org (victor.stinner) Date: Fri, 9 Jul 2010 01:33:36 +0200 (CEST) Subject: [Python-checkins] r82721 - in python/branches/import_unicode: Include/moduleobject.h Objects/moduleobject.c Message-ID: <20100708233336.7D425EEBC3@mail.python.org> Author: victor.stinner Date: Fri Jul 9 01:33:36 2010 New Revision: 82721 Log: Create PyModule_GetFilenameObject() (public) function Modified: python/branches/import_unicode/Include/moduleobject.h python/branches/import_unicode/Objects/moduleobject.c Modified: python/branches/import_unicode/Include/moduleobject.h ============================================================================== --- python/branches/import_unicode/Include/moduleobject.h (original) +++ python/branches/import_unicode/Include/moduleobject.h Fri Jul 9 01:33:36 2010 @@ -16,6 +16,7 @@ PyAPI_FUNC(PyObject *) PyModule_GetDict(PyObject *); PyAPI_FUNC(const char *) PyModule_GetName(PyObject *); PyAPI_FUNC(const char *) PyModule_GetFilename(PyObject *); +PyAPI_FUNC(PyObject *) PyModule_GetFilenameObject(PyObject *); PyAPI_FUNC(void) _PyModule_Clear(PyObject *); PyAPI_FUNC(struct PyModuleDef*) PyModule_GetDef(PyObject*); PyAPI_FUNC(void*) PyModule_GetState(PyObject*); Modified: python/branches/import_unicode/Objects/moduleobject.c ============================================================================== --- python/branches/import_unicode/Objects/moduleobject.c (original) +++ python/branches/import_unicode/Objects/moduleobject.c Fri Jul 9 01:33:36 2010 @@ -188,8 +188,8 @@ return _PyUnicode_AsString(nameobj); } -static PyObject* -module_getfilename(PyObject *m) +PyObject* +PyModule_GetFilenameObject(PyObject *m) { PyObject *d; PyObject *fileobj; @@ -212,7 +212,7 @@ PyModule_GetFilename(PyObject *m) { PyObject *fileobj; - fileobj = module_getfilename(m); + fileobj = PyModule_GetFilenameObject(m); if (fileobj == NULL) return NULL; return _PyUnicode_AsString(fileobj); @@ -353,7 +353,7 @@ PyErr_Clear(); name = "?"; } - filename = module_getfilename((PyObject *)m); + filename = PyModule_GetFilenameObject((PyObject *)m); if (filename == NULL) { PyErr_Clear(); return PyUnicode_FromFormat("", name); From python-checkins at python.org Fri Jul 9 01:33:38 2010 From: python-checkins at python.org (victor.stinner) Date: Fri, 9 Jul 2010 01:33:38 +0200 (CEST) Subject: [Python-checkins] r82722 - python/branches/import_unicode/Python/pythonrun.c Message-ID: <20100708233338.1C48CEEBC3@mail.python.org> Author: victor.stinner Date: Fri Jul 9 01:33:37 2010 New Revision: 82722 Log: initfsencoding() reencodes sys.path and sys.modules filenames Modified: python/branches/import_unicode/Python/pythonrun.c Modified: python/branches/import_unicode/Python/pythonrun.c ============================================================================== --- python/branches/import_unicode/Python/pythonrun.c (original) +++ python/branches/import_unicode/Python/pythonrun.c Fri Jul 9 01:33:37 2010 @@ -696,6 +696,118 @@ } } +static PyObject* +reencode_filename(PyObject *module, PyObject *file, const char *new_encoding) +{ + PyObject *file_bytes = NULL; + PyObject *new_file = NULL; + + file_bytes = PyUnicode_AsEncodedString( + file, + Py_FileSystemDefaultEncoding, + "surrogateescape"); + if (file_bytes == NULL) + return NULL; + new_file = PyUnicode_Decode( + PyBytes_AsString(file_bytes), + PyBytes_GET_SIZE(file_bytes), + new_encoding, + "surrogateescape"); + Py_DECREF(file_bytes); + return new_file; +} + +static int +reencode_module_path(PyObject *module, PyObject *path, const char *new_encoding) +{ + PyObject *filename; + PyObject *new_filename; + Py_ssize_t i, size; + + size = PyList_Size(path); + for (i=0; iinterp; + PyObject *modules = interp->modules; + PyObject *values; + PyObject *iter = NULL; + PyObject *module = NULL; + PyObject *module_dict = NULL; + PyObject *file; + PyObject *path; + int ret = 1; + + /* FIXME: Re-encode PySys_GetObject("path_importer_cache") keys? */ + /* FIXME: Re-encode co_filename of all code objects! */ + + if (strcmp(new_encoding, PyUnicode_GetDefaultEncoding()) == 0) + return 0; + + + values = PyObject_CallMethod(modules, "values", ""); + if (values == NULL) + return 1; + + iter = PyObject_GetIter(values); + Py_DECREF(values); + if (iter == NULL) + return 1; + + for (module = PyIter_Next(iter); module != NULL; module = PyIter_Next(iter)) { + file = PyModule_GetFilenameObject(module); + if (file != NULL) { + PyObject *new_file = reencode_filename(module, file, new_encoding); + if (new_file == NULL) + goto error; + if (PyObject_SetAttrString(module, "__file__", new_file)) { + Py_DECREF(new_file); + goto error; + } + Py_DECREF(new_file); + } else { + PyErr_Clear(); + } + + module_dict = PyModule_GetDict(module); + if (module_dict == NULL) + goto error; + path = PyDict_GetItemString(module_dict, "__path__"); + if (path != NULL) { + if (reencode_module_path(module, path, new_encoding)) + goto error; + } else { + PyErr_Clear(); + } + + Py_CLEAR(module); + } + + ret = 0; + goto finally; + +error: + ret = 1; +finally: + Py_XDECREF(iter); + Py_XDECREF(module); + return ret; +} + static void initfsencoding(void) { @@ -711,6 +823,10 @@ stdin and stdout if these are terminals. */ codeset = get_codeset(); if (codeset != NULL) { + if (reencode_modules_path(codeset)) + Py_FatalError( + "Py_Initialize: can't reencode paths"); + Py_FileSystemDefaultEncoding = codeset; Py_HasFileSystemDefaultEncoding = 0; return; From victor.stinner at haypocalc.com Fri Jul 9 02:13:58 2010 From: victor.stinner at haypocalc.com (Victor Stinner) Date: Fri, 9 Jul 2010 02:13:58 +0200 Subject: [Python-checkins] r82666 - python/branches/import_unicode/Python/pythonrun.c In-Reply-To: <20100708233214.4C449EE9BC@mail.python.org> References: <20100708233214.4C449EE9BC@mail.python.org> Message-ID: <201007090213.58471.victor.stinner@haypocalc.com> Le vendredi 09 juillet 2010 01:32:14, victor.stinner a ?crit : > Author: victor.stinner > Date: Fri Jul 9 01:32:14 2010 > New Revision: 82666 > > Log: > initialize GIL earlier in Py_InitializeEx() I should maybe reopen issue #8063 (or open a new one): it's really annoying when gdb crashes while I'm debugging the import machinery (or anything else while Python is starting). -- Victor Stinner http://www.haypocalc.com/ From victor.stinner at haypocalc.com Fri Jul 9 02:19:09 2010 From: victor.stinner at haypocalc.com (Victor Stinner) Date: Fri, 9 Jul 2010 02:19:09 +0200 Subject: [Python-checkins] r82695 - in python/branches/import_unicode: Doc/library/sys.rst Python/import.c In-Reply-To: <20100708233257.8D264EEB39@mail.python.org> References: <20100708233257.8D264EEB39@mail.python.org> Message-ID: <201007090219.09573.victor.stinner@haypocalc.com> > New Revision: 82695 > > Log: > _find_module() fills directly path argument > > * find_module(): rename "path" argument to "search_path" > * find_module(): result can be NULL > * reject bytes path > * fix refleak Reject bytes path is temporary. I think that I can restore support of bytes using PyUnicode_DecodeFSDefault(). -- Victor Stinner http://www.haypocalc.com/ From victor.stinner at haypocalc.com Fri Jul 9 02:22:49 2010 From: victor.stinner at haypocalc.com (Victor Stinner) Date: Fri, 9 Jul 2010 02:22:49 +0200 Subject: [Python-checkins] r82702 - in python/branches/import_unicode: PC/import_nt.c Python/import.c In-Reply-To: <20100708233307.C8DCAEEBCF@mail.python.org> References: <20100708233307.C8DCAEEBCF@mail.python.org> Message-ID: <201007090222.49344.victor.stinner@haypocalc.com> Le vendredi 09 juillet 2010 01:33:07, victor.stinner a ?crit : > Author: victor.stinner > Date: Fri Jul 9 01:33:07 2010 > New Revision: 82702 > > Log: > Move buffer into PyWin_FindRegisteredModule() > > The function now returns the path as a PyUnicodeObject* Should I consider PyWin_FindRegisteredModule() as a public function? Because it's not a good idea to change public functions API :-) It's not listed in any header file and import.c uses it with "extern ...". -- Victor Stinner http://www.haypocalc.com/ From victor.stinner at haypocalc.com Fri Jul 9 02:26:13 2010 From: victor.stinner at haypocalc.com (Victor Stinner) Date: Fri, 9 Jul 2010 02:26:13 +0200 Subject: [Python-checkins] r82711 - in python/branches/import_unicode: Include/Python.h Modules/main.c In-Reply-To: <20100708233321.2F196EEBA0@mail.python.org> References: <20100708233321.2F196EEBA0@mail.python.org> Message-ID: <201007090226.13309.victor.stinner@haypocalc.com> Le vendredi 09 juillet 2010 01:33:21, victor.stinner a ?crit : > Author: victor.stinner > Date: Fri Jul 9 01:33:21 2010 > New Revision: 82711 > > Log: > create _Py_wchar2char() The implementation is very inefficient, it should be optimized. I don't know if it works for 16 and 32 bits wchar_t, and narrow and wide Python builds. -- Victor Stinner http://www.haypocalc.com/ From victor.stinner at haypocalc.com Fri Jul 9 02:29:17 2010 From: victor.stinner at haypocalc.com (Victor Stinner) Date: Fri, 9 Jul 2010 02:29:17 +0200 Subject: [Python-checkins] r82716 - python/branches/import_unicode/Python/ceval.c In-Reply-To: <20100708233328.AC29EEEBA6@mail.python.org> References: <20100708233328.AC29EEEBA6@mail.python.org> Message-ID: <201007090229.17476.victor.stinner@haypocalc.com> Le vendredi 09 juillet 2010 01:33:28, victor.stinner a ?crit : > Author: victor.stinner > Date: Fri Jul 9 01:33:28 2010 > New Revision: 82716 > > Log: > ceval: remove filename debug variable > > _PyUnicode_AsString() may raise an exception Another solution is to store and then restore the exception (eg. as does mywrite()) and set filename to NULL on error. -- Victor Stinner http://www.haypocalc.com/ From nnorwitz at gmail.com Fri Jul 9 02:56:33 2010 From: nnorwitz at gmail.com (Neal Norwitz) Date: Thu, 8 Jul 2010 20:56:33 -0400 Subject: [Python-checkins] Python Regression Test Failures refleak (1) Message-ID: <20100709005633.GA15572@kbk-i386-bb.psfb.org> More important issues: ---------------------- test_format leaked [0, 60, 0] references, sum=60 Less important issues: ---------------------- From python-checkins at python.org Fri Jul 9 03:58:26 2010 From: python-checkins at python.org (benjamin.peterson) Date: Fri, 9 Jul 2010 03:58:26 +0200 (CEST) Subject: [Python-checkins] r82723 - python/branches/py3k/Lib/test/test_structseq.py Message-ID: <20100709015826.8797FEE988@mail.python.org> Author: benjamin.peterson Date: Fri Jul 9 03:58:26 2010 New Revision: 82723 Log: use assert method Modified: python/branches/py3k/Lib/test/test_structseq.py Modified: python/branches/py3k/Lib/test/test_structseq.py ============================================================================== --- python/branches/py3k/Lib/test/test_structseq.py (original) +++ python/branches/py3k/Lib/test/test_structseq.py Fri Jul 9 03:58:26 2010 @@ -8,7 +8,7 @@ def test_tuple(self): t = time.gmtime() - assert isinstance(t, tuple) + self.assertIsInstance(t, tuple) astuple = tuple(t) self.assertEqual(len(t), len(astuple)) self.assertEqual(t, astuple) From g.brandl at gmx.net Fri Jul 9 09:09:43 2010 From: g.brandl at gmx.net (Georg Brandl) Date: Fri, 09 Jul 2010 09:09:43 +0200 Subject: [Python-checkins] r82659 - in python/branches/py3k: Doc/library/os.path.rst Doc/library/os.rst Lib/ntpath.py Lib/tarfile.py Lib/test/support.py Lib/test/symlink_support.py Lib/test/test_glob.py Lib/test/test_httpservers.py Lib/test/test_os.py Lib/test/test_platform.py Lib/test/test_posixpath.py Lib/test/test_shutil.py Lib/test/test_sys.py Lib/test/test_sysconfig.py Lib/test/test_tarfile.py Misc/ACKS Misc/NEWS Modules/posixmodule.c In-Reply-To: <20100708213909.4B34DD267@mail.python.org> References: <20100708213909.4B34DD267@mail.python.org> Message-ID: Am 08.07.2010 23:39, schrieb brian.curtin: > Author: brian.curtin > Date: Thu Jul 8 23:39:08 2010 > New Revision: 82659 > > Log: > Implement #1578269. Patch by Jason R. Coombs. > > Added Windows support for os.symlink when run on Windows 6.0 or greater, > aka Vista. Previous Windows versions will raise NotImplementedError > when trying to symlink. > > Includes numerous test updates and additions to test_os, including > a symlink_support module because of the fact that privilege escalation > is required in order to run the tests to ensure that the user is able > to create symlinks. By default, accounts do not have the required > privilege, so the escalation code will have to be exposed later (or > documented on how to do so). I'll be following up with that work next. > > Note that the tests use ctypes, which was agreed on during the PyCon > language summit. > > > > Added: > python/branches/py3k/Lib/test/symlink_support.py (contents, props changed) > Modified: > python/branches/py3k/Doc/library/os.path.rst > python/branches/py3k/Doc/library/os.rst > python/branches/py3k/Lib/ntpath.py > python/branches/py3k/Lib/tarfile.py > python/branches/py3k/Lib/test/support.py > python/branches/py3k/Lib/test/test_glob.py > python/branches/py3k/Lib/test/test_httpservers.py > python/branches/py3k/Lib/test/test_os.py > python/branches/py3k/Lib/test/test_platform.py > python/branches/py3k/Lib/test/test_posixpath.py > python/branches/py3k/Lib/test/test_shutil.py > python/branches/py3k/Lib/test/test_sys.py > python/branches/py3k/Lib/test/test_sysconfig.py > python/branches/py3k/Lib/test/test_tarfile.py > python/branches/py3k/Misc/ACKS > python/branches/py3k/Misc/NEWS > python/branches/py3k/Modules/posixmodule.c > > Modified: python/branches/py3k/Doc/library/os.path.rst > ============================================================================== > --- python/branches/py3k/Doc/library/os.path.rst (original) > +++ python/branches/py3k/Doc/library/os.path.rst Thu Jul 8 23:39:08 2010 > @@ -231,11 +231,15 @@ > > .. function:: samefile(path1, path2) > > - Return ``True`` if both pathname arguments refer to the same file or directory > - (as indicated by device number and i-node number). Raise an exception if a > - :func:`os.stat` call on either pathname fails. > + Return ``True`` if both pathname arguments refer to the same file or directory. > + On Unix, this is determined by the device number and i-node number and raises an > + exception if a :func:`os.stat` call on either pathname fails. > + > + On Windows, two files are the same if they resolve to the same final path > + name using the Windows API call GetFinalPathNameByHandle and this function > + raises an exception if handles cannot be obtained to either file. > > - Availability: Unix. > + Availability: Windows, Unix. There is a ".. versionchanged" missing here (and in the other places where Windows availability was added). > Modified: python/branches/py3k/Lib/tarfile.py > ============================================================================== > --- python/branches/py3k/Lib/tarfile.py (original) > +++ python/branches/py3k/Lib/tarfile.py Thu Jul 8 23:39:08 2010 > @@ -2273,7 +2273,7 @@ > (platform limitation), we try to make a copy of the referenced file > instead of a link. > """ > - if hasattr(os, "symlink") and hasattr(os, "link"): > + try: > # For systems that support symbolic and hard links. > if tarinfo.issym(): > os.symlink(tarinfo.linkname, targetpath) > @@ -2282,7 +2282,15 @@ > if os.path.exists(tarinfo._link_target): > os.link(tarinfo._link_target, targetpath) > else: > - self._extract_member(self._find_link_target(tarinfo), targetpath) > + self._extract_mem > + except (AttributeError, NotImplementedError, WindowsError): > + # AttributeError if no os.symlink > + # NotImplementedError if on Windows XP > + # WindowsError (1314) if the required privilege is not held by the client > + if tarinfo.issym(): > + linkpath = os.path.join(os.path.dirname(tarinfo.name),tarinfo.linkname) > + else: > + linkpath = tarinfo.linkname > else: > try: > self._extract_member(self._find_link_target(tarinfo), targetpath) Please observe PEP 8 (no overlong lines, space after comma). (I also see overlong lines in other files in the diff.) > Modified: python/branches/py3k/Misc/ACKS > ============================================================================== > --- python/branches/py3k/Misc/ACKS (original) > +++ python/branches/py3k/Misc/ACKS Thu Jul 8 23:39:08 2010 > @@ -154,6 +154,7 @@ > Jeffery Collins > Robert Collins > Paul Colomiets > +Jason R. Coombs > Geremy Condra > Juan Jos? Conti > Matt Conway This doesn't seem to be the correct ordering :) Georg -- Thus spake the Lord: Thou shalt indent with four spaces. No more, no less. Four shall be the number of spaces thou shalt indent, and the number of thy indenting shall be four. Eight shalt thou not indent, nor either indent thou two, excepting that thou then proceed to four. Tabs are right out. From python-checkins at python.org Fri Jul 9 09:33:15 2010 From: python-checkins at python.org (georg.brandl) Date: Fri, 9 Jul 2010 09:33:15 +0200 (CEST) Subject: [Python-checkins] r82724 - python/branches/py3k/Doc/tools/sphinxext/indexsidebar.html Message-ID: <20100709073315.AD349EE985@mail.python.org> Author: georg.brandl Date: Fri Jul 9 09:33:15 2010 New Revision: 82724 Log: 2.7 is now stable. Modified: python/branches/py3k/Doc/tools/sphinxext/indexsidebar.html Modified: python/branches/py3k/Doc/tools/sphinxext/indexsidebar.html ============================================================================== --- python/branches/py3k/Doc/tools/sphinxext/indexsidebar.html (original) +++ python/branches/py3k/Doc/tools/sphinxext/indexsidebar.html Fri Jul 9 09:33:15 2010 @@ -2,8 +2,7 @@

    Download these documents

    Docs for other versions

    From python-checkins at python.org Fri Jul 9 09:38:13 2010 From: python-checkins at python.org (georg.brandl) Date: Fri, 9 Jul 2010 09:38:13 +0200 (CEST) Subject: [Python-checkins] r82725 - python/branches/release27-maint Message-ID: <20100709073813.45386EE99D@mail.python.org> Author: georg.brandl Date: Fri Jul 9 09:38:13 2010 New Revision: 82725 Log: Recorded merge of revisions 82724 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ........ r82724 | georg.brandl | 2010-07-09 09:33:15 +0200 (Fr, 09 Jul 2010) | 1 line 2.7 is now stable. ........ Modified: python/branches/release27-maint/ (props changed) From python-checkins at python.org Fri Jul 9 09:42:13 2010 From: python-checkins at python.org (georg.brandl) Date: Fri, 9 Jul 2010 09:42:13 +0200 (CEST) Subject: [Python-checkins] r82726 - python/branches/release26-maint/Doc/tools/sphinxext/indexsidebar.html Message-ID: <20100709074213.8EF53EE9A5@mail.python.org> Author: georg.brandl Date: Fri Jul 9 09:42:13 2010 New Revision: 82726 Log: 2.7 is stable now. Modified: python/branches/release26-maint/Doc/tools/sphinxext/indexsidebar.html Modified: python/branches/release26-maint/Doc/tools/sphinxext/indexsidebar.html ============================================================================== --- python/branches/release26-maint/Doc/tools/sphinxext/indexsidebar.html (original) +++ python/branches/release26-maint/Doc/tools/sphinxext/indexsidebar.html Fri Jul 9 09:42:13 2010 @@ -2,7 +2,7 @@

    Download these documents

    Docs for other versions