From python-checkins at python.org Tue Jun 1 00:57:25 2010 From: python-checkins at python.org (r.david.murray) Date: Tue, 1 Jun 2010 00:57:25 +0200 (CEST) Subject: [Python-checkins] r81626 - in python/branches/release26-maint: Doc/extending/newtypes.rst Message-ID: <20100531225725.28F08EE988@mail.python.org> Author: r.david.murray Date: Tue Jun 1 00:57:24 2010 New Revision: 81626 Log: Merged revisions 81586 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81586 | r.david.murray | 2010-05-28 14:08:11 -0400 (Fri, 28 May 2010) | 2 lines Make reference to Generic Attribute Management a hyperlink. ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Doc/extending/newtypes.rst Modified: python/branches/release26-maint/Doc/extending/newtypes.rst ============================================================================== --- python/branches/release26-maint/Doc/extending/newtypes.rst (original) +++ python/branches/release26-maint/Doc/extending/newtypes.rst Tue Jun 1 00:57:24 2010 @@ -446,7 +446,7 @@ Noddy_members, /* tp_members */ Each member definition has a member name, type, offset, access flags and -documentation string. See the "Generic Attribute Management" section below for +documentation string. See the :ref:`Generic-Attribute-Management` section below for details. A disadvantage of this approach is that it doesn't provide a way to restrict the @@ -1129,6 +1129,8 @@ not been updated to use some of the new generic mechanism that is available. +.. _generic-attribute-management: + Generic Attribute Management ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From python-checkins at python.org Tue Jun 1 01:06:41 2010 From: python-checkins at python.org (r.david.murray) Date: Tue, 1 Jun 2010 01:06:41 +0200 (CEST) Subject: [Python-checkins] r81627 - python/branches/release26-maint Message-ID: <20100531230641.AF813EE999@mail.python.org> Author: r.david.murray Date: Tue Jun 1 01:06:41 2010 New Revision: 81627 Log: Blocked revisions 81587 via svnmerge ........ r81587 | r.david.murray | 2010-05-28 14:17:20 -0400 (Fri, 28 May 2010) | 2 lines Make the ctl-C shutdown of serve.py prettier. ........ Modified: python/branches/release26-maint/ (props changed) From solipsis at pitrou.net Tue Jun 1 01:23:40 2010 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Tue, 1 Jun 2010 01:23:40 +0200 (CEST) Subject: [Python-checkins] Daily py3k reference leaks (r81625): sum=0 Message-ID: <20100531232340.506D11770A@ns6635.ovh.net> py3k results for svn r81625 (hg cset d3879c2afa33) -------------------------------------------------- Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/py3k/refleaks/reflog2jS3Oo', '-x'] From python-checkins at python.org Tue Jun 1 01:23:50 2010 From: python-checkins at python.org (r.david.murray) Date: Tue, 1 Jun 2010 01:23:50 +0200 (CEST) Subject: [Python-checkins] r81628 - in python/branches/py3k: Tools/scripts/serve.py Message-ID: <20100531232350.5E030EE9F0@mail.python.org> Author: r.david.murray Date: Tue Jun 1 01:23:50 2010 New Revision: 81628 Log: Merged revisions 81587 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81587 | r.david.murray | 2010-05-28 14:17:20 -0400 (Fri, 28 May 2010) | 2 lines Make the ctl-C shutdown of serve.py prettier. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Tools/scripts/serve.py Modified: python/branches/py3k/Tools/scripts/serve.py ============================================================================== --- python/branches/py3k/Tools/scripts/serve.py (original) +++ python/branches/py3k/Tools/scripts/serve.py Tue Jun 1 01:23:50 2010 @@ -28,5 +28,8 @@ path = sys.argv[1] port = int(sys.argv[2]) if len(sys.argv) > 2 else 8000 httpd = simple_server.make_server('', port, app) - print("Serving {} on port {}".format(path, port)) - httpd.serve_forever() + print("Serving {} on port {}, control-C to stop".format(path, port)) + try: + httpd.serve_forever() + except KeyboardInterrupt: + print("\b\bShutting down.") From python-checkins at python.org Tue Jun 1 03:04:16 2010 From: python-checkins at python.org (r.david.murray) Date: Tue, 1 Jun 2010 03:04:16 +0200 (CEST) Subject: [Python-checkins] r81629 - python/branches/release31-maint Message-ID: <20100601010416.51DE9EE9B5@mail.python.org> Author: r.david.murray Date: Tue Jun 1 03:04:14 2010 New Revision: 81629 Log: Blocked revisions 81628 via svnmerge ................ r81628 | r.david.murray | 2010-05-31 19:23:50 -0400 (Mon, 31 May 2010) | 9 lines Merged revisions 81587 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81587 | r.david.murray | 2010-05-28 14:17:20 -0400 (Fri, 28 May 2010) | 2 lines Make the ctl-C shutdown of serve.py prettier. ........ ................ Modified: python/branches/release31-maint/ (props changed) From python-checkins at python.org Tue Jun 1 03:11:18 2010 From: python-checkins at python.org (r.david.murray) Date: Tue, 1 Jun 2010 03:11:18 +0200 (CEST) Subject: [Python-checkins] r81630 - in python/branches/py3k: Doc/extending/newtypes.rst Message-ID: <20100601011118.4163AEE9A4@mail.python.org> Author: r.david.murray Date: Tue Jun 1 03:11:18 2010 New Revision: 81630 Log: Merged revisions 81586 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81586 | r.david.murray | 2010-05-28 14:08:11 -0400 (Fri, 28 May 2010) | 2 lines Make reference to Generic Attribute Management a hyperlink. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Doc/extending/newtypes.rst Modified: python/branches/py3k/Doc/extending/newtypes.rst ============================================================================== --- python/branches/py3k/Doc/extending/newtypes.rst (original) +++ python/branches/py3k/Doc/extending/newtypes.rst Tue Jun 1 03:11:18 2010 @@ -430,7 +430,7 @@ Noddy_members, /* tp_members */ Each member definition has a member name, type, offset, access flags and -documentation string. See the "Generic Attribute Management" section below for +documentation string. See the :ref:`Generic-Attribute-Management` section below for details. A disadvantage of this approach is that it doesn't provide a way to restrict the @@ -1078,6 +1078,8 @@ not been updated to use some of the new generic mechanism that is available. +.. _generic-attribute-management: + Generic Attribute Management ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From python-checkins at python.org Tue Jun 1 03:12:24 2010 From: python-checkins at python.org (r.david.murray) Date: Tue, 1 Jun 2010 03:12:24 +0200 (CEST) Subject: [Python-checkins] r81631 - in python/branches/release31-maint: Doc/extending/newtypes.rst Message-ID: <20100601011224.76AECEE9A4@mail.python.org> Author: r.david.murray Date: Tue Jun 1 03:12:24 2010 New Revision: 81631 Log: Merged revisions 81630 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ................ r81630 | r.david.murray | 2010-05-31 21:11:18 -0400 (Mon, 31 May 2010) | 9 lines Merged revisions 81586 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81586 | r.david.murray | 2010-05-28 14:08:11 -0400 (Fri, 28 May 2010) | 2 lines Make reference to Generic Attribute Management a hyperlink. ........ ................ Modified: python/branches/release31-maint/ (props changed) python/branches/release31-maint/Doc/extending/newtypes.rst Modified: python/branches/release31-maint/Doc/extending/newtypes.rst ============================================================================== --- python/branches/release31-maint/Doc/extending/newtypes.rst (original) +++ python/branches/release31-maint/Doc/extending/newtypes.rst Tue Jun 1 03:12:24 2010 @@ -430,7 +430,7 @@ Noddy_members, /* tp_members */ Each member definition has a member name, type, offset, access flags and -documentation string. See the "Generic Attribute Management" section below for +documentation string. See the :ref:`Generic-Attribute-Management` section below for details. A disadvantage of this approach is that it doesn't provide a way to restrict the @@ -1078,6 +1078,8 @@ not been updated to use some of the new generic mechanism that is available. +.. _generic-attribute-management: + Generic Attribute Management ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From python-checkins at python.org Tue Jun 1 03:32:12 2010 From: python-checkins at python.org (r.david.murray) Date: Tue, 1 Jun 2010 03:32:12 +0200 (CEST) Subject: [Python-checkins] r81632 - in python/branches/py3k: Doc/library/sqlite3.rst Doc/whatsnew/3.2.rst Lib/sqlite3/test/dbapi.py Misc/ACKS Misc/NEWS Modules/_sqlite/connection.c Message-ID: <20100601013212.5F6EBEE983@mail.python.org> Author: r.david.murray Date: Tue Jun 1 03:32:12 2010 New Revision: 81632 Log: #8845: expose sqlite3 inTransaction as RO in_transaction Connection attribute. Patch by R. David Murray, unit tests by Shashwat Anand. Modified: python/branches/py3k/Doc/library/sqlite3.rst python/branches/py3k/Doc/whatsnew/3.2.rst python/branches/py3k/Lib/sqlite3/test/dbapi.py python/branches/py3k/Misc/ACKS python/branches/py3k/Misc/NEWS python/branches/py3k/Modules/_sqlite/connection.c Modified: python/branches/py3k/Doc/library/sqlite3.rst ============================================================================== --- python/branches/py3k/Doc/library/sqlite3.rst (original) +++ python/branches/py3k/Doc/library/sqlite3.rst Tue Jun 1 03:32:12 2010 @@ -227,6 +227,13 @@ one of "DEFERRED", "IMMEDIATE" or "EXCLUSIVE". See section :ref:`sqlite3-controlling-transactions` for a more detailed explanation. +.. attribute:: Connection.in_transaction + + .. versionadded:: 3.2 + + :cont:`True` if a transaction is active (there are uncommitted changes), + :const:`False` otherwise. Read-only attribute. + .. method:: Connection.cursor([cursorClass]) @@ -806,7 +813,8 @@ before executing that command. There are two reasons for doing that. The first is that some of these commands don't work within transactions. The other reason is that sqlite3 needs to keep track of the transaction state (if a transaction -is active or not). +is active or not). The current transaction state is exposed through the +:attr:`Connection.in_transaction` attribute of the connection object. You can control which kind of ``BEGIN`` statements sqlite3 implicitly executes (or none at all) via the *isolation_level* parameter to the :func:`connect` Modified: python/branches/py3k/Doc/whatsnew/3.2.rst ============================================================================== --- python/branches/py3k/Doc/whatsnew/3.2.rst (original) +++ python/branches/py3k/Doc/whatsnew/3.2.rst Tue Jun 1 03:32:12 2010 @@ -100,6 +100,18 @@ (Contributed by Tarek Ziade.) +* The *sqlite3* module has some new features: + + * XXX *enable_load_extension* + + * XXX *load_extension* + + * New :class:`~sqlite3.Connection` attribute + :attr:`~sqlite3.Connection.in_transaction` is :const:`True` when there + are uncommitted changes, and :const:`False` otherwise. (Contributed + by R. David Murray and Shashwat Anand, :issue:`8845`.) + + Multi-threading =============== Modified: python/branches/py3k/Lib/sqlite3/test/dbapi.py ============================================================================== --- python/branches/py3k/Lib/sqlite3/test/dbapi.py (original) +++ python/branches/py3k/Lib/sqlite3/test/dbapi.py Tue Jun 1 03:32:12 2010 @@ -84,6 +84,7 @@ "NotSupportedError is not a subclass of DatabaseError") class ConnectionTests(unittest.TestCase): + def setUp(self): self.cx = sqlite.connect(":memory:") cu = self.cx.cursor() @@ -140,6 +141,28 @@ self.assertEqual(self.cx.ProgrammingError, sqlite.ProgrammingError) self.assertEqual(self.cx.NotSupportedError, sqlite.NotSupportedError) + def CheckInTransaction(self): + # Can't use db from setUp because we want to test initial state. + cx = sqlite.connect(":memory:") + cu = cx.cursor() + self.assertEqual(cx.in_transaction, False) + cu.execute("create table transactiontest(id integer primary key, name text)") + self.assertEqual(cx.in_transaction, False) + cu.execute("insert into transactiontest(name) values (?)", ("foo",)) + self.assertEqual(cx.in_transaction, True) + cu.execute("select name from transactiontest where name=?", ["foo"]) + row = cu.fetchone() + self.assertEqual(cx.in_transaction, True) + cx.commit() + self.assertEqual(cx.in_transaction, False) + cu.execute("select name from transactiontest where name=?", ["foo"]) + row = cu.fetchone() + self.assertEqual(cx.in_transaction, False) + + def CheckInTransactionRO(self): + with self.assertRaises(AttributeError): + self.cx.in_transaction = True + class CursorTests(unittest.TestCase): def setUp(self): self.cx = sqlite.connect(":memory:") Modified: python/branches/py3k/Misc/ACKS ============================================================================== --- python/branches/py3k/Misc/ACKS (original) +++ python/branches/py3k/Misc/ACKS Tue Jun 1 03:32:12 2010 @@ -19,6 +19,7 @@ Kevin Altis Joe Amenta Mark Anacker +Shashwat Anand Anders Andersen John Anderson Erik Anders?n Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Tue Jun 1 03:32:12 2010 @@ -398,6 +398,9 @@ Library ------- +- Issue #8845: sqlite3 Connection objects now have a read-only in_transaction + attribute that is True iff there are uncommitted changes. + - Issue #1289118: datetime.timedelta objects can now be multiplied by float and divided by float and int objects. Results are rounded to the nearest multiple of timedelta.resolution with ties resolved using round-half-to-even Modified: python/branches/py3k/Modules/_sqlite/connection.c ============================================================================== --- python/branches/py3k/Modules/_sqlite/connection.c (original) +++ python/branches/py3k/Modules/_sqlite/connection.c Tue Jun 1 03:32:12 2010 @@ -23,6 +23,7 @@ #include "cache.h" #include "module.h" +#include "structmember.h" #include "connection.h" #include "statement.h" #include "cursor.h" @@ -1551,6 +1552,7 @@ {"NotSupportedError", T_OBJECT, offsetof(pysqlite_Connection, NotSupportedError), READONLY}, {"row_factory", T_OBJECT, offsetof(pysqlite_Connection, row_factory)}, {"text_factory", T_OBJECT, offsetof(pysqlite_Connection, text_factory)}, + {"in_transaction", T_BOOL, offsetof(pysqlite_Connection, inTransaction), READONLY}, {NULL} }; From python-checkins at python.org Tue Jun 1 03:33:31 2010 From: python-checkins at python.org (r.david.murray) Date: Tue, 1 Jun 2010 03:33:31 +0200 (CEST) Subject: [Python-checkins] r81633 - python/branches/release31-maint Message-ID: <20100601013331.6E871EE983@mail.python.org> Author: r.david.murray Date: Tue Jun 1 03:33:31 2010 New Revision: 81633 Log: Blocked revisions 81632 via svnmerge ........ r81632 | r.david.murray | 2010-05-31 21:32:12 -0400 (Mon, 31 May 2010) | 4 lines #8845: expose sqlite3 inTransaction as RO in_transaction Connection attribute. Patch by R. David Murray, unit tests by Shashwat Anand. ........ Modified: python/branches/release31-maint/ (props changed) From python-checkins at python.org Tue Jun 1 03:42:41 2010 From: python-checkins at python.org (r.david.murray) Date: Tue, 1 Jun 2010 03:42:41 +0200 (CEST) Subject: [Python-checkins] r81634 - python/trunk/Doc/library/doctest.rst Message-ID: <20100601014241.D221DEE9AE@mail.python.org> Author: r.david.murray Date: Tue Jun 1 03:42:41 2010 New Revision: 81634 Log: #7583: clarify discussion of hard tab expansion in doctests. Modified: python/trunk/Doc/library/doctest.rst Modified: python/trunk/Doc/library/doctest.rst ============================================================================== --- python/trunk/Doc/library/doctest.rst (original) +++ python/trunk/Doc/library/doctest.rst Tue Jun 1 03:42:41 2010 @@ -299,15 +299,8 @@ How are Docstring Examples Recognized? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -In most cases a copy-and-paste of an interactive console session works fine, but -doctest isn't trying to do an exact emulation of any specific Python shell. All -hard tab characters are expanded to spaces, using 8-column tab stops. If you -don't believe tabs should mean that, too bad: don't use hard tabs, or write -your own :class:`DocTestParser` class. - -.. versionchanged:: 2.4 - Expanding tabs to spaces is new; previous versions tried to preserve hard tabs, - with confusing results. +In most cases a copy-and-paste of an interactive console session works fine, +but doctest isn't trying to do an exact emulation of any specific Python shell. :: @@ -342,6 +335,21 @@ ```` was added; there was no way to use expected output containing empty lines in previous versions. +* All hard tab characters are expanded to spaces, using 8-column tab stops. + Tabs in output generated by the tested code are not modified. Because any + hard tabs in the sample output *are* expanded, this means that if the code + output includes hard tabs, the only way the doctest can pass is if the + :const:`NORMALIZE_WHITESPACE` option or directive is in effect. + Alternatively, the test can be rewritten to capture the output and compare it + to an expected value as part of the test. This handling of tabs in the + source was arrived at through trial and error, and has proven to be the least + error prone way of handling them. It is possible to use a different + algorithm for handling tabs by writing a custom :class:`DocTestParser` class. + + .. versionchanged:: 2.4 + Expanding tabs to spaces is new; previous versions tried to preserve hard tabs, + with confusing results. + * Output to stdout is captured, but not output to stderr (exception tracebacks are captured via a different means). @@ -1872,4 +1880,3 @@ .. [#] Examples containing both expected output and an exception are not supported. Trying to guess where one ends and the other begins is too error-prone, and that also makes for a confusing test. - From python-checkins at python.org Tue Jun 1 09:25:23 2010 From: python-checkins at python.org (georg.brandl) Date: Tue, 1 Jun 2010 09:25:23 +0200 (CEST) Subject: [Python-checkins] r81635 - python/trunk/Doc/library/re.rst Message-ID: <20100601072523.4F22EEE98C@mail.python.org> Author: georg.brandl Date: Tue Jun 1 09:25:23 2010 New Revision: 81635 Log: Put docs for RegexObject.search() before RegexObject.match() to mirror re.search() and re.match() order. Modified: python/trunk/Doc/library/re.rst Modified: python/trunk/Doc/library/re.rst ============================================================================== --- python/trunk/Doc/library/re.rst (original) +++ python/trunk/Doc/library/re.rst Tue Jun 1 09:25:23 2010 @@ -689,18 +689,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 @@ -712,24 +706,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]) From python-checkins at python.org Tue Jun 1 14:40:07 2010 From: python-checkins at python.org (senthil.kumaran) Date: Tue, 1 Jun 2010 14:40:07 +0200 (CEST) Subject: [Python-checkins] r81636 - in python/trunk/Lib: test/test_urllib2.py urllib2.py Message-ID: <20100601124007.DE6FBF004@mail.python.org> Author: senthil.kumaran Date: Tue Jun 1 14:40:07 2010 New Revision: 81636 Log: Fix Issue8797 - urllib2 basic authentication fix for wrong passwords. It fails after 5 retries. Modified: python/trunk/Lib/test/test_urllib2.py python/trunk/Lib/urllib2.py Modified: python/trunk/Lib/test/test_urllib2.py ============================================================================== --- python/trunk/Lib/test/test_urllib2.py (original) +++ python/trunk/Lib/test/test_urllib2.py Tue Jun 1 14:40:07 2010 @@ -1143,7 +1143,6 @@ self.assertEqual(len(http_handler.requests), 1) self.assertFalse(http_handler.requests[0].has_header(auth_header)) - class MiscTests(unittest.TestCase): def test_build_opener(self): Modified: python/trunk/Lib/urllib2.py ============================================================================== --- python/trunk/Lib/urllib2.py (original) +++ python/trunk/Lib/urllib2.py Tue Jun 1 14:40:07 2010 @@ -819,12 +819,21 @@ password_mgr = HTTPPasswordMgr() self.passwd = password_mgr self.add_password = self.passwd.add_password + self.retried = 0 def http_error_auth_reqed(self, authreq, host, req, headers): # host may be an authority (without userinfo) or a URL with an # authority # XXX could be multiple headers authreq = headers.get(authreq, None) + + if self.retried > 5: + # retry sending the username:password 5 times before failing. + raise HTTPError(req.get_full_url(), 401, "basic auth failed", + headers, None) + else: + self.retried += 1 + if authreq: mo = AbstractBasicAuthHandler.rx.search(authreq) if mo: From python-checkins at python.org Tue Jun 1 14:42:45 2010 From: python-checkins at python.org (senthil.kumaran) Date: Tue, 1 Jun 2010 14:42:45 +0200 (CEST) Subject: [Python-checkins] r81637 - in python/branches/release26-maint: Lib/test/test_urllib2.py Lib/urllib2.py Message-ID: <20100601124245.244A6F079@mail.python.org> Author: senthil.kumaran Date: Tue Jun 1 14:42:44 2010 New Revision: 81637 Log: Merged revisions 81636 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81636 | senthil.kumaran | 2010-06-01 18:10:07 +0530 (Tue, 01 Jun 2010) | 3 lines Fix Issue8797 - urllib2 basic authentication fix for wrong passwords. It fails after 5 retries. ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Lib/test/test_urllib2.py python/branches/release26-maint/Lib/urllib2.py Modified: python/branches/release26-maint/Lib/test/test_urllib2.py ============================================================================== --- python/branches/release26-maint/Lib/test/test_urllib2.py (original) +++ python/branches/release26-maint/Lib/test/test_urllib2.py Tue Jun 1 14:42:44 2010 @@ -1145,7 +1145,6 @@ self.assertEqual(len(http_handler.requests), 1) self.assertFalse(http_handler.requests[0].has_header(auth_header)) - class MiscTests(unittest.TestCase): def test_build_opener(self): Modified: python/branches/release26-maint/Lib/urllib2.py ============================================================================== --- python/branches/release26-maint/Lib/urllib2.py (original) +++ python/branches/release26-maint/Lib/urllib2.py Tue Jun 1 14:42:44 2010 @@ -819,12 +819,21 @@ password_mgr = HTTPPasswordMgr() self.passwd = password_mgr self.add_password = self.passwd.add_password + self.retried = 0 def http_error_auth_reqed(self, authreq, host, req, headers): # host may be an authority (without userinfo) or a URL with an # authority # XXX could be multiple headers authreq = headers.get(authreq, None) + + if self.retried > 5: + # retry sending the username:password 5 times before failing. + raise HTTPError(req.get_full_url(), 401, "basic auth failed", + headers, None) + else: + self.retried += 1 + if authreq: mo = AbstractBasicAuthHandler.rx.search(authreq) if mo: From python-checkins at python.org Tue Jun 1 14:53:48 2010 From: python-checkins at python.org (senthil.kumaran) Date: Tue, 1 Jun 2010 14:53:48 +0200 (CEST) Subject: [Python-checkins] r81638 - in python/branches/py3k: Lib/test/test_urllib2.py Lib/urllib/request.py Message-ID: <20100601125348.613CDEE981@mail.python.org> Author: senthil.kumaran Date: Tue Jun 1 14:53:48 2010 New Revision: 81638 Log: Merged revisions 81636 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81636 | senthil.kumaran | 2010-06-01 18:10:07 +0530 (Tue, 01 Jun 2010) | 3 lines Fix Issue8797 - urllib2 basic authentication fix for wrong passwords. It fails after 5 retries. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/test/test_urllib2.py python/branches/py3k/Lib/urllib/request.py Modified: python/branches/py3k/Lib/test/test_urllib2.py ============================================================================== --- python/branches/py3k/Lib/test/test_urllib2.py (original) +++ python/branches/py3k/Lib/test/test_urllib2.py Tue Jun 1 14:53:48 2010 @@ -1151,7 +1151,6 @@ self.assertEqual(len(http_handler.requests), 1) self.assertFalse(http_handler.requests[0].has_header(auth_header)) - class MiscTests(unittest.TestCase): def test_build_opener(self): Modified: python/branches/py3k/Lib/urllib/request.py ============================================================================== --- python/branches/py3k/Lib/urllib/request.py (original) +++ python/branches/py3k/Lib/urllib/request.py Tue Jun 1 14:53:48 2010 @@ -775,12 +775,21 @@ password_mgr = HTTPPasswordMgr() self.passwd = password_mgr self.add_password = self.passwd.add_password + self.retried = 0 def http_error_auth_reqed(self, authreq, host, req, headers): # host may be an authority (without userinfo) or a URL with an # authority # XXX could be multiple headers authreq = headers.get(authreq, None) + + if self.retried > 5: + # retry sending the username:password 5 times before failing. + raise HTTPError(req.get_full_url(), 401, "basic auth failed", + headers, None) + else: + self.retried += 1 + if authreq: mo = AbstractBasicAuthHandler.rx.search(authreq) if mo: From python-checkins at python.org Tue Jun 1 14:56:17 2010 From: python-checkins at python.org (senthil.kumaran) Date: Tue, 1 Jun 2010 14:56:17 +0200 (CEST) Subject: [Python-checkins] r81639 - in python/branches/release31-maint: Lib/test/test_urllib2.py Lib/urllib/request.py Message-ID: <20100601125617.D7E2CDCC3@mail.python.org> Author: senthil.kumaran Date: Tue Jun 1 14:56:17 2010 New Revision: 81639 Log: Merged revisions 81638 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ................ r81638 | senthil.kumaran | 2010-06-01 18:23:48 +0530 (Tue, 01 Jun 2010) | 9 lines Merged revisions 81636 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81636 | senthil.kumaran | 2010-06-01 18:10:07 +0530 (Tue, 01 Jun 2010) | 3 lines Fix Issue8797 - urllib2 basic authentication fix for wrong passwords. It fails after 5 retries. ........ ................ Modified: python/branches/release31-maint/ (props changed) python/branches/release31-maint/Lib/test/test_urllib2.py python/branches/release31-maint/Lib/urllib/request.py Modified: python/branches/release31-maint/Lib/test/test_urllib2.py ============================================================================== --- python/branches/release31-maint/Lib/test/test_urllib2.py (original) +++ python/branches/release31-maint/Lib/test/test_urllib2.py Tue Jun 1 14:56:17 2010 @@ -1156,7 +1156,6 @@ self.assertEqual(len(http_handler.requests), 1) self.assertFalse(http_handler.requests[0].has_header(auth_header)) - class MiscTests(unittest.TestCase): def test_build_opener(self): Modified: python/branches/release31-maint/Lib/urllib/request.py ============================================================================== --- python/branches/release31-maint/Lib/urllib/request.py (original) +++ python/branches/release31-maint/Lib/urllib/request.py Tue Jun 1 14:56:17 2010 @@ -775,12 +775,21 @@ password_mgr = HTTPPasswordMgr() self.passwd = password_mgr self.add_password = self.passwd.add_password + self.retried = 0 def http_error_auth_reqed(self, authreq, host, req, headers): # host may be an authority (without userinfo) or a URL with an # authority # XXX could be multiple headers authreq = headers.get(authreq, None) + + if self.retried > 5: + # retry sending the username:password 5 times before failing. + raise HTTPError(req.get_full_url(), 401, "basic auth failed", + headers, None) + else: + self.retried += 1 + if authreq: mo = AbstractBasicAuthHandler.rx.search(authreq) if mo: From python-checkins at python.org Tue Jun 1 15:29:13 2010 From: python-checkins at python.org (brian.curtin) Date: Tue, 1 Jun 2010 15:29:13 +0200 (CEST) Subject: [Python-checkins] r81640 - python/trunk/Lib/test/test_winsound.py Message-ID: <20100601132913.B7398EE981@mail.python.org> Author: brian.curtin Date: Tue Jun 1 15:29:13 2010 New Revision: 81640 Log: Fix #8618. Ask the Windows mixer API if there are any playback devices configured before attempting to test PlaySound. Modified: python/trunk/Lib/test/test_winsound.py Modified: python/trunk/Lib/test/test_winsound.py ============================================================================== --- python/trunk/Lib/test/test_winsound.py (original) +++ python/trunk/Lib/test/test_winsound.py Tue Jun 1 15:29:13 2010 @@ -5,6 +5,7 @@ import time import os import subprocess +import ctypes winsound = test_support.import_module('winsound') import _winreg @@ -12,6 +13,11 @@ def has_sound(sound): """Find out if a particular event is configured with a default sound""" try: + # Ask the mixer API for the number of devices it knows about. + # When there are no devices, PlaySound will fail. + if ctypes.windll.winmm.mixerGetNumDevs() is 0: + return False + key = _winreg.OpenKeyEx(_winreg.HKEY_CURRENT_USER, "AppEvents\Schemes\Apps\.Default\{0}\.Default".format(sound)) value = _winreg.EnumValue(key, 0)[1] From python-checkins at python.org Tue Jun 1 15:42:48 2010 From: python-checkins at python.org (brian.curtin) Date: Tue, 1 Jun 2010 15:42:48 +0200 (CEST) Subject: [Python-checkins] r81641 - in python/branches/release26-maint: Lib/test/test_winsound.py Message-ID: <20100601134248.6AE5CEE981@mail.python.org> Author: brian.curtin Date: Tue Jun 1 15:42:48 2010 New Revision: 81641 Log: Merged revisions 81640 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81640 | brian.curtin | 2010-06-01 08:29:13 -0500 (Tue, 01 Jun 2010) | 3 lines Fix #8618. Ask the Windows mixer API if there are any playback devices configured before attempting to test PlaySound. ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Lib/test/test_winsound.py Modified: python/branches/release26-maint/Lib/test/test_winsound.py ============================================================================== --- python/branches/release26-maint/Lib/test/test_winsound.py (original) +++ python/branches/release26-maint/Lib/test/test_winsound.py Tue Jun 1 15:42:48 2010 @@ -2,15 +2,23 @@ import unittest from test import test_support -import winsound, time +import time import os import subprocess +import ctypes + +winsound = test_support.import_module('winsound') import _winreg def has_sound(sound): """Find out if a particular event is configured with a default sound""" try: + # Ask the mixer API for the number of devices it knows about. + # When there are no devices, PlaySound will fail. + if ctypes.windll.winmm.mixerGetNumDevs() is 0: + return False + key = _winreg.OpenKeyEx(_winreg.HKEY_CURRENT_USER, "AppEvents\Schemes\Apps\.Default\{0}\.Default".format(sound)) value = _winreg.EnumValue(key, 0)[1] From python-checkins at python.org Tue Jun 1 15:49:19 2010 From: python-checkins at python.org (brian.curtin) Date: Tue, 1 Jun 2010 15:49:19 +0200 (CEST) Subject: [Python-checkins] r81642 - in python/branches/py3k: Lib/test/test_winsound.py Message-ID: <20100601134919.D87BEEE999@mail.python.org> Author: brian.curtin Date: Tue Jun 1 15:49:19 2010 New Revision: 81642 Log: Merged revisions 81640 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81640 | brian.curtin | 2010-06-01 08:29:13 -0500 (Tue, 01 Jun 2010) | 3 lines Fix #8618. Ask the Windows mixer API if there are any playback devices configured before attempting to test PlaySound. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/test/test_winsound.py Modified: python/branches/py3k/Lib/test/test_winsound.py ============================================================================== --- python/branches/py3k/Lib/test/test_winsound.py (original) +++ python/branches/py3k/Lib/test/test_winsound.py Tue Jun 1 15:49:19 2010 @@ -6,6 +6,7 @@ import time import os import subprocess +import ctypes winsound = support.import_module('winsound') import winreg @@ -13,6 +14,11 @@ def has_sound(sound): """Find out if a particular event is configured with a default sound""" try: + # Ask the mixer API for the number of devices it knows about. + # When there are no devices, PlaySound will fail. + if ctypes.windll.winmm.mixerGetNumDevs() is 0: + return False + key = winreg.OpenKeyEx(winreg.HKEY_CURRENT_USER, "AppEvents\Schemes\Apps\.Default\{0}\.Default".format(sound)) value = winreg.EnumValue(key, 0)[1] From python-checkins at python.org Tue Jun 1 15:52:18 2010 From: python-checkins at python.org (brian.curtin) Date: Tue, 1 Jun 2010 15:52:18 +0200 (CEST) Subject: [Python-checkins] r81643 - in python/branches/release31-maint: Lib/test/test_winsound.py Message-ID: <20100601135218.9FB9EEFE5@mail.python.org> Author: brian.curtin Date: Tue Jun 1 15:52:18 2010 New Revision: 81643 Log: Merged revisions 81642 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ................ r81642 | brian.curtin | 2010-06-01 08:49:19 -0500 (Tue, 01 Jun 2010) | 10 lines Merged revisions 81640 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81640 | brian.curtin | 2010-06-01 08:29:13 -0500 (Tue, 01 Jun 2010) | 3 lines Fix #8618. Ask the Windows mixer API if there are any playback devices configured before attempting to test PlaySound. ........ ................ Modified: python/branches/release31-maint/ (props changed) python/branches/release31-maint/Lib/test/test_winsound.py Modified: python/branches/release31-maint/Lib/test/test_winsound.py ============================================================================== --- python/branches/release31-maint/Lib/test/test_winsound.py (original) +++ python/branches/release31-maint/Lib/test/test_winsound.py Tue Jun 1 15:52:18 2010 @@ -6,6 +6,7 @@ import time import os import subprocess +import ctypes winsound = support.import_module('winsound') import winreg @@ -13,6 +14,11 @@ def has_sound(sound): """Find out if a particular event is configured with a default sound""" try: + # Ask the mixer API for the number of devices it knows about. + # When there are no devices, PlaySound will fail. + if ctypes.windll.winmm.mixerGetNumDevs() is 0: + return False + key = winreg.OpenKeyEx(winreg.HKEY_CURRENT_USER, "AppEvents\Schemes\Apps\.Default\{0}\.Default".format(sound)) value = winreg.EnumValue(key, 0)[1] From python-checkins at python.org Wed Jun 2 01:18:23 2010 From: python-checkins at python.org (tarek.ziade) Date: Wed, 02 Jun 2010 01:18:23 +0200 Subject: [Python-checkins] distutils2: Silence two py3k deprecation warnings and fix a bug. Message-ID: tarek.ziade pushed ce0d6be25d09 to distutils2: http://hg.python.org/distutils2/rev/ce0d6be25d09 changeset: 191:ce0d6be25d09 user: ?ric Araujo date: Mon May 31 23:03:46 2010 +0200 summary: Silence two py3k deprecation warnings and fix a bug. files: src/distutils2/tests/test_upload.py, src/distutils2/version.py diff --git a/src/distutils2/tests/test_upload.py b/src/distutils2/tests/test_upload.py --- a/src/distutils2/tests/test_upload.py +++ b/src/distutils2/tests/test_upload.py @@ -116,7 +116,7 @@ # what did we send ? self.assertIn('d??d??', self.last_open.req.data) headers = dict(self.last_open.req.headers) - self.assertTrue(headers['Content-length'] > 2000) + self.assertTrue(int(headers['Content-length']) < 2000) self.assertTrue(headers['Content-type'].startswith('multipart/form-data')) self.assertEquals(self.last_open.req.get_method(), 'POST') self.assertEquals(self.last_open.req.get_full_url(), diff --git a/src/distutils2/version.py b/src/distutils2/version.py --- a/src/distutils2/version.py +++ b/src/distutils2/version.py @@ -197,6 +197,9 @@ def __ge__(self, other): return self.__eq__(other) or self.__gt__(other) + # See http://docs.python.org/reference/datamodel#object.__hash__ + __hash__ = object.__hash__ + def suggest_normalized_version(s): """Suggest a normalized version close to the given version string. -- Repository URL: http://hg.python.org/distutils2 From python-checkins at python.org Wed Jun 2 01:18:23 2010 From: python-checkins at python.org (tarek.ziade) Date: Wed, 02 Jun 2010 01:18:23 +0200 Subject: [Python-checkins] distutils2: Use Mercurial command-line API instead of Python internals. Message-ID: tarek.ziade pushed 0e17b47e7ab2 to distutils2: http://hg.python.org/distutils2/rev/0e17b47e7ab2 changeset: 193:0e17b47e7ab2 user: ?ric Araujo date: Tue Jun 01 15:12:25 2010 +0200 summary: Use Mercurial command-line API instead of Python internals. files: src/setup.py diff --git a/src/setup.py b/src/setup.py --- a/src/setup.py +++ b/src/setup.py @@ -17,19 +17,17 @@ f.close() def get_tip_revision(path=os.getcwd()): + from subprocess import Popen, PIPE try: - from mercurial.hg import repository - from mercurial.ui import ui - from mercurial import node - from mercurial.error import RepoError - except ImportError: + cmd = Popen(['hg', 'tip', '--template', '{rev}', '-R', path], + stdout=PIPE, stderr=PIPE) + except OSError: return 0 - try: - repo = repository(ui(), path) - tip = repo.changelog.tip() - return repo.changelog.rev(tip) - except RepoError: + rev = cmd.stdout.read() + if rev == '': + # there has been an error in the command return 0 + return int(rev) DEV_SUFFIX = '.dev%d' % get_tip_revision('..') -- Repository URL: http://hg.python.org/distutils2 From python-checkins at python.org Wed Jun 2 01:18:23 2010 From: python-checkins at python.org (tarek.ziade) Date: Wed, 02 Jun 2010 01:18:23 +0200 Subject: [Python-checkins] distutils2: Ignore default build dir Message-ID: tarek.ziade pushed 9b2bfeed1630 to distutils2: http://hg.python.org/distutils2/rev/9b2bfeed1630 changeset: 189:9b2bfeed1630 parent: 160:30ad3af43b5f user: ?ric Araujo date: Sat May 29 15:53:10 2010 +0200 summary: Ignore default build dir files: .hgignore diff --git a/.hgignore b/.hgignore --- a/.hgignore +++ b/.hgignore @@ -1,5 +1,5 @@ .*\.pyc$ .*\.pyo$ +^src/build ^docs/build .*\.swp$ - -- Repository URL: http://hg.python.org/distutils2 From python-checkins at python.org Wed Jun 2 01:18:23 2010 From: python-checkins at python.org (tarek.ziade) Date: Wed, 02 Jun 2010 01:18:23 +0200 Subject: [Python-checkins] distutils2: branch merge Message-ID: tarek.ziade pushed 90e7d3dd3d2e to distutils2: http://hg.python.org/distutils2/rev/90e7d3dd3d2e changeset: 192:90e7d3dd3d2e parent: 191:ce0d6be25d09 parent: 189:9b2bfeed1630 user: ?ric Araujo date: Mon May 31 23:06:57 2010 +0200 summary: branch merge files: diff --git a/.hgignore b/.hgignore --- a/.hgignore +++ b/.hgignore @@ -1,5 +1,5 @@ .*\.pyc$ .*\.pyo$ +^src/build ^docs/build .*\.swp$ - -- Repository URL: http://hg.python.org/distutils2 From python-checkins at python.org Wed Jun 2 01:18:23 2010 From: python-checkins at python.org (tarek.ziade) Date: Wed, 02 Jun 2010 01:18:23 +0200 Subject: [Python-checkins] distutils2: Use the same name everywhere. Message-ID: tarek.ziade pushed ccaea7a5f39d to distutils2: http://hg.python.org/distutils2/rev/ccaea7a5f39d changeset: 190:ccaea7a5f39d parent: 188:b7fd258b33e7 user: ?ric Araujo date: Mon May 31 21:58:31 2010 +0200 summary: Use the same name everywhere. files: src/distutils2/_backport/tests/test_sysconfig.py, src/distutils2/tests/test_check.py, src/distutils2/tests/test_metadata.py, src/distutils2/tests/test_upload.py diff --git a/src/distutils2/_backport/tests/test_sysconfig.py b/src/distutils2/_backport/tests/test_sysconfig.py --- a/src/distutils2/_backport/tests/test_sysconfig.py +++ b/src/distutils2/_backport/tests/test_sysconfig.py @@ -97,7 +97,7 @@ substitution key (which would be weird). """ - self.failUnlessEqual(_subst_vars('{py{version}}', {'version': '31'}), '{py31}') + self.assertEqual(_subst_vars('{py{version}}', {'version': '31'}), '{py31}') def test_get_paths(self): scheme = get_paths() diff --git a/src/distutils2/tests/test_check.py b/src/distutils2/tests/test_check.py --- a/src/distutils2/tests/test_check.py +++ b/src/distutils2/tests/test_check.py @@ -27,7 +27,7 @@ # by default, check is checking the metadata # should have some warnings cmd = self._run() - self.assert_(len(cmd._warnings) > 0) + self.assertTrue(len(cmd._warnings) > 0) # now let's add the required fields # and run it again, to make sure we don't get diff --git a/src/distutils2/tests/test_metadata.py b/src/distutils2/tests/test_metadata.py --- a/src/distutils2/tests/test_metadata.py +++ b/src/distutils2/tests/test_metadata.py @@ -64,7 +64,7 @@ res = res.read() f = open(PKG_INFO) wanted = f.read() - self.assert_('Keywords: keyring,password,crypt' in res) + self.assertTrue('Keywords: keyring,password,crypt' in res) f.close() def test_metadata_markers(self): diff --git a/src/distutils2/tests/test_upload.py b/src/distutils2/tests/test_upload.py --- a/src/distutils2/tests/test_upload.py +++ b/src/distutils2/tests/test_upload.py @@ -116,7 +116,7 @@ # what did we send ? self.assertIn('d??d??', self.last_open.req.data) headers = dict(self.last_open.req.headers) - self.assert_(headers['Content-length'] > 2000) + self.assertTrue(headers['Content-length'] > 2000) self.assertTrue(headers['Content-type'].startswith('multipart/form-data')) self.assertEquals(self.last_open.req.get_method(), 'POST') self.assertEquals(self.last_open.req.get_full_url(), -- Repository URL: http://hg.python.org/distutils2 From python-checkins at python.org Wed Jun 2 01:18:23 2010 From: python-checkins at python.org (tarek.ziade) Date: Wed, 02 Jun 2010 01:18:23 +0200 Subject: [Python-checkins] distutils2: Restore 3.x-compatible syntax. Message-ID: tarek.ziade pushed 3050b9075187 to distutils2: http://hg.python.org/distutils2/rev/3050b9075187 changeset: 195:3050b9075187 user: ?ric Araujo date: Wed Jun 02 00:44:01 2010 +0200 summary: Restore 3.x-compatible syntax. files: src/runtests.py diff --git a/src/runtests.py b/src/runtests.py --- a/src/runtests.py +++ b/src/runtests.py @@ -28,7 +28,7 @@ try: from distutils2.tests.support import unittest except ImportError: - print >> sys.stderr, 'Error: You have to install unittest2' + print('Error: You have to install unittest2') sys.exit(1) sys.exit(test_main()) -- Repository URL: http://hg.python.org/distutils2 From python-checkins at python.org Wed Jun 2 01:18:23 2010 From: python-checkins at python.org (tarek.ziade) Date: Wed, 02 Jun 2010 01:18:23 +0200 Subject: [Python-checkins] distutils2: Add myself to contibutors. Message-ID: tarek.ziade pushed 67b757954d46 to distutils2: http://hg.python.org/distutils2/rev/67b757954d46 changeset: 196:67b757954d46 user: ?ric Araujo date: Wed Jun 02 01:07:34 2010 +0200 summary: Add myself to contibutors. files: src/CONTRIBUTORS.txt diff --git a/src/CONTRIBUTORS.txt b/src/CONTRIBUTORS.txt --- a/src/CONTRIBUTORS.txt +++ b/src/CONTRIBUTORS.txt @@ -9,6 +9,7 @@ Thanks to: +- ??ric Araujo - Pior Bastida - Titus Brown - Nicolas Cadou -- Repository URL: http://hg.python.org/distutils2 From python-checkins at python.org Wed Jun 2 01:18:23 2010 From: python-checkins at python.org (tarek.ziade) Date: Wed, 02 Jun 2010 01:18:23 +0200 Subject: [Python-checkins] distutils2: Isolate import of unittest or unittest2 in one place. Message-ID: tarek.ziade pushed 30409c856689 to distutils2: http://hg.python.org/distutils2/rev/30409c856689 changeset: 194:30409c856689 user: ?ric Araujo date: Tue Jun 01 17:55:57 2010 +0200 summary: Isolate import of unittest or unittest2 in one place. files: src/distutils2/_backport/tests/__init__.py, src/distutils2/_backport/tests/test_pkgutil.py, src/distutils2/_backport/tests/test_sysconfig.py, src/distutils2/tests/__init__.py, src/distutils2/tests/support.py, src/distutils2/tests/test_bdist.py, src/distutils2/tests/test_bdist_dumb.py, src/distutils2/tests/test_bdist_msi.py, src/distutils2/tests/test_bdist_wininst.py, src/distutils2/tests/test_build.py, src/distutils2/tests/test_build_clib.py, src/distutils2/tests/test_build_ext.py, src/distutils2/tests/test_build_py.py, src/distutils2/tests/test_build_scripts.py, src/distutils2/tests/test_ccompiler.py, src/distutils2/tests/test_check.py, src/distutils2/tests/test_clean.py, src/distutils2/tests/test_cmd.py, src/distutils2/tests/test_config.py, src/distutils2/tests/test_config_cmd.py, src/distutils2/tests/test_converter.py, src/distutils2/tests/test_core.py, src/distutils2/tests/test_cygwinccompiler.py, src/distutils2/tests/test_dist.py, src/distutils2/tests/test_emxccompiler.py, src/distutils2/tests/test_extension.py, src/distutils2/tests/test_install.py, src/distutils2/tests/test_install_data.py, src/distutils2/tests/test_install_headers.py, src/distutils2/tests/test_install_lib.py, src/distutils2/tests/test_install_scripts.py, src/distutils2/tests/test_manifest.py, src/distutils2/tests/test_metadata.py, src/distutils2/tests/test_msvc9compiler.py, src/distutils2/tests/test_pypi_versions.py, src/distutils2/tests/test_register.py, src/distutils2/tests/test_sdist.py, src/distutils2/tests/test_spawn.py, src/distutils2/tests/test_unixccompiler.py, src/distutils2/tests/test_upload.py, src/distutils2/tests/test_util.py, src/distutils2/tests/test_version.py, src/runtests.py diff --git a/src/distutils2/_backport/tests/__init__.py b/src/distutils2/_backport/tests/__init__.py --- a/src/distutils2/_backport/tests/__init__.py +++ b/src/distutils2/_backport/tests/__init__.py @@ -1,12 +1,13 @@ import os import sys -import unittest2 + +from distutils2.tests.support import unittest here = os.path.dirname(__file__) def test_suite(): - suite = unittest2.TestSuite() + suite = unittest.TestSuite() for fn in os.listdir(here): if fn.startswith("test") and fn.endswith(".py"): modname = "distutils2._backport.tests." + fn[:-3] diff --git a/src/distutils2/_backport/tests/test_pkgutil.py b/src/distutils2/_backport/tests/test_pkgutil.py --- a/src/distutils2/_backport/tests/test_pkgutil.py +++ b/src/distutils2/_backport/tests/test_pkgutil.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- """Tests for PEP 376 pkgutil functionality""" -import unittest2 import sys import os import csv @@ -12,13 +11,14 @@ from test.test_support import run_unittest, TESTFN import distutils2._backport.pkgutil +from distutils2.tests.support import unittest # TODO Add a test for getting a distribution that is provided by another # distribution. # TODO Add a test for absolute pathed RECORD items (e.g. /etc/myapp/config.ini) -class TestPkgUtilDistribution(unittest2.TestCase): +class TestPkgUtilDistribution(unittest.TestCase): """Tests the pkgutil.Distribution class""" def setUp(self): @@ -171,7 +171,7 @@ self.assertEqual(sorted(found), sorted(distinfo_record_paths)) -class TestPkgUtilFunctions(unittest2.TestCase): +class TestPkgUtilFunctions(unittest.TestCase): """Tests for the new functionality added in PEP 376.""" def setUp(self): @@ -371,8 +371,8 @@ def test_suite(): - suite = unittest2.TestSuite() - testcase_loader = unittest2.loader.defaultTestLoader.loadTestsFromTestCase + suite = unittest.TestSuite() + testcase_loader = unittest.loader.defaultTestLoader.loadTestsFromTestCase suite.addTest(testcase_loader(TestPkgUtilFunctions)) suite.addTest(testcase_loader(TestPkgUtilDistribution)) return suite @@ -384,8 +384,8 @@ test_main() def test_suite(): - suite = unittest2.TestSuite() - testcase_loader = unittest2.loader.defaultTestLoader.loadTestsFromTestCase + suite = unittest.TestSuite() + testcase_loader = unittest.loader.defaultTestLoader.loadTestsFromTestCase suite.addTest(testcase_loader(TestPkgUtilFunctions)) suite.addTest(testcase_loader(TestPkgUtilDistribution)) return suite diff --git a/src/distutils2/_backport/tests/test_sysconfig.py b/src/distutils2/_backport/tests/test_sysconfig.py --- a/src/distutils2/_backport/tests/test_sysconfig.py +++ b/src/distutils2/_backport/tests/test_sysconfig.py @@ -4,7 +4,6 @@ executing have not been removed. """ -import unittest2 import sys import os import shutil @@ -19,8 +18,9 @@ get_path, get_path_names, _get_default_scheme, _subst_vars, _expand_vars, get_scheme_names, _CONFIG_FILE) +from distutils2.tests.support import unittest -class TestSysConfig(unittest2.TestCase): +class TestSysConfig(unittest.TestCase): def setUp(self): """Make a copy of sys.path""" @@ -262,7 +262,7 @@ _expand_globals(config) def test_suite(): - return unittest2.makeSuite(TestSysConfig) + return unittest.makeSuite(TestSysConfig) def test_main(): run_unittest(test_suite()) diff --git a/src/distutils2/tests/__init__.py b/src/distutils2/tests/__init__.py --- a/src/distutils2/tests/__init__.py +++ b/src/distutils2/tests/__init__.py @@ -1,20 +1,25 @@ -"""Test suite for distutils. +"""Test suite for distutils2. This test suite consists of a collection of test modules in the -distutils.tests package. Each test module has a name starting with +distutils2.tests package. Each test module has a name starting with 'test' and contains a function test_suite(). The function is expected -to return an initialized unittest2.TestSuite instance. +to return an initialized unittest.TestSuite instance. -Tests for the command classes in the distutils.command package are -included in distutils.tests as well, instead of using a separate -distutils.command.tests package, since command identification is done +Tests for the command classes in the distutils2.command package are +included in distutils2.tests as well, instead of using a separate +distutils2.command.tests package, since command identification is done by import rather than matching pre-defined names. +Utility code is included in distutils2.tests.support. Always import +unittest from that module, it will be the right version (standard +library unittest for 2.7 and higher, third-party unittest2 release for +older versions). """ + import os import sys import warnings -import unittest2 +from distutils2.tests.support import unittest from test.test_support import TESTFN # use TESTFN from stdlib/test_support. @@ -23,7 +28,7 @@ verbose = 1 def test_suite(): - suite = unittest2.TestSuite() + suite = unittest.TestSuite() for fn in os.listdir(here): if fn.startswith("test") and fn.endswith(".py"): modname = "distutils2.tests." + fn[:-3] @@ -42,17 +47,17 @@ class BasicTestRunner: def run(self, test): - result = unittest2.TestResult() + result = unittest.TestResult() test(result) return result def _run_suite(suite, verbose_=1): - """Run tests from a unittest2.TestSuite-derived class.""" + """Run tests from a unittest.TestSuite-derived class.""" global verbose verbose = verbose_ if verbose_: - runner = unittest2.TextTestRunner(sys.stdout, verbosity=2) + runner = unittest.TextTestRunner(sys.stdout, verbosity=2) else: runner = BasicTestRunner() @@ -68,22 +73,22 @@ def run_unittest(classes, verbose_=1): - """Run tests from unittest2.TestCase-derived classes. + """Run tests from unittest.TestCase-derived classes. - Extracted from stdlib test.test_support and modified to support unittest2. + Extracted from stdlib test.test_support and modified to support unittest. """ - valid_types = (unittest2.TestSuite, unittest2.TestCase) - suite = unittest2.TestSuite() + valid_types = (unittest.TestSuite, unittest.TestCase) + suite = unittest.TestSuite() for cls in classes: if isinstance(cls, str): if cls in sys.modules: - suite.addTest(unittest2.findTestCases(sys.modules[cls])) + suite.addTest(unittest.findTestCases(sys.modules[cls])) else: raise ValueError("str arguments must be keys in sys.modules") elif isinstance(cls, valid_types): suite.addTest(cls) else: - suite.addTest(unittest2.makeSuite(cls)) + suite.addTest(unittest.makeSuite(cls)) _run_suite(suite, verbose_) @@ -128,4 +133,4 @@ if __name__ == "__main__": - unittest2.main(defaultTest="test_suite") + unittest.main(defaultTest="test_suite") diff --git a/src/distutils2/tests/support.py b/src/distutils2/tests/support.py --- a/src/distutils2/tests/support.py +++ b/src/distutils2/tests/support.py @@ -1,5 +1,12 @@ -"""Support code for distutils test cases.""" +"""Support code for distutils2 test cases. + +Always import unittest from this module, it will be the right version +(standard library unittest for 2.7 and higher, third-party unittest2 +release for older versions). +""" + import os +import sys import shutil import tempfile from copy import deepcopy @@ -9,6 +16,13 @@ from distutils2.log import DEBUG, INFO, WARN, ERROR, FATAL from distutils2.core import Distribution +if sys.version_info >= (2, 7): + # improved unittest package from 2.7's standard library + import unittest +else: + # external release of same package for older versions + import unittest2 as unittest + class LoggingSilencer(object): def setUp(self): diff --git a/src/distutils2/tests/test_bdist.py b/src/distutils2/tests/test_bdist.py --- a/src/distutils2/tests/test_bdist.py +++ b/src/distutils2/tests/test_bdist.py @@ -1,5 +1,4 @@ """Tests for distutils.command.bdist.""" -import unittest2 import sys import os import tempfile @@ -10,12 +9,13 @@ from distutils2.core import Distribution from distutils2.command.bdist import bdist from distutils2.tests import support +from distutils2.tests.support import unittest from distutils2.spawn import find_executable from distutils2 import spawn from distutils2.errors import DistutilsExecError class BuildTestCase(support.TempdirManager, - unittest2.TestCase): + unittest.TestCase): def test_formats(self): @@ -38,7 +38,7 @@ self.assertEquals(founded, formats) def test_suite(): - return unittest2.makeSuite(BuildTestCase) + return unittest.makeSuite(BuildTestCase) if __name__ == '__main__': run_unittest(test_suite()) diff --git a/src/distutils2/tests/test_bdist_dumb.py b/src/distutils2/tests/test_bdist_dumb.py --- a/src/distutils2/tests/test_bdist_dumb.py +++ b/src/distutils2/tests/test_bdist_dumb.py @@ -1,6 +1,5 @@ """Tests for distutils.command.bdist_dumb.""" -import unittest2 import sys import os @@ -12,6 +11,7 @@ zlib = None from distutils2.tests import run_unittest +from distutils2.tests.support import unittest from distutils2.core import Distribution from distutils2.command.bdist_dumb import bdist_dumb @@ -29,7 +29,7 @@ class BuildDumbTestCase(support.TempdirManager, support.LoggingSilencer, support.EnvironGuard, - unittest2.TestCase): + unittest.TestCase): def setUp(self): super(BuildDumbTestCase, self).setUp() @@ -42,7 +42,7 @@ sys.argv[:] = self.old_sys_argv[1] super(BuildDumbTestCase, self).tearDown() - @unittest2.skipUnless(zlib, "requires zlib") + @unittest.skipUnless(zlib, "requires zlib") def test_simple_built(self): # let's create a simple package @@ -99,7 +99,7 @@ self.assertEquals(cmd.format, default) def test_suite(): - return unittest2.makeSuite(BuildDumbTestCase) + return unittest.makeSuite(BuildDumbTestCase) if __name__ == '__main__': run_unittest(test_suite()) diff --git a/src/distutils2/tests/test_bdist_msi.py b/src/distutils2/tests/test_bdist_msi.py --- a/src/distutils2/tests/test_bdist_msi.py +++ b/src/distutils2/tests/test_bdist_msi.py @@ -1,16 +1,16 @@ """Tests for distutils.command.bdist_msi.""" -import unittest2 import sys from distutils2.tests import run_unittest from distutils2.tests import support +from distutils2.tests.support import unittest class BDistMSITestCase(support.TempdirManager, support.LoggingSilencer, - unittest2.TestCase): + unittest.TestCase): - @unittest2.skipUnless(sys.platform=="win32", "These tests are only for win32") + @unittest.skipUnless(sys.platform=="win32", "These tests are only for win32") def test_minial(self): # minimal test XXX need more tests from distutils2.command.bdist_msi import bdist_msi @@ -19,7 +19,7 @@ cmd.ensure_finalized() def test_suite(): - return unittest2.makeSuite(BDistMSITestCase) + return unittest.makeSuite(BDistMSITestCase) if __name__ == '__main__': run_unittest(test_suite()) diff --git a/src/distutils2/tests/test_bdist_wininst.py b/src/distutils2/tests/test_bdist_wininst.py --- a/src/distutils2/tests/test_bdist_wininst.py +++ b/src/distutils2/tests/test_bdist_wininst.py @@ -1,14 +1,14 @@ """Tests for distutils.command.bdist_wininst.""" -import unittest2 from distutils2.tests import run_unittest from distutils2.command.bdist_wininst import bdist_wininst from distutils2.tests import support +from distutils2.tests.support import unittest class BuildWinInstTestCase(support.TempdirManager, support.LoggingSilencer, - unittest2.TestCase): + unittest.TestCase): def test_get_exe_bytes(self): @@ -26,7 +26,7 @@ self.assertTrue(len(exe_file) > 10) def test_suite(): - return unittest2.makeSuite(BuildWinInstTestCase) + return unittest.makeSuite(BuildWinInstTestCase) if __name__ == '__main__': run_unittest(test_suite()) diff --git a/src/distutils2/tests/test_build.py b/src/distutils2/tests/test_build.py --- a/src/distutils2/tests/test_build.py +++ b/src/distutils2/tests/test_build.py @@ -1,10 +1,10 @@ """Tests for distutils.command.build.""" -import unittest2 import os import sys from distutils2.command.build import build from distutils2.tests import support +from distutils2.tests.support import unittest try: from sysconfig import get_platform except ImportError: @@ -12,7 +12,7 @@ class BuildTestCase(support.TempdirManager, support.LoggingSilencer, - unittest2.TestCase): + unittest.TestCase): def test_finalize_options(self): pkg_dir, dist = self.create_dist() @@ -51,7 +51,7 @@ self.assertEquals(cmd.executable, os.path.normpath(sys.executable)) def test_suite(): - return unittest2.makeSuite(BuildTestCase) + return unittest.makeSuite(BuildTestCase) if __name__ == "__main__": - unittest2.main(defaultTest="test_suite") + unittest.main(defaultTest="test_suite") diff --git a/src/distutils2/tests/test_build_clib.py b/src/distutils2/tests/test_build_clib.py --- a/src/distutils2/tests/test_build_clib.py +++ b/src/distutils2/tests/test_build_clib.py @@ -1,5 +1,4 @@ """Tests for distutils.command.build_clib.""" -import unittest2 import os import sys @@ -7,10 +6,11 @@ from distutils2.errors import DistutilsSetupError from distutils2.tests import support from distutils2.spawn import find_executable +from distutils2.tests.support import unittest class BuildCLibTestCase(support.TempdirManager, support.LoggingSilencer, - unittest2.TestCase): + unittest.TestCase): def test_check_library_dist(self): pkg_dir, dist = self.create_dist() @@ -137,7 +137,7 @@ self.assertTrue('libfoo.a' in os.listdir(build_temp)) def test_suite(): - return unittest2.makeSuite(BuildCLibTestCase) + return unittest.makeSuite(BuildCLibTestCase) if __name__ == "__main__": - unittest2.main(defaultTest="test_suite") + unittest.main(defaultTest="test_suite") diff --git a/src/distutils2/tests/test_build_ext.py b/src/distutils2/tests/test_build_ext.py --- a/src/distutils2/tests/test_build_ext.py +++ b/src/distutils2/tests/test_build_ext.py @@ -6,6 +6,7 @@ import warnings import distutils2.tests +from distutils2.tests.support import unittest from distutils2.core import Extension, Distribution from distutils2.command.build_ext import build_ext from distutils2.tests import support @@ -17,7 +18,6 @@ except ImportError: from distutils2._backport import sysconfig -import unittest2 # http://bugs.python.org/issue4373 # Don't load the xx module more than once. @@ -29,7 +29,7 @@ class BuildExtTestCase(support.TempdirManager, support.LoggingSilencer, - unittest2.TestCase): + unittest.TestCase): def setUp(self): # Create a simple test environment # Note that we're making changes to sys.path @@ -46,7 +46,7 @@ build_ext.USER_BASE = site.USER_BASE # XXX only works with 2.6 > -- dunno why yet - @unittest2.skipUnless(sys.version_info >= (2, 6,), 'works for >= 2.6') + @unittest.skipUnless(sys.version_info >= (2, 6,), 'works for >= 2.6') def test_build_ext(self): global ALREADY_TESTED xx_c = os.path.join(self.tmp_dir, 'xxmodule.c') @@ -412,8 +412,8 @@ if distutils2.tests.verbose: print ('test_build_ext: Cannot find source code (test' ' must run in python build dir)') - return unittest2.TestSuite() - else: return unittest2.makeSuite(BuildExtTestCase) + return unittest.TestSuite() + else: return unittest.makeSuite(BuildExtTestCase) if __name__ == '__main__': distsutils2.tests.run_unittest(test_suite()) diff --git a/src/distutils2/tests/test_build_py.py b/src/distutils2/tests/test_build_py.py --- a/src/distutils2/tests/test_build_py.py +++ b/src/distutils2/tests/test_build_py.py @@ -3,18 +3,18 @@ import os import sys import StringIO -import unittest2 from distutils2.command.build_py import build_py from distutils2.core import Distribution from distutils2.errors import DistutilsFileError from distutils2.tests import support +from distutils2.tests.support import unittest class BuildPyTestCase(support.TempdirManager, support.LoggingSilencer, - unittest2.TestCase): + unittest.TestCase): def test_package_data(self): sources = self.mkdtemp() @@ -90,7 +90,7 @@ os.chdir(cwd) sys.stdout = old_stdout - @unittest2.skipUnless(hasattr(sys, 'dont_write_bytecode'), + @unittest.skipUnless(hasattr(sys, 'dont_write_bytecode'), 'dont_write_bytecode support') def test_dont_write_bytecode(self): # makes sure byte_compile is not used @@ -109,7 +109,7 @@ self.assertTrue('byte-compiling is disabled' in self.logs[0][1]) def test_suite(): - return unittest2.makeSuite(BuildPyTestCase) + return unittest.makeSuite(BuildPyTestCase) if __name__ == "__main__": - unittest2.main(defaultTest="test_suite") + unittest.main(defaultTest="test_suite") diff --git a/src/distutils2/tests/test_build_scripts.py b/src/distutils2/tests/test_build_scripts.py --- a/src/distutils2/tests/test_build_scripts.py +++ b/src/distutils2/tests/test_build_scripts.py @@ -1,7 +1,6 @@ """Tests for distutils.command.build_scripts.""" import os -import unittest2 from distutils2.command.build_scripts import build_scripts from distutils2.core import Distribution @@ -11,11 +10,12 @@ from distutils2._backport import sysconfig from distutils2.tests import support +from distutils2.tests.support import unittest class BuildScriptsTestCase(support.TempdirManager, support.LoggingSilencer, - unittest2.TestCase): + unittest.TestCase): def test_default_settings(self): cmd = self.get_build_scripts_cmd("/foo/bar", []) @@ -106,7 +106,7 @@ self.assertTrue(name in built) def test_suite(): - return unittest2.makeSuite(BuildScriptsTestCase) + return unittest.makeSuite(BuildScriptsTestCase) if __name__ == "__main__": - unittest2.main(defaultTest="test_suite") + unittest.main(defaultTest="test_suite") diff --git a/src/distutils2/tests/test_ccompiler.py b/src/distutils2/tests/test_ccompiler.py --- a/src/distutils2/tests/test_ccompiler.py +++ b/src/distutils2/tests/test_ccompiler.py @@ -1,11 +1,11 @@ """Tests for distutils.ccompiler.""" import os -import unittest2 from distutils2.tests import captured_stdout from distutils2.compiler.ccompiler import (gen_lib_options, CCompiler, get_default_compiler, customize_compiler) from distutils2.tests import support +from distutils2.tests.support import unittest class FakeCompiler(object): def library_dir_option(self, dir): @@ -20,7 +20,7 @@ def library_option(self, lib): return "-l" + lib -class CCompilerTestCase(support.EnvironGuard, unittest2.TestCase): +class CCompilerTestCase(support.EnvironGuard, unittest.TestCase): def test_gen_lib_options(self): compiler = FakeCompiler() @@ -54,7 +54,7 @@ self.assertEquals(comp.exes['archiver'], 'my_ar -arflags') def test_suite(): - return unittest2.makeSuite(CCompilerTestCase) + return unittest.makeSuite(CCompilerTestCase) if __name__ == "__main__": - unittest2.main(defaultTest="test_suite") + unittest.main(defaultTest="test_suite") diff --git a/src/distutils2/tests/test_check.py b/src/distutils2/tests/test_check.py --- a/src/distutils2/tests/test_check.py +++ b/src/distutils2/tests/test_check.py @@ -1,14 +1,14 @@ """Tests for distutils.command.check.""" -import unittest2 from distutils2.command.check import check from distutils2.metadata import _HAS_DOCUTILS from distutils2.tests import support +from distutils2.tests.support import unittest from distutils2.errors import DistutilsSetupError class CheckTestCase(support.LoggingSilencer, support.TempdirManager, - unittest2.TestCase): + unittest.TestCase): def _run(self, metadata=None, **options): if metadata is None: @@ -79,7 +79,7 @@ 'restructuredtext': 1}) def test_suite(): - return unittest2.makeSuite(CheckTestCase) + return unittest.makeSuite(CheckTestCase) if __name__ == "__main__": - unittest2.main(defaultTest="test_suite") + unittest.main(defaultTest="test_suite") diff --git a/src/distutils2/tests/test_clean.py b/src/distutils2/tests/test_clean.py --- a/src/distutils2/tests/test_clean.py +++ b/src/distutils2/tests/test_clean.py @@ -1,15 +1,15 @@ """Tests for distutils.command.clean.""" import sys import os -import unittest2 import getpass from distutils2.command.clean import clean from distutils2.tests import support +from distutils2.tests.support import unittest class cleanTestCase(support.TempdirManager, support.LoggingSilencer, - unittest2.TestCase): + unittest.TestCase): def test_simple_run(self): pkg_dir, dist = self.create_dist() @@ -44,7 +44,7 @@ cmd.run() def test_suite(): - return unittest2.makeSuite(cleanTestCase) + return unittest.makeSuite(cleanTestCase) if __name__ == "__main__": - unittest2.main(defaultTest="test_suite") + unittest.main(defaultTest="test_suite") diff --git a/src/distutils2/tests/test_cmd.py b/src/distutils2/tests/test_cmd.py --- a/src/distutils2/tests/test_cmd.py +++ b/src/distutils2/tests/test_cmd.py @@ -1,17 +1,17 @@ """Tests for distutils.cmd.""" -import unittest2 import os from distutils2.tests import captured_stdout, run_unittest from distutils2.cmd import Command from distutils2.dist import Distribution from distutils2.errors import DistutilsOptionError +from distutils2.tests.support import unittest class MyCmd(Command): def initialize_options(self): pass -class CommandTestCase(unittest2.TestCase): +class CommandTestCase(unittest.TestCase): def setUp(self): dist = Distribution() @@ -104,7 +104,7 @@ self.assertRaises(DistutilsOptionError, cmd.ensure_dirname, 'option2') def test_suite(): - return unittest2.makeSuite(CommandTestCase) + return unittest.makeSuite(CommandTestCase) if __name__ == '__main__': run_unittest(test_suite()) diff --git a/src/distutils2/tests/test_config.py b/src/distutils2/tests/test_config.py --- a/src/distutils2/tests/test_config.py +++ b/src/distutils2/tests/test_config.py @@ -1,7 +1,6 @@ """Tests for distutils.pypirc.pypirc.""" import sys import os -import unittest2 import tempfile import shutil @@ -11,6 +10,7 @@ from distutils2.log import WARN from distutils2.tests import support +from distutils2.tests.support import unittest PYPIRC = """\ [distutils] @@ -50,7 +50,7 @@ class PyPIRCCommandTestCase(support.TempdirManager, support.LoggingSilencer, support.EnvironGuard, - unittest2.TestCase): + unittest.TestCase): def setUp(self): """Patches the environment.""" @@ -112,7 +112,7 @@ self.assertEquals(content, WANTED) def test_suite(): - return unittest2.makeSuite(PyPIRCCommandTestCase) + return unittest.makeSuite(PyPIRCCommandTestCase) if __name__ == "__main__": - unittest2.main(defaultTest="test_suite") + unittest.main(defaultTest="test_suite") diff --git a/src/distutils2/tests/test_config_cmd.py b/src/distutils2/tests/test_config_cmd.py --- a/src/distutils2/tests/test_config_cmd.py +++ b/src/distutils2/tests/test_config_cmd.py @@ -1,15 +1,15 @@ """Tests for distutils.command.config.""" -import unittest2 import os import sys from distutils2.command.config import dump_file, config from distutils2.tests import support +from distutils2.tests.support import unittest from distutils2 import log class ConfigTestCase(support.LoggingSilencer, support.TempdirManager, - unittest2.TestCase): + unittest.TestCase): def _info(self, msg, *args): for line in msg.splitlines(): @@ -83,7 +83,7 @@ self.assertTrue(not os.path.exists(f)) def test_suite(): - return unittest2.makeSuite(ConfigTestCase) + return unittest.makeSuite(ConfigTestCase) if __name__ == "__main__": - unittest2.main(defaultTest="test_suite") + unittest.main(defaultTest="test_suite") diff --git a/src/distutils2/tests/test_converter.py b/src/distutils2/tests/test_converter.py --- a/src/distutils2/tests/test_converter.py +++ b/src/distutils2/tests/test_converter.py @@ -1,8 +1,8 @@ """Tests for distutils.converter.""" import os import sys -import unittest2 from distutils2.converter import DistutilsRefactoringTool +from distutils2.tests.support import unittest _CURDIR = os.path.dirname(__file__) @@ -15,9 +15,9 @@ f.close() -class ConverterTestCase(unittest2.TestCase): +class ConverterTestCase(unittest.TestCase): - @unittest2.skipUnless(not sys.version < '2.6', 'Needs Python >=2.6') + @unittest.skipUnless(not sys.version < '2.6', 'Needs Python >=2.6') def test_conversions(self): # for all XX_before in the conversions/ dir # we run the refactoring tool @@ -33,7 +33,7 @@ self.assertEquals(str(res), wanted) def test_suite(): - return unittest2.makeSuite(ConverterTestCase) + return unittest.makeSuite(ConverterTestCase) if __name__ == '__main__': - unittest2.main(defaultTest="test_suite") + unittest.main(defaultTest="test_suite") diff --git a/src/distutils2/tests/test_core.py b/src/distutils2/tests/test_core.py --- a/src/distutils2/tests/test_core.py +++ b/src/distutils2/tests/test_core.py @@ -6,8 +6,8 @@ import shutil import sys from distutils2.tests import captured_stdout -import unittest2 from distutils2.tests import support +from distutils2.tests.support import unittest # setup script that uses __file__ setup_using___file__ = """\ @@ -28,7 +28,7 @@ """ -class CoreTestCase(support.EnvironGuard, unittest2.TestCase): +class CoreTestCase(support.EnvironGuard, unittest.TestCase): def setUp(self): super(CoreTestCase, self).setUp() @@ -92,7 +92,7 @@ self.assertEqual(cwd, output) def test_suite(): - return unittest2.makeSuite(CoreTestCase) + return unittest.makeSuite(CoreTestCase) if __name__ == "__main__": - unittest2.main(defaultTest="test_suite") + unittest.main(defaultTest="test_suite") diff --git a/src/distutils2/tests/test_cygwinccompiler.py b/src/distutils2/tests/test_cygwinccompiler.py --- a/src/distutils2/tests/test_cygwinccompiler.py +++ b/src/distutils2/tests/test_cygwinccompiler.py @@ -1,5 +1,4 @@ """Tests for distutils.cygwinccompiler.""" -import unittest2 import sys import os import warnings @@ -18,9 +17,10 @@ get_msvcr, RE_VERSION) from distutils2.util import get_compiler_versions from distutils2.tests import support +from distutils2.tests.support import unittest class CygwinCCompilerTestCase(support.TempdirManager, - unittest2.TestCase): + unittest.TestCase): def setUp(self): super(CygwinCCompilerTestCase, self).setUp() @@ -94,7 +94,7 @@ def test_suite(): - return unittest2.makeSuite(CygwinCCompilerTestCase) + return unittest.makeSuite(CygwinCCompilerTestCase) if __name__ == '__main__': run_unittest(test_suite()) diff --git a/src/distutils2/tests/test_dist.py b/src/distutils2/tests/test_dist.py --- a/src/distutils2/tests/test_dist.py +++ b/src/distutils2/tests/test_dist.py @@ -4,7 +4,6 @@ import os import StringIO import sys -import unittest2 import warnings import textwrap @@ -13,6 +12,7 @@ import distutils2.dist from distutils2.tests import TESTFN, captured_stdout from distutils2.tests import support +from distutils2.tests.support import unittest class test_dist(Command): """Sample distutils2 extension command.""" @@ -40,7 +40,7 @@ class DistributionTestCase(support.TempdirManager, support.LoggingSilencer, support.EnvironGuard, - unittest2.TestCase): + unittest.TestCase): def setUp(self): super(DistributionTestCase, self).setUp() @@ -242,7 +242,7 @@ class MetadataTestCase(support.TempdirManager, support.EnvironGuard, - unittest2.TestCase): + unittest.TestCase): def setUp(self): super(MetadataTestCase, self).setUp() @@ -422,10 +422,10 @@ self.assertEquals(metadata['requires-dist'], ['foo']) def test_suite(): - suite = unittest2.TestSuite() - suite.addTest(unittest2.makeSuite(DistributionTestCase)) - suite.addTest(unittest2.makeSuite(MetadataTestCase)) + suite = unittest.TestSuite() + suite.addTest(unittest.makeSuite(DistributionTestCase)) + suite.addTest(unittest.makeSuite(MetadataTestCase)) return suite if __name__ == "__main__": - unittest2.main(defaultTest="test_suite") + unittest.main(defaultTest="test_suite") diff --git a/src/distutils2/tests/test_emxccompiler.py b/src/distutils2/tests/test_emxccompiler.py --- a/src/distutils2/tests/test_emxccompiler.py +++ b/src/distutils2/tests/test_emxccompiler.py @@ -1,5 +1,4 @@ """Tests for distutils.emxccompiler.""" -import unittest2 import sys import os import warnings @@ -10,14 +9,15 @@ from distutils2.compiler.emxccompiler import get_versions from distutils2.util import get_compiler_versions from distutils2.tests import support +from distutils2.tests.support import unittest class EmxCCompilerTestCase(support.TempdirManager, - unittest2.TestCase): + unittest.TestCase): pass def test_suite(): - return unittest2.makeSuite(EmxCCompilerTestCase) + return unittest.makeSuite(EmxCCompilerTestCase) if __name__ == '__main__': run_unittest(test_suite()) diff --git a/src/distutils2/tests/test_extension.py b/src/distutils2/tests/test_extension.py --- a/src/distutils2/tests/test_extension.py +++ b/src/distutils2/tests/test_extension.py @@ -1,16 +1,16 @@ """Tests for distutils.extension.""" -import unittest2 import os import warnings from distutils2.extension import Extension +from distutils2.tests.support import unittest -class ExtensionTestCase(unittest2.TestCase): +class ExtensionTestCase(unittest.TestCase): pass def test_suite(): - return unittest2.makeSuite(ExtensionTestCase) + return unittest.makeSuite(ExtensionTestCase) if __name__ == "__main__": - unittest2.main(defaultTest="test_suite") + unittest.main(defaultTest="test_suite") diff --git a/src/distutils2/tests/test_install.py b/src/distutils2/tests/test_install.py --- a/src/distutils2/tests/test_install.py +++ b/src/distutils2/tests/test_install.py @@ -3,7 +3,6 @@ import os import os.path import sys -import unittest2 import site from distutils2._backport import sysconfig @@ -22,11 +21,12 @@ from distutils2.errors import DistutilsOptionError from distutils2.tests import support +from distutils2.tests.support import unittest class InstallTestCase(support.TempdirManager, support.EnvironGuard, support.LoggingSilencer, - unittest2.TestCase): + unittest.TestCase): def test_home_installation_scheme(self): # This ensure two things: @@ -214,7 +214,7 @@ self.assertTrue(len(self.logs) > old_logs_len) def test_suite(): - return unittest2.makeSuite(InstallTestCase) + return unittest.makeSuite(InstallTestCase) if __name__ == "__main__": - unittest2.main(defaultTest="test_suite") + unittest.main(defaultTest="test_suite") diff --git a/src/distutils2/tests/test_install_data.py b/src/distutils2/tests/test_install_data.py --- a/src/distutils2/tests/test_install_data.py +++ b/src/distutils2/tests/test_install_data.py @@ -1,16 +1,16 @@ """Tests for distutils.command.install_data.""" import sys import os -import unittest2 import getpass from distutils2.command.install_data import install_data from distutils2.tests import support +from distutils2.tests.support import unittest class InstallDataTestCase(support.TempdirManager, support.LoggingSilencer, support.EnvironGuard, - unittest2.TestCase): + unittest.TestCase): def test_simple_run(self): pkg_dir, dist = self.create_dist() @@ -70,7 +70,7 @@ self.assertTrue(os.path.exists(os.path.join(inst, rone))) def test_suite(): - return unittest2.makeSuite(InstallDataTestCase) + return unittest.makeSuite(InstallDataTestCase) if __name__ == "__main__": - unittest2.main(defaultTest="test_suite") + unittest.main(defaultTest="test_suite") diff --git a/src/distutils2/tests/test_install_headers.py b/src/distutils2/tests/test_install_headers.py --- a/src/distutils2/tests/test_install_headers.py +++ b/src/distutils2/tests/test_install_headers.py @@ -1,16 +1,16 @@ """Tests for distutils.command.install_headers.""" import sys import os -import unittest2 import getpass from distutils2.command.install_headers import install_headers from distutils2.tests import support +from distutils2.tests.support import unittest class InstallHeadersTestCase(support.TempdirManager, support.LoggingSilencer, support.EnvironGuard, - unittest2.TestCase): + unittest.TestCase): def test_simple_run(self): # we have two headers @@ -34,7 +34,7 @@ self.assertEquals(len(cmd.get_outputs()), 2) def test_suite(): - return unittest2.makeSuite(InstallHeadersTestCase) + return unittest.makeSuite(InstallHeadersTestCase) if __name__ == "__main__": - unittest2.main(defaultTest="test_suite") + unittest.main(defaultTest="test_suite") diff --git a/src/distutils2/tests/test_install_lib.py b/src/distutils2/tests/test_install_lib.py --- a/src/distutils2/tests/test_install_lib.py +++ b/src/distutils2/tests/test_install_lib.py @@ -1,12 +1,12 @@ """Tests for distutils.command.install_data.""" import sys import os -import unittest2 from distutils2.command.install_lib import install_lib from distutils2.extension import Extension from distutils2.tests import support from distutils2.errors import DistutilsOptionError +from distutils2.tests.support import unittest try: no_bytecode = sys.dont_write_bytecode @@ -18,7 +18,7 @@ class InstallLibTestCase(support.TempdirManager, support.LoggingSilencer, support.EnvironGuard, - unittest2.TestCase): + unittest.TestCase): def test_finalize_options(self): pkg_dir, dist = self.create_dist() @@ -38,7 +38,7 @@ cmd.finalize_options() self.assertEquals(cmd.optimize, 2) - @unittest2.skipIf(no_bytecode, 'byte-compile not supported') + @unittest.skipIf(no_bytecode, 'byte-compile not supported') def test_byte_compile(self): pkg_dir, dist = self.create_dist() cmd = install_lib(dist) @@ -84,7 +84,7 @@ # get_input should return 2 elements self.assertEquals(len(cmd.get_inputs()), 2) - @unittest2.skipUnless(bytecode_support, 'sys.dont_write_bytecode not supported') + @unittest.skipUnless(bytecode_support, 'sys.dont_write_bytecode not supported') def test_dont_write_bytecode(self): # makes sure byte_compile is not used pkg_dir, dist = self.create_dist() @@ -102,7 +102,7 @@ self.assertTrue('byte-compiling is disabled' in self.logs[0][1]) def test_suite(): - return unittest2.makeSuite(InstallLibTestCase) + return unittest.makeSuite(InstallLibTestCase) if __name__ == "__main__": - unittest2.main(defaultTest="test_suite") + unittest.main(defaultTest="test_suite") diff --git a/src/distutils2/tests/test_install_scripts.py b/src/distutils2/tests/test_install_scripts.py --- a/src/distutils2/tests/test_install_scripts.py +++ b/src/distutils2/tests/test_install_scripts.py @@ -1,17 +1,17 @@ """Tests for distutils.command.install_scripts.""" import os -import unittest2 from distutils2.command.install_scripts import install_scripts from distutils2.core import Distribution from distutils2.tests import support +from distutils2.tests.support import unittest class InstallScriptsTestCase(support.TempdirManager, support.LoggingSilencer, - unittest2.TestCase): + unittest.TestCase): def test_default_settings(self): dist = Distribution() @@ -73,7 +73,7 @@ def test_suite(): - return unittest2.makeSuite(InstallScriptsTestCase) + return unittest.makeSuite(InstallScriptsTestCase) if __name__ == "__main__": - unittest2.main(defaultTest="test_suite") + unittest.main(defaultTest="test_suite") diff --git a/src/distutils2/tests/test_manifest.py b/src/distutils2/tests/test_manifest.py --- a/src/distutils2/tests/test_manifest.py +++ b/src/distutils2/tests/test_manifest.py @@ -1,10 +1,10 @@ """Tests for distutils.manifest.""" -import unittest2 import os import sys import logging from distutils2.tests import support +from distutils2.tests.support import unittest from distutils2.manifest import Manifest _MANIFEST = """\ @@ -18,7 +18,7 @@ """ class ManifestTestCase(support.TempdirManager, - unittest2.TestCase): + unittest.TestCase): def test_manifest_reader(self): @@ -51,7 +51,7 @@ def test_suite(): - return unittest2.makeSuite(ManifestTestCase) + return unittest.makeSuite(ManifestTestCase) if __name__ == '__main__': run_unittest(test_suite()) diff --git a/src/distutils2/tests/test_metadata.py b/src/distutils2/tests/test_metadata.py --- a/src/distutils2/tests/test_metadata.py +++ b/src/distutils2/tests/test_metadata.py @@ -1,13 +1,13 @@ """Tests for distutils.command.bdist.""" -import unittest2 import os import sys from StringIO import StringIO from distutils2.metadata import (DistributionMetadata, _interpret, PKG_INFO_PREFERRED_VERSION) +from distutils2.tests.support import unittest -class DistributionMetadataTestCase(unittest2.TestCase): +class DistributionMetadataTestCase(unittest.TestCase): def test_interpret(self): @@ -228,7 +228,7 @@ def test_suite(): - return unittest2.makeSuite(DistributionMetadataTestCase) + return unittest.makeSuite(DistributionMetadataTestCase) if __name__ == '__main__': run_unittest(test_suite()) diff --git a/src/distutils2/tests/test_msvc9compiler.py b/src/distutils2/tests/test_msvc9compiler.py --- a/src/distutils2/tests/test_msvc9compiler.py +++ b/src/distutils2/tests/test_msvc9compiler.py @@ -1,10 +1,10 @@ """Tests for distutils.msvc9compiler.""" import sys -import unittest2 import os from distutils2.errors import DistutilsPlatformError from distutils2.tests import support +from distutils2.tests.support import unittest _MANIFEST = """\ @@ -62,9 +62,9 @@ class msvc9compilerTestCase(support.TempdirManager, - unittest2.TestCase): + unittest.TestCase): - @unittest2.skipUnless(sys.platform=="win32", "These tests are only for win32") + @unittest.skipUnless(sys.platform=="win32", "These tests are only for win32") def test_no_compiler(self): # makes sure query_vcvarsall throws # a DistutilsPlatformError if the compiler @@ -86,7 +86,7 @@ finally: msvc9compiler.find_vcvarsall = old_find_vcvarsall - @unittest2.skipUnless(sys.platform=="win32", "These tests are only for win32") + @unittest.skipUnless(sys.platform=="win32", "These tests are only for win32") def test_reg_class(self): from distutils2.msvccompiler import get_build_version if get_build_version() < 8.0: @@ -110,7 +110,7 @@ keys = Reg.read_keys(HKCU, r'Control Panel') self.assertTrue('Desktop' in keys) - @unittest2.skipUnless(sys.platform=="win32", "These tests are only for win32") + @unittest.skipUnless(sys.platform=="win32", "These tests are only for win32") def test_remove_visual_c_ref(self): from distutils2.msvc9compiler import MSVCCompiler tempdir = self.mkdtemp() @@ -133,7 +133,7 @@ def test_suite(): - return unittest2.makeSuite(msvc9compilerTestCase) + return unittest.makeSuite(msvc9compilerTestCase) if __name__ == "__main__": - unittest2.main(defaultTest="test_suite") + unittest.main(defaultTest="test_suite") diff --git a/src/distutils2/tests/test_pypi_versions.py b/src/distutils2/tests/test_pypi_versions.py --- a/src/distutils2/tests/test_pypi_versions.py +++ b/src/distutils2/tests/test_pypi_versions.py @@ -17,9 +17,9 @@ import xmlrpclib import os.path -import unittest2 from distutils2.version import suggest_normalized_version +from distutils2.tests.support import unittest def test_pypi(): # @@ -121,11 +121,11 @@ print "Have Suggestion : ", have_sugg, pct % (have_sugg/total_versions*100,) print "No Suggestion : ", no_sugg, pct % (no_sugg/total_versions*100,) -class TestPyPI(unittest2.TestCase): +class TestPyPI(unittest.TestCase): pass def test_suite(): - return unittest2.makeSuite(TestPyPI) + return unittest.makeSuite(TestPyPI) if __name__ == '__main__': run_unittest(test_suite()) diff --git a/src/distutils2/tests/test_register.py b/src/distutils2/tests/test_register.py --- a/src/distutils2/tests/test_register.py +++ b/src/distutils2/tests/test_register.py @@ -2,7 +2,6 @@ # -*- encoding: utf8 -*- import sys import os -import unittest2 import getpass import urllib2 import warnings @@ -19,6 +18,7 @@ from distutils2.errors import DistutilsSetupError from distutils2.tests import support +from distutils2.tests.support import unittest from distutils2.tests.test_config import PYPIRC, PyPIRCCommandTestCase PYPIRC_NOPASSWORD = """\ @@ -192,7 +192,7 @@ self.assertEquals(headers['Content-length'], '290') self.assertTrue('tarek' in req.data) - @unittest2.skipUnless(DOCUTILS_SUPPORT, 'needs docutils') + @unittest.skipUnless(DOCUTILS_SUPPORT, 'needs docutils') def test_strict(self): # testing the script option # when on, the register command stops if @@ -250,7 +250,7 @@ self.assertEquals(data['requires_dist'], ['lxml']) def test_suite(): - return unittest2.makeSuite(RegisterTestCase) + return unittest.makeSuite(RegisterTestCase) if __name__ == "__main__": - unittest2.main(defaultTest="test_suite") + unittest.main(defaultTest="test_suite") diff --git a/src/distutils2/tests/test_sdist.py b/src/distutils2/tests/test_sdist.py --- a/src/distutils2/tests/test_sdist.py +++ b/src/distutils2/tests/test_sdist.py @@ -1,6 +1,5 @@ """Tests for distutils.command.sdist.""" import os -import unittest2 import shutil import zipfile import tarfile @@ -29,6 +28,7 @@ from distutils2.command.sdist import sdist from distutils2.command.sdist import show_formats from distutils2.core import Distribution +from distutils2.tests.support import unittest from distutils2.tests.test_config import PyPIRCCommandTestCase from distutils2.errors import DistutilsExecError, DistutilsOptionError from distutils2.spawn import find_executable @@ -97,7 +97,7 @@ cmd.warn = _warn return dist, cmd - @unittest2.skipUnless(zlib, "requires zlib") + @unittest.skipUnless(zlib, "requires zlib") def test_prune_file_list(self): # this test creates a package with some vcs dirs in it # and launch sdist to make sure they get pruned @@ -139,7 +139,7 @@ # making sure everything has been pruned correctly self.assertEquals(len(content), 4) - @unittest2.skipUnless(zlib, "requires zlib") + @unittest.skipUnless(zlib, "requires zlib") def test_make_distribution(self): # check if tar and gzip are installed @@ -176,7 +176,7 @@ self.assertEquals(result, ['fake-1.0.tar', 'fake-1.0.tar.gz']) - @unittest2.skipUnless(zlib, "requires zlib") + @unittest.skipUnless(zlib, "requires zlib") def test_add_defaults(self): # http://bugs.python.org/issue2279 @@ -238,7 +238,7 @@ manifest = open(join(self.tmp_dir, 'MANIFEST')).read() self.assertEquals(manifest, MANIFEST % {'sep': os.sep}) - @unittest2.skipUnless(zlib, "requires zlib") + @unittest.skipUnless(zlib, "requires zlib") def test_metadata_check_option(self): # testing the `medata-check` option dist, cmd = self.get_cmd(metadata={}) @@ -293,8 +293,8 @@ cmd.formats = 'supazipa' self.assertRaises(DistutilsOptionError, cmd.finalize_options) - @unittest2.skipUnless(zlib, "requires zlib") - @unittest2.skipUnless(UID_GID_SUPPORT, "Requires grp and pwd support") + @unittest.skipUnless(zlib, "requires zlib") + @unittest.skipUnless(UID_GID_SUPPORT, "Requires grp and pwd support") def test_make_distribution_owner_group(self): # check if tar and gzip are installed @@ -357,7 +357,7 @@ self.assertIn('MANIFEST.in', cmd.filelist.files) def test_suite(): - return unittest2.makeSuite(SDistTestCase) + return unittest.makeSuite(SDistTestCase) if __name__ == "__main__": - unittest2.main(defaultTest="test_suite") + unittest.main(defaultTest="test_suite") diff --git a/src/distutils2/tests/test_spawn.py b/src/distutils2/tests/test_spawn.py --- a/src/distutils2/tests/test_spawn.py +++ b/src/distutils2/tests/test_spawn.py @@ -1,5 +1,4 @@ """Tests for distutils.spawn.""" -import unittest2 import os import time from distutils2.tests import captured_stdout @@ -8,10 +7,11 @@ from distutils2.spawn import spawn, find_executable from distutils2.errors import DistutilsExecError from distutils2.tests import support +from distutils2.tests.support import unittest class SpawnTestCase(support.TempdirManager, support.LoggingSilencer, - unittest2.TestCase): + unittest.TestCase): def test_nt_quote_args(self): @@ -23,7 +23,7 @@ self.assertEquals(res, wanted) - @unittest2.skipUnless(os.name in ('nt', 'posix'), + @unittest.skipUnless(os.name in ('nt', 'posix'), 'Runs only under posix or nt') def test_spawn(self): tmpdir = self.mkdtemp() @@ -54,7 +54,7 @@ spawn([exe]) # should work without any error def test_suite(): - return unittest2.makeSuite(SpawnTestCase) + return unittest.makeSuite(SpawnTestCase) if __name__ == "__main__": - unittest2.main(defaultTest="test_suite") + unittest.main(defaultTest="test_suite") diff --git a/src/distutils2/tests/test_unixccompiler.py b/src/distutils2/tests/test_unixccompiler.py --- a/src/distutils2/tests/test_unixccompiler.py +++ b/src/distutils2/tests/test_unixccompiler.py @@ -1,6 +1,5 @@ """Tests for distutils.unixccompiler.""" import sys -import unittest2 try: import sysconfig @@ -8,8 +7,9 @@ from distutils2._backport import sysconfig from distutils2.compiler.unixccompiler import UnixCCompiler +from distutils2.tests.support import unittest -class UnixCCompilerTestCase(unittest2.TestCase): +class UnixCCompilerTestCase(unittest.TestCase): def setUp(self): self._backup_platform = sys.platform @@ -127,7 +127,7 @@ def test_suite(): - return unittest2.makeSuite(UnixCCompilerTestCase) + return unittest.makeSuite(UnixCCompilerTestCase) if __name__ == "__main__": - unittest2.main(defaultTest="test_suite") + unittest.main(defaultTest="test_suite") diff --git a/src/distutils2/tests/test_upload.py b/src/distutils2/tests/test_upload.py --- a/src/distutils2/tests/test_upload.py +++ b/src/distutils2/tests/test_upload.py @@ -2,13 +2,13 @@ # -*- encoding: utf8 -*- import sys import os -import unittest2 from distutils2.command import upload as upload_mod from distutils2.command.upload import upload from distutils2.core import Distribution from distutils2.tests import support +from distutils2.tests.support import unittest from distutils2.tests.test_config import PYPIRC, PyPIRCCommandTestCase PYPIRC_LONG_PASSWORD = """\ @@ -126,7 +126,7 @@ self.assertFalse('\n' in auth) def test_suite(): - return unittest2.makeSuite(uploadTestCase) + return unittest.makeSuite(uploadTestCase) if __name__ == "__main__": - unittest2.main(defaultTest="test_suite") + unittest.main(defaultTest="test_suite") diff --git a/src/distutils2/tests/test_util.py b/src/distutils2/tests/test_util.py --- a/src/distutils2/tests/test_util.py +++ b/src/distutils2/tests/test_util.py @@ -1,7 +1,6 @@ """Tests for distutils.util.""" import os import sys -import unittest2 from copy import copy from StringIO import StringIO import subprocess @@ -17,6 +16,7 @@ byte_compile, find_packages) from distutils2 import util from distutils2.tests import support +from distutils2.tests.support import unittest class FakePopen(object): test_class = None @@ -34,7 +34,7 @@ class UtilTestCase(support.EnvironGuard, support.TempdirManager, - unittest2.TestCase): + unittest.TestCase): def setUp(self): super(UtilTestCase, self).setUp() @@ -243,7 +243,7 @@ res = get_compiler_versions() self.assertEquals(res[2], None) - @unittest2.skipUnless(hasattr(sys, 'dont_write_bytecode'), + @unittest.skipUnless(hasattr(sys, 'dont_write_bytecode'), 'no dont_write_bytecode support') def test_dont_write_bytecode(self): # makes sure byte_compile raise a DistutilsError @@ -298,7 +298,7 @@ def test_suite(): - return unittest2.makeSuite(UtilTestCase) + return unittest.makeSuite(UtilTestCase) if __name__ == "__main__": - unittest2.main(defaultTest="test_suite") + unittest.main(defaultTest="test_suite") diff --git a/src/distutils2/tests/test_version.py b/src/distutils2/tests/test_version.py --- a/src/distutils2/tests/test_version.py +++ b/src/distutils2/tests/test_version.py @@ -1,5 +1,4 @@ """Tests for distutils.version.""" -import unittest import doctest import os @@ -7,6 +6,7 @@ from distutils2.version import IrrationalVersionError from distutils2.version import suggest_normalized_version as suggest from distutils2.version import VersionPredicate +from distutils2.tests.support import unittest class VersionTestCase(unittest.TestCase): diff --git a/src/runtests.py b/src/runtests.py --- a/src/runtests.py +++ b/src/runtests.py @@ -26,9 +26,9 @@ if __name__ == "__main__": try: - import unittest2 + from distutils2.tests.support import unittest except ImportError: - print('!!! You need to install unittest2') + print >> sys.stderr, 'Error: You have to install unittest2' sys.exit(1) sys.exit(test_main()) -- Repository URL: http://hg.python.org/distutils2 From python-checkins at python.org Wed Jun 2 01:18:23 2010 From: python-checkins at python.org (tarek.ziade) Date: Wed, 02 Jun 2010 01:18:23 +0200 Subject: [Python-checkins] distutils2: moving cmd.py into command/ Message-ID: tarek.ziade pushed 8a30e3667a75 to distutils2: http://hg.python.org/distutils2/rev/8a30e3667a75 changeset: 197:8a30e3667a75 tag: tip user: Tarek Ziade date: Wed Jun 02 01:18:14 2010 +0200 summary: moving cmd.py into command/ files: src/distutils2/cmd.py, src/distutils2/command/cmd.py, src/distutils2/command/install_egg_info.py, src/distutils2/config.py, src/distutils2/core.py, src/distutils2/dist.py, src/distutils2/tests/test_cmd.py, src/distutils2/tests/test_dist.py diff --git a/src/distutils2/cmd.py b/src/distutils2/command/cmd.py rename from src/distutils2/cmd.py rename to src/distutils2/command/cmd.py diff --git a/src/distutils2/command/install_egg_info.py b/src/distutils2/command/install_egg_info.py --- a/src/distutils2/command/install_egg_info.py +++ b/src/distutils2/command/install_egg_info.py @@ -4,7 +4,7 @@ a package's PKG-INFO metadata.""" -from distutils2.cmd import Command +from distutils2.command.cmd import Command from distutils2 import log from distutils2._backport.shutil import rmtree import os, sys, re diff --git a/src/distutils2/config.py b/src/distutils2/config.py --- a/src/distutils2/config.py +++ b/src/distutils2/config.py @@ -6,7 +6,7 @@ import os from ConfigParser import ConfigParser -from distutils2.cmd import Command +from distutils2.command.cmd import Command DEFAULT_PYPIRC = """\ [distutils] diff --git a/src/distutils2/core.py b/src/distutils2/core.py --- a/src/distutils2/core.py +++ b/src/distutils2/core.py @@ -17,7 +17,7 @@ # Mainly import these so setup scripts can "from distutils2.core import" them. from distutils2.dist import Distribution -from distutils2.cmd import Command +from distutils2.command.cmd import Command from distutils2.config import PyPIRCCommand from distutils2.extension import Extension diff --git a/src/distutils2/dist.py b/src/distutils2/dist.py --- a/src/distutils2/dist.py +++ b/src/distutils2/dist.py @@ -493,7 +493,7 @@ None if the user asked for help on this command. """ # late import because of mutual dependence between these modules - from distutils2.cmd import Command + from distutils2.command.cmd import Command # Pull the current command from the head of the command line command = args[0] @@ -607,7 +607,7 @@ """ # late import because of mutual dependence between these modules from distutils2.core import gen_usage - from distutils2.cmd import Command + from distutils2.command.cmd import Command if global_options: if display_options: @@ -904,7 +904,7 @@ Returns the reinitialized command object. """ - from distutils2.cmd import Command + from distutils2.command.cmd import Command if not isinstance(command, Command): command_name = command command = self.get_command_obj(command_name) diff --git a/src/distutils2/tests/test_cmd.py b/src/distutils2/tests/test_cmd.py --- a/src/distutils2/tests/test_cmd.py +++ b/src/distutils2/tests/test_cmd.py @@ -2,7 +2,7 @@ import os from distutils2.tests import captured_stdout, run_unittest -from distutils2.cmd import Command +from distutils2.command.cmd import Command from distutils2.dist import Distribution from distutils2.errors import DistutilsOptionError from distutils2.tests.support import unittest diff --git a/src/distutils2/tests/test_dist.py b/src/distutils2/tests/test_dist.py --- a/src/distutils2/tests/test_dist.py +++ b/src/distutils2/tests/test_dist.py @@ -8,7 +8,7 @@ import textwrap from distutils2.dist import Distribution, fix_help_options, DistributionMetadata -from distutils2.cmd import Command +from distutils2.command.cmd import Command import distutils2.dist from distutils2.tests import TESTFN, captured_stdout from distutils2.tests import support -- Repository URL: http://hg.python.org/distutils2 From python-checkins at python.org Wed Jun 2 01:21:12 2010 From: python-checkins at python.org (georg.brandl) Date: Wed, 2 Jun 2010 01:21:12 +0200 (CEST) Subject: [Python-checkins] r81644 - in python/branches/release26-maint: Doc/library/re.rst Message-ID: <20100601232112.9BF95F107@mail.python.org> Author: georg.brandl Date: Wed Jun 2 01:21:12 2010 New Revision: 81644 Log: Merged revisions 81635 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81635 | georg.brandl | 2010-06-01 09:25:23 +0200 (Di, 01 Jun 2010) | 1 line Put docs for RegexObject.search() before RegexObject.match() to mirror re.search() and re.match() order. ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Doc/library/re.rst Modified: python/branches/release26-maint/Doc/library/re.rst ============================================================================== --- python/branches/release26-maint/Doc/library/re.rst (original) +++ python/branches/release26-maint/Doc/library/re.rst Wed Jun 2 01:21:12 2010 @@ -677,18 +677,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 @@ -700,24 +694,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]) From solipsis at pitrou.net Wed Jun 2 01:23:18 2010 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Wed, 2 Jun 2010 01:23:18 +0200 (CEST) Subject: [Python-checkins] Daily py3k reference leaks (r81642): sum=0 Message-ID: <20100601232318.A66871770A@ns6635.ovh.net> py3k results for svn r81642 (hg cset a5d9c6f86abc) -------------------------------------------------- Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/py3k/refleaks/reflogkKBlc4', '-x'] From python-checkins at python.org Wed Jun 2 04:19:15 2010 From: python-checkins at python.org (senthil.kumaran) Date: Wed, 2 Jun 2010 04:19:15 +0200 (CEST) Subject: [Python-checkins] r81645 - python/trunk/Doc/library/urllib.rst Message-ID: <20100602021915.BA201EE983@mail.python.org> Author: senthil.kumaran Date: Wed Jun 2 04:19:15 2010 New Revision: 81645 Log: Fix issue8788 - description of doseq parameter in urllib.urlencode Modified: python/trunk/Doc/library/urllib.rst Modified: python/trunk/Doc/library/urllib.rst ============================================================================== --- python/trunk/Doc/library/urllib.rst (original) +++ python/trunk/Doc/library/urllib.rst Wed Jun 2 04:19:15 2010 @@ -236,17 +236,19 @@ .. function:: urlencode(query[, doseq]) - 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. If the optional parameter *doseq* is present and - evaluates to true, individual ``key=value`` pairs are generated for each element - of the sequence. 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 order of parameters in the encoded string will match the order of parameter - tuples in the sequence. The :mod:`urlparse` module provides the functions + 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. The :mod:`urlparse` module provides the functions :func:`parse_qs` and :func:`parse_qsl` which are used to parse query strings into Python data structures. From python-checkins at python.org Wed Jun 2 04:22:00 2010 From: python-checkins at python.org (senthil.kumaran) Date: Wed, 2 Jun 2010 04:22:00 +0200 (CEST) Subject: [Python-checkins] r81646 - in python/branches/release26-maint: Doc/library/urllib.rst Message-ID: <20100602022200.7F3BBEE983@mail.python.org> Author: senthil.kumaran Date: Wed Jun 2 04:22:00 2010 New Revision: 81646 Log: Merged revisions 81645 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81645 | senthil.kumaran | 2010-06-02 07:49:15 +0530 (Wed, 02 Jun 2010) | 3 lines Fix issue8788 - description of doseq parameter in urllib.urlencode ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Doc/library/urllib.rst Modified: python/branches/release26-maint/Doc/library/urllib.rst ============================================================================== --- python/branches/release26-maint/Doc/library/urllib.rst (original) +++ python/branches/release26-maint/Doc/library/urllib.rst Wed Jun 2 04:22:00 2010 @@ -236,17 +236,19 @@ .. function:: urlencode(query[, doseq]) - 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. If the optional parameter *doseq* is present and - evaluates to true, individual ``key=value`` pairs are generated for each element - of the sequence. 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 order of parameters in the encoded string will match the order of parameter - tuples in the sequence. The :mod:`urlparse` module provides the functions + 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. The :mod:`urlparse` module provides the functions :func:`parse_qs` and :func:`parse_qsl` which are used to parse query strings into Python data structures. From python-checkins at python.org Wed Jun 2 04:29:00 2010 From: python-checkins at python.org (senthil.kumaran) Date: Wed, 2 Jun 2010 04:29:00 +0200 (CEST) Subject: [Python-checkins] r81647 - in python/branches/py3k: Doc/library/urllib.parse.rst Message-ID: <20100602022900.ABCBAEE990@mail.python.org> Author: senthil.kumaran Date: Wed Jun 2 04:29:00 2010 New Revision: 81647 Log: Merged revisions 81645 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81645 | senthil.kumaran | 2010-06-02 07:49:15 +0530 (Wed, 02 Jun 2010) | 3 lines Fix issue8788 - description of doseq parameter in urllib.urlencode ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Doc/library/urllib.parse.rst Modified: python/branches/py3k/Doc/library/urllib.parse.rst ============================================================================== --- python/branches/py3k/Doc/library/urllib.parse.rst (original) +++ python/branches/py3k/Doc/library/urllib.parse.rst Wed Jun 2 04:29:00 2010 @@ -312,19 +312,21 @@ .. function:: urlencode(query, doseq=False) - 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. If the optional parameter *doseq* is present and - evaluates to true, individual ``key=value`` pairs are generated for each element - of the sequence. 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 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 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. .. seealso:: From python-checkins at python.org Wed Jun 2 04:31:04 2010 From: python-checkins at python.org (senthil.kumaran) Date: Wed, 2 Jun 2010 04:31:04 +0200 (CEST) Subject: [Python-checkins] r81648 - in python/branches/release31-maint: Doc/library/urllib.parse.rst Message-ID: <20100602023104.7D70EEE9A5@mail.python.org> Author: senthil.kumaran Date: Wed Jun 2 04:31:04 2010 New Revision: 81648 Log: Merged revisions 81647 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ................ r81647 | senthil.kumaran | 2010-06-02 07:59:00 +0530 (Wed, 02 Jun 2010) | 9 lines Merged revisions 81645 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81645 | senthil.kumaran | 2010-06-02 07:49:15 +0530 (Wed, 02 Jun 2010) | 3 lines Fix issue8788 - description of doseq parameter in urllib.urlencode ........ ................ Modified: python/branches/release31-maint/ (props changed) python/branches/release31-maint/Doc/library/urllib.parse.rst Modified: python/branches/release31-maint/Doc/library/urllib.parse.rst ============================================================================== --- python/branches/release31-maint/Doc/library/urllib.parse.rst (original) +++ python/branches/release31-maint/Doc/library/urllib.parse.rst Wed Jun 2 04:31:04 2010 @@ -309,19 +309,21 @@ .. function:: urlencode(query, doseq=False) - 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. If the optional parameter *doseq* is present and - evaluates to true, individual ``key=value`` pairs are generated for each element - of the sequence. 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 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 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. .. seealso:: From python-checkins at python.org Wed Jun 2 05:47:14 2010 From: python-checkins at python.org (ronald.oussoren) Date: Wed, 2 Jun 2010 05:47:14 +0200 (CEST) Subject: [Python-checkins] r81649 - in python/trunk: Mac/Tools/pythonw.c Misc/NEWS Message-ID: <20100602034714.9975AEE990@mail.python.org> Author: ronald.oussoren Date: Wed Jun 2 05:47:14 2010 New Revision: 81649 Log: Fix for issue8868: without this patch 'MacOS.WMAvailable()' will return False on MacOSX 10.5 or earlier and scripts won't be able to access GUI functionality. Modified: python/trunk/Mac/Tools/pythonw.c python/trunk/Misc/NEWS Modified: python/trunk/Mac/Tools/pythonw.c ============================================================================== --- python/trunk/Mac/Tools/pythonw.c (original) +++ python/trunk/Mac/Tools/pythonw.c Wed Jun 2 05:47:14 2010 @@ -149,6 +149,14 @@ main(int argc, char **argv) { char* exec_path = get_python_path(); + /* + * Let argv[0] refer to the new interpreter. This is needed to + * get the effect we want on OSX 10.5 or earlier. That is, without + * changing argv[0] the real interpreter won't have access to + * the Window Server. + */ + argv[0] = exec_path; + #ifdef HAVE_SPAWN_H /* We're weak-linking to posix-spawnv to ensure that Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Wed Jun 2 05:47:14 2010 @@ -32,6 +32,9 @@ - Issue #7079: Fix a possible crash when closing a file object while using it from another thread. Patch by Daniel Stutzbach. +- Issue #8868: Fix that ensures that python scripts have access to the + Window Server again in a framework build on MacOSX 10.5 or earlier. + C-API ----- From python-checkins at python.org Wed Jun 2 05:50:56 2010 From: python-checkins at python.org (ronald.oussoren) Date: Wed, 2 Jun 2010 05:50:56 +0200 (CEST) Subject: [Python-checkins] r81650 - in python/branches/py3k: Mac/Tools/pythonw.c Message-ID: <20100602035056.EFC74F3C4@mail.python.org> Author: ronald.oussoren Date: Wed Jun 2 05:50:56 2010 New Revision: 81650 Log: Merged revisions 81649 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81649 | ronald.oussoren | 2010-06-02 05:47:14 +0200 (Wed, 02 Jun 2010) | 5 lines Fix for issue8868: without this patch 'MacOS.WMAvailable()' will return False on MacOSX 10.5 or earlier and scripts won't be able to access GUI functionality. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Mac/Tools/pythonw.c Modified: python/branches/py3k/Mac/Tools/pythonw.c ============================================================================== --- python/branches/py3k/Mac/Tools/pythonw.c (original) +++ python/branches/py3k/Mac/Tools/pythonw.c Wed Jun 2 05:50:56 2010 @@ -151,6 +151,14 @@ main(int argc, char **argv) { char* exec_path = get_python_path(); + /* + * Let argv[0] refer to the new interpreter. This is needed to + * get the effect we want on OSX 10.5 or earlier. That is, without + * changing argv[0] the real interpreter won't have access to + * the Window Server. + */ + argv[0] = exec_path; + #ifdef HAVE_SPAWN_H /* We're weak-linking to posix-spawnv to ensure that * an executable build on 10.5 can work on 10.4. From python-checkins at python.org Wed Jun 2 12:05:31 2010 From: python-checkins at python.org (vinay.sajip) Date: Wed, 2 Jun 2010 12:05:31 +0200 (CEST) Subject: [Python-checkins] r81651 - python/trunk/Lib/logging/config.py Message-ID: <20100602100531.EE241EEA11@mail.python.org> Author: vinay.sajip Date: Wed Jun 2 12:05:31 2010 New Revision: 81651 Log: Logging: improved error reporting for BaseConfigurator.resolve(). Modified: python/trunk/Lib/logging/config.py Modified: python/trunk/Lib/logging/config.py ============================================================================== --- python/trunk/Lib/logging/config.py (original) +++ python/trunk/Lib/logging/config.py Wed Jun 2 12:05:31 2010 @@ -387,15 +387,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.""" From nnorwitz at gmail.com Wed Jun 2 13:15:31 2010 From: nnorwitz at gmail.com (Neal Norwitz) Date: Wed, 2 Jun 2010 07:15:31 -0400 Subject: [Python-checkins] Python Regression Test Failures refleak (1) Message-ID: <20100602111531.GA10528@kbk-i386-bb.psfb.org> More important issues: ---------------------- test_bz2 leaked [-84, 0, 0] references, sum=-84 Less important issues: ---------------------- From python-checkins at python.org Wed Jun 2 19:08:47 2010 From: python-checkins at python.org (antoine.pitrou) Date: Wed, 2 Jun 2010 19:08:47 +0200 (CEST) Subject: [Python-checkins] r81652 - python/trunk/Doc/library/subprocess.rst Message-ID: <20100602170847.2DF41EEA87@mail.python.org> Author: antoine.pitrou Date: Wed Jun 2 19:08:47 2010 New Revision: 81652 Log: Issue #8873: add a documentation note about possible performance issues with the default of unbuffered IO in subprocess.Popen. Modified: python/trunk/Doc/library/subprocess.rst Modified: python/trunk/Doc/library/subprocess.rst ============================================================================== --- python/trunk/Doc/library/subprocess.rst (original) +++ python/trunk/Doc/library/subprocess.rst Wed Jun 2 19:08:47 2010 @@ -94,6 +94,12 @@ size. A negative *bufsize* means to use the system default, which usually means fully buffered. The default value for *bufsize* is :const:`0` (unbuffered). + .. note:: + + If you experience performance issues, it is recommended that you try to + enable buffering by setting *bufsize* to either -1 or a large enough + positive value (such as 4096). + The *executable* argument specifies the program to execute. It is very seldom needed: Usually, the program to execute is defined by the *args* argument. If ``shell=True``, the *executable* argument specifies which shell to use. On Unix, From python-checkins at python.org Wed Jun 2 19:10:46 2010 From: python-checkins at python.org (antoine.pitrou) Date: Wed, 2 Jun 2010 19:10:46 +0200 (CEST) Subject: [Python-checkins] r81653 - in python/branches/release26-maint: Doc/library/subprocess.rst Message-ID: <20100602171046.16090CA7D@mail.python.org> Author: antoine.pitrou Date: Wed Jun 2 19:10:45 2010 New Revision: 81653 Log: Merged revisions 81652 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81652 | antoine.pitrou | 2010-06-02 19:08:47 +0200 (mer., 02 juin 2010) | 4 lines Issue #8873: add a documentation note about possible performance issues with the default of unbuffered IO in subprocess.Popen. ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Doc/library/subprocess.rst Modified: python/branches/release26-maint/Doc/library/subprocess.rst ============================================================================== --- python/branches/release26-maint/Doc/library/subprocess.rst (original) +++ python/branches/release26-maint/Doc/library/subprocess.rst Wed Jun 2 19:10:45 2010 @@ -94,6 +94,12 @@ size. A negative *bufsize* means to use the system default, which usually means fully buffered. The default value for *bufsize* is :const:`0` (unbuffered). + .. note:: + + If you experience performance issues, it is recommended that you try to + enable buffering by setting *bufsize* to either -1 or a large enough + positive value (such as 4096). + The *executable* argument specifies the program to execute. It is very seldom needed: Usually, the program to execute is defined by the *args* argument. If ``shell=True``, the *executable* argument specifies which shell to use. On Unix, From python-checkins at python.org Wed Jun 2 19:10:49 2010 From: python-checkins at python.org (antoine.pitrou) Date: Wed, 2 Jun 2010 19:10:49 +0200 (CEST) Subject: [Python-checkins] r81654 - in python/branches/py3k: Doc/library/subprocess.rst Message-ID: <20100602171049.402A1EEAB6@mail.python.org> Author: antoine.pitrou Date: Wed Jun 2 19:10:49 2010 New Revision: 81654 Log: Merged revisions 81652 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81652 | antoine.pitrou | 2010-06-02 19:08:47 +0200 (mer., 02 juin 2010) | 4 lines Issue #8873: add a documentation note about possible performance issues with the default of unbuffered IO in subprocess.Popen. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Doc/library/subprocess.rst Modified: python/branches/py3k/Doc/library/subprocess.rst ============================================================================== --- python/branches/py3k/Doc/library/subprocess.rst (original) +++ python/branches/py3k/Doc/library/subprocess.rst Wed Jun 2 19:10:49 2010 @@ -89,6 +89,12 @@ size. A negative *bufsize* means to use the system default, which usually means fully buffered. The default value for *bufsize* is :const:`0` (unbuffered). + .. note:: + + If you experience performance issues, it is recommended that you try to + enable buffering by setting *bufsize* to either -1 or a large enough + positive value (such as 4096). + The *executable* argument specifies the program to execute. It is very seldom needed: Usually, the program to execute is defined by the *args* argument. If ``shell=True``, the *executable* argument specifies which shell to use. On Unix, From python-checkins at python.org Wed Jun 2 19:11:32 2010 From: python-checkins at python.org (antoine.pitrou) Date: Wed, 2 Jun 2010 19:11:32 +0200 (CEST) Subject: [Python-checkins] r81655 - in python/branches/release31-maint: Doc/library/subprocess.rst Message-ID: <20100602171132.561D0EEAC1@mail.python.org> Author: antoine.pitrou Date: Wed Jun 2 19:11:32 2010 New Revision: 81655 Log: Merged revisions 81654 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ................ r81654 | antoine.pitrou | 2010-06-02 19:10:49 +0200 (mer., 02 juin 2010) | 10 lines Merged revisions 81652 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81652 | antoine.pitrou | 2010-06-02 19:08:47 +0200 (mer., 02 juin 2010) | 4 lines Issue #8873: add a documentation note about possible performance issues with the default of unbuffered IO in subprocess.Popen. ........ ................ Modified: python/branches/release31-maint/ (props changed) python/branches/release31-maint/Doc/library/subprocess.rst Modified: python/branches/release31-maint/Doc/library/subprocess.rst ============================================================================== --- python/branches/release31-maint/Doc/library/subprocess.rst (original) +++ python/branches/release31-maint/Doc/library/subprocess.rst Wed Jun 2 19:11:32 2010 @@ -88,6 +88,12 @@ size. A negative *bufsize* means to use the system default, which usually means fully buffered. The default value for *bufsize* is :const:`0` (unbuffered). + .. note:: + + If you experience performance issues, it is recommended that you try to + enable buffering by setting *bufsize* to either -1 or a large enough + positive value (such as 4096). + The *executable* argument specifies the program to execute. It is very seldom needed: Usually, the program to execute is defined by the *args* argument. If ``shell=True``, the *executable* argument specifies which shell to use. On Unix, From python-checkins at python.org Wed Jun 2 20:10:09 2010 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 2 Jun 2010 20:10:09 +0200 (CEST) Subject: [Python-checkins] r81656 - python/branches/py3k/Doc/library/dis.rst Message-ID: <20100602181009.4D524EEA98@mail.python.org> Author: benjamin.peterson Date: Wed Jun 2 20:10:09 2010 New Revision: 81656 Log: remove description of LOAD_LOCALS #8874 Modified: python/branches/py3k/Doc/library/dis.rst Modified: python/branches/py3k/Doc/library/dis.rst ============================================================================== --- python/branches/py3k/Doc/library/dis.rst (original) +++ python/branches/py3k/Doc/library/dis.rst Wed Jun 2 20:10:09 2010 @@ -383,13 +383,6 @@ the stack so that it is available for further iterations of the loop. -.. opcode:: LOAD_LOCALS () - - Pushes a reference to the locals of the current scope on the stack. This is used - in the code for a class definition: After the class body is evaluated, the - locals are passed to the class definition. - - .. opcode:: RETURN_VALUE () Returns with TOS to the caller of the function. From python-checkins at python.org Wed Jun 2 20:47:26 2010 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 2 Jun 2010 20:47:26 +0200 (CEST) Subject: [Python-checkins] r81657 - in python/branches/release31-maint: Doc/library/dis.rst Message-ID: <20100602184726.55B34EEA20@mail.python.org> Author: benjamin.peterson Date: Wed Jun 2 20:47:26 2010 New Revision: 81657 Log: Merged revisions 81656 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ........ r81656 | benjamin.peterson | 2010-06-02 13:10:09 -0500 (Wed, 02 Jun 2010) | 1 line remove description of LOAD_LOCALS #8874 ........ Modified: python/branches/release31-maint/ (props changed) python/branches/release31-maint/Doc/library/dis.rst Modified: python/branches/release31-maint/Doc/library/dis.rst ============================================================================== --- python/branches/release31-maint/Doc/library/dis.rst (original) +++ python/branches/release31-maint/Doc/library/dis.rst Wed Jun 2 20:47:26 2010 @@ -383,13 +383,6 @@ the stack so that it is available for further iterations of the loop. -.. opcode:: LOAD_LOCALS () - - Pushes a reference to the locals of the current scope on the stack. This is used - in the code for a class definition: After the class body is evaluated, the - locals are passed to the class definition. - - .. opcode:: RETURN_VALUE () Returns with TOS to the caller of the function. From python-checkins at python.org Thu Jun 3 00:03:15 2010 From: python-checkins at python.org (r.david.murray) Date: Thu, 3 Jun 2010 00:03:15 +0200 (CEST) Subject: [Python-checkins] r81658 - in python/trunk: Doc/library/email.message.rst Doc/library/email.mime.rst Lib/email/message.py Lib/email/test/test_email.py Misc/NEWS Message-ID: <20100602220315.E4AF6EEA78@mail.python.org> Author: r.david.murray Date: Thu Jun 3 00:03:15 2010 New Revision: 81658 Log: #1368247: make set_charset/MIMEText automatically encode unicode _payload. Fixes (mysterious, to the end user) UnicodeErrors when using utf-8 as the charset and unicode as the _text argument. Also makes the way in which unicode gets encoded to quoted printable for other charsets more sane (it only worked by accident previously). The _payload now is encoded to the charset.output_charset if it is unicode. Modified: python/trunk/Doc/library/email.message.rst python/trunk/Doc/library/email.mime.rst python/trunk/Lib/email/message.py python/trunk/Lib/email/test/test_email.py python/trunk/Misc/NEWS Modified: python/trunk/Doc/library/email.message.rst ============================================================================== --- python/trunk/Doc/library/email.message.rst (original) +++ python/trunk/Doc/library/email.message.rst Thu Jun 3 00:03:15 2010 @@ -136,9 +136,10 @@ :mailheader:`Content-Type` header. Anything else will generate a :exc:`TypeError`. - The message will be assumed to be of type :mimetype:`text/\*` encoded with - *charset.input_charset*. It will be converted to *charset.output_charset* - and encoded properly, if needed, when generating the plain text + The message will be assumed to be of type :mimetype:`text/\*`, with the + payload either in unicode or encoded with *charset.input_charset*. + It will be encoded or converted to *charset.output_charset* + and transfer encoded properly, if needed, when generating the plain text representation of the message. MIME headers (:mailheader:`MIME-Version`, :mailheader:`Content-Type`, :mailheader:`Content-Transfer-Encoding`) will be added as needed. Modified: python/trunk/Doc/library/email.mime.rst ============================================================================== --- python/trunk/Doc/library/email.mime.rst (original) +++ python/trunk/Doc/library/email.mime.rst Thu Jun 3 00:03:15 2010 @@ -191,9 +191,11 @@ minor type and defaults to :mimetype:`plain`. *_charset* is the character set of the text and is passed as a parameter to the :class:`~email.mime.nonmultipart.MIMENonMultipart` constructor; it defaults - to ``us-ascii``. No guessing or encoding is performed on the text data. + to ``us-ascii``. If *_text* is unicode, it is encoded using the + *output_charset* of *_charset*, otherwise it is used as-is. .. versionchanged:: 2.4 - The previously deprecated *_encoding* argument has been removed. Encoding - happens implicitly based on the *_charset* argument. + The previously deprecated *_encoding* argument has been removed. Content + Transfer Encoding now happens happens implicitly based on the *_charset* + argument. Modified: python/trunk/Lib/email/message.py ============================================================================== --- python/trunk/Lib/email/message.py (original) +++ python/trunk/Lib/email/message.py Thu Jun 3 00:03:15 2010 @@ -256,6 +256,8 @@ charset=charset.get_output_charset()) else: self.set_param('charset', charset.get_output_charset()) + if isinstance(self._payload, unicode): + self._payload = self._payload.encode(charset.output_charset) if str(charset) != charset.get_output_charset(): self._payload = charset.body_encode(self._payload) if 'Content-Transfer-Encoding' not in self: Modified: python/trunk/Lib/email/test/test_email.py ============================================================================== --- python/trunk/Lib/email/test/test_email.py (original) +++ python/trunk/Lib/email/test/test_email.py Thu Jun 3 00:03:15 2010 @@ -1045,6 +1045,31 @@ eq(msg.get_charset().input_charset, 'us-ascii') eq(msg['content-type'], 'text/plain; charset="us-ascii"') + def test_7bit_unicode_input(self): + eq = self.assertEqual + msg = MIMEText(u'hello there', _charset='us-ascii') + eq(msg.get_charset().input_charset, 'us-ascii') + eq(msg['content-type'], 'text/plain; charset="us-ascii"') + + def test_7bit_unicode_input_no_charset(self): + eq = self.assertEqual + msg = MIMEText(u'hello there') + eq(msg.get_charset(), 'us-ascii') + eq(msg['content-type'], 'text/plain; charset="us-ascii"') + self.assertTrue('hello there' in msg.as_string()) + + def test_8bit_unicode_input(self): + teststr = u'\u043a\u0438\u0440\u0438\u043b\u0438\u0446\u0430' + eq = self.assertEqual + msg = MIMEText(teststr, _charset='utf-8') + eq(msg.get_charset().output_charset, 'utf-8') + eq(msg['content-type'], 'text/plain; charset="utf-8"') + eq(msg.get_payload(decode=True), teststr.encode('utf-8')) + + def test_8bit_unicode_input_no_charset(self): + teststr = u'\u043a\u0438\u0440\u0438\u043b\u0438\u0446\u0430' + self.assertRaises(UnicodeEncodeError, MIMEText, teststr) + # Test complicated multipart/* messages Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Thu Jun 3 00:03:15 2010 @@ -46,6 +46,9 @@ Library ------- +- Issue #1368247: set_charset (and therefore MIMEText) now automatically + encodes a unicode _payload to the output_charset. + - Issue #7150: Raise OverflowError if the result of adding or subtracting timedelta from date or datetime falls outside of the MINYEAR:MAXYEAR range. From python-checkins at python.org Thu Jun 3 00:11:01 2010 From: python-checkins at python.org (r.david.murray) Date: Thu, 3 Jun 2010 00:11:01 +0200 (CEST) Subject: [Python-checkins] r81659 - in python/branches/release26-maint: Doc/library/email.message.rst Doc/library/email.mime.rst Lib/email/message.py Lib/email/test/test_email.py Misc/NEWS Message-ID: <20100602221101.4325BEEA7C@mail.python.org> Author: r.david.murray Date: Thu Jun 3 00:11:01 2010 New Revision: 81659 Log: Merged revisions 81658 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81658 | r.david.murray | 2010-06-02 18:03:15 -0400 (Wed, 02 Jun 2010) | 9 lines #1368247: make set_charset/MIMEText automatically encode unicode _payload. Fixes (mysterious, to the end user) UnicodeErrors when using utf-8 as the charset and unicode as the _text argument. Also makes the way in which unicode gets encoded to quoted printable for other charsets more sane (it only worked by accident previously). The _payload now is encoded to the charset.output_charset if it is unicode. ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Doc/library/email.message.rst python/branches/release26-maint/Doc/library/email.mime.rst python/branches/release26-maint/Lib/email/message.py python/branches/release26-maint/Lib/email/test/test_email.py python/branches/release26-maint/Misc/NEWS Modified: python/branches/release26-maint/Doc/library/email.message.rst ============================================================================== --- python/branches/release26-maint/Doc/library/email.message.rst (original) +++ python/branches/release26-maint/Doc/library/email.message.rst Thu Jun 3 00:11:01 2010 @@ -136,9 +136,10 @@ :mailheader:`Content-Type` header. Anything else will generate a :exc:`TypeError`. - The message will be assumed to be of type :mimetype:`text/\*` encoded with - *charset.input_charset*. It will be converted to *charset.output_charset* - and encoded properly, if needed, when generating the plain text + The message will be assumed to be of type :mimetype:`text/\*`, with the + payload either in unicode or encoded with *charset.input_charset*. + It will be encoded or converted to *charset.output_charset* + and transfer encoded properly, if needed, when generating the plain text representation of the message. MIME headers (:mailheader:`MIME-Version`, :mailheader:`Content-Type`, :mailheader:`Content-Transfer-Encoding`) will be added as needed. Modified: python/branches/release26-maint/Doc/library/email.mime.rst ============================================================================== --- python/branches/release26-maint/Doc/library/email.mime.rst (original) +++ python/branches/release26-maint/Doc/library/email.mime.rst Thu Jun 3 00:11:01 2010 @@ -191,9 +191,11 @@ minor type and defaults to :mimetype:`plain`. *_charset* is the character set of the text and is passed as a parameter to the :class:`~email.mime.nonmultipart.MIMENonMultipart` constructor; it defaults - to ``us-ascii``. No guessing or encoding is performed on the text data. + to ``us-ascii``. If *_text* is unicode, it is encoded using the + *output_charset* of *_charset*, otherwise it is used as-is. .. versionchanged:: 2.4 - The previously deprecated *_encoding* argument has been removed. Encoding - happens implicitly based on the *_charset* argument. + The previously deprecated *_encoding* argument has been removed. Content + Transfer Encoding now happens happens implicitly based on the *_charset* + argument. Modified: python/branches/release26-maint/Lib/email/message.py ============================================================================== --- python/branches/release26-maint/Lib/email/message.py (original) +++ python/branches/release26-maint/Lib/email/message.py Thu Jun 3 00:11:01 2010 @@ -256,6 +256,8 @@ charset=charset.get_output_charset()) else: self.set_param('charset', charset.get_output_charset()) + if isinstance(self._payload, unicode): + self._payload = self._payload.encode(charset.output_charset) if str(charset) != charset.get_output_charset(): self._payload = charset.body_encode(self._payload) if not self.has_key('Content-Transfer-Encoding'): Modified: python/branches/release26-maint/Lib/email/test/test_email.py ============================================================================== --- python/branches/release26-maint/Lib/email/test/test_email.py (original) +++ python/branches/release26-maint/Lib/email/test/test_email.py Thu Jun 3 00:11:01 2010 @@ -1025,6 +1025,31 @@ eq(msg.get_charset().input_charset, 'us-ascii') eq(msg['content-type'], 'text/plain; charset="us-ascii"') + def test_7bit_unicode_input(self): + eq = self.assertEqual + msg = MIMEText(u'hello there', _charset='us-ascii') + eq(msg.get_charset().input_charset, 'us-ascii') + eq(msg['content-type'], 'text/plain; charset="us-ascii"') + + def test_7bit_unicode_input_no_charset(self): + eq = self.assertEqual + msg = MIMEText(u'hello there') + eq(msg.get_charset(), 'us-ascii') + eq(msg['content-type'], 'text/plain; charset="us-ascii"') + self.assertTrue('hello there' in msg.as_string()) + + def test_8bit_unicode_input(self): + teststr = u'\u043a\u0438\u0440\u0438\u043b\u0438\u0446\u0430' + eq = self.assertEqual + msg = MIMEText(teststr, _charset='utf-8') + eq(msg.get_charset().output_charset, 'utf-8') + eq(msg['content-type'], 'text/plain; charset="utf-8"') + eq(msg.get_payload(decode=True), teststr.encode('utf-8')) + + def test_8bit_unicode_input_no_charset(self): + teststr = u'\u043a\u0438\u0440\u0438\u043b\u0438\u0446\u0430' + self.assertRaises(UnicodeEncodeError, MIMEText, teststr) + # Test complicated multipart/* messages Modified: python/branches/release26-maint/Misc/NEWS ============================================================================== --- python/branches/release26-maint/Misc/NEWS (original) +++ python/branches/release26-maint/Misc/NEWS Thu Jun 3 00:11:01 2010 @@ -58,6 +58,9 @@ Library ------- +- Issue #1368247: set_charset (and therefore MIMEText) now automatically + encodes a unicode _payload to the output_charset. + - Issue #7150: Raise OverflowError if the result of adding or subtracting timedelta from date or datetime falls outside of the MINYEAR:MAXYEAR range. From solipsis at pitrou.net Thu Jun 3 01:23:54 2010 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Thu, 3 Jun 2010 01:23:54 +0200 (CEST) Subject: [Python-checkins] Daily py3k reference leaks (r81656): sum=0 Message-ID: <20100602232354.AA63E1770A@ns6635.ovh.net> py3k results for svn r81656 (hg cset a3a8e8822cf8) -------------------------------------------------- Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/py3k/refleaks/reflogdMwVjq', '-x'] From python-checkins at python.org Thu Jun 3 03:58:29 2010 From: python-checkins at python.org (r.david.murray) Date: Thu, 3 Jun 2010 03:58:29 +0200 (CEST) Subject: [Python-checkins] r81660 - in python/branches/py3k: Lib/email/charset.py Lib/email/test/test_email.py Misc/NEWS Message-ID: <20100603015829.3C9D3EE9B3@mail.python.org> Author: r.david.murray Date: Thu Jun 3 03:58:28 2010 New Revision: 81660 Log: Fix Charset.body_encode to encode to output_charset before calling base64mime. This means that what gets encoded in base64 is the encoded version of the unicode payload. This bug was revealed by a forward port of the tests from Issue 1368247, but the fix was completely different. Note that the merge is only of the tests, the doc changes were inappropriate since email5 expects unicode, not bytes. I'm also not convinced that quopri works correctly in email5, but that's a different issue. Merged revisions 81658 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81658 | r.david.murray | 2010-06-02 18:03:15 -0400 (Wed, 02 Jun 2010) | 9 lines #1368247: make set_charset/MIMEText automatically encode unicode _payload. Fixes (mysterious, to the end user) UnicodeErrors when using utf-8 as the charset and unicode as the _text argument. Also makes the way in which unicode gets encoded to quoted printable for other charsets more sane (it only worked by accident previously). The _payload now is encoded to the charset.output_charset if it is unicode. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/email/charset.py python/branches/py3k/Lib/email/test/test_email.py python/branches/py3k/Misc/NEWS Modified: python/branches/py3k/Lib/email/charset.py ============================================================================== --- python/branches/py3k/Lib/email/charset.py (original) +++ python/branches/py3k/Lib/email/charset.py Thu Jun 3 03:58:28 2010 @@ -377,6 +377,8 @@ """ # 7bit/8bit encodings return the string unchanged (module conversions) if self.body_encoding is BASE64: + if isinstance(string, str): + string = string.encode(self.output_charset) return email.base64mime.body_encode(string) elif self.body_encoding is QP: return email.quoprimime.body_encode(string) Modified: python/branches/py3k/Lib/email/test/test_email.py ============================================================================== --- python/branches/py3k/Lib/email/test/test_email.py (original) +++ python/branches/py3k/Lib/email/test/test_email.py Thu Jun 3 03:58:28 2010 @@ -535,7 +535,7 @@ # whose output character set is 7bit gets a transfer-encoding # of 7bit. eq = self.assertEqual - msg = MIMEText('\xca\xb8', _charset='euc-jp') + msg = MIMEText('?', _charset='euc-jp') eq(msg['content-transfer-encoding'], '7bit') @@ -1080,6 +1080,33 @@ eq(msg.get_charset().input_charset, 'us-ascii') eq(msg['content-type'], 'text/plain; charset="us-ascii"') + def test_7bit_input(self): + eq = self.assertEqual + msg = MIMEText('hello there', _charset='us-ascii') + eq(msg.get_charset().input_charset, 'us-ascii') + eq(msg['content-type'], 'text/plain; charset="us-ascii"') + + def test_7bit_input_no_charset(self): + eq = self.assertEqual + msg = MIMEText('hello there') + eq(msg.get_charset(), 'us-ascii') + eq(msg['content-type'], 'text/plain; charset="us-ascii"') + self.assertTrue('hello there' in msg.as_string()) + + def test_utf8_input(self): + teststr = '\u043a\u0438\u0440\u0438\u043b\u0438\u0446\u0430' + eq = self.assertEqual + msg = MIMEText(teststr, _charset='utf-8') + eq(msg.get_charset().output_charset, 'utf-8') + eq(msg['content-type'], 'text/plain; charset="utf-8"') + eq(msg.get_payload(decode=True), teststr.encode('utf-8')) + + @unittest.skip("can't fix because of backward compat in email5, " + "will fix in email6") + def test_utf8_input_no_charset(self): + teststr = '\u043a\u0438\u0440\u0438\u043b\u0438\u0446\u0430' + self.assertRaises(UnicodeEncodeError, MIMEText, teststr) + # Test complicated multipart/* messages Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Thu Jun 3 03:58:28 2010 @@ -398,6 +398,10 @@ Library ------- +- Charset.body_encode now correctly handles base64 encoding by encoding + with the output_charset before calling base64mime.encode. Passes the + tests from 2.x issue 1368247. + - Issue #8845: sqlite3 Connection objects now have a read-only in_transaction attribute that is True iff there are uncommitted changes. From python-checkins at python.org Thu Jun 3 04:05:47 2010 From: python-checkins at python.org (r.david.murray) Date: Thu, 3 Jun 2010 04:05:47 +0200 (CEST) Subject: [Python-checkins] r81661 - in python/branches/release31-maint: Lib/email/charset.py Lib/email/test/test_email.py Misc/NEWS Message-ID: <20100603020547.BD821EE9A0@mail.python.org> Author: r.david.murray Date: Thu Jun 3 04:05:47 2010 New Revision: 81661 Log: Merged revisions 81660 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ................ r81660 | r.david.murray | 2010-06-02 21:58:28 -0400 (Wed, 02 Jun 2010) | 25 lines Fix Charset.body_encode to encode to output_charset before calling base64mime. This means that what gets encoded in base64 is the encoded version of the unicode payload. This bug was revealed by a forward port of the tests from Issue 1368247, but the fix was completely different. Note that the merge is only of the tests, the doc changes were inappropriate since email5 expects unicode, not bytes. I'm also not convinced that quopri works correctly in email5, but that's a different issue. Merged revisions 81658 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81658 | r.david.murray | 2010-06-02 18:03:15 -0400 (Wed, 02 Jun 2010) | 9 lines #1368247: make set_charset/MIMEText automatically encode unicode _payload. Fixes (mysterious, to the end user) UnicodeErrors when using utf-8 as the charset and unicode as the _text argument. Also makes the way in which unicode gets encoded to quoted printable for other charsets more sane (it only worked by accident previously). The _payload now is encoded to the charset.output_charset if it is unicode. ........ ................ Modified: python/branches/release31-maint/ (props changed) python/branches/release31-maint/Lib/email/charset.py python/branches/release31-maint/Lib/email/test/test_email.py python/branches/release31-maint/Misc/NEWS Modified: python/branches/release31-maint/Lib/email/charset.py ============================================================================== --- python/branches/release31-maint/Lib/email/charset.py (original) +++ python/branches/release31-maint/Lib/email/charset.py Thu Jun 3 04:05:47 2010 @@ -377,6 +377,8 @@ """ # 7bit/8bit encodings return the string unchanged (module conversions) if self.body_encoding is BASE64: + if isinstance(string, str): + string = string.encode(self.output_charset) return email.base64mime.body_encode(string) elif self.body_encoding is QP: return email.quoprimime.body_encode(string) Modified: python/branches/release31-maint/Lib/email/test/test_email.py ============================================================================== --- python/branches/release31-maint/Lib/email/test/test_email.py (original) +++ python/branches/release31-maint/Lib/email/test/test_email.py Thu Jun 3 04:05:47 2010 @@ -531,7 +531,7 @@ # whose output character set is 7bit gets a transfer-encoding # of 7bit. eq = self.assertEqual - msg = MIMEText('\xca\xb8', _charset='euc-jp') + msg = MIMEText('?', _charset='euc-jp') eq(msg['content-transfer-encoding'], '7bit') @@ -1076,6 +1076,33 @@ eq(msg.get_charset().input_charset, 'us-ascii') eq(msg['content-type'], 'text/plain; charset="us-ascii"') + def test_7bit_input(self): + eq = self.assertEqual + msg = MIMEText('hello there', _charset='us-ascii') + eq(msg.get_charset().input_charset, 'us-ascii') + eq(msg['content-type'], 'text/plain; charset="us-ascii"') + + def test_7bit_input_no_charset(self): + eq = self.assertEqual + msg = MIMEText('hello there') + eq(msg.get_charset(), 'us-ascii') + eq(msg['content-type'], 'text/plain; charset="us-ascii"') + self.assertTrue('hello there' in msg.as_string()) + + def test_utf8_input(self): + teststr = '\u043a\u0438\u0440\u0438\u043b\u0438\u0446\u0430' + eq = self.assertEqual + msg = MIMEText(teststr, _charset='utf-8') + eq(msg.get_charset().output_charset, 'utf-8') + eq(msg['content-type'], 'text/plain; charset="utf-8"') + eq(msg.get_payload(decode=True), teststr.encode('utf-8')) + + @unittest.skip("can't fix because of backward compat in email5, " + "will fix in email6") + def test_utf8_input_no_charset(self): + teststr = '\u043a\u0438\u0440\u0438\u043b\u0438\u0446\u0430' + self.assertRaises(UnicodeEncodeError, MIMEText, teststr) + # Test complicated multipart/* messages Modified: python/branches/release31-maint/Misc/NEWS ============================================================================== --- python/branches/release31-maint/Misc/NEWS (original) +++ python/branches/release31-maint/Misc/NEWS Thu Jun 3 04:05:47 2010 @@ -54,6 +54,10 @@ Library ------- +- Charset.body_encode now correctly handles base64 encoding by encoding + with the output_charset before calling base64mime.encode. Passes the + tests from 2.x issue 1368247. + - Issue #7150: Raise OverflowError if the result of adding or subtracting timedelta from date or datetime falls outside of the MINYEAR:MAXYEAR range. From python-checkins at python.org Thu Jun 3 11:47:22 2010 From: python-checkins at python.org (ronald.oussoren) Date: Thu, 3 Jun 2010 11:47:22 +0200 (CEST) Subject: [Python-checkins] r81662 - in python/trunk: Lib/distutils/unixccompiler.py setup.py Message-ID: <20100603094722.03CC3EE9B3@mail.python.org> Author: ronald.oussoren Date: Thu Jun 3 11:47:21 2010 New Revision: 81662 Log: Fix for issue #7724: ensure that distutils and python's own setup.py honor the MacOSX SDK when one is specified. This is needed to be able to build using the 10.4u SDK while running on OSX 10.6. This is a fixed version of the patch in r80963, I've tested this patch on OSX and Linux. Modified: python/trunk/Lib/distutils/unixccompiler.py python/trunk/setup.py Modified: python/trunk/Lib/distutils/unixccompiler.py ============================================================================== --- python/trunk/Lib/distutils/unixccompiler.py (original) +++ python/trunk/Lib/distutils/unixccompiler.py Thu Jun 3 11:47:21 2010 @@ -15,7 +15,7 @@ __revision__ = "$Id$" -import os, sys +import os, sys, re from types import StringType, NoneType from distutils import sysconfig @@ -305,10 +305,30 @@ dylib_f = self.library_filename(lib, lib_type='dylib') static_f = self.library_filename(lib, lib_type='static') + if sys.platform == 'darwin': + # On OSX users can specify an alternate SDK using + # '-isysroot', calculate the SDK root if it is specified + # (and use it further on) + cflags = sysconfig.get_config_var('CFLAGS') + m = re.search(r'-isysroot\s+(\S+)', cflags) + if m is None: + sysroot = '/' + else: + sysroot = m.group(1) + + + for dir in dirs: shared = os.path.join(dir, shared_f) dylib = os.path.join(dir, dylib_f) static = os.path.join(dir, static_f) + + if sys.platform == 'darwin' and ( + dir.startswith('/System/') or dir.startswith('/usr/')): + 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) + # We're second-guessing the linker here, with not much hard # data to go on: GCC seems to prefer the shared library, so I'm # assuming that *all* Unix C compilers do. And of course I'm Modified: python/trunk/setup.py ============================================================================== --- python/trunk/setup.py (original) +++ python/trunk/setup.py Thu Jun 3 11:47:21 2010 @@ -29,6 +29,25 @@ if dir is not None and os.path.isdir(dir) and dir not in dirlist: dirlist.insert(0, dir) +def macosx_sdk_root(): + """ + Return the directory of the current OSX SDK, + or '/' if no SDK was specified. + """ + cflags = sysconfig.get_config_var('CFLAGS') + m = re.search(r'-isysroot\s+(\S+)', cflags) + if m is None: + sysroot = '/' + else: + sysroot = m.group(1) + return sysroot + +def is_macosx_sdk_path(path): + """ + Returns True if 'path' can be located in an OSX SDK + """ + return path.startswith('/usr/') or path.startswith('/System/') + def find_file(filename, std_dirs, paths): """Searches for the directory where a given file is located, and returns a possibly-empty list of additional directories, or None @@ -40,15 +59,28 @@ 'paths' is a list of additional locations to check; if the file is found in one of them, the resulting list will contain the directory. """ + if sys.platform == 'darwin': + # Honor the MacOSX SDK setting when one was specified. + # An SDK is a directory with the same structure as a real + # system, but with only header files and libraries. + sysroot = macosx_sdk_root() # Check the standard locations for dir in std_dirs: f = os.path.join(dir, filename) + + if sys.platform == 'darwin' and is_macosx_sdk_path(dir): + f = os.path.join(sysroot, dir[1:], filename) + if os.path.exists(f): return [] # Check the additional directories for dir in paths: f = os.path.join(dir, filename) + + if sys.platform == 'darwin' and is_macosx_sdk_path(dir): + f = os.path.join(sysroot, dir[1:], filename) + if os.path.exists(f): return [dir] @@ -60,11 +92,19 @@ if result is None: return None + if sys.platform == 'darwin': + sysroot = macosx_sdk_root() + # Check whether the found file is in one of the standard directories dirname = os.path.dirname(result) for p in std_dirs: # Ensure path doesn't end with path separator p = p.rstrip(os.sep) + + if sys.platform == 'darwin' and is_macosx_sdk_path(p): + if os.path.join(sysroot, p[1:]) == dirname: + return [ ] + if p == dirname: return [ ] @@ -73,6 +113,11 @@ for p in paths: # Ensure path doesn't end with path separator p = p.rstrip(os.sep) + + if sys.platform == 'darwin' and is_macosx_sdk_path(p): + if os.path.join(sysroot, p[1:]) == dirname: + return [ p ] + if p == dirname: return [p] else: @@ -560,7 +605,7 @@ # library and then a static library, instead of first looking # for dynamic libraries on the entiry path. # This way a staticly linked custom readline gets picked up - # before the (broken) dynamic library in /usr/lib. + # before the (possibly broken) dynamic library in /usr/lib. readline_extra_link_args = ('-Wl,-search_paths_first',) else: readline_extra_link_args = () @@ -631,24 +676,24 @@ openssl_ver = 0 openssl_ver_re = re.compile( '^\s*#\s*define\s+OPENSSL_VERSION_NUMBER\s+(0x[0-9a-fA-F]+)' ) - for ssl_inc_dir in inc_dirs + search_for_ssl_incs_in: - name = os.path.join(ssl_inc_dir, 'openssl', 'opensslv.h') - if os.path.isfile(name): - try: - incfile = open(name, 'r') - for line in incfile: - m = openssl_ver_re.match(line) - if m: - openssl_ver = eval(m.group(1)) - break - except IOError: - pass - # first version found is what we'll use (as the compiler should) - if openssl_ver: - break + # look for the openssl version header on the compiler search path. + opensslv_h = find_file('openssl/opensslv.h', [], + inc_dirs + search_for_ssl_incs_in) + if opensslv_h: + name = os.path.join(opensslv_h[0], 'openssl/opensslv.h') + if sys.platform == 'darwin' and is_macosx_sdk_path(name): + name = os.path.join(macosx_sdk_root(), name[1:]) + try: + incfile = open(name, 'r') + for line in incfile: + m = openssl_ver_re.match(line) + if m: + openssl_ver = eval(m.group(1)) + except IOError, msg: + print "IOError while reading opensshv.h:", msg + pass - #print 'openssl_ver = 0x%08x' % openssl_ver min_openssl_ver = 0x00907000 have_any_openssl = ssl_incs is not None and ssl_libs is not None have_usable_openssl = (have_any_openssl and @@ -781,12 +826,19 @@ db_ver_inc_map = {} + if sys.platform == 'darwin': + sysroot = macosx_sdk_root() + class db_found(Exception): pass try: # See whether there is a Sleepycat header in the standard # search path. for d in inc_dirs + db_inc_paths: f = os.path.join(d, "db.h") + + if sys.platform == 'darwin' and is_macosx_sdk_path(d): + f = os.path.join(sysroot, d[1:], "db.h") + if db_setup_debug: print "db: looking for db.h in", f if os.path.exists(f): f = open(f).read() @@ -833,7 +885,20 @@ db_incdir.replace("include", 'lib64'), db_incdir.replace("include", 'lib'), ] - db_dirs_to_check = filter(os.path.isdir, db_dirs_to_check) + + if sys.platform != 'darwin': + db_dirs_to_check = filter(os.path.isdir, db_dirs_to_check) + + else: + # Same as other branch, but takes OSX SDK into account + tmp = [] + for dn in db_dirs_to_check: + if is_macosx_sdk_path(dn): + if os.path.isdir(os.path.join(sysroot, dn[1:])): + tmp.append(dn) + else: + if os.path.isdir(dn): + tmp.append(dn) # Look for a version specific db-X.Y before an ambiguoius dbX # XXX should we -ever- look for a dbX name? Do any @@ -895,8 +960,15 @@ # Scan the default include directories before the SQLite specific # ones. This allows one to override the copy of sqlite on OSX, # where /usr/include contains an old version of sqlite. + if sys.platform == 'darwin': + sysroot = macosx_sdk_root() + for d in inc_dirs + sqlite_inc_paths: f = os.path.join(d, "sqlite3.h") + + if sys.platform == 'darwin' and is_macosx_sdk_path(d): + f = os.path.join(sysroot, d[1:], "sqlite3.h") + if os.path.exists(f): if sqlite_setup_debug: print "sqlite: found %s"%f incf = open(f).read() @@ -984,6 +1056,12 @@ # the more recent berkeleydb's db.h file first in the include path # when attempting to compile and it will fail. f = "/usr/include/db.h" + + if sys.platform == 'darwin': + if is_macosx_sdk_path(f): + sysroot = macosx_sdk_root() + f = os.path.join(sysroot, f[1:]) + if os.path.exists(f) and not db_incs: data = open(f).read() m = re.search(r"#s*define\s+HASHVERSION\s+2\s*", data) @@ -1490,14 +1568,22 @@ join(os.getenv('HOME'), '/Library/Frameworks') ] + sysroot = macosx_sdk_root() + # Find the directory that contains the Tcl.framework and Tk.framework # bundles. # XXX distutils should support -F! for F in framework_dirs: # both Tcl.framework and Tk.framework should be present + + for fw in 'Tcl', 'Tk': - if not exists(join(F, fw + '.framework')): - break + if is_macosx_sdk_path(F): + if not exists(join(sysroot, F[1:], fw + '.framework')): + break + else: + if not exists(join(F, fw + '.framework')): + break else: # ok, F is now directory with both frameworks. Continure # building @@ -1527,7 +1613,12 @@ # architectures. cflags = sysconfig.get_config_vars('CFLAGS')[0] archs = re.findall('-arch\s+(\w+)', cflags) - fp = os.popen("file %s/Tk.framework/Tk | grep 'for architecture'"%(F,)) + + if is_macosx_sdk_path(F): + fp = os.popen("file %s/Tk.framework/Tk | grep 'for architecture'"%(os.path.join(sysroot, F[1:]),)) + else: + fp = os.popen("file %s/Tk.framework/Tk | grep 'for architecture'"%(F,)) + detected_archs = [] for ln in fp: a = ln.split()[-1] From python-checkins at python.org Thu Jun 3 11:56:22 2010 From: python-checkins at python.org (lars.gustaebel) Date: Thu, 3 Jun 2010 11:56:22 +0200 (CEST) Subject: [Python-checkins] r81663 - in python/trunk: Lib/tarfile.py Lib/test/test_tarfile.py Misc/NEWS Message-ID: <20100603095622.DC4A4EE9B3@mail.python.org> Author: lars.gustaebel Date: Thu Jun 3 11:56:22 2010 New Revision: 81663 Log: Issue #8833: tarfile created hard link entries with a size field != 0 by mistake. The associated testcase did not expose this bug because it was broken too. Modified: python/trunk/Lib/tarfile.py python/trunk/Lib/test/test_tarfile.py python/trunk/Misc/NEWS Modified: python/trunk/Lib/tarfile.py ============================================================================== --- python/trunk/Lib/tarfile.py (original) +++ python/trunk/Lib/tarfile.py Thu Jun 3 11:56:22 2010 @@ -1884,7 +1884,7 @@ tarinfo.mode = stmd tarinfo.uid = statres.st_uid tarinfo.gid = statres.st_gid - if stat.S_ISREG(stmd): + if type == REGTYPE: tarinfo.size = statres.st_size else: tarinfo.size = 0L Modified: python/trunk/Lib/test/test_tarfile.py ============================================================================== --- python/trunk/Lib/test/test_tarfile.py (original) +++ python/trunk/Lib/test/test_tarfile.py Thu Jun 3 11:56:22 2010 @@ -662,10 +662,14 @@ if hasattr(os, "link"): link = os.path.join(TEMPDIR, "link") target = os.path.join(TEMPDIR, "link_target") - open(target, "wb").close() + fobj = open(target, "wb") + fobj.write("aaa") + fobj.close() os.link(target, link) try: tar = tarfile.open(tmpname, self.mode) + # Record the link target in the inodes list. + tar.gettarinfo(target) tarinfo = tar.gettarinfo(link) self.assertEqual(tarinfo.size, 0) finally: Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Thu Jun 3 11:56:22 2010 @@ -46,6 +46,9 @@ Library ------- +- Issue #8833: tarfile created hard link entries with a size field != 0 by + mistake. + - Issue #1368247: set_charset (and therefore MIMEText) now automatically encodes a unicode _payload to the output_charset. From python-checkins at python.org Thu Jun 3 12:07:09 2010 From: python-checkins at python.org (lars.gustaebel) Date: Thu, 3 Jun 2010 12:07:09 +0200 (CEST) Subject: [Python-checkins] r81664 - in python/branches/release26-maint: Lib/tarfile.py Lib/test/test_tarfile.py Misc/NEWS Message-ID: <20100603100709.09018EE9A4@mail.python.org> Author: lars.gustaebel Date: Thu Jun 3 12:07:08 2010 New Revision: 81664 Log: Merged revisions 81663 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81663 | lars.gustaebel | 2010-06-03 11:56:22 +0200 (Thu, 03 Jun 2010) | 4 lines Issue #8833: tarfile created hard link entries with a size field != 0 by mistake. The associated testcase did not expose this bug because it was broken too. ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Lib/tarfile.py python/branches/release26-maint/Lib/test/test_tarfile.py python/branches/release26-maint/Misc/NEWS Modified: python/branches/release26-maint/Lib/tarfile.py ============================================================================== --- python/branches/release26-maint/Lib/tarfile.py (original) +++ python/branches/release26-maint/Lib/tarfile.py Thu Jun 3 12:07:08 2010 @@ -1880,7 +1880,7 @@ tarinfo.mode = stmd tarinfo.uid = statres.st_uid tarinfo.gid = statres.st_gid - if stat.S_ISREG(stmd): + if type == REGTYPE: tarinfo.size = statres.st_size else: tarinfo.size = 0L Modified: python/branches/release26-maint/Lib/test/test_tarfile.py ============================================================================== --- python/branches/release26-maint/Lib/test/test_tarfile.py (original) +++ python/branches/release26-maint/Lib/test/test_tarfile.py Thu Jun 3 12:07:08 2010 @@ -617,10 +617,14 @@ if hasattr(os, "link"): link = os.path.join(TEMPDIR, "link") target = os.path.join(TEMPDIR, "link_target") - open(target, "wb").close() + fobj = open(target, "wb") + fobj.write("aaa") + fobj.close() os.link(target, link) try: tar = tarfile.open(tmpname, self.mode) + # Record the link target in the inodes list. + tar.gettarinfo(target) tarinfo = tar.gettarinfo(link) self.assertEqual(tarinfo.size, 0) finally: Modified: python/branches/release26-maint/Misc/NEWS ============================================================================== --- python/branches/release26-maint/Misc/NEWS (original) +++ python/branches/release26-maint/Misc/NEWS Thu Jun 3 12:07:08 2010 @@ -58,6 +58,9 @@ Library ------- +- Issue #8833: tarfile created hard link entries with a size field != 0 by + mistake. + - Issue #1368247: set_charset (and therefore MIMEText) now automatically encodes a unicode _payload to the output_charset. From python-checkins at python.org Thu Jun 3 12:11:52 2010 From: python-checkins at python.org (lars.gustaebel) Date: Thu, 3 Jun 2010 12:11:52 +0200 (CEST) Subject: [Python-checkins] r81665 - in python/branches/py3k: Lib/tarfile.py Lib/test/test_tarfile.py Misc/NEWS Message-ID: <20100603101152.A9B60EE986@mail.python.org> Author: lars.gustaebel Date: Thu Jun 3 12:11:52 2010 New Revision: 81665 Log: Merged revisions 81663 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81663 | lars.gustaebel | 2010-06-03 11:56:22 +0200 (Thu, 03 Jun 2010) | 4 lines Issue #8833: tarfile created hard link entries with a size field != 0 by mistake. The associated testcase did not expose this bug because it was broken too. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/tarfile.py python/branches/py3k/Lib/test/test_tarfile.py python/branches/py3k/Misc/NEWS Modified: python/branches/py3k/Lib/tarfile.py ============================================================================== --- python/branches/py3k/Lib/tarfile.py (original) +++ python/branches/py3k/Lib/tarfile.py Thu Jun 3 12:11:52 2010 @@ -1920,7 +1920,7 @@ tarinfo.mode = stmd tarinfo.uid = statres.st_uid tarinfo.gid = statres.st_gid - if stat.S_ISREG(stmd): + if type == REGTYPE: tarinfo.size = statres.st_size else: tarinfo.size = 0 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 Jun 3 12:11:52 2010 @@ -661,10 +661,14 @@ if hasattr(os, "link"): link = os.path.join(TEMPDIR, "link") target = os.path.join(TEMPDIR, "link_target") - open(target, "wb").close() + fobj = open(target, "wb") + fobj.write(b"aaa") + fobj.close() os.link(target, link) try: tar = tarfile.open(tmpname, self.mode) + # Record the link target in the inodes list. + tar.gettarinfo(target) tarinfo = tar.gettarinfo(link) self.assertEqual(tarinfo.size, 0) finally: Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Thu Jun 3 12:11:52 2010 @@ -398,6 +398,9 @@ Library ------- +- Issue #8833: tarfile created hard link entries with a size field != 0 by + mistake. + - Charset.body_encode now correctly handles base64 encoding by encoding with the output_charset before calling base64mime.encode. Passes the tests from 2.x issue 1368247. From python-checkins at python.org Thu Jun 3 12:15:18 2010 From: python-checkins at python.org (lars.gustaebel) Date: Thu, 3 Jun 2010 12:15:18 +0200 (CEST) Subject: [Python-checkins] r81666 - in python/branches/release31-maint: Lib/tarfile.py Lib/test/test_tarfile.py Misc/NEWS Message-ID: <20100603101518.E86B4EEAE6@mail.python.org> Author: lars.gustaebel Date: Thu Jun 3 12:15:18 2010 New Revision: 81666 Log: Merged revisions 81665 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ................ r81665 | lars.gustaebel | 2010-06-03 12:11:52 +0200 (Thu, 03 Jun 2010) | 11 lines Merged revisions 81663 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81663 | lars.gustaebel | 2010-06-03 11:56:22 +0200 (Thu, 03 Jun 2010) | 4 lines Issue #8833: tarfile created hard link entries with a size field != 0 by mistake. The associated testcase did not expose this bug because it was broken too. ........ ................ Modified: python/branches/release31-maint/ (props changed) python/branches/release31-maint/Lib/tarfile.py python/branches/release31-maint/Lib/test/test_tarfile.py python/branches/release31-maint/Misc/NEWS Modified: python/branches/release31-maint/Lib/tarfile.py ============================================================================== --- python/branches/release31-maint/Lib/tarfile.py (original) +++ python/branches/release31-maint/Lib/tarfile.py Thu Jun 3 12:15:18 2010 @@ -1857,7 +1857,7 @@ tarinfo.mode = stmd tarinfo.uid = statres.st_uid tarinfo.gid = statres.st_gid - if stat.S_ISREG(stmd): + if type == REGTYPE: tarinfo.size = statres.st_size else: tarinfo.size = 0 Modified: python/branches/release31-maint/Lib/test/test_tarfile.py ============================================================================== --- python/branches/release31-maint/Lib/test/test_tarfile.py (original) +++ python/branches/release31-maint/Lib/test/test_tarfile.py Thu Jun 3 12:15:18 2010 @@ -616,10 +616,14 @@ if hasattr(os, "link"): link = os.path.join(TEMPDIR, "link") target = os.path.join(TEMPDIR, "link_target") - open(target, "wb").close() + fobj = open(target, "wb") + fobj.write(b"aaa") + fobj.close() os.link(target, link) try: tar = tarfile.open(tmpname, self.mode) + # Record the link target in the inodes list. + tar.gettarinfo(target) tarinfo = tar.gettarinfo(link) self.assertEqual(tarinfo.size, 0) finally: Modified: python/branches/release31-maint/Misc/NEWS ============================================================================== --- python/branches/release31-maint/Misc/NEWS (original) +++ python/branches/release31-maint/Misc/NEWS Thu Jun 3 12:15:18 2010 @@ -54,6 +54,9 @@ Library ------- +- Issue #8833: tarfile created hard link entries with a size field != 0 by + mistake. + - Charset.body_encode now correctly handles base64 encoding by encoding with the output_charset before calling base64mime.encode. Passes the tests from 2.x issue 1368247. From nnorwitz at gmail.com Thu Jun 3 14:06:26 2010 From: nnorwitz at gmail.com (Neal Norwitz) Date: Thu, 3 Jun 2010 08:06:26 -0400 Subject: [Python-checkins] Python Regression Test Failures all (1) Message-ID: <20100603120626.GA10422@kbk-i386-bb.psfb.org> 352 tests OK. 1 test failed: test_smtplib 28 tests skipped: test_aepack test_al test_applesingle test_bsddb185 test_cd test_cl test_epoll test_gdb test_gl test_imgfile test_ioctl test_kqueue test_macos test_macostools test_multiprocessing test_pep277 test_py3kwarn test_scriptpackages test_startfile test_sunaudiodev test_tcl test_tk test_ttk_guionly test_ttk_textonly test_unicode_file 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.7b2+ (trunk:81661M, Jun 3 2010, 04:01:39) [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_5552 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 Sleepycat Software: Berkeley DB 4.1.25: (December 19, 2002) Test path prefix: /tmp/z-test_bsddb3-5552 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 testCompileLibrary still working, be patient... testCompileLibrary still working, be patient... 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_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 [20673 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 [16678 refs] [16678 refs] [16678 refs] [26966 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_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 [16678 refs] [16678 refs] 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 [18074 refs] [18074 refs] test_plistlib test_poll test_popen [16683 refs] [16683 refs] [16683 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 [21890 refs] [21890 refs] [21890 refs] [21890 refs] [21890 refs] [21889 refs] [21889 refs] test_pyexpat test_queue test_quopri [19507 refs] [19507 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 [16678 refs] [16678 refs] [16678 refs] [16678 refs] test_slice test_smtplib test test_smtplib failed -- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_smtplib.py", line 235, in testSend smtp.quit() File "/tmp/python-test/local/lib/python2.7/smtplib.py", line 733, in quit res = self.docmd("quit") File "/tmp/python-test/local/lib/python2.7/smtplib.py", line 366, in docmd return self.getreply() File "/tmp/python-test/local/lib/python2.7/smtplib.py", line 343, in getreply raise SMTPServerDisconnected("Connection unexpectedly closed") SMTPServerDisconnected: Connection unexpectedly closed Re-running test 'test_smtplib' in verbose mode testBasic1 (test.test_smtplib.GeneralTests) ... ok testBasic2 (test.test_smtplib.GeneralTests) ... ok testLocalHostName (test.test_smtplib.GeneralTests) ... ok testTimeoutDefault (test.test_smtplib.GeneralTests) ... ok testTimeoutNone (test.test_smtplib.GeneralTests) ... ok testTimeoutValue (test.test_smtplib.GeneralTests) ... ok testBasic (test.test_smtplib.DebuggingServerTests) ... ok testHELP (test.test_smtplib.DebuggingServerTests) ... ERROR testNOOP (test.test_smtplib.DebuggingServerTests) ... ok testNotImplemented (test.test_smtplib.DebuggingServerTests) ... ok testRSET (test.test_smtplib.DebuggingServerTests) ... ok testSecondHELO (test.test_smtplib.DebuggingServerTests) ... ok testSend (test.test_smtplib.DebuggingServerTests) ... ok testVRFY (test.test_smtplib.DebuggingServerTests) ... ok testNonnumericPort (test.test_smtplib.NonConnectingTests) ... ok testNotConnected (test.test_smtplib.NonConnectingTests) ... ok testFailingHELO (test.test_smtplib.BadHELOServerTests) ... ok testAUTH_CRAM_MD5 (test.test_smtplib.SMTPSimTests) ... ok testAUTH_LOGIN (test.test_smtplib.SMTPSimTests) ... ok testAUTH_PLAIN (test.test_smtplib.SMTPSimTests) ... ok testBasic (test.test_smtplib.SMTPSimTests) ... ok testEHLO (test.test_smtplib.SMTPSimTests) ... ok testEXPN (test.test_smtplib.SMTPSimTests) ... ok testVRFY (test.test_smtplib.SMTPSimTests) ... ok ====================================================================== ERROR: testHELP (test.test_smtplib.DebuggingServerTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_smtplib.py", line 222, in testHELP smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=3) File "/tmp/python-test/local/lib/python2.7/smtplib.py", line 239, in __init__ (code, msg) = self.connect(host, port) File "/tmp/python-test/local/lib/python2.7/smtplib.py", line 296, in connect (code, msg) = self.getreply() File "/tmp/python-test/local/lib/python2.7/smtplib.py", line 343, in getreply raise SMTPServerDisconnected("Connection unexpectedly closed") SMTPServerDisconnected: Connection unexpectedly closed ---------------------------------------------------------------------- Ran 24 tests in 16.683s FAILED (errors=1) test test_smtplib failed -- Traceback (most recent call last): File "/tmp/python-test/local/lib/python2.7/test/test_smtplib.py", line 222, in testHELP smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=3) File "/tmp/python-test/local/lib/python2.7/smtplib.py", line 239, in __init__ (code, msg) = self.connect(host, port) File "/tmp/python-test/local/lib/python2.7/smtplib.py", line 296, in connect (code, msg) = self.getreply() File "/tmp/python-test/local/lib/python2.7/smtplib.py", line 343, in getreply raise SMTPServerDisconnected("Connection unexpectedly closed") SMTPServerDisconnected: Connection unexpectedly closed test_smtpnet test_socket test_socketserver 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 [16678 refs] [16678 refs] [16678 refs] [16678 refs] [16678 refs] [16678 refs] [16678 refs] [16678 refs] [16678 refs] [16678 refs] [16678 refs] [16678 refs] [16678 refs] [16678 refs] [16893 refs] [16678 refs] [16678 refs] [16678 refs] [16678 refs] [16678 refs] . [16678 refs] [16678 refs] this bit of output is from a test of stdout in a different process ... [16678 refs] [16678 refs] [16893 refs] [16678 refs] [16678 refs] [16678 refs] [16678 refs] [16678 refs] [16678 refs] [16678 refs] [16678 refs] [16678 refs] [16678 refs] [16678 refs] [16678 refs] [16678 refs] [16678 refs] [16678 refs] [16678 refs] [16678 refs] [16893 refs] [16678 refs] [16678 refs] [16678 refs] [16678 refs] [16678 refs] . [16678 refs] [16678 refs] this bit of output is from a test of stdout in a different process ... [16678 refs] [16678 refs] [16893 refs] test_sunaudiodev test_sunaudiodev skipped -- No module named sunaudiodev test_sundry test_symtable test_syntax test_sys [16678 refs] [16678 refs] [16678 refs] [16907 refs] [16701 refs] test_sysconfig [16678 refs] [16678 refs] test_tarfile test_tcl test_tcl skipped -- No module named _tkinter test_telnetlib test_tempfile [16678 refs] test_textwrap test_thread test_threaded_import test_threadedtempfile test_threading [19978 refs] [22149 refs] [21061 refs] [21061 refs] [21061 refs] [21061 refs] test_threading_local test_threadsignals test_time test_timeout 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_urllibnet test_urlparse test_userdict test_userlist test_userstring test_uu test_uuid test_wait3 test_wait4 test_warnings [16709 refs] [16709 refs] [16702 refs] [16709 refs] [16709 refs] [16702 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 sh: line 1: python2.4: command not found sh: line 1: python2.6: command not found 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 352 tests OK. 1 test failed: test_smtplib 28 tests skipped: test_aepack test_al test_applesingle test_bsddb185 test_cd test_cl test_epoll test_gdb test_gl test_imgfile test_ioctl test_kqueue test_macos test_macostools test_multiprocessing test_pep277 test_py3kwarn test_scriptpackages test_startfile test_sunaudiodev test_tcl test_tk test_ttk_guionly test_ttk_textonly test_unicode_file 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 [983760 refs] From python-checkins at python.org Thu Jun 3 14:34:14 2010 From: python-checkins at python.org (lars.gustaebel) Date: Thu, 3 Jun 2010 14:34:14 +0200 (CEST) Subject: [Python-checkins] r81667 - in python/trunk/Lib: tarfile.py test/test_tarfile.py test/testtar.tar Message-ID: <20100603123414.41830EE989@mail.python.org> Author: lars.gustaebel Date: Thu Jun 3 14:34:14 2010 New Revision: 81667 Log: Issue #8741: Fixed the TarFile.makelink() method that is responsible for extracting symbolic and hard link entries as regular files as a work-around on platforms that do not support filesystem links. This stopped working reliably after a change in r74571. I also added a few tests for this functionality. Modified: python/trunk/Lib/tarfile.py python/trunk/Lib/test/test_tarfile.py python/trunk/Lib/test/testtar.tar Modified: python/trunk/Lib/tarfile.py ============================================================================== --- python/trunk/Lib/tarfile.py (original) +++ python/trunk/Lib/tarfile.py Thu Jun 3 14:34:14 2010 @@ -2127,8 +2127,7 @@ raise StreamError("cannot extract (sym)link as file object") else: # A (sym)link's file object is its target's file object. - return self.extractfile(self._getmember(tarinfo.linkname, - tarinfo)) + return self.extractfile(self._find_link_target(tarinfo)) else: # If there's no data associated with the member (directory, chrdev, # blkdev, etc.), return None instead of a file object. @@ -2237,27 +2236,21 @@ (platform limitation), we try to make a copy of the referenced file instead of a link. """ - try: + if hasattr(os, "symlink") and hasattr(os, "link"): + # For systems that support symbolic and hard links. if tarinfo.issym(): os.symlink(tarinfo.linkname, targetpath) else: # See extract(). - os.link(tarinfo._link_target, targetpath) - except AttributeError: - if tarinfo.issym(): - linkpath = os.path.dirname(tarinfo.name) + "/" + \ - tarinfo.linkname - else: - linkpath = tarinfo.linkname - + if os.path.exists(tarinfo._link_target): + os.link(tarinfo._link_target, targetpath) + else: + self._extract_member(self._find_link_target(tarinfo), targetpath) + else: try: - self._extract_member(self.getmember(linkpath), targetpath) - except (EnvironmentError, KeyError), e: - linkpath = linkpath.replace("/", os.sep) - try: - shutil.copy2(linkpath, targetpath) - except EnvironmentError, e: - raise IOError("link could not be created") + self._extract_member(self._find_link_target(tarinfo), targetpath) + except KeyError: + raise ExtractError("unable to resolve link inside archive") def chown(self, tarinfo, targetpath): """Set owner of targetpath according to tarinfo. @@ -2356,21 +2349,28 @@ #-------------------------------------------------------------------------- # Little helper methods: - def _getmember(self, name, tarinfo=None): + def _getmember(self, name, tarinfo=None, normalize=False): """Find an archive member by name from bottom to top. If tarinfo is given, it is used as the starting point. """ # Ensure that all members have been loaded. members = self.getmembers() - if tarinfo is None: - end = len(members) - else: - end = members.index(tarinfo) + # Limit the member search list up to tarinfo. + if tarinfo is not None: + members = members[:members.index(tarinfo)] - for i in xrange(end - 1, -1, -1): - if name == members[i].name: - return members[i] + if normalize: + name = os.path.normpath(name) + + for member in reversed(members): + if normalize: + member_name = os.path.normpath(member.name) + else: + member_name = member.name + + if name == member_name: + return member def _load(self): """Read through the entire archive file and look for readable @@ -2391,6 +2391,25 @@ if mode is not None and self.mode not in mode: raise IOError("bad operation for mode %r" % self.mode) + def _find_link_target(self, tarinfo): + """Find the target member of a symlink or hardlink member in the + archive. + """ + if tarinfo.issym(): + # Always search the entire archive. + linkname = os.path.dirname(tarinfo.name) + "/" + tarinfo.linkname + limit = None + else: + # Search the archive before the link, because a hard link is + # just a reference to an already archived file. + linkname = tarinfo.linkname + limit = tarinfo + + member = self._getmember(linkname, tarinfo=limit, normalize=True) + if member is None: + raise KeyError("linkname %r not found" % linkname) + return member + def __iter__(self): """Provide an iterator object. """ Modified: python/trunk/Lib/test/test_tarfile.py ============================================================================== --- python/trunk/Lib/test/test_tarfile.py (original) +++ python/trunk/Lib/test/test_tarfile.py Thu Jun 3 14:34:14 2010 @@ -134,6 +134,26 @@ "read() after readline() failed") fobj.close() + # Test if symbolic and hard links are resolved by extractfile(). The + # test link members each point to a regular member whose data is + # supposed to be exported. + def _test_fileobj_link(self, lnktype, regtype): + a = self.tar.extractfile(lnktype) + b = self.tar.extractfile(regtype) + self.assertEqual(a.name, b.name) + + def test_fileobj_link1(self): + self._test_fileobj_link("ustar/lnktype", "ustar/regtype") + + def test_fileobj_link2(self): + self._test_fileobj_link("./ustar/linktest2/lnktype", "ustar/linktest1/regtype") + + def test_fileobj_symlink1(self): + self._test_fileobj_link("ustar/symtype", "ustar/regtype") + + def test_fileobj_symlink2(self): + self._test_fileobj_link("./ustar/linktest2/symtype", "ustar/linktest1/regtype") + class CommonReadTest(ReadTest): @@ -1376,6 +1396,29 @@ fobj.close() +class LinkEmulationTest(ReadTest): + + # Test for issue #8741 regression. On platforms that do not support + # symbolic or hard links tarfile tries to extract these types of members as + # the regular files they point to. + def _test_link_extraction(self, name): + self.tar.extract(name, TEMPDIR) + data = open(os.path.join(TEMPDIR, name), "rb").read() + self.assertEqual(md5sum(data), md5_regtype) + + def test_hardlink_extraction1(self): + self._test_link_extraction("ustar/lnktype") + + def test_hardlink_extraction2(self): + self._test_link_extraction("./ustar/linktest2/lnktype") + + def test_symlink_extraction1(self): + self._test_link_extraction("ustar/symtype") + + def test_symlink_extraction2(self): + self._test_link_extraction("./ustar/linktest2/symtype") + + class GzipMiscReadTest(MiscReadTest): tarname = gzipname mode = "r:gz" @@ -1460,6 +1503,8 @@ if hasattr(os, "link"): tests.append(HardlinkTest) + else: + tests.append(LinkEmulationTest) fobj = open(tarname, "rb") data = fobj.read() Modified: python/trunk/Lib/test/testtar.tar ============================================================================== Binary files. No diff available. From python-checkins at python.org Thu Jun 3 14:38:15 2010 From: python-checkins at python.org (lars.gustaebel) Date: Thu, 3 Jun 2010 14:38:15 +0200 (CEST) Subject: [Python-checkins] r81668 - python/branches/release26-maint Message-ID: <20100603123815.AE7E3EE989@mail.python.org> Author: lars.gustaebel Date: Thu Jun 3 14:38:15 2010 New Revision: 81668 Log: Blocked revisions 81667 via svnmerge ........ r81667 | lars.gustaebel | 2010-06-03 14:34:14 +0200 (Thu, 03 Jun 2010) | 8 lines Issue #8741: Fixed the TarFile.makelink() method that is responsible for extracting symbolic and hard link entries as regular files as a work-around on platforms that do not support filesystem links. This stopped working reliably after a change in r74571. I also added a few tests for this functionality. ........ Modified: python/branches/release26-maint/ (props changed) From python-checkins at python.org Thu Jun 3 14:39:50 2010 From: python-checkins at python.org (stefan.krah) Date: Thu, 3 Jun 2010 14:39:50 +0200 (CEST) Subject: [Python-checkins] r81669 - in python/trunk: Lib/test/test_curses.py Misc/NEWS setup.py Message-ID: <20100603123950.BACCCEE9B1@mail.python.org> Author: stefan.krah Date: Thu Jun 3 14:39:50 2010 New Revision: 81669 Log: Issue #7384: If the system readline library is linked against ncurses, the curses module must be linked against ncurses as well. Otherwise it is not safe to load both the readline and curses modules in an application. Thanks Thomas Dickey for answering questions about ncurses/ncursesw and readline! Modified: python/trunk/Lib/test/test_curses.py python/trunk/Misc/NEWS python/trunk/setup.py Modified: python/trunk/Lib/test/test_curses.py ============================================================================== --- python/trunk/Lib/test/test_curses.py (original) +++ python/trunk/Lib/test/test_curses.py Thu Jun 3 14:39:50 2010 @@ -21,11 +21,6 @@ curses = import_module('curses') curses.panel = import_module('curses.panel') -# skip all these tests on FreeBSD: test_curses currently hangs the -# FreeBSD buildbots, preventing other tests from running. See issue -# #7384. -if 'freebsd' in sys.platform: - raise unittest.SkipTest('The curses module is broken on FreeBSD. See http://bugs.python.org/issue7384.') # XXX: if newterm was supported we could use it instead of initscr and not exit term = os.environ.get('TERM') Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Thu Jun 3 14:39:50 2010 @@ -89,6 +89,10 @@ Extension Modules ----------------- +- Issue #7384: If the system readline library is linked against ncurses, + the curses module must be linked against ncurses as well. Otherwise it + is not safe to load both the readline and curses modules in an application. + - Issue #2810: Fix cases where the Windows registry API returns ERROR_MORE_DATA, requiring a re-try in order to get the complete result. Modified: python/trunk/setup.py ============================================================================== --- python/trunk/setup.py (original) +++ python/trunk/setup.py Thu Jun 3 14:39:50 2010 @@ -588,6 +588,32 @@ # readline do_readline = self.compiler.find_library_file(lib_dirs, 'readline') + readline_termcap_library = "" + curses_library = "" + # Determine if readline is already linked against curses or tinfo. + if do_readline and platform != 'darwin': # OS X does not have ldd. + fp = os.popen("ldd %s" % do_readline) + for ln in fp: + if 'curses' in ln: + readline_termcap_library = re.sub( + r'.*lib(n?cursesw?)\.so.*', r'\1', ln + ).rstrip() + break + if 'tinfo' in ln: # termcap interface split out from ncurses + readline_termcap_library = 'tinfo' + break + fp.close() + # Issue 7384: If readline is already linked against curses, + # use the same library for the readline and curses modules. + if 'curses' in readline_termcap_library: + curses_library = readline_termcap_library + elif self.compiler_obj.find_library_file(lib_dirs, 'ncursesw'): + curses_library = 'ncursesw' + elif self.compiler_obj.find_library_file(lib_dirs, 'ncurses'): + curses_library = 'ncurses' + elif self.compiler_obj.find_library_file(lib_dirs, 'curses'): + curses_library = 'curses' + if platform == 'darwin': os_release = int(os.uname()[2].split('.')[0]) dep_target = sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET') @@ -611,14 +637,10 @@ readline_extra_link_args = () readline_libs = ['readline'] - if self.compiler.find_library_file(lib_dirs, - 'ncursesw'): - readline_libs.append('ncursesw') - elif self.compiler.find_library_file(lib_dirs, - 'ncurses'): - readline_libs.append('ncurses') - elif self.compiler.find_library_file(lib_dirs, 'curses'): - readline_libs.append('curses') + if readline_termcap_library: + pass # Issue 7384: Already linked against curses or tinfo. + elif curses_library: + readline_libs.append(curses_library) elif self.compiler.find_library_file(lib_dirs + ['/usr/lib/termcap'], 'termcap'): @@ -1187,19 +1209,15 @@ # Curses support, requiring the System V version of curses, often # provided by the ncurses library. panel_library = 'panel' - if (self.compiler.find_library_file(lib_dirs, 'ncursesw')): - curses_libs = ['ncursesw'] - # Bug 1464056: If _curses.so links with ncursesw, - # _curses_panel.so must link with panelw. - panel_library = 'panelw' - exts.append( Extension('_curses', ['_cursesmodule.c'], - libraries = curses_libs) ) - elif (self.compiler.find_library_file(lib_dirs, 'ncurses')): - curses_libs = ['ncurses'] + if curses_library.startswith('ncurses'): + if curses_library == 'ncursesw': + # Bug 1464056: If _curses.so links with ncursesw, + # _curses_panel.so must link with panelw. + panel_library = 'panelw' + curses_libs = [curses_library] exts.append( Extension('_curses', ['_cursesmodule.c'], libraries = curses_libs) ) - elif (self.compiler.find_library_file(lib_dirs, 'curses') - and platform != 'darwin'): + elif curses_library == 'curses' and platform != 'darwin': # OSX has an old Berkeley curses, not good enough for # the _curses module. if (self.compiler.find_library_file(lib_dirs, 'terminfo')): From python-checkins at python.org Thu Jun 3 14:45:17 2010 From: python-checkins at python.org (lars.gustaebel) Date: Thu, 3 Jun 2010 14:45:17 +0200 (CEST) Subject: [Python-checkins] r81670 - in python/branches/py3k: Lib/tarfile.py Lib/test/test_tarfile.py Lib/test/testtar.tar Message-ID: <20100603124517.281EBEEA02@mail.python.org> Author: lars.gustaebel Date: Thu Jun 3 14:45:16 2010 New Revision: 81670 Log: Merged revisions 81667 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81667 | lars.gustaebel | 2010-06-03 14:34:14 +0200 (Thu, 03 Jun 2010) | 8 lines Issue #8741: Fixed the TarFile.makelink() method that is responsible for extracting symbolic and hard link entries as regular files as a work-around on platforms that do not support filesystem links. This stopped working reliably after a change in r74571. I also added a few tests for this functionality. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/tarfile.py python/branches/py3k/Lib/test/test_tarfile.py python/branches/py3k/Lib/test/testtar.tar Modified: python/branches/py3k/Lib/tarfile.py ============================================================================== --- python/branches/py3k/Lib/tarfile.py (original) +++ python/branches/py3k/Lib/tarfile.py Thu Jun 3 14:45:16 2010 @@ -2163,8 +2163,7 @@ raise StreamError("cannot extract (sym)link as file object") else: # A (sym)link's file object is its target's file object. - return self.extractfile(self._getmember(tarinfo.linkname, - tarinfo)) + return self.extractfile(self._find_link_target(tarinfo)) else: # If there's no data associated with the member (directory, chrdev, # blkdev, etc.), return None instead of a file object. @@ -2273,27 +2272,21 @@ (platform limitation), we try to make a copy of the referenced file instead of a link. """ - try: + if hasattr(os, "symlink") and hasattr(os, "link"): + # For systems that support symbolic and hard links. if tarinfo.issym(): os.symlink(tarinfo.linkname, targetpath) else: # See extract(). - os.link(tarinfo._link_target, targetpath) - except AttributeError: - if tarinfo.issym(): - linkpath = os.path.dirname(tarinfo.name) + "/" + \ - tarinfo.linkname - else: - linkpath = tarinfo.linkname - + if os.path.exists(tarinfo._link_target): + os.link(tarinfo._link_target, targetpath) + else: + self._extract_member(self._find_link_target(tarinfo), targetpath) + else: try: - self._extract_member(self.getmember(linkpath), targetpath) - except (EnvironmentError, KeyError) as e: - linkpath = linkpath.replace("/", os.sep) - try: - shutil.copy2(linkpath, targetpath) - except EnvironmentError as e: - raise IOError("link could not be created") + self._extract_member(self._find_link_target(tarinfo), targetpath) + except KeyError: + raise ExtractError("unable to resolve link inside archive") def chown(self, tarinfo, targetpath): """Set owner of targetpath according to tarinfo. @@ -2392,21 +2385,28 @@ #-------------------------------------------------------------------------- # Little helper methods: - def _getmember(self, name, tarinfo=None): + def _getmember(self, name, tarinfo=None, normalize=False): """Find an archive member by name from bottom to top. If tarinfo is given, it is used as the starting point. """ # Ensure that all members have been loaded. members = self.getmembers() - if tarinfo is None: - end = len(members) - else: - end = members.index(tarinfo) + # Limit the member search list up to tarinfo. + if tarinfo is not None: + members = members[:members.index(tarinfo)] - for i in range(end - 1, -1, -1): - if name == members[i].name: - return members[i] + if normalize: + name = os.path.normpath(name) + + for member in reversed(members): + if normalize: + member_name = os.path.normpath(member.name) + else: + member_name = member.name + + if name == member_name: + return member def _load(self): """Read through the entire archive file and look for readable @@ -2427,6 +2427,25 @@ if mode is not None and self.mode not in mode: raise IOError("bad operation for mode %r" % self.mode) + def _find_link_target(self, tarinfo): + """Find the target member of a symlink or hardlink member in the + archive. + """ + if tarinfo.issym(): + # Always search the entire archive. + linkname = os.path.dirname(tarinfo.name) + "/" + tarinfo.linkname + limit = None + else: + # Search the archive before the link, because a hard link is + # just a reference to an already archived file. + linkname = tarinfo.linkname + limit = tarinfo + + member = self._getmember(linkname, tarinfo=limit, normalize=True) + if member is None: + raise KeyError("linkname %r not found" % linkname) + return member + def __iter__(self): """Provide an iterator object. """ 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 Jun 3 14:45:16 2010 @@ -133,6 +133,26 @@ "read() after readline() failed") fobj.close() + # Test if symbolic and hard links are resolved by extractfile(). The + # test link members each point to a regular member whose data is + # supposed to be exported. + def _test_fileobj_link(self, lnktype, regtype): + a = self.tar.extractfile(lnktype) + b = self.tar.extractfile(regtype) + self.assertEqual(a.name, b.name) + + def test_fileobj_link1(self): + self._test_fileobj_link("ustar/lnktype", "ustar/regtype") + + def test_fileobj_link2(self): + self._test_fileobj_link("./ustar/linktest2/lnktype", "ustar/linktest1/regtype") + + def test_fileobj_symlink1(self): + self._test_fileobj_link("ustar/symtype", "ustar/regtype") + + def test_fileobj_symlink2(self): + self._test_fileobj_link("./ustar/linktest2/symtype", "ustar/linktest1/regtype") + class CommonReadTest(ReadTest): @@ -1378,6 +1398,29 @@ fobj.close() +class LinkEmulationTest(ReadTest): + + # Test for issue #8741 regression. On platforms that do not support + # symbolic or hard links tarfile tries to extract these types of members as + # the regular files they point to. + def _test_link_extraction(self, name): + self.tar.extract(name, TEMPDIR) + data = open(os.path.join(TEMPDIR, name), "rb").read() + self.assertEqual(md5sum(data), md5_regtype) + + def test_hardlink_extraction1(self): + self._test_link_extraction("ustar/lnktype") + + def test_hardlink_extraction2(self): + self._test_link_extraction("./ustar/linktest2/lnktype") + + def test_symlink_extraction1(self): + self._test_link_extraction("ustar/symtype") + + def test_symlink_extraction2(self): + self._test_link_extraction("./ustar/linktest2/symtype") + + class GzipMiscReadTest(MiscReadTest): tarname = gzipname mode = "r:gz" @@ -1463,6 +1506,8 @@ if hasattr(os, "link"): tests.append(HardlinkTest) + else: + tests.append(LinkEmulationTest) fobj = open(tarname, "rb") data = fobj.read() Modified: python/branches/py3k/Lib/test/testtar.tar ============================================================================== Binary files. No diff available. From python-checkins at python.org Thu Jun 3 14:46:14 2010 From: python-checkins at python.org (lars.gustaebel) Date: Thu, 3 Jun 2010 14:46:14 +0200 (CEST) Subject: [Python-checkins] r81671 - python/branches/release31-maint Message-ID: <20100603124614.D7320EEB3A@mail.python.org> Author: lars.gustaebel Date: Thu Jun 3 14:46:14 2010 New Revision: 81671 Log: Blocked revisions 81670 via svnmerge ................ r81670 | lars.gustaebel | 2010-06-03 14:45:16 +0200 (Thu, 03 Jun 2010) | 14 lines Merged revisions 81667 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81667 | lars.gustaebel | 2010-06-03 14:34:14 +0200 (Thu, 03 Jun 2010) | 8 lines Issue #8741: Fixed the TarFile.makelink() method that is responsible for extracting symbolic and hard link entries as regular files as a work-around on platforms that do not support filesystem links. This stopped working reliably after a change in r74571. I also added a few tests for this functionality. ........ ................ Modified: python/branches/release31-maint/ (props changed) From fuzzyman at voidspace.org.uk Thu Jun 3 16:03:13 2010 From: fuzzyman at voidspace.org.uk (Michael Foord) Date: Thu, 3 Jun 2010 15:03:13 +0100 Subject: [Python-checkins] r81669 - in python/trunk: Lib/test/test_curses.py Misc/NEWS setup.py In-Reply-To: <20100603123950.BACCCEE9B1@mail.python.org> References: <20100603123950.BACCCEE9B1@mail.python.org> Message-ID: This kills the build on Mac OS X (Snow Leopard) for me: Traceback (most recent call last): File "./setup.py", line 2040, in main() File "./setup.py", line 2035, in main 'Lib/smtpd.py'] File "/compile/python-trunk/Lib/distutils/core.py", line 152, in setup dist.run_commands() File "/compile/python-trunk/Lib/distutils/dist.py", line 953, in run_commands self.run_command(cmd) File "/compile/python-trunk/Lib/distutils/dist.py", line 972, in run_command cmd_obj.run() File "/compile/python-trunk/Lib/distutils/command/build.py", line 127, in run self.run_command(cmd_name) File "/compile/python-trunk/Lib/distutils/cmd.py", line 326, in run_command self.distribution.run_command(command) File "/compile/python-trunk/Lib/distutils/dist.py", line 972, in run_command cmd_obj.run() File "/compile/python-trunk/Lib/distutils/command/build_ext.py", line 340, in run self.build_extensions() File "./setup.py", line 151, in build_extensions missing = self.detect_modules() File "./setup.py", line 610, in detect_modules elif self.compiler_obj.find_library_file(lib_dirs, 'ncursesw'): File "/compile/python-trunk/Lib/distutils/cmd.py", line 105, in __getattr__ raise AttributeError, attr AttributeError: compiler_obj [35980 refs] make: *** [sharedmods] Error 1 On 3 June 2010 13:39, stefan.krah wrote: > Author: stefan.krah > Date: Thu Jun 3 14:39:50 2010 > New Revision: 81669 > > Log: > Issue #7384: If the system readline library is linked against ncurses, > the curses module must be linked against ncurses as well. Otherwise it > is not safe to load both the readline and curses modules in an application. > > Thanks Thomas Dickey for answering questions about ncurses/ncursesw > and readline! > > > > > Modified: > python/trunk/Lib/test/test_curses.py > python/trunk/Misc/NEWS > python/trunk/setup.py > > Modified: python/trunk/Lib/test/test_curses.py > > ============================================================================== > --- python/trunk/Lib/test/test_curses.py (original) > +++ python/trunk/Lib/test/test_curses.py Thu Jun 3 14:39:50 2010 > @@ -21,11 +21,6 @@ > curses = import_module('curses') > curses.panel = import_module('curses.panel') > > -# skip all these tests on FreeBSD: test_curses currently hangs the > -# FreeBSD buildbots, preventing other tests from running. See issue > -# #7384. > -if 'freebsd' in sys.platform: > - raise unittest.SkipTest('The curses module is broken on FreeBSD. See > http://bugs.python.org/issue7384.') > > # XXX: if newterm was supported we could use it instead of initscr and not > exit > term = os.environ.get('TERM') > > Modified: python/trunk/Misc/NEWS > > ============================================================================== > --- python/trunk/Misc/NEWS (original) > +++ python/trunk/Misc/NEWS Thu Jun 3 14:39:50 2010 > @@ -89,6 +89,10 @@ > Extension Modules > ----------------- > > +- Issue #7384: If the system readline library is linked against ncurses, > + the curses module must be linked against ncurses as well. Otherwise it > + is not safe to load both the readline and curses modules in an > application. > + > - Issue #2810: Fix cases where the Windows registry API returns > ERROR_MORE_DATA, requiring a re-try in order to get the complete result. > > > Modified: python/trunk/setup.py > > ============================================================================== > --- python/trunk/setup.py (original) > +++ python/trunk/setup.py Thu Jun 3 14:39:50 2010 > @@ -588,6 +588,32 @@ > > # readline > do_readline = self.compiler.find_library_file(lib_dirs, 'readline') > + readline_termcap_library = "" > + curses_library = "" > + # Determine if readline is already linked against curses or tinfo. > + if do_readline and platform != 'darwin': # OS X does not have ldd. > + fp = os.popen("ldd %s" % do_readline) > + for ln in fp: > + if 'curses' in ln: > + readline_termcap_library = re.sub( > + r'.*lib(n?cursesw?)\.so.*', r'\1', ln > + ).rstrip() > + break > + if 'tinfo' in ln: # termcap interface split out from > ncurses > + readline_termcap_library = 'tinfo' > + break > + fp.close() > + # Issue 7384: If readline is already linked against curses, > + # use the same library for the readline and curses modules. > + if 'curses' in readline_termcap_library: > + curses_library = readline_termcap_library > + elif self.compiler_obj.find_library_file(lib_dirs, 'ncursesw'): > + curses_library = 'ncursesw' > + elif self.compiler_obj.find_library_file(lib_dirs, 'ncurses'): > + curses_library = 'ncurses' > + elif self.compiler_obj.find_library_file(lib_dirs, 'curses'): > + curses_library = 'curses' > + > if platform == 'darwin': > os_release = int(os.uname()[2].split('.')[0]) > dep_target = > sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET') > @@ -611,14 +637,10 @@ > readline_extra_link_args = () > > readline_libs = ['readline'] > - if self.compiler.find_library_file(lib_dirs, > - 'ncursesw'): > - readline_libs.append('ncursesw') > - elif self.compiler.find_library_file(lib_dirs, > - 'ncurses'): > - readline_libs.append('ncurses') > - elif self.compiler.find_library_file(lib_dirs, 'curses'): > - readline_libs.append('curses') > + if readline_termcap_library: > + pass # Issue 7384: Already linked against curses or tinfo. > + elif curses_library: > + readline_libs.append(curses_library) > elif self.compiler.find_library_file(lib_dirs + > ['/usr/lib/termcap'], > 'termcap'): > @@ -1187,19 +1209,15 @@ > # Curses support, requiring the System V version of curses, often > # provided by the ncurses library. > panel_library = 'panel' > - if (self.compiler.find_library_file(lib_dirs, 'ncursesw')): > - curses_libs = ['ncursesw'] > - # Bug 1464056: If _curses.so links with ncursesw, > - # _curses_panel.so must link with panelw. > - panel_library = 'panelw' > - exts.append( Extension('_curses', ['_cursesmodule.c'], > - libraries = curses_libs) ) > - elif (self.compiler.find_library_file(lib_dirs, 'ncurses')): > - curses_libs = ['ncurses'] > + if curses_library.startswith('ncurses'): > + if curses_library == 'ncursesw': > + # Bug 1464056: If _curses.so links with ncursesw, > + # _curses_panel.so must link with panelw. > + panel_library = 'panelw' > + curses_libs = [curses_library] > exts.append( Extension('_curses', ['_cursesmodule.c'], > libraries = curses_libs) ) > - elif (self.compiler.find_library_file(lib_dirs, 'curses') > - and platform != 'darwin'): > + elif curses_library == 'curses' and platform != 'darwin': > # OSX has an old Berkeley curses, not good enough for > # the _curses module. > if (self.compiler.find_library_file(lib_dirs, 'terminfo')): > _______________________________________________ > Python-checkins mailing list > Python-checkins at python.org > http://mail.python.org/mailman/listinfo/python-checkins > -- http://www.voidspace.org.uk -------------- next part -------------- An HTML attachment was scrubbed... URL: From python-checkins at python.org Thu Jun 3 16:25:16 2010 From: python-checkins at python.org (stefan.krah) Date: Thu, 3 Jun 2010 16:25:16 +0200 (CEST) Subject: [Python-checkins] r81672 - python/trunk/setup.py Message-ID: <20100603142516.A809DEE9A4@mail.python.org> Author: stefan.krah Date: Thu Jun 3 16:25:16 2010 New Revision: 81672 Log: Use compiler rather than compiler_obj. Thanks Michael Foord for noticing. Modified: python/trunk/setup.py Modified: python/trunk/setup.py ============================================================================== --- python/trunk/setup.py (original) +++ python/trunk/setup.py Thu Jun 3 16:25:16 2010 @@ -607,11 +607,11 @@ # use the same library for the readline and curses modules. if 'curses' in readline_termcap_library: curses_library = readline_termcap_library - elif self.compiler_obj.find_library_file(lib_dirs, 'ncursesw'): + elif self.compiler.find_library_file(lib_dirs, 'ncursesw'): curses_library = 'ncursesw' - elif self.compiler_obj.find_library_file(lib_dirs, 'ncurses'): + elif self.compiler.find_library_file(lib_dirs, 'ncurses'): curses_library = 'ncurses' - elif self.compiler_obj.find_library_file(lib_dirs, 'curses'): + elif self.compiler.find_library_file(lib_dirs, 'curses'): curses_library = 'curses' if platform == 'darwin': From stefan-usenet at bytereef.org Thu Jun 3 16:20:24 2010 From: stefan-usenet at bytereef.org (Stefan Krah) Date: Thu, 3 Jun 2010 16:20:24 +0200 Subject: [Python-checkins] r81669 - in python/trunk: Lib/test/test_curses.py Misc/NEWS setup.py In-Reply-To: References: <20100603123950.BACCCEE9B1@mail.python.org> Message-ID: <20100603142024.GA2775@yoda.bytereef.org> Michael Foord wrote: > This kills the build on Mac OS X (Snow Leopard) for me: > elif self.compiler_obj.find_library_file(lib_dirs, 'ncursesw'): > File "/compile/python-trunk/Lib/distutils/cmd.py", line 105, in __getattr__ > raise AttributeError, attr > AttributeError: compiler_obj > [35980 refs] > make: *** [sharedmods] Error 1 Thanks, the compiler_obj slipped in from the py3k patch. Stefan Krah From python-checkins at python.org Thu Jun 3 16:42:25 2010 From: python-checkins at python.org (ronald.oussoren) Date: Thu, 3 Jun 2010 16:42:25 +0200 (CEST) Subject: [Python-checkins] r81673 - in python/branches/py3k: Lib/distutils/unixccompiler.py setup.py Message-ID: <20100603144225.3EBA9EE9E4@mail.python.org> Author: ronald.oussoren Date: Thu Jun 3 16:42:25 2010 New Revision: 81673 Log: Merged revisions 81662 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81662 | ronald.oussoren | 2010-06-03 11:47:21 +0200 (Thu, 03 Jun 2010) | 9 lines Fix for issue #7724: ensure that distutils and python's own setup.py honor the MacOSX SDK when one is specified. This is needed to be able to build using the 10.4u SDK while running on OSX 10.6. This is a fixed version of the patch in r80963, I've tested this patch on OSX and Linux. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/distutils/unixccompiler.py python/branches/py3k/setup.py Modified: python/branches/py3k/Lib/distutils/unixccompiler.py ============================================================================== --- python/branches/py3k/Lib/distutils/unixccompiler.py (original) +++ python/branches/py3k/Lib/distutils/unixccompiler.py Thu Jun 3 16:42:25 2010 @@ -15,7 +15,7 @@ __revision__ = "$Id$" -import os, sys +import os, sys, re from distutils.dep_util import newer from distutils.ccompiler import \ @@ -320,10 +320,31 @@ dylib_f = self.library_filename(lib, lib_type='dylib') static_f = self.library_filename(lib, lib_type='static') + if sys.platform == 'darwin': + # On OSX users can specify an alternate SDK using + # '-isysroot', calculate the SDK root if it is specified + # (and use it further on) + _sysconfig = __import__('sysconfig') + cflags = _sysconfig.get_config_var('CFLAGS') + m = re.search(r'-isysroot\s+(\S+)', cflags) + if m is None: + sysroot = '/' + else: + sysroot = m.group(1) + + + for dir in dirs: shared = os.path.join(dir, shared_f) dylib = os.path.join(dir, dylib_f) static = os.path.join(dir, static_f) + + if sys.platform == 'darwin' and ( + dir.startswith('/System/') or dir.startswith('/usr/')): + 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) + # We're second-guessing the linker here, with not much hard # data to go on: GCC seems to prefer the shared library, so I'm # assuming that *all* Unix C compilers do. And of course I'm Modified: python/branches/py3k/setup.py ============================================================================== --- python/branches/py3k/setup.py (original) +++ python/branches/py3k/setup.py Thu Jun 3 16:42:25 2010 @@ -28,6 +28,25 @@ if dir is not None and os.path.isdir(dir) and dir not in dirlist: dirlist.insert(0, dir) +def macosx_sdk_root(): + """ + Return the directory of the current OSX SDK, + or '/' if no SDK was specified. + """ + cflags = sysconfig.get_config_var('CFLAGS') + m = re.search(r'-isysroot\s+(\S+)', cflags) + if m is None: + sysroot = '/' + else: + sysroot = m.group(1) + return sysroot + +def is_macosx_sdk_path(path): + """ + Returns True if 'path' can be located in an OSX SDK + """ + return path.startswith('/usr/') or path.startswith('/System/') + def find_file(filename, std_dirs, paths): """Searches for the directory where a given file is located, and returns a possibly-empty list of additional directories, or None @@ -39,15 +58,28 @@ 'paths' is a list of additional locations to check; if the file is found in one of them, the resulting list will contain the directory. """ + if sys.platform == 'darwin': + # Honor the MacOSX SDK setting when one was specified. + # An SDK is a directory with the same structure as a real + # system, but with only header files and libraries. + sysroot = macosx_sdk_root() # Check the standard locations for dir in std_dirs: f = os.path.join(dir, filename) + + if sys.platform == 'darwin' and is_macosx_sdk_path(dir): + f = os.path.join(sysroot, dir[1:], filename) + if os.path.exists(f): return [] # Check the additional directories for dir in paths: f = os.path.join(dir, filename) + + if sys.platform == 'darwin' and is_macosx_sdk_path(dir): + f = os.path.join(sysroot, dir[1:], filename) + if os.path.exists(f): return [dir] @@ -59,11 +91,19 @@ if result is None: return None + if sys.platform == 'darwin': + sysroot = macosx_sdk_root() + # Check whether the found file is in one of the standard directories dirname = os.path.dirname(result) for p in std_dirs: # Ensure path doesn't end with path separator p = p.rstrip(os.sep) + + if sys.platform == 'darwin' and is_macosx_sdk_path(p): + if os.path.join(sysroot, p[1:]) == dirname: + return [ ] + if p == dirname: return [ ] @@ -72,6 +112,11 @@ for p in paths: # Ensure path doesn't end with path separator p = p.rstrip(os.sep) + + if sys.platform == 'darwin' and is_macosx_sdk_path(p): + if os.path.join(sysroot, p[1:]) == dirname: + return [ p ] + if p == dirname: return [p] else: @@ -497,7 +542,7 @@ # library and then a static library, instead of first looking # for dynamic libraries on the entire path. # This way a staticly linked custom readline gets picked up - # before the (broken) dynamic library in /usr/lib. + # before the (possibly broken) dynamic library in /usr/lib. readline_extra_link_args = ('-Wl,-search_paths_first',) else: readline_extra_link_args = () @@ -571,22 +616,23 @@ openssl_ver = 0 openssl_ver_re = re.compile( '^\s*#\s*define\s+OPENSSL_VERSION_NUMBER\s+(0x[0-9a-fA-F]+)' ) - for ssl_inc_dir in inc_dirs + search_for_ssl_incs_in: - name = os.path.join(ssl_inc_dir, 'openssl', 'opensslv.h') - if os.path.isfile(name): - try: - incfile = open(name, 'r') - for line in incfile: - m = openssl_ver_re.match(line) - if m: - openssl_ver = eval(m.group(1)) - break - except IOError: - pass - # first version found is what we'll use (as the compiler should) - if openssl_ver: - break + # look for the openssl version header on the compiler search path. + opensslv_h = find_file('openssl/opensslv.h', [], + inc_dirs + search_for_ssl_incs_in) + if opensslv_h: + name = os.path.join(opensslv_h[0], 'openssl/opensslv.h') + if sys.platform == 'darwin' and is_macosx_sdk_path(name): + name = os.path.join(macosx_sdk_root(), name[1:]) + try: + incfile = open(name, 'r') + for line in incfile: + m = openssl_ver_re.match(line) + if m: + openssl_ver = eval(m.group(1)) + except IOError as msg: + print("IOError while reading opensshv.h:", msg) + pass #print('openssl_ver = 0x%08x' % openssl_ver) min_openssl_ver = 0x00907000 @@ -715,12 +761,18 @@ db_ver_inc_map = {} + if sys.platform == 'darwin': + sysroot = macosx_sdk_root() + class db_found(Exception): pass try: # See whether there is a Sleepycat header in the standard # search path. for d in inc_dirs + db_inc_paths: f = os.path.join(d, "db.h") + if sys.platform == 'darwin' and is_macosx_sdk_path(d): + f = os.path.join(sysroot, d[1:], "db.h") + if db_setup_debug: print("db: looking for db.h in", f) if os.path.exists(f): f = open(f, "rb").read() @@ -767,7 +819,22 @@ db_incdir.replace("include", 'lib64'), db_incdir.replace("include", 'lib'), ] - db_dirs_to_check = list(filter(os.path.isdir, db_dirs_to_check)) + + if sys.platform != 'darwin': + db_dirs_to_check = list(filter(os.path.isdir, db_dirs_to_check)) + + else: + # Same as other branch, but takes OSX SDK into account + tmp = [] + for dn in db_dirs_to_check: + if is_macosx_sdk_path(dn): + if os.path.isdir(os.path.join(sysroot, dn[1:])): + tmp.append(dn) + else: + if os.path.isdir(dn): + tmp.append(dn) + + db_dirs_to_check = tmp # Look for a version specific db-X.Y before an ambiguoius dbX # XXX should we -ever- look for a dbX name? Do any @@ -816,8 +883,15 @@ # Scan the default include directories before the SQLite specific # ones. This allows one to override the copy of sqlite on OSX, # where /usr/include contains an old version of sqlite. + if sys.platform == 'darwin': + sysroot = macosx_sdk_root() + for d in inc_dirs + sqlite_inc_paths: f = os.path.join(d, "sqlite3.h") + + if sys.platform == 'darwin' and is_macosx_sdk_path(d): + f = os.path.join(sysroot, d[1:], "sqlite3.h") + if os.path.exists(f): if sqlite_setup_debug: print("sqlite: found %s"%f) incf = open(f).read() @@ -1253,14 +1327,22 @@ join(os.getenv('HOME'), '/Library/Frameworks') ] + sysroot = macosx_sdk_root() + # Find the directory that contains the Tcl.framework and Tk.framework # bundles. # XXX distutils should support -F! for F in framework_dirs: # both Tcl.framework and Tk.framework should be present + + for fw in 'Tcl', 'Tk': - if not exists(join(F, fw + '.framework')): - break + if is_macosx_sdk_path(F): + if not exists(join(sysroot, F[1:], fw + '.framework')): + break + else: + if not exists(join(F, fw + '.framework')): + break else: # ok, F is now directory with both frameworks. Continure # building @@ -1297,8 +1379,12 @@ # Note: cannot use os.popen or subprocess here, that # requires extensions that are not available here. - os.system("file %s/Tk.framework/Tk | grep 'for architecture' > %s"%(F, tmpfile)) + if is_macosx_sdk_path(F): + os.system("file %s/Tk.framework/Tk | grep 'for architecture' > %s"%(os.path.join(sysroot, F[1:]), tmpfile)) + else: + os.system("file %s/Tk.framework/Tk | grep 'for architecture' > %s"%(F, tmpfile)) fp = open(tmpfile) + detected_archs = [] for ln in fp: a = ln.split()[-1] From python-checkins at python.org Thu Jun 3 16:59:56 2010 From: python-checkins at python.org (ronald.oussoren) Date: Thu, 3 Jun 2010 16:59:56 +0200 (CEST) Subject: [Python-checkins] r81674 - in python/branches/release26-maint: Lib/distutils/unixccompiler.py setup.py Message-ID: <20100603145956.6FC1BEEA2E@mail.python.org> Author: ronald.oussoren Date: Thu Jun 3 16:59:56 2010 New Revision: 81674 Log: Merged revisions 81662 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81662 | ronald.oussoren | 2010-06-03 11:47:21 +0200 (Thu, 03 Jun 2010) | 9 lines Fix for issue #7724: ensure that distutils and python's own setup.py honor the MacOSX SDK when one is specified. This is needed to be able to build using the 10.4u SDK while running on OSX 10.6. This is a fixed version of the patch in r80963, I've tested this patch on OSX and Linux. ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Lib/distutils/unixccompiler.py python/branches/release26-maint/setup.py Modified: python/branches/release26-maint/Lib/distutils/unixccompiler.py ============================================================================== --- python/branches/release26-maint/Lib/distutils/unixccompiler.py (original) +++ python/branches/release26-maint/Lib/distutils/unixccompiler.py Thu Jun 3 16:59:56 2010 @@ -15,7 +15,7 @@ __revision__ = "$Id$" -import os, sys +import os, sys, re from types import StringType, NoneType from distutils import sysconfig @@ -305,10 +305,30 @@ dylib_f = self.library_filename(lib, lib_type='dylib') static_f = self.library_filename(lib, lib_type='static') + if sys.platform == 'darwin': + # On OSX users can specify an alternate SDK using + # '-isysroot', calculate the SDK root if it is specified + # (and use it further on) + cflags = sysconfig.get_config_var('CFLAGS') + m = re.search(r'-isysroot\s+(\S+)', cflags) + if m is None: + sysroot = '/' + else: + sysroot = m.group(1) + + + for dir in dirs: shared = os.path.join(dir, shared_f) dylib = os.path.join(dir, dylib_f) static = os.path.join(dir, static_f) + + if sys.platform == 'darwin' and ( + dir.startswith('/System/') or dir.startswith('/usr/')): + 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) + # We're second-guessing the linker here, with not much hard # data to go on: GCC seems to prefer the shared library, so I'm # assuming that *all* Unix C compilers do. And of course I'm Modified: python/branches/release26-maint/setup.py ============================================================================== --- python/branches/release26-maint/setup.py (original) +++ python/branches/release26-maint/setup.py Thu Jun 3 16:59:56 2010 @@ -26,6 +26,25 @@ if dir is not None and os.path.isdir(dir) and dir not in dirlist: dirlist.insert(0, dir) +def macosx_sdk_root(): + """ + Return the directory of the current OSX SDK, + or '/' if no SDK was specified. + """ + cflags = sysconfig.get_config_var('CFLAGS') + m = re.search(r'-isysroot\s+(\S+)', cflags) + if m is None: + sysroot = '/' + else: + sysroot = m.group(1) + return sysroot + +def is_macosx_sdk_path(path): + """ + Returns True if 'path' can be located in an OSX SDK + """ + return path.startswith('/usr/') or path.startswith('/System/') + def find_file(filename, std_dirs, paths): """Searches for the directory where a given file is located, and returns a possibly-empty list of additional directories, or None @@ -37,15 +56,28 @@ 'paths' is a list of additional locations to check; if the file is found in one of them, the resulting list will contain the directory. """ + if sys.platform == 'darwin': + # Honor the MacOSX SDK setting when one was specified. + # An SDK is a directory with the same structure as a real + # system, but with only header files and libraries. + sysroot = macosx_sdk_root() # Check the standard locations for dir in std_dirs: f = os.path.join(dir, filename) + + if sys.platform == 'darwin' and is_macosx_sdk_path(dir): + f = os.path.join(sysroot, dir[1:], filename) + if os.path.exists(f): return [] # Check the additional directories for dir in paths: f = os.path.join(dir, filename) + + if sys.platform == 'darwin' and is_macosx_sdk_path(dir): + f = os.path.join(sysroot, dir[1:], filename) + if os.path.exists(f): return [dir] @@ -57,11 +89,19 @@ if result is None: return None + if sys.platform == 'darwin': + sysroot = macosx_sdk_root() + # Check whether the found file is in one of the standard directories dirname = os.path.dirname(result) for p in std_dirs: # Ensure path doesn't end with path separator p = p.rstrip(os.sep) + + if sys.platform == 'darwin' and is_macosx_sdk_path(p): + if os.path.join(sysroot, p[1:]) == dirname: + return [ ] + if p == dirname: return [ ] @@ -70,6 +110,11 @@ for p in paths: # Ensure path doesn't end with path separator p = p.rstrip(os.sep) + + if sys.platform == 'darwin' and is_macosx_sdk_path(p): + if os.path.join(sysroot, p[1:]) == dirname: + return [ p ] + if p == dirname: return [p] else: @@ -573,7 +618,7 @@ # library and then a static library, instead of first looking # for dynamic libraries on the entiry path. # This way a staticly linked custom readline gets picked up - # before the (broken) dynamic library in /usr/lib. + # before the (possibly broken) dynamic library in /usr/lib. readline_extra_link_args = ('-Wl,-search_paths_first',) else: readline_extra_link_args = () @@ -647,24 +692,24 @@ openssl_ver = 0 openssl_ver_re = re.compile( '^\s*#\s*define\s+OPENSSL_VERSION_NUMBER\s+(0x[0-9a-fA-F]+)' ) - for ssl_inc_dir in inc_dirs + search_for_ssl_incs_in: - name = os.path.join(ssl_inc_dir, 'openssl', 'opensslv.h') - if os.path.isfile(name): - try: - incfile = open(name, 'r') - for line in incfile: - m = openssl_ver_re.match(line) - if m: - openssl_ver = eval(m.group(1)) - break - except IOError: - pass - # first version found is what we'll use (as the compiler should) - if openssl_ver: - break + # look for the openssl version header on the compiler search path. + opensslv_h = find_file('openssl/opensslv.h', [], + inc_dirs + search_for_ssl_incs_in) + if opensslv_h: + name = os.path.join(opensslv_h[0], 'openssl/opensslv.h') + if sys.platform == 'darwin' and is_macosx_sdk_path(name): + name = os.path.join(macosx_sdk_root(), name[1:]) + try: + incfile = open(name, 'r') + for line in incfile: + m = openssl_ver_re.match(line) + if m: + openssl_ver = eval(m.group(1)) + except IOError, msg: + print "IOError while reading opensshv.h:", msg + pass - #print 'openssl_ver = 0x%08x' % openssl_ver if (ssl_incs is not None and ssl_libs is not None and @@ -792,12 +837,19 @@ db_ver_inc_map = {} + if sys.platform == 'darwin': + sysroot = macosx_sdk_root() + class db_found(Exception): pass try: # See whether there is a Sleepycat header in the standard # search path. for d in inc_dirs + db_inc_paths: f = os.path.join(d, "db.h") + + if sys.platform == 'darwin' and is_macosx_sdk_path(d): + f = os.path.join(sysroot, d[1:], "db.h") + if db_setup_debug: print "db: looking for db.h in", f if os.path.exists(f): f = open(f).read() @@ -844,7 +896,20 @@ db_incdir.replace("include", 'lib64'), db_incdir.replace("include", 'lib'), ] - db_dirs_to_check = filter(os.path.isdir, db_dirs_to_check) + + if sys.platform != 'darwin': + db_dirs_to_check = filter(os.path.isdir, db_dirs_to_check) + + else: + # Same as other branch, but takes OSX SDK into account + tmp = [] + for dn in db_dirs_to_check: + if is_macosx_sdk_path(dn): + if os.path.isdir(os.path.join(sysroot, dn[1:])): + tmp.append(dn) + else: + if os.path.isdir(dn): + tmp.append(dn) # Look for a version specific db-X.Y before an ambiguoius dbX # XXX should we -ever- look for a dbX name? Do any @@ -906,8 +971,15 @@ # Scan the default include directories before the SQLite specific # ones. This allows one to override the copy of sqlite on OSX, # where /usr/include contains an old version of sqlite. + if sys.platform == 'darwin': + sysroot = macosx_sdk_root() + for d in inc_dirs + sqlite_inc_paths: f = os.path.join(d, "sqlite3.h") + + if sys.platform == 'darwin' and is_macosx_sdk_path(d): + f = os.path.join(sysroot, d[1:], "sqlite3.h") + if os.path.exists(f): if sqlite_setup_debug: print "sqlite: found %s"%f incf = open(f).read() @@ -993,6 +1065,12 @@ # the more recent berkeleydb's db.h file first in the include path # when attempting to compile and it will fail. f = "/usr/include/db.h" + + if sys.platform == 'darwin': + if is_macosx_sdk_path(f): + sysroot = macosx_sdk_root() + f = os.path.join(sysroot, f[1:]) + if os.path.exists(f) and not db_incs: data = open(f).read() m = re.search(r"#s*define\s+HASHVERSION\s+2\s*", data) @@ -1483,14 +1561,22 @@ join(os.getenv('HOME'), '/Library/Frameworks') ] + sysroot = macosx_sdk_root() + # Find the directory that contains the Tcl.framework and Tk.framework # bundles. # XXX distutils should support -F! for F in framework_dirs: # both Tcl.framework and Tk.framework should be present + + for fw in 'Tcl', 'Tk': - if not exists(join(F, fw + '.framework')): - break + if is_macosx_sdk_path(F): + if not exists(join(sysroot, F[1:], fw + '.framework')): + break + else: + if not exists(join(F, fw + '.framework')): + break else: # ok, F is now directory with both frameworks. Continure # building @@ -1520,7 +1606,12 @@ # architectures. cflags = sysconfig.get_config_vars('CFLAGS')[0] archs = re.findall('-arch\s+(\w+)', cflags) - fp = os.popen("file %s/Tk.framework/Tk | grep 'for architecture'"%(F,)) + + if is_macosx_sdk_path(F): + fp = os.popen("file %s/Tk.framework/Tk | grep 'for architecture'"%(os.path.join(sysroot, F[1:]),)) + else: + fp = os.popen("file %s/Tk.framework/Tk | grep 'for architecture'"%(F,)) + detected_archs = [] for ln in fp: a = ln.split()[-1] From python-checkins at python.org Thu Jun 3 17:43:20 2010 From: python-checkins at python.org (r.david.murray) Date: Thu, 3 Jun 2010 17:43:20 +0200 (CEST) Subject: [Python-checkins] r81675 - in python/trunk: Lib/email/feedparser.py Lib/email/test/test_email.py Misc/NEWS Message-ID: <20100603154320.5878FEEB88@mail.python.org> Author: r.david.murray Date: Thu Jun 3 17:43:20 2010 New Revision: 81675 Log: #5610: use \Z not $ so we don't eat extra chars when body part ends with \r\n. If a body part ended with \r\n, feedparser, using '$' to terminate its search for the newline, would match on the \r\n, and think that it needed to strip two characters in order to account for the line end before the boundary. That made it chop one too many characters off the end of the body part. Using \Z makes the match correct. Patch and test by Tony Nelson. Modified: python/trunk/Lib/email/feedparser.py python/trunk/Lib/email/test/test_email.py python/trunk/Misc/NEWS Modified: python/trunk/Lib/email/feedparser.py ============================================================================== --- python/trunk/Lib/email/feedparser.py (original) +++ python/trunk/Lib/email/feedparser.py Thu Jun 3 17:43:20 2010 @@ -28,7 +28,7 @@ NLCRE = re.compile('\r\n|\r|\n') NLCRE_bol = re.compile('(\r\n|\r|\n)') -NLCRE_eol = re.compile('(\r\n|\r|\n)$') +NLCRE_eol = re.compile('(\r\n|\r|\n)\Z') NLCRE_crack = re.compile('(\r\n|\r|\n)') # RFC 2822 $3.6.8 Optional fields. ftext is %d33-57 / %d59-126, Any character # except controls, SP, and ":". Modified: python/trunk/Lib/email/test/test_email.py ============================================================================== --- python/trunk/Lib/email/test/test_email.py (original) +++ python/trunk/Lib/email/test/test_email.py Thu Jun 3 17:43:20 2010 @@ -2610,6 +2610,24 @@ eq(headers, ['A', 'B', 'CC']) eq(msg.get_payload(), 'body') + def test_CRLFLF_at_end_of_part(self): + # issue 5610: feedparser should not eat two chars from body part ending + # with "\r\n\n". + m = ( + "From: foo at bar.com\n" + "To: baz\n" + "Mime-Version: 1.0\n" + "Content-Type: multipart/mixed; boundary=BOUNDARY\n" + "\n" + "--BOUNDARY\n" + "Content-Type: text/plain\n" + "\n" + "body ending with CRLF newline\r\n" + "\n" + "--BOUNDARY--\n" + ) + msg = email.message_from_string(m) + self.assertTrue(msg.get_payload(0).get_payload().endswith('\r\n')) class TestBase64(unittest.TestCase): Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Thu Jun 3 17:43:20 2010 @@ -46,6 +46,9 @@ Library ------- +- Issue #5610: feedparser no longer eats extra characters at the end of + a body part if the body part ends with a \r\n. + - Issue #8833: tarfile created hard link entries with a size field != 0 by mistake. From python-checkins at python.org Thu Jun 3 18:04:47 2010 From: python-checkins at python.org (stefan.krah) Date: Thu, 3 Jun 2010 18:04:47 +0200 (CEST) Subject: [Python-checkins] r81676 - python/branches/release26-maint/Lib/test/test_signal.py Message-ID: <20100603160447.94CA4EEBAF@mail.python.org> Author: stefan.krah Date: Thu Jun 3 18:04:47 2010 New Revision: 81676 Log: Also skip when test_support.verbose is false. Modified: python/branches/release26-maint/Lib/test/test_signal.py Modified: python/branches/release26-maint/Lib/test/test_signal.py ============================================================================== --- python/branches/release26-maint/Lib/test/test_signal.py (original) +++ python/branches/release26-maint/Lib/test/test_signal.py Thu Jun 3 18:04:47 2010 @@ -141,9 +141,10 @@ def test_main(self): # Issue 3864, unknown if this affects earlier versions of freebsd also - if sys.platform=='freebsd6' and test_support.verbose: - sys.stderr.write('skipping -- inter process signals not reliable ' - '(do not mix well with threading) on freebsd6\n') + if sys.platform=='freebsd6': + if test_support.verbose: + sys.stderr.write('skipping -- inter process signals not ' + 'reliable (do not mix well with threading) on freebsd6\n') return # This function spawns a child process to insulate the main # test-running process from all the signals. It then @@ -435,9 +436,10 @@ def test_itimer_virtual(self): # Issue 3864, unknown if this affects earlier versions of freebsd also - if sys.platform=='freebsd6' and test_support.verbose: - sys.stderr.write('skipping -- itimer not reliable ' - '(does not mix well with threading) on freebsd6\n') + if sys.platform=='freebsd6': + if test_support.verbose: + sys.stderr.write('skipping -- itimer not reliable (does not ' + 'mix well with threading) on freebsd6\n') return self.itimer = signal.ITIMER_VIRTUAL signal.signal(signal.SIGVTALRM, self.sig_vtalrm) @@ -461,9 +463,10 @@ def test_itimer_prof(self): # Issue 3864, unknown if this affects earlier versions of freebsd also - if sys.platform=='freebsd6' and test_support.verbose: - sys.stderr.write('skipping -- itimer not reliable ' - '(does not mix well with threading) on freebsd6\n') + if sys.platform=='freebsd6': + if test_support.verbose: + sys.stderr.write('skipping -- itimer not reliable (does not ' + 'mix well with threading) on freebsd6\n') return self.itimer = signal.ITIMER_PROF signal.signal(signal.SIGPROF, self.sig_prof) From python-checkins at python.org Thu Jun 3 18:21:04 2010 From: python-checkins at python.org (ronald.oussoren) Date: Thu, 3 Jun 2010 18:21:04 +0200 (CEST) Subject: [Python-checkins] r81677 - in python/branches/release31-maint: Lib/distutils/unixccompiler.py setup.py Message-ID: <20100603162104.05D9EEEBB8@mail.python.org> Author: ronald.oussoren Date: Thu Jun 3 18:21:03 2010 New Revision: 81677 Log: Merged revisions 81673 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ................ r81673 | ronald.oussoren | 2010-06-03 16:42:25 +0200 (Thu, 03 Jun 2010) | 16 lines Merged revisions 81662 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81662 | ronald.oussoren | 2010-06-03 11:47:21 +0200 (Thu, 03 Jun 2010) | 9 lines Fix for issue #7724: ensure that distutils and python's own setup.py honor the MacOSX SDK when one is specified. This is needed to be able to build using the 10.4u SDK while running on OSX 10.6. This is a fixed version of the patch in r80963, I've tested this patch on OSX and Linux. ........ ................ Modified: python/branches/release31-maint/ (props changed) python/branches/release31-maint/Lib/distutils/unixccompiler.py python/branches/release31-maint/setup.py Modified: python/branches/release31-maint/Lib/distutils/unixccompiler.py ============================================================================== --- python/branches/release31-maint/Lib/distutils/unixccompiler.py (original) +++ python/branches/release31-maint/Lib/distutils/unixccompiler.py Thu Jun 3 18:21:03 2010 @@ -15,7 +15,7 @@ __revision__ = "$Id$" -import os, sys +import os, sys, re from distutils import sysconfig from distutils.dep_util import newer @@ -317,10 +317,30 @@ dylib_f = self.library_filename(lib, lib_type='dylib') static_f = self.library_filename(lib, lib_type='static') + if sys.platform == 'darwin': + # On OSX users can specify an alternate SDK using + # '-isysroot', calculate the SDK root if it is specified + # (and use it further on) + cflags = sysconfig.get_config_var('CFLAGS') + m = re.search(r'-isysroot\s+(\S+)', cflags) + if m is None: + sysroot = '/' + else: + sysroot = m.group(1) + + + for dir in dirs: shared = os.path.join(dir, shared_f) dylib = os.path.join(dir, dylib_f) static = os.path.join(dir, static_f) + + if sys.platform == 'darwin' and ( + dir.startswith('/System/') or dir.startswith('/usr/')): + 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) + # We're second-guessing the linker here, with not much hard # data to go on: GCC seems to prefer the shared library, so I'm # assuming that *all* Unix C compilers do. And of course I'm Modified: python/branches/release31-maint/setup.py ============================================================================== --- python/branches/release31-maint/setup.py (original) +++ python/branches/release31-maint/setup.py Thu Jun 3 18:21:03 2010 @@ -25,6 +25,25 @@ if dir is not None and os.path.isdir(dir) and dir not in dirlist: dirlist.insert(0, dir) +def macosx_sdk_root(): + """ + Return the directory of the current OSX SDK, + or '/' if no SDK was specified. + """ + cflags = sysconfig.get_config_var('CFLAGS') + m = re.search(r'-isysroot\s+(\S+)', cflags) + if m is None: + sysroot = '/' + else: + sysroot = m.group(1) + return sysroot + +def is_macosx_sdk_path(path): + """ + Returns True if 'path' can be located in an OSX SDK + """ + return path.startswith('/usr/') or path.startswith('/System/') + def find_file(filename, std_dirs, paths): """Searches for the directory where a given file is located, and returns a possibly-empty list of additional directories, or None @@ -36,15 +55,28 @@ 'paths' is a list of additional locations to check; if the file is found in one of them, the resulting list will contain the directory. """ + if sys.platform == 'darwin': + # Honor the MacOSX SDK setting when one was specified. + # An SDK is a directory with the same structure as a real + # system, but with only header files and libraries. + sysroot = macosx_sdk_root() # Check the standard locations for dir in std_dirs: f = os.path.join(dir, filename) + + if sys.platform == 'darwin' and is_macosx_sdk_path(dir): + f = os.path.join(sysroot, dir[1:], filename) + if os.path.exists(f): return [] # Check the additional directories for dir in paths: f = os.path.join(dir, filename) + + if sys.platform == 'darwin' and is_macosx_sdk_path(dir): + f = os.path.join(sysroot, dir[1:], filename) + if os.path.exists(f): return [dir] @@ -56,11 +88,19 @@ if result is None: return None + if sys.platform == 'darwin': + sysroot = macosx_sdk_root() + # Check whether the found file is in one of the standard directories dirname = os.path.dirname(result) for p in std_dirs: # Ensure path doesn't end with path separator p = p.rstrip(os.sep) + + if sys.platform == 'darwin' and is_macosx_sdk_path(p): + if os.path.join(sysroot, p[1:]) == dirname: + return [ ] + if p == dirname: return [ ] @@ -69,6 +109,11 @@ for p in paths: # Ensure path doesn't end with path separator p = p.rstrip(os.sep) + + if sys.platform == 'darwin' and is_macosx_sdk_path(p): + if os.path.join(sysroot, p[1:]) == dirname: + return [ p ] + if p == dirname: return [p] else: @@ -507,7 +552,7 @@ # library and then a static library, instead of first looking # for dynamic libraries on the entire path. # This way a staticly linked custom readline gets picked up - # before the (broken) dynamic library in /usr/lib. + # before the (possibly broken) dynamic library in /usr/lib. readline_extra_link_args = ('-Wl,-search_paths_first',) else: readline_extra_link_args = () @@ -581,22 +626,23 @@ openssl_ver = 0 openssl_ver_re = re.compile( '^\s*#\s*define\s+OPENSSL_VERSION_NUMBER\s+(0x[0-9a-fA-F]+)' ) - for ssl_inc_dir in inc_dirs + search_for_ssl_incs_in: - name = os.path.join(ssl_inc_dir, 'openssl', 'opensslv.h') - if os.path.isfile(name): - try: - incfile = open(name, 'r') - for line in incfile: - m = openssl_ver_re.match(line) - if m: - openssl_ver = eval(m.group(1)) - break - except IOError: - pass - # first version found is what we'll use (as the compiler should) - if openssl_ver: - break + # look for the openssl version header on the compiler search path. + opensslv_h = find_file('openssl/opensslv.h', [], + inc_dirs + search_for_ssl_incs_in) + if opensslv_h: + name = os.path.join(opensslv_h[0], 'openssl/opensslv.h') + if sys.platform == 'darwin' and is_macosx_sdk_path(name): + name = os.path.join(macosx_sdk_root(), name[1:]) + try: + incfile = open(name, 'r') + for line in incfile: + m = openssl_ver_re.match(line) + if m: + openssl_ver = eval(m.group(1)) + except IOError as msg: + print("IOError while reading opensshv.h:", msg) + pass #print('openssl_ver = 0x%08x' % openssl_ver) @@ -717,12 +763,18 @@ db_ver_inc_map = {} + if sys.platform == 'darwin': + sysroot = macosx_sdk_root() + class db_found(Exception): pass try: # See whether there is a Sleepycat header in the standard # search path. for d in inc_dirs + db_inc_paths: f = os.path.join(d, "db.h") + if sys.platform == 'darwin' and is_macosx_sdk_path(d): + f = os.path.join(sysroot, d[1:], "db.h") + if db_setup_debug: print("db: looking for db.h in", f) if os.path.exists(f): f = open(f, "rb").read() @@ -769,7 +821,22 @@ db_incdir.replace("include", 'lib64'), db_incdir.replace("include", 'lib'), ] - db_dirs_to_check = list(filter(os.path.isdir, db_dirs_to_check)) + + if sys.platform != 'darwin': + db_dirs_to_check = list(filter(os.path.isdir, db_dirs_to_check)) + + else: + # Same as other branch, but takes OSX SDK into account + tmp = [] + for dn in db_dirs_to_check: + if is_macosx_sdk_path(dn): + if os.path.isdir(os.path.join(sysroot, dn[1:])): + tmp.append(dn) + else: + if os.path.isdir(dn): + tmp.append(dn) + + db_dirs_to_check = tmp # Look for a version specific db-X.Y before an ambiguoius dbX # XXX should we -ever- look for a dbX name? Do any @@ -818,8 +885,15 @@ # Scan the default include directories before the SQLite specific # ones. This allows one to override the copy of sqlite on OSX, # where /usr/include contains an old version of sqlite. + if sys.platform == 'darwin': + sysroot = macosx_sdk_root() + for d in inc_dirs + sqlite_inc_paths: f = os.path.join(d, "sqlite3.h") + + if sys.platform == 'darwin' and is_macosx_sdk_path(d): + f = os.path.join(sysroot, d[1:], "sqlite3.h") + if os.path.exists(f): if sqlite_setup_debug: print("sqlite: found %s"%f) incf = open(f).read() @@ -1245,14 +1319,22 @@ join(os.getenv('HOME'), '/Library/Frameworks') ] + sysroot = macosx_sdk_root() + # Find the directory that contains the Tcl.framework and Tk.framework # bundles. # XXX distutils should support -F! for F in framework_dirs: # both Tcl.framework and Tk.framework should be present + + for fw in 'Tcl', 'Tk': - if not exists(join(F, fw + '.framework')): - break + if is_macosx_sdk_path(F): + if not exists(join(sysroot, F[1:], fw + '.framework')): + break + else: + if not exists(join(F, fw + '.framework')): + break else: # ok, F is now directory with both frameworks. Continure # building @@ -1289,8 +1371,12 @@ # Note: cannot use os.popen or subprocess here, that # requires extensions that are not available here. - os.system("file %s/Tk.framework/Tk | grep 'for architecture' > %s"%(F, tmpfile)) + if is_macosx_sdk_path(F): + os.system("file %s/Tk.framework/Tk | grep 'for architecture' > %s"%(os.path.join(sysroot, F[1:]), tmpfile)) + else: + os.system("file %s/Tk.framework/Tk | grep 'for architecture' > %s"%(F, tmpfile)) fp = open(tmpfile) + detected_archs = [] for ln in fp: a = ln.split()[-1] From python-checkins at python.org Thu Jun 3 22:19:25 2010 From: python-checkins at python.org (r.david.murray) Date: Thu, 3 Jun 2010 22:19:25 +0200 (CEST) Subject: [Python-checkins] r81678 - in python/trunk: Lib/test/test_support.py Misc/NEWS Message-ID: <20100603201925.47F61EE990@mail.python.org> Author: r.david.murray Date: Thu Jun 3 22:19:25 2010 New Revision: 81678 Log: #8889: rewrite transient_internet so we don't use EAI_NODATA on FreeBSD. FreeBSD doesn't have socket.EAI_NODATA. I rewrote the routine because there's no easy way to conditionally include a context manager in a with statement. As a side benefit, instead of a stack of context managers there's now only one. Modified: python/trunk/Lib/test/test_support.py python/trunk/Misc/NEWS Modified: python/trunk/Lib/test/test_support.py ============================================================================== --- python/trunk/Lib/test/test_support.py (original) +++ python/trunk/Lib/test/test_support.py Thu Jun 3 22:19:25 2010 @@ -750,17 +750,32 @@ raise ResourceDenied("an optional resource is not available") +_transients = { + IOError: (errno.ECONNRESET, errno.ETIMEDOUT), + socket.error: (errno.ECONNRESET,), + socket.gaierror: [getattr(socket, t) + for t in ('EAI_NODATA', 'EAI_NONAME') + if hasattr(socket, t)], + } @contextlib.contextmanager def transient_internet(): """Return a context manager that raises ResourceDenied when various issues - with the Internet connection manifest themselves as exceptions.""" - time_out = TransientResource(IOError, errno=errno.ETIMEDOUT) - socket_peer_reset = TransientResource(socket.error, errno=errno.ECONNRESET) - ioerror_peer_reset = TransientResource(IOError, errno=errno.ECONNRESET) - dns_nodata = TransientResource(socket.gaierror, errno=socket.EAI_NODATA) - dns_noname = TransientResource(socket.gaierror, errno=socket.EAI_NONAME) - with time_out, socket_peer_reset, ioerror_peer_reset, dns_nodata, dns_noname: + with the Internet connection manifest themselves as exceptions. + + Errors caught: + timeout IOError errno = ETIMEDOUT + socket reset socket.error, IOError errno = ECONNRESET + dns no data socket.gaierror errno = EAI_NODATA + dns no name socket.gaierror errno = EAI_NONAME + """ + try: yield + except tuple(_transients) as err: + for errtype in _transients: + if isinstance(err, errtype) and err.errno in _transients[errtype]: + raise ResourceDenied("could not establish network " + "connection ({})".format(err)) + raise @contextlib.contextmanager Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Thu Jun 3 22:19:25 2010 @@ -105,7 +105,10 @@ Tests ----- -- Issue #8835: test_support.transient_internet() catchs gaierror(EAI_NONAME) +- Issue #8889: test_support.transient_internet rewritten so that the new + checks also work on FreeBSD, which lacks EAI_NODATA. + +- Issue #8835: test_support.transient_internet() catches gaierror(EAI_NONAME) and gaierror(EAI_NODATA) - Issue #7449: Skip test_socketserver if threading support is disabled From python-checkins at python.org Thu Jun 3 23:21:03 2010 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 3 Jun 2010 23:21:03 +0200 (CEST) Subject: [Python-checkins] r81679 - python/trunk/Lib/site.py Message-ID: <20100603212103.8CB3CEE99B@mail.python.org> Author: benjamin.peterson Date: Thu Jun 3 23:21:03 2010 New Revision: 81679 Log: use a set for membership testing Modified: python/trunk/Lib/site.py Modified: python/trunk/Lib/site.py ============================================================================== --- python/trunk/Lib/site.py (original) +++ python/trunk/Lib/site.py Thu Jun 3 23:21:03 2010 @@ -276,12 +276,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")) From python-checkins at python.org Fri Jun 4 00:34:42 2010 From: python-checkins at python.org (vinay.sajip) Date: Fri, 4 Jun 2010 00:34:42 +0200 (CEST) Subject: [Python-checkins] r81680 - python/trunk/Doc/library/logging.rst Message-ID: <20100603223442.852F7EE996@mail.python.org> Author: vinay.sajip Date: Fri Jun 4 00:34:42 2010 New Revision: 81680 Log: Issue #8890: Documentation changed to avoid reference to temporary files. Modified: python/trunk/Doc/library/logging.rst Modified: python/trunk/Doc/library/logging.rst ============================================================================== --- python/trunk/Doc/library/logging.rst (original) +++ python/trunk/Doc/library/logging.rst Fri Jun 4 00:34:42 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') From solipsis at pitrou.net Fri Jun 4 01:23:25 2010 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Fri, 4 Jun 2010 01:23:25 +0200 (CEST) Subject: [Python-checkins] Daily py3k reference leaks (r81673): sum=0 Message-ID: <20100603232326.102961770A@ns6635.ovh.net> py3k results for svn r81673 (hg cset 7da632f142ed) -------------------------------------------------- Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/py3k/refleaks/reflogXBofHD', '-x'] From python-checkins at python.org Fri Jun 4 03:51:27 2010 From: python-checkins at python.org (sean.reifschneider) Date: Fri, 4 Jun 2010 03:51:27 +0200 (CEST) Subject: [Python-checkins] r81681 - python/trunk/Modules/datetimemodule.c Message-ID: <20100604015127.1C135EEBFB@mail.python.org> Author: sean.reifschneider Date: Fri Jun 4 03:51:26 2010 New Revision: 81681 Log: Issue8810: Clearing up docstring for tzinfo.utcoffset. Modified: python/trunk/Modules/datetimemodule.c Modified: python/trunk/Modules/datetimemodule.c ============================================================================== --- python/trunk/Modules/datetimemodule.c (original) +++ python/trunk/Modules/datetimemodule.c Fri Jun 4 03:51:26 2010 @@ -3026,7 +3026,8 @@ PyDoc_STR("datetime -> DST offset in minutes east of UTC.")}, {"fromutc", (PyCFunction)tzinfo_fromutc, METH_O, - PyDoc_STR("datetime in UTC -> datetime in local time.")}, + PyDoc_STR("datetime -> timedelta showing offset from UTC, negative " + "values indicating West of UTC")}, {"__reduce__", (PyCFunction)tzinfo_reduce, METH_NOARGS, PyDoc_STR("-> (cls, state)")}, From python-checkins at python.org Fri Jun 4 03:51:38 2010 From: python-checkins at python.org (sean.reifschneider) Date: Fri, 4 Jun 2010 03:51:38 +0200 (CEST) Subject: [Python-checkins] r81682 - python/branches/py3k/Modules/datetimemodule.c Message-ID: <20100604015138.59F86EEC05@mail.python.org> Author: sean.reifschneider Date: Fri Jun 4 03:51:38 2010 New Revision: 81682 Log: Issue8810: Clearing up docstring for tzinfo.utcoffset. 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 Fri Jun 4 03:51:38 2010 @@ -3223,8 +3223,8 @@ PyDoc_STR("datetime -> string name of time zone.")}, {"utcoffset", (PyCFunction)tzinfo_utcoffset, METH_O, - PyDoc_STR("datetime -> minutes east of UTC (negative for " - "west of UTC).")}, + PyDoc_STR("datetime -> timedelta showing offset from UTC, negative " + "values indicating West of UTC")}, {"dst", (PyCFunction)tzinfo_dst, METH_O, PyDoc_STR("datetime -> DST offset in minutes east of UTC.")}, From mal at egenix.com Fri Jun 4 10:58:09 2010 From: mal at egenix.com (M.-A. Lemburg) Date: Fri, 04 Jun 2010 10:58:09 +0200 Subject: [Python-checkins] r81674 - in python/branches/release26-maint: Lib/distutils/unixccompiler.py setup.py In-Reply-To: <20100603145956.6FC1BEEA2E@mail.python.org> References: <20100603145956.6FC1BEEA2E@mail.python.org> Message-ID: <4C08C021.5010309@egenix.com> ronald.oussoren wrote: > Author: ronald.oussoren > Date: Thu Jun 3 16:59:56 2010 > New Revision: 81674 > > Log: > Merged revisions 81662 via svnmerge from > svn+ssh://pythondev at svn.python.org/python/trunk > > ........ > r81662 | ronald.oussoren | 2010-06-03 11:47:21 +0200 (Thu, 03 Jun 2010) | 9 lines > > Fix for issue #7724: ensure that distutils and python's own setup.py > honor the MacOSX SDK when one is specified. > > This is needed to be able to build using the 10.4u SDK while running > on OSX 10.6. > > This is a fixed version of the patch in r80963, I've tested this patch > on OSX and Linux. Overall, I don't particularly like this patch. It adds way too many special cases just for the MacOSX SDK setup. Isn't there some more elegant way to update the search paths if an SDK is present - one that doesn't require this long tail of "if sys.platform == 'darwin':..." all over setup.py ? BTW, this part still doesn't look right: > @@ -647,24 +692,24 @@ > openssl_ver = 0 > openssl_ver_re = re.compile( > '^\s*#\s*define\s+OPENSSL_VERSION_NUMBER\s+(0x[0-9a-fA-F]+)' ) > - for ssl_inc_dir in inc_dirs + search_for_ssl_incs_in: > - name = os.path.join(ssl_inc_dir, 'openssl', 'opensslv.h') > - if os.path.isfile(name): > - try: > - incfile = open(name, 'r') > - for line in incfile: > - m = openssl_ver_re.match(line) > - if m: > - openssl_ver = eval(m.group(1)) > - break > - except IOError: > - pass > > - # first version found is what we'll use (as the compiler should) > - if openssl_ver: > - break > + # look for the openssl version header on the compiler search path. > + opensslv_h = find_file('openssl/opensslv.h', [], You should use os.path.join() for this rather than a verbatim '/'. > + inc_dirs + search_for_ssl_incs_in) > + if opensslv_h: > + name = os.path.join(opensslv_h[0], 'openssl/opensslv.h') > + if sys.platform == 'darwin' and is_macosx_sdk_path(name): > + name = os.path.join(macosx_sdk_root(), name[1:]) > + try: > + incfile = open(name, 'r') > + for line in incfile: > + m = openssl_ver_re.match(line) > + if m: > + openssl_ver = eval(m.group(1)) > + except IOError, msg: > + print "IOError while reading opensshv.h:", msg > + pass Note that the new code doesn't search all available opensslv.h header files for a matching case. It only looks at the first found and if that doesn't match, it fails. -- Marc-Andre Lemburg eGenix.com Professional Python Services directly from the Source (#1, Jun 04 2010) >>> Python/Zope Consulting and Support ... http://www.egenix.com/ >>> mxODBC.Zope.Database.Adapter ... http://zope.egenix.com/ >>> mxODBC, mxDateTime, mxTextTools ... http://python.egenix.com/ ________________________________________________________________________ 2010-07-19: EuroPython 2010, Birmingham, UK 44 days to go ::: Try our new mxODBC.Connect Python Database Interface for free ! :::: eGenix.com Software, Skills and Services GmbH Pastor-Loeh-Str.48 D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg Registered at Amtsgericht Duesseldorf: HRB 46611 http://www.egenix.com/company/contact/ From python-checkins at python.org Fri Jun 4 11:49:21 2010 From: python-checkins at python.org (stefan.krah) Date: Fri, 4 Jun 2010 11:49:21 +0200 (CEST) Subject: [Python-checkins] r81683 - python/trunk/setup.py Message-ID: <20100604094921.2C2A4EE994@mail.python.org> Author: stefan.krah Date: Fri Jun 4 11:49:20 2010 New Revision: 81683 Log: Detect missing ldd on all systems. Modified: python/trunk/setup.py Modified: python/trunk/setup.py ============================================================================== --- python/trunk/setup.py (original) +++ python/trunk/setup.py Fri Jun 4 11:49:20 2010 @@ -15,6 +15,7 @@ from distutils.command.build_ext import build_ext from distutils.command.install import install from distutils.command.install_lib import install_lib +from distutils.spawn import find_executable # Were we compiled --with-pydebug or with #define Py_DEBUG? COMPILED_WITH_PYDEBUG = hasattr(sys, 'gettotalrefcount') @@ -591,7 +592,7 @@ readline_termcap_library = "" curses_library = "" # Determine if readline is already linked against curses or tinfo. - if do_readline and platform != 'darwin': # OS X does not have ldd. + if do_readline and find_executable('ldd'): fp = os.popen("ldd %s" % do_readline) for ln in fp: if 'curses' in ln: From python-checkins at python.org Fri Jun 4 15:41:02 2010 From: python-checkins at python.org (vinay.sajip) Date: Fri, 4 Jun 2010 15:41:02 +0200 (CEST) Subject: [Python-checkins] r81684 - python/trunk/Doc/library/logging.rst Message-ID: <20100604134102.60B6BEEC1B@mail.python.org> Author: vinay.sajip Date: Fri Jun 4 15:41:02 2010 New Revision: 81684 Log: Issue #8890: Documentation changed to avoid reference to temporary files - other cases covered. Modified: python/trunk/Doc/library/logging.rst Modified: python/trunk/Doc/library/logging.rst ============================================================================== --- python/trunk/Doc/library/logging.rst (original) +++ python/trunk/Doc/library/logging.rst Fri Jun 4 15:41:02 2010 @@ -57,7 +57,7 @@ with that case. Using the :func:`basicConfig` function, we can set up the 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:: +*example.log* in the current directory):: import logging LOG_FILENAME = 'example.log' @@ -79,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') @@ -104,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. @@ -1134,14 +1134,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 From python-checkins at python.org Fri Jun 4 18:11:08 2010 From: python-checkins at python.org (r.david.murray) Date: Fri, 4 Jun 2010 18:11:08 +0200 (CEST) Subject: [Python-checkins] r81685 - in python/branches/py3k: Lib/email/encoders.py Lib/email/test/test_email.py Misc/ACKS Misc/NEWS Message-ID: <20100604161108.E11EEEECD8@mail.python.org> Author: r.david.murray Date: Fri Jun 4 18:11:08 2010 New Revision: 81685 Log: #4768: store base64 encoded email body parts as text, not binary. Patch and tests by Forest Bond. Modified: python/branches/py3k/Lib/email/encoders.py python/branches/py3k/Lib/email/test/test_email.py python/branches/py3k/Misc/ACKS python/branches/py3k/Misc/NEWS Modified: python/branches/py3k/Lib/email/encoders.py ============================================================================== --- python/branches/py3k/Lib/email/encoders.py (original) +++ python/branches/py3k/Lib/email/encoders.py Fri Jun 4 18:11:08 2010 @@ -29,7 +29,7 @@ Also, add an appropriate Content-Transfer-Encoding header. """ orig = msg.get_payload() - encdata = _bencode(orig) + encdata = str(_bencode(orig), 'ascii') msg.set_payload(encdata) msg['Content-Transfer-Encoding'] = 'base64' Modified: python/branches/py3k/Lib/email/test/test_email.py ============================================================================== --- python/branches/py3k/Lib/email/test/test_email.py (original) +++ python/branches/py3k/Lib/email/test/test_email.py Fri Jun 4 18:11:08 2010 @@ -970,7 +970,8 @@ def test_encoding(self): payload = self._au.get_payload() - self.assertEqual(base64.decodebytes(payload), self._audiodata) + self.assertEqual(base64.decodebytes(bytes(payload, 'ascii')), + self._audiodata) def test_checkSetMinor(self): au = MIMEAudio(self._audiodata, 'fish') @@ -1010,7 +1011,8 @@ def test_encoding(self): payload = self._im.get_payload() - self.assertEqual(base64.decodebytes(payload), self._imgdata) + self.assertEqual(base64.decodebytes(bytes(payload, 'ascii')), + self._imgdata) def test_checkSetMinor(self): im = MIMEImage(self._imgdata, 'fish') @@ -1050,7 +1052,7 @@ eq = self.assertEqual bytes = b'\xfa\xfb\xfc\xfd\xfe\xff' msg = MIMEApplication(bytes) - eq(msg.get_payload(), b'+vv8/f7/') + eq(msg.get_payload(), '+vv8/f7/') eq(msg.get_payload(decode=True), bytes) Modified: python/branches/py3k/Misc/ACKS ============================================================================== --- python/branches/py3k/Misc/ACKS (original) +++ python/branches/py3k/Misc/ACKS Fri Jun 4 18:11:08 2010 @@ -83,6 +83,7 @@ Paul Boddie Matthew Boedicker David Bolen +Forest Bond Gawain Bolton Gregory Bond Jurjen Bos Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Fri Jun 4 18:11:08 2010 @@ -398,6 +398,9 @@ Library ------- +- Issue #4768: base64 encoded email body parts were incorrectly stored as + binary strings. They are now correctly converted to strings. + - Issue #8833: tarfile created hard link entries with a size field != 0 by mistake. From python-checkins at python.org Fri Jun 4 18:15:35 2010 From: python-checkins at python.org (r.david.murray) Date: Fri, 4 Jun 2010 18:15:35 +0200 (CEST) Subject: [Python-checkins] r81686 - in python/branches/release31-maint: Lib/email/encoders.py Lib/email/test/test_email.py Misc/ACKS Misc/NEWS Message-ID: <20100604161535.252B7EEA2@mail.python.org> Author: r.david.murray Date: Fri Jun 4 18:15:34 2010 New Revision: 81686 Log: Merged revisions 81685 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ........ r81685 | r.david.murray | 2010-06-04 12:11:08 -0400 (Fri, 04 Jun 2010) | 4 lines #4768: store base64 encoded email body parts as text, not binary. Patch and tests by Forest Bond. ........ Modified: python/branches/release31-maint/ (props changed) python/branches/release31-maint/Lib/email/encoders.py python/branches/release31-maint/Lib/email/test/test_email.py python/branches/release31-maint/Misc/ACKS python/branches/release31-maint/Misc/NEWS Modified: python/branches/release31-maint/Lib/email/encoders.py ============================================================================== --- python/branches/release31-maint/Lib/email/encoders.py (original) +++ python/branches/release31-maint/Lib/email/encoders.py Fri Jun 4 18:15:34 2010 @@ -29,7 +29,7 @@ Also, add an appropriate Content-Transfer-Encoding header. """ orig = msg.get_payload() - encdata = _bencode(orig) + encdata = str(_bencode(orig), 'ascii') msg.set_payload(encdata) msg['Content-Transfer-Encoding'] = 'base64' Modified: python/branches/release31-maint/Lib/email/test/test_email.py ============================================================================== --- python/branches/release31-maint/Lib/email/test/test_email.py (original) +++ python/branches/release31-maint/Lib/email/test/test_email.py Fri Jun 4 18:15:34 2010 @@ -966,7 +966,8 @@ def test_encoding(self): payload = self._au.get_payload() - self.assertEqual(base64.decodebytes(payload), self._audiodata) + self.assertEqual(base64.decodebytes(bytes(payload, 'ascii')), + self._audiodata) def test_checkSetMinor(self): au = MIMEAudio(self._audiodata, 'fish') @@ -1006,7 +1007,8 @@ def test_encoding(self): payload = self._im.get_payload() - self.assertEqual(base64.decodebytes(payload), self._imgdata) + self.assertEqual(base64.decodebytes(bytes(payload, 'ascii')), + self._imgdata) def test_checkSetMinor(self): im = MIMEImage(self._imgdata, 'fish') @@ -1046,7 +1048,7 @@ eq = self.assertEqual bytes = b'\xfa\xfb\xfc\xfd\xfe\xff' msg = MIMEApplication(bytes) - eq(msg.get_payload(), b'+vv8/f7/') + eq(msg.get_payload(), '+vv8/f7/') eq(msg.get_payload(decode=True), bytes) Modified: python/branches/release31-maint/Misc/ACKS ============================================================================== --- python/branches/release31-maint/Misc/ACKS (original) +++ python/branches/release31-maint/Misc/ACKS Fri Jun 4 18:15:34 2010 @@ -81,6 +81,7 @@ Paul Boddie Matthew Boedicker David Bolen +Forest Bond Gregory Bond Jurjen Bos Peter Bosch Modified: python/branches/release31-maint/Misc/NEWS ============================================================================== --- python/branches/release31-maint/Misc/NEWS (original) +++ python/branches/release31-maint/Misc/NEWS Fri Jun 4 18:15:34 2010 @@ -54,6 +54,9 @@ Library ------- +- Issue #4768: base64 encoded email body parts were incorrectly stored as + binary strings. They are now correctly converted to strings. + - Issue #8833: tarfile created hard link entries with a size field != 0 by mistake. From python-checkins at python.org Fri Jun 4 18:32:14 2010 From: python-checkins at python.org (senthil.kumaran) Date: Fri, 4 Jun 2010 18:32:14 +0200 (CEST) Subject: [Python-checkins] r81687 - python/trunk/Lib/httplib.py Message-ID: <20100604163214.8A4F1EECE9@mail.python.org> Author: senthil.kumaran Date: Fri Jun 4 18:32:14 2010 New Revision: 81687 Log: Fix issue6312 - close the resp object for HEAD response. Modified: python/trunk/Lib/httplib.py Modified: python/trunk/Lib/httplib.py ============================================================================== --- python/trunk/Lib/httplib.py (original) +++ python/trunk/Lib/httplib.py Fri Jun 4 18:32:14 2010 @@ -525,6 +525,7 @@ return '' if self._method == 'HEAD': + self.close() return '' if self.chunked: From python-checkins at python.org Fri Jun 4 18:34:53 2010 From: python-checkins at python.org (senthil.kumaran) Date: Fri, 4 Jun 2010 18:34:53 +0200 (CEST) Subject: [Python-checkins] r81688 - in python/branches/release26-maint: Lib/httplib.py Message-ID: <20100604163453.83E7BEFE3@mail.python.org> Author: senthil.kumaran Date: Fri Jun 4 18:34:53 2010 New Revision: 81688 Log: Merged revisions 81687 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81687 | senthil.kumaran | 2010-06-04 22:02:14 +0530 (Fri, 04 Jun 2010) | 3 lines Fix issue6312 - close the resp object for HEAD response. ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Lib/httplib.py Modified: python/branches/release26-maint/Lib/httplib.py ============================================================================== --- python/branches/release26-maint/Lib/httplib.py (original) +++ python/branches/release26-maint/Lib/httplib.py Fri Jun 4 18:34:53 2010 @@ -515,6 +515,7 @@ return '' if self._method == 'HEAD': + self.close() return '' if self.chunked: From python-checkins at python.org Fri Jun 4 18:38:00 2010 From: python-checkins at python.org (senthil.kumaran) Date: Fri, 4 Jun 2010 18:38:00 +0200 (CEST) Subject: [Python-checkins] r81689 - in python/branches/py3k: Lib/http/client.py Message-ID: <20100604163800.BAC2FEE98A@mail.python.org> Author: senthil.kumaran Date: Fri Jun 4 18:38:00 2010 New Revision: 81689 Log: Merged revisions 81687 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81687 | senthil.kumaran | 2010-06-04 22:02:14 +0530 (Fri, 04 Jun 2010) | 3 lines Fix issue6312 - close the resp object for HEAD response. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/http/client.py Modified: python/branches/py3k/Lib/http/client.py ============================================================================== --- python/branches/py3k/Lib/http/client.py (original) +++ python/branches/py3k/Lib/http/client.py Fri Jun 4 18:38:00 2010 @@ -488,6 +488,7 @@ return b"" if self._method == "HEAD": + self.close() return b"" if self.chunked: From python-checkins at python.org Fri Jun 4 18:43:10 2010 From: python-checkins at python.org (senthil.kumaran) Date: Fri, 4 Jun 2010 18:43:10 +0200 (CEST) Subject: [Python-checkins] r81690 - in python/branches/release31-maint: Lib/http/client.py Message-ID: <20100604164310.CDA46EE9AC@mail.python.org> Author: senthil.kumaran Date: Fri Jun 4 18:43:10 2010 New Revision: 81690 Log: Merged revisions 81689 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ................ r81689 | senthil.kumaran | 2010-06-04 22:08:00 +0530 (Fri, 04 Jun 2010) | 9 lines Merged revisions 81687 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81687 | senthil.kumaran | 2010-06-04 22:02:14 +0530 (Fri, 04 Jun 2010) | 3 lines Fix issue6312 - close the resp object for HEAD response. ........ ................ Modified: python/branches/release31-maint/ (props changed) python/branches/release31-maint/Lib/http/client.py Modified: python/branches/release31-maint/Lib/http/client.py ============================================================================== --- python/branches/release31-maint/Lib/http/client.py (original) +++ python/branches/release31-maint/Lib/http/client.py Fri Jun 4 18:43:10 2010 @@ -488,6 +488,7 @@ return b"" if self._method == "HEAD": + self.close() return b"" if self.chunked: From python-checkins at python.org Fri Jun 4 19:17:09 2010 From: python-checkins at python.org (senthil.kumaran) Date: Fri, 4 Jun 2010 19:17:09 +0200 (CEST) Subject: [Python-checkins] r81691 - python/trunk/Lib/test/test_httplib.py Message-ID: <20100604171709.62EADEECBA@mail.python.org> Author: senthil.kumaran Date: Fri Jun 4 19:17:09 2010 New Revision: 81691 Log: test verifying the resp object is closed for HEAD response. Modified: python/trunk/Lib/test/test_httplib.py Modified: python/trunk/Lib/test/test_httplib.py ============================================================================== --- python/trunk/Lib/test/test_httplib.py (original) +++ python/trunk/Lib/test/test_httplib.py Fri Jun 4 19:17:09 2010 @@ -227,7 +227,7 @@ self.assertEquals(resp.read(), '') self.assertEquals(resp.status, 200) self.assertEquals(resp.reason, 'OK') - resp.close() + self.assertTrue(resp.isclosed()) def test_negative_content_length(self): sock = FakeSocket('HTTP/1.1 200 OK\r\n' From python-checkins at python.org Fri Jun 4 19:18:43 2010 From: python-checkins at python.org (martin.v.loewis) Date: Fri, 4 Jun 2010 19:18:43 +0200 (CEST) Subject: [Python-checkins] r81692 - in python/trunk: Misc/NEWS Modules/_multiprocessing/multiprocessing.h Message-ID: <20100604171843.056C4F2F1@mail.python.org> Author: martin.v.loewis Date: Fri Jun 4 19:18:42 2010 New Revision: 81692 Log: Issue #8864: Define _XOPEN_SOURCE on Solaris for the multiprocessing module. Modified: python/trunk/Misc/NEWS python/trunk/Modules/_multiprocessing/multiprocessing.h Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Fri Jun 4 19:18:42 2010 @@ -120,7 +120,8 @@ Build ----- -- Issue #1759169: Drop _XOPEN_SOURCE on Solaris. +- Issues #1759169, #8864: Drop _XOPEN_SOURCE on Solaris, define it for + multiprocessing only. What's New in Python 2.7 beta 2? ================================ Modified: python/trunk/Modules/_multiprocessing/multiprocessing.h ============================================================================== --- python/trunk/Modules/_multiprocessing/multiprocessing.h (original) +++ python/trunk/Modules/_multiprocessing/multiprocessing.h Fri Jun 4 19:18:42 2010 @@ -3,6 +3,12 @@ #define PY_SSIZE_T_CLEAN +#ifdef __sun +/* The control message API is only available on Solaris + if XPG 4.2 or later is requested. */ +#define _XOPEN_SOURCE 500 +#endif + #include "Python.h" #include "structmember.h" #include "pythread.h" From python-checkins at python.org Fri Jun 4 19:20:13 2010 From: python-checkins at python.org (senthil.kumaran) Date: Fri, 4 Jun 2010 19:20:13 +0200 (CEST) Subject: [Python-checkins] r81693 - in python/branches/release26-maint: Lib/test/test_httplib.py Message-ID: <20100604172013.BAFD4EE999@mail.python.org> Author: senthil.kumaran Date: Fri Jun 4 19:20:13 2010 New Revision: 81693 Log: Merged revisions 81691 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81691 | senthil.kumaran | 2010-06-04 22:47:09 +0530 (Fri, 04 Jun 2010) | 3 lines test verifying the resp object is closed for HEAD response. ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Lib/test/test_httplib.py Modified: python/branches/release26-maint/Lib/test/test_httplib.py ============================================================================== --- python/branches/release26-maint/Lib/test/test_httplib.py (original) +++ python/branches/release26-maint/Lib/test/test_httplib.py Fri Jun 4 19:20:13 2010 @@ -222,7 +222,7 @@ self.assertEquals(resp.read(), '') self.assertEquals(resp.status, 200) self.assertEquals(resp.reason, 'OK') - resp.close() + self.assertTrue(resp.isclosed()) def test_negative_content_length(self): sock = FakeSocket('HTTP/1.1 200 OK\r\n' From python-checkins at python.org Fri Jun 4 19:20:56 2010 From: python-checkins at python.org (martin.v.loewis) Date: Fri, 4 Jun 2010 19:20:56 +0200 (CEST) Subject: [Python-checkins] r81694 - in python/branches/py3k: Misc/NEWS Modules/_multiprocessing/multiprocessing.h Message-ID: <20100604172056.69FACEE999@mail.python.org> Author: martin.v.loewis Date: Fri Jun 4 19:20:56 2010 New Revision: 81694 Log: Merged revisions 81692 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81692 | martin.v.loewis | 2010-06-04 19:18:42 +0200 (Fr, 04 Jun 2010) | 3 lines Issue #8864: Define _XOPEN_SOURCE on Solaris for the multiprocessing module. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Misc/NEWS python/branches/py3k/Modules/_multiprocessing/multiprocessing.h Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Fri Jun 4 19:20:56 2010 @@ -1328,7 +1328,8 @@ Build ----- -- Issue #1759169: Drop _XOPEN_SOURCE on Solaris. +- Issue #1759169, #8864: Drop _XOPEN_SOURCE on Solaris, define it for + multiprocessing only. - Issue #8625: Turn off optimization in --with-pydebug builds with gcc. (Optimization was unintentionally turned on in gcc Modified: python/branches/py3k/Modules/_multiprocessing/multiprocessing.h ============================================================================== --- python/branches/py3k/Modules/_multiprocessing/multiprocessing.h (original) +++ python/branches/py3k/Modules/_multiprocessing/multiprocessing.h Fri Jun 4 19:20:56 2010 @@ -3,6 +3,12 @@ #define PY_SSIZE_T_CLEAN +#ifdef __sun +/* The control message API is only available on Solaris + if XPG 4.2 or later is requested. */ +#define _XOPEN_SOURCE 500 +#endif + #include "Python.h" #include "structmember.h" #include "pythread.h" From python-checkins at python.org Fri Jun 4 19:27:11 2010 From: python-checkins at python.org (senthil.kumaran) Date: Fri, 4 Jun 2010 19:27:11 +0200 (CEST) Subject: [Python-checkins] r81695 - in python/branches/py3k: Lib/test/test_httplib.py Message-ID: <20100604172711.94547F6905@mail.python.org> Author: senthil.kumaran Date: Fri Jun 4 19:27:11 2010 New Revision: 81695 Log: Merged revisions 81691 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81691 | senthil.kumaran | 2010-06-04 22:47:09 +0530 (Fri, 04 Jun 2010) | 3 lines test verifying the resp object is closed for HEAD response. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/test/test_httplib.py Modified: python/branches/py3k/Lib/test/test_httplib.py ============================================================================== --- python/branches/py3k/Lib/test/test_httplib.py (original) +++ python/branches/py3k/Lib/test/test_httplib.py Fri Jun 4 19:27:11 2010 @@ -239,7 +239,7 @@ self.assertEquals(resp.read(), b'') self.assertEquals(resp.status, 200) self.assertEquals(resp.reason, 'OK') - resp.close() + self.assertTrue(resp.isclosed()) def test_negative_content_length(self): sock = FakeSocket( From python-checkins at python.org Fri Jun 4 19:31:11 2010 From: python-checkins at python.org (senthil.kumaran) Date: Fri, 4 Jun 2010 19:31:11 +0200 (CEST) Subject: [Python-checkins] r81696 - in python/branches/release31-maint: Lib/test/test_httplib.py Message-ID: <20100604173111.B3FECEE9B8@mail.python.org> Author: senthil.kumaran Date: Fri Jun 4 19:31:11 2010 New Revision: 81696 Log: Merged revisions 81695 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ................ r81695 | senthil.kumaran | 2010-06-04 22:57:11 +0530 (Fri, 04 Jun 2010) | 9 lines Merged revisions 81691 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81691 | senthil.kumaran | 2010-06-04 22:47:09 +0530 (Fri, 04 Jun 2010) | 3 lines test verifying the resp object is closed for HEAD response. ........ ................ Modified: python/branches/release31-maint/ (props changed) python/branches/release31-maint/Lib/test/test_httplib.py Modified: python/branches/release31-maint/Lib/test/test_httplib.py ============================================================================== --- python/branches/release31-maint/Lib/test/test_httplib.py (original) +++ python/branches/release31-maint/Lib/test/test_httplib.py Fri Jun 4 19:31:11 2010 @@ -234,7 +234,7 @@ self.assertEquals(resp.read(), b'') self.assertEquals(resp.status, 200) self.assertEquals(resp.reason, 'OK') - resp.close() + self.assertTrue(resp.isclosed()) def test_negative_content_length(self): sock = FakeSocket( From python-checkins at python.org Fri Jun 4 20:04:42 2010 From: python-checkins at python.org (martin.v.loewis) Date: Fri, 4 Jun 2010 20:04:42 +0200 (CEST) Subject: [Python-checkins] r81697 - in python/trunk: Misc/NEWS Tools/i18n/msgfmt.py Message-ID: <20100604180442.6EAFEEECE6@mail.python.org> Author: martin.v.loewis Date: Fri Jun 4 20:04:42 2010 New Revision: 81697 Log: Issue #5464: Implement plural forms in msgfmt.py. Modified: python/trunk/Misc/NEWS python/trunk/Tools/i18n/msgfmt.py Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Fri Jun 4 20:04:42 2010 @@ -123,6 +123,12 @@ - Issues #1759169, #8864: Drop _XOPEN_SOURCE on Solaris, define it for multiprocessing only. +Tools/Demos +----------- + +- Issue #5464: Implement plural forms in msgfmt.py. + + What's New in Python 2.7 beta 2? ================================ Modified: python/trunk/Tools/i18n/msgfmt.py ============================================================================== --- python/trunk/Tools/i18n/msgfmt.py (original) +++ python/trunk/Tools/i18n/msgfmt.py Fri Jun 4 20:04:42 2010 @@ -133,16 +133,39 @@ if l[0] == '#': continue # Now we are in a msgid section, output previous section - if l.startswith('msgid'): + if l.startswith('msgid') and not l.startswith('msgid_plural'): if section == STR: add(msgid, msgstr, fuzzy) section = ID l = l[5:] msgid = msgstr = '' + is_plural = False + # This is a message with plural forms + elif l.startswith('msgid_plural'): + if section != ID: + print >> sys.stderr, 'msgid_plural not preceeded by msgid on %s:%d' %\ + (infile, lno) + sys.exit(1) + l = l[12:] + msgid += '\0' # separator of singular and plural + is_plural = True # Now we are in a msgstr section elif l.startswith('msgstr'): section = STR - l = l[6:] + if l.startswith('msgstr['): + if not is_plural: + print >> sys.stderr, 'plural without msgid_plural on %s:%d' %\ + (infile, lno) + sys.exit(1) + l = l.split(']', 1)[1] + if msgstr: + msgstr += '\0' # Separator of the various plural forms + else: + if is_plural: + print >> sys.stderr, 'indexed msgstr required for plural on %s:%d' %\ + (infile, lno) + sys.exit(1) + l = l[6:] # Skip empty lines l = l.strip() if not l: From python-checkins at python.org Fri Jun 4 20:14:43 2010 From: python-checkins at python.org (martin.v.loewis) Date: Fri, 4 Jun 2010 20:14:43 +0200 (CEST) Subject: [Python-checkins] r81698 - in python/branches/py3k: Misc/NEWS Tools/i18n/msgfmt.py Message-ID: <20100604181443.034B0F6905@mail.python.org> Author: martin.v.loewis Date: Fri Jun 4 20:14:42 2010 New Revision: 81698 Log: Merged revisions 81697 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81697 | martin.v.loewis | 2010-06-04 20:04:42 +0200 (Fr, 04 Jun 2010) | 2 lines Issue #5464: Implement plural forms in msgfmt.py. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Misc/NEWS python/branches/py3k/Tools/i18n/msgfmt.py Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Fri Jun 4 20:14:42 2010 @@ -1548,6 +1548,8 @@ Tools/Demos ----------- +- Issue #5464: Implement plural forms in msgfmt.py. + - iobench (a file I/O benchmark) and ccbench (a concurrency benchmark) were added to the `Tools/` directory. They were previously living in the sandbox. Modified: python/branches/py3k/Tools/i18n/msgfmt.py ============================================================================== --- python/branches/py3k/Tools/i18n/msgfmt.py (original) +++ python/branches/py3k/Tools/i18n/msgfmt.py Fri Jun 4 20:14:42 2010 @@ -132,16 +132,39 @@ if l[0] == '#': continue # Now we are in a msgid section, output previous section - if l.startswith('msgid'): + if l.startswith('msgid') and not l.startswith('msgid_plural'): if section == STR: add(msgid, msgstr, fuzzy) section = ID l = l[5:] msgid = msgstr = '' + is_plural = False + # This is a message with plural forms + elif l.startswith('msgid_plural'): + if section != ID: + print('msgid_plural not preceeded by msgid on %s:%d' % (infile, lno), + file=sys.stderr) + sys.exit(1) + l = l[12:] + msgid += '\0' # separator of singular and plural + is_plural = True # Now we are in a msgstr section elif l.startswith('msgstr'): section = STR - l = l[6:] + if l.startswith('msgstr['): + if not is_plural: + print(sys.stderr, 'plural without msgid_plural on %s:%d' % (infile, lno), + file=sys.stderr) + sys.exit(1) + l = l.split(']', 1)[1] + if msgstr: + msgstr += '\0' # Separator of the various plural forms + else: + if is_plural: + print(sys.stderr, 'indexed msgstr required for plural on %s:%d' % (infile, lno), + file=sys.stderr) + sys.exit(1) + l = l[6:] # Skip empty lines l = l.strip() if not l: From python-checkins at python.org Fri Jun 4 20:40:55 2010 From: python-checkins at python.org (martin.v.loewis) Date: Fri, 4 Jun 2010 20:40:55 +0200 (CEST) Subject: [Python-checkins] r81699 - python/branches/py3k/Tools/i18n/msgfmt.py Message-ID: <20100604184055.66D12EED08@mail.python.org> Author: martin.v.loewis Date: Fri Jun 4 20:40:55 2010 New Revision: 81699 Log: Port to Python 3. Modified: python/branches/py3k/Tools/i18n/msgfmt.py Modified: python/branches/py3k/Tools/i18n/msgfmt.py ============================================================================== --- python/branches/py3k/Tools/i18n/msgfmt.py (original) +++ python/branches/py3k/Tools/i18n/msgfmt.py Fri Jun 4 20:40:55 2010 @@ -30,6 +30,7 @@ import getopt import struct import array +from email.parser import HeaderParser __version__ = "1.1" @@ -59,13 +60,13 @@ # the keys are sorted in the .mo file keys = sorted(MESSAGES.keys()) offsets = [] - ids = strs = '' + ids = strs = b'' for id in keys: # For each string, we need size and file offset. Each string is NUL # terminated; the NUL does not count into the size. offsets.append((len(ids), len(id), len(strs), len(MESSAGES[id]))) - ids += id + '\0' - strs += MESSAGES[id] + '\0' + ids += id + b'\0' + strs += MESSAGES[id] + b'\0' output = '' # The header is 7 32-bit unsigned integers. We don't use hash tables, so # the keys start right after the index tables. @@ -108,7 +109,7 @@ outfile = os.path.splitext(infile)[0] + '.mo' try: - lines = open(infile).readlines() + lines = open(infile, 'rb').readlines() except IOError as msg: print(msg, file=sys.stderr) sys.exit(1) @@ -116,9 +117,14 @@ section = None fuzzy = 0 + # Start off assuming Latin-1, so everything decodes without failure, + # until we know the exact encoding + encoding = 'latin-1' + # Parse the catalog lno = 0 for l in lines: + l = l.decode(encoding) lno += 1 # If we get a comment line after a msgstr, this is a new entry if l[0] == '#' and section == STR: @@ -135,9 +141,15 @@ if l.startswith('msgid') and not l.startswith('msgid_plural'): if section == STR: add(msgid, msgstr, fuzzy) + if not msgid: + # See whether there is an encoding declaration + p = HeaderParser() + charset = p.parsestr(msgstr.decode(encoding)).get_content_charset() + if charset: + encoding = charset section = ID l = l[5:] - msgid = msgstr = '' + msgid = msgstr = b'' is_plural = False # This is a message with plural forms elif l.startswith('msgid_plural'): @@ -146,7 +158,7 @@ file=sys.stderr) sys.exit(1) l = l[12:] - msgid += '\0' # separator of singular and plural + msgid += b'\0' # separator of singular and plural is_plural = True # Now we are in a msgstr section elif l.startswith('msgstr'): @@ -158,7 +170,7 @@ sys.exit(1) l = l.split(']', 1)[1] if msgstr: - msgstr += '\0' # Separator of the various plural forms + msgstr += b'\0' # Separator of the various plural forms else: if is_plural: print(sys.stderr, 'indexed msgstr required for plural on %s:%d' % (infile, lno), @@ -172,9 +184,9 @@ # XXX: Does this always follow Python escape semantics? l = eval(l) if section == ID: - msgid += l + msgid += l.encode(encoding) elif section == STR: - msgstr += l + msgstr += l.encode(encoding) else: print('Syntax error on %s:%d' % (infile, lno), \ 'before:', file=sys.stderr) From python-checkins at python.org Fri Jun 4 21:15:32 2010 From: python-checkins at python.org (martin.v.loewis) Date: Fri, 4 Jun 2010 21:15:32 +0200 (CEST) Subject: [Python-checkins] r81700 - in python/trunk: Misc/NEWS Tools/msi/msi.py Message-ID: <20100604191532.9AA0AEED17@mail.python.org> Author: martin.v.loewis Date: Fri Jun 4 21:15:32 2010 New Revision: 81700 Log: Display installer warning that Windows 2000 won't be supported in future releases. Modified: python/trunk/Misc/NEWS python/trunk/Tools/msi/msi.py Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Fri Jun 4 21:15:32 2010 @@ -120,6 +120,9 @@ Build ----- +- Display installer warning that Windows 2000 won't be supported in future + releases. + - Issues #1759169, #8864: Drop _XOPEN_SOURCE on Solaris, define it for multiprocessing only. Modified: python/trunk/Tools/msi/msi.py ============================================================================== --- python/trunk/Tools/msi/msi.py (original) +++ python/trunk/Tools/msi/msi.py Fri Jun 4 21:15:32 2010 @@ -503,9 +503,9 @@ " would still be Python for DOS.") c = exit_dialog.text("warning", 135, 200, 220, 40, 0x30003, - "{\\VerdanaRed9}Warning: Python 2.5.x is the last " - "Python release for Windows 9x.") - c.condition("Hide", "NOT Version9X") + "{\\VerdanaRed9}Warning: Python 2.7.x is the last " + "Python release for Windows 2000.") + c.condition("Hide", "VersionNT > 500") exit_dialog.text("Description", 135, 235, 220, 20, 0x30003, "Click the Finish button to exit the Installer.") From python-checkins at python.org Fri Jun 4 21:39:07 2010 From: python-checkins at python.org (martin.v.loewis) Date: Fri, 4 Jun 2010 21:39:07 +0200 (CEST) Subject: [Python-checkins] r81701 - in python/trunk: Lib/lib-tk/FixTk.py Lib/test/test_tcl.py Misc/NEWS Message-ID: <20100604193907.55480EEC20@mail.python.org> Author: martin.v.loewis Date: Fri Jun 4 21:39:07 2010 New Revision: 81701 Log: Issue #6470: Drop UNC prefix in FixTk.py Patch by Christop Gohlke and Amaury Forgeot d'Arc. Modified: python/trunk/Lib/lib-tk/FixTk.py python/trunk/Lib/test/test_tcl.py python/trunk/Misc/NEWS Modified: python/trunk/Lib/lib-tk/FixTk.py ============================================================================== --- python/trunk/Lib/lib-tk/FixTk.py (original) +++ python/trunk/Lib/lib-tk/FixTk.py Fri Jun 4 21:39:07 2010 @@ -42,6 +42,8 @@ # Ignore leading \\?\ if s.startswith("\\\\?\\"): s = s[4:] + if s.startswith("UNC"): + s = "\\" + s[3:] return s prefix = os.path.join(sys.prefix,"tcl") Modified: python/trunk/Lib/test/test_tcl.py ============================================================================== --- python/trunk/Lib/test/test_tcl.py (original) +++ python/trunk/Lib/test/test_tcl.py Fri Jun 4 21:39:07 2010 @@ -127,6 +127,31 @@ tcl = self.interp self.assertRaises(TclError,tcl.eval,'package require DNE') + def testLoadWithUNC(self): + import sys + if sys.platform != 'win32': + return + + # Build a UNC path from the regular path. + # Something like + # \\%COMPUTERNAME%\c$\python27\python.exe + + fullname = os.path.abspath(sys.executable) + if fullname[1] != ':': + return + unc_name = r'\\%s\%s$\%s' % (os.environ['COMPUTERNAME'], + fullname[0], + fullname[3:]) + + with test_support.EnvironmentVarGuard() as env: + env.unset("TCL_LIBRARY") + f = os.popen('%s -c "import Tkinter; print Tkinter"' % (unc_name,)) + + self.assert_('Tkinter.py' in f.read()) + # exit code must be zero + self.assertEqual(f.close(), None) + + def test_main(): test_support.run_unittest(TclTest, TkinterTest) Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Fri Jun 4 21:39:07 2010 @@ -46,6 +46,8 @@ Library ------- +- Issue #6470: Drop UNC prefix in FixTk. + - Issue #5610: feedparser no longer eats extra characters at the end of a body part if the body part ends with a \r\n. From python-checkins at python.org Fri Jun 4 21:46:21 2010 From: python-checkins at python.org (martin.v.loewis) Date: Fri, 4 Jun 2010 21:46:21 +0200 (CEST) Subject: [Python-checkins] r81702 - in python/branches/release26-maint: Lib/lib-tk/FixTk.py Lib/test/test_tcl.py Misc/NEWS Message-ID: <20100604194621.E5FD2EED0A@mail.python.org> Author: martin.v.loewis Date: Fri Jun 4 21:46:21 2010 New Revision: 81702 Log: Merged revisions 81701 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81701 | martin.v.loewis | 2010-06-04 21:39:07 +0200 (Fr, 04 Jun 2010) | 2 lines Issue #6470: Drop UNC prefix in FixTk.py Patch by Christop Gohlke and Amaury Forgeot d'Arc. ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Lib/lib-tk/FixTk.py python/branches/release26-maint/Lib/test/test_tcl.py python/branches/release26-maint/Misc/NEWS Modified: python/branches/release26-maint/Lib/lib-tk/FixTk.py ============================================================================== --- python/branches/release26-maint/Lib/lib-tk/FixTk.py (original) +++ python/branches/release26-maint/Lib/lib-tk/FixTk.py Fri Jun 4 21:46:21 2010 @@ -42,6 +42,8 @@ # Ignore leading \\?\ if s.startswith("\\\\?\\"): s = s[4:] + if s.startswith("UNC"): + s = "\\" + s[3:] return s prefix = os.path.join(sys.prefix,"tcl") Modified: python/branches/release26-maint/Lib/test/test_tcl.py ============================================================================== --- python/branches/release26-maint/Lib/test/test_tcl.py (original) +++ python/branches/release26-maint/Lib/test/test_tcl.py Fri Jun 4 21:46:21 2010 @@ -150,6 +150,31 @@ if old_display is not None: os.environ['DISPLAY'] = old_display + def testLoadWithUNC(self): + import sys + if sys.platform != 'win32': + return + + # Build a UNC path from the regular path. + # Something like + # \\%COMPUTERNAME%\c$\python27\python.exe + + fullname = os.path.abspath(sys.executable) + if fullname[1] != ':': + return + unc_name = r'\\%s\%s$\%s' % (os.environ['COMPUTERNAME'], + fullname[0], + fullname[3:]) + + with test_support.EnvironmentVarGuard() as env: + env.unset("TCL_LIBRARY") + f = os.popen('%s -c "import Tkinter; print Tkinter"' % (unc_name,)) + + self.assert_('Tkinter.py' in f.read()) + # exit code must be zero + self.assertEqual(f.close(), None) + + def test_main(): test_support.run_unittest(TclTest) Modified: python/branches/release26-maint/Misc/NEWS ============================================================================== --- python/branches/release26-maint/Misc/NEWS (original) +++ python/branches/release26-maint/Misc/NEWS Fri Jun 4 21:46:21 2010 @@ -58,6 +58,8 @@ Library ------- +- Issue #6470: Drop UNC prefix in FixTk. + - Issue #8833: tarfile created hard link entries with a size field != 0 by mistake. From python-checkins at python.org Fri Jun 4 21:50:27 2010 From: python-checkins at python.org (martin.v.loewis) Date: Fri, 4 Jun 2010 21:50:27 +0200 (CEST) Subject: [Python-checkins] r81703 - in python/branches/py3k: Lib/test/test_tcl.py Lib/tkinter/_fix.py Misc/NEWS Message-ID: <20100604195027.11DC6EEC9B@mail.python.org> Author: martin.v.loewis Date: Fri Jun 4 21:50:26 2010 New Revision: 81703 Log: Merged revisions 81701 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81701 | martin.v.loewis | 2010-06-04 21:39:07 +0200 (Fr, 04 Jun 2010) | 2 lines Issue #6470: Drop UNC prefix in FixTk.py Patch by Christop Gohlke and Amaury Forgeot d'Arc. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/test/test_tcl.py python/branches/py3k/Lib/tkinter/_fix.py python/branches/py3k/Misc/NEWS Modified: python/branches/py3k/Lib/test/test_tcl.py ============================================================================== --- python/branches/py3k/Lib/test/test_tcl.py (original) +++ python/branches/py3k/Lib/test/test_tcl.py Fri Jun 4 21:50:26 2010 @@ -127,6 +127,31 @@ tcl = self.interp self.assertRaises(TclError,tcl.eval,'package require DNE') + def testLoadWithUNC(self): + import sys + if sys.platform != 'win32': + return + + # Build a UNC path from the regular path. + # Something like + # \\%COMPUTERNAME%\c$\python27\python.exe + + fullname = os.path.abspath(sys.executable) + if fullname[1] != ':': + return + unc_name = r'\\%s\%s$\%s' % (os.environ['COMPUTERNAME'], + fullname[0], + fullname[3:]) + + with test_support.EnvironmentVarGuard() as env: + env.unset("TCL_LIBRARY") + f = os.popen('%s -c "import Tkinter; print Tkinter"' % (unc_name,)) + + self.assert_('Tkinter.py' in f.read()) + # exit code must be zero + self.assertEqual(f.close(), None) + + def test_main(): support.run_unittest(TclTest, TkinterTest) Modified: python/branches/py3k/Lib/tkinter/_fix.py ============================================================================== --- python/branches/py3k/Lib/tkinter/_fix.py (original) +++ python/branches/py3k/Lib/tkinter/_fix.py Fri Jun 4 21:50:26 2010 @@ -42,6 +42,8 @@ # Ignore leading \\?\ if s.startswith("\\\\?\\"): s = s[4:] + if s.startswith("UNC"): + s = "\\" + s[3:] return s prefix = os.path.join(sys.prefix,"tcl") Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Fri Jun 4 21:50:26 2010 @@ -398,6 +398,8 @@ Library ------- +- Issue #6470: Drop UNC prefix in FixTk. + - Issue #4768: base64 encoded email body parts were incorrectly stored as binary strings. They are now correctly converted to strings. From python-checkins at python.org Fri Jun 4 21:51:05 2010 From: python-checkins at python.org (martin.v.loewis) Date: Fri, 4 Jun 2010 21:51:05 +0200 (CEST) Subject: [Python-checkins] r81704 - in python/branches/release31-maint: Lib/test/test_tcl.py Lib/tkinter/_fix.py Misc/NEWS Message-ID: <20100604195105.3E139EEC9E@mail.python.org> Author: martin.v.loewis Date: Fri Jun 4 21:51:05 2010 New Revision: 81704 Log: Merged revisions 81703 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ................ r81703 | martin.v.loewis | 2010-06-04 21:50:26 +0200 (Fr, 04 Jun 2010) | 10 lines Merged revisions 81701 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81701 | martin.v.loewis | 2010-06-04 21:39:07 +0200 (Fr, 04 Jun 2010) | 2 lines Issue #6470: Drop UNC prefix in FixTk.py Patch by Christop Gohlke and Amaury Forgeot d'Arc. ........ ................ Modified: python/branches/release31-maint/ (props changed) python/branches/release31-maint/Lib/test/test_tcl.py python/branches/release31-maint/Lib/tkinter/_fix.py python/branches/release31-maint/Misc/NEWS Modified: python/branches/release31-maint/Lib/test/test_tcl.py ============================================================================== --- python/branches/release31-maint/Lib/test/test_tcl.py (original) +++ python/branches/release31-maint/Lib/test/test_tcl.py Fri Jun 4 21:51:05 2010 @@ -127,6 +127,31 @@ tcl = self.interp self.assertRaises(TclError,tcl.eval,'package require DNE') + def testLoadWithUNC(self): + import sys + if sys.platform != 'win32': + return + + # Build a UNC path from the regular path. + # Something like + # \\%COMPUTERNAME%\c$\python27\python.exe + + fullname = os.path.abspath(sys.executable) + if fullname[1] != ':': + return + unc_name = r'\\%s\%s$\%s' % (os.environ['COMPUTERNAME'], + fullname[0], + fullname[3:]) + + with test_support.EnvironmentVarGuard() as env: + env.unset("TCL_LIBRARY") + f = os.popen('%s -c "import Tkinter; print Tkinter"' % (unc_name,)) + + self.assert_('Tkinter.py' in f.read()) + # exit code must be zero + self.assertEqual(f.close(), None) + + def test_main(): support.run_unittest(TclTest, TkinterTest) Modified: python/branches/release31-maint/Lib/tkinter/_fix.py ============================================================================== --- python/branches/release31-maint/Lib/tkinter/_fix.py (original) +++ python/branches/release31-maint/Lib/tkinter/_fix.py Fri Jun 4 21:51:05 2010 @@ -42,6 +42,8 @@ # Ignore leading \\?\ if s.startswith("\\\\?\\"): s = s[4:] + if s.startswith("UNC"): + s = "\\" + s[3:] return s prefix = os.path.join(sys.prefix,"tcl") Modified: python/branches/release31-maint/Misc/NEWS ============================================================================== --- python/branches/release31-maint/Misc/NEWS (original) +++ python/branches/release31-maint/Misc/NEWS Fri Jun 4 21:51:05 2010 @@ -54,6 +54,8 @@ Library ------- +- Issue #6470: Drop UNC prefix in FixTk. + - Issue #4768: base64 encoded email body parts were incorrectly stored as binary strings. They are now correctly converted to strings. From python-checkins at python.org Fri Jun 4 21:51:06 2010 From: python-checkins at python.org (r.david.murray) Date: Fri, 4 Jun 2010 21:51:06 +0200 (CEST) Subject: [Python-checkins] r81705 - in python/trunk: Lib/email/charset.py Lib/email/test/test_email.py Misc/NEWS Message-ID: <20100604195106.E3D15EED13@mail.python.org> Author: r.david.murray Date: Fri Jun 4 21:51:06 2010 New Revision: 81705 Log: #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. Modified: python/trunk/Lib/email/charset.py python/trunk/Lib/email/test/test_email.py python/trunk/Misc/NEWS Modified: python/trunk/Lib/email/charset.py ============================================================================== --- python/trunk/Lib/email/charset.py (original) +++ python/trunk/Lib/email/charset.py Fri Jun 4 21:51:06 2010 @@ -9,6 +9,7 @@ 'add_codec', ] +import codecs import email.base64mime import email.quoprimime @@ -209,7 +210,12 @@ except UnicodeError: raise errors.CharsetError(input_charset) input_charset = input_charset.lower() - # Set the input charset after filtering through the aliases + # Set the input charset after filtering through the aliases and/or codecs + if not (input_charset in ALIASES or input_charset in CHARSETS): + try: + input_charset = codecs.lookup(input_charset).name + except LookupError: + pass self.input_charset = ALIASES.get(input_charset, input_charset) # We can try to guess which encoding and conversion to use by the # charset_map dictionary. Try that first, but let the user override Modified: python/trunk/Lib/email/test/test_email.py ============================================================================== --- python/trunk/Lib/email/test/test_email.py (original) +++ python/trunk/Lib/email/test/test_email.py Fri Jun 4 21:51:06 2010 @@ -2868,6 +2868,9 @@ self.assertEqual(str(charset), 'us-ascii') self.assertRaises(Errors.CharsetError, Charset, 'asc\xffii') + def test_codecs_aliases_accepted(self): + charset = Charset('utf8') + self.assertEqual(str(charset), 'utf-8') # Test multilingual MIME headers. Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Fri Jun 4 21:51:06 2010 @@ -46,6 +46,9 @@ Library ------- +- Issue #4487: email now accepts as charset aliases all codec aliases + accepted by the codecs module. + - Issue #6470: Drop UNC prefix in FixTk. - Issue #5610: feedparser no longer eats extra characters at the end of From solipsis at pitrou.net Sat Jun 5 01:23:39 2010 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sat, 5 Jun 2010 01:23:39 +0200 (CEST) Subject: [Python-checkins] Daily py3k reference leaks (r81703): sum=0 Message-ID: <20100604232339.8D4261770A@ns6635.ovh.net> py3k results for svn r81703 (hg cset a0c24aaa2de5) -------------------------------------------------- Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/py3k/refleaks/reflogUlgvl4', '-x'] From python-checkins at python.org Sat Jun 5 02:32:51 2010 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 5 Jun 2010 02:32:51 +0200 (CEST) Subject: [Python-checkins] r81706 - in python/trunk: Lib/test/test_descr.py Objects/abstract.c Message-ID: <20100605003251.2A9BCEECF3@mail.python.org> Author: benjamin.peterson Date: Sat Jun 5 02:32:50 2010 New Revision: 81706 Log: properly lookup the __format__ special method Modified: python/trunk/Lib/test/test_descr.py python/trunk/Objects/abstract.c Modified: python/trunk/Lib/test/test_descr.py ============================================================================== --- python/trunk/Lib/test/test_descr.py (original) +++ python/trunk/Lib/test/test_descr.py Sat Jun 5 02:32:50 2010 @@ -1697,6 +1697,8 @@ def some_number(self_, key): self.assertEqual(key, "hi") return 4 + def format_impl(self, spec): + return "hello" # It would be nice to have every special method tested here, but I'm # only listing the ones I can remember outside of typeobject.c, since it @@ -1715,6 +1717,7 @@ ("__enter__", run_context, iden, set(), {"__exit__" : swallow}), ("__exit__", run_context, swallow, set(), {"__enter__" : iden}), ("__complex__", complex, complex_num, set(), {}), + ("__format__", format, format_impl, set(), {}), ] class Checker(object): Modified: python/trunk/Objects/abstract.c ============================================================================== --- python/trunk/Objects/abstract.c (original) +++ python/trunk/Objects/abstract.c Sat Jun 5 02:32:50 2010 @@ -723,7 +723,6 @@ PyObject * PyObject_Format(PyObject* obj, PyObject *format_spec) { - static PyObject * str__format__ = NULL; PyObject *empty = NULL; PyObject *result = NULL; #ifdef Py_USING_UNICODE @@ -731,14 +730,6 @@ int result_is_unicode; #endif - /* Initialize cached value */ - if (str__format__ == NULL) { - /* Initialize static variable needed by _PyType_Lookup */ - str__format__ = PyString_InternFromString("__format__"); - if (str__format__ == NULL) - goto done; - } - /* If no format_spec is provided, use an empty string */ if (format_spec == NULL) { empty = PyString_FromStringAndSize(NULL, 0); @@ -769,8 +760,7 @@ /* Check for a __format__ method and call it. */ if (PyInstance_Check(obj)) { /* We're an instance of a classic class */ - PyObject *bound_method = PyObject_GetAttr(obj, - str__format__); + PyObject *bound_method = PyObject_GetAttrString(obj, "__format__"); if (bound_method != NULL) { result = PyObject_CallFunctionObjArgs(bound_method, format_spec, @@ -820,8 +810,7 @@ } /* Then call str.__format__ on that result */ - format_method = PyObject_GetAttr(self_as_str, - str__format__); + format_method = PyObject_GetAttrString(self_as_str, "__format__"); if (format_method == NULL) { goto done1; } @@ -837,20 +826,21 @@ } else { /* Not an instance of a classic class, use the code from py3k */ + static PyObject *format_cache; /* Find the (unbound!) __format__ method (a borrowed reference) */ - PyObject *method = _PyType_Lookup(Py_TYPE(obj), - str__format__); + PyObject *method = _PyObject_LookupSpecial(obj, "__format__", + &format_cache); if (method == NULL) { - PyErr_Format(PyExc_TypeError, - "Type %.100s doesn't define __format__", - Py_TYPE(obj)->tp_name); + if (!PyErr_Occurred()) + PyErr_Format(PyExc_TypeError, + "Type %.100s doesn't define __format__", + Py_TYPE(obj)->tp_name); goto done; } - /* And call it, binding it to the value */ - result = PyObject_CallFunctionObjArgs(method, obj, - format_spec, NULL); + /* And call it. */ + result = PyObject_CallFunctionObjArgs(method, format_spec, NULL); } if (result == NULL) From python-checkins at python.org Sat Jun 5 02:38:22 2010 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 5 Jun 2010 02:38:22 +0200 (CEST) Subject: [Python-checkins] r81707 - python/trunk/Objects/abstract.c Message-ID: <20100605003822.EF84AEECF3@mail.python.org> Author: benjamin.peterson Date: Sat Jun 5 02:38:22 2010 New Revision: 81707 Log: remove PyType_Ready call; float should be initialized in interpreter startup Modified: python/trunk/Objects/abstract.c Modified: python/trunk/Objects/abstract.c ============================================================================== --- python/trunk/Objects/abstract.c (original) +++ python/trunk/Objects/abstract.c Sat Jun 5 02:38:22 2010 @@ -752,11 +752,6 @@ goto done; } - /* Make sure the type is initialized. float gets initialized late */ - if (Py_TYPE(obj)->tp_dict == NULL) - if (PyType_Ready(Py_TYPE(obj)) < 0) - goto done; - /* Check for a __format__ method and call it. */ if (PyInstance_Check(obj)) { /* We're an instance of a classic class */ @@ -826,7 +821,7 @@ } else { /* Not an instance of a classic class, use the code from py3k */ - static PyObject *format_cache; + static PyObject *format_cache = NULL; /* Find the (unbound!) __format__ method (a borrowed reference) */ From python-checkins at python.org Sat Jun 5 02:45:38 2010 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 5 Jun 2010 02:45:38 +0200 (CEST) Subject: [Python-checkins] r81708 - in python/branches/py3k: Lib/test/test_descr.py Objects/abstract.c Message-ID: <20100605004538.15428EED0C@mail.python.org> Author: benjamin.peterson Date: Sat Jun 5 02:45:37 2010 New Revision: 81708 Log: Merged revisions 81706-81707 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81706 | benjamin.peterson | 2010-06-04 19:32:50 -0500 (Fri, 04 Jun 2010) | 1 line properly lookup the __format__ special method ........ r81707 | benjamin.peterson | 2010-06-04 19:38:22 -0500 (Fri, 04 Jun 2010) | 1 line remove PyType_Ready call; float should be initialized in interpreter startup ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/test/test_descr.py python/branches/py3k/Objects/abstract.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 Sat Jun 5 02:45:37 2010 @@ -1557,6 +1557,8 @@ self.assertEqual(key, "hi") return 4 def swallow(*args): pass + def format_impl(self, spec): + return "hello" # It would be nice to have every special method tested here, but I'm # only listing the ones I can remember outside of typeobject.c, since it @@ -1575,6 +1577,7 @@ ("__enter__", run_context, iden, set(), {"__exit__" : swallow}), ("__exit__", run_context, swallow, set(), {"__enter__" : iden}), ("__complex__", complex, complex_num, set(), {}), + ("__format__", format, format_impl, set(), {}), ] class Checker(object): Modified: python/branches/py3k/Objects/abstract.c ============================================================================== --- python/branches/py3k/Objects/abstract.c (original) +++ python/branches/py3k/Objects/abstract.c Sat Jun 5 02:45:37 2010 @@ -693,48 +693,36 @@ PyObject * PyObject_Format(PyObject *obj, PyObject *format_spec) { - static PyObject * str__format__ = NULL; PyObject *meth; PyObject *empty = NULL; PyObject *result = NULL; - - /* Initialize cached value */ - if (str__format__ == NULL) { - /* Initialize static variable needed by _PyType_Lookup */ - str__format__ = PyUnicode_FromString("__format__"); - if (str__format__ == NULL) - goto done; - } + static PyObject *format_cache = NULL; /* If no format_spec is provided, use an empty string */ if (format_spec == NULL) { - empty = PyUnicode_FromUnicode(NULL, 0); - format_spec = empty; + empty = PyUnicode_FromUnicode(NULL, 0); + format_spec = empty; } - /* Make sure the type is initialized. float gets initialized late */ - if (Py_TYPE(obj)->tp_dict == NULL) - if (PyType_Ready(Py_TYPE(obj)) < 0) - goto done; - /* Find the (unbound!) __format__ method (a borrowed reference) */ - meth = _PyType_Lookup(Py_TYPE(obj), str__format__); + meth = _PyObject_LookupSpecial(obj, "__format__", &format_cache); if (meth == NULL) { - PyErr_Format(PyExc_TypeError, - "Type %.100s doesn't define __format__", - Py_TYPE(obj)->tp_name); + if (!PyErr_Occurred()) + PyErr_Format(PyExc_TypeError, + "Type %.100s doesn't define __format__", + Py_TYPE(obj)->tp_name); goto done; } - /* And call it, binding it to the value */ - result = PyObject_CallFunctionObjArgs(meth, obj, format_spec, NULL); + /* And call it. */ + result = PyObject_CallFunctionObjArgs(meth, format_spec, NULL); if (result && !PyUnicode_Check(result)) { - PyErr_SetString(PyExc_TypeError, - "__format__ method did not return string"); - Py_DECREF(result); - result = NULL; - goto done; + PyErr_SetString(PyExc_TypeError, + "__format__ method did not return string"); + Py_DECREF(result); + result = NULL; + goto done; } done: From python-checkins at python.org Sat Jun 5 02:56:46 2010 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 5 Jun 2010 02:56:46 +0200 (CEST) Subject: [Python-checkins] r81709 - python/trunk/Objects/typeobject.c Message-ID: <20100605005646.7D6E2EE9C1@mail.python.org> Author: benjamin.peterson Date: Sat Jun 5 02:56:46 2010 New Revision: 81709 Log: implement object.__format__ with PyObject_Format Modified: python/trunk/Objects/typeobject.c Modified: python/trunk/Objects/typeobject.c ============================================================================== --- python/trunk/Objects/typeobject.c (original) +++ python/trunk/Objects/typeobject.c Sat Jun 5 02:56:46 2010 @@ -3413,7 +3413,6 @@ PyObject *format_spec; PyObject *self_as_str = NULL; PyObject *result = NULL; - PyObject *format_meth = NULL; Py_ssize_t format_len; if (!PyArg_ParseTuple(args, "O:__format__", &format_spec)) @@ -3449,21 +3448,11 @@ goto done; */ } - - /* find the format function */ - format_meth = PyObject_GetAttrString(self_as_str, - "__format__"); - if (format_meth != NULL) { - /* and call it */ - result = PyObject_CallFunctionObjArgs(format_meth, - format_spec, - NULL); - } + return PyObject_Format(self_as_str, format_spec); } done: Py_XDECREF(self_as_str); - Py_XDECREF(format_meth); return result; } From python-checkins at python.org Sat Jun 5 03:00:10 2010 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 5 Jun 2010 03:00:10 +0200 (CEST) Subject: [Python-checkins] r81710 - python/trunk/Objects/typeobject.c Message-ID: <20100605010010.B832DEE9C1@mail.python.org> Author: benjamin.peterson Date: Sat Jun 5 03:00:10 2010 New Revision: 81710 Log: fix ref counting Modified: python/trunk/Objects/typeobject.c Modified: python/trunk/Objects/typeobject.c ============================================================================== --- python/trunk/Objects/typeobject.c (original) +++ python/trunk/Objects/typeobject.c Sat Jun 5 03:00:10 2010 @@ -3448,7 +3448,7 @@ goto done; */ } - return PyObject_Format(self_as_str, format_spec); + result = PyObject_Format(self_as_str, format_spec); } done: From python-checkins at python.org Sat Jun 5 03:03:25 2010 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 5 Jun 2010 03:03:25 +0200 (CEST) Subject: [Python-checkins] r81711 - in python/branches/py3k: Objects/typeobject.c Message-ID: <20100605010325.0FBB7EEDA1@mail.python.org> Author: benjamin.peterson Date: Sat Jun 5 03:03:24 2010 New Revision: 81711 Log: Merged revisions 81709-81710 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81709 | benjamin.peterson | 2010-06-04 19:56:46 -0500 (Fri, 04 Jun 2010) | 1 line implement object.__format__ with PyObject_Format ........ r81710 | benjamin.peterson | 2010-06-04 20:00:10 -0500 (Fri, 04 Jun 2010) | 1 line fix ref counting ........ Modified: python/branches/py3k/ (props changed) 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 Sat Jun 5 03:03:24 2010 @@ -3310,23 +3310,15 @@ PyObject *format_spec; PyObject *self_as_str = NULL; PyObject *result = NULL; - PyObject *format_meth = NULL; if (!PyArg_ParseTuple(args, "U:__format__", &format_spec)) return NULL; self_as_str = PyObject_Str(self); - if (self_as_str != NULL) { - /* find the format function */ - format_meth = PyObject_GetAttrString(self_as_str, "__format__"); - if (format_meth != NULL) { - /* and call it */ - result = PyObject_CallFunctionObjArgs(format_meth, format_spec, NULL); - } - } + if (self_as_str != NULL) + result = PyObject_Format(self_as_str, format_spec); Py_XDECREF(self_as_str); - Py_XDECREF(format_meth); return result; } From python-checkins at python.org Sat Jun 5 04:07:01 2010 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 5 Jun 2010 04:07:01 +0200 (CEST) Subject: [Python-checkins] r81712 - python/trunk/Objects/abstract.c Message-ID: <20100605020701.32B58EE9D5@mail.python.org> Author: benjamin.peterson Date: Sat Jun 5 04:07:01 2010 New Revision: 81712 Log: _PyObject_LookupSpecial returns a new reference Modified: python/trunk/Objects/abstract.c Modified: python/trunk/Objects/abstract.c ============================================================================== --- python/trunk/Objects/abstract.c (original) +++ python/trunk/Objects/abstract.c Sat Jun 5 04:07:01 2010 @@ -836,6 +836,7 @@ } /* And call it. */ result = PyObject_CallFunctionObjArgs(method, format_spec, NULL); + Py_DECREF(method); } if (result == NULL) From python-checkins at python.org Sat Jun 5 04:11:45 2010 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 5 Jun 2010 04:11:45 +0200 (CEST) Subject: [Python-checkins] r81713 - in python/branches/py3k: Objects/abstract.c Message-ID: <20100605021145.670C7EEDA8@mail.python.org> Author: benjamin.peterson Date: Sat Jun 5 04:11:45 2010 New Revision: 81713 Log: Merged revisions 81712 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81712 | benjamin.peterson | 2010-06-04 21:07:01 -0500 (Fri, 04 Jun 2010) | 1 line _PyObject_LookupSpecial returns a new reference ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Objects/abstract.c Modified: python/branches/py3k/Objects/abstract.c ============================================================================== --- python/branches/py3k/Objects/abstract.c (original) +++ python/branches/py3k/Objects/abstract.c Sat Jun 5 04:11:45 2010 @@ -716,6 +716,7 @@ /* And call it. */ result = PyObject_CallFunctionObjArgs(meth, format_spec, NULL); + Py_DECREF(meth); if (result && !PyUnicode_Check(result)) { PyErr_SetString(PyExc_TypeError, From python-checkins at python.org Sat Jun 5 09:45:11 2010 From: python-checkins at python.org (stefan.krah) Date: Sat, 5 Jun 2010 09:45:11 +0200 (CEST) Subject: [Python-checkins] r81714 - python/branches/py3k-cdecimal/Modules/cdecimal/cdecimal.c Message-ID: <20100605074511.43C68EED8B@mail.python.org> Author: stefan.krah Date: Sat Jun 5 09:45:11 2010 New Revision: 81714 Log: 1) Speed up threading: The speed penalty is now about 16%. The new default is to compile with thread local contexts enabled. 2) Make clamp a public context field. Allow both _clamp and clamp for backwards compatibility. 3) Add IEEEContext factory function for interchange format contexts. 4) context.copy() should not zero the status. 5) All sNaN comparisons raise InvalidOperation. 6) Module default context is initialized from DefaultContext on first access (compatibility with decimal.py). 7) Use DefaultContext for the Context() constructor. 8) format() uses the 'capitals' setting of the context as default. 9) Change order of Context.__repr__ to match decimal.py. 10) Use PyUnicode_CompareWithASCIIString. Modified: python/branches/py3k-cdecimal/Modules/cdecimal/cdecimal.c Modified: python/branches/py3k-cdecimal/Modules/cdecimal/cdecimal.c ============================================================================== --- python/branches/py3k-cdecimal/Modules/cdecimal/cdecimal.c (original) +++ python/branches/py3k-cdecimal/Modules/cdecimal/cdecimal.c Sat Jun 5 09:45:11 2010 @@ -32,7 +32,6 @@ #define Dec_INCREF_TRUE (Py_INCREF(Py_True), Py_True) #define Dec_INCREF_FALSE (Py_INCREF(Py_False), Py_False) -#define Dec_INCREF_NONE (Py_INCREF(Py_None), Py_None) typedef struct { @@ -72,15 +71,23 @@ #define SdFlagAddr(v) (((PyDecSignalDictObject *)v)->flags) #define SdFlags(v) (*((PyDecSignalDictObject *)v)->flags) #define CtxAddr(v) (&((PyDecContextObject *)v)->ctx) +#define CtxCaps(v) (((PyDecContextObject *)v)->capitals) +#ifdef WITHOUT_THREADS /* Default module context */ static PyObject *module_context = NULL; -/* Basic and extended contexts */ -static PyObject *basic_context = NULL; -static PyObject *ext_context = NULL; -/* Thread local objects */ -static PyObject *tls = NULL; +#else +/* Key for thread state dictionary */ +static PyObject *tls_context_key = NULL; +#endif + +/* Template for creating new thread contexts, calling Context() without + * arguments and initializing the module_context on first access. */ +static PyObject *default_context_template = NULL; +/* Basic and extended context templates */ +static PyObject *basic_context_template = NULL; +static PyObject *extended_context_template = NULL; typedef struct { @@ -696,7 +703,7 @@ static PyObject * context_getcapitals(PyObject *self, void *closure UNUSED) { - return Py_BuildValue("i", ((PyDecContextObject *)self)->capitals); + return Py_BuildValue("i", CtxCaps(self)); } static PyObject * @@ -870,7 +877,7 @@ return -1; } - ((PyDecContextObject *)self)->capitals = (int)x; + CtxCaps(self) = (int)x; return 0; } @@ -1040,54 +1047,59 @@ static PyObject * context_getattr(PyObject *self, PyObject *name) { - PyObject *retval, *s; + PyObject *retval; - if ((s = PyUnicode_AsASCIIString(name)) == NULL) { + if (!PyUnicode_Check(name)) { + PyErr_Format(PyExc_TypeError, + "attribute name must be string, not '%.200s'", + name->ob_type->tp_name); return NULL; } - if (strcmp(PyBytes_AS_STRING(s), "traps") == 0) { + if (PyUnicode_CompareWithASCIIString(name, "traps") == 0) { retval = ((PyDecContextObject *)self)->traps; Py_INCREF(retval); + return retval; } - else if (strcmp(PyBytes_AS_STRING(s), "flags") == 0) { + else if (PyUnicode_CompareWithASCIIString(name, "flags") == 0) { retval = ((PyDecContextObject *)self)->flags; Py_INCREF(retval); + return retval; } else { - retval = PyObject_GenericGetAttr(self, name); + return PyObject_GenericGetAttr(self, name); } - - Py_DECREF(s); - return retval; } static int context_setattr(PyObject *self, PyObject *name, PyObject *value) { - PyObject *s; - int retval = 0; - - if ((s = PyUnicode_AsASCIIString(name)) == NULL) { + if (!PyUnicode_Check(name)) { + PyErr_Format(PyExc_TypeError, + "attribute name must be string, not '%.200s'", + name->ob_type->tp_name); return -1; } - if (strcmp(PyBytes_AS_STRING(s), "traps") == 0) { - if (context_settraps_dict(self, value) < 0) { - retval = -1; + if (PyUnicode_CompareWithASCIIString(name, "traps") == 0) { + if (value == NULL) { + PyErr_SetString(PyExc_ValueError, + "traps cannot be deleted"); + return -1; } + return context_settraps_dict(self, value); } - else if (strcmp(PyBytes_AS_STRING(s), "flags") == 0) { - if (context_setstatus_dict(self, value) < 0) { - retval = -1; + else if (PyUnicode_CompareWithASCIIString(name, "flags") == 0) { + if (value == NULL) { + PyErr_SetString(PyExc_ValueError, + "flags cannot be deleted"); + return -1; } + return context_setstatus_dict(self, value); } else { - retval = PyObject_GenericSetAttr(self, name, value); + return PyObject_GenericSetAttr(self, name, value); } - - Py_DECREF(s); - return retval; } static PyObject * @@ -1150,28 +1162,44 @@ PyObject_Del(self); } +#ifdef CONFIG_64 + #define DEC_DFLT_EMAX 999999999 + #define DEC_DFLT_EMIN -999999999 +#else + #define DEC_DFLT_EMAX MPD_MAX_EMAX + #define DEC_DFLT_EMIN MPD_MIN_EMIN +#endif + +static mpd_context_t dflt_ctx = { + 28, DEC_DFLT_EMAX, DEC_DFLT_EMIN, + MPD_Invalid_operation|MPD_Division_by_zero|MPD_Overflow, + 0, 0, MPD_ROUND_HALF_EVEN, 0, 1 +}; + static int context_init(PyObject *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = { - "prec", "Emin", "Emax", "rounding", "capitals", - "traps", "flags", "_clamp", "_allcr", NULL + "prec", "rounding", "Emin", "Emax", "capitals", "clamp", + "flags", "traps", "_allcr", NULL }; PyObject *traps = NULL; PyObject *status = NULL; - mpd_context_t *ctx, t; + mpd_context_t *ctx, t=dflt_ctx; int capitals = 1; assert(PyTuple_Check(args)); ctx = CtxAddr(self); - mpd_defaultcontext(&t); + if (default_context_template) { + t = *CtxAddr(default_context_template); + } if (!PyArg_ParseTupleAndKeywords( args, kwds, - "|"CONV_mpd_ssize_t CONV_mpd_ssize_t CONV_mpd_ssize_t"iiOOii", - kwlist, - &t.prec, &t.emin, &t.emax, &t.round, &capitals, - &traps, &status, &t.clamp, &t.allcr + "|" CONV_mpd_ssize_t "i" CONV_mpd_ssize_t CONV_mpd_ssize_t "ii" + "OOi", kwlist, + &t.prec, &t.round, &t.emin, &t.emax, &capitals, &t.clamp, + &status, &traps, &t.allcr )) { return -1; } @@ -1193,7 +1221,7 @@ PyErr_SetString(PyExc_ValueError, "invalid value for capitals"); return -1; } - ((PyDecContextObject *)self)->capitals = capitals; + CtxCaps(self) = capitals; if (traps != NULL) { if (PyLong_Check(traps)) { @@ -1221,7 +1249,7 @@ return 0; } -#define FD_CTX_LEN 640 +#define FD_CTX_LEN 400 static PyObject * context_repr(PyDecContextObject *self) { @@ -1235,32 +1263,97 @@ cp = s; mem = FD_CTX_LEN; n = snprintf(cp, mem, - "Context(prec=%"PRI_mpd_ssize_t", Emin=%"PRI_mpd_ssize_t"" - ", Emax=%"PRI_mpd_ssize_t", rounding=%s, capitals=%d, traps=", - ctx->prec, ctx->emin, ctx->emax, mpd_round_string[ctx->round], - self->capitals); - if (n < 0 || n >= mem) return NULL; + "Context(prec=%"PRI_mpd_ssize_t", rounding=%s, " + "Emin=%"PRI_mpd_ssize_t", Emax=%"PRI_mpd_ssize_t", " + "capitals=%d, clamp=%d, flags=", + ctx->prec, mpd_round_string[ctx->round], + ctx->emin, ctx->emax, + self->capitals, ctx->clamp); + if (n < 0 || n >= mem) goto error; cp += n; mem -= n; - n = mpd_lsnprint_signals(cp, mem, ctx->traps, dec_signal_string); - if (n < 0 || n >= mem) return NULL; + n = mpd_lsnprint_signals(cp, mem, ctx->status, dec_signal_string); + if (n < 0 || n >= mem) goto error; cp += n; mem -= n; - n = snprintf(cp, mem, ", flags="); - if (n < 0 || n >= mem) return NULL; + n = snprintf(cp, mem, ", traps="); + if (n < 0 || n >= mem) goto error; cp += n; mem -= n; - n = mpd_lsnprint_signals(cp, mem, ctx->status, dec_signal_string); - if (n < 0 || n >= mem) return NULL; + n = mpd_lsnprint_signals(cp, mem, ctx->traps, dec_signal_string); + if (n < 0 || n >= mem) goto error; cp += n; mem -= n; n = snprintf(cp, mem, ")"); - if (n < 0 || n >= mem) return NULL; + if (n < 0 || n >= mem) goto error; return PyUnicode_FromString(s); + +error: + PyErr_SetString(PyExc_RuntimeError, "internal error in context_repr"); + return NULL; +} + +static void +init_basic_context(PyObject *v) +{ + mpd_context_t ctx = dflt_ctx; + + ctx.prec = 9; + ctx.traps |= (MPD_Underflow|MPD_Clamped); + ctx.round = MPD_ROUND_HALF_UP; + + *CtxAddr(v) = ctx; + CtxCaps(v) = 1; +} + +static void +init_extended_context(PyObject *v) +{ + mpd_context_t ctx = dflt_ctx; + + ctx.prec = 9; + ctx.traps = 0; + + *CtxAddr(v) = ctx; + CtxCaps(v) = 1; +} + +/* Factory function for creating IEEE interchange format contexts */ +static PyObject * +ieee_context(PyObject *dummy UNUSED, PyObject *v) +{ + PyObject *ctxobj; + mpd_ssize_t bits; + mpd_context_t ctx; + + bits = PyLong_AsMpdSsize(v); + if (PyErr_Occurred()) { + return NULL; + } + if (bits <= 0 || bits > INT_MAX) { + goto error; + } + if (mpd_ieee_context(&ctx, (int)bits) < 0) { + goto error; + } + + ctxobj = PyObject_CallObject((PyObject *)&PyDecContext_Type, NULL); + if (ctxobj == NULL) { + return NULL; + } + *CtxAddr(ctxobj) = ctx; + + return ctxobj; + +error: + PyErr_Format(PyExc_ValueError, + "argument must be a multiple of 32, with a maximum of %d", + MPD_IEEE_CONTEXT_MAX_BITS + ); + return NULL; } -/* New copy with all settings except the status */ static PyObject * context_copy(PyObject *self) { @@ -1275,10 +1368,8 @@ ctx = CtxAddr(newob); *ctx = *CtxAddr(self); - ctx->status = 0; ctx->newtrap = 0; - ((PyDecContextObject *)newob)->capitals = - ((PyDecContextObject *)self)->capitals; + CtxCaps(newob) = CtxCaps(self); return newob; } @@ -1289,11 +1380,10 @@ mpd_context_t *ctx = CtxAddr(self); return Py_BuildValue( - "O("CONV_mpd_ssize_t CONV_mpd_ssize_t CONV_mpd_ssize_t \ - "iiiiii)", - Py_TYPE(self), ctx->prec, ctx->emin, ctx->emax, - ctx->round, ((PyDecContextObject *)self)->capitals, - ctx->traps, ctx->status, ctx->clamp, ctx->allcr + "O(" CONV_mpd_ssize_t "i" CONV_mpd_ssize_t CONV_mpd_ssize_t + "iiiii)", + Py_TYPE(self), ctx->prec, ctx->round, ctx->emin, ctx->emax, + CtxCaps(self), ctx->clamp, ctx->status, ctx->traps, ctx->allcr ); } @@ -1305,6 +1395,7 @@ { "Emin", (getter)context_getemin, (setter)context_setemin, NULL, NULL}, { "rounding", (getter)context_getround, (setter)context_setround, NULL, NULL}, { "capitals", (getter)context_getcapitals, (setter)context_setcapitals, NULL, NULL}, + { "clamp", (getter)context_getclamp, (setter)context_setclamp, NULL, NULL}, { "_clamp", (getter)context_getclamp, (setter)context_setclamp, NULL, NULL}, { "_allcr", (getter)context_getallcr, (setter)context_setallcr, NULL, NULL}, { "_traps", (getter)context_gettraps, (setter)context_settraps, NULL, NULL}, @@ -1332,214 +1423,254 @@ /* Global, thread local and temporary contexts */ /******************************************************************************/ +#ifdef WITHOUT_THREADS +/* Return borrowed reference to the current context. When compiled + * without threads, this is always the module context. */ +static int module_context_set = 0; +static PyObject * +current_context(void) +{ + /* In decimal.py, the module context is automatically initialized + * from the DefaultContext when it is first accessed. This + * complicates the code and has a speed penalty of 1-2%. */ + if (module_context_set) { + return module_context; + } -#ifndef USE_THREAD_LOCAL_STORAGE /* Recommended: No TLS */ -/* Internal: return borrowed reference to default context object */ -static inline PyObject * -dflt_ctx(void) -{ + *CtxAddr(module_context) = *CtxAddr(default_context_template); + module_context_set = 1; return module_context; } -/* Internal: set default context, preserve old reference */ -static inline PyObject * -set_dflt_ctx(PyObject *obj) -{ - module_context = obj; - return Py_None; -} +/* ctxobj := borrowed reference to the current context */ +#define CURRENT_CONTEXT(ctxobj) \ + ctxobj = current_context() -/* Internal: return convenience pointer to raw default context */ -static inline mpd_context_t * -mpd_ctx(void) -{ - return CtxAddr(module_context); -} +/* ctx := pointer to the mpd_context_t struct of the current context */ +#define CURRENT_CONTEXT_ADDR(ctx) \ + ctx = CtxAddr(current_context()) -/* Return context object, increment reference */ +/* Return current context, increment reference */ static PyObject * -PyDec_GetDefaultContext(void) +PyDec_GetCurrentContext(void) { - Py_INCREF(module_context); - return module_context; + PyObject *ctxobj; + + CURRENT_CONTEXT(ctxobj); + + Py_INCREF(ctxobj); + return ctxobj; } -/* Set the module context to a new context object */ +/* Set the module context to a new context, decrement old reference */ static PyObject * -PyDec_SetDefaultContext(PyObject *self UNUSED, PyObject *obj) +PyDec_SetCurrentContext(PyObject *self UNUSED, PyObject *v) { - CONTEXT_CHECK(obj); + CONTEXT_CHECK(v); + + /* If the new context is one of the templates, make a copy. + * This is the current behavior of decimal.py. */ + if (v == default_context_template || + v == basic_context_template || + v == extended_context_template) { + if ((v = context_copy(v)) == NULL) { + return NULL; + } + } + else { + Py_INCREF(v); + } Py_DECREF(module_context); - module_context = obj; - Py_INCREF(module_context); + module_context = v; + module_context_set = 1; Py_RETURN_NONE; } #else /* - * Thread local storage for the context is not a good idea. All functions - * that map Python's arithmetic operators to mpdecimal functions have to - * look up the default context for each and every operation. This is more - * than twice as slow as using the module context. - * - * This section is here for compatibility with decimal.py, but compiling - * with USE_THREAD_LOCAL_STORAGE is strongly discouraged. - * - * If you need threads in your application, simply create a context for - * each thread and only use the functions that accept a context parameter. + * Thread local storage currently has a speed penalty of about 16%. + * All functions that map Python's arithmetic operators to mpdecimal + * functions have to look up the current context for each and every + * operation. */ -/* Internal: return borrowed reference to thread local default context object */ +/* Return borrowed reference to thread local context. */ static PyObject * -dflt_ctx(void) +current_context(void) { - PyObject *obj = NULL; + PyObject *dict = NULL; + PyObject *tl_context = NULL; - if ((obj = PyObject_GetAttrString(tls, "default_context")) != NULL) { - /* We already have a thread local context and return a - * borrowed reference. */ - assert(PyDecContext_Check(obj)); - Py_DECREF(obj); - return obj; + dict = PyThreadState_GetDict(); + if (dict == NULL) { + PyErr_SetString(PyExc_RuntimeError, "cannot get thread state"); + return NULL; + } + + tl_context = PyDict_GetItem(dict, tls_context_key); + if (tl_context != NULL) { + /* We already have a thread local context and + * return a borrowed reference. */ + CONTEXT_CHECK(tl_context); + return tl_context; } - /* Otherwise, set the default context attribute */ - PyErr_Clear(); - if ((obj = (PyObject *)context_copy(module_context)) == NULL) { + /* Otherwise, set up a new thread local context. */ + tl_context = (PyObject *)context_copy(default_context_template); + if (tl_context == NULL) { return NULL; } - if (PyObject_SetAttrString(tls, "default_context", obj) == -1) { - Py_DECREF(obj); + if (PyDict_SetItem(dict, tls_context_key, tl_context) < 0) { + Py_DECREF(tl_context); return NULL; } - Py_DECREF(obj); + Py_DECREF(tl_context); /* refcount is 1 */ - return obj; + return tl_context; } -/* Internal: set thread local default context, preserve old reference */ -static PyObject * -set_dflt_ctx(PyObject *obj) -{ - /* Preserve a reference to the previous context. */ - Py_INCREF(dflt_ctx()); - /* This decrements the refcount of a previous context. */ - if (PyObject_SetAttrString(tls, "default_context", obj) == -1) { - return NULL; - } - return Py_None; -} - -/* Internal: return convenience pointer to thread local raw context */ -static mpd_context_t * -mpd_ctx(void) -{ - PyObject *obj; +/* ctxobj := borrowed reference to the current context */ +#define CURRENT_CONTEXT(ctxobj) \ + if ((ctxobj = current_context()) == NULL) { \ + return NULL; \ + } - if ((obj = dflt_ctx()) == NULL) { - /* XXX The alternative is to add even more error handling code - * to the arithmetic functions. This would punish users who do - * not use TLS. */ - mpd_err_fatal("Retrieving thread local context failed."); - /* Not reached */ - } - return CtxAddr(obj); +/* ctx := pointer to the mpd_context_t struct of the current context */ +#define CURRENT_CONTEXT_ADDR(ctx) { \ + PyObject *_c_t_x_o_b_j = current_context(); \ + if (_c_t_x_o_b_j == NULL) { \ + return NULL; \ + } \ + ctx = CtxAddr(_c_t_x_o_b_j); \ } -/* Return thread local default context object with incremented refcount */ +/* Return current context, increment reference */ static PyObject * -PyDec_GetDefaultContext(void) +PyDec_GetCurrentContext(void) { PyObject *obj; - if ((obj = dflt_ctx()) == NULL) { + if ((obj = current_context()) == NULL) { return NULL; } + Py_INCREF(obj); return obj; } -/* Set thread local context object */ +/* Set the thread local context to a new context, decrement old reference */ static PyObject * -PyDec_SetDefaultContext(PyObject *self UNUSED, PyObject *obj) +PyDec_SetCurrentContext(PyObject *self UNUSED, PyObject *v) { - CONTEXT_CHECK(obj); + PyObject *dict; + + CONTEXT_CHECK(v); + + dict = PyThreadState_GetDict(); + if (dict == NULL) { + PyErr_SetString(PyExc_RuntimeError, "cannot get thread state"); + return NULL; + } + + /* If the new context is one of the templates, make a copy. + * This is the current behavior of decimal.py. */ + if (v == default_context_template || + v == basic_context_template || + v == extended_context_template) { + if ((v = context_copy(v)) == NULL) { + return NULL; + } + } + else { + Py_INCREF(v); + } - /* This clears one reference to a previous context. */ - if (PyObject_SetAttrString(tls, "default_context", obj) == -1) { + if (PyDict_SetItem(dict, tls_context_key, v) < 0) { return NULL; } + Py_DECREF(v); Py_RETURN_NONE; } #endif - -/* For the "with" statement: return a context manager object */ +/* Context manager object for the 'with' statement. The manager + * owns one reference to the global (outer) context and one + * to the local (inner) context. */ static PyObject * -ctxmanager_new(PyObject *self UNUSED, PyObject *args) +ctxmanager_new(PyTypeObject *type UNUSED, PyObject *args) { - PyDecContextManagerObject *ctx_mgr; - PyObject *src; - - src = dflt_ctx(); - if (!PyArg_ParseTuple(args, "|O", &src)) { - return NULL; - } - CONTEXT_CHECK_VA(src); + PyDecContextManagerObject *self; + PyObject *local; + PyObject *global; - ctx_mgr = PyObject_New(PyDecContextManagerObject, - &PyDecContextManager_Type); - if (ctx_mgr == NULL) { + CURRENT_CONTEXT(global); + local = global; + if (!PyArg_ParseTuple(args, "|O", &local)) { return NULL; } + CONTEXT_CHECK_VA(local); - ctx_mgr->local = context_copy(src); - if (ctx_mgr->local == NULL) { - Py_DECREF(ctx_mgr); + self = PyObject_New(PyDecContextManagerObject, + &PyDecContextManager_Type); + if (self == NULL) { return NULL; } - ctx_mgr->global = dflt_ctx(); - if (ctx_mgr->global == NULL) { - Py_DECREF(ctx_mgr->local); - Py_DECREF(ctx_mgr); + self->local = context_copy(local); + if (self->local == NULL) { + Py_DECREF(self); return NULL; } + self->global = global; + Py_INCREF(self->global); - return (PyObject *)ctx_mgr; + return (PyObject *)self; } static void -ctxmanager_dealloc(PyDecContextObject *self) +ctxmanager_dealloc(PyDecContextManagerObject *self) { + Py_DECREF(self->local); + Py_DECREF(self->global); PyObject_Del(self); } static PyObject * ctxmanager_set_local(PyDecContextManagerObject *self, PyObject *args UNUSED) { - if (set_dflt_ctx(self->local) == NULL) { + PyObject *ret; + + ret = PyDec_SetCurrentContext(NULL, self->local); + if (ret == NULL) { return NULL; } - return (PyObject *)self->local; + Py_DECREF(ret); + + Py_INCREF(self->local); + return self->local; } static PyObject * -ctxmanager_restore_default(PyDecContextManagerObject *self, +ctxmanager_restore_global(PyDecContextManagerObject *self, PyObject *args UNUSED) { - if (set_dflt_ctx(self->global) == NULL) { + PyObject *ret; + + ret = PyDec_SetCurrentContext(NULL, self->global); + if (ret == NULL) { return NULL; } - return Dec_INCREF_FALSE; + Py_DECREF(ret); + + Py_RETURN_NONE; } static PyMethodDef ctxmanager_methods[] = { {"__enter__", (PyCFunction)ctxmanager_set_local, METH_NOARGS, NULL}, - {"__exit__", (PyCFunction)ctxmanager_restore_default, METH_VARARGS, NULL}, + {"__exit__", (PyCFunction)ctxmanager_restore_global, METH_VARARGS, NULL}, {NULL, NULL} }; @@ -1841,9 +1972,8 @@ /* Caller guarantees types. */ static PyObject * -_PyDec_FromTuple_Max(PyObject *v, mpd_context_t *ctx) +string_from_tuple(PyObject *v) { - PyObject *result; PyObject *tmp, *dtuple; char *decstring, *cp; char sign_special[6]; @@ -1875,27 +2005,21 @@ tmp = PyTuple_GET_ITEM(v, 2); if (PyUnicode_Check(tmp)) { - tmp = PyUnicode_AsASCIIString(tmp); - if (tmp == NULL) { - return NULL; - } - if (strcmp(PyBytes_AS_STRING(tmp), "F") == 0) { + if (PyUnicode_CompareWithASCIIString(tmp, "F") == 0) { strcat(sign_special, "Inf"); } - else if (strcmp(PyBytes_AS_STRING(tmp), "n") == 0) { + else if (PyUnicode_CompareWithASCIIString(tmp, "n") == 0) { strcat(sign_special, "NaN"); } - else if (strcmp(PyBytes_AS_STRING(tmp), "N") == 0) { + else if (PyUnicode_CompareWithASCIIString(tmp, "N") == 0) { strcat(sign_special, "sNaN"); } else { - Py_DECREF(tmp); PyErr_SetString(PyExc_ValueError, "string argument in the third position " "must be 'F', 'n' or 'N'"); return NULL; } - Py_DECREF(tmp); } else { exp = PyLong_AsMpdSsize(tmp); @@ -1956,12 +2080,37 @@ tmp = PyUnicode_FromString(decstring); PyMem_Free(decstring); - if (tmp == NULL) { + + return tmp; +} + +static PyObject * +_PyDec_FromTuple_Max(PyObject *v, mpd_context_t *ctx) +{ + PyObject *result; + PyObject *s; + + s = string_from_tuple(v); + if (s == NULL) { return NULL; } + result = _PyDec_FromUnicode_Max(s, ctx); + Py_DECREF(s); + return result; +} - result = _PyDec_FromUnicode_Max(tmp, ctx); - Py_DECREF(tmp); +static PyObject * +_PyDec_FromTuple(PyObject *v, mpd_context_t *ctx) +{ + PyObject *result; + PyObject *s; + + s = string_from_tuple(v); + if (s == NULL) { + return NULL; + } + result = _PyDec_FromUnicode(s, ctx); + Py_DECREF(s); return result; } @@ -1997,7 +2146,7 @@ PyObject *ctxobj; mpd_context_t *ctx; - ctxobj = dflt_ctx(); + CURRENT_CONTEXT(ctxobj); if (!PyArg_ParseTuple(args, "|O", &ctxobj)) { return NULL; } @@ -2137,14 +2286,15 @@ static PyObject * dec_new(PyTypeObject *type, PyObject *args, PyObject *kwds UNUSED) { - PyObject *v = NULL, *ctxobj = NULL; + PyObject *v = NULL; + PyObject *ctxobj; mpd_context_t *ctx; if (type != &PyDec_Type) { return dec_subtype_new(type, args, kwds); } - ctxobj = dflt_ctx(); + CURRENT_CONTEXT(ctxobj); if (!PyArg_ParseTuple(args, "|OO", &v, &ctxobj)) { return NULL; } @@ -2232,12 +2382,7 @@ return _PyDec_FromLong(v, ctx); } else if (PyTuple_Check(v)) { - PyObject *tmp; - tmp = _PyDec_FromTuple_Max(v, ctx); - if (tmp == NULL) return NULL; - v = dec_apply(tmp, ctx); - Py_DECREF(tmp); - return v; + return _PyDec_FromTuple(v, ctx); } else { PyErr_Format(PyExc_TypeError, "conversion from %s to Decimal is" @@ -2256,11 +2401,12 @@ int sign; mpd_t *d1, *d2; uint32_t status = 0; - mpd_context_t maxctx; + mpd_context_t *ctx, maxctx; + CURRENT_CONTEXT_ADDR(ctx); if (PyLong_Check(v)) { - return _PyDec_FromLong_Max(v, mpd_ctx()); + return _PyDec_FromLong_Max(v, ctx); } x = PyFloat_AsDouble(v); @@ -2329,7 +2475,7 @@ mpd_qset_uint(d1, 5, &maxctx, &status); mpd_qset_ssize(d2, k, &maxctx, &status); mpd_qpow(d1, d1, d2, &maxctx, &status); - if (dec_addstatus(mpd_ctx(), status)) { + if (dec_addstatus(ctx, status)) { mpd_del(d1); mpd_del(d2); Py_DECREF(n_d); @@ -2350,7 +2496,7 @@ mpd_qmul(DecAddr(result), DecAddr(result), d1, &maxctx, &status); mpd_del(d1); mpd_del(d2); - if (dec_addstatus(mpd_ctx(), status)) { + if (dec_addstatus(ctx, status)) { Py_DECREF(result); return NULL; } @@ -2466,7 +2612,10 @@ static PyObject * PyLong_FromDec(PyDecObject *self) { - return _PyInt_FromDec(self, mpd_ctx(), MPD_ROUND_DOWN); + mpd_context_t *ctx; + + CURRENT_CONTEXT_ADDR(ctx); + return _PyInt_FromDec(self, ctx, MPD_ROUND_DOWN); } /* Caller guarantees type */ @@ -2480,7 +2629,10 @@ static PyObject * PyDec_Trunc(PyObject *self, PyObject *dummy UNUSED) { - return _PyInt_FromDec((PyDecObject *)self, mpd_ctx(), MPD_ROUND_DOWN); + mpd_context_t *ctx; + + CURRENT_CONTEXT_ADDR(ctx); + return _PyInt_FromDec((PyDecObject *)self, ctx, MPD_ROUND_DOWN); } static PyObject * @@ -2488,19 +2640,19 @@ { static char *kwlist[] = {"rounding", "context", NULL}; PyDecObject *result; - PyObject *dctx; + PyObject *ctxobj; int round = -1; mpd_context_t *ctx, workctx; uint32_t status = 0; assert(PyTuple_Check(args)); - dctx = dflt_ctx(); + CURRENT_CONTEXT(ctxobj); if (!PyArg_ParseTupleAndKeywords(args, kwds, "|iO", - kwlist, &round, &dctx)) { + kwlist, &round, &ctxobj)) { return NULL; } - if (!PyDecContext_Check(dctx)) { + if (!PyDecContext_Check(ctxobj)) { PyErr_SetString(PyExc_TypeError, "optional second arg must be a context"); return NULL; @@ -2509,7 +2661,7 @@ return NULL; } - ctx = CtxAddr(dctx); + ctx = CtxAddr(ctxobj); workctx = *ctx; if (round >= 0) { workctx.round = round; @@ -2529,19 +2681,19 @@ { static char *kwlist[] = {"rounding", "context", NULL}; PyDecObject *result; - PyObject *dctx; + PyObject *ctxobj; int round = -1; mpd_context_t *ctx, workctx; uint32_t status = 0; assert(PyTuple_Check(args)); - dctx = dflt_ctx(); + CURRENT_CONTEXT(ctxobj); if (!PyArg_ParseTupleAndKeywords(args, kwds, "|iO", - kwlist, &round, &dctx)) { + kwlist, &round, &ctxobj)) { return NULL; } - if (!PyDecContext_Check(dctx)) { + if (!PyDecContext_Check(ctxobj)) { PyErr_SetString(PyExc_TypeError, "optional second arg must be a context"); return NULL; @@ -2550,7 +2702,7 @@ return NULL; } - ctx = CtxAddr(dctx); + ctx = CtxAddr(ctxobj); workctx = *ctx; if (round >= 0) { workctx.round = round; @@ -2664,8 +2816,8 @@ PyObject *s, *c; char *res; - c = dflt_ctx(); - res = mpd_to_sci(self->dec, ((PyDecContextObject *)c)->capitals); + CURRENT_CONTEXT(c); + res = mpd_to_sci(self->dec, CtxCaps(c)); if (res == NULL) { PyErr_NoMemory(); return NULL; @@ -2689,8 +2841,8 @@ char *cp; size_t declen; - c = dflt_ctx(); - cp = mpd_to_sci(self->dec, ((PyDecContextObject *)c)->capitals); + CURRENT_CONTEXT(c); + cp = mpd_to_sci(self->dec, CtxCaps(c)); if (cp == NULL) { PyErr_NoMemory(); return NULL; @@ -2742,12 +2894,12 @@ uint32_t status = 0; mpd_context_t *ctx; + + CURRENT_CONTEXT_ADDR(ctx); if (!PyArg_ParseTuple(args, "|O", &x)) { return NULL; } - ctx = mpd_ctx(); - if (x) { mpd_uint_t dq[1] = {1}; mpd_t q = {MPD_STATIC|MPD_CONST_DATA,0,1,1,1,dq}; @@ -2791,6 +2943,7 @@ PyObject *grouping = NULL; PyObject *fmtarg, *fmt; PyObject *tmp; + PyObject *ctxobj; mpd_spec_t spec; wchar_t buf[2]; char *decstring= NULL; @@ -2798,6 +2951,7 @@ size_t n; + CURRENT_CONTEXT(ctxobj); if (!PyArg_ParseTuple(args, "O|O", &fmtarg, &override)) { return NULL; } @@ -2816,7 +2970,8 @@ return NULL; } - if (!mpd_parse_fmt_str(&spec, PyBytes_AS_STRING(fmt))) { + if (!mpd_parse_fmt_str(&spec, PyBytes_AS_STRING(fmt), + CtxCaps(ctxobj))) { PyErr_SetString(PyExc_ValueError, "invalid format string"); goto finish; } @@ -2887,9 +3042,9 @@ } - decstring = mpd_qformat_spec(DecAddr(self), &spec, mpd_ctx(), &status); + decstring = mpd_qformat_spec(DecAddr(self), &spec, CtxAddr(ctxobj), &status); if (decstring == NULL) { - dec_addstatus(mpd_ctx(), status); + dec_addstatus(CtxAddr(ctxobj), status); goto finish; } result = PyUnicode_DecodeUTF8(decstring, strlen(decstring), NULL); @@ -2937,7 +3092,7 @@ PyObject *ctxobj; \ mpd_context_t *ctx; \ \ - ctxobj = dflt_ctx(); \ + CURRENT_CONTEXT(ctxobj); \ if (!PyArg_ParseTuple(args, "|O", &ctxobj)) { \ return NULL; \ } \ @@ -2959,11 +3114,11 @@ uint32_t status = 0; \ mpd_context_t *ctx; \ \ + CURRENT_CONTEXT_ADDR(ctx); \ if ((result = dec_alloc()) == NULL) { \ return NULL; \ } \ \ - ctx = mpd_ctx(); \ MPDFUNC(result->dec, a->dec, ctx, &status); \ if (dec_addstatus(ctx, status)) { \ Py_DECREF(result); \ @@ -2984,11 +3139,11 @@ uint32_t status = 0; \ mpd_context_t *ctx; \ \ + CURRENT_CONTEXT_ADDR(ctx); \ if ((result = dec_alloc()) == NULL) { \ return NULL; \ } \ \ - ctx = mpd_ctx(); \ MPDFUNC(result->dec, a->dec, ctx, &status); \ if (dec_addstatus(ctx, &status)) { \ Py_DECREF(result); \ @@ -3010,7 +3165,7 @@ uint32_t status = 0; \ mpd_context_t *ctx; \ \ - ctxobj = dflt_ctx(); \ + CURRENT_CONTEXT(ctxobj); \ if (!PyArg_ParseTuple(args, "|O", &ctxobj)) { \ return NULL; \ } \ @@ -3043,7 +3198,7 @@ uint32_t status = 0; \ mpd_context_t *ctx; \ \ - ctx = mpd_ctx(); \ + CURRENT_CONTEXT_ADDR(ctx); \ CONVERT_BINOP(v, w, &a, &b, ctx); \ \ if ((result = dec_alloc()) == NULL) { \ @@ -3075,7 +3230,7 @@ uint32_t status = 0; \ mpd_context_t *ctx; \ \ - ctxobj = dflt_ctx(); \ + CURRENT_CONTEXT(ctxobj); \ if (!PyArg_ParseTuple(args, "O|O", &w, &ctxobj)) { \ return NULL; \ } \ @@ -3113,7 +3268,7 @@ PyDecObject *result; \ mpd_context_t *ctx; \ \ - ctxobj = dflt_ctx(); \ + CURRENT_CONTEXT(ctxobj); \ if (!PyArg_ParseTuple(args, "O|O", &w, &ctxobj)) { \ return NULL; \ } \ @@ -3149,7 +3304,7 @@ uint32_t status = 0; \ mpd_context_t *ctx; \ \ - ctxobj = dflt_ctx(); \ + CURRENT_CONTEXT(ctxobj); \ if (!PyArg_ParseTuple(args, "OO|O", &w, &x, &ctxobj)) { \ return NULL; \ } \ @@ -3223,7 +3378,7 @@ uint32_t status = 0; mpd_context_t *ctx; - ctx = mpd_ctx(); + CURRENT_CONTEXT_ADDR(ctx); CONVERT_BINOP(v, w, &a, &b, ctx); if ((q = dec_alloc()) == NULL) { @@ -3258,7 +3413,7 @@ uint32_t status = 0; mpd_context_t *ctx; - ctx = mpd_ctx(); + CURRENT_CONTEXT_ADDR(ctx); CONVERT_BINOP(base, exp, &a, &b, ctx); if (mod != Py_None) { @@ -3350,13 +3505,15 @@ PyDecObject *a = (PyDecObject *) self; PyDecObject *result; uint32_t status = 0; + mpd_context_t *ctx; + CURRENT_CONTEXT_ADDR(ctx); if ((result = dec_alloc()) == NULL) { return NULL; } mpd_qcopy_abs(result->dec, a->dec, &status); - if (dec_addstatus(mpd_ctx(), status)) { + if (dec_addstatus(ctx, status)) { Py_DECREF(result); return NULL; } @@ -3370,13 +3527,15 @@ PyDecObject *a = (PyDecObject *) self; PyDecObject *result; uint32_t status = 0; + mpd_context_t *ctx; + CURRENT_CONTEXT_ADDR(ctx); if ((result = dec_alloc()) == NULL) { return NULL; } mpd_qcopy_negate(result->dec, a->dec, &status); - if (dec_addstatus(mpd_ctx(), status)) { + if (dec_addstatus(ctx, status)) { Py_DECREF(result); return NULL; } @@ -3398,7 +3557,7 @@ uint32_t status = 0; mpd_context_t *ctx; - ctx = mpd_ctx(); + CURRENT_CONTEXT_ADDR(ctx); CONVERT_BINOP_SET(v, w, &a, &b, ctx); if ((result = dec_alloc()) == NULL) { @@ -3434,7 +3593,7 @@ mpd_context_t *ctx; const char *cp; - ctxobj = dflt_ctx(); + CURRENT_CONTEXT(ctxobj); if (!PyArg_ParseTuple(args, "|O", &ctxobj)) { return NULL; } @@ -3469,7 +3628,7 @@ uint32_t status = 0; mpd_context_t *ctx; - ctxobj = dflt_ctx(); + CURRENT_CONTEXT(ctxobj); if (!PyArg_ParseTuple(args, "O|O", &w, &ctxobj)) { return NULL; } @@ -3516,7 +3675,7 @@ PyDecObject *a, *b; mpd_context_t *ctx; - ctxobj = dflt_ctx(); + CURRENT_CONTEXT(ctxobj); if (!PyArg_ParseTuple(args, "O|O", &w, &ctxobj)) { return NULL; } @@ -3549,13 +3708,13 @@ PyObject *result, *c; char *s; - c = dflt_ctx(); + CURRENT_CONTEXT(c); if (!PyArg_ParseTuple(args, "|O", &c)) { return NULL; } CONTEXT_CHECK_VA(c); - s = mpd_to_sci(a->dec, ((PyDecContextObject *)c)->capitals); + s = mpd_to_sci(a->dec, CtxCaps(c)); if (s == NULL) { PyErr_NoMemory(); return NULL; @@ -3574,13 +3733,13 @@ PyObject *result, *c; char *s; - c = dflt_ctx(); + CURRENT_CONTEXT(c); if (!PyArg_ParseTuple(args, "|O", &c)) { return NULL; } CONTEXT_CHECK_VA(c); - s = mpd_to_eng(a->dec, ((PyDecContextObject *)c)->capitals); + s = mpd_to_eng(a->dec, CtxCaps(c)); if (s == NULL) { PyErr_NoMemory(); return NULL; @@ -3596,13 +3755,13 @@ dec_richcompare(PyObject *v, PyObject *w, int op) { PyDecObject *a = (PyDecObject *)v; - PyDecObject *b; + PyDecObject *b; uint32_t status = 0; mpd_context_t *ctx; int a_issnan, b_issnan; int r; - ctx = mpd_ctx(); + CURRENT_CONTEXT_ADDR(ctx); CONVERT_BINOP(v, w, &a, &b, ctx); a_issnan = mpd_issnan(a->dec); @@ -3670,7 +3829,7 @@ mpd_t *tmp = NULL; char *cp = NULL; uint32_t status = 0; - mpd_context_t maxcontext, *ctx; + mpd_context_t maxcontext; long result; if ((a = dec_alloc()) == NULL) { @@ -3701,11 +3860,15 @@ result = 0; } else if (mpd_isinteger(a->dec)) { - + PyObject *ctxobj = current_context(); + mpd_context_t *ctx; + if (ctxobj == NULL) { + result = -1; + goto finish; + } + ctx = CtxAddr(ctxobj); mpd_maxcontext(&maxcontext); - ctx = mpd_ctx(); -#if PY_VERSION_HEX >= 0x02060000 if ((tmp = mpd_qnew()) == NULL) { PyErr_NoMemory(); result = -1; @@ -3725,7 +3888,6 @@ goto finish; } } -#endif if ((obj = PyLong_FromDecCtx(a, &maxcontext)) == NULL) { result = -1; @@ -4402,7 +4564,7 @@ ctx = CtxAddr(self); CONVERT_OP_SET(v, &a, ctx); - s = mpd_to_sci(a->dec, ((PyDecContextObject *)self)->capitals); + s = mpd_to_sci(a->dec, CtxCaps(self)); Py_DECREF(a); if (s == NULL) { PyErr_NoMemory(); @@ -4426,7 +4588,7 @@ ctx = CtxAddr(self); CONVERT_OP_SET(v, &a, ctx); - s = mpd_to_eng(a->dec, ((PyDecContextObject *)self)->capitals); + s = mpd_to_eng(a->dec, CtxCaps(self)); Py_DECREF(a); if (s == NULL) { PyErr_NoMemory(); @@ -4628,9 +4790,10 @@ static PyMethodDef cdecimal_methods [] = { - { "getcontext", (PyCFunction)PyDec_GetDefaultContext, METH_NOARGS, doc_getcontext}, - { "setcontext", (PyCFunction)PyDec_SetDefaultContext, METH_O, doc_setcontext}, + { "getcontext", (PyCFunction)PyDec_GetCurrentContext, METH_NOARGS, doc_getcontext}, + { "setcontext", (PyCFunction)PyDec_SetCurrentContext, METH_O, doc_setcontext}, { "localcontext", (PyCFunction)ctxmanager_new, METH_VARARGS, doc_localcontext}, + { "IEEEContext", (PyCFunction)ieee_context, METH_O, doc_ieee_context}, { NULL, NULL, 1, NULL } }; @@ -4654,6 +4817,7 @@ PyObject *_numbers = NULL; PyObject *_Number = NULL; PyObject *obj, *ret, *s; + PyObject *ctxobj; DecCondMap *cm; @@ -4712,28 +4876,6 @@ Py_DECREF(obj); Py_DECREF(ret); - -#ifdef USE_THREAD_LOCAL_STORAGE /* not recommended */ -{ - PyObject *_thread; - PyObject *_local; - if ((_thread = PyImport_ImportModule("_thread")) == NULL) { - goto error; - } - if ((_local = PyObject_GetAttrString(_thread, "_local")) == NULL) { - goto error; - } - if ((tls = PyObject_CallObject(_local, NULL)) == NULL) { - Py_DECREF(_thread); - Py_DECREF(_local); - goto error; - } - Py_DECREF(_thread); - Py_DECREF(_local); -} -#endif - - if ((m = PyModule_Create(&cdecimal_module)) == NULL) { goto error; } @@ -4744,11 +4886,11 @@ mpd_callocfunc = mpd_callocfunc_em; mpd_free = PyMem_Free; - Py_INCREF(&PyDec_Type); - PyModule_AddObject(m, "Decimal", (PyObject *)&PyDec_Type); + Py_INCREF(&PyDec_Type); + PyModule_AddObject(m, "Decimal", (PyObject *)&PyDec_Type); - Py_INCREF(&PyDecContext_Type); - PyModule_AddObject(m, "Context", (PyObject *)&PyDecContext_Type); + Py_INCREF(&PyDecContext_Type); + PyModule_AddObject(m, "Context", (PyObject *)&PyDecContext_Type); /* Top level Exception */ @@ -4772,7 +4914,7 @@ */ cond_map[0].dec_cond = signal_map[0].dec_cond; - /* Remaining exceptions, inherit from the InvalidOperation */ + /* Remaining exceptions, inherit from InvalidOperation */ for (cm = cond_map+1; cm->name != NULL; cm++) { cm->dec_cond = PyErr_NewException((char *)cm->fqname, signal_map[0].dec_cond , NULL); @@ -4781,35 +4923,53 @@ } - /* Module default context and template for local and - * thread local contexts */ - module_context = PyObject_CallObject((PyObject *)&PyDecContext_Type, NULL); - if (module_context == NULL) { + /* MPD_MINALLOC */ + mpd_setminalloc(4); + + /* Default context template */ + ctxobj = PyObject_CallObject((PyObject *)&PyDecContext_Type, NULL); + if (ctxobj == NULL) { goto error; } - mpd_init(CtxAddr(module_context), 28); - CtxAddr(module_context)->traps &= ~MPD_Underflow; /* XXX */ - Py_INCREF(module_context); - PyModule_AddObject(m, "DefaultContext", (PyObject *)module_context); - - /* Basic context */ - basic_context = PyObject_CallObject((PyObject *)&PyDecContext_Type, NULL); - if (basic_context == NULL) { + default_context_template = ctxobj; + Py_INCREF(ctxobj); + PyModule_AddObject(m, "DefaultContext", ctxobj); + +#ifdef WITHOUT_THREADS + /* Module context */ + ctxobj = PyObject_CallObject((PyObject *)&PyDecContext_Type, NULL); + if (ctxobj == NULL) { goto error; } - mpd_basiccontext(CtxAddr(basic_context)); - Py_INCREF(basic_context); - PyModule_AddObject(m, "BasicContext", (PyObject *)basic_context); - - /* Extended context */ - ext_context = PyObject_CallObject((PyObject *)&PyDecContext_Type, NULL); - if (ext_context == NULL) { + module_context = ctxobj; + PyModule_AddIntConstant(m, "HAVE_THREADS", 0); +#else + tls_context_key = Py_BuildValue("s", "__CDECIMAL_CTX__"); + if (tls_context_key == NULL) { goto error; } - mpd_extcontext(CtxAddr(ext_context)); - Py_INCREF(ext_context); - PyModule_AddObject(m, "ExtendedContext", (PyObject *)ext_context); + PyModule_AddIntConstant(m, "HAVE_THREADS", 1); +#endif + /* Basic context template */ + ctxobj = PyObject_CallObject((PyObject *)&PyDecContext_Type, NULL); + if (ctxobj == NULL) { + goto error; + } + init_basic_context(ctxobj); + basic_context_template = ctxobj; + Py_INCREF(ctxobj); + PyModule_AddObject(m, "BasicContext", ctxobj); + + /* Extended context template */ + ctxobj = PyObject_CallObject((PyObject *)&PyDecContext_Type, NULL); + if (ctxobj == NULL) { + goto error; + } + init_extended_context(ctxobj); + extended_context_template = ctxobj; + Py_INCREF(ctxobj); + PyModule_AddObject(m, "ExtendedContext", ctxobj); /* Useful constants */ @@ -4818,6 +4978,11 @@ PyModule_AddObject(m, "MIN_EMIN", Py_BuildValue(CONV_mpd_ssize_t, MPD_MIN_EMIN)); PyModule_AddObject(m, "MIN_ETINY", Py_BuildValue(CONV_mpd_ssize_t, MPD_MIN_ETINY)); + PyModule_AddIntConstant(m, "DECIMAL32", MPD_DECIMAL32); + PyModule_AddIntConstant(m, "DECIMAL64", MPD_DECIMAL64); + PyModule_AddIntConstant(m, "DECIMAL128", MPD_DECIMAL128); + PyModule_AddIntConstant(m, "IEEE_CONTEXT_MAX_BITS", MPD_IEEE_CONTEXT_MAX_BITS); + PyModule_AddIntConstant(m, "ROUND_CEILING", MPD_ROUND_CEILING); PyModule_AddIntConstant(m, "ROUND_FLOOR", MPD_ROUND_FLOOR); PyModule_AddIntConstant(m, "ROUND_UP", MPD_ROUND_UP); @@ -4851,14 +5016,17 @@ return m; - error: - if (tls) Py_DECREF(tls); if (_numbers) Py_DECREF(_numbers); if (_Number) Py_DECREF(_Number); +#ifdef WITHOUT_THREADS if (module_context) Py_DECREF(module_context); - if (basic_context) Py_DECREF(basic_context); - if (ext_context) Py_DECREF(ext_context); +#else + if (default_context_template) Py_DECREF(default_context_template); + if (tls_context_key) Py_DECREF(tls_context_key); +#endif + if (basic_context_template) Py_DECREF(basic_context_template); + if (extended_context_template) Py_DECREF(extended_context_template); if (m) Py_DECREF(m); return NULL; From python-checkins at python.org Sat Jun 5 09:51:13 2010 From: python-checkins at python.org (stefan.krah) Date: Sat, 5 Jun 2010 09:51:13 +0200 (CEST) Subject: [Python-checkins] r81715 - python/branches/py3k-cdecimal/Modules/cdecimal/context.c Message-ID: <20100605075113.3ADA8EE9A5@mail.python.org> Author: stefan.krah Date: Sat Jun 5 09:51:13 2010 New Revision: 81715 Log: Remove mpd_extcontext (only from the library) and add mpd_ieee_context. Modified: python/branches/py3k-cdecimal/Modules/cdecimal/context.c Modified: python/branches/py3k-cdecimal/Modules/cdecimal/context.c ============================================================================== --- python/branches/py3k-cdecimal/Modules/cdecimal/context.c (original) +++ python/branches/py3k-cdecimal/Modules/cdecimal/context.c Sat Jun 5 09:51:13 2010 @@ -19,7 +19,7 @@ void (* mpd_traphandler)(mpd_context_t *) = mpd_dflt_traphandler; -static void +void mpd_setminalloc(mpd_ssize_t n) { static int minalloc_is_set = 0; @@ -97,20 +97,25 @@ ctx->allcr=1; } -void -mpd_extcontext(mpd_context_t *ctx) +int +mpd_ieee_context(mpd_context_t *ctx, int bits) { - ctx->prec=9; - ctx->emax=MPD_MAX_EMAX; - ctx->emin=MPD_MIN_EMIN; + if (bits <= 0 || bits > MPD_IEEE_CONTEXT_MAX_BITS || bits % 32) { + return -1; + } + + ctx->prec = 9 * (bits/32) - 2; + ctx->emax = 3 * ((mpd_ssize_t)1<<(bits/16+3)); + ctx->emin = 1 - ctx->emax; ctx->round=MPD_ROUND_HALF_EVEN; ctx->traps=0; ctx->status=0; ctx->newtrap=0; - ctx->clamp=0; + ctx->clamp=1; ctx->allcr=1; -} + return 0; +} mpd_ssize_t mpd_getprec(const mpd_context_t *ctx) From python-checkins at python.org Sat Jun 5 09:54:56 2010 From: python-checkins at python.org (stefan.krah) Date: Sat, 5 Jun 2010 09:54:56 +0200 (CEST) Subject: [Python-checkins] r81716 - python/branches/py3k-cdecimal/Modules/cdecimal/docstrings.h Message-ID: <20100605075456.1A5F8EE9CF@mail.python.org> Author: stefan.krah Date: Sat Jun 5 09:54:55 2010 New Revision: 81716 Log: 1) Document IEEEContext(). 2) Example code should pass doctests. Modified: python/branches/py3k-cdecimal/Modules/cdecimal/docstrings.h Modified: python/branches/py3k-cdecimal/Modules/cdecimal/docstrings.h ============================================================================== --- python/branches/py3k-cdecimal/Modules/cdecimal/docstrings.h (original) +++ python/branches/py3k-cdecimal/Modules/cdecimal/docstrings.h Sat Jun 5 09:54:55 2010 @@ -34,6 +34,13 @@ the current default context is used.\n\ \n"); +PyDoc_STRVAR(doc_ieee_context,"\n\ +IEEEContext(bits) - Return a context object initialized to the proper values for\n\ +one of the IEEE interchange formats. The argument must be a multiple of 32 and\n\ +less than IEEE_CONTEXT_MAX_BITS. For the most common values, the constants\n\ +DECIMAL32, DECIMAL64 and DECIMAL128 are provided.\n\ +\n"); + /******************************************************************************/ /* Decimal Object and Methods */ @@ -552,10 +559,11 @@ Over/Underflow, raising of exceptions and much more. A new context\n\ can be constructed as follows:\n\ \n\ - >>> c = Context(prec=28, Emin=-425000000, Emax=425000000, \n\ - rounding=ROUND_HALF_EVEN, capitals=1,\n\ - traps=[InvalidOperation, DivisionByZero, Overflow],\n\ - flags=[], _clamp=0, _allcr=1)\n\ + >>> c = Context(prec=28, Emin=-425000000, Emax=425000000,\n\ + ... rounding=ROUND_HALF_EVEN, capitals=1, clamp=1,\n\ + ... traps=[InvalidOperation, DivisionByZero, Overflow],\n\ + ... flags=[], _allcr=1)\n\ + >>>\n\ \n\ \n"); From python-checkins at python.org Sat Jun 5 09:59:37 2010 From: python-checkins at python.org (stefan.krah) Date: Sat, 5 Jun 2010 09:59:37 +0200 (CEST) Subject: [Python-checkins] r81717 - python/branches/py3k-cdecimal/Modules/cdecimal/io.c Message-ID: <20100605075937.70102EE983@mail.python.org> Author: stefan.krah Date: Sat Jun 5 09:59:37 2010 New Revision: 81717 Log: 1) Take the default for 'capitals' from the current context. 2) Must use maxcontext. Modified: python/branches/py3k-cdecimal/Modules/cdecimal/io.c Modified: python/branches/py3k-cdecimal/Modules/cdecimal/io.c ============================================================================== --- python/branches/py3k-cdecimal/Modules/cdecimal/io.c (original) +++ python/branches/py3k-cdecimal/Modules/cdecimal/io.c Sat Jun 5 09:59:37 2010 @@ -665,7 +665,7 @@ } int -mpd_parse_fmt_str(mpd_spec_t *spec, const char *fmt) +mpd_parse_fmt_str(mpd_spec_t *spec, const char *fmt, int caps) { char *cp = (char *)fmt; int have_align = 0, n; @@ -673,7 +673,7 @@ /* defaults */ spec->min_width = 0; spec->prec = -1; - spec->type = 'G'; + spec->type = caps ? 'G' : 'g'; spec->align = '>'; spec->sign = '-'; spec->dot = ""; @@ -1081,8 +1081,8 @@ flags |= MPD_FMT_SIGN_PLUS; } - workctx = *ctx; - workctx.traps = workctx.status = 0; + mpd_maxcontext(&workctx); + workctx.round = ctx->round; if (mpd_isspecial(&tmp)) { /* no percent formatting */ flags |= MPD_FMT_TOSCI; @@ -1165,7 +1165,7 @@ { mpd_spec_t spec; - if (!mpd_parse_fmt_str(&spec, fmt)) { + if (!mpd_parse_fmt_str(&spec, fmt, 1)) { *status |= MPD_Invalid_operation; return NULL; } From python-checkins at python.org Sat Jun 5 10:07:35 2010 From: python-checkins at python.org (stefan.krah) Date: Sat, 5 Jun 2010 10:07:35 +0200 (CEST) Subject: [Python-checkins] r81718 - python/branches/py3k-cdecimal/Modules/cdecimal/mpdecimal32.h Message-ID: <20100605080735.63165EED55@mail.python.org> Author: stefan.krah Date: Sat Jun 5 10:07:35 2010 New Revision: 81718 Log: 1) Add constants for IEEE 754 interchange format contexts. 2) Export mpd_setminalloc(), add mpd_ieee_context(). Modified: python/branches/py3k-cdecimal/Modules/cdecimal/mpdecimal32.h Modified: python/branches/py3k-cdecimal/Modules/cdecimal/mpdecimal32.h ============================================================================== --- python/branches/py3k-cdecimal/Modules/cdecimal/mpdecimal32.h (original) +++ python/branches/py3k-cdecimal/Modules/cdecimal/mpdecimal32.h Sat Jun 5 10:07:35 2010 @@ -142,6 +142,12 @@ /* Official name */ #define MPD_Insufficient_storage MPD_Malloc_error + +/* IEEE 754 interchange format contexts */ +#define MPD_IEEE_CONTEXT_MAX_BITS 512 /* 16*(log2(MPD_MAX_EMAX / 3)-3) */ +#define MPD_DECIMAL32 32 +#define MPD_DECIMAL64 64 +#define MPD_DECIMAL128 128 #define MPD_MINALLOC_MIN 2 @@ -149,12 +155,13 @@ extern mpd_ssize_t MPD_MINALLOC; extern void (* mpd_traphandler)(mpd_context_t *); +void mpd_setminalloc(mpd_ssize_t n); void mpd_init(mpd_context_t *ctx, mpd_ssize_t prec); void mpd_maxcontext(mpd_context_t *ctx); void mpd_defaultcontext(mpd_context_t *ctx); void mpd_basiccontext(mpd_context_t *ctx); -void mpd_extcontext(mpd_context_t *ctx); +int mpd_ieee_context(mpd_context_t *ctx, int bits); mpd_ssize_t mpd_getprec(const mpd_context_t *ctx); mpd_ssize_t mpd_getemax(const mpd_context_t *ctx); @@ -228,7 +235,7 @@ /* output to a string */ char *mpd_to_sci(const mpd_t *dec, int fmt); char *mpd_to_eng(const mpd_t *dec, int fmt); -int mpd_parse_fmt_str(mpd_spec_t *spec, const char *fmt); +int mpd_parse_fmt_str(mpd_spec_t *spec, const char *fmt, int caps); char * mpd_qformat_spec(const mpd_t *dec, mpd_spec_t *spec, const mpd_context_t *ctx, uint32_t *status); char *mpd_qformat(const mpd_t *dec, const char *fmt, const mpd_context_t *ctx, uint32_t *status); From ncoghlan at gmail.com Sat Jun 5 10:08:05 2010 From: ncoghlan at gmail.com (Nick Coghlan) Date: Sat, 05 Jun 2010 18:08:05 +1000 Subject: [Python-checkins] r81706 - in python/trunk: Lib/test/test_descr.py Objects/abstract.c In-Reply-To: <20100605003251.2A9BCEECF3@mail.python.org> References: <20100605003251.2A9BCEECF3@mail.python.org> Message-ID: <4C0A05E5.3030105@gmail.com> On 05/06/10 10:32, benjamin.peterson wrote: > - /* Initialize cached value */ > - if (str__format__ == NULL) { > - /* Initialize static variable needed by _PyType_Lookup */ > - str__format__ = PyString_InternFromString("__format__"); > - if (str__format__ == NULL) > - goto done; > - } > - Why kill the microoptimisation here? Looking the string up in the intern dict every time (as these changes do) is a waste of cycles. Since avoiding it is pretty easy using this common idiom, it's generally worth doing. I suggest restoring the microoptimisation and then rewriting the _PyObject_LookupSpecial call to prepopulate the object: _PyObject_LookupSpecial(obj, NULL, str__format) Cheers, Nick. -- Nick Coghlan | ncoghlan at gmail.com | Brisbane, Australia --------------------------------------------------------------- From python-checkins at python.org Sat Jun 5 10:15:47 2010 From: python-checkins at python.org (stefan.krah) Date: Sat, 5 Jun 2010 10:15:47 +0200 (CEST) Subject: [Python-checkins] r81719 - python/branches/py3k-cdecimal/Modules/cdecimal/mpdecimal64.h Message-ID: <20100605081547.DBC8EEEDCA@mail.python.org> Author: stefan.krah Date: Sat Jun 5 10:15:47 2010 New Revision: 81719 Log: 1) Add constants for IEEE 754 interchange format contexts. 2) Export mpd_setminalloc(), add mpd_ieee_context(). Modified: python/branches/py3k-cdecimal/Modules/cdecimal/mpdecimal64.h Modified: python/branches/py3k-cdecimal/Modules/cdecimal/mpdecimal64.h ============================================================================== --- python/branches/py3k-cdecimal/Modules/cdecimal/mpdecimal64.h (original) +++ python/branches/py3k-cdecimal/Modules/cdecimal/mpdecimal64.h Sat Jun 5 10:15:47 2010 @@ -138,18 +138,25 @@ /* Official name */ #define MPD_Insufficient_storage MPD_Malloc_error +/* IEEE 754 interchange format contexts */ +#define MPD_IEEE_CONTEXT_MAX_BITS 512 /* 16*(log2(MPD_MAX_EMAX / 3)-3) */ +#define MPD_DECIMAL32 32 +#define MPD_DECIMAL64 64 +#define MPD_DECIMAL128 128 + #define MPD_MINALLOC_MIN 2 #define MPD_MINALLOC_MAX 64 extern mpd_ssize_t MPD_MINALLOC; extern void (* mpd_traphandler)(mpd_context_t *); +void mpd_setminalloc(mpd_ssize_t n); void mpd_init(mpd_context_t *ctx, mpd_ssize_t prec); void mpd_maxcontext(mpd_context_t *ctx); void mpd_defaultcontext(mpd_context_t *ctx); void mpd_basiccontext(mpd_context_t *ctx); -void mpd_extcontext(mpd_context_t *ctx); +int mpd_ieee_context(mpd_context_t *ctx, int bits); mpd_ssize_t mpd_getprec(const mpd_context_t *ctx); mpd_ssize_t mpd_getemax(const mpd_context_t *ctx); @@ -223,7 +230,7 @@ /* output to a string */ char *mpd_to_sci(const mpd_t *dec, int fmt); char *mpd_to_eng(const mpd_t *dec, int fmt); -int mpd_parse_fmt_str(mpd_spec_t *spec, const char *fmt); +int mpd_parse_fmt_str(mpd_spec_t *spec, const char *fmt, int caps); char * mpd_qformat_spec(const mpd_t *dec, mpd_spec_t *spec, const mpd_context_t *ctx, uint32_t *status); char *mpd_qformat(const mpd_t *dec, const char *fmt, const mpd_context_t *ctx, uint32_t *status); From python-checkins at python.org Sat Jun 5 11:04:03 2010 From: python-checkins at python.org (stefan.krah) Date: Sat, 5 Jun 2010 11:04:03 +0200 (CEST) Subject: [Python-checkins] r81720 - python/branches/py3k-cdecimal/Modules/cdecimal/mpdecimal.c Message-ID: <20100605090403.2A170EEDEE@mail.python.org> Author: stefan.krah Date: Sat Jun 5 11:04:02 2010 New Revision: 81720 Log: 1) If clamp=1, the maximum payload length of a NaN is prec-1. 2) Change cutoff for Newton division. 3) _mpd_qbarrett_divmod should use MAX_EMAX, MIN_EMIN. 4) _mpd_qexp() and _mpd_qln(): Do not use all excess digits by default. Ziv's strategy for correct rounding increases the precision as needed. 5) context.clamp must be set to 0 in several intermediate calculations. 6) Check for v = 1 must happen in mpd_qln(). 7) Add skips for certain underflow in _mpd_qln(). 8) Add skips for certain overflow in mpd_qln() and mpd_qlog10(). Modified: python/branches/py3k-cdecimal/Modules/cdecimal/mpdecimal.c Modified: python/branches/py3k-cdecimal/Modules/cdecimal/mpdecimal.c ============================================================================== --- python/branches/py3k-cdecimal/Modules/cdecimal/mpdecimal.c (original) +++ python/branches/py3k-cdecimal/Modules/cdecimal/mpdecimal.c Sat Jun 5 11:04:02 2010 @@ -42,7 +42,7 @@ #define ALWAYS_INLINE inline __attribute__ ((always_inline)) #endif -#define MPD_NEWTONDIV_CUTOFF (8*MPD_RDIGITS) +#define MPD_NEWTONDIV_CUTOFF 1024L #define MPD_NEW_STATIC(name, flags, exp, digits, len) \ mpd_uint_t name##_data[MPD_MINALLOC_MAX]; \ @@ -77,7 +77,7 @@ static inline void _mpd_qmul(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status); static void _mpd_qbarrett_divmod(mpd_t *q, mpd_t *r, const mpd_t *a, - const mpd_t *b, const mpd_context_t *ctx, uint32_t *status); + const mpd_t *b, uint32_t *status); static inline void _mpd_qpow_uint(mpd_t *result, mpd_t *base, mpd_uint_t exp, uint8_t resultsign, const mpd_context_t *ctx, uint32_t *status); @@ -731,14 +731,13 @@ _mpd_idiv_word(&len, &r, ctx->prec, MPD_RDIGITS); len = (r == 0) ? len : len+1; - /* resize to fewer words cannot fail */ - mpd_qresize(result, len, &dummy); - if (r != 0) { result->data[len-1] %= mpd_pow10[r]; } len = _mpd_real_size(result->data, len); + /* resize to fewer words cannot fail */ + mpd_qresize(result, len, &dummy); result->len = len; mpd_setdigits(result); } @@ -749,31 +748,38 @@ /* * Cut off the most significant digits of a NaN payload so that the rest - * fits in ctx->prec. Cannot fail. + * fits in ctx->prec - ctx->clamp. Cannot fail. */ static void _mpd_fix_nan(mpd_t *result, const mpd_context_t *ctx) { uint32_t dummy; + mpd_ssize_t prec; mpd_ssize_t len, r; - if (result->len > 0 && result->digits > ctx->prec-ctx->clamp) { - _mpd_idiv_word(&len, &r, ctx->prec, MPD_RDIGITS); - len = (r == 0) ? len : len+1; - - /* resize to fewer words cannot fail */ - mpd_qresize(result, len, &dummy); - - if (r != 0) { - result->data[len-1] %= mpd_pow10[r]; + prec = ctx->prec - ctx->clamp; + if (result->len > 0 && result->digits > prec) { + if (prec == 0) { + mpd_minalloc(result); + result->len = result->digits = 0; } + else { + _mpd_idiv_word(&len, &r, prec, MPD_RDIGITS); + len = (r == 0) ? len : len+1; - len = _mpd_real_size(result->data, len); - result->len = len; - mpd_setdigits(result); - if (mpd_iszerocoeff(result)) { - /* NaN0 is not a valid representation */ - result->len = result->digits = 0; + if (r != 0) { + result->data[len-1] %= mpd_pow10[r]; + } + + len = _mpd_real_size(result->data, len); + /* resize to fewer words cannot fail */ + mpd_qresize(result, len, &dummy); + result->len = len; + mpd_setdigits(result); + if (mpd_iszerocoeff(result)) { + /* NaN0 is not a valid representation */ + result->len = result->digits = 0; + } } } } @@ -1220,7 +1226,8 @@ *status |= MPD_Invalid_operation; return MPD_UINT_MAX; } - /* at this point a->digits+a->exp <= MPD_RDIGITS+1, so the shift fits */ + /* At this point a->digits+a->exp <= MPD_RDIGITS+1, + * so the shift fits. */ tmp.data = tmp_data; tmp.flags = MPD_STATIC|MPD_CONST_DATA; mpd_qsshiftr(&tmp, a, -a->exp); @@ -2486,6 +2493,7 @@ mpd_clear_flags(result); result->exp = 0; result->len = _mpd_real_size(result->data, len); + mpd_qresize(result, result->len, status); mpd_setdigits(result); _mpd_cap(result, ctx); return; @@ -2598,6 +2606,7 @@ mpd_clear_flags(result); result->exp = 0; result->len = _mpd_real_size(result->data, big->len); + mpd_qresize(result, result->len, status); mpd_setdigits(result); _mpd_cap(result, ctx); return; @@ -2890,6 +2899,7 @@ mpd_clear_flags(result); result->exp = 0; result->len = _mpd_real_size(result->data, big->len); + mpd_qresize(result, result->len, status); mpd_setdigits(result); _mpd_cap(result, ctx); return; @@ -3301,8 +3311,8 @@ if (b->len == 1) { rem = _mpd_shortdiv(q->data, a->data, a->len, b->data[0]); } - else if (ctx->prec < MPD_NEWTONDIV_CUTOFF || - b->digits < MPD_NEWTONDIV_CUTOFF) { + else if (a->len < 2*MPD_NEWTONDIV_CUTOFF && + b->len < MPD_NEWTONDIV_CUTOFF) { int ret = _mpd_basedivmod(q->data, NULL, a->data, b->data, a->len, b->len); if (ret < 0) { @@ -3313,7 +3323,7 @@ } else { MPD_NEW_STATIC(r,0,0,0,0); - _mpd_qbarrett_divmod(q, &r, a, b, ctx, status); + _mpd_qbarrett_divmod(q, &r, a, b, status); rem = !mpd_iszerocoeff(&r); mpd_del(&r); newsize = q->len; @@ -3457,8 +3467,8 @@ r->data[0] = _mpd_shortdiv(q->data, a->data, a->len, b->data[0]); } } - else if (ctx->prec < MPD_NEWTONDIV_CUTOFF || - b->digits < MPD_NEWTONDIV_CUTOFF) { + else if (a->len < 2*MPD_NEWTONDIV_CUTOFF && + b->len < MPD_NEWTONDIV_CUTOFF) { int ret; ret = _mpd_basedivmod(q->data, r->data, a->data, b->data, a->len, b->len); @@ -3468,7 +3478,7 @@ } } else { - _mpd_qbarrett_divmod(q, r, a, b, ctx, status); + _mpd_qbarrett_divmod(q, r, a, b, status); if (mpd_isinfinite(q) || q->digits > ctx->prec) { *status |= MPD_Division_impossible; goto nanresult; @@ -3763,9 +3773,9 @@ } mpd_maxcontext(&workctx); - workctx.round = MPD_ROUND_HALF_EVEN; - workctx.prec = (ctx->prec > a->digits ? ctx->prec : a->digits) + t + 2; + workctx.prec = ctx->prec + t + 2; workctx.prec = (workctx.prec < 9) ? 9 : workctx.prec; + workctx.round = MPD_ROUND_HALF_EVEN; if ((n = _mpd_get_exp_iterations(a, workctx.prec)) == MPD_SSIZE_MAX) { mpd_seterror(result, MPD_Invalid_operation, status); @@ -3844,6 +3854,7 @@ a = &aa; } + workctx.clamp = 0; prec = ctx->prec + 3; while (1) { workctx.prec = prec; @@ -3852,10 +3863,11 @@ result->exp + result->digits-workctx.prec-1); workctx.prec = ctx->prec; - mpd_qadd(&t1, result, &ulp, &workctx, status); - mpd_qsub(&t2, result, &ulp, &workctx, status); + mpd_qadd(&t1, result, &ulp, &workctx, &workctx.status); + mpd_qsub(&t2, result, &ulp, &workctx, &workctx.status); if (mpd_isspecial(result) || mpd_iszerocoeff(result) || mpd_qcmp(&t1, &t2, status) == 0) { + workctx.clamp = ctx->clamp; mpd_qfinalize(result, &workctx, status); break; } @@ -3949,13 +3961,13 @@ mpd_ssize_t klist[MPD_MAX_PREC_LOG2]; int i; - if (mpd_ln10.digits > maxprec) { + if (mpd_ln10.digits > maxprec+2*MPD_RDIGITS) { /* shift to smaller cannot fail */ mpd_qshiftr_inplace(&mpd_ln10, mpd_ln10.digits-maxprec); mpd_ln10.exp = -(mpd_ln10.digits-1); return; } - else if (mpd_ln10.digits == maxprec) { + else if (mpd_ln10.digits >= maxprec) { return; } @@ -4047,7 +4059,7 @@ 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 }; -/* Internal ln() function that does not check for specials or zero. */ +/* Internal ln() function that does not check for specials, zero or one. */ static void _mpd_qln(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status) @@ -4063,11 +4075,6 @@ mpd_uint_t dummy, x; int i; - if (_mpd_cmp(a, &one) == 0) { - _settriple(result, MPD_POS, 0, 0); - return; - } - /* * We are calculating ln(a) = ln(v * 10^t) = ln(v) + t*ln(10), * where 0.5 < v <= 5. @@ -4104,22 +4111,42 @@ mpd_set_negative(z); } - mpd_maxcontext(&maxcontext); mpd_maxcontext(&varcontext); varcontext.round = MPD_ROUND_TRUNC; - maxprec = (a->digits > ctx->prec) ? a->digits : ctx->prec; - maxprec += 2; + maxprec = ctx->prec + 2; if (x <= 10 || x >= 805) { - /* v is close to 1: We estimate the magnitude of - * the logarithm and adjust the precision upwards. - * x/10 < x/(1+x) < ln(1+x), for 0 < x < 1 - * ln(1+x) < x, for -1 < x < 0 + /* v is close to 1: Estimate the magnitude of the logarithm. + * If v = 1 or ln(v) will underflow, skip the loop. Otherwise, + * adjust the precision upwards in order to obtain a sufficient + * number of significant digits. + * + * 1) x/(1+x) < ln(1+x) < x, for x > -1, x != 0 + * + * 2) (v-1)/v < ln(v) < v-1 */ - mpd_qsub(&tmp, &one, &v, &varcontext, &varcontext.status); - maxprec -= (tmp.exp < 0) ? tmp.exp : 0; - maxprec++; + mpd_t *lower = &tmp; + mpd_t *upper = &vtmp; + int cmp = _mpd_cmp(&v, &one); + + varcontext.round = MPD_ROUND_CEILING; + varcontext.prec = maxprec; + mpd_qsub(upper, &v, &one, &varcontext, &varcontext.status); + varcontext.round = MPD_ROUND_FLOOR; + mpd_qdiv(lower, upper, &v, &varcontext, &varcontext.status); + varcontext.round = MPD_ROUND_TRUNC; + + if (cmp < 0) { + _mpd_ptrswap(&upper, &lower); + } + if (mpd_adjexp(upper) < mpd_etiny(ctx)) { + _settriple(z, (cmp<0), 1, mpd_etiny(ctx)-1); + goto postloop; + } + if (mpd_adjexp(lower) < 0) { + maxprec = maxprec - mpd_adjexp(lower); + } } i = ln_schedule_prec(klist, maxprec, 2); @@ -4143,9 +4170,11 @@ mpd_qadd(z, z, &tmp, &maxcontext, status); } +postloop: mpd_update_ln10(maxprec+2, status); mpd_qmul_ssize(&tmp, &mpd_ln10, t, &maxcontext, status); - mpd_qadd(result, &tmp, z, &maxcontext, status); + varcontext.prec = maxprec+2; + mpd_qadd(result, &tmp, z, &varcontext, status); finish: @@ -4160,6 +4189,7 @@ uint32_t *status) { mpd_context_t workctx; + mpd_ssize_t adjexp, t; if (mpd_isspecial(a)) { if (mpd_qcheck_nan(result, a, ctx, status)) { @@ -4180,6 +4210,27 @@ mpd_seterror(result, MPD_Invalid_operation, status); return; } + if (_mpd_cmp(a, &one) == 0) { + _settriple(result, MPD_POS, 0, 0); + return; + } + /* Check if the result will overflow. + * + * 1) adjexp(a) + 1 > log10(a) >= adjexp(a) + * + * 2) |log10(a)| >= adjexp(a), if adjexp(a) >= 0 + * |log10(a)| > -adjexp(a)-1, if adjexp(a) < 0 + * + * 3) |log(a)| > 2*|log10(a)| + */ + adjexp = mpd_adjexp(a); + t = (adjexp < 0) ? -adjexp-1 : adjexp; + t *= 2; + if (mpd_exp_digits(t)-1 > ctx->emax) { + *status |= MPD_Overflow|MPD_Inexact|MPD_Rounded; + mpd_setspecial(result, (adjexp<0), MPD_INF); + return; + } workctx = *ctx; workctx.round = MPD_ROUND_HALF_EVEN; @@ -4196,6 +4247,7 @@ a = &aa; } + workctx.clamp = 0; prec = ctx->prec + 3; while (1) { workctx.prec = prec; @@ -4204,10 +4256,11 @@ result->exp + result->digits-workctx.prec-1); workctx.prec = ctx->prec; - mpd_qadd(&t1, result, &ulp, &workctx, status); - mpd_qsub(&t2, result, &ulp, &workctx, status); + mpd_qadd(&t1, result, &ulp, &workctx, &workctx.status); + mpd_qsub(&t2, result, &ulp, &workctx, &workctx.status); if (mpd_isspecial(result) || mpd_iszerocoeff(result) || mpd_qcmp(&t1, &t2, status) == 0) { + workctx.clamp = ctx->clamp; mpd_qfinalize(result, &workctx, status); break; } @@ -4232,9 +4285,9 @@ mpd_context_t workctx; mpd_maxcontext(&workctx); - workctx.prec = ctx->prec + a->digits + 3; + workctx.prec = ctx->prec + 3; _mpd_qln(result, a, &workctx, status); - mpd_update_ln10(ctx->prec + 3, status); + mpd_update_ln10(workctx.prec, status); workctx = *ctx; workctx.round = MPD_ROUND_HALF_EVEN; @@ -4247,6 +4300,7 @@ uint32_t *status) { mpd_context_t workctx; + mpd_ssize_t adjexp, t; workctx = *ctx; workctx.round = MPD_ROUND_HALF_EVEN; @@ -4281,6 +4335,20 @@ mpd_qfinalize(result, &workctx, status); return; } + /* Check if the result will overflow. + * + * 1) adjexp(a) + 1 > log10(a) >= adjexp(a) + * + * 2) |log10(a)| >= adjexp(a), if adjexp(a) >= 0 + * |log10(a)| > -adjexp(a)-1, if adjexp(a) < 0 + */ + adjexp = mpd_adjexp(a); + t = (adjexp < 0) ? -adjexp-1 : adjexp; + if (mpd_exp_digits(t)-1 > ctx->emax) { + *status |= MPD_Overflow|MPD_Inexact|MPD_Rounded; + mpd_setspecial(result, (adjexp<0), MPD_INF); + return; + } if (ctx->allcr) { MPD_NEW_STATIC(t1, 0,0,0,0); @@ -4294,6 +4362,7 @@ a = &aa; } + workctx.clamp = 0; prec = ctx->prec + 3; while (1) { workctx.prec = prec; @@ -4302,10 +4371,11 @@ result->exp + result->digits-workctx.prec-1); workctx.prec = ctx->prec; - mpd_qadd(&t1, result, &ulp, &workctx, status); - mpd_qsub(&t2, result, &ulp, &workctx, status); + mpd_qadd(&t1, result, &ulp, &workctx, &workctx.status); + mpd_qsub(&t2, result, &ulp, &workctx, &workctx.status); if (mpd_isspecial(result) || mpd_iszerocoeff(result) || mpd_qcmp(&t1, &t2, status) == 0) { + workctx.clamp = ctx->clamp; mpd_qfinalize(result, &workctx, status); break; } @@ -5367,6 +5437,7 @@ mpd_workcontext(&workctx, ctx); workctx.prec += (exp->digits + exp->exp + 2); workctx.round = MPD_ROUND_HALF_EVEN; + workctx.clamp = 0; if (mpd_isnegative(exp)) { mpd_qdiv(&tbase, &one, base, &workctx, status); if (*status&MPD_Errors) { @@ -5637,6 +5708,7 @@ workctx.prec = (base->digits > ctx->prec) ? base->digits : ctx->prec; workctx.prec += (4 + MPD_EXPDIGITS); workctx.round = MPD_ROUND_HALF_EVEN; + workctx.allcr = ctx->allcr; mpd_qln(result, base, &workctx, &workctx.status); mpd_qmul(result, result, &texp, &workctx, &workctx.status); @@ -5952,10 +6024,8 @@ return; } - if (mpd_issubnormal(result, ctx)) { - *status |= MPD_Subnormal; - } *status |= workstatus; + mpd_qfinalize(result, ctx, status); } void @@ -6378,14 +6448,14 @@ */ static void _mpd_qbarrett_divmod(mpd_t *q, mpd_t *r, const mpd_t *a, const mpd_t *b, - const mpd_context_t *ctx, uint32_t *status) + uint32_t *status) { mpd_context_t workctx; mpd_t *qq = q, *rr = r; mpd_t aa, bb; int k; - workctx = *ctx; + mpd_maxcontext(&workctx); _mpd_copy_shared(&aa, a); _mpd_copy_shared(&bb, b); From python-checkins at python.org Sat Jun 5 11:11:28 2010 From: python-checkins at python.org (stefan.krah) Date: Sat, 5 Jun 2010 11:11:28 +0200 (CEST) Subject: [Python-checkins] r81721 - python/branches/py3k-cdecimal/Modules/cdecimal/mpdecimal.c Message-ID: <20100605091128.536DDEE993@mail.python.org> Author: stefan.krah Date: Sat Jun 5 11:11:28 2010 New Revision: 81721 Log: _mpd_qbarrett_divmod does not take a context arg any longer. Modified: python/branches/py3k-cdecimal/Modules/cdecimal/mpdecimal.c Modified: python/branches/py3k-cdecimal/Modules/cdecimal/mpdecimal.c ============================================================================== --- python/branches/py3k-cdecimal/Modules/cdecimal/mpdecimal.c (original) +++ python/branches/py3k-cdecimal/Modules/cdecimal/mpdecimal.c Sat Jun 5 11:11:28 2010 @@ -7323,9 +7323,9 @@ } - { /* some compilers need a new block here for the declaration of r */ + { MPD_NEW_STATIC(r,0,0,0,0); - _mpd_qbarrett_divmod(q, &r, a, b, ctx, status); + _mpd_qbarrett_divmod(q, &r, a, b, status); rem = !mpd_iszerocoeff(&r); mpd_del(&r); newsize = q->len; @@ -7453,7 +7453,7 @@ } } - _mpd_qbarrett_divmod(q, r, a, b, ctx, status); + _mpd_qbarrett_divmod(q, r, a, b, status); if (mpd_isinfinite(q) || q->digits > ctx->prec) { *status |= MPD_Division_impossible; goto nanresult; From python-checkins at python.org Sat Jun 5 11:21:38 2010 From: python-checkins at python.org (stefan.krah) Date: Sat, 5 Jun 2010 11:21:38 +0200 (CEST) Subject: [Python-checkins] r81722 - python/branches/py3k-cdecimal/Modules/cdecimal/typearith.h Message-ID: <20100605092138.4E651EE9BD@mail.python.org> Author: stefan.krah Date: Sat Jun 5 11:21:38 2010 New Revision: 81722 Log: Add fast arithmetic for non-amd64 platforms. Tested on ppc64/AIX. Modified: python/branches/py3k-cdecimal/Modules/cdecimal/typearith.h Modified: python/branches/py3k-cdecimal/Modules/cdecimal/typearith.h ============================================================================== --- python/branches/py3k-cdecimal/Modules/cdecimal/typearith.h (original) +++ python/branches/py3k-cdecimal/Modules/cdecimal/typearith.h Sat Jun 5 11:21:38 2010 @@ -22,13 +22,13 @@ */ #if defined(CONFIG_64) -#if defined(__GNUC__) && defined(__x86_64__) +#if defined(__GNUC__) && defined(__x86_64__) && !defined(TEST_UINT128_T) static inline void _mpd_mul_words(mpd_uint_t *hi, mpd_uint_t *lo, mpd_uint_t a, mpd_uint_t b) { mpd_uint_t h, l; - asm( "mulq %3\n\t"\ + asm ( "mulq %3\n\t"\ : "=d" (h), "=a" (l)\ : "%a" (a), "rm" (b)\ : "cc" @@ -54,7 +54,29 @@ *r = rr; } /* END __GNUC__ (amd64) */ +#elif defined(HAVE_UINT128_T) +static inline void +_mpd_mul_words(mpd_uint_t *hi, mpd_uint_t *lo, mpd_uint_t a, mpd_uint_t b) +{ + __uint128_t hl; + + hl = (__uint128_t)a * b; + + *hi = hl >> 64; + *lo = (mpd_uint_t)hl; +} +static inline void +_mpd_div_words(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t hi, mpd_uint_t lo, + mpd_uint_t d) +{ + __uint128_t hl; + + hl = ((__uint128_t)hi<<64) + lo; + *q = (mpd_uint_t)(hl / d); /* quotient is known to fit */ + *r = (mpd_uint_t)(hl - (__uint128_t)(*q) * d); +} +/* END HAVE_UINT128_T */ #elif defined(_MSC_VER) #include #pragma intrinsic(_umul128) From python-checkins at python.org Sat Jun 5 11:32:09 2010 From: python-checkins at python.org (stefan.krah) Date: Sat, 5 Jun 2010 11:32:09 +0200 (CEST) Subject: [Python-checkins] r81723 - python/branches/py3k-cdecimal/Modules/cdecimal/mpdecimal32.h Message-ID: <20100605093209.DFA08EE9DD@mail.python.org> Author: stefan.krah Date: Sat Jun 5 11:32:09 2010 New Revision: 81723 Log: Whitespace Modified: python/branches/py3k-cdecimal/Modules/cdecimal/mpdecimal32.h Modified: python/branches/py3k-cdecimal/Modules/cdecimal/mpdecimal32.h ============================================================================== --- python/branches/py3k-cdecimal/Modules/cdecimal/mpdecimal32.h (original) +++ python/branches/py3k-cdecimal/Modules/cdecimal/mpdecimal32.h Sat Jun 5 11:32:09 2010 @@ -142,7 +142,7 @@ /* Official name */ #define MPD_Insufficient_storage MPD_Malloc_error - + /* IEEE 754 interchange format contexts */ #define MPD_IEEE_CONTEXT_MAX_BITS 512 /* 16*(log2(MPD_MAX_EMAX / 3)-3) */ #define MPD_DECIMAL32 32 From nnorwitz at gmail.com Sat Jun 5 12:23:05 2010 From: nnorwitz at gmail.com (Neal Norwitz) Date: Sat, 5 Jun 2010 06:23:05 -0400 Subject: [Python-checkins] Python Regression Test Failures refleak (1) Message-ID: <20100605102305.GA32015@kbk-i386-bb.psfb.org> More important issues: ---------------------- test_bz2 leaked [0, 0, 69] references, sum=69 Less important issues: ---------------------- From python-checkins at python.org Sat Jun 5 12:39:42 2010 From: python-checkins at python.org (michael.foord) Date: Sat, 5 Jun 2010 12:39:42 +0200 (CEST) Subject: [Python-checkins] r81724 - python/trunk/Lib/unittest/loader.py Message-ID: <20100605103942.55BC6EE9AE@mail.python.org> Author: michael.foord Date: Sat Jun 5 12:39:42 2010 New Revision: 81724 Log: unittest TestLoader test discovery filename matching done in a method. This makes it easier to override the matching strategy in subclasses. No behaviour change in actual implementation. Modified: python/trunk/Lib/unittest/loader.py Modified: python/trunk/Lib/unittest/loader.py ============================================================================== --- python/trunk/Lib/unittest/loader.py (original) +++ python/trunk/Lib/unittest/loader.py Sat Jun 5 12:39:42 2010 @@ -230,6 +230,10 @@ __import__(name) return sys.modules[name] + def _match_path(self, path, full_path, pattern): + # override this method to use alternative matching strategy + return fnmatch(path, pattern) + def _find_tests(self, start_dir, pattern): """Used by discovery. Yields test suites it loads.""" paths = os.listdir(start_dir) @@ -240,26 +244,26 @@ if not VALID_MODULE_NAME.match(path): # valid Python identifiers only continue - - if fnmatch(path, pattern): - # if the test file matches, load it - name = self._get_name_from_path(full_path) - try: - module = self._get_module_from_name(name) - except: - yield _make_failed_import_test(name, self.suiteClass) - else: - mod_file = os.path.abspath(getattr(module, '__file__', full_path)) - realpath = os.path.splitext(mod_file)[0] - fullpath_noext = os.path.splitext(full_path)[0] - if realpath.lower() != fullpath_noext.lower(): - module_dir = os.path.dirname(realpath) - mod_name = os.path.splitext(os.path.basename(full_path))[0] - expected_dir = os.path.dirname(full_path) - msg = ("%r module incorrectly imported from %r. Expected %r. " - "Is this module globally installed?") - raise ImportError(msg % (mod_name, module_dir, expected_dir)) - yield self.loadTestsFromModule(module) + if not self._match_path(path, full_path, pattern): + continue + # if the test file matches, load it + name = self._get_name_from_path(full_path) + try: + module = self._get_module_from_name(name) + except: + yield _make_failed_import_test(name, self.suiteClass) + else: + mod_file = os.path.abspath(getattr(module, '__file__', full_path)) + realpath = os.path.splitext(mod_file)[0] + fullpath_noext = os.path.splitext(full_path)[0] + if realpath.lower() != fullpath_noext.lower(): + module_dir = os.path.dirname(realpath) + mod_name = os.path.splitext(os.path.basename(full_path))[0] + expected_dir = os.path.dirname(full_path) + msg = ("%r module incorrectly imported from %r. Expected %r. " + "Is this module globally installed?") + raise ImportError(msg % (mod_name, module_dir, expected_dir)) + yield self.loadTestsFromModule(module) elif os.path.isdir(full_path): if not os.path.isfile(os.path.join(full_path, '__init__.py')): continue From python-checkins at python.org Sat Jun 5 12:45:41 2010 From: python-checkins at python.org (michael.foord) Date: Sat, 5 Jun 2010 12:45:41 +0200 (CEST) Subject: [Python-checkins] r81725 - in python/branches/py3k: Lib/unittest/loader.py Message-ID: <20100605104541.5E2CBEE9BA@mail.python.org> Author: michael.foord Date: Sat Jun 5 12:45:41 2010 New Revision: 81725 Log: Merged revisions 81724 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81724 | michael.foord | 2010-06-05 11:39:42 +0100 (Sat, 05 Jun 2010) | 1 line unittest TestLoader test discovery filename matching done in a method. This makes it easier to override the matching strategy in subclasses. No behaviour change in actual implementation. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/unittest/loader.py Modified: python/branches/py3k/Lib/unittest/loader.py ============================================================================== --- python/branches/py3k/Lib/unittest/loader.py (original) +++ python/branches/py3k/Lib/unittest/loader.py Sat Jun 5 12:45:41 2010 @@ -235,6 +235,10 @@ __import__(name) return sys.modules[name] + def _match_path(self, path, full_path, pattern): + # override this method to use alternative matching strategy + return fnmatch(path, pattern) + def _find_tests(self, start_dir, pattern): """Used by discovery. Yields test suites it loads.""" paths = os.listdir(start_dir) @@ -245,26 +249,26 @@ if not VALID_MODULE_NAME.match(path): # valid Python identifiers only continue - - if fnmatch(path, pattern): - # if the test file matches, load it - name = self._get_name_from_path(full_path) - try: - module = self._get_module_from_name(name) - except: - yield _make_failed_import_test(name, self.suiteClass) - else: - mod_file = os.path.abspath(getattr(module, '__file__', full_path)) - realpath = os.path.splitext(mod_file)[0] - fullpath_noext = os.path.splitext(full_path)[0] - if realpath.lower() != fullpath_noext.lower(): - module_dir = os.path.dirname(realpath) - mod_name = os.path.splitext(os.path.basename(full_path))[0] - expected_dir = os.path.dirname(full_path) - msg = ("%r module incorrectly imported from %r. Expected %r. " - "Is this module globally installed?") - raise ImportError(msg % (mod_name, module_dir, expected_dir)) - yield self.loadTestsFromModule(module) + if not self._match_path(path, full_path, pattern): + continue + # if the test file matches, load it + name = self._get_name_from_path(full_path) + try: + module = self._get_module_from_name(name) + except: + yield _make_failed_import_test(name, self.suiteClass) + else: + mod_file = os.path.abspath(getattr(module, '__file__', full_path)) + realpath = os.path.splitext(mod_file)[0] + fullpath_noext = os.path.splitext(full_path)[0] + if realpath.lower() != fullpath_noext.lower(): + module_dir = os.path.dirname(realpath) + mod_name = os.path.splitext(os.path.basename(full_path))[0] + expected_dir = os.path.dirname(full_path) + msg = ("%r module incorrectly imported from %r. Expected %r. " + "Is this module globally installed?") + raise ImportError(msg % (mod_name, module_dir, expected_dir)) + yield self.loadTestsFromModule(module) elif os.path.isdir(full_path): if not os.path.isfile(os.path.join(full_path, '__init__.py')): continue From python-checkins at python.org Sat Jun 5 13:11:28 2010 From: python-checkins at python.org (stefan.krah) Date: Sat, 5 Jun 2010 13:11:28 +0200 (CEST) Subject: [Python-checkins] r81726 - python/branches/py3k-cdecimal/Lib/test/decimal_tests.py Message-ID: <20100605111128.451FEEE9C7@mail.python.org> Author: stefan.krah Date: Sat Jun 5 13:11:28 2010 New Revision: 81726 Log: 1) Add nested with-statements to the threading test. 2) Add nested with-statements and garbage collection stress tests to WithStatementTest(). 3) Test the context templates and IEEEContext(). Modified: python/branches/py3k-cdecimal/Lib/test/decimal_tests.py Modified: python/branches/py3k-cdecimal/Lib/test/decimal_tests.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/test/decimal_tests.py (original) +++ python/branches/py3k-cdecimal/Lib/test/decimal_tests.py Sat Jun 5 13:11:28 2010 @@ -1299,28 +1299,68 @@ d1 = Decimal(1) d3 = Decimal(3) test1 = d1/d3 + + cls.finish1.set() cls.synchro.wait() + test2 = d1/d3 - cls.finish1.set() + with localcontext() as c2: + cls.assertTrue(c2.flags[Inexact]) + cls.assertRaises(DivisionByZero, c2.divide, d1, 0) + cls.assertTrue(c2.flags[DivisionByZero]) + with localcontext() as c3: + cls.assertTrue(c3.flags[Inexact]) + cls.assertTrue(c3.flags[DivisionByZero]) + cls.assertRaises(InvalidOperation, c3.compare, d1, Decimal('sNaN')) + cls.assertTrue(c3.flags[InvalidOperation]) + del c3 + cls.assertFalse(c2.flags[InvalidOperation]) + del c2 cls.assertEqual(test1, Decimal('0.333333333333333333333333')) cls.assertEqual(test2, Decimal('0.333333333333333333333333')) + + c1 = getcontext() + cls.assertTrue(c1.flags[Inexact]) + for sig in Overflow, Underflow, DivisionByZero, InvalidOperation: + cls.assertFalse(c1.flags[sig]) return def thfunc2(cls): d1 = Decimal(1) d3 = Decimal(3) test1 = d1/d3 + thiscontext = getcontext() thiscontext.prec = 18 test2 = d1/d3 + + with localcontext() as c2: + cls.assertTrue(c2.flags[Inexact]) + cls.assertRaises(Overflow, c2.multiply, Decimal('1e425000000'), 999) + cls.assertTrue(c2.flags[Overflow]) + with localcontext(thiscontext) as c3: + cls.assertTrue(c3.flags[Inexact]) + cls.assertFalse(c3.flags[Overflow]) + c3.traps[Underflow] = True + cls.assertRaises(Underflow, c3.divide, Decimal('1e-425000000'), 999) + cls.assertTrue(c3.flags[Underflow]) + del c3 + cls.assertFalse(c2.flags[Underflow]) + cls.assertFalse(c2.traps[Underflow]) + del c2 + cls.synchro.set() cls.finish2.set() cls.assertEqual(test1, Decimal('0.333333333333333333333333')) cls.assertEqual(test2, Decimal('0.333333333333333333')) - return + cls.assertFalse(thiscontext.traps[Underflow]) + cls.assertTrue(thiscontext.flags[Inexact]) + for sig in Overflow, Underflow, DivisionByZero, InvalidOperation: + cls.assertFalse(thiscontext.flags[sig]) + return class DecimalUseOfContextTest(unittest.TestCase): '''Unit tests for Use of Context cases in Decimal.''' @@ -1328,21 +1368,23 @@ try: import threading except ImportError: - threading = None + self.skipTest("importing threading failed") # Take care executing this test from IDLE, there's an issue in threading # that hangs IDLE and I couldn't find it def test_threading(self): + if HAVE_CDECIMAL and not HAVE_THREADS: + self.skipTest("compiled without threading") # Test the "threading isolation" of a Context. Also test changing # the DefaultContext, which acts as a template for the thread-local # contexts. - - # XXX Must re-enable if compiled with USE_THREAD_LOCAL_STORAGE! - if HAVE_CDECIMAL: return - - saveprec = DefaultContext.prec + save_prec = DefaultContext.prec + save_emax = DefaultContext.Emax + save_emin = DefaultContext.Emin DefaultContext.prec = 24 + DefaultContext.Emax = 425000000 + DefaultContext.Emin = -425000000 self.synchro = threading.Event() self.finish1 = threading.Event() @@ -1357,13 +1399,15 @@ self.finish1.wait() self.finish2.wait() - DefaultContext.prec = saveprec + for sig in (Inexact, Overflow, Underflow, DivisionByZero, + InvalidOperation): + self.assertFalse(DefaultContext.flags[sig]) + + DefaultContext.prec = save_prec + DefaultContext.Emax = save_emax + DefaultContext.Emin = save_emin return - if threading is None: - del test_threading - - class DecimalUsabilityTest(unittest.TestCase): '''Unit tests for Usability cases of Decimal.''' @@ -1462,6 +1506,9 @@ Decimal("56531E100"), ]) + if HAVE_CDECIMAL: + self.skipTest("new hashing scheme and float comparisons not " + "implemented yet") # check that hash(d) == hash(int(d)) for integral values for value in test_values: self.assertEqual(hash(value), hash(int(value))) @@ -1472,15 +1519,14 @@ self.assertTrue(hash(Decimal('Inf'))) self.assertTrue(hash(Decimal('-Inf'))) - if not HAVE_CDECIMAL: # XXX float comparisons not implemented yet. - # check that the hashes of a Decimal float match when they - # represent exactly the same values - test_strings = ['inf', '-Inf', '0.0', '-.0e1', - '34.0', '2.5', '112390.625', '-0.515625'] - for s in test_strings: - f = float(s) - d = Decimal(s) - self.assertEqual(hash(f), hash(d)) + # check that the hashes of a Decimal float match when they + # represent exactly the same values + test_strings = ['inf', '-Inf', '0.0', '-.0e1', + '34.0', '2.5', '112390.625', '-0.515625'] + for s in test_strings: + f = float(s) + d = Decimal(s) + self.assertEqual(hash(f), hash(d)) # check that the value of the hash doesn't depend on the # current context (issue #1757) @@ -1957,6 +2003,7 @@ self.assertNotEqual(id(c), id(d)) self.assertNotEqual(id(c.flags), id(d.flags)) self.assertNotEqual(id(c.traps), id(d.traps)) + self.assertEqual(c.flags, d.flags) def test_abs(self): c = Context() @@ -2416,6 +2463,81 @@ self.assertIsNot(new_ctx, set_ctx, 'did not copy the context') self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context') + def test_nested_with_statements(self): + # Use a copy of the supplied context in the block + orig_ctx = getcontext() + orig_ctx.clear_flags() + new_ctx = Context(Emax=384) + with localcontext() as c1: + self.assertEqual(c1.flags, orig_ctx.flags) + self.assertEqual(c1.traps, orig_ctx.traps) + c1.traps[Clamped] = True + c1.Emin = -383 + self.assertRaises(Clamped, c1.create_decimal, '0e-999') + self.assertTrue(c1.flags[Clamped]) + with localcontext(new_ctx) as c2: + self.assertEqual(c2.flags, new_ctx.flags) + self.assertEqual(c2.traps, new_ctx.traps) + self.assertRaises(Overflow, c2.power, Decimal('3.4e200'), 2) + self.assertFalse(c2.flags[Clamped]) + self.assertTrue(c2.flags[Overflow]) + del c2 + self.assertFalse(c1.flags[Overflow]) + del c1 + self.assertNotEqual(orig_ctx.Emin, -383) + self.assertFalse(orig_ctx.flags[Clamped]) + self.assertFalse(orig_ctx.flags[Overflow]) + self.assertFalse(new_ctx.flags[Clamped]) + self.assertFalse(new_ctx.flags[Overflow]) + + def test_with_statements_gc1(self): + with localcontext() as c1: + del c1 + with localcontext() as c2: + del c2 + with localcontext() as c3: + del c3 + with localcontext() as c4: + del c4 + + def test_with_statements_gc2(self): + with localcontext() as c1: + with localcontext(c1) as c2: + del c1 + with localcontext(c2) as c3: + del c2 + with localcontext(c3) as c4: + del c3 + del c4 + + def test_with_statements_gc3(self): + with localcontext() as c1: + del c1 + n1 = Context(prec=1) + setcontext(n1) + with localcontext(n1) as c2: + del n1 + self.assertEqual(c2.prec, 1) + del c2 + n2 = Context(prec=2) + setcontext(n2) + del n2 + self.assertEqual(getcontext().prec, 2) + n3 = Context(prec=3) + setcontext(n3) + self.assertEqual(getcontext().prec, 3) + with localcontext(n3) as c3: + del n3 + self.assertEqual(c3.prec, 3) + del c3 + n4 = Context(prec=4) + setcontext(n4) + del n4 + self.assertEqual(getcontext().prec, 4) + with localcontext() as c4: + self.assertEqual(c4.prec, 4) + del c4 + class ContextFlags(unittest.TestCase): def test_flags_irrelevant(self): # check that the result (numeric result + flags raised) of an @@ -2468,6 +2590,65 @@ "operation raises different flags depending on flags set: " + "expected %s, got %s" % (expected_flags, new_flags)) +class SpecialContexts(unittest.TestCase): + def test_context_templates(self): + basic_context_prec = BasicContext.prec + extended_context_prec = ExtendedContext.prec + + BasicContext.prec = ExtendedContext.prec = 441 + + for template in BasicContext, ExtendedContext: + setcontext(template) + c = getcontext() + self.assertIsNot(c, template) + self.assertEqual(c.prec, 441) + + BasicContext.prec = basic_context_prec + ExtendedContext.prec = extended_context_prec + + def test_default_context(self): + default_context_prec = DefaultContext.prec + + c = getcontext() + saveprec = c.prec + + DefaultContext.prec = 961 + c = getcontext() + self.assertEqual(c.prec, saveprec) + + setcontext(DefaultContext) + c = getcontext() + self.assertIsNot(c, DefaultContext) + self.assertEqual(c.prec, 961) + + DefaultContext.prec = default_context_prec + + def test_ieee_context(self): + def assert_rest(self, context): + self.assertEqual(context.clamp, 1) + for v in context.traps: + self.assertFalse(v) + for v in context.flags: + self.assertFalse(v) + + c = IEEEContext(DECIMAL32) + self.assertEqual(c.prec, 7) + self.assertEqual(c.Emax, 96) + self.assertEqual(c.Emin, -95) + assert_rest(self, c) + + c = IEEEContext(DECIMAL64) + self.assertEqual(c.prec, 16) + self.assertEqual(c.Emax, 384) + self.assertEqual(c.Emin, -383) + assert_rest(self, c) + + c = IEEEContext(DECIMAL128) + self.assertEqual(c.prec, 34) + self.assertEqual(c.Emax, 6144) + self.assertEqual(c.Emin, -6143) + assert_rest(self, c) + def test_main(arith=False, verbose=None, todo_tests=None, debug=None): """ Execute the tests. @@ -2492,7 +2673,8 @@ ContextAPItests, DecimalTest, WithStatementTest, - ContextFlags + ContextFlags, + SpecialContexts ] else: test_classes = [DecimalTest] @@ -2514,7 +2696,10 @@ try: run_unittest(*test_classes) if todo_tests is None: - import decimal as DecimalModule + if HAVE_CDECIMAL: + import cdecimal as DecimalModule + else: + import decimal as DecimalModule run_doctest(DecimalModule, verbose) finally: setcontext(ORIGINAL_CONTEXT) From python-checkins at python.org Sat Jun 5 13:23:51 2010 From: python-checkins at python.org (stefan.krah) Date: Sat, 5 Jun 2010 13:23:51 +0200 (CEST) Subject: [Python-checkins] r81727 - python/branches/py3k-cdecimal/Lib/test/decimal_extended_tests/deccheck.py Message-ID: <20100605112351.D27A5EE9BF@mail.python.org> Author: stefan.krah Date: Sat Jun 5 13:23:51 2010 New Revision: 81727 Log: Add tests for contexts with small Emin/Emax, IEEE and random contexts. Modified: python/branches/py3k-cdecimal/Lib/test/decimal_extended_tests/deccheck.py Modified: python/branches/py3k-cdecimal/Lib/test/decimal_extended_tests/deccheck.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/test/decimal_extended_tests/deccheck.py (original) +++ python/branches/py3k-cdecimal/Lib/test/decimal_extended_tests/deccheck.py Sat Jun 5 13:23:51 2010 @@ -15,8 +15,11 @@ import cdecimal, decimal import sys, inspect -import platform +import array + from copy import copy +from randdec import * +from randfloat import * py_minor = sys.version_info[1] @@ -109,8 +112,7 @@ self.d.Emax = val def getround(self): - assert(self.f.rounding == self.d.rounding) - return self.f.rounding + return self.d.rounding def setround(self, val): self.f.rounding = val @@ -133,9 +135,9 @@ self.d._clamp = val prec = property(getprec, setprec) - emin = property(getemin, setemin) - emax = property(getemax, setemax) - round = property(getround, setround) + Emin = property(getemin, setemin) + Emax = property(getemax, setemax) + rounding = property(getround, setround) clamp = property(getclamp, setclamp) capitals = property(getcapitals, setcapitals) @@ -170,6 +172,8 @@ # We don't want exceptions so that we can compare the status flags. context = Context() +context.Emin = cdecimal.MIN_EMIN +context.Emax = cdecimal.MAX_EMAX context.clear_traps() # When creating decimals, cdecimal is ultimately limited by the maximum @@ -209,7 +213,7 @@ decimal: %s\n\n" class CdecException(ArithmeticError): - def __init__(self, result, funcname, operands): + def __init__(self, result, funcname, operands, fctxstr, dctxstr): self.errstring = "Error in %s(%s" % (funcname, operands[0]) for op in operands[1:]: self.errstring += ", %s" % op @@ -226,7 +230,7 @@ str(dec_tuple)) else: self.errstring += _exc_fmt_obj % (str(result[0]), str(result[1])) - self.errstring += "%s\n%s\n\n" % (str(context.f), str(context.d)) + self.errstring += "%s\n%s\n\n" % (fctxstr, dctxstr) def __str__(self): return self.errstring @@ -255,6 +259,32 @@ b = dec.next_minus() return abs(a - b) + def un_resolve_ulp(self, result, funcname, operands): + """Results of cdecimal's power function are currently not always + correctly rounded. Check if the cdecimal result differs by less + than 1 ULP from the correctly rounded decimal.py result.""" + mpdstr = str(result.mpd) + mpdresult = decimal.Decimal(mpdstr) + decresult = result.dec + deculp = self.ulp(decresult) + op = operands[0].dec + tmpctx = context.d.copy() + tmpctx.prec *= 2 + # result, recalculated at double precision + dpresult = getattr(op, funcname)(context=tmpctx) + mpddiff = abs(dpresult - mpdresult) + if mpddiff >= deculp: + print("deculp: %d dpresult: %s mpdresult: %s" % + (deculp, dpresult, mpdresult)) + return False # not simply a disagreement, but wrong + decdiff = abs(dpresult - decresult) + if decdiff >= deculp: + print("deculp: %d dpresult: %s mpdresult: %s" % + (deculp, dpresult, mpdresult)) + return False # not simply a disagreement, but wrong + self.ulpdiff += 1 + return True + def bin_resolve_ulp(self, result, funcname, operands): """Results of cdecimal's power function are currently not always correctly rounded. Check if the cdecimal result differs by less @@ -271,13 +301,29 @@ dpresult = getattr(op1, funcname)(op2, context=tmpctx) mpddiff = abs(dpresult - mpdresult) if mpddiff >= deculp: + print("deculp: %d dpresult: %s mpdresult: %s" % + (deculp, dpresult, mpdresult)) return False # not simply a disagreement, but wrong decdiff = abs(dpresult - decresult) if decdiff >= deculp: + print("deculp: %d dpresult: %s mpdresult: %s" % + (deculp, dpresult, mpdresult)) return False # not simply a disagreement, but wrong self.ulpdiff += 1 return True + def exp(self, result, operands): + if context.f.allcr: return False + return self.un_resolve_ulp(result, "exp", operands) + + def log10(self, result, operands): + if context.f.allcr: return False + return self.un_resolve_ulp(result, "log10", operands) + + def ln(self, result, operands): + if context.f.allcr: return False + return self.un_resolve_ulp(result, "ln", operands) + def __pow__(self, result, operands): """See DIFFERENCES.txt""" if operands[2] is not None: # three argument __pow__ @@ -342,19 +388,29 @@ def default(self, result, operands): return False - __ge__ = __gt__ = __le__ = __lt__ = __repr__ = __str__ = \ - __ne__ = __eq__ = default + __ge__ = __gt__ = __le__ = __lt__ = __repr__ = __str__ = default if py_minor >= 2: def __hash__(self, result, operands): - c = operands[0] - if c.mpd.is_infinite(): - # Hashing infinities changed in 3.2 + # New hashing scheme in r81486 is not yet implemented. + return True + __ne__ = __eq__ = default + + if py_minor <= 2: + # Actually <= 1, but this is quite recent in 3.2, so + # not all installed 3.2 versions have it. + def __eq__(self, result, operands): + """cdecimal raises for all sNaN comparisons""" + if operands[0].mpd.is_snan() or operands[1].mpd.is_snan(): return True - # If a Decimal instance is exactly representable as a float - # then (in 3.2) its hash matches that of the float. - f = float(c.dec) - if decimal.Decimal.from_float(f) == c.dec: + __ne__ = __eq__ + + if py_minor <= 1: + # Fixed in release31-maint, but a lot of distributed + # versions do not have the fix yet. + def is_normal(self, result, operands): + # Issue7099 + if operands[0].mpd.is_normal(): return True @@ -374,7 +430,8 @@ if result[0] != result[1] or not context.assert_eq_status(): if obj_known_disagreement(result, funcname, operands): return # skip known disagreements - raise CdecException(result, funcname, operands) + raise CdecException(result, funcname, operands, + str(context.f), str(context.d)) class cdec(object): @@ -416,7 +473,8 @@ or not context.assert_eq_status(): if cdec_known_disagreement(self, funcname, operands): return # skip known disagreements - raise CdecException(self, funcname, operands) + raise CdecException(self, funcname, operands, + str(context.f), str(context.d)) def unaryfunc(self, funcname): "unary function returning a cdec" @@ -437,7 +495,7 @@ return c def obj_unaryfunc(self, funcname): - "unary function returning a cdec" + "unary function returning an object other than a cdec" context.clear_status() r_mpd = getattr(self.mpd, funcname)() r_dec = getattr(self.dec, funcname)() @@ -834,11 +892,8 @@ if isinstance(third, cdec): third_mpd = third.mpd third_dec = third.dec - if (third is not None): - c.mpd = getattr(self.mpd, 'powmod')(other_mpd, third_mpd) - else: - c.mpd = getattr(self.mpd, 'pow')(other_mpd) - c.dec = getattr(context.d, 'power')(self.dec, other_dec, third_dec) + c.mpd = pow(self.mpd, other_mpd, third_mpd) + c.dec = pow(self.dec, other_dec, third_dec) c.verify('power', (self, other, third)) return c @@ -908,333 +963,363 @@ sys.stdout.write(''.join((str(fmt), '\n'))) sys.stdout.flush() -def test_unary(method, prec_lst, iter): +def test_method(method, testspecs, testfunc): log("testing %s ...", method) - for prec in prec_lst: - log(" prec: %d", prec) - context.prec = prec - for round in sorted(decround): - context.round = round - rprec = 10**prec - exprange = cdecimal.MAX_EMAX - if method in ['__int__', '__long__', '__trunc__', 'to_integral', \ - 'to_integral_value', 'to_integral_value']: - exprange = 9999 - for a in un_close_to_pow10(prec, exprange, iter): - try: - x = cdec(a) - getattr(x, method)() - except CdecException as err: - log(err) - for a in un_close_numbers(prec, exprange, -exprange, iter): - try: - x = cdec(a) - getattr(x, method)() - except CdecException as err: - log(err) - for a in un_incr_digits_tuple(prec, exprange, iter): - try: - x = cdec(a) - getattr(x, method)() - except CdecException as err: - log(err) - for i in range(1000): - try: - s = randdec(prec, exprange) - x = cdec(s) - getattr(x, method)() - except CdecException as err: - log(err) - except OverflowError: - pass - try: - s = randtuple(prec, exprange) - x = cdec(s) - getattr(x, method)() - except CdecException as err: - log(err) - except OverflowError: - pass + for spec in testspecs: + if 'samples' in spec: + spec['prec'] = sorted(random.sample(range(1, 101), spec['samples'])) + for prec in spec['prec']: + context.prec = prec + for expts in spec['expts']: + emin, emax = expts + if emin == 'rand': + context.Emin = random.randrange(-1000, 0) + context.Emax = random.randrange(prec, 1000) + else: + context.Emin, context.Emax = emin, emax + if prec > context.Emax: continue + log(" prec: %d emin: %d emax: %d", + (context.prec, context.Emin, context.Emax)) + restr_range = 9999 if context.Emax > 9999 else context.Emax+99 + for rounding in sorted(decround): + context.rounding = rounding + context.capitals = random.randrange(2) + if spec['clamp'] == 2: + context.clamp = random.randrange(2) + else: + context.clamp = spec['clamp'] + exprange = context.f.Emax + testfunc(method, prec, exprange, restr_range, spec['iter']) + +def test_unary(method, prec, exprange, restr_range, iter): + if method in ['__int__', '__long__', '__trunc__', 'to_integral', + 'to_integral_value', 'to_integral_value']: + exprange = restr_range + for a in un_close_to_pow10(prec, exprange, iter): + try: + x = cdec(a) + getattr(x, method)() + except CdecException as err: + log(err) + for a in un_close_numbers(prec, exprange, -exprange, iter): + try: + x = cdec(a) + getattr(x, method)() + except CdecException as err: + log(err) + for a in un_incr_digits_tuple(prec, exprange, iter): + try: + x = cdec(a) + getattr(x, method)() + except CdecException as err: + log(err) + for a in un_randfloat(): + try: + x = cdec(a) + getattr(x, method)() + except CdecException as err: + log(err) + for i in range(1000): + try: + s = randdec(prec, exprange) + x = cdec(s) + getattr(x, method)() + except CdecException as err: + log(err) + except OverflowError: + pass + try: + s = randtuple(prec, exprange) + x = cdec(s) + getattr(x, method)() + except CdecException as err: + log(err) + except OverflowError: + pass -def test_un_logical(method, prec_lst, iter): - log("testing %s ...", method) - for prec in prec_lst: - log(" prec: %d", prec) - context.prec = prec - for round in sorted(decround): - context.round = round - for a in logical_un_incr_digits(prec, iter): - try: - x = cdec(a) - getattr(x, method)() - except CdecException as err: - log(err) - for i in range(1000): - try: - s = randdec(prec, 999999) - x = cdec(s) - getattr(x, method)() - except CdecException as err: - log(err) - except OverflowError: - pass +def test_un_logical(method, prec, exprange, restr_range, iter): + for a in logical_un_incr_digits(prec, iter): + try: + x = cdec(a) + getattr(x, method)() + except CdecException as err: + log(err) + for i in range(1000): + try: + s = randdec(prec, restr_range) + x = cdec(s) + getattr(x, method)() + except CdecException as err: + log(err) + except OverflowError: + pass + +def test_binary(method, prec, exprange, restr_range, iter): + if method in ['__pow__', '__rpow__', 'power']: + exprange = restr_range + for a, b in bin_close_to_pow10(prec, exprange, iter): + try: + x = cdec(a) + y = cdec(b) + getattr(x, method)(y) + except CdecException as err: + log(err) + for a, b in bin_close_numbers(prec, exprange, -exprange, iter): + try: + x = cdec(a) + y = cdec(b) + getattr(x, method)(y) + except CdecException as err: + log(err) + for a, b in bin_incr_digits(prec, exprange, iter): + try: + x = cdec(a) + y = cdec(b) + getattr(x, method)(y) + except CdecException as err: + log(err) + for a, b in bin_randfloat(): + try: + x = cdec(a) + y = cdec(b) + getattr(x, method)(y) + except CdecException as err: + log(err) + for i in range(1000): + s1 = randdec(prec, exprange) + s2 = randdec(prec, exprange) + try: + x = cdec(s1) + y = cdec(s2) + getattr(x, method)(y) + except CdecException as err: + log(err) -def test_binary(method, prec_lst, iter): - log("testing %s ...", method) - for prec in prec_lst: - log(" prec: %d", prec) - context.prec = prec - for round in sorted(decround): - context.round = round - exprange = cdecimal.MAX_EMAX - if method in ['__pow__', '__rpow__', 'power']: - exprange = 99999 - for a, b in bin_close_to_pow10(prec, exprange, iter): - try: - x = cdec(a) - y = cdec(b) - getattr(x, method)(y) - except CdecException as err: - log(err) - for a, b in bin_close_numbers(prec, exprange, -exprange, iter): - try: - x = cdec(a) - y = cdec(b) - getattr(x, method)(y) - except CdecException as err: - log(err) - for a, b in bin_incr_digits(prec, exprange, iter): - try: - x = cdec(a) - y = cdec(b) - getattr(x, method)(y) - except CdecException as err: - log(err) - for i in range(1000): - s1 = randdec(prec, exprange) - s2 = randdec(prec, exprange) - try: - x = cdec(s1) - y = cdec(s2) - getattr(x, method)(y) - except CdecException as err: - log(err) +def test_bin_logical(method, prec, exprange, restr_range, iter): + for a, b in logical_bin_incr_digits(prec, iter): + try: + x = cdec(a) + y = cdec(b) + getattr(x, method)(y) + except CdecException as err: + log(err) + for i in range(1000): + s1 = randdec(prec, restr_range) + s2 = randdec(prec, restr_range) + try: + x = cdec(s1) + y = cdec(s2) + getattr(x, method)(y) + except CdecException as err: + log(err) + +def test_ternary(method, prec, exprange, restr_range, iter): + if method in ['__pow__', 'power']: + exprange = restr_range + for a, b, c in tern_close_numbers(prec, exprange, -exprange, iter): + try: + x = cdec(a) + y = cdec(b) + z = cdec(c) + getattr(x, method)(y, z) + except CdecException as err: + log(err) + for a, b, c in tern_incr_digits(prec, exprange, iter): + try: + x = cdec(a) + y = cdec(b) + z = cdec(c) + getattr(x, method)(y, z) + except CdecException as err: + log(err) + for a, b, c in tern_randfloat(): + try: + x = cdec(a) + y = cdec(b) + z = cdec(c) + getattr(x, method)(y, z) + except CdecException as err: + log(err) + for i in range(1000): + s1 = randdec(prec, 2*exprange) + s2 = randdec(prec, 2*exprange) + s3 = randdec(prec, 2*exprange) + try: + x = cdec(s1) + y = cdec(s2) + z = cdec(s3) + getattr(x, method)(y, z) + except CdecException as err: + log(err) -def test_bin_logical(method, prec_lst, iter): - log("testing %s ...", method) - for prec in prec_lst: - log(" prec: %d", prec) - context.prec = prec - for round in sorted(decround): - context.round = round - for a, b in logical_bin_incr_digits(prec, iter): - try: - x = cdec(a) - y = cdec(b) - getattr(x, method)(y) - except CdecException as err: - log(err) - for i in range(1000): - s1 = randdec(prec, 999999) - s2 = randdec(prec, 999999) - try: - x = cdec(s1) - y = cdec(s2) - getattr(x, method)(y) - except CdecException as err: - log(err) +def test_format(method, prec, exprange, restr_range, iter): + for a in un_incr_digits_tuple(prec, restr_range, iter): + context.clear_status() + try: + fmt = rand_format(chr(random.randrange(32, 128))) + x = format(context.f.create_decimal(a), fmt) + y = format(context.d.create_decimal(a), fmt) + except Exception as err: + print(err, fmt) + continue + if x != y: + print(context.f) + print(context.d) + print("\n%s %s" % (a, fmt)) + print("%s %s\n" % (x, y)) + for i in range(1000): + context.clear_status() + try: + a = randdec(99, 9999) + fmt = rand_format(chr(random.randrange(32, 128))) + x = format(context.f.create_decimal(a), fmt) + y = format(context.d.create_decimal(a), fmt) + except Exception as err: + print(err, fmt) + continue + if x != y: + print(context.f) + print(context.d) + print("\n%s %s" % (a, fmt)) + print("%s %s\n" % (x, y)) -def test_ternary(method, prec_lst, iter): - log("testing %s ...", method) - for prec in prec_lst: - log(" prec: %d", prec) - context.prec = prec - for round in sorted(decround): - context.round = round - exprange = cdecimal.MAX_EMAX - if method in ['__pow__', 'power']: - exprange = 99999 - for a, b, c in tern_close_numbers(prec, exprange, -exprange, iter): - try: - x = cdec(a) - y = cdec(b) - z = cdec(c) - getattr(x, method)(y, z) - except CdecException as err: - log(err) - for a, b, c in tern_incr_digits(prec, exprange, iter): - try: - x = cdec(a) - y = cdec(b) - z = cdec(c) - getattr(x, method)(y, z) - except CdecException as err: - log(err) - for i in range(1000): - s1 = randdec(prec, 2*exprange) - s2 = randdec(prec, 2*exprange) - s3 = randdec(prec, 2*exprange) - try: - x = cdec(s1) - y = cdec(s2) - z = cdec(s3) - getattr(x, method)(y, z) - except CdecException as err: - log(err) - -def test_format(prec_lst, iter): - log("testing format") - for prec in prec_lst: - log(" prec: %d", prec) - context.prec = prec - for round in sorted(decround): - context.round = round - for a in un_incr_digits_tuple(prec, 9999, iter): - try: - fmt = rand_format(chr(random.randrange(32, 128))) - x = format(context.f.create_decimal(a), fmt) - y = format(context.d.create_decimal(a), fmt) - except Exception as err: - print(err, fmt) - continue - if x != y: - print(context.f) - print(context.d) - print("\n%s %s" % (a, fmt)) - print("%s %s\n" % (x, y)) - for i in range(1000): - try: - a = randdec(99, 9999) - fmt = rand_format(chr(random.randrange(32, 128))) - x = format(context.f.create_decimal(a), fmt) - y = format(context.d.create_decimal(a), fmt) - except Exception as err: - print(err, fmt) - continue - if x != y: - print(context.f) - print(context.d) - print("\n%s %s" % (a, fmt)) - print("%s %s\n" % (x, y)) - -def test_locale(prec_lst, iter): - import array - log("testing locale") - for prec in prec_lst: - log(" prec: %d", prec) - context.prec = prec - for round in sorted(decround): - context.round = round - for a in un_incr_digits_tuple(prec, 9999, iter): - try: - fmt = rand_locale() - x = format(context.f.create_decimal(a), fmt) - y = format(context.d.create_decimal(a), fmt) - except Exception as err: - print(err, fmt) - continue - if x != y: - print(context.f) - print(context.d) - print(locale.setlocale(locale.LC_NUMERIC)) - print("%s %s" % (a, fmt)) - print(list(array.array('u', x))) - print(list(array.array('u', y))) - for i in range(1000): - try: - a = randdec(99, 9999) - fmt = rand_locale() - x = format(context.f.create_decimal(a), fmt) - y = format(context.d.create_decimal(a), fmt) - except Exception as err: - print(err, fmt) - continue - if x != y: - print(context.f) - print(context.d) - print(locale.setlocale(locale.LC_NUMERIC)) - print("%s %s" % (a, fmt)) - print(list(array.array('u', x))) - print(list(array.array('u', y))) - -def test_round(prec_lst, iter): - log("testing round") - for prec in prec_lst: - log(" prec: %d", prec) - context.prec = 99 - for round in sorted(decround): - context.round = round - for a in un_incr_digits_tuple(prec, 9999, 1): - try: - n = random.randrange(10) - x = (context.f.create_decimal(a)).__round__(n) - y = (context.d.create_decimal(a)).__round__(n) - except Exception as err: - print(err) - continue - if str(x) != str(y): - print(context.f) - print(context.d) - print("\n%s %s" % (a, n)) - print("%s %s\n" % (x, y)) - exit(1) - for i in range(1000): - try: - a = randdec(99, 9999) - n = random.randrange(10) - x = context.f.create_decimal(a).__round__(n) - y = context.d.create_decimal(a).__round__(n) - except Exception as err: - print(err) - continue - if str(x) != str(y): - print(context.f) - print(context.d) - print("\n%s %s" % (a, n)) - print("%s %s\n" % (x, y)) - -def test_from_float(prec_lst): - log("testing from_float ...") - for prec in prec_lst: - log(" prec: %d", prec) - context.prec = prec - for round in sorted(decround): - context.round = round - exprange = 384 - for i in range(1000): - intpart = str(random.randrange(100000000000000000000000000000000000000)) - fracpart = str(random.randrange(100000000000000000000000000000000000000)) - exp = str(random.randrange(-384, 384)) - fstring = intpart + '.' + fracpart + 'e' + exp - f = float(fstring) - try: - c = cdec(f) - except CdecException as err: - log(err) +def test_locale(method, prec, exprange, restr_range, iter): + for a in un_incr_digits_tuple(prec, restr_range, iter): + context.clear_status() + try: + fmt = rand_locale() + x = format(context.f.create_decimal(a), fmt) + y = format(context.d.create_decimal(a), fmt) + except Exception as err: + print(err, fmt) + continue + if x != y: + print(context.f) + print(context.d) + print(locale.setlocale(locale.LC_NUMERIC)) + print("%s %s" % (a, fmt)) + print(list(array.array('u', x))) + print(list(array.array('u', y))) + for i in range(1000): + context.clear_status() + try: + a = randdec(99, 9999) + fmt = rand_locale() + x = format(context.f.create_decimal(a), fmt) + y = format(context.d.create_decimal(a), fmt) + except Exception as err: + print(err, fmt) + continue + if x != y: + print(context.f) + print(context.d) + print(locale.setlocale(locale.LC_NUMERIC)) + print("%s %s" % (a, fmt)) + print(list(array.array('u', x))) + print(list(array.array('u', y))) + +def test_round(method, prec, exprange, restr_range, iter): + for a in un_incr_digits_tuple(prec, restr_range, 1): + context.clear_status() + try: + n = random.randrange(10) + x = (context.f.create_decimal(a)).__round__(n) + y = (context.d.create_decimal(a)).__round__(n) + except Exception as err: + print(err) + continue + if str(x) != str(y): + print(context.f) + print(context.d) + print("\n%s %s" % (a, n)) + print("%s %s\n" % (x, y)) + exit(1) + for i in range(1000): + context.clear_status() + try: + a = randdec(99, 9999) + n = random.randrange(10) + x = context.f.create_decimal(a).__round__(n) + y = context.d.create_decimal(a).__round__(n) + except Exception as err: + print(err) + continue + if str(x) != str(y): + print(context.f) + print(context.d) + print("\n%s %s" % (a, n)) + print("%s %s\n" % (x, y)) + +def test_from_float(method, prec, exprange, restr_range, iter): + for rounding in sorted(decround): + context.rounding = rounding + exprange = 384 + for i in range(1000): + intpart = str(random.randrange(100000000000000000000000000000000000000)) + fracpart = str(random.randrange(100000000000000000000000000000000000000)) + exp = str(random.randrange(-384, 384)) + fstring = intpart + '.' + fracpart + 'e' + exp + f = float(fstring) + try: + c = cdec(f) + except CdecException as err: + log(err) if __name__ == '__main__': - from randdec import * import time - import sys - - samples = 1 - iter = 1 + randseed = int(time.time()) + random.seed(randseed) - if '--short' in sys.argv: - samples = 1 - iter = 1 - elif '--medium' in sys.argv: - samples = 1 - iter = None - elif '--long' in sys.argv: - samples = 5 - iter = None + base_expts = [(cdecimal.MIN_EMIN, cdecimal.MAX_EMAX)] + if cdecimal.MAX_EMAX == 999999999999999999: + base_expts.append((-999999999, 999999999)) + + base = { + 'name': 'base', + 'expts': base_expts, + 'prec': [], + 'clamp': 2, + 'iter': None, + 'samples': None, + } + small = { + 'name': 'small', + 'prec': [1, 2, 3, 4, 5], + 'expts': [(-1,1), (-2,2), (-3,3), (-4,4), (-5,5)], + 'clamp': 2, + 'iter': None + } + ieee = [ + {'name': 'decimal32', 'prec': [7], 'expts': [(-95, 96)], 'clamp': 1, 'iter': None}, + {'name': 'decimal64', 'prec': [16], 'expts': [(-383, 384)], 'clamp': 1, 'iter': None}, + {'name': 'decimal128', 'prec': [34], 'expts': [(-6143, 6144)], 'clamp': 1, 'iter': None} + ] + + if '--medium' in sys.argv: + base['expts'].append(('rand', 'rand')) + base['samples'] = None + testspecs = [small, ieee, base] + if '--long' in sys.argv: + base['expts'].append(('rand', 'rand')) + base['samples'] = 5 + testspecs = [small, ieee, base] elif '--all' in sys.argv: - samples = 100 - iter = None + base['expts'].append(('rand', 'rand')) + base['samples'] = 100 + testspecs = [small, ieee, base] + else: # --short + rand_ieee = random.choice(ieee) + base['iter'] = small['iter'] = rand_ieee['iter'] = 1 + base['samples'] = 1 + base['expts'] = [random.choice(base_expts)] + prec = random.randrange(1, 6) + small['prec'] = [prec] + small['expts'] = [(-prec, prec)] + testspecs = [small, rand_ieee, base] + all_decimal_methods = set(dir(cdecimal.Decimal) + dir(decimal.Decimal)) all_cdec_methods = [m for m in dir(cdec) if m in all_decimal_methods] @@ -1273,37 +1358,30 @@ ternary_methods.sort() - x = int(time.time()) - random.seed(x) - log("\nRandom seed: %d\n\n", x) + log("\nRandom seed: %d\n\n", randseed) log("Skipping tests: \n\n%s\n", untested_methods) for method in unary_methods: - prec_lst = sorted(random.sample(range(1, 101), samples)) - test_unary(method, prec_lst, iter) + test_method(method, testspecs, test_unary) for method in binary_methods: - prec_lst = sorted(random.sample(range(1, 101), samples)) - test_binary(method, prec_lst, iter) + test_method(method, testspecs, test_binary) for method in ternary_methods: - prec_lst = sorted(random.sample(range(1, 101), samples)) - test_ternary(method, prec_lst, iter) + test_method(method, testspecs, test_ternary) - prec_lst = sorted(random.sample(range(1, 101), samples)) - test_un_logical('logical_invert', prec_lst, iter) + test_method('logical_invert', testspecs, test_un_logical) for method in ['logical_and', 'logical_or', 'logical_xor']: - prec_lst = sorted(random.sample(range(1, 101), samples)) - test_bin_logical(method, prec_lst, iter) + test_method(method, testspecs, test_bin_logical) + if py_minor >= 2: # Some tests will fail with 3.1, since alignment has been changed # in decimal.py 3.2. from genlocale import * - prec_lst = sorted(random.sample(range(1, 101), samples)) - test_format(prec_lst, iter) - test_locale(prec_lst, iter) - test_round(prec_lst, iter) - test_from_float(prec_lst) + test_method('format', testspecs, test_format) + test_method('locale', testspecs, test_locale) + test_method('round', testspecs, test_round) + test_method('from_float', testspecs, test_from_float) From python-checkins at python.org Sat Jun 5 13:23:51 2010 From: python-checkins at python.org (michael.foord) Date: Sat, 5 Jun 2010 13:23:51 +0200 (CEST) Subject: [Python-checkins] r81728 - in python/trunk/Lib/unittest: case.py test/test_case.py Message-ID: <20100605112351.DE8DCEE9DB@mail.python.org> Author: michael.foord Date: Sat Jun 5 13:23:51 2010 New Revision: 81728 Log: Issue 8351. Suppress large diffs in unittest.TestCase.assertSequenceEqual. Modified: python/trunk/Lib/unittest/case.py python/trunk/Lib/unittest/test/test_case.py Modified: python/trunk/Lib/unittest/case.py ============================================================================== --- python/trunk/Lib/unittest/case.py (original) +++ python/trunk/Lib/unittest/case.py Sat Jun 5 13:23:51 2010 @@ -13,7 +13,7 @@ ) __unittest = True - +TRUNCATED_DIFF = '\n[diff truncated...]' class SkipTest(Exception): """ @@ -589,7 +589,8 @@ failUnlessRaises = _deprecate(assertRaises) failIf = _deprecate(assertFalse) - def assertSequenceEqual(self, seq1, seq2, msg=None, seq_type=None): + def assertSequenceEqual(self, seq1, seq2, msg=None, seq_type=None, + max_diff=80*8): """An equality assertion for ordered sequences (like lists and tuples). For the purposes of this function, a valid ordered sequence type is one @@ -602,6 +603,7 @@ datatype should be enforced. msg: Optional message to use on failure instead of a list of differences. + max_diff: Maximum size off the diff, larger diffs are not shown """ if seq_type is not None: seq_type_name = seq_type.__name__ @@ -684,9 +686,14 @@ except (TypeError, IndexError, NotImplementedError): differing += ('Unable to index element %d ' 'of second %s\n' % (len1, seq_type_name)) - standardMsg = differing + '\n' + '\n'.join( + standardMsg = differing + diffMsg = '\n' + '\n'.join( difflib.ndiff(pprint.pformat(seq1).splitlines(), pprint.pformat(seq2).splitlines())) + if max_diff is None or len(diffMsg) <= max_diff: + standardMsg += diffMsg + else: + standardMsg += diffMsg[:max_diff] + TRUNCATED_DIFF msg = self._formatMessage(msg, standardMsg) self.fail(msg) Modified: python/trunk/Lib/unittest/test/test_case.py ============================================================================== --- python/trunk/Lib/unittest/test/test_case.py (original) +++ python/trunk/Lib/unittest/test/test_case.py Sat Jun 5 13:23:51 2010 @@ -1,3 +1,5 @@ +import difflib +import pprint import re import sys @@ -588,6 +590,23 @@ self.assertRaises(self.failureException, self.assertDictEqual, [], d) self.assertRaises(self.failureException, self.assertDictEqual, 1, 1) + def testAssertSequenceEqualMaxDiff(self): + seq1 = 'a' + 'x' * 80**2 + seq2 = 'b' + 'x' * 80**2 + diff = '\n'.join(difflib.ndiff(pprint.pformat(seq1).splitlines(), + pprint.pformat(seq2).splitlines())) + try: + self.assertSequenceEqual(seq1, seq2, max_diff=len(diff)/2) + except AssertionError as e: + msg = e.args[0] + self.assertTrue(len(msg) < len(diff)) + + try: + self.assertSequenceEqual(seq1, seq2, max_diff=len(diff)*2) + except AssertionError as e: + msg = e.args[0] + self.assertTrue(len(msg) > len(diff)) + def testAssertItemsEqual(self): a = object() self.assertItemsEqual([1, 2, 3], [3, 2, 1]) From python-checkins at python.org Sat Jun 5 13:26:24 2010 From: python-checkins at python.org (stefan.krah) Date: Sat, 5 Jun 2010 13:26:24 +0200 (CEST) Subject: [Python-checkins] r81729 - python/branches/py3k-cdecimal/Lib/test/decimal_extended_tests/randfloat.py Message-ID: <20100605112624.2FAFAEE9F4@mail.python.org> Author: stefan.krah Date: Sat Jun 5 13:26:23 2010 New Revision: 81729 Log: Add more random tests. Added: python/branches/py3k-cdecimal/Lib/test/decimal_extended_tests/randfloat.py (contents, props changed) Added: python/branches/py3k-cdecimal/Lib/test/decimal_extended_tests/randfloat.py ============================================================================== --- (empty file) +++ python/branches/py3k-cdecimal/Lib/test/decimal_extended_tests/randfloat.py Sat Jun 5 13:26:23 2010 @@ -0,0 +1,250 @@ +# Copyright (c) 2010 Python Software Foundation. All Rights Reserved. +# Adapted from Python's Lib/test/test_strtod.py (by Mark Dickinson) + +# Tests for the correctly-rounded string -> float conversions +# introduced in Python 2.7 and 3.1. + +import random + +TEST_SIZE = 16 + + +def test_short_halfway_cases(): + # exact halfway cases with a small number of significant digits + for k in 0, 5, 10, 15, 20: + # upper = smallest integer >= 2**54/5**k + upper = -(-2**54//5**k) + # lower = smallest odd number >= 2**53/5**k + lower = -(-2**53//5**k) + if lower % 2 == 0: + lower += 1 + for i in range(10 * TEST_SIZE): + # Select a random odd n in [2**53/5**k, + # 2**54/5**k). Then n * 10**k gives a halfway case + # with small number of significant digits. + n, e = random.randrange(lower, upper, 2), k + + # Remove any additional powers of 5. + while n % 5 == 0: + n, e = n // 5, e + 1 + assert n % 10 in (1, 3, 7, 9) + + # Try numbers of the form n * 2**p2 * 10**e, p2 >= 0, + # until n * 2**p2 has more than 20 significant digits. + digits, exponent = n, e + while digits < 10**20: + s = '{}e{}'.format(digits, exponent) + yield s + # Same again, but with extra trailing zeros. + s = '{}e{}'.format(digits * 10**40, exponent - 40) + yield s + digits *= 2 + + # Try numbers of the form n * 5**p2 * 10**(e - p5), p5 + # >= 0, with n * 5**p5 < 10**20. + digits, exponent = n, e + while digits < 10**20: + s = '{}e{}'.format(digits, exponent) + yield s + # Same again, but with extra trailing zeros. + s = '{}e{}'.format(digits * 10**40, exponent - 40) + yield s + digits *= 5 + exponent -= 1 + +def test_halfway_cases(): + # test halfway cases for the round-half-to-even rule + for i in range(1000): + for j in range(TEST_SIZE): + # bit pattern for a random finite positive (or +0.0) float + bits = random.randrange(2047*2**52) + + # convert bit pattern to a number of the form m * 2**e + e, m = divmod(bits, 2**52) + if e: + m, e = m + 2**52, e - 1 + e -= 1074 + + # add 0.5 ulps + m, e = 2*m + 1, e - 1 + + # convert to a decimal string + if e >= 0: + digits = m << e + exponent = 0 + else: + # m * 2**e = (m * 5**-e) * 10**e + digits = m * 5**-e + exponent = e + s = '{}e{}'.format(digits, exponent) + yield s + +def test_boundaries(): + # boundaries expressed as triples (n, e, u), where + # n*10**e is an approximation to the boundary value and + # u*10**e is 1ulp + boundaries = [ + (10000000000000000000, -19, 1110), # a power of 2 boundary (1.0) + (17976931348623159077, 289, 1995), # overflow boundary (2.**1024) + (22250738585072013831, -327, 4941), # normal/subnormal (2.**-1022) + (0, -327, 4941), # zero + ] + for n, e, u in boundaries: + for j in range(1000): + for i in range(TEST_SIZE): + digits = n + random.randrange(-3*u, 3*u) + exponent = e + s = '{}e{}'.format(digits, exponent) + yield s + n *= 10 + u *= 10 + e -= 1 + +def test_underflow_boundary(): + # test values close to 2**-1075, the underflow boundary; similar + # to boundary_tests, except that the random error doesn't scale + # with n + for exponent in range(-400, -320): + base = 10**-exponent // 2**1075 + for j in range(TEST_SIZE): + digits = base + random.randrange(-1000, 1000) + s = '{}e{}'.format(digits, exponent) + yield s + +def test_bigcomp(): + for ndigs in 5, 10, 14, 15, 16, 17, 18, 19, 20, 40, 41, 50: + dig10 = 10**ndigs + for i in range(100 * TEST_SIZE): + digits = random.randrange(dig10) + exponent = random.randrange(-400, 400) + s = '{}e{}'.format(digits, exponent) + yield s + +def test_parsing(): + # make '0' more likely to be chosen than other digits + digits = '000000123456789' + signs = ('+', '-', '') + + # put together random short valid strings + # \d*[.\d*]?e + for i in range(1000): + for j in range(TEST_SIZE): + s = random.choice(signs) + intpart_len = random.randrange(5) + s += ''.join(random.choice(digits) for _ in range(intpart_len)) + if random.choice([True, False]): + s += '.' + fracpart_len = random.randrange(5) + s += ''.join(random.choice(digits) + for _ in range(fracpart_len)) + else: + fracpart_len = 0 + if random.choice([True, False]): + s += random.choice(['e', 'E']) + s += random.choice(signs) + exponent_len = random.randrange(1, 4) + s += ''.join(random.choice(digits) + for _ in range(exponent_len)) + + if intpart_len + fracpart_len: + yield s + +test_particular = [ + # squares + '1.00000000100000000025', + '1.0000000000000000000000000100000000000000000000000' #... + '00025', + '1.0000000000000000000000000000000000000000000010000' #... + '0000000000000000000000000000000000000000025', + '1.0000000000000000000000000000000000000000000000000' #... + '000001000000000000000000000000000000000000000000000' #... + '000000000025', + '0.99999999900000000025', + '0.9999999999999999999999999999999999999999999999999' #... + '999000000000000000000000000000000000000000000000000' #... + '000025', + '0.9999999999999999999999999999999999999999999999999' #... + '999999999999999999999999999999999999999999999999999' #... + '999999999999999999999999999999999999999990000000000' #... + '000000000000000000000000000000000000000000000000000' #... + '000000000000000000000000000000000000000000000000000' #... + '0000000000000000000000000000025', + + '1.0000000000000000000000000000000000000000000000000' #... + '000000000000000000000000000000000000000000000000000' #... + '100000000000000000000000000000000000000000000000000' #... + '000000000000000000000000000000000000000000000000001', + '1.0000000000000000000000000000000000000000000000000' #... + '000000000000000000000000000000000000000000000000000' #... + '500000000000000000000000000000000000000000000000000' #... + '000000000000000000000000000000000000000000000000005', + '1.0000000000000000000000000000000000000000000000000' #... + '000000000100000000000000000000000000000000000000000' #... + '000000000000000000250000000000000002000000000000000' #... + '000000000000000000000000000000000000000000010000000' #... + '000000000000000000000000000000000000000000000000000' #... + '0000000000000000001', + '1.0000000000000000000000000000000000000000000000000' #... + '000000000100000000000000000000000000000000000000000' #... + '000000000000000000249999999999999999999999999999999' #... + '999999999999979999999999999999999999999999999999999' #... + '999999999999999999999900000000000000000000000000000' #... + '000000000000000000000000000000000000000000000000000' #... + '00000000000000000000000001', + + '0.9999999999999999999999999999999999999999999999999' #... + '999999999900000000000000000000000000000000000000000' #... + '000000000000000000249999999999999998000000000000000' #... + '000000000000000000000000000000000000000000010000000' #... + '000000000000000000000000000000000000000000000000000' #... + '0000000000000000001', + '0.9999999999999999999999999999999999999999999999999' #... + '999999999900000000000000000000000000000000000000000' #... + '000000000000000000250000001999999999999999999999999' #... + '999999999999999999999999999999999990000000000000000' #... + '000000000000000000000000000000000000000000000000000' #... + '1', + ] + + +TESTCASES = [ + [x for x in test_short_halfway_cases()], + [x for x in test_halfway_cases()], + [x for x in test_boundaries()], + [x for x in test_underflow_boundary()], + [x for x in test_bigcomp()], + [x for x in test_parsing()], + test_particular +] + +def un_randfloat(): + for i in range(1000): + l = random.choice(TESTCASES[:6]) + yield random.choice(l) + for v in test_particular: + yield v + +def bin_randfloat(): + for i in range(1000): + l1 = random.choice(TESTCASES) + l2 = random.choice(TESTCASES) + yield random.choice(l1), random.choice(l2) + +def tern_randfloat(): + for i in range(1000): + l1 = random.choice(TESTCASES) + l2 = random.choice(TESTCASES) + l3 = random.choice(TESTCASES) + yield random.choice(l1), random.choice(l2), random.choice(l3) + + +if __name__ == '__main__': + + for s in un_randfloat(): + print(s) + + for s in bin_randfloat(): + print(s) + + for s in tern_randfloat(): + print(s) From python-checkins at python.org Sat Jun 5 13:27:52 2010 From: python-checkins at python.org (michael.foord) Date: Sat, 5 Jun 2010 13:27:52 +0200 (CEST) Subject: [Python-checkins] r81730 - in python/branches/py3k: Lib/unittest/case.py Lib/unittest/test/test_case.py Message-ID: <20100605112752.DD66DEE9C7@mail.python.org> Author: michael.foord Date: Sat Jun 5 13:27:52 2010 New Revision: 81730 Log: Merged revisions 81728 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81728 | michael.foord | 2010-06-05 12:23:51 +0100 (Sat, 05 Jun 2010) | 1 line Issue 8351. Suppress large diffs in unittest.TestCase.assertSequenceEqual. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/unittest/case.py python/branches/py3k/Lib/unittest/test/test_case.py Modified: python/branches/py3k/Lib/unittest/case.py ============================================================================== --- python/branches/py3k/Lib/unittest/case.py (original) +++ python/branches/py3k/Lib/unittest/case.py Sat Jun 5 13:27:52 2010 @@ -12,7 +12,7 @@ unorderable_list_difference) __unittest = True - +TRUNCATED_DIFF = '\n[diff truncated...]' class SkipTest(Exception): """ @@ -599,7 +599,8 @@ failUnlessRaises = _deprecate(assertRaises) failIf = _deprecate(assertFalse) - def assertSequenceEqual(self, seq1, seq2, msg=None, seq_type=None): + def assertSequenceEqual(self, seq1, seq2, msg=None, seq_type=None, + max_diff=80*8): """An equality assertion for ordered sequences (like lists and tuples). For the purposes of this function, a valid ordered sequence type is one @@ -612,6 +613,7 @@ datatype should be enforced. msg: Optional message to use on failure instead of a list of differences. + max_diff: Maximum size off the diff, larger diffs are not shown """ if seq_type != None: seq_type_name = seq_type.__name__ @@ -694,9 +696,14 @@ except (TypeError, IndexError, NotImplementedError): differing += ('Unable to index element %d ' 'of second %s\n' % (len1, seq_type_name)) - standardMsg = differing + '\n' + '\n'.join( + standardMsg = differing + diffMsg = '\n' + '\n'.join( difflib.ndiff(pprint.pformat(seq1).splitlines(), pprint.pformat(seq2).splitlines())) + if max_diff is None or len(diffMsg) <= max_diff: + standardMsg += diffMsg + else: + standardMsg += diffMsg[:max_diff] + TRUNCATED_DIFF msg = self._formatMessage(msg, standardMsg) self.fail(msg) Modified: python/branches/py3k/Lib/unittest/test/test_case.py ============================================================================== --- python/branches/py3k/Lib/unittest/test/test_case.py (original) +++ python/branches/py3k/Lib/unittest/test/test_case.py Sat Jun 5 13:27:52 2010 @@ -1,3 +1,5 @@ +import difflib +import pprint import re import sys @@ -589,6 +591,23 @@ self.assertRaises(self.failureException, self.assertDictEqual, [], d) self.assertRaises(self.failureException, self.assertDictEqual, 1, 1) + def testAssertSequenceEqualMaxDiff(self): + seq1 = 'a' + 'x' * 80**2 + seq2 = 'b' + 'x' * 80**2 + diff = '\n'.join(difflib.ndiff(pprint.pformat(seq1).splitlines(), + pprint.pformat(seq2).splitlines())) + try: + self.assertSequenceEqual(seq1, seq2, max_diff=len(diff)/2) + except AssertionError as e: + msg = e.args[0] + self.assertTrue(len(msg) < len(diff)) + + try: + self.assertSequenceEqual(seq1, seq2, max_diff=len(diff)*2) + except AssertionError as e: + msg = e.args[0] + self.assertTrue(len(msg) > len(diff)) + def testAssertItemsEqual(self): a = object() self.assertItemsEqual([1, 2, 3], [3, 2, 1]) From python-checkins at python.org Sat Jun 5 13:30:23 2010 From: python-checkins at python.org (michael.foord) Date: Sat, 5 Jun 2010 13:30:23 +0200 (CEST) Subject: [Python-checkins] r81731 - python/branches/py3k/Lib/unittest/test/test_case.py Message-ID: <20100605113023.707EFEED81@mail.python.org> Author: michael.foord Date: Sat Jun 5 13:30:23 2010 New Revision: 81731 Log: Test fix to use floor division. Correction from merge in previous commit. Modified: python/branches/py3k/Lib/unittest/test/test_case.py Modified: python/branches/py3k/Lib/unittest/test/test_case.py ============================================================================== --- python/branches/py3k/Lib/unittest/test/test_case.py (original) +++ python/branches/py3k/Lib/unittest/test/test_case.py Sat Jun 5 13:30:23 2010 @@ -597,7 +597,7 @@ diff = '\n'.join(difflib.ndiff(pprint.pformat(seq1).splitlines(), pprint.pformat(seq2).splitlines())) try: - self.assertSequenceEqual(seq1, seq2, max_diff=len(diff)/2) + self.assertSequenceEqual(seq1, seq2, max_diff=len(diff)//2) except AssertionError as e: msg = e.args[0] self.assertTrue(len(msg) < len(diff)) From python-checkins at python.org Sat Jun 5 13:33:09 2010 From: python-checkins at python.org (stefan.krah) Date: Sat, 5 Jun 2010 13:33:09 +0200 (CEST) Subject: [Python-checkins] r81732 - python/branches/py3k-cdecimal/Lib/test/decimal_extended_tests/genlocale.py Message-ID: <20100605113309.2E71BEEDCF@mail.python.org> Author: stefan.krah Date: Sat Jun 5 13:33:09 2010 New Revision: 81732 Log: randint() signature changed Modified: python/branches/py3k-cdecimal/Lib/test/decimal_extended_tests/genlocale.py Modified: python/branches/py3k-cdecimal/Lib/test/decimal_extended_tests/genlocale.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/test/decimal_extended_tests/genlocale.py (original) +++ python/branches/py3k-cdecimal/Lib/test/decimal_extended_tests/genlocale.py Sat Jun 5 13:33:09 2010 @@ -141,7 +141,7 @@ testno += 1 printit(testno, s, fmt) for x in range(100): - s = randint(20, 425) + s = randint(20) testno += 1 printit(testno, s, fmt) From python-checkins at python.org Sat Jun 5 13:39:02 2010 From: python-checkins at python.org (stefan.krah) Date: Sat, 5 Jun 2010 13:39:02 +0200 (CEST) Subject: [Python-checkins] r81733 - python/branches/py3k-cdecimal/Lib/test/decimal_extended_tests/ctx-deccheck.py Message-ID: <20100605113902.DE7E5EE9C7@mail.python.org> Author: stefan.krah Date: Sat Jun 5 13:39:02 2010 New Revision: 81733 Log: Fix minor bugs. Keep pychecker happy. Modified: python/branches/py3k-cdecimal/Lib/test/decimal_extended_tests/ctx-deccheck.py Modified: python/branches/py3k-cdecimal/Lib/test/decimal_extended_tests/ctx-deccheck.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/test/decimal_extended_tests/ctx-deccheck.py (original) +++ python/branches/py3k-cdecimal/Lib/test/decimal_extended_tests/ctx-deccheck.py Sat Jun 5 13:39:02 2010 @@ -9,6 +9,7 @@ import cdecimal, decimal import sys, inspect from copy import copy +from randdec import * py_minor = sys.version_info[1] @@ -101,8 +102,7 @@ self.d.Emax = val def getround(self): - assert(self.f.rounding == self.d.rounding) - return self.f.rounding + return self.d.rounding def setround(self, val): self.f.rounding = val @@ -125,9 +125,9 @@ self.d._clamp = val prec = property(getprec, setprec) - emin = property(getemin, setemin) - emax = property(getemax, setemax) - round = property(getround, setround) + Emin = property(getemin, setemin) + Emax = property(getemax, setemax) + rounding = property(getround, setround) clamp = property(getclamp, setclamp) capitals = property(getcapitals, setcapitals) @@ -162,6 +162,8 @@ # We don't want exceptions so that we can compare the status flags. context = Context() +context.Emin = cdecimal.MIN_EMIN +context.Emax = cdecimal.MAX_EMAX context.clear_traps() @@ -180,7 +182,7 @@ decimal: %s\n\n" class CdecException(ArithmeticError): - def __init__(self, result, funcname, operands): + def __init__(self, result, funcname, operands, fctxstr, dctxstr): self.errstring = "Error in %s(%s" % (funcname, operands[0]) for op in operands[1:]: self.errstring += ", %s" % op @@ -197,7 +199,7 @@ str(dec_tuple)) else: self.errstring += _exc_fmt_obj % (str(result[0]), str(result[1])) - self.errstring += "%s\n%s\n\n" % (str(context.f), str(context.d)) + self.errstring += "%s\n%s\n\n" % (fctxstr, dctxstr) def __str__(self): return self.errstring @@ -306,14 +308,22 @@ __eq__ = __ne__ = __ge__ = __gt__ = __le__ = __lt__ = \ __repr__ = __str__ = default + if py_minor <= 1: + # Fixed in release31-maint, but a lot of distributed + # versions do not have the fix yet. + def is_normal(self, result, operands): + # Issue7099 + if operands[0].mpd.is_normal(): + return True + dhandler_cdec = dHandlerCdec() def cdec_known_disagreement(result, funcname, operands): return getattr(dhandler_cdec, funcname, dhandler_cdec.default)(result, operands) -#dhandler_obj = dHandlerObj() -#def obj_known_disagreement(result, funcname, operands): -# return getattr(dhandler_obj, funcname, dhandler_obj.default)(result, operands) +dhandler_obj = dHandlerObj() +def obj_known_disagreement(result, funcname, operands): + return getattr(dhandler_obj, funcname, dhandler_obj.default)(result, operands) def verify(result, funcname, operands): @@ -321,9 +331,10 @@ result[0] and result[1] as well as the context flags have the same values.""" if result[0] != result[1] or not context.assert_eq_status(): - #if obj_known_disagreement(result, funcname, operands): - # return # skip known disagreements - raise CdecException(result, funcname, operands) + if obj_known_disagreement(result, funcname, operands): + return # skip known disagreements + raise CdecException(result, funcname, operands, + str(context.f), str(context.d)) class cdec(object): @@ -361,7 +372,8 @@ not context.assert_eq_status(): if cdec_known_disagreement(self, funcname, operands): return # skip known disagreements - raise CdecException(self, funcname, operands) + raise CdecException(self, funcname, operands, + str(context.f), str(context.d)) def unaryfunc(self, funcname): "unary function returning a cdec, uses the context methods" @@ -419,9 +431,9 @@ third_dec = third.dec if funcname == 'power': if (third is not None): - c.mpd = getattr(context.f, 'powmod')(self.mpd, other_mpd, third_mpd) + c.mpd = context.f.powmod(self.mpd, other_mpd, third_mpd) else: - c.mpd = getattr(context.f, 'pow')(self.mpd, other_mpd) + c.mpd = context.f.pow(self.mpd, other_mpd) else: c.mpd = getattr(context.f, funcname)(self.mpd, other_mpd, third_mpd) c.dec = getattr(context.d, funcname)(self.dec, other_dec, third_dec) @@ -650,10 +662,10 @@ for prec in prec_lst: log(" prec: %d", prec) context.prec = prec - for round in sorted(decround): - context.round = round + for rounding in sorted(decround): + context.rounding = rounding rprec = 10**prec - exprange = cdecimal.MAX_EMAX + exprange = context.f.Emax if method in ['__int__', '__long__', '__trunc__', 'to_integral', \ 'to_integral_value', 'to_integral_value']: exprange = 9999 @@ -698,8 +710,8 @@ for prec in prec_lst: log(" prec: %d", prec) context.prec = prec - for round in sorted(decround): - context.round = round + for rounding in sorted(decround): + context.rounding = rounding for a in logical_un_incr_digits(prec, iter): try: x = cdec(a) @@ -721,11 +733,11 @@ for prec in prec_lst: log(" prec: %d", prec) context.prec = prec - for round in sorted(decround): - context.round = round - exprange = cdecimal.MAX_EMAX + for rounding in sorted(decround): + context.rounding = rounding + exprange = context.f.Emax if method in ['__pow__', '__rpow__', 'power']: - exprange = 99999 + exprange = 9999 for a, b in bin_close_to_pow10(prec, exprange, iter): try: x = cdec(a) @@ -762,8 +774,8 @@ for prec in prec_lst: log(" prec: %d", prec) context.prec = prec - for round in sorted(decround): - context.round = round + for rounding in sorted(decround): + context.rounding = rounding for a, b in logical_bin_incr_digits(prec, iter): try: x = cdec(a) @@ -786,11 +798,11 @@ for prec in prec_lst: log(" prec: %d", prec) context.prec = prec - for round in sorted(decround): - context.round = round - exprange = cdecimal.MAX_EMAX + for rounding in sorted(decround): + context.rounding = rounding + exprange = context.f.Emax if method in ['__pow__', 'power']: - exprange = 99999 + exprange = 9999 for a, b, c in tern_close_numbers(prec, exprange, -exprange, iter): try: x = cdec(a) @@ -824,8 +836,8 @@ for prec in prec_lst: log(" prec: %d", prec) context.prec = prec - for round in sorted(decround): - context.round = round + for rounding in sorted(decround): + context.rounding = rounding exprange = 384 for i in range(1000): intpart = str(random.randrange(100000000000000000000000000000000000000)) @@ -841,26 +853,23 @@ if __name__ == '__main__': - from randdec import * import time - import sys - samples = 1 - iter = 1 + iterations = 1 if '--short' in sys.argv: samples = 1 - iter = 1 + iterations = 1 elif '--medium' in sys.argv: samples = 1 - iter = None + iterations = None elif '--long' in sys.argv: samples = 5 - iter = None + iterations = None elif '--all' in sys.argv: samples = 100 - iter = None + iterations = None all_context_methods = set(dir(cdecimal.getcontext()) + dir(decimal.getcontext())) all_cdec_methods = [m for m in dir(cdec) if m in all_context_methods] @@ -907,22 +916,22 @@ for method in unary_methods: prec_lst = sorted(random.sample(range(1, 101), samples)) - test_unary(method, prec_lst, iter) + test_unary(method, prec_lst, iterations) for method in binary_methods: prec_lst = sorted(random.sample(range(1, 101), samples)) - test_binary(method, prec_lst, iter) + test_binary(method, prec_lst, iterations) for method in ternary_methods: prec_lst = sorted(random.sample(range(1, 101), samples)) - test_ternary(method, prec_lst, iter) + test_ternary(method, prec_lst, iterations) prec_lst = sorted(random.sample(range(1, 101), samples)) - test_un_logical('logical_invert', prec_lst, iter) + test_un_logical('logical_invert', prec_lst, iterations) for method in ['logical_and', 'logical_or', 'logical_xor']: prec_lst = sorted(random.sample(range(1, 101), samples)) - test_bin_logical(method, prec_lst, iter) + test_bin_logical(method, prec_lst, iterations) prec_lst = sorted(random.sample(range(1, 101), samples)) test_from_float(prec_lst) From python-checkins at python.org Sat Jun 5 13:45:31 2010 From: python-checkins at python.org (stefan.krah) Date: Sat, 5 Jun 2010 13:45:31 +0200 (CEST) Subject: [Python-checkins] r81734 - python/branches/py3k-cdecimal/Lib/test/decimal_extended_tests/randdec.py Message-ID: <20100605114531.5739FEE993@mail.python.org> Author: stefan.krah Date: Sat Jun 5 13:45:31 2010 New Revision: 81734 Log: Whitespace; pychecker Modified: python/branches/py3k-cdecimal/Lib/test/decimal_extended_tests/randdec.py Modified: python/branches/py3k-cdecimal/Lib/test/decimal_extended_tests/randdec.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/test/decimal_extended_tests/randdec.py (original) +++ python/branches/py3k-cdecimal/Lib/test/decimal_extended_tests/randdec.py Sat Jun 5 13:45:31 2010 @@ -89,7 +89,7 @@ def randdec(maxprec, maxexp): return numeric_string(maxprec, maxexp) -def randint(maxprec, maxexp): +def randint(maxprec): return digits(maxprec) def rand_adjexp(maxprec, maxadjexp): @@ -125,11 +125,11 @@ # Close to 10**n -def un_close_to_pow10(prec, maxexp, iter=None): - if iter is None: +def un_close_to_pow10(prec, maxexp, itertns=None): + if itertns is None: lst = range(prec+30) else: - lst = random.sample(range(prec+30), iter) + lst = random.sample(range(prec+30), itertns) nines = [10**n - 1 for n in lst] pow10 = [10**n for n in lst] for coeff in nines: @@ -142,11 +142,11 @@ yield -coeff # Close to 10**n -def bin_close_to_pow10(prec, maxexp, iter=None): - if iter is None: +def bin_close_to_pow10(prec, maxexp, itertns=None): + if itertns is None: lst = range(prec+30) else: - lst = random.sample(range(prec+30), iter) + lst = random.sample(range(prec+30), itertns) nines = [10**n - 1 for n in lst] pow10 = [10**n for n in lst] for coeff in nines: @@ -167,80 +167,93 @@ # Close to 1: def close_to_one_greater(prec, emax, emin): rprec = 10**prec - return ''.join(("1.", '0'*random.randrange(prec), str(random.randrange(rprec)))) + return ''.join(("1.", '0'*random.randrange(prec), + str(random.randrange(rprec)))) def close_to_one_less(prec, emax, emin): rprec = 10**prec - return ''.join(("0.9", '9'*random.randrange(prec), str(random.randrange(rprec)))) + return ''.join(("0.9", '9'*random.randrange(prec), + str(random.randrange(rprec)))) # Close to 0: def close_to_zero_greater(prec, emax, emin): rprec = 10**prec - return ''.join(("0.", '0'*random.randrange(prec), str(random.randrange(rprec)))) + return ''.join(("0.", '0'*random.randrange(prec), + str(random.randrange(rprec)))) def close_to_zero_less(prec, emax, emin): rprec = 10**prec - return ''.join(("-0.", '0'*random.randrange(prec), str(random.randrange(rprec)))) + return ''.join(("-0.", '0'*random.randrange(prec), + str(random.randrange(rprec)))) # Close to emax: def close_to_emax_less(prec, emax, emin): rprec = 10**prec - return ''.join(("9.", '9'*random.randrange(prec), str(random.randrange(rprec)), "E", str(emax))) + return ''.join(("9.", '9'*random.randrange(prec), + str(random.randrange(rprec)), "E", str(emax))) def close_to_emax_greater(prec, emax, emin): rprec = 10**prec - return ''.join(("1.", '0'*random.randrange(prec), str(random.randrange(rprec)), "E", str(emax+1))) + return ''.join(("1.", '0'*random.randrange(prec), + str(random.randrange(rprec)), "E", str(emax+1))) # Close to emin: def close_to_emin_greater(prec, emax, emin): rprec = 10**prec - return ''.join(("1.", '0'*random.randrange(prec), str(random.randrange(rprec)), "E", str(emin))) + return ''.join(("1.", '0'*random.randrange(prec), + str(random.randrange(rprec)), "E", str(emin))) def close_to_emin_less(prec, emax, emin): rprec = 10**prec - return ''.join(("9.", '9'*random.randrange(prec), str(random.randrange(rprec)), "E", str(emin-1))) + return ''.join(("9.", '9'*random.randrange(prec), + str(random.randrange(rprec)), "E", str(emin-1))) # Close to etiny: def close_to_etiny_greater(prec, emax, emin): rprec = 10**prec etiny = emin - (prec - 1) - return ''.join(("1.", '0'*random.randrange(prec), str(random.randrange(rprec)), "E", str(etiny))) + return ''.join(("1.", '0'*random.randrange(prec), + str(random.randrange(rprec)), "E", str(etiny))) def close_to_etiny_less(prec, emax, emin): rprec = 10**prec etiny = emin - (prec - 1) - return ''.join(("9.", '9'*random.randrange(prec), str(random.randrange(rprec)), "E", str(etiny-1))) + return ''.join(("9.", '9'*random.randrange(prec), + str(random.randrange(rprec)), "E", str(etiny-1))) def close_to_min_etiny_greater(prec, max_prec, min_emin): rprec = 10**prec etiny = min_emin - (max_prec - 1) - return ''.join(("1.", '0'*random.randrange(prec), str(random.randrange(rprec)), "E", str(etiny))) + return ''.join(("1.", '0'*random.randrange(prec), + str(random.randrange(rprec)), "E", str(etiny))) def close_to_min_etiny_less(prec, max_prec, min_emin): rprec = 10**prec etiny = min_emin - (max_prec - 1) - return ''.join(("9.", '9'*random.randrange(prec), str(random.randrange(rprec)), "E", str(etiny-1))) + return ''.join(("9.", '9'*random.randrange(prec), + str(random.randrange(rprec)), "E", str(etiny-1))) close_funcs = [ - close_to_one_greater, close_to_one_less, close_to_zero_greater, close_to_zero_less, - close_to_emax_less, close_to_emax_greater, close_to_emin_greater, close_to_emin_less, - close_to_etiny_greater, close_to_etiny_less, close_to_min_etiny_greater, close_to_min_etiny_less + close_to_one_greater, close_to_one_less, close_to_zero_greater, + close_to_zero_less, close_to_emax_less, close_to_emax_greater, + close_to_emin_greater, close_to_emin_less, close_to_etiny_greater, + close_to_etiny_less, close_to_min_etiny_greater, close_to_min_etiny_less ] -def un_close_numbers(prec, emax, emin, iter=None): - if iter is None: - iter = 1000 - for i in range(iter): +def un_close_numbers(prec, emax, emin, itertns=None): + if itertns is None: + itertns = 1000 + for i in range(itertns): for func in close_funcs: yield func(prec, emax, emin) -def bin_close_numbers(prec, emax, emin, iter=None): - if iter is None: - iter = 1000 - for i in range(iter): +def bin_close_numbers(prec, emax, emin, itertns=None): + if itertns is None: + itertns = 1000 + for i in range(itertns): for func1 in close_funcs: for func2 in close_funcs: yield func1(prec, emax, emin), func2(prec, emax, emin) @@ -248,43 +261,50 @@ yield randdec(prec, emax), func(prec, emax, emin) yield func(prec, emax, emin), randdec(prec, emax) -def tern_close_numbers(prec, emax, emin, iter): - if iter is None: - iter = 1000 - for i in range(iter): +def tern_close_numbers(prec, emax, emin, itertns): + if itertns is None: + itertns = 1000 + for i in range(itertns): for func1 in close_funcs: for func2 in close_funcs: for func3 in close_funcs: - yield func1(prec, emax, emin), func2(prec, emax, emin), func3(prec, emax, emin) + yield (func1(prec, emax, emin), func2(prec, emax, emin), + func3(prec, emax, emin)) for func in close_funcs: - yield randdec(prec, emax), func(prec, emax, emin), func(prec, emax, emin) - yield func(prec, emax, emin), randdec(prec, emax), func(prec, emax, emin) - yield func(prec, emax, emin), func(prec, emax, emin), randdec(prec, emax) + yield (randdec(prec, emax), func(prec, emax, emin), + func(prec, emax, emin)) + yield (func(prec, emax, emin), randdec(prec, emax), + func(prec, emax, emin)) + yield (func(prec, emax, emin), func(prec, emax, emin), + randdec(prec, emax)) for func in close_funcs: - yield randdec(prec, emax), randdec(prec, emax), func(prec, emax, emin) - yield randdec(prec, emax), func(prec, emax, emin), randdec(prec, emax) - yield func(prec, emax, emin), randdec(prec, emax), randdec(prec, emax) + yield (randdec(prec, emax), randdec(prec, emax), + func(prec, emax, emin)) + yield (randdec(prec, emax), func(prec, emax, emin), + randdec(prec, emax)) + yield (func(prec, emax, emin), randdec(prec, emax), + randdec(prec, emax)) -# If iter == None, test all digit lengths up to prec + 30 -def un_incr_digits(prec, maxexp, iter): - if iter is None: +# If itertns == None, test all digit lengths up to prec + 30 +def un_incr_digits(prec, maxexp, itertns): + if itertns is None: lst = range(prec+30) else: - lst = random.sample(range(prec+30), iter) + lst = random.sample(range(prec+30), itertns) for m in lst: yield from_triple(1, ndigits(m), 0) yield from_triple(-1, ndigits(m), 0) yield from_triple(1, ndigits(m), random.randrange(maxexp)) yield from_triple(-1, ndigits(m), random.randrange(maxexp)) -# If iter == None, test all digit lengths up to prec + 30 +# If itertns == None, test all digit lengths up to prec + 30 # Also output decimals im tuple form. -def un_incr_digits_tuple(prec, maxexp, iter): - if iter is None: +def un_incr_digits_tuple(prec, maxexp, itertns): + if itertns is None: lst = range(prec+30) else: - lst = random.sample(range(prec+30), iter) + lst = random.sample(range(prec+30), itertns) for m in lst: yield from_triple(1, ndigits(m), 0) yield from_triple(-1, ndigits(m), 0) @@ -296,104 +316,103 @@ yield (0, tuple(map(int, str(ndigits(m)))), random.randrange(maxexp)) yield (1, tuple(map(int, str(ndigits(m)))), random.randrange(maxexp)) -# If iter == None, test all combinations of digit lengths up to prec + 30 -def bin_incr_digits(prec, maxexp, iter): - if iter is None: +# If itertns == None, test all combinations of digit lengths up to prec + 30 +def bin_incr_digits(prec, maxexp, itertns): + if itertns is None: lst1 = range(prec+30) lst2 = range(prec+30) else: - lst1 = random.sample(range(prec+30), iter) - lst2 = random.sample(range(prec+30), iter) + lst1 = random.sample(range(prec+30), itertns) + lst2 = random.sample(range(prec+30), itertns) for m in lst1: - self = from_triple(1, ndigits(m), 0) - yield self, self - self = from_triple(-1, ndigits(m), 0) - yield self, self - self = from_triple(1, ndigits(m), random.randrange(maxexp)) - yield self, self - self = from_triple(-1, ndigits(m), random.randrange(maxexp)) - yield self, self + x = from_triple(1, ndigits(m), 0) + yield x, x + x = from_triple(-1, ndigits(m), 0) + yield x, x + x = from_triple(1, ndigits(m), random.randrange(maxexp)) + yield x, x + x = from_triple(-1, ndigits(m), random.randrange(maxexp)) + yield x, x for m in lst1: for n in lst2: - self = from_triple(1, ndigits(m), 0) - other = from_triple(1, ndigits(n), 0) - yield self, other - self = from_triple(-1, ndigits(m), 0) - other = from_triple(1, ndigits(n), 0) - yield self, other - self = from_triple(1, ndigits(m), 0) - other = from_triple(-1, ndigits(n), 0) - yield self, other - self = from_triple(-1, ndigits(m), 0) - other = from_triple(-1, ndigits(n), 0) - yield self, other - self = from_triple(1, ndigits(m), random.randrange(maxexp)) - other = from_triple(1, ndigits(n), random.randrange(maxexp)) - yield self, other - self = from_triple(-1, ndigits(m), random.randrange(maxexp)) - other = from_triple(1, ndigits(n), random.randrange(maxexp)) - yield self, other - self = from_triple(1, ndigits(m), random.randrange(maxexp)) - other = from_triple(-1, ndigits(n), random.randrange(maxexp)) - yield self, other - self = from_triple(-1, ndigits(m), random.randrange(maxexp)) - other = from_triple(-1, ndigits(n), random.randrange(maxexp)) - yield self, other + x = from_triple(1, ndigits(m), 0) + y = from_triple(1, ndigits(n), 0) + yield x, y + x = from_triple(-1, ndigits(m), 0) + y = from_triple(1, ndigits(n), 0) + yield x, y + x = from_triple(1, ndigits(m), 0) + y = from_triple(-1, ndigits(n), 0) + yield x, y + x = from_triple(-1, ndigits(m), 0) + y = from_triple(-1, ndigits(n), 0) + yield x, y + x = from_triple(1, ndigits(m), random.randrange(maxexp)) + y = from_triple(1, ndigits(n), random.randrange(maxexp)) + yield x, y + x = from_triple(-1, ndigits(m), random.randrange(maxexp)) + y = from_triple(1, ndigits(n), random.randrange(maxexp)) + yield x, y + x = from_triple(1, ndigits(m), random.randrange(maxexp)) + y = from_triple(-1, ndigits(n), random.randrange(maxexp)) + yield x, y + x = from_triple(-1, ndigits(m), random.randrange(maxexp)) + y = from_triple(-1, ndigits(n), random.randrange(maxexp)) + yield x, y def randsign(): return (1, -1)[random.randrange(2)] -# If iter == None, test all combinations of digit lengths up to prec + 30 -def tern_incr_digits(prec, maxexp, iter): - if iter is None: +# If itertns == None, test all combinations of digit lengths up to prec + 30 +def tern_incr_digits(prec, maxexp, itertns): + if itertns is None: lst1 = range(prec+30) lst2 = range(prec+30) lst3 = range(prec+30) else: - lst1 = random.sample(range(prec+30), iter) - lst2 = random.sample(range(prec+30), iter) - lst3 = random.sample(range(prec+30), iter) + lst1 = random.sample(range(prec+30), itertns) + lst2 = random.sample(range(prec+30), itertns) + lst3 = random.sample(range(prec+30), itertns) for m in lst1: for n in lst2: for p in lst3: - self = from_triple(randsign(), ndigits(m), 0) - other = from_triple(randsign(), ndigits(n), 0) - third = from_triple(randsign(), ndigits(p), 0) - yield self, other, third + x = from_triple(randsign(), ndigits(m), 0) + y = from_triple(randsign(), ndigits(n), 0) + z = from_triple(randsign(), ndigits(p), 0) + yield x, y, z -# Tests for the 'logical' fucntions +# Tests for the 'logical' functions def bindigits(prec): z = 0 for i in range(prec): z += random.randrange(2) * 10**i return z -def logical_un_incr_digits(prec, iter): - if iter is None: +def logical_un_incr_digits(prec, itertns): + if itertns is None: lst = range(prec+30) else: - lst = random.sample(range(prec+30), iter) + lst = random.sample(range(prec+30), itertns) for m in lst: - self = from_triple(1, bindigits(m), 0) - yield self + yield from_triple(1, bindigits(m), 0) -def logical_bin_incr_digits(prec, iter): - if iter is None: +def logical_bin_incr_digits(prec, itertns): + if itertns is None: lst1 = range(prec+30) lst2 = range(prec+30) else: - lst1 = random.sample(range(prec+30), iter) - lst2 = random.sample(range(prec+30), iter) + lst1 = random.sample(range(prec+30), itertns) + lst2 = random.sample(range(prec+30), itertns) for m in lst1: - self = from_triple(1, bindigits(m), 0) - yield self, self + x = from_triple(1, bindigits(m), 0) + yield x, x for m in lst1: for n in lst2: - self = from_triple(1, bindigits(m), 0) - other = from_triple(1, bindigits(n), 0) - yield self, other + x = from_triple(1, bindigits(m), 0) + y = from_triple(1, bindigits(n), 0) + yield x, y py_major = sys.version_info[0] @@ -435,7 +454,6 @@ # Generate random format strings # [[fill]align][sign][#][0][width][.precision][type] -import string def rand_format(fill): active = sorted(random.sample(range(7), random.randrange(8))) have_align = 0 From python-checkins at python.org Sat Jun 5 13:46:59 2010 From: python-checkins at python.org (michael.foord) Date: Sat, 5 Jun 2010 13:46:59 +0200 (CEST) Subject: [Python-checkins] r81735 - python/trunk/Lib/unittest/case.py Message-ID: <20100605114659.BCA5BEE993@mail.python.org> Author: michael.foord Date: Sat Jun 5 13:46:59 2010 New Revision: 81735 Log: Extract error message truncating into a method (unittest.TestCase._truncateMessage). Modified: python/trunk/Lib/unittest/case.py Modified: python/trunk/Lib/unittest/case.py ============================================================================== --- python/trunk/Lib/unittest/case.py (original) +++ python/trunk/Lib/unittest/case.py Sat Jun 5 13:46:59 2010 @@ -690,13 +690,15 @@ diffMsg = '\n' + '\n'.join( difflib.ndiff(pprint.pformat(seq1).splitlines(), pprint.pformat(seq2).splitlines())) - if max_diff is None or len(diffMsg) <= max_diff: - standardMsg += diffMsg - else: - standardMsg += diffMsg[:max_diff] + TRUNCATED_DIFF + standardMsg = self._truncateMessage(standardMsg, diffMsg, max_diff) msg = self._formatMessage(msg, standardMsg) self.fail(msg) + def _truncateMessage(self, message, diff, max_diff): + if max_diff is None or len(diff) <= max_diff: + return message + diff + return message + diff[:max_diff] + TRUNCATED_DIFF + def assertListEqual(self, list1, list2, msg=None): """A list-specific equality assertion. From python-checkins at python.org Sat Jun 5 13:52:24 2010 From: python-checkins at python.org (mark.dickinson) Date: Sat, 5 Jun 2010 13:52:24 +0200 (CEST) Subject: [Python-checkins] r81736 - in python/trunk: Lib/test/test_descr.py Misc/NEWS Objects/typeobject.c Message-ID: <20100605115224.A74F4EE9C7@mail.python.org> Author: mark.dickinson Date: Sat Jun 5 13:52:24 2010 New Revision: 81736 Log: Issue #8627: remove out-of-date warning about overriding __cmp__ Modified: python/trunk/Lib/test/test_descr.py python/trunk/Misc/NEWS python/trunk/Objects/typeobject.c Modified: python/trunk/Lib/test/test_descr.py ============================================================================== --- python/trunk/Lib/test/test_descr.py (original) +++ python/trunk/Lib/test/test_descr.py Sat Jun 5 13:52:24 2010 @@ -4621,7 +4621,6 @@ deprecations += [ ("classic (int|long) division", DeprecationWarning), ("coerce.. not supported", DeprecationWarning), - ("Overriding __cmp__ ", DeprecationWarning), (".+__(get|set|del)slice__ has been removed", DeprecationWarning)] with test_support.check_warnings(*deprecations): # Run all local test cases, with PTypesLongInitTest first. Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Sat Jun 5 13:52:24 2010 @@ -12,6 +12,9 @@ Core and Builtins ----------------- +- Issue #8627: Remove bogus "Overriding __cmp__ blocks inheritance of + __hash__ in 3.x" warning. + - Issue #8748: Fix two issues with comparisons between complex and integer objects. (1) The comparison could incorrectly return True in some cases (2**53+1 == complex(2**53) == 2**53), breaking transivity of equality. Modified: python/trunk/Objects/typeobject.c ============================================================================== --- python/trunk/Objects/typeobject.c (original) +++ python/trunk/Objects/typeobject.c Sat Jun 5 13:52:24 2010 @@ -3723,7 +3723,6 @@ } #define OVERRIDES_HASH(x) overrides_name(x, "__hash__") -#define OVERRIDES_CMP(x) overrides_name(x, "__cmp__") #define OVERRIDES_EQ(x) overrides_name(x, "__eq__") static void @@ -3869,12 +3868,6 @@ if (base->tp_hash && (base->tp_hash != PyObject_HashNotImplemented) && !OVERRIDES_HASH(type)) { - if (OVERRIDES_CMP(type)) { - PyErr_WarnPy3k("Overriding " - "__cmp__ blocks inheritance " - "of __hash__ in 3.x", - 1); - } if (OVERRIDES_EQ(type)) { PyErr_WarnPy3k("Overriding " "__eq__ blocks inheritance " From python-checkins at python.org Sat Jun 5 13:53:12 2010 From: python-checkins at python.org (mark.dickinson) Date: Sat, 5 Jun 2010 13:53:12 +0200 (CEST) Subject: [Python-checkins] r81737 - python/branches/py3k Message-ID: <20100605115312.221DAEE9C7@mail.python.org> Author: mark.dickinson Date: Sat Jun 5 13:53:11 2010 New Revision: 81737 Log: Blocked revisions 81736 via svnmerge ........ r81736 | mark.dickinson | 2010-06-05 12:52:24 +0100 (Sat, 05 Jun 2010) | 1 line Issue #8627: remove out-of-date warning about overriding __cmp__ ........ Modified: python/branches/py3k/ (props changed) From python-checkins at python.org Sat Jun 5 13:59:41 2010 From: python-checkins at python.org (mark.dickinson) Date: Sat, 5 Jun 2010 13:59:41 +0200 (CEST) Subject: [Python-checkins] r81738 - in python/branches/release26-maint: Misc/NEWS Objects/typeobject.c Message-ID: <20100605115941.46D7CEE9C7@mail.python.org> Author: mark.dickinson Date: Sat Jun 5 13:59:41 2010 New Revision: 81738 Log: Merged revisions 81736 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81736 | mark.dickinson | 2010-06-05 12:52:24 +0100 (Sat, 05 Jun 2010) | 1 line Issue #8627: remove out-of-date warning about overriding __cmp__ ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Misc/NEWS python/branches/release26-maint/Objects/typeobject.c Modified: python/branches/release26-maint/Misc/NEWS ============================================================================== --- python/branches/release26-maint/Misc/NEWS (original) +++ python/branches/release26-maint/Misc/NEWS Sat Jun 5 13:59:41 2010 @@ -12,6 +12,9 @@ Core and Builtins ----------------- +- Issue #8627: Remove bogus "Overriding __cmp__ blocks inheritance of + __hash__ in 3.x" warning. + - Issue #3798: Write sys.exit() message to sys.stderr to use stderr encoding and error handler, instead of writing to the C stderr file in utf-8 Modified: python/branches/release26-maint/Objects/typeobject.c ============================================================================== --- python/branches/release26-maint/Objects/typeobject.c (original) +++ python/branches/release26-maint/Objects/typeobject.c Sat Jun 5 13:59:41 2010 @@ -3707,7 +3707,6 @@ } #define OVERRIDES_HASH(x) overrides_name(x, "__hash__") -#define OVERRIDES_CMP(x) overrides_name(x, "__cmp__") #define OVERRIDES_EQ(x) overrides_name(x, "__eq__") static void @@ -3853,12 +3852,6 @@ if (base->tp_hash && (base->tp_hash != PyObject_HashNotImplemented) && !OVERRIDES_HASH(type)) { - if (OVERRIDES_CMP(type)) { - PyErr_WarnPy3k("Overriding " - "__cmp__ blocks inheritance " - "of __hash__ in 3.x", - 1); - } if (OVERRIDES_EQ(type)) { PyErr_WarnPy3k("Overriding " "__eq__ blocks inheritance " From python-checkins at python.org Sat Jun 5 14:10:52 2010 From: python-checkins at python.org (michael.foord) Date: Sat, 5 Jun 2010 14:10:52 +0200 (CEST) Subject: [Python-checkins] r81739 - in python/trunk/Lib/unittest: case.py test/test_case.py Message-ID: <20100605121052.74F97EE9CE@mail.python.org> Author: michael.foord Date: Sat Jun 5 14:10:52 2010 New Revision: 81739 Log: Removed the new max_diff argument to assertSequenceEqual. All unittest.TestCase assert methods that use difflib to produce failure messages now truncate overly long messages. New class attribute unittest.TestCase.maxDiff to configure this if necessary. Issue 8351. Modified: python/trunk/Lib/unittest/case.py python/trunk/Lib/unittest/test/test_case.py Modified: python/trunk/Lib/unittest/case.py ============================================================================== --- python/trunk/Lib/unittest/case.py (original) +++ python/trunk/Lib/unittest/case.py Sat Jun 5 14:10:52 2010 @@ -13,7 +13,6 @@ ) __unittest = True -TRUNCATED_DIFF = '\n[diff truncated...]' class SkipTest(Exception): """ @@ -157,6 +156,11 @@ longMessage = False + # This attribute sets the maximum length of a diff in failure messsages + # by assert methods using difflib. It is looked up as an instance attribute + # so can be configured by individual tests if required. + maxDiff = 80*8 + # Attribute used by TestSuite for classSetUp _classSetupFailed = False @@ -589,8 +593,7 @@ failUnlessRaises = _deprecate(assertRaises) failIf = _deprecate(assertFalse) - def assertSequenceEqual(self, seq1, seq2, msg=None, seq_type=None, - max_diff=80*8): + def assertSequenceEqual(self, seq1, seq2, msg=None, seq_type=None): """An equality assertion for ordered sequences (like lists and tuples). For the purposes of this function, a valid ordered sequence type is one @@ -603,7 +606,6 @@ datatype should be enforced. msg: Optional message to use on failure instead of a list of differences. - max_diff: Maximum size off the diff, larger diffs are not shown """ if seq_type is not None: seq_type_name = seq_type.__name__ @@ -690,14 +692,15 @@ diffMsg = '\n' + '\n'.join( difflib.ndiff(pprint.pformat(seq1).splitlines(), pprint.pformat(seq2).splitlines())) - standardMsg = self._truncateMessage(standardMsg, diffMsg, max_diff) + standardMsg = self._truncateMessage(standardMsg, diffMsg) msg = self._formatMessage(msg, standardMsg) self.fail(msg) - def _truncateMessage(self, message, diff, max_diff): + def _truncateMessage(self, message, diff): + max_diff = self.maxDiff if max_diff is None or len(diff) <= max_diff: return message + diff - return message + diff[:max_diff] + TRUNCATED_DIFF + return message def assertListEqual(self, list1, list2, msg=None): """A list-specific equality assertion. @@ -797,9 +800,10 @@ self.assert_(isinstance(d2, dict), 'Second argument is not a dictionary') if d1 != d2: - standardMsg = ('\n' + '\n'.join(difflib.ndiff( + diff = ('\n' + '\n'.join(difflib.ndiff( pprint.pformat(d1).splitlines(), pprint.pformat(d2).splitlines()))) + standardMsg = self._truncateMessage('', diff) self.fail(self._formatMessage(msg, standardMsg)) def assertDictContainsSubset(self, expected, actual, msg=None): @@ -882,8 +886,9 @@ 'Second argument is not a string')) if first != second: - standardMsg = '\n' + ''.join(difflib.ndiff(first.splitlines(True), + diff = '\n' + ''.join(difflib.ndiff(first.splitlines(True), second.splitlines(True))) + standardMsg = self._truncateMessage('', diff) self.fail(self._formatMessage(msg, standardMsg)) def assertLess(self, a, b, msg=None): Modified: python/trunk/Lib/unittest/test/test_case.py ============================================================================== --- python/trunk/Lib/unittest/test/test_case.py (original) +++ python/trunk/Lib/unittest/test/test_case.py Sat Jun 5 14:10:52 2010 @@ -591,20 +591,37 @@ self.assertRaises(self.failureException, self.assertDictEqual, 1, 1) def testAssertSequenceEqualMaxDiff(self): + self.assertEqual(self.maxDiff, 80*8) seq1 = 'a' + 'x' * 80**2 seq2 = 'b' + 'x' * 80**2 diff = '\n'.join(difflib.ndiff(pprint.pformat(seq1).splitlines(), pprint.pformat(seq2).splitlines())) + + self.maxDiff = len(diff)//2 try: - self.assertSequenceEqual(seq1, seq2, max_diff=len(diff)/2) - except AssertionError as e: + self.assertSequenceEqual(seq1, seq2) + except self.failureException as e: msg = e.args[0] + else: + self.fail('assertSequenceEqual did not fail.') self.assertTrue(len(msg) < len(diff)) + self.maxDiff = len(diff) * 2 + try: + self.assertSequenceEqual(seq1, seq2) + except self.failureException as e: + msg = e.args[0] + else: + self.fail('assertSequenceEqual did not fail.') + self.assertTrue(len(msg) > len(diff)) + + self.maxDiff = None try: - self.assertSequenceEqual(seq1, seq2, max_diff=len(diff)*2) - except AssertionError as e: + self.assertSequenceEqual(seq1, seq2) + except self.failureException as e: msg = e.args[0] + else: + self.fail('assertSequenceEqual did not fail.') self.assertTrue(len(msg) > len(diff)) def testAssertItemsEqual(self): From python-checkins at python.org Sat Jun 5 14:14:43 2010 From: python-checkins at python.org (mark.dickinson) Date: Sat, 5 Jun 2010 14:14:43 +0200 (CEST) Subject: [Python-checkins] r81740 - in python/trunk: Misc/NEWS Objects/typeobject.c Message-ID: <20100605121443.C8502EE9CE@mail.python.org> Author: mark.dickinson Date: Sat Jun 5 14:14:43 2010 New Revision: 81740 Log: Issue #8627: Fix "XXX undetected error" from unchecked PyErr_WarnPy3k return. This is just a quick fix: if the warning is turned into an exception, the exception simply gets ignored. Modified: python/trunk/Misc/NEWS python/trunk/Objects/typeobject.c Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Sat Jun 5 14:14:43 2010 @@ -13,7 +13,10 @@ ----------------- - Issue #8627: Remove bogus "Overriding __cmp__ blocks inheritance of - __hash__ in 3.x" warning. + __hash__ in 3.x" warning. Also fix "XXX undetected error" that + arises from the "Overriding __eq__ blocks inheritance ..." warning + when turned into an exception: in this case the exception simply + gets ignored. - Issue #8748: Fix two issues with comparisons between complex and integer objects. (1) The comparison could incorrectly return True in some cases Modified: python/trunk/Objects/typeobject.c ============================================================================== --- python/trunk/Objects/typeobject.c (original) +++ python/trunk/Objects/typeobject.c Sat Jun 5 14:14:43 2010 @@ -3869,10 +3869,16 @@ (base->tp_hash != PyObject_HashNotImplemented) && !OVERRIDES_HASH(type)) { if (OVERRIDES_EQ(type)) { - PyErr_WarnPy3k("Overriding " - "__eq__ blocks inheritance " - "of __hash__ in 3.x", - 1); + if (PyErr_WarnPy3k("Overriding " + "__eq__ blocks inheritance " + "of __hash__ in 3.x", + 1) < 0) + /* XXX This isn't right. If the warning is turned + into an exception, we should be communicating + the error back to the caller, but figuring out + how to clean-up in that case is tricky. See + issue 8627 for more. */ + PyErr_Clear(); } } } From python-checkins at python.org Sat Jun 5 14:15:36 2010 From: python-checkins at python.org (mark.dickinson) Date: Sat, 5 Jun 2010 14:15:36 +0200 (CEST) Subject: [Python-checkins] r81741 - in python/branches/release26-maint: Misc/NEWS Objects/typeobject.c Message-ID: <20100605121536.04B16EE9CE@mail.python.org> Author: mark.dickinson Date: Sat Jun 5 14:15:35 2010 New Revision: 81741 Log: Merged revisions 81740 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81740 | mark.dickinson | 2010-06-05 13:14:43 +0100 (Sat, 05 Jun 2010) | 5 lines Issue #8627: Fix "XXX undetected error" from unchecked PyErr_WarnPy3k return. This is just a quick fix: if the warning is turned into an exception, the exception simply gets ignored. ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Misc/NEWS python/branches/release26-maint/Objects/typeobject.c Modified: python/branches/release26-maint/Misc/NEWS ============================================================================== --- python/branches/release26-maint/Misc/NEWS (original) +++ python/branches/release26-maint/Misc/NEWS Sat Jun 5 14:15:35 2010 @@ -13,7 +13,10 @@ ----------------- - Issue #8627: Remove bogus "Overriding __cmp__ blocks inheritance of - __hash__ in 3.x" warning. + __hash__ in 3.x" warning. Also fix "XXX undetected error" that + arises from the "Overriding __eq__ blocks inheritance ..." warning + when turned into an exception: in this case the exception simply + gets ignored. - Issue #3798: Write sys.exit() message to sys.stderr to use stderr encoding and error handler, instead of writing to the C stderr file in utf-8 Modified: python/branches/release26-maint/Objects/typeobject.c ============================================================================== --- python/branches/release26-maint/Objects/typeobject.c (original) +++ python/branches/release26-maint/Objects/typeobject.c Sat Jun 5 14:15:35 2010 @@ -3853,10 +3853,16 @@ (base->tp_hash != PyObject_HashNotImplemented) && !OVERRIDES_HASH(type)) { if (OVERRIDES_EQ(type)) { - PyErr_WarnPy3k("Overriding " - "__eq__ blocks inheritance " - "of __hash__ in 3.x", - 1); + if (PyErr_WarnPy3k("Overriding " + "__eq__ blocks inheritance " + "of __hash__ in 3.x", + 1) < 0) + /* XXX This isn't right. If the warning is turned + into an exception, we should be communicating + the error back to the caller, but figuring out + how to clean-up in that case is tricky. See + issue 8627 for more. */ + PyErr_Clear(); } } } From python-checkins at python.org Sat Jun 5 14:17:02 2010 From: python-checkins at python.org (michael.foord) Date: Sat, 5 Jun 2010 14:17:02 +0200 (CEST) Subject: [Python-checkins] r81742 - in python/branches/py3k: Lib/unittest/case.py Lib/unittest/test/test_case.py Message-ID: <20100605121702.9972CEE9CE@mail.python.org> Author: michael.foord Date: Sat Jun 5 14:17:02 2010 New Revision: 81742 Log: Merged revisions 81739 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81739 | michael.foord | 2010-06-05 13:10:52 +0100 (Sat, 05 Jun 2010) | 1 line Removed the new max_diff argument to assertSequenceEqual. All unittest.TestCase assert methods that use difflib to produce failure messages now truncate overly long messages. New class attribute unittest.TestCase.maxDiff to configure this if necessary. Issue 8351. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/unittest/case.py python/branches/py3k/Lib/unittest/test/test_case.py Modified: python/branches/py3k/Lib/unittest/case.py ============================================================================== --- python/branches/py3k/Lib/unittest/case.py (original) +++ python/branches/py3k/Lib/unittest/case.py Sat Jun 5 14:17:02 2010 @@ -12,7 +12,6 @@ unorderable_list_difference) __unittest = True -TRUNCATED_DIFF = '\n[diff truncated...]' class SkipTest(Exception): """ @@ -169,6 +168,11 @@ longMessage = False + # This attribute sets the maximum length of a diff in failure messsages + # by assert methods using difflib. It is looked up as an instance attribute + # so can be configured by individual tests if required. + maxDiff = 80*8 + # Attribute used by TestSuite for classSetUp _classSetupFailed = False @@ -599,8 +603,7 @@ failUnlessRaises = _deprecate(assertRaises) failIf = _deprecate(assertFalse) - def assertSequenceEqual(self, seq1, seq2, msg=None, seq_type=None, - max_diff=80*8): + def assertSequenceEqual(self, seq1, seq2, msg=None, seq_type=None): """An equality assertion for ordered sequences (like lists and tuples). For the purposes of this function, a valid ordered sequence type is one @@ -613,7 +616,6 @@ datatype should be enforced. msg: Optional message to use on failure instead of a list of differences. - max_diff: Maximum size off the diff, larger diffs are not shown """ if seq_type != None: seq_type_name = seq_type.__name__ @@ -700,13 +702,17 @@ diffMsg = '\n' + '\n'.join( difflib.ndiff(pprint.pformat(seq1).splitlines(), pprint.pformat(seq2).splitlines())) - if max_diff is None or len(diffMsg) <= max_diff: - standardMsg += diffMsg - else: - standardMsg += diffMsg[:max_diff] + TRUNCATED_DIFF + + standardMsg = self._truncateMessage(standardMsg, diffMsg) msg = self._formatMessage(msg, standardMsg) self.fail(msg) + def _truncateMessage(self, message, diff): + max_diff = self.maxDiff + if max_diff is None or len(diff) <= max_diff: + return message + diff + return message + def assertListEqual(self, list1, list2, msg=None): """A list-specific equality assertion. @@ -805,9 +811,10 @@ self.assert_(isinstance(d2, dict), 'Second argument is not a dictionary') if d1 != d2: - standardMsg = ('\n' + '\n'.join(difflib.ndiff( + diff = ('\n' + '\n'.join(difflib.ndiff( pprint.pformat(d1).splitlines(), pprint.pformat(d2).splitlines()))) + standardMsg = self._truncateMessage('', diff) self.fail(self._formatMessage(msg, standardMsg)) def assertDictContainsSubset(self, expected, actual, msg=None): @@ -924,8 +931,9 @@ 'Second argument is not a string')) if first != second: - standardMsg = '\n' + ''.join(difflib.ndiff(first.splitlines(True), + diff = '\n' + ''.join(difflib.ndiff(first.splitlines(True), second.splitlines(True))) + standardMsg = self._truncateMessage('', diff) self.fail(self._formatMessage(msg, standardMsg)) def assertLess(self, a, b, msg=None): Modified: python/branches/py3k/Lib/unittest/test/test_case.py ============================================================================== --- python/branches/py3k/Lib/unittest/test/test_case.py (original) +++ python/branches/py3k/Lib/unittest/test/test_case.py Sat Jun 5 14:17:02 2010 @@ -592,20 +592,38 @@ self.assertRaises(self.failureException, self.assertDictEqual, 1, 1) def testAssertSequenceEqualMaxDiff(self): + self.assertEqual(self.maxDiff, 80*8) seq1 = 'a' + 'x' * 80**2 seq2 = 'b' + 'x' * 80**2 diff = '\n'.join(difflib.ndiff(pprint.pformat(seq1).splitlines(), pprint.pformat(seq2).splitlines())) + + self.maxDiff = len(diff)//2 try: - self.assertSequenceEqual(seq1, seq2, max_diff=len(diff)//2) - except AssertionError as e: + + self.assertSequenceEqual(seq1, seq2) + except self.failureException as e: msg = e.args[0] + else: + self.fail('assertSequenceEqual did not fail.') self.assertTrue(len(msg) < len(diff)) + self.maxDiff = len(diff) * 2 try: - self.assertSequenceEqual(seq1, seq2, max_diff=len(diff)*2) - except AssertionError as e: + self.assertSequenceEqual(seq1, seq2) + except self.failureException as e: + msg = e.args[0] + else: + self.fail('assertSequenceEqual did not fail.') + self.assertTrue(len(msg) > len(diff)) + + self.maxDiff = None + try: + self.assertSequenceEqual(seq1, seq2) + except self.failureException as e: msg = e.args[0] + else: + self.fail('assertSequenceEqual did not fail.') self.assertTrue(len(msg) > len(diff)) def testAssertItemsEqual(self): From python-checkins at python.org Sat Jun 5 14:38:00 2010 From: python-checkins at python.org (mark.dickinson) Date: Sat, 5 Jun 2010 14:38:00 +0200 (CEST) Subject: [Python-checkins] r81743 - python/branches/py3k Message-ID: <20100605123800.7820AEE9E8@mail.python.org> Author: mark.dickinson Date: Sat Jun 5 14:38:00 2010 New Revision: 81743 Log: Blocked revisions 81740 via svnmerge ........ r81740 | mark.dickinson | 2010-06-05 13:14:43 +0100 (Sat, 05 Jun 2010) | 5 lines Issue #8627: Fix "XXX undetected error" from unchecked PyErr_WarnPy3k return. This is just a quick fix: if the warning is turned into an exception, the exception simply gets ignored. ........ Modified: python/branches/py3k/ (props changed) From python-checkins at python.org Sat Jun 5 14:51:21 2010 From: python-checkins at python.org (mark.dickinson) Date: Sat, 5 Jun 2010 14:51:21 +0200 (CEST) Subject: [Python-checkins] r81744 - python/trunk/Objects/typeobject.c Message-ID: <20100605125121.DEC74EE9C7@mail.python.org> Author: mark.dickinson Date: Sat Jun 5 14:51:21 2010 New Revision: 81744 Log: Fix comment typo. Modified: python/trunk/Objects/typeobject.c Modified: python/trunk/Objects/typeobject.c ============================================================================== --- python/trunk/Objects/typeobject.c (original) +++ python/trunk/Objects/typeobject.c Sat Jun 5 14:51:21 2010 @@ -3876,7 +3876,7 @@ /* XXX This isn't right. If the warning is turned into an exception, we should be communicating the error back to the caller, but figuring out - how to clean-up in that case is tricky. See + how to clean up in that case is tricky. See issue 8627 for more. */ PyErr_Clear(); } From python-checkins at python.org Sat Jun 5 14:52:03 2010 From: python-checkins at python.org (mark.dickinson) Date: Sat, 5 Jun 2010 14:52:03 +0200 (CEST) Subject: [Python-checkins] r81745 - in python/branches/release26-maint: Objects/typeobject.c Message-ID: <20100605125203.29A20EE9C7@mail.python.org> Author: mark.dickinson Date: Sat Jun 5 14:52:03 2010 New Revision: 81745 Log: Merged revisions 81744 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81744 | mark.dickinson | 2010-06-05 13:51:21 +0100 (Sat, 05 Jun 2010) | 1 line Fix comment typo. ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Objects/typeobject.c Modified: python/branches/release26-maint/Objects/typeobject.c ============================================================================== --- python/branches/release26-maint/Objects/typeobject.c (original) +++ python/branches/release26-maint/Objects/typeobject.c Sat Jun 5 14:52:03 2010 @@ -3860,7 +3860,7 @@ /* XXX This isn't right. If the warning is turned into an exception, we should be communicating the error back to the caller, but figuring out - how to clean-up in that case is tricky. See + how to clean up in that case is tricky. See issue 8627 for more. */ PyErr_Clear(); } From python-checkins at python.org Sat Jun 5 14:52:23 2010 From: python-checkins at python.org (mark.dickinson) Date: Sat, 5 Jun 2010 14:52:23 +0200 (CEST) Subject: [Python-checkins] r81746 - python/branches/py3k Message-ID: <20100605125223.3E591EE9C7@mail.python.org> Author: mark.dickinson Date: Sat Jun 5 14:52:23 2010 New Revision: 81746 Log: Blocked revisions 81744 via svnmerge ........ r81744 | mark.dickinson | 2010-06-05 13:51:21 +0100 (Sat, 05 Jun 2010) | 1 line Fix comment typo. ........ Modified: python/branches/py3k/ (props changed) From python-checkins at python.org Sat Jun 5 14:58:39 2010 From: python-checkins at python.org (michael.foord) Date: Sat, 5 Jun 2010 14:58:39 +0200 (CEST) Subject: [Python-checkins] r81747 - in python/trunk/Lib/unittest: case.py util.py Message-ID: <20100605125839.63890EE9C7@mail.python.org> Author: michael.foord Date: Sat Jun 5 14:58:39 2010 New Revision: 81747 Log: unittest.TestCase.assertDictEqual and assertMultilineEqual provide better default failure messages in the event of long diffs. Modified: python/trunk/Lib/unittest/case.py python/trunk/Lib/unittest/util.py Modified: python/trunk/Lib/unittest/case.py ============================================================================== --- python/trunk/Lib/unittest/case.py (original) +++ python/trunk/Lib/unittest/case.py Sat Jun 5 14:58:39 2010 @@ -800,10 +800,11 @@ self.assert_(isinstance(d2, dict), 'Second argument is not a dictionary') if d1 != d2: + standardMsg = '%s != %s' % (safe_repr(d1, True), safe_repr(d2, True)) diff = ('\n' + '\n'.join(difflib.ndiff( pprint.pformat(d1).splitlines(), pprint.pformat(d2).splitlines()))) - standardMsg = self._truncateMessage('', diff) + standardMsg = self._truncateMessage(standardMsg, diff) self.fail(self._formatMessage(msg, standardMsg)) def assertDictContainsSubset(self, expected, actual, msg=None): @@ -886,9 +887,10 @@ 'Second argument is not a string')) if first != second: + standardMsg = '%s != %s' % (safe_repr(d1, True), safe_repr(d2, True)) diff = '\n' + ''.join(difflib.ndiff(first.splitlines(True), second.splitlines(True))) - standardMsg = self._truncateMessage('', diff) + standardMsg = self._truncateMessage(standardMsg, diff) self.fail(self._formatMessage(msg, standardMsg)) def assertLess(self, a, b, msg=None): Modified: python/trunk/Lib/unittest/util.py ============================================================================== --- python/trunk/Lib/unittest/util.py (original) +++ python/trunk/Lib/unittest/util.py Sat Jun 5 14:58:39 2010 @@ -2,12 +2,16 @@ __unittest = True - -def safe_repr(obj): +_MAX_LENGTH = 80 +def safe_repr(obj, short=False): try: - return repr(obj) + result = repr(obj) except Exception: - return object.__repr__(obj) + result = object.__repr__(obj) + if not short or len(result) < _MAX_LENGTH: + return result + return result[:_MAX_LENGTH] + ' [truncated]...' + def strclass(cls): return "%s.%s" % (cls.__module__, cls.__name__) From python-checkins at python.org Sat Jun 5 15:14:43 2010 From: python-checkins at python.org (michael.foord) Date: Sat, 5 Jun 2010 15:14:43 +0200 (CEST) Subject: [Python-checkins] r81748 - in python/branches/py3k: Lib/unittest/case.py Lib/unittest/util.py Message-ID: <20100605131443.42224EE9C3@mail.python.org> Author: michael.foord Date: Sat Jun 5 15:14:43 2010 New Revision: 81748 Log: Merged revisions 81747 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81747 | michael.foord | 2010-06-05 13:58:39 +0100 (Sat, 05 Jun 2010) | 1 line unittest.TestCase.assertDictEqual and assertMultilineEqual provide better default failure messages in the event of long diffs. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/unittest/case.py python/branches/py3k/Lib/unittest/util.py Modified: python/branches/py3k/Lib/unittest/case.py ============================================================================== --- python/branches/py3k/Lib/unittest/case.py (original) +++ python/branches/py3k/Lib/unittest/case.py Sat Jun 5 15:14:43 2010 @@ -811,10 +811,11 @@ self.assert_(isinstance(d2, dict), 'Second argument is not a dictionary') if d1 != d2: + standardMsg = '%s != %s' % (safe_repr(d1, True), safe_repr(d2, True)) diff = ('\n' + '\n'.join(difflib.ndiff( pprint.pformat(d1).splitlines(), pprint.pformat(d2).splitlines()))) - standardMsg = self._truncateMessage('', diff) + standardMsg = self._truncateMessage(standardMsg, diff) self.fail(self._formatMessage(msg, standardMsg)) def assertDictContainsSubset(self, expected, actual, msg=None): @@ -931,9 +932,10 @@ 'Second argument is not a string')) if first != second: + standardMsg = '%s != %s' % (safe_repr(d1, True), safe_repr(d2, True)) diff = '\n' + ''.join(difflib.ndiff(first.splitlines(True), second.splitlines(True))) - standardMsg = self._truncateMessage('', diff) + standardMsg = self._truncateMessage(standardMsg, diff) self.fail(self._formatMessage(msg, standardMsg)) def assertLess(self, a, b, msg=None): Modified: python/branches/py3k/Lib/unittest/util.py ============================================================================== --- python/branches/py3k/Lib/unittest/util.py (original) +++ python/branches/py3k/Lib/unittest/util.py Sat Jun 5 15:14:43 2010 @@ -2,12 +2,16 @@ __unittest = True - -def safe_repr(obj): +_MAX_LENGTH = 80 +def safe_repr(obj, short=False): try: - return repr(obj) + result = repr(obj) except Exception: - return object.__repr__(obj) + result = object.__repr__(obj) + if not short or len(result) < _MAX_LENGTH: + return result + return result[:_MAX_LENGTH] + ' [truncated]...' + def strclass(cls): return "%s.%s" % (cls.__module__, cls.__name__) From python-checkins at python.org Sat Jun 5 15:18:34 2010 From: python-checkins at python.org (mark.dickinson) Date: Sat, 5 Jun 2010 15:18:34 +0200 (CEST) Subject: [Python-checkins] r81749 - python/trunk/Lib/test/test_py3kwarn.py Message-ID: <20100605131834.0EF38EE9CE@mail.python.org> Author: mark.dickinson Date: Sat Jun 5 15:18:33 2010 New Revision: 81749 Log: Fix test_py3kwarn not to test for __cmp__-related DeprecationWarning. Modified: python/trunk/Lib/test/test_py3kwarn.py Modified: python/trunk/Lib/test/test_py3kwarn.py ============================================================================== --- python/trunk/Lib/test/test_py3kwarn.py (original) +++ python/trunk/Lib/test/test_py3kwarn.py Sat Jun 5 15:18:33 2010 @@ -251,9 +251,7 @@ # With object as the base class class WarnOnlyCmp(object): def __cmp__(self, other): pass - self.assertEqual(len(w.warnings), 1) - self.assertWarning(None, w, - "Overriding __cmp__ blocks inheritance of __hash__ in 3.x") + self.assertEqual(len(w.warnings), 0) w.reset() class WarnOnlyEq(object): def __eq__(self, other): pass @@ -264,9 +262,7 @@ class WarnCmpAndEq(object): def __cmp__(self, other): pass def __eq__(self, other): pass - self.assertEqual(len(w.warnings), 2) - self.assertWarning(None, w.warnings[0], - "Overriding __cmp__ blocks inheritance of __hash__ in 3.x") + self.assertEqual(len(w.warnings), 1) self.assertWarning(None, w, "Overriding __eq__ blocks inheritance of __hash__ in 3.x") w.reset() @@ -280,9 +276,7 @@ def __hash__(self): pass class WarnOnlyCmp(DefinesAllThree): def __cmp__(self, other): pass - self.assertEqual(len(w.warnings), 1) - self.assertWarning(None, w, - "Overriding __cmp__ blocks inheritance of __hash__ in 3.x") + self.assertEqual(len(w.warnings), 0) w.reset() class WarnOnlyEq(DefinesAllThree): def __eq__(self, other): pass @@ -293,9 +287,7 @@ class WarnCmpAndEq(DefinesAllThree): def __cmp__(self, other): pass def __eq__(self, other): pass - self.assertEqual(len(w.warnings), 2) - self.assertWarning(None, w.warnings[0], - "Overriding __cmp__ blocks inheritance of __hash__ in 3.x") + self.assertEqual(len(w.warnings), 1) self.assertWarning(None, w, "Overriding __eq__ blocks inheritance of __hash__ in 3.x") w.reset() From python-checkins at python.org Sat Jun 5 15:24:04 2010 From: python-checkins at python.org (mark.dickinson) Date: Sat, 5 Jun 2010 15:24:04 +0200 (CEST) Subject: [Python-checkins] r81750 - in python/branches/release26-maint: Lib/test/test_py3kwarn.py Message-ID: <20100605132404.BCFD5EE9E8@mail.python.org> Author: mark.dickinson Date: Sat Jun 5 15:24:04 2010 New Revision: 81750 Log: Merged revisions 81749 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81749 | mark.dickinson | 2010-06-05 14:18:33 +0100 (Sat, 05 Jun 2010) | 2 lines Fix test_py3kwarn not to test for __cmp__-related DeprecationWarning. ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Lib/test/test_py3kwarn.py Modified: python/branches/release26-maint/Lib/test/test_py3kwarn.py ============================================================================== --- python/branches/release26-maint/Lib/test/test_py3kwarn.py (original) +++ python/branches/release26-maint/Lib/test/test_py3kwarn.py Sat Jun 5 15:24:04 2010 @@ -248,9 +248,7 @@ # With object as the base class class WarnOnlyCmp(object): def __cmp__(self, other): pass - self.assertEqual(len(w.warnings), 1) - self.assertWarning(None, w, - "Overriding __cmp__ blocks inheritance of __hash__ in 3.x") + self.assertEqual(len(w.warnings), 0) w.reset() class WarnOnlyEq(object): def __eq__(self, other): pass @@ -261,9 +259,7 @@ class WarnCmpAndEq(object): def __cmp__(self, other): pass def __eq__(self, other): pass - self.assertEqual(len(w.warnings), 2) - self.assertWarning(None, w.warnings[0], - "Overriding __cmp__ blocks inheritance of __hash__ in 3.x") + self.assertEqual(len(w.warnings), 1) self.assertWarning(None, w, "Overriding __eq__ blocks inheritance of __hash__ in 3.x") w.reset() @@ -277,9 +273,7 @@ def __hash__(self): pass class WarnOnlyCmp(DefinesAllThree): def __cmp__(self, other): pass - self.assertEqual(len(w.warnings), 1) - self.assertWarning(None, w, - "Overriding __cmp__ blocks inheritance of __hash__ in 3.x") + self.assertEqual(len(w.warnings), 0) w.reset() class WarnOnlyEq(DefinesAllThree): def __eq__(self, other): pass @@ -290,9 +284,7 @@ class WarnCmpAndEq(DefinesAllThree): def __cmp__(self, other): pass def __eq__(self, other): pass - self.assertEqual(len(w.warnings), 2) - self.assertWarning(None, w.warnings[0], - "Overriding __cmp__ blocks inheritance of __hash__ in 3.x") + self.assertEqual(len(w.warnings), 1) self.assertWarning(None, w, "Overriding __eq__ blocks inheritance of __hash__ in 3.x") w.reset() From python-checkins at python.org Sat Jun 5 15:27:17 2010 From: python-checkins at python.org (mark.dickinson) Date: Sat, 5 Jun 2010 15:27:17 +0200 (CEST) Subject: [Python-checkins] r81751 - python/branches/py3k Message-ID: <20100605132717.463DFEE9E0@mail.python.org> Author: mark.dickinson Date: Sat Jun 5 15:27:17 2010 New Revision: 81751 Log: Blocked revisions 81749 via svnmerge ........ r81749 | mark.dickinson | 2010-06-05 14:18:33 +0100 (Sat, 05 Jun 2010) | 2 lines Fix test_py3kwarn not to test for __cmp__-related DeprecationWarning. ........ Modified: python/branches/py3k/ (props changed) From python-checkins at python.org Sat Jun 5 15:38:17 2010 From: python-checkins at python.org (michael.foord) Date: Sat, 5 Jun 2010 15:38:17 +0200 (CEST) Subject: [Python-checkins] r81752 - python/trunk/Lib/unittest/case.py Message-ID: <20100605133817.1FFC4F5EF@mail.python.org> Author: michael.foord Date: Sat Jun 5 15:38:16 2010 New Revision: 81752 Log: unittest.TestCase assertion methods inform you when they have omitted an over long diff on failure. Issue 8351. Modified: python/trunk/Lib/unittest/case.py Modified: python/trunk/Lib/unittest/case.py ============================================================================== --- python/trunk/Lib/unittest/case.py (original) +++ python/trunk/Lib/unittest/case.py Sat Jun 5 15:38:16 2010 @@ -14,6 +14,10 @@ __unittest = True + +DIFF_OMITTED = ('\nDiff is %s characters long. ' + 'Set self.maxDiff to None to see it.') + class SkipTest(Exception): """ Raise this exception in a test to skip it. @@ -700,7 +704,7 @@ max_diff = self.maxDiff if max_diff is None or len(diff) <= max_diff: return message + diff - return message + return message + (DIFF_OMITTED % len(diff)) def assertListEqual(self, list1, list2, msg=None): """A list-specific equality assertion. From python-checkins at python.org Sat Jun 5 15:48:27 2010 From: python-checkins at python.org (michael.foord) Date: Sat, 5 Jun 2010 15:48:27 +0200 (CEST) Subject: [Python-checkins] r81753 - in python/trunk/Lib/unittest: case.py test/test_case.py Message-ID: <20100605134827.69F29EEA4D@mail.python.org> Author: michael.foord Date: Sat Jun 5 15:48:27 2010 New Revision: 81753 Log: Fix unittest tests after previous commit. Modified: python/trunk/Lib/unittest/case.py python/trunk/Lib/unittest/test/test_case.py Modified: python/trunk/Lib/unittest/case.py ============================================================================== --- python/trunk/Lib/unittest/case.py (original) +++ python/trunk/Lib/unittest/case.py Sat Jun 5 15:48:27 2010 @@ -891,7 +891,7 @@ 'Second argument is not a string')) if first != second: - standardMsg = '%s != %s' % (safe_repr(d1, True), safe_repr(d2, True)) + standardMsg = '%s != %s' % (safe_repr(first, True), safe_repr(second, True)) diff = '\n' + ''.join(difflib.ndiff(first.splitlines(True), second.splitlines(True))) standardMsg = self._truncateMessage(standardMsg, diff) Modified: python/trunk/Lib/unittest/test/test_case.py ============================================================================== --- python/trunk/Lib/unittest/test/test_case.py (original) +++ python/trunk/Lib/unittest/test/test_case.py Sat Jun 5 15:48:27 2010 @@ -807,7 +807,7 @@ A test case is the smallest unit of testing. [...] You may provide your own implementation that does not subclass from TestCase, of course. """ - sample_text_error = b""" + sample_text_error = b"""\ - http://www.python.org/doc/2.3/lib/module-unittest.html ? ^ + http://www.python.org/doc/2.4.1/lib/module-unittest.html @@ -818,15 +818,18 @@ ? +++++++++++++++++++++ + own implementation that does not subclass from TestCase, of course. """ - + self.maxDiff = None for type_changer in (lambda x: x, lambda x: x.decode('utf8')): try: self.assertMultiLineEqual(type_changer(sample_text), type_changer(revised_sample_text)) except self.failureException, e: + # need to remove the first line of the error message + error = str(e).encode('utf8').split('\n', 1)[1] + # assertMultiLineEqual is hooked up as the default for # unicode strings - so we can't use it for this check - self.assertTrue(sample_text_error == str(e).encode('utf8')) + self.assertTrue(sample_text_error == error) def testAssertIsNone(self): self.assertIsNone(None) From python-checkins at python.org Sat Jun 5 15:49:56 2010 From: python-checkins at python.org (michael.foord) Date: Sat, 5 Jun 2010 15:49:56 +0200 (CEST) Subject: [Python-checkins] r81754 - in python/branches/py3k: Lib/unittest/case.py Message-ID: <20100605134956.E8DDEEE993@mail.python.org> Author: michael.foord Date: Sat Jun 5 15:49:56 2010 New Revision: 81754 Log: Merged revisions 81752 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81752 | michael.foord | 2010-06-05 14:38:16 +0100 (Sat, 05 Jun 2010) | 1 line unittest.TestCase assertion methods inform you when they have omitted an over long diff on failure. Issue 8351. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/unittest/case.py Modified: python/branches/py3k/Lib/unittest/case.py ============================================================================== --- python/branches/py3k/Lib/unittest/case.py (original) +++ python/branches/py3k/Lib/unittest/case.py Sat Jun 5 15:49:56 2010 @@ -13,6 +13,10 @@ __unittest = True + +DIFF_OMITTED = ('\nDiff is %s characters long. ' + 'Set self.maxDiff to None to see it.') + class SkipTest(Exception): """ Raise this exception in a test to skip it. @@ -711,7 +715,7 @@ max_diff = self.maxDiff if max_diff is None or len(diff) <= max_diff: return message + diff - return message + return message + (DIFF_OMITTED % len(diff)) def assertListEqual(self, list1, list2, msg=None): """A list-specific equality assertion. From python-checkins at python.org Sat Jun 5 15:57:23 2010 From: python-checkins at python.org (michael.foord) Date: Sat, 5 Jun 2010 15:57:23 +0200 (CEST) Subject: [Python-checkins] r81755 - in python/branches/py3k: Lib/unittest/case.py Lib/unittest/test/test_case.py Message-ID: <20100605135723.A1369EE9D9@mail.python.org> Author: michael.foord Date: Sat Jun 5 15:57:23 2010 New Revision: 81755 Log: Merged revisions 81753 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81753 | michael.foord | 2010-06-05 14:48:27 +0100 (Sat, 05 Jun 2010) | 1 line Fix unittest tests after previous commit. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/unittest/case.py python/branches/py3k/Lib/unittest/test/test_case.py Modified: python/branches/py3k/Lib/unittest/case.py ============================================================================== --- python/branches/py3k/Lib/unittest/case.py (original) +++ python/branches/py3k/Lib/unittest/case.py Sat Jun 5 15:57:23 2010 @@ -936,7 +936,7 @@ 'Second argument is not a string')) if first != second: - standardMsg = '%s != %s' % (safe_repr(d1, True), safe_repr(d2, True)) + standardMsg = '%s != %s' % (safe_repr(first, True), safe_repr(second, True)) diff = '\n' + ''.join(difflib.ndiff(first.splitlines(True), second.splitlines(True))) standardMsg = self._truncateMessage(standardMsg, diff) Modified: python/branches/py3k/Lib/unittest/test/test_case.py ============================================================================== --- python/branches/py3k/Lib/unittest/test/test_case.py (original) +++ python/branches/py3k/Lib/unittest/test/test_case.py Sat Jun 5 15:57:23 2010 @@ -776,7 +776,7 @@ A test case is the smallest unit of testing. [...] You may provide your own implementation that does not subclass from TestCase, of course. """ - sample_text_error = """ + sample_text_error = """\ - http://www.python.org/doc/2.3/lib/module-unittest.html ? ^ + http://www.python.org/doc/2.4.1/lib/module-unittest.html @@ -787,13 +787,16 @@ ? +++++++++++++++++++++ + own implementation that does not subclass from TestCase, of course. """ - + self.maxDiff = None try: self.assertMultiLineEqual(sample_text, revised_sample_text) except self.failureException as e: + # need to remove the first line of the error message + error = str(e).split('\n', 1)[1] + # no fair testing ourself with ourself, and assertEqual is used for strings # so can't use assertEqual either. Just use assertTrue. - self.assertTrue(sample_text_error == str(e)) + self.assertTrue(sample_text_error == error) def testAssertIsNone(self): self.assertIsNone(None) From python-checkins at python.org Sat Jun 5 16:54:26 2010 From: python-checkins at python.org (alexander.belopolsky) Date: Sat, 5 Jun 2010 16:54:26 +0200 (CEST) Subject: [Python-checkins] r81756 - in python/trunk: Doc/library/time.rst Misc/NEWS Modules/timemodule.c Message-ID: <20100605145426.57A41C974@mail.python.org> Author: alexander.belopolsky Date: Sat Jun 5 16:54:26 2010 New Revision: 81756 Log: Issue #8899: time.struct_time now has class and atribute docstrings. Modified: python/trunk/Doc/library/time.rst python/trunk/Misc/NEWS python/trunk/Modules/timemodule.c Modified: python/trunk/Doc/library/time.rst ============================================================================== --- python/trunk/Doc/library/time.rst (original) +++ python/trunk/Doc/library/time.rst Sat Jun 5 16:54:26 2010 @@ -87,25 +87,26 @@ +=======+===================+=================================+ | 0 | :attr:`tm_year` | (for example, 1993) | +-------+-------------------+---------------------------------+ - | 1 | :attr:`tm_mon` | range [1,12] | + | 1 | :attr:`tm_mon` | range [1, 12] | +-------+-------------------+---------------------------------+ - | 2 | :attr:`tm_mday` | range [1,31] | + | 2 | :attr:`tm_mday` | range [1, 31] | +-------+-------------------+---------------------------------+ - | 3 | :attr:`tm_hour` | range [0,23] | + | 3 | :attr:`tm_hour` | range [0, 23] | +-------+-------------------+---------------------------------+ - | 4 | :attr:`tm_min` | range [0,59] | + | 4 | :attr:`tm_min` | range [0, 59] | +-------+-------------------+---------------------------------+ - | 5 | :attr:`tm_sec` | range [0,61]; see **(1)** in | + | 5 | :attr:`tm_sec` | range [0, 61]; see **(1)** in | | | | :func:`strftime` description | +-------+-------------------+---------------------------------+ - | 6 | :attr:`tm_wday` | range [0,6], Monday is 0 | + | 6 | :attr:`tm_wday` | range [0, 6], Monday is 0 | +-------+-------------------+---------------------------------+ - | 7 | :attr:`tm_yday` | range [1,366] | + | 7 | :attr:`tm_yday` | range [1, 366] | +-------+-------------------+---------------------------------+ | 8 | :attr:`tm_isdst` | 0, 1 or -1; see below | +-------+-------------------+---------------------------------+ - Note that unlike the C structure, the month value is a range of 1-12, not 0-11. + Note that unlike the C structure, the month value is a range of [1, 12], + not [0, 11]. A year value will be handled as described under "Year 2000 (Y2K) issues" above. A ``-1`` argument as the daylight savings flag, passed to :func:`mktime` will usually result in the correct daylight savings state to be filled in. Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Sat Jun 5 16:54:26 2010 @@ -52,6 +52,8 @@ Library ------- +- Issue #8899: time.struct_time now has class and atribute docstrings. + - Issue #4487: email now accepts as charset aliases all codec aliases accepted by the codecs module. Modified: python/trunk/Modules/timemodule.c ============================================================================== --- python/trunk/Modules/timemodule.c (original) +++ python/trunk/Modules/timemodule.c Sat Jun 5 16:54:26 2010 @@ -216,21 +216,27 @@ a floating point number for subsecond precision."); static PyStructSequence_Field struct_time_type_fields[] = { - {"tm_year", NULL}, - {"tm_mon", NULL}, - {"tm_mday", NULL}, - {"tm_hour", NULL}, - {"tm_min", NULL}, - {"tm_sec", NULL}, - {"tm_wday", NULL}, - {"tm_yday", NULL}, - {"tm_isdst", NULL}, + {"tm_year", "year, for example, 1993"}, + {"tm_mon", "month of year, range [1, 12]"}, + {"tm_mday", "day of month, range [1, 31]"}, + {"tm_hour", "hours, range [0, 23]"}, + {"tm_min", "minutes, range [0, 59]"}, + {"tm_sec", "seconds, range [0, 61])"}, + {"tm_wday", "day of week, range [0, 6], Monday is 0"}, + {"tm_yday", "day of year, range [1, 366]"}, + {"tm_isdst", "1 if summer time is in effect, 0 if not, and -1 if unknown"}, {0} }; static PyStructSequence_Desc struct_time_type_desc = { "time.struct_time", - NULL, + "The time value as returned by gmtime(), localtime(), and strptime(), and\n" + " accepted by asctime(), mktime() and strftime(). May be considered as a\n" + " sequence of 9 integers.\n\n" + " Note that several fields' values are not the same as those defined by\n" + " the C language standard for struct tm. For example, the value of the\n" + " field tm_year is the actual year, not year - 1900. See individual\n" + " fields' descriptions for details.", struct_time_type_fields, 9, }; From python-checkins at python.org Sat Jun 5 17:04:51 2010 From: python-checkins at python.org (alexander.belopolsky) Date: Sat, 5 Jun 2010 17:04:51 +0200 (CEST) Subject: [Python-checkins] r81757 - in python/branches/py3k: Doc/library/time.rst Misc/NEWS Modules/timemodule.c Message-ID: <20100605150451.7934DEEA29@mail.python.org> Author: alexander.belopolsky Date: Sat Jun 5 17:04:51 2010 New Revision: 81757 Log: Merged revisions 81756 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81756 | alexander.belopolsky | 2010-06-05 10:54:26 -0400 (Sat, 05 Jun 2010) | 1 line Issue #8899: time.struct_time now has class and atribute docstrings. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Doc/library/time.rst python/branches/py3k/Misc/NEWS python/branches/py3k/Modules/timemodule.c Modified: python/branches/py3k/Doc/library/time.rst ============================================================================== --- python/branches/py3k/Doc/library/time.rst (original) +++ python/branches/py3k/Doc/library/time.rst Sat Jun 5 17:04:51 2010 @@ -81,30 +81,31 @@ :func:`gmtime`, :func:`localtime`, and :func:`strptime` also offer attribute names for individual fields. - +-------+------------------+------------------------------+ - | Index | Attribute | Values | - +=======+==================+==============================+ - | 0 | :attr:`tm_year` | (for example, 1993) | - +-------+------------------+------------------------------+ - | 1 | :attr:`tm_mon` | range [1,12] | - +-------+------------------+------------------------------+ - | 2 | :attr:`tm_mday` | range [1,31] | - +-------+------------------+------------------------------+ - | 3 | :attr:`tm_hour` | range [0,23] | - +-------+------------------+------------------------------+ - | 4 | :attr:`tm_min` | range [0,59] | - +-------+------------------+------------------------------+ - | 5 | :attr:`tm_sec` | range [0,61]; see **(1)** in | - | | | :func:`strftime` description | - +-------+------------------+------------------------------+ - | 6 | :attr:`tm_wday` | range [0,6], Monday is 0 | - +-------+------------------+------------------------------+ - | 7 | :attr:`tm_yday` | range [1,366] | - +-------+------------------+------------------------------+ - | 8 | :attr:`tm_isdst` | 0, 1 or -1; see below | - +-------+------------------+------------------------------+ + +-------+-------------------+---------------------------------+ + | Index | Attribute | Values | + +=======+===================+=================================+ + | 0 | :attr:`tm_year` | (for example, 1993) | + +-------+-------------------+---------------------------------+ + | 1 | :attr:`tm_mon` | range [1, 12] | + +-------+-------------------+---------------------------------+ + | 2 | :attr:`tm_mday` | range [1, 31] | + +-------+-------------------+---------------------------------+ + | 3 | :attr:`tm_hour` | range [0, 23] | + +-------+-------------------+---------------------------------+ + | 4 | :attr:`tm_min` | range [0, 59] | + +-------+-------------------+---------------------------------+ + | 5 | :attr:`tm_sec` | range [0, 61]; see **(1)** in | + | | | :func:`strftime` description | + +-------+-------------------+---------------------------------+ + | 6 | :attr:`tm_wday` | range [0, 6], Monday is 0 | + +-------+-------------------+---------------------------------+ + | 7 | :attr:`tm_yday` | range [1, 366] | + +-------+-------------------+---------------------------------+ + | 8 | :attr:`tm_isdst` | 0, 1 or -1; see below | + +-------+-------------------+---------------------------------+ - Note that unlike the C structure, the month value is a range of 1-12, not 0-11. + Note that unlike the C structure, the month value is a range of [1, 12], + not [0, 11]. A year value will be handled as described under "Year 2000 (Y2K) issues" above. A ``-1`` argument as the daylight savings flag, passed to :func:`mktime` will usually result in the correct daylight savings state to be filled in. Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Sat Jun 5 17:04:51 2010 @@ -398,6 +398,8 @@ Library ------- +- Issue #8899: time.struct_time now has class and atribute docstrings. + - Issue #6470: Drop UNC prefix in FixTk. - Issue #4768: base64 encoded email body parts were incorrectly stored as Modified: python/branches/py3k/Modules/timemodule.c ============================================================================== --- python/branches/py3k/Modules/timemodule.c (original) +++ python/branches/py3k/Modules/timemodule.c Sat Jun 5 17:04:51 2010 @@ -208,21 +208,27 @@ a floating point number for subsecond precision."); static PyStructSequence_Field struct_time_type_fields[] = { - {"tm_year", NULL}, - {"tm_mon", NULL}, - {"tm_mday", NULL}, - {"tm_hour", NULL}, - {"tm_min", NULL}, - {"tm_sec", NULL}, - {"tm_wday", NULL}, - {"tm_yday", NULL}, - {"tm_isdst", NULL}, + {"tm_year", "year, for example, 1993"}, + {"tm_mon", "month of year, range [1, 12]"}, + {"tm_mday", "day of month, range [1, 31]"}, + {"tm_hour", "hours, range [0, 23]"}, + {"tm_min", "minutes, range [0, 59]"}, + {"tm_sec", "seconds, range [0, 61])"}, + {"tm_wday", "day of week, range [0, 6], Monday is 0"}, + {"tm_yday", "day of year, range [1, 366]"}, + {"tm_isdst", "1 if summer time is in effect, 0 if not, and -1 if unknown"}, {0} }; static PyStructSequence_Desc struct_time_type_desc = { "time.struct_time", - NULL, + "The time value as returned by gmtime(), localtime(), and strptime(), and\n" + " accepted by asctime(), mktime() and strftime(). May be considered as a\n" + " sequence of 9 integers.\n\n" + " Note that several fields' values are not the same as those defined by\n" + " the C language standard for struct tm. For example, the value of the\n" + " field tm_year is the actual year, not year - 1900. See individual\n" + " fields' descriptions for details.", struct_time_type_fields, 9, }; From python-checkins at python.org Sat Jun 5 19:51:07 2010 From: python-checkins at python.org (ezio.melotti) Date: Sat, 5 Jun 2010 19:51:07 +0200 (CEST) Subject: [Python-checkins] r81758 - in python/trunk: Lib/test/test_codeccallbacks.py Lib/test/test_unicode.py Objects/unicodeobject.c Message-ID: <20100605175107.6C11FEE993@mail.python.org> Author: ezio.melotti Date: Sat Jun 5 19:51:07 2010 New Revision: 81758 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) Add code and tests to reject surrogates (U+D800-U+DFFF) as defined in RFC 3629, but leave it commented out since it's not backward compatible; 4) Change the error messages "unexpected code byte" to "invalid start byte" and "invalid data" to "invalid continuation byte"; 5) Add an extensive set of tests in test_unicode; 6) Fix test_codeccallbacks because it was failing after this change. Modified: python/trunk/Lib/test/test_codeccallbacks.py python/trunk/Lib/test/test_unicode.py python/trunk/Objects/unicodeobject.c Modified: python/trunk/Lib/test/test_codeccallbacks.py ============================================================================== --- python/trunk/Lib/test/test_codeccallbacks.py (original) +++ python/trunk/Lib/test/test_codeccallbacks.py Sat Jun 5 19:51:07 2010 @@ -153,28 +153,30 @@ sout += "\\U%08x" % sys.maxunicode 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("\xc0\x80"): + if exc.object[exc.start:exc.start+2] == "\xc0\x80": return (u"\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 = "a\x00b\xc0\x80c\xc3\xbc\xc0\x80\xc0\x80" sout = u"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 = "\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/trunk/Lib/test/test_unicode.py ============================================================================== --- python/trunk/Lib/test/test_unicode.py (original) +++ python/trunk/Lib/test/test_unicode.py Sat Jun 5 19:51:07 2010 @@ -600,6 +600,164 @@ # * strict decoding testing for all of the # UTF8_ERROR cases in PyUnicode_DecodeUTF8 + def test_utf8_decode_valid_sequences(self): + sequences = [ + # single byte + ('\x00', u'\x00'), ('a', u'a'), ('\x7f', u'\x7f'), + # 2 bytes + ('\xc2\x80', u'\x80'), ('\xdf\xbf', u'\u07ff'), + # 3 bytes + ('\xe0\xa0\x80', u'\u0800'), ('\xed\x9f\xbf', u'\ud7ff'), + ('\xee\x80\x80', u'\uE000'), ('\xef\xbf\xbf', u'\uffff'), + # 4 bytes + ('\xF0\x90\x80\x80', u'\U00010000'), + ('\xf4\x8f\xbf\xbf', u'\U0010FFFF') + ] + for seq, res in sequences: + self.assertEqual(seq.decode('utf-8'), res) + + for ch in map(unichr, range(0, sys.maxunicode)): + self.assertEqual(ch, ch.encode('utf-8').decode('utf-8')) + + def test_utf8_decode_invalid_sequences(self): + # continuation bytes in a sequence of 2, 3, or 4 bytes + continuation_bytes = map(chr, range(0x80, 0xC0)) + # start bytes of a 2-byte sequence equivalent to codepoints < 0x7F + invalid_2B_seq_start_bytes = map(chr, range(0xC0, 0xC2)) + # start bytes of a 4-byte sequence equivalent to codepoints > 0x10FFFF + invalid_4B_seq_start_bytes = map(chr, range(0xF5, 0xF8)) + invalid_start_bytes = ( + continuation_bytes + invalid_2B_seq_start_bytes + + invalid_4B_seq_start_bytes + map(chr, 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+'\x80'+cb3).decode, 'utf-8') + + for cb in map(chr, range(0x80, 0xA0)): + self.assertRaises(UnicodeDecodeError, + ('\xE0'+cb+'\x80').decode, 'utf-8') + self.assertRaises(UnicodeDecodeError, + ('\xE0'+cb+'\xBF').decode, 'utf-8') + # 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 + #for cb in map(chr, range(0xA0, 0xC0)): + #sys.__stdout__.write('\\xED\\x%02x\\x80\n' % ord(cb)) + #self.assertRaises(UnicodeDecodeError, + #('\xED'+cb+'\x80').decode, 'utf-8') + #self.assertRaises(UnicodeDecodeError, + #('\xED'+cb+'\xBF').decode, 'utf-8') + for cb in map(chr, range(0x80, 0x90)): + self.assertRaises(UnicodeDecodeError, + ('\xF0'+cb+'\x80\x80').decode, 'utf-8') + self.assertRaises(UnicodeDecodeError, + ('\xF0'+cb+'\xBF\xBF').decode, 'utf-8') + for cb in map(chr, range(0x90, 0xC0)): + self.assertRaises(UnicodeDecodeError, + ('\xF4'+cb+'\x80\x80').decode, 'utf-8') + self.assertRaises(UnicodeDecodeError, + ('\xF4'+cb+'\xBF\xBF').decode, 'utf-8') + + def test_issue8271(self): + # Issue #8271: when a byte sequence is invalid, only the start byte + # and all the valid continuation bytes should be replaced by U+FFFD, + # not 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 = u'\ufffd' + sequences = [ + # invalid start bytes + ('\x80', FFFD), # continuation byte + ('\x80\x80', FFFD*2), # 2 continuation bytes + ('\xc0', FFFD), + ('\xc0\xc0', FFFD*2), + ('\xc1', FFFD), + ('\xc1\xc0', FFFD*2), + ('\xc0\xc1', FFFD*2), + # with start byte of a 2-byte sequence + ('\xc2', FFFD), # only the start byte + ('\xc2\xc2', FFFD*2), # 2 start bytes + ('\xc2\xc2\xc2', FFFD*3), # 2 start bytes + ('\xc2\x41', FFFD+'A'), # invalid continuation byte + # with start byte of a 3-byte sequence + ('\xe1', FFFD), # only the start byte + ('\xe1\xe1', FFFD*2), # 2 start bytes + ('\xe1\xe1\xe1', FFFD*3), # 3 start bytes + ('\xe1\xe1\xe1\xe1', FFFD*4), # 4 start bytes + ('\xe1\x80', FFFD), # only 1 continuation byte + ('\xe1\x41', FFFD+'A'), # invalid continuation byte + ('\xe1\x41\x80', FFFD+'A'+FFFD), # invalid cb followed by valid cb + ('\xe1\x41\x41', FFFD+'AA'), # 2 invalid continuation bytes + ('\xe1\x80\x41', FFFD+'A'), # only 1 valid continuation byte + ('\xe1\x80\xe1\x41', FFFD*2+'A'), # 1 valid and the other invalid + ('\xe1\x41\xe1\x80', FFFD+'A'+FFFD), # 1 invalid and the other valid + # with start byte of a 4-byte sequence + ('\xf1', FFFD), # only the start byte + ('\xf1\xf1', FFFD*2), # 2 start bytes + ('\xf1\xf1\xf1', FFFD*3), # 3 start bytes + ('\xf1\xf1\xf1\xf1', FFFD*4), # 4 start bytes + ('\xf1\xf1\xf1\xf1\xf1', FFFD*5), # 5 start bytes + ('\xf1\x80', FFFD), # only 1 continuation bytes + ('\xf1\x80\x80', FFFD), # only 2 continuation bytes + ('\xf1\x80\x41', FFFD+'A'), # 1 valid cb and 1 invalid + ('\xf1\x80\x41\x41', FFFD+'AA'), # 1 valid cb and 1 invalid + ('\xf1\x80\x80\x41', FFFD+'A'), # 2 valid cb and 1 invalid + ('\xf1\x41\x80', FFFD+'A'+FFFD), # 1 invalid cv and 1 valid + ('\xf1\x41\x80\x80', FFFD+'A'+FFFD*2), # 1 invalid cb and 2 invalid + ('\xf1\x41\x80\x41', FFFD+'A'+FFFD+'A'), # 2 invalid cb and 1 invalid + ('\xf1\x41\x41\x80', FFFD+'AA'+FFFD), # 1 valid cb and 1 invalid + ('\xf1\x41\xf1\x80', FFFD+'A'+FFFD), + ('\xf1\x41\x80\xf1', FFFD+'A'+FFFD*2), + ('\xf1\xf1\x80\x41', FFFD*2+'A'), + ('\xf1\x41\xf1\xf1', FFFD+'A'+FFFD*2), + # with invalid start byte of a 4-byte sequence (rfc2279) + ('\xf5', FFFD), # only the start byte + ('\xf5\xf5', FFFD*2), # 2 start bytes + ('\xf5\x80', FFFD*2), # only 1 continuation byte + ('\xf5\x80\x80', FFFD*3), # only 2 continuation byte + ('\xf5\x80\x80\x80', FFFD*4), # 3 continuation bytes + ('\xf5\x80\x41', FFFD*2+'A'), # 1 valid cb and 1 invalid + ('\xf5\x80\x41\xf5', FFFD*2+'A'+FFFD), + ('\xf5\x41\x80\x80\x41', FFFD+'A'+FFFD*2+'A'), + # with invalid start byte of a 5-byte sequence (rfc2279) + ('\xf8', FFFD), # only the start byte + ('\xf8\xf8', FFFD*2), # 2 start bytes + ('\xf8\x80', FFFD*2), # only one continuation byte + ('\xf8\x80\x41', FFFD*2 + 'A'), # 1 valid cb and 1 invalid + ('\xf8\x80\x80\x80\x80', FFFD*5), # invalid 5 bytes seq with 5 bytes + # with invalid start byte of a 6-byte sequence (rfc2279) + ('\xfc', FFFD), # only the start byte + ('\xfc\xfc', FFFD*2), # 2 start bytes + ('\xfc\x80\x80', FFFD*3), # only 2 continuation bytes + ('\xfc\x80\x80\x80\x80\x80', FFFD*6), # 6 continuation bytes + # invalid start byte + ('\xfe', FFFD), + ('\xfe\x80\x80', FFFD*3), + # other sequences + ('\xf1\x80\x41\x42\x43', u'\ufffd\x41\x42\x43'), + ('\xf1\x80\xff\x42\x43', u'\ufffd\ufffd\x42\x43'), + ('\xf1\x80\xc2\x81\x43', u'\ufffd\x81\x43'), + ('\x61\xF1\x80\x80\xE1\x80\xC2\x62\x80\x63\x80\xBF\x64', + u'\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').decode('utf-8', 'replace'), res+'b') + self.assertEqual(seq.decode('utf-8', 'ignore'), + res.replace(u'\uFFFD', '')) + def test_codecs_idna(self): # Test whether trailing dot is preserved self.assertEqual(u"www.python.org.".encode("idna"), "www.python.org.") Modified: python/trunk/Objects/unicodeobject.c ============================================================================== --- python/trunk/Objects/unicodeobject.c (original) +++ python/trunk/Objects/unicodeobject.c Sat Jun 5 19:51:07 2010 @@ -1863,24 +1863,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, @@ -1897,6 +1897,7 @@ { const char *starts = s; int n; + int k; Py_ssize_t startinpos; Py_ssize_t endinpos; Py_ssize_t outpos; @@ -1939,7 +1940,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; } } @@ -1947,7 +1950,7 @@ switch (n) { case 0: - errmsg = "unexpected code byte"; + errmsg = "invalid start byte"; startinpos = s-starts; endinpos = startinpos+1; goto utf8Error; @@ -1960,70 +1963,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) { - /* Note: UTF-8 encodings of surrogates are considered - legal UTF-8 sequences; - - XXX For wide builds (UCS-4) we should probably try - to recombine the surrogates into a single code - unit. - */ - 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 @@ -2039,13 +2039,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 benjamin at python.org Sat Jun 5 20:55:09 2010 From: benjamin at python.org (Benjamin Peterson) Date: Sat, 5 Jun 2010 13:55:09 -0500 Subject: [Python-checkins] r81706 - in python/trunk: Lib/test/test_descr.py Objects/abstract.c In-Reply-To: <4C0A05E5.3030105@gmail.com> References: <20100605003251.2A9BCEECF3@mail.python.org> <4C0A05E5.3030105@gmail.com> Message-ID: 2010/6/5 Nick Coghlan : > On 05/06/10 10:32, benjamin.peterson wrote: >> >> - ? ?/* Initialize cached value */ >> - ? ?if (str__format__ == NULL) { >> - ? ? ? ?/* Initialize static variable needed by _PyType_Lookup */ >> - ? ? ? ?str__format__ = PyString_InternFromString("__format__"); >> - ? ? ? ?if (str__format__ == NULL) >> - ? ? ? ? ? ?goto done; >> - ? ?} >> - > > Why kill the microoptimisation here? Looking the string up in the intern > dict every time (as these changes do) is a waste of cycles. Since avoiding > it is pretty easy using this common idiom, it's generally worth doing. Yes, but that's only applicable to classic classes, which I can't say I care much about. -- Regards, Benjamin From python-checkins at python.org Sat Jun 5 21:21:32 2010 From: python-checkins at python.org (ezio.melotti) Date: Sat, 5 Jun 2010 21:21:32 +0200 (CEST) Subject: [Python-checkins] r81759 - in python/trunk: Lib/test/test_unicode.py Misc/NEWS Message-ID: <20100605192132.CB127EE99D@mail.python.org> Author: ezio.melotti Date: Sat Jun 5 21:21:32 2010 New Revision: 81759 Log: Add a NEWS entry for r81758 and clarify a comment. Modified: python/trunk/Lib/test/test_unicode.py python/trunk/Misc/NEWS Modified: python/trunk/Lib/test/test_unicode.py ============================================================================== --- python/trunk/Lib/test/test_unicode.py (original) +++ python/trunk/Lib/test/test_unicode.py Sat Jun 5 21:21:32 2010 @@ -670,9 +670,9 @@ ('\xF4'+cb+'\xBF\xBF').decode, 'utf-8') def test_issue8271(self): - # Issue #8271: when a byte sequence is invalid, only the start byte - # and all the valid continuation bytes should be replaced by U+FFFD, - # not the number of bytes specified by the start byte. + # 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 = u'\ufffd' Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Sat Jun 5 21:21:32 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 #8627: Remove bogus "Overriding __cmp__ blocks inheritance of __hash__ in 3.x" warning. Also fix "XXX undetected error" that arises from the "Overriding __eq__ blocks inheritance ..." warning From python-checkins at python.org Sat Jun 5 21:38:42 2010 From: python-checkins at python.org (michael.foord) Date: Sat, 5 Jun 2010 21:38:42 +0200 (CEST) Subject: [Python-checkins] r81760 - python/trunk/Lib/unittest/suite.py Message-ID: <20100605193842.72663C9AF@mail.python.org> Author: michael.foord Date: Sat Jun 5 21:38:42 2010 New Revision: 81760 Log: Issue 8302. SkipTest exception is setUpClass or setUpModule is now reported as a skip rather than an error. Modified: python/trunk/Lib/unittest/suite.py Modified: python/trunk/Lib/unittest/suite.py ============================================================================== --- python/trunk/Lib/unittest/suite.py (original) +++ python/trunk/Lib/unittest/suite.py Sat Jun 5 21:38:42 2010 @@ -130,9 +130,12 @@ if setUpClass is not None: try: setUpClass() - except: + except Exception as e: currentClass._classSetupFailed = True - self._addClassSetUpError(result, currentClass) + className = util.strclass(currentClass) + errorName = 'classSetUp (%s)' % className + self._addClassOrModuleLevelException(result, e, errorName) + def _get_previous_module(self, result): previousModule = None @@ -150,7 +153,6 @@ self._handleModuleTearDown(result) - result._moduleSetUpFailed = False try: module = sys.modules[currentModule] @@ -160,10 +162,18 @@ if setUpModule is not None: try: setUpModule() - except: + except Exception, e: result._moduleSetUpFailed = True - error = _ErrorHolder('setUpModule (%s)' % currentModule) - result.addError(error, sys.exc_info()) + errorName = 'setUpModule (%s)' % currentModule + self._addClassOrModuleLevelException(result, e, errorName) + + def _addClassOrModuleLevelException(self, result, exception, errorName): + error = _ErrorHolder(errorName) + addSkip = getattr(result, 'addSkip', None) + if addSkip is not None and isinstance(exception, case.SkipTest): + addSkip(error, str(exception)) + else: + result.addError(error, sys.exc_info()) def _handleModuleTearDown(self, result): previousModule = self._get_previous_module(result) @@ -181,9 +191,9 @@ if tearDownModule is not None: try: tearDownModule() - except: - error = _ErrorHolder('tearDownModule (%s)' % previousModule) - result.addError(error, sys.exc_info()) + except Exception as e: + errorName = 'tearDownModule (%s)' % previousModule + self._addClassOrModuleLevelException(result, e, errorName) def _tearDownPreviousClass(self, test, result): previousClass = getattr(result, '_previousTestClass', None) @@ -201,18 +211,10 @@ if tearDownClass is not None: try: tearDownClass() - except: - self._addClassTearDownError(result) - - def _addClassTearDownError(self, result): - className = util.strclass(result._previousTestClass) - error = _ErrorHolder('classTearDown (%s)' % className) - result.addError(error, sys.exc_info()) - - def _addClassSetUpError(self, result, klass): - className = util.strclass(klass) - error = _ErrorHolder('classSetUp (%s)' % className) - result.addError(error, sys.exc_info()) + except Exception, e: + className = util.strclass(previousClass) + errorName = 'classTearDown (%s)' % className + self._addClassOrModuleLevelException(result, e, errorName) class _ErrorHolder(object): From python-checkins at python.org Sat Jun 5 21:51:38 2010 From: python-checkins at python.org (michael.foord) Date: Sat, 5 Jun 2010 21:51:38 +0200 (CEST) Subject: [Python-checkins] r81761 - python/trunk/Misc/NEWS Message-ID: <20100605195138.EA83FEEA2@mail.python.org> Author: michael.foord Date: Sat Jun 5 21:51:38 2010 New Revision: 81761 Log: Updated NEWS file. Modified: python/trunk/Misc/NEWS Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Sat Jun 5 21:51:38 2010 @@ -60,6 +60,13 @@ Library ------- +- Issue #8302: SkipTest in unittest.TestCase.setUpClass or setUpModule is now + reported as a skip rather than an error. + +- Issue #8351: Excessively large diffs due to + unittest.TestCase.assertSequenceEqual are no longer included in failure + reports. + - Issue #8899: time.struct_time now has class and atribute docstrings. - Issue #4487: email now accepts as charset aliases all codec aliases From python-checkins at python.org Sat Jun 5 21:58:25 2010 From: python-checkins at python.org (michael.foord) Date: Sat, 5 Jun 2010 21:58:25 +0200 (CEST) Subject: [Python-checkins] r81762 - python/branches/py3k Message-ID: <20100605195825.3885CEE993@mail.python.org> Author: michael.foord Date: Sat Jun 5 21:58:25 2010 New Revision: 81762 Log: Blocked revisions 81761 via svnmerge ........ r81761 | michael.foord | 2010-06-05 20:51:38 +0100 (Sat, 05 Jun 2010) | 1 line Updated NEWS file. ........ Modified: python/branches/py3k/ (props changed) From python-checkins at python.org Sat Jun 5 22:33:43 2010 From: python-checkins at python.org (michael.foord) Date: Sat, 5 Jun 2010 22:33:43 +0200 (CEST) Subject: [Python-checkins] r81763 - python/trunk/Lib/unittest/test/test_case.py Message-ID: <20100605203343.7A882EEA6E@mail.python.org> Author: michael.foord Date: Sat Jun 5 22:33:43 2010 New Revision: 81763 Log: Tests for unittest.TestCase.maxDiff. Modified: python/trunk/Lib/unittest/test/test_case.py Modified: python/trunk/Lib/unittest/test/test_case.py ============================================================================== --- python/trunk/Lib/unittest/test/test_case.py (original) +++ python/trunk/Lib/unittest/test/test_case.py Sat Jun 5 22:33:43 2010 @@ -596,6 +596,8 @@ seq2 = 'b' + 'x' * 80**2 diff = '\n'.join(difflib.ndiff(pprint.pformat(seq1).splitlines(), pprint.pformat(seq2).splitlines())) + # the +1 is the leading \n added by assertSequenceEqual + omitted = unittest.case.DIFF_OMITTED % (len(diff) + 1,) self.maxDiff = len(diff)//2 try: @@ -605,6 +607,7 @@ else: self.fail('assertSequenceEqual did not fail.') self.assertTrue(len(msg) < len(diff)) + self.assertIn(omitted, msg) self.maxDiff = len(diff) * 2 try: @@ -614,6 +617,7 @@ else: self.fail('assertSequenceEqual did not fail.') self.assertTrue(len(msg) > len(diff)) + self.assertNotIn(omitted, msg) self.maxDiff = None try: @@ -623,6 +627,41 @@ else: self.fail('assertSequenceEqual did not fail.') self.assertTrue(len(msg) > len(diff)) + self.assertNotIn(omitted, msg) + + def testTruncateMessage(self): + self.maxDiff = 1 + message = self._truncateMessage('foo', 'bar') + omitted = unittest.case.DIFF_OMITTED % len('bar') + self.assertEqual(message, 'foo' + omitted) + + self.maxDiff = None + message = self._truncateMessage('foo', 'bar') + self.assertEqual(message, 'foobar') + + def testAssertDictEqualTruncates(self): + test = unittest.TestCase('assertEqual') + def truncate(msg, diff): + return 'foo' + test._truncateMessage = truncate + try: + test.assertDictEqual({}, {1: 0}) + except self.failureException as e: + self.assertEqual(str(e), 'foo') + else: + self.fail('assertDictEqual did not fail') + + def testAssertMultiLineEqualTruncates(self): + test = unittest.TestCase('assertEqual') + def truncate(msg, diff): + return 'foo' + test._truncateMessage = truncate + try: + test.assertMultiLineEqual('foo', 'bar') + except self.failureException as e: + self.assertEqual(str(e), 'foo') + else: + self.fail('assertMultiLineEqual did not fail') def testAssertItemsEqual(self): a = object() From python-checkins at python.org Sat Jun 5 22:59:00 2010 From: python-checkins at python.org (michael.foord) Date: Sat, 5 Jun 2010 22:59:00 +0200 (CEST) Subject: [Python-checkins] r81764 - in python/trunk/Lib/unittest: suite.py test/test_case.py test/test_setups.py Message-ID: <20100605205900.7B510EEA06@mail.python.org> Author: michael.foord Date: Sat Jun 5 22:59:00 2010 New Revision: 81764 Log: Tests for issue 8302, skipped test in a setUpClass or a setUpModule are reported as skips rather than errors. Modified: python/trunk/Lib/unittest/suite.py python/trunk/Lib/unittest/test/test_case.py python/trunk/Lib/unittest/test/test_setups.py Modified: python/trunk/Lib/unittest/suite.py ============================================================================== --- python/trunk/Lib/unittest/suite.py (original) +++ python/trunk/Lib/unittest/suite.py Sat Jun 5 22:59:00 2010 @@ -133,7 +133,7 @@ except Exception as e: currentClass._classSetupFailed = True className = util.strclass(currentClass) - errorName = 'classSetUp (%s)' % className + errorName = 'setUpClass (%s)' % className self._addClassOrModuleLevelException(result, e, errorName) @@ -213,7 +213,7 @@ tearDownClass() except Exception, e: className = util.strclass(previousClass) - errorName = 'classTearDown (%s)' % className + errorName = 'tearDownClass (%s)' % className self._addClassOrModuleLevelException(result, e, errorName) Modified: python/trunk/Lib/unittest/test/test_case.py ============================================================================== --- python/trunk/Lib/unittest/test/test_case.py (original) +++ python/trunk/Lib/unittest/test/test_case.py Sat Jun 5 22:59:00 2010 @@ -639,6 +639,10 @@ message = self._truncateMessage('foo', 'bar') self.assertEqual(message, 'foobar') + self.maxDiff = 4 + message = self._truncateMessage('foo', 'bar') + self.assertEqual(message, 'foobar') + def testAssertDictEqualTruncates(self): test = unittest.TestCase('assertEqual') def truncate(msg, diff): Modified: python/trunk/Lib/unittest/test/test_setups.py ============================================================================== --- python/trunk/Lib/unittest/test/test_setups.py (original) +++ python/trunk/Lib/unittest/test/test_setups.py Sat Jun 5 22:59:00 2010 @@ -112,7 +112,7 @@ self.assertEqual(len(result.errors), 1) error, _ = result.errors[0] self.assertEqual(str(error), - 'classSetUp (%s.BrokenTest)' % __name__) + 'setUpClass (%s.BrokenTest)' % __name__) def test_error_in_teardown_class(self): class Test(unittest.TestCase): @@ -145,7 +145,7 @@ error, _ = result.errors[0] self.assertEqual(str(error), - 'classTearDown (%s.Test)' % __name__) + 'tearDownClass (%s.Test)' % __name__) def test_class_not_torndown_when_setup_fails(self): class Test(unittest.TestCase): @@ -400,6 +400,45 @@ error, _ = result.errors[0] self.assertEqual(str(error), 'tearDownModule (Module)') + def test_skiptest_in_setupclass(self): + class Test(unittest.TestCase): + @classmethod + def setUpClass(cls): + raise unittest.SkipTest('foo') + def test_one(self): + pass + def test_two(self): + pass + + result = self.runTests(Test) + self.assertEqual(result.testsRun, 0) + self.assertEqual(len(result.errors), 0) + self.assertEqual(len(result.skipped), 1) + skipped = result.skipped[0][0] + self.assertEqual(str(skipped), 'setUpClass (%s.Test)' % __name__) + + def test_skiptest_in_setupmodule(self): + class Test(unittest.TestCase): + def test_one(self): + pass + def test_two(self): + pass + + class Module(object): + @staticmethod + def setUpModule(): + raise unittest.SkipTest('foo') + + Test.__module__ = 'Module' + sys.modules['Module'] = Module + + result = self.runTests(Test) + self.assertEqual(result.testsRun, 0) + self.assertEqual(len(result.errors), 0) + self.assertEqual(len(result.skipped), 1) + skipped = result.skipped[0][0] + self.assertEqual(str(skipped), 'setUpModule (Module)') + if __name__ == '__main__': unittest.main() From python-checkins at python.org Sat Jun 5 23:01:08 2010 From: python-checkins at python.org (michael.foord) Date: Sat, 5 Jun 2010 23:01:08 +0200 (CEST) Subject: [Python-checkins] r81765 - in python/branches/py3k: Lib/unittest/test/test_case.py Message-ID: <20100605210108.8EFADEE99D@mail.python.org> Author: michael.foord Date: Sat Jun 5 23:01:08 2010 New Revision: 81765 Log: Merged revisions 81763 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81763 | michael.foord | 2010-06-05 21:33:43 +0100 (Sat, 05 Jun 2010) | 1 line Tests for unittest.TestCase.maxDiff. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/unittest/test/test_case.py Modified: python/branches/py3k/Lib/unittest/test/test_case.py ============================================================================== --- python/branches/py3k/Lib/unittest/test/test_case.py (original) +++ python/branches/py3k/Lib/unittest/test/test_case.py Sat Jun 5 23:01:08 2010 @@ -597,6 +597,8 @@ seq2 = 'b' + 'x' * 80**2 diff = '\n'.join(difflib.ndiff(pprint.pformat(seq1).splitlines(), pprint.pformat(seq2).splitlines())) + # the +1 is the leading \n added by assertSequenceEqual + omitted = unittest.case.DIFF_OMITTED % (len(diff) + 1,) self.maxDiff = len(diff)//2 try: @@ -607,6 +609,7 @@ else: self.fail('assertSequenceEqual did not fail.') self.assertTrue(len(msg) < len(diff)) + self.assertIn(omitted, msg) self.maxDiff = len(diff) * 2 try: @@ -616,6 +619,7 @@ else: self.fail('assertSequenceEqual did not fail.') self.assertTrue(len(msg) > len(diff)) + self.assertNotIn(omitted, msg) self.maxDiff = None try: @@ -625,6 +629,41 @@ else: self.fail('assertSequenceEqual did not fail.') self.assertTrue(len(msg) > len(diff)) + self.assertNotIn(omitted, msg) + + def testTruncateMessage(self): + self.maxDiff = 1 + message = self._truncateMessage('foo', 'bar') + omitted = unittest.case.DIFF_OMITTED % len('bar') + self.assertEqual(message, 'foo' + omitted) + + self.maxDiff = None + message = self._truncateMessage('foo', 'bar') + self.assertEqual(message, 'foobar') + + def testAssertDictEqualTruncates(self): + test = unittest.TestCase('assertEqual') + def truncate(msg, diff): + return 'foo' + test._truncateMessage = truncate + try: + test.assertDictEqual({}, {1: 0}) + except self.failureException as e: + self.assertEqual(str(e), 'foo') + else: + self.fail('assertDictEqual did not fail') + + def testAssertMultiLineEqualTruncates(self): + test = unittest.TestCase('assertEqual') + def truncate(msg, diff): + return 'foo' + test._truncateMessage = truncate + try: + test.assertMultiLineEqual('foo', 'bar') + except self.failureException as e: + self.assertEqual(str(e), 'foo') + else: + self.fail('assertMultiLineEqual did not fail') def testAssertItemsEqual(self): a = object() From python-checkins at python.org Sat Jun 5 23:12:23 2010 From: python-checkins at python.org (michael.foord) Date: Sat, 5 Jun 2010 23:12:23 +0200 (CEST) Subject: [Python-checkins] r81766 - in python/branches/py3k: Lib/unittest/suite.py Lib/unittest/test/test_case.py Lib/unittest/test/test_setups.py Message-ID: <20100605211223.60A75EE99D@mail.python.org> Author: michael.foord Date: Sat Jun 5 23:12:23 2010 New Revision: 81766 Log: Merged revisions 81764 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81764 | michael.foord | 2010-06-05 21:59:00 +0100 (Sat, 05 Jun 2010) | 1 line Tests for issue 8302, skipped test in a setUpClass or a setUpModule are reported as skips rather than errors. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/unittest/suite.py python/branches/py3k/Lib/unittest/test/test_case.py python/branches/py3k/Lib/unittest/test/test_setups.py Modified: python/branches/py3k/Lib/unittest/suite.py ============================================================================== --- python/branches/py3k/Lib/unittest/suite.py (original) +++ python/branches/py3k/Lib/unittest/suite.py Sat Jun 5 23:12:23 2010 @@ -127,9 +127,11 @@ if setUpClass is not None: try: setUpClass() - except: + except Exception as e: currentClass._classSetupFailed = True - self._addClassSetUpError(result, currentClass) + className = util.strclass(currentClass) + errorName = 'setUpClass (%s)' % className + self._addClassOrModuleLevelException(result, e, errorName) def _get_previous_module(self, result): previousModule = None @@ -157,10 +159,18 @@ if setUpModule is not None: try: setUpModule() - except: + except Exception as e: result._moduleSetUpFailed = True - error = _ErrorHolder('setUpModule (%s)' % currentModule) - result.addError(error, sys.exc_info()) + errorName = 'setUpModule (%s)' % currentModule + self._addClassOrModuleLevelException(result, e, errorName) + + def _addClassOrModuleLevelException(self, result, exception, errorName): + error = _ErrorHolder(errorName) + addSkip = getattr(result, 'addSkip', None) + if addSkip is not None and isinstance(exception, case.SkipTest): + addSkip(error, str(exception)) + else: + result.addError(error, sys.exc_info()) def _handleModuleTearDown(self, result): previousModule = self._get_previous_module(result) @@ -178,9 +188,9 @@ if tearDownModule is not None: try: tearDownModule() - except: - error = _ErrorHolder('tearDownModule (%s)' % previousModule) - result.addError(error, sys.exc_info()) + except Exception as e: + errorName = 'tearDownModule (%s)' % previousModule + self._addClassOrModuleLevelException(result, e, errorName) def _tearDownPreviousClass(self, test, result): previousClass = getattr(result, '_previousTestClass', None) @@ -198,18 +208,11 @@ if tearDownClass is not None: try: tearDownClass() - except: - self._addClassTearDownError(result) + except Exception as e: + className = util.strclass(previousClass) + errorName = 'tearDownClass (%s)' % className + self._addClassOrModuleLevelException(result, e, errorName) - def _addClassTearDownError(self, result): - className = util.strclass(result._previousTestClass) - error = _ErrorHolder('classTearDown (%s)' % className) - result.addError(error, sys.exc_info()) - - def _addClassSetUpError(self, result, klass): - className = util.strclass(klass) - error = _ErrorHolder('classSetUp (%s)' % className) - result.addError(error, sys.exc_info()) class _ErrorHolder(object): Modified: python/branches/py3k/Lib/unittest/test/test_case.py ============================================================================== --- python/branches/py3k/Lib/unittest/test/test_case.py (original) +++ python/branches/py3k/Lib/unittest/test/test_case.py Sat Jun 5 23:12:23 2010 @@ -641,6 +641,10 @@ message = self._truncateMessage('foo', 'bar') self.assertEqual(message, 'foobar') + self.maxDiff = 4 + message = self._truncateMessage('foo', 'bar') + self.assertEqual(message, 'foobar') + def testAssertDictEqualTruncates(self): test = unittest.TestCase('assertEqual') def truncate(msg, diff): Modified: python/branches/py3k/Lib/unittest/test/test_setups.py ============================================================================== --- python/branches/py3k/Lib/unittest/test/test_setups.py (original) +++ python/branches/py3k/Lib/unittest/test/test_setups.py Sat Jun 5 23:12:23 2010 @@ -111,7 +111,7 @@ self.assertEqual(len(result.errors), 1) error, _ = result.errors[0] self.assertEqual(str(error), - 'classSetUp (%s.BrokenTest)' % __name__) + 'setUpClass (%s.BrokenTest)' % __name__) def test_error_in_teardown_class(self): class Test(unittest.TestCase): @@ -144,7 +144,7 @@ error, _ = result.errors[0] self.assertEqual(str(error), - 'classTearDown (%s.Test)' % __name__) + 'tearDownClass (%s.Test)' % __name__) def test_class_not_torndown_when_setup_fails(self): class Test(unittest.TestCase): @@ -398,3 +398,46 @@ self.assertEqual(len(result.errors), 1) error, _ = result.errors[0] self.assertEqual(str(error), 'tearDownModule (Module)') + + def test_skiptest_in_setupclass(self): + class Test(unittest.TestCase): + @classmethod + def setUpClass(cls): + raise unittest.SkipTest('foo') + def test_one(self): + pass + def test_two(self): + pass + + result = self.runTests(Test) + self.assertEqual(result.testsRun, 0) + self.assertEqual(len(result.errors), 0) + self.assertEqual(len(result.skipped), 1) + skipped = result.skipped[0][0] + self.assertEqual(str(skipped), 'setUpClass (%s.Test)' % __name__) + + def test_skiptest_in_setupmodule(self): + class Test(unittest.TestCase): + def test_one(self): + pass + def test_two(self): + pass + + class Module(object): + @staticmethod + def setUpModule(): + raise unittest.SkipTest('foo') + + Test.__module__ = 'Module' + sys.modules['Module'] = Module + + result = self.runTests(Test) + self.assertEqual(result.testsRun, 0) + self.assertEqual(len(result.errors), 0) + self.assertEqual(len(result.skipped), 1) + skipped = result.skipped[0][0] + self.assertEqual(str(skipped), 'setUpModule (Module)') + + +if __name__ == '__main__': + unittest.main() From python-checkins at python.org Sat Jun 5 23:57:03 2010 From: python-checkins at python.org (michael.foord) Date: Sat, 5 Jun 2010 23:57:03 +0200 (CEST) Subject: [Python-checkins] r81767 - python/trunk/Doc/library/unittest.rst Message-ID: <20100605215703.28CAFEEA06@mail.python.org> Author: michael.foord Date: Sat Jun 5 23:57:03 2010 New Revision: 81767 Log: Documentation updates for issues 8302 and 8351 (truncating excessive diffs in unittest failure messages and reporting SkipTest exceptions in setUpClass and setUpModule as skips rather than errors). Modified: python/trunk/Doc/library/unittest.rst Modified: python/trunk/Doc/library/unittest.rst ============================================================================== --- python/trunk/Doc/library/unittest.rst (original) +++ python/trunk/Doc/library/unittest.rst Sat Jun 5 23:57:03 2010 @@ -1150,6 +1150,21 @@ .. versionadded:: 2.7 + .. attribute:: maxDiff + + This attribute controls the maximum length of diffs output by assert + methods that report diffs on failure. It defaults to 80*8 characters. + Assert methods affected by this attribute are + :meth:`assertSequenceEqual` (including all the sequence comparison + methods that delegate to it), :meth:`assertDictEqual` and + :meth:`assertMultiLineEqual`. + + Setting ``maxDiff`` to None means that there is no maximum length of + diffs. + + .. versionadded:: 2.7 + + Testing frameworks can use the following methods to collect information on the test: @@ -1848,7 +1863,9 @@ If an exception is raised during a ``setUpClass`` then the tests in the class are not run and the ``tearDownClass`` is not run. Skipped classes will not -have ``setUpClass`` or ``tearDownClass`` run. +have ``setUpClass`` or ``tearDownClass`` run. If the exception is a +``SkipTest`` exception then the class will be reported as having been skipped +instead of as an error. setUpModule and tearDownModule @@ -1863,7 +1880,9 @@ closeConnection() If an exception is raised in a ``setUpModule`` then none of the tests in the -module will be run and the ``tearDownModule`` will not be run. +module will be run and the ``tearDownModule`` will not be run. If the exception is a +``SkipTest`` exception then the module will be reported as having been skipped +instead of as an error. Signal Handling From python-checkins at python.org Sat Jun 5 23:59:55 2010 From: python-checkins at python.org (michael.foord) Date: Sat, 5 Jun 2010 23:59:55 +0200 (CEST) Subject: [Python-checkins] r81768 - in python/branches/py3k: Doc/library/unittest.rst Message-ID: <20100605215955.AF8C1EEA9B@mail.python.org> Author: michael.foord Date: Sat Jun 5 23:59:55 2010 New Revision: 81768 Log: Merged revisions 81767 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81767 | michael.foord | 2010-06-05 22:57:03 +0100 (Sat, 05 Jun 2010) | 1 line Documentation updates for issues 8302 and 8351 (truncating excessive diffs in unittest failure messages and reporting SkipTest exceptions in setUpClass and setUpModule as skips rather than errors). ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Doc/library/unittest.rst Modified: python/branches/py3k/Doc/library/unittest.rst ============================================================================== --- python/branches/py3k/Doc/library/unittest.rst (original) +++ python/branches/py3k/Doc/library/unittest.rst Sat Jun 5 23:59:55 2010 @@ -1168,6 +1168,21 @@ .. versionadded:: 3.1 + .. attribute:: maxDiff + + This attribute controls the maximum length of diffs output by assert + methods that report diffs on failure. It defaults to 80*8 characters. + Assert methods affected by this attribute are + :meth:`assertSequenceEqual` (including all the sequence comparison + methods that delegate to it), :meth:`assertDictEqual` and + :meth:`assertMultiLineEqual`. + + Setting ``maxDiff`` to None means that there is no maximum length of + diffs. + + .. versionadded:: 3.2 + + Testing frameworks can use the following methods to collect information on the test: @@ -1862,7 +1877,9 @@ If an exception is raised during a ``setUpClass`` then the tests in the class are not run and the ``tearDownClass`` is not run. Skipped classes will not -have ``setUpClass`` or ``tearDownClass`` run. +have ``setUpClass`` or ``tearDownClass`` run. If the exception is a +``SkipTest`` exception then the class will be reported as having been skipped +instead of as an error. setUpModule and tearDownModule @@ -1877,7 +1894,9 @@ closeConnection() If an exception is raised in a ``setUpModule`` then none of the tests in the -module will be run and the ``tearDownModule`` will not be run. +module will be run and the ``tearDownModule`` will not be run. If the exception is a +``SkipTest`` exception then the module will be reported as having been skipped +instead of as an error. Signal Handling From python-checkins at python.org Sun Jun 6 00:28:11 2010 From: python-checkins at python.org (ezio.melotti) Date: Sun, 6 Jun 2010 00:28:11 +0200 (CEST) Subject: [Python-checkins] r81769 - python/trunk/Lib/test/test_shutil.py Message-ID: <20100605222811.04A20EEA64@mail.python.org> Author: ezio.melotti Date: Sun Jun 6 00:28:10 2010 New Revision: 81769 Log: Replace deprecated fail* methods with the equivalent assert* ones. Modified: python/trunk/Lib/test/test_shutil.py Modified: python/trunk/Lib/test/test_shutil.py ============================================================================== --- python/trunk/Lib/test/test_shutil.py (original) +++ python/trunk/Lib/test/test_shutil.py Sun Jun 6 00:28:10 2010 @@ -751,8 +751,8 @@ self._set_shutil_open(_open) shutil.copyfile('srcfile', 'destfile') - self.failUnless(srcfile._entered) - self.failUnless(srcfile._exited_with[0] is IOError) + self.assertTrue(srcfile._entered) + self.assertTrue(srcfile._exited_with[0] is IOError) self.assertEqual(srcfile._exited_with[1].args, ('Cannot open "destfile"',)) @@ -771,10 +771,10 @@ self._set_shutil_open(_open) shutil.copyfile('srcfile', 'destfile') - self.failUnless(srcfile._entered) - self.failUnless(destfile._entered) - self.failUnless(destfile._raised) - self.failUnless(srcfile._exited_with[0] is IOError) + self.assertTrue(srcfile._entered) + self.assertTrue(destfile._entered) + self.assertTrue(destfile._raised) + self.assertTrue(srcfile._exited_with[0] is IOError) self.assertEqual(srcfile._exited_with[1].args, ('Cannot close',)) @@ -794,11 +794,11 @@ self.assertRaises(IOError, shutil.copyfile, 'srcfile', 'destfile') - self.failUnless(srcfile._entered) - self.failUnless(destfile._entered) - self.failIf(destfile._raised) - self.failUnless(srcfile._exited_with[0] is None) - self.failUnless(srcfile._raised) + self.assertTrue(srcfile._entered) + self.assertTrue(destfile._entered) + self.assertFalse(destfile._raised) + self.assertTrue(srcfile._exited_with[0] is None) + self.assertTrue(srcfile._raised) def test_main(): From solipsis at pitrou.net Sun Jun 6 01:26:20 2010 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sun, 6 Jun 2010 01:26:20 +0200 (CEST) Subject: [Python-checkins] Daily py3k reference leaks (r81765): sum=0 Message-ID: <20100605232620.DF2A71788A@ns6635.ovh.net> py3k results for svn r81765 (hg cset 59d0e4dba3e5) -------------------------------------------------- Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/py3k/refleaks/reflogM6TCkA', '-x'] From python-checkins at python.org Sun Jun 6 01:58:40 2010 From: python-checkins at python.org (michael.foord) Date: Sun, 6 Jun 2010 01:58:40 +0200 (CEST) Subject: [Python-checkins] r81770 - python/trunk/Lib/unittest/case.py Message-ID: <20100605235840.CB047EEABC@mail.python.org> Author: michael.foord Date: Sun Jun 6 01:58:40 2010 New Revision: 81770 Log: Code formatting change. Modified: python/trunk/Lib/unittest/case.py Modified: python/trunk/Lib/unittest/case.py ============================================================================== --- python/trunk/Lib/unittest/case.py (original) +++ python/trunk/Lib/unittest/case.py Sun Jun 6 01:58:40 2010 @@ -163,6 +163,7 @@ # This attribute sets the maximum length of a diff in failure messsages # by assert methods using difflib. It is looked up as an instance attribute # so can be configured by individual tests if required. + maxDiff = 80*8 # Attribute used by TestSuite for classSetUp From python-checkins at python.org Sun Jun 6 01:59:34 2010 From: python-checkins at python.org (michael.foord) Date: Sun, 6 Jun 2010 01:59:34 +0200 (CEST) Subject: [Python-checkins] r81771 - in python/branches/py3k: Lib/unittest/case.py Message-ID: <20100605235934.4E635C9E8@mail.python.org> Author: michael.foord Date: Sun Jun 6 01:59:34 2010 New Revision: 81771 Log: Merged revisions 81770 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81770 | michael.foord | 2010-06-06 00:58:40 +0100 (Sun, 06 Jun 2010) | 1 line Code formatting change. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/unittest/case.py Modified: python/branches/py3k/Lib/unittest/case.py ============================================================================== --- python/branches/py3k/Lib/unittest/case.py (original) +++ python/branches/py3k/Lib/unittest/case.py Sun Jun 6 01:59:34 2010 @@ -175,6 +175,7 @@ # This attribute sets the maximum length of a diff in failure messsages # by assert methods using difflib. It is looked up as an instance attribute # so can be configured by individual tests if required. + maxDiff = 80*8 # Attribute used by TestSuite for classSetUp From python-checkins at python.org Sun Jun 6 02:22:09 2010 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 6 Jun 2010 02:22:09 +0200 (CEST) Subject: [Python-checkins] r81772 - in python/trunk: Include/patchlevel.h Lib/distutils/__init__.py Lib/idlelib/idlever.py Misc/NEWS Misc/RPM/python-2.7.spec README Message-ID: <20100606002209.EA353EEA64@mail.python.org> Author: benjamin.peterson Date: Sun Jun 6 02:22:09 2010 New Revision: 81772 Log: bump version to 2.7 rc1 Modified: python/trunk/Include/patchlevel.h python/trunk/Lib/distutils/__init__.py python/trunk/Lib/idlelib/idlever.py python/trunk/Misc/NEWS python/trunk/Misc/RPM/python-2.7.spec python/trunk/README Modified: python/trunk/Include/patchlevel.h ============================================================================== --- python/trunk/Include/patchlevel.h (original) +++ python/trunk/Include/patchlevel.h Sun Jun 6 02:22:09 2010 @@ -23,11 +23,11 @@ #define PY_MAJOR_VERSION 2 #define PY_MINOR_VERSION 7 #define PY_MICRO_VERSION 0 -#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_BETA -#define PY_RELEASE_SERIAL 2 +#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_GAMMA +#define PY_RELEASE_SERIAL 1 /* Version as a string */ -#define PY_VERSION "2.7b2+" +#define PY_VERSION "2.7rc1" /*--end constants--*/ /* Subversion Revision number of this file (not of the repository) */ Modified: python/trunk/Lib/distutils/__init__.py ============================================================================== --- python/trunk/Lib/distutils/__init__.py (original) +++ python/trunk/Lib/distutils/__init__.py Sun Jun 6 02:22:09 2010 @@ -15,5 +15,5 @@ # Updated automatically by the Python release process. # #--start constants-- -__version__ = "2.7b2" +__version__ = "2.7rc1" #--end constants-- Modified: python/trunk/Lib/idlelib/idlever.py ============================================================================== --- python/trunk/Lib/idlelib/idlever.py (original) +++ python/trunk/Lib/idlelib/idlever.py Sun Jun 6 02:22:09 2010 @@ -1 +1 @@ -IDLE_VERSION = "2.7b2" +IDLE_VERSION = "2.7rc1" Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Sun Jun 6 02:22:09 2010 @@ -7,7 +7,7 @@ What's New in Python 2.7 Release Candidate 1? ============================================= -*Release date: XXXX-XX-XX* +*Release date: 2010-06-05* Core and Builtins ----------------- Modified: python/trunk/Misc/RPM/python-2.7.spec ============================================================================== --- python/trunk/Misc/RPM/python-2.7.spec (original) +++ python/trunk/Misc/RPM/python-2.7.spec Sun Jun 6 02:22:09 2010 @@ -39,7 +39,7 @@ %define name python #--start constants-- -%define version 2.7b2 +%define version 2.7rc1 %define libver 2.7 #--end constants-- %define release 1pydotorg Modified: python/trunk/README ============================================================================== --- python/trunk/README (original) +++ python/trunk/README Sun Jun 6 02:22:09 2010 @@ -1,5 +1,5 @@ -This is Python version 2.7 beta 2 -================================= +This is Python version 2.7 release candidate 1 +============================================== Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Python Software Foundation. From python-checkins at python.org Sun Jun 6 02:49:28 2010 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 6 Jun 2010 02:49:28 +0200 (CEST) Subject: [Python-checkins] r81773 - python/trunk/Lib/pydoc_data/topics.py Message-ID: <20100606004928.1F267EEA27@mail.python.org> Author: benjamin.peterson Date: Sun Jun 6 02:49:27 2010 New Revision: 81773 Log: update pydoc-topics Modified: python/trunk/Lib/pydoc_data/topics.py Modified: python/trunk/Lib/pydoc_data/topics.py ============================================================================== --- python/trunk/Lib/pydoc_data/topics.py (original) +++ python/trunk/Lib/pydoc_data/topics.py Sun Jun 6 02:49:27 2010 @@ -1,4 +1,4 @@ -# Autogenerated by Sphinx on Sat May 8 12:01:30 2010 +# Autogenerated by Sphinx on Sat Jun 5 19:26:01 2010 topics = {'assert': u'\nThe ``assert`` statement\n************************\n\nAssert statements are a convenient way to insert debugging assertions\ninto a program:\n\n assert_stmt ::= "assert" expression ["," expression]\n\nThe simple form, ``assert expression``, is equivalent to\n\n if __debug__:\n if not expression: raise AssertionError\n\nThe extended form, ``assert expression1, expression2``, is equivalent\nto\n\n if __debug__:\n if not expression1: raise AssertionError(expression2)\n\nThese equivalences assume that ``__debug__`` and ``AssertionError``\nrefer to the built-in variables with those names. In the current\nimplementation, the built-in variable ``__debug__`` is ``True`` under\nnormal circumstances, ``False`` when optimization is requested\n(command line option -O). The current code generator emits no code\nfor an assert statement when optimization is requested at compile\ntime. Note that it is unnecessary to include the source code for the\nexpression that failed in the error message; it will be displayed as\npart of the stack trace.\n\nAssignments to ``__debug__`` are illegal. The value for the built-in\nvariable is determined when the interpreter starts.\n', 'assignment': u'\nAssignment statements\n*********************\n\nAssignment statements are used to (re)bind names to values and to\nmodify attributes or items of mutable objects:\n\n assignment_stmt ::= (target_list "=")+ (expression_list | yield_expression)\n target_list ::= target ("," target)* [","]\n target ::= identifier\n | "(" target_list ")"\n | "[" target_list "]"\n | attributeref\n | subscription\n | slicing\n\n(See section *Primaries* for the syntax definitions for the last three\nsymbols.)\n\nAn assignment statement evaluates the expression list (remember that\nthis can be a single expression or a comma-separated list, the latter\nyielding a tuple) and assigns the single resulting object to each of\nthe target lists, from left to right.\n\nAssignment is defined recursively depending on the form of the target\n(list). When a target is part of a mutable object (an attribute\nreference, subscription or slicing), the mutable object must\nultimately perform the assignment and decide about its validity, and\nmay raise an exception if the assignment is unacceptable. The rules\nobserved by various types and the exceptions raised are given with the\ndefinition of the object types (see section *The standard type\nhierarchy*).\n\nAssignment of an object to a target list is recursively defined as\nfollows.\n\n* If the target list is a single target: The object is assigned to\n that target.\n\n* If the target list is a comma-separated list of targets: The object\n must be an iterable with the same number of items as there are\n targets in the target list, and the items are assigned, from left to\n right, to the corresponding targets. (This rule is relaxed as of\n Python 1.5; in earlier versions, the object had to be a tuple.\n Since strings are sequences, an assignment like ``a, b = "xy"`` is\n now legal as long as the string has the right length.)\n\nAssignment of an object to a single target is recursively defined as\nfollows.\n\n* If the target is an identifier (name):\n\n * If the name does not occur in a ``global`` statement in the\n current code block: the name is bound to the object in the current\n local namespace.\n\n * Otherwise: the name is bound to the object in the current global\n namespace.\n\n The name is rebound if it was already bound. This may cause the\n reference count for the object previously bound to the name to reach\n zero, causing the object to be deallocated and its destructor (if it\n has one) to be called.\n\n* If the target is a target list enclosed in parentheses or in square\n brackets: The object must be an iterable with the same number of\n items as there are targets in the target list, and its items are\n assigned, from left to right, to the corresponding targets.\n\n* If the target is an attribute reference: The primary expression in\n the reference is evaluated. It should yield an object with\n assignable attributes; if this is not the case, ``TypeError`` is\n raised. That object is then asked to assign the assigned object to\n the given attribute; if it cannot perform the assignment, it raises\n an exception (usually but not necessarily ``AttributeError``).\n\n Note: If the object is a class instance and the attribute reference\n occurs on both sides of the assignment operator, the RHS expression,\n ``a.x`` can access either an instance attribute or (if no instance\n attribute exists) a class attribute. The LHS target ``a.x`` is\n always set as an instance attribute, creating it if necessary.\n Thus, the two occurrences of ``a.x`` do not necessarily refer to the\n same attribute: if the RHS expression refers to a class attribute,\n the LHS creates a new instance attribute as the target of the\n assignment:\n\n class Cls:\n x = 3 # class variable\n inst = Cls()\n inst.x = inst.x + 1 # writes inst.x as 4 leaving Cls.x as 3\n\n This description does not necessarily apply to descriptor\n attributes, such as properties created with ``property()``.\n\n* If the target is a subscription: The primary expression in the\n reference is evaluated. It should yield either a mutable sequence\n object (such as a list) or a mapping object (such as a dictionary).\n Next, the subscript expression is evaluated.\n\n If the primary is a mutable sequence object (such as a list), the\n subscript must yield a plain integer. If it is negative, the\n sequence\'s length is added to it. The resulting value must be a\n nonnegative integer less than the sequence\'s length, and the\n sequence is asked to assign the assigned object to its item with\n that index. If the index is out of range, ``IndexError`` is raised\n (assignment to a subscripted sequence cannot add new items to a\n list).\n\n If the primary is a mapping object (such as a dictionary), the\n subscript must have a type compatible with the mapping\'s key type,\n and the mapping is then asked to create a key/datum pair which maps\n the subscript to the assigned object. This can either replace an\n existing key/value pair with the same key value, or insert a new\n key/value pair (if no key with the same value existed).\n\n* If the target is a slicing: The primary expression in the reference\n is evaluated. It should yield a mutable sequence object (such as a\n list). The assigned object should be a sequence object of the same\n type. Next, the lower and upper bound expressions are evaluated,\n insofar they are present; defaults are zero and the sequence\'s\n length. The bounds should evaluate to (small) integers. If either\n bound is negative, the sequence\'s length is added to it. The\n resulting bounds are clipped to lie between zero and the sequence\'s\n length, inclusive. Finally, the sequence object is asked to replace\n the slice with the items of the assigned sequence. The length of\n the slice may be different from the length of the assigned sequence,\n thus changing the length of the target sequence, if the object\n allows it.\n\n**CPython implementation detail:** In the current implementation, the\nsyntax for targets is taken to be the same as for expressions, and\ninvalid syntax is rejected during the code generation phase, causing\nless detailed error messages.\n\nWARNING: Although the definition of assignment implies that overlaps\nbetween the left-hand side and the right-hand side are \'safe\' (for\nexample ``a, b = b, a`` swaps two variables), overlaps *within* the\ncollection of assigned-to variables are not safe! For instance, the\nfollowing program prints ``[0, 2]``:\n\n x = [0, 1]\n i = 0\n i, x[i] = 1, 2\n print x\n\n\nAugmented assignment statements\n===============================\n\nAugmented assignment is the combination, in a single statement, of a\nbinary operation and an assignment statement:\n\n augmented_assignment_stmt ::= augtarget augop (expression_list | yield_expression)\n augtarget ::= identifier | attributeref | subscription | slicing\n augop ::= "+=" | "-=" | "*=" | "/=" | "//=" | "%=" | "**="\n | ">>=" | "<<=" | "&=" | "^=" | "|="\n\n(See section *Primaries* for the syntax definitions for the last three\nsymbols.)\n\nAn augmented assignment evaluates the target (which, unlike normal\nassignment statements, cannot be an unpacking) and the expression\nlist, performs the binary operation specific to the type of assignment\non the two operands, and assigns the result to the original target.\nThe target is only evaluated once.\n\nAn augmented assignment expression like ``x += 1`` can be rewritten as\n``x = x + 1`` to achieve a similar, but not exactly equal effect. In\nthe augmented version, ``x`` is only evaluated once. Also, when\npossible, the actual operation is performed *in-place*, meaning that\nrather than creating a new object and assigning that to the target,\nthe old object is modified instead.\n\nWith the exception of assigning to tuples and multiple targets in a\nsingle statement, the assignment done by augmented assignment\nstatements is handled the same way as normal assignments. Similarly,\nwith the exception of the possible *in-place* behavior, the binary\noperation performed by augmented assignment is the same as the normal\nbinary operations.\n\nFor targets which are attribute references, the same *caveat about\nclass and instance attributes* applies as for regular assignments.\n', 'atom-identifiers': u'\nIdentifiers (Names)\n*******************\n\nAn identifier occurring as an atom is a name. See section\n*Identifiers and keywords* for lexical definition and section *Naming\nand binding* for documentation of naming and binding.\n\nWhen the name is bound to an object, evaluation of the atom yields\nthat object. When a name is not bound, an attempt to evaluate it\nraises a ``NameError`` exception.\n\n**Private name mangling:** When an identifier that textually occurs in\na class definition begins with two or more underscore characters and\ndoes not end in two or more underscores, it is considered a *private\nname* of that class. Private names are transformed to a longer form\nbefore code is generated for them. The transformation inserts the\nclass name in front of the name, with leading underscores removed, and\na single underscore inserted in front of the class name. For example,\nthe identifier ``__spam`` occurring in a class named ``Ham`` will be\ntransformed to ``_Ham__spam``. This transformation is independent of\nthe syntactical context in which the identifier is used. If the\ntransformed name is extremely long (longer than 255 characters),\nimplementation defined truncation may happen. If the class name\nconsists only of underscores, no transformation is done.\n', From python-checkins at python.org Sun Jun 6 02:50:58 2010 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 6 Jun 2010 02:50:58 +0200 (CEST) Subject: [Python-checkins] r81774 - python/trunk/Doc/library/urllib.rst Message-ID: <20100606005058.EC8C3EEA80@mail.python.org> Author: benjamin.peterson Date: Sun Jun 6 02:50:58 2010 New Revision: 81774 Log: remove extra space Modified: python/trunk/Doc/library/urllib.rst Modified: python/trunk/Doc/library/urllib.rst ============================================================================== --- python/trunk/Doc/library/urllib.rst (original) +++ python/trunk/Doc/library/urllib.rst Sun Jun 6 02:50:58 2010 @@ -236,7 +236,7 @@ .. function:: urlencode(query[, doseq]) - Convert a mapping object or a sequence of two-element tuples to a + 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 From python-checkins at python.org Sun Jun 6 02:54:29 2010 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 6 Jun 2010 02:54:29 +0200 (CEST) Subject: [Python-checkins] r81775 - python/trunk/Doc/library/urllib.rst Message-ID: <20100606005429.C1A09EEA27@mail.python.org> Author: benjamin.peterson Date: Sun Jun 6 02:54:29 2010 New Revision: 81775 Log: fix sphinx warning with an extra space Modified: python/trunk/Doc/library/urllib.rst Modified: python/trunk/Doc/library/urllib.rst ============================================================================== --- python/trunk/Doc/library/urllib.rst (original) +++ python/trunk/Doc/library/urllib.rst Sun Jun 6 02:54:29 2010 @@ -245,7 +245,7 @@ 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 + 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. The :mod:`urlparse` module provides the functions From python-checkins at python.org Sun Jun 6 02:55:14 2010 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 6 Jun 2010 02:55:14 +0200 (CEST) Subject: [Python-checkins] r81776 - python/tags/r27rc1 Message-ID: <20100606005514.4361FEEA27@mail.python.org> Author: benjamin.peterson Date: Sun Jun 6 02:55:14 2010 New Revision: 81776 Log: tag 2.7's first release candidate Added: python/tags/r27rc1/ - copied from r81775, /python/trunk/ From python-checkins at python.org Sun Jun 6 04:09:34 2010 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 6 Jun 2010 04:09:34 +0200 (CEST) Subject: [Python-checkins] r81777 - in python/trunk: Include/patchlevel.h Misc/NEWS Message-ID: <20100606020934.1DB5DEEAD0@mail.python.org> Author: benjamin.peterson Date: Sun Jun 6 04:09:33 2010 New Revision: 81777 Log: careening towards 2.7rc2 we go Modified: python/trunk/Include/patchlevel.h python/trunk/Misc/NEWS Modified: python/trunk/Include/patchlevel.h ============================================================================== --- python/trunk/Include/patchlevel.h (original) +++ python/trunk/Include/patchlevel.h Sun Jun 6 04:09:33 2010 @@ -27,7 +27,7 @@ #define PY_RELEASE_SERIAL 1 /* Version as a string */ -#define PY_VERSION "2.7rc1" +#define PY_VERSION "2.7rc1+" /*--end constants--*/ /* Subversion Revision number of this file (not of the repository) */ Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Sun Jun 6 04:09:33 2010 @@ -4,6 +4,18 @@ (editors: check NEWS.help for information about editing NEWS using ReST.) +What's New in Python release candidate 2? +========================================= + +*Release date: XXXX-XX-XX* + +Core and Builtins +----------------- + +Library +------- + + What's New in Python 2.7 Release Candidate 1? ============================================= From python-checkins at python.org Sun Jun 6 04:14:27 2010 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 6 Jun 2010 04:14:27 +0200 (CEST) Subject: [Python-checkins] r81778 - python/branches/py3k Message-ID: <20100606021427.AF67DEE9FD@mail.python.org> Author: benjamin.peterson Date: Sun Jun 6 04:14:27 2010 New Revision: 81778 Log: Blocked revisions 81772-81773,81777 via svnmerge ........ r81772 | benjamin.peterson | 2010-06-05 19:22:09 -0500 (Sat, 05 Jun 2010) | 1 line bump version to 2.7 rc1 ........ r81773 | benjamin.peterson | 2010-06-05 19:49:27 -0500 (Sat, 05 Jun 2010) | 1 line update pydoc-topics ........ r81777 | benjamin.peterson | 2010-06-05 21:09:33 -0500 (Sat, 05 Jun 2010) | 1 line careening towards 2.7rc2 we go ........ Modified: python/branches/py3k/ (props changed) From ncoghlan at gmail.com Sun Jun 6 04:18:28 2010 From: ncoghlan at gmail.com (Nick Coghlan) Date: Sun, 06 Jun 2010 12:18:28 +1000 Subject: [Python-checkins] r81706 - in python/trunk: Lib/test/test_descr.py Objects/abstract.c In-Reply-To: References: <20100605003251.2A9BCEECF3@mail.python.org> <4C0A05E5.3030105@gmail.com> Message-ID: <4C0B0574.1050502@gmail.com> On 06/06/10 04:55, Benjamin Peterson wrote: >> Why kill the microoptimisation here? Looking the string up in the intern >> dict every time (as these changes do) is a waste of cycles. Since avoiding >> it is pretty easy using this common idiom, it's generally worth doing. > > Yes, but that's only applicable to classic classes, which I can't say > I care much about. Ah, true, you do still have it cached in the new-style code. No worries then. Cheers, Nick. -- Nick Coghlan | ncoghlan at gmail.com | Brisbane, Australia --------------------------------------------------------------- From python-checkins at python.org Sun Jun 6 04:32:09 2010 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 6 Jun 2010 04:32:09 +0200 (CEST) Subject: [Python-checkins] r81779 - in python/branches/py3k: Doc/library/urllib.parse.rst Message-ID: <20100606023209.4E7D7EECC2@mail.python.org> Author: benjamin.peterson Date: Sun Jun 6 04:32:09 2010 New Revision: 81779 Log: Merged revisions 81774-81775 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81774 | benjamin.peterson | 2010-06-05 19:50:58 -0500 (Sat, 05 Jun 2010) | 1 line remove extra space ........ r81775 | benjamin.peterson | 2010-06-05 19:54:29 -0500 (Sat, 05 Jun 2010) | 1 line fix sphinx warning with an extra space ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Doc/library/urllib.parse.rst Modified: python/branches/py3k/Doc/library/urllib.parse.rst ============================================================================== --- python/branches/py3k/Doc/library/urllib.parse.rst (original) +++ python/branches/py3k/Doc/library/urllib.parse.rst Sun Jun 6 04:32:09 2010 @@ -312,7 +312,7 @@ .. function:: urlencode(query, doseq=False) - Convert a mapping object or a sequence of two-element tuples to a + 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 @@ -321,7 +321,7 @@ 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 + 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 From python-checkins at python.org Sun Jun 6 04:40:38 2010 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 6 Jun 2010 04:40:38 +0200 (CEST) Subject: [Python-checkins] r81780 - python/branches/py3k/Doc/library/sqlite3.rst Message-ID: <20100606024038.578DBEEC85@mail.python.org> Author: benjamin.peterson Date: Sun Jun 6 04:40:38 2010 New Revision: 81780 Log: fix typo Modified: python/branches/py3k/Doc/library/sqlite3.rst Modified: python/branches/py3k/Doc/library/sqlite3.rst ============================================================================== --- python/branches/py3k/Doc/library/sqlite3.rst (original) +++ python/branches/py3k/Doc/library/sqlite3.rst Sun Jun 6 04:40:38 2010 @@ -231,7 +231,7 @@ .. versionadded:: 3.2 - :cont:`True` if a transaction is active (there are uncommitted changes), + :const:`True` if a transaction is active (there are uncommitted changes), :const:`False` otherwise. Read-only attribute. From python-checkins at python.org Sun Jun 6 04:41:24 2010 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 6 Jun 2010 04:41:24 +0200 (CEST) Subject: [Python-checkins] r81781 - python/branches/py3k/Doc/library/winreg.rst Message-ID: <20100606024124.A76BCEECB3@mail.python.org> Author: benjamin.peterson Date: Sun Jun 6 04:41:24 2010 New Revision: 81781 Log: reST indentation nit Modified: python/branches/py3k/Doc/library/winreg.rst Modified: python/branches/py3k/Doc/library/winreg.rst ============================================================================== --- python/branches/py3k/Doc/library/winreg.rst (original) +++ python/branches/py3k/Doc/library/winreg.rst Sun Jun 6 04:41:24 2010 @@ -111,7 +111,7 @@ The :func:`DeleteKeyEx` function is implemented with the RegDeleteKeyEx Windows API function, which is specific to 64-bit versions of Windows. See the `RegDeleteKeyEx documentation - `__. + `__. *key* is an already open key, or one of the predefined :ref:`HKEY_* constants `. From python-checkins at python.org Sun Jun 6 04:44:41 2010 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 6 Jun 2010 04:44:41 +0200 (CEST) Subject: [Python-checkins] r81782 - python/branches/py3k/Doc/tools/sphinxext/pyspecific.py Message-ID: <20100606024441.D0052EECCE@mail.python.org> Author: benjamin.peterson Date: Sun Jun 6 04:44:41 2010 New Revision: 81782 Log: bltn-file-objects don't exist in python3 Modified: python/branches/py3k/Doc/tools/sphinxext/pyspecific.py Modified: python/branches/py3k/Doc/tools/sphinxext/pyspecific.py ============================================================================== --- python/branches/py3k/Doc/tools/sphinxext/pyspecific.py (original) +++ python/branches/py3k/Doc/tools/sphinxext/pyspecific.py Sun Jun 6 04:44:41 2010 @@ -78,7 +78,7 @@ 'assert', 'assignment', 'atom-identifiers', 'atom-literals', 'attribute-access', 'attribute-references', 'augassign', 'binary', 'bitwise', 'bltin-code-objects', 'bltin-ellipsis-object', - 'bltin-file-objects', 'bltin-null-object', 'bltin-type-objects', 'booleans', + 'bltin-null-object', 'bltin-type-objects', 'booleans', 'break', 'callable-types', 'calls', 'class', 'comparisons', 'compound', 'context-managers', 'continue', 'conversions', 'customization', 'debugger', 'del', 'dict', 'dynamic-features', 'else', 'exceptions', 'execmodel', From python-checkins at python.org Sun Jun 6 04:51:17 2010 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 6 Jun 2010 04:51:17 +0200 (CEST) Subject: [Python-checkins] r81783 - in python/branches/release31-maint: Doc/tools/sphinxext/pyspecific.py Message-ID: <20100606025117.AA18BEE9E3@mail.python.org> Author: benjamin.peterson Date: Sun Jun 6 04:51:17 2010 New Revision: 81783 Log: Merged revisions 81782 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ........ r81782 | benjamin.peterson | 2010-06-05 21:44:41 -0500 (Sat, 05 Jun 2010) | 1 line bltn-file-objects don't exist in python3 ........ Modified: python/branches/release31-maint/ (props changed) python/branches/release31-maint/Doc/tools/sphinxext/pyspecific.py Modified: python/branches/release31-maint/Doc/tools/sphinxext/pyspecific.py ============================================================================== --- python/branches/release31-maint/Doc/tools/sphinxext/pyspecific.py (original) +++ python/branches/release31-maint/Doc/tools/sphinxext/pyspecific.py Sun Jun 6 04:51:17 2010 @@ -78,7 +78,7 @@ 'assert', 'assignment', 'atom-identifiers', 'atom-literals', 'attribute-access', 'attribute-references', 'augassign', 'binary', 'bitwise', 'bltin-code-objects', 'bltin-ellipsis-object', - 'bltin-file-objects', 'bltin-null-object', 'bltin-type-objects', 'booleans', + 'bltin-null-object', 'bltin-type-objects', 'booleans', 'break', 'callable-types', 'calls', 'class', 'comparisons', 'compound', 'context-managers', 'continue', 'conversions', 'customization', 'debugger', 'del', 'dict', 'dynamic-features', 'else', 'exceptions', 'execmodel', From python-checkins at python.org Sun Jun 6 12:13:18 2010 From: python-checkins at python.org (stefan.krah) Date: Sun, 6 Jun 2010 12:13:18 +0200 (CEST) Subject: [Python-checkins] r81784 - python/branches/py3k-cdecimal/Modules/cdecimal/mpdecimal.c Message-ID: <20100606101318.3A516EEA03@mail.python.org> Author: stefan.krah Date: Sun Jun 6 12:13:18 2010 New Revision: 81784 Log: In rare corner cases, exp, ln and log10 did not set Underflow. Modified: python/branches/py3k-cdecimal/Modules/cdecimal/mpdecimal.c Modified: python/branches/py3k-cdecimal/Modules/cdecimal/mpdecimal.c ============================================================================== --- python/branches/py3k-cdecimal/Modules/cdecimal/mpdecimal.c (original) +++ python/branches/py3k-cdecimal/Modules/cdecimal/mpdecimal.c Sun Jun 6 12:13:18 2010 @@ -1606,6 +1606,20 @@ } } +/* Transcendental functions do not always set Underflow reliably, + * since they only use as much precision as is necessary for correct + * rounding. If a result like 1.0000000000e-101 is finalized, there + * is no rounding digit that would trigger Underflow. But we can + * assume Inexact, so a short check suffices. */ +static inline void +mpd_check_underflow(mpd_t *dec, const mpd_context_t *ctx, uint32_t *status) +{ + if (mpd_adjexp(dec) < ctx->emin && !mpd_iszero(dec) && + dec->exp < mpd_etiny(ctx)) { + *status |= MPD_Underflow; + } +} + /* Check if a normal number must be rounded after the exponent has been checked. */ static inline void _mpd_check_round(mpd_t *dec, const mpd_context_t *ctx, uint32_t *status) @@ -3868,6 +3882,7 @@ if (mpd_isspecial(result) || mpd_iszerocoeff(result) || mpd_qcmp(&t1, &t2, status) == 0) { workctx.clamp = ctx->clamp; + mpd_check_underflow(result, &workctx, status); mpd_qfinalize(result, &workctx, status); break; } @@ -3880,6 +3895,7 @@ } else { _mpd_qexp(result, a, &workctx, status); + mpd_check_underflow(result, &workctx, status); mpd_qfinalize(result, &workctx, status); } } @@ -4261,6 +4277,7 @@ if (mpd_isspecial(result) || mpd_iszerocoeff(result) || mpd_qcmp(&t1, &t2, status) == 0) { workctx.clamp = ctx->clamp; + mpd_check_underflow(result, &workctx, status); mpd_qfinalize(result, &workctx, status); break; } @@ -4273,6 +4290,7 @@ } else { _mpd_qln(result, a, &workctx, status); + mpd_check_underflow(result, &workctx, status); mpd_qfinalize(result, &workctx, status); } } @@ -4376,6 +4394,7 @@ if (mpd_isspecial(result) || mpd_iszerocoeff(result) || mpd_qcmp(&t1, &t2, status) == 0) { workctx.clamp = ctx->clamp; + mpd_check_underflow(result, &workctx, status); mpd_qfinalize(result, &workctx, status); break; } @@ -4388,6 +4407,7 @@ } else { _mpd_qlog10(result, a, &workctx, status); + mpd_check_underflow(result, &workctx, status); } } From python-checkins at python.org Sun Jun 6 12:20:38 2010 From: python-checkins at python.org (stefan.krah) Date: Sun, 6 Jun 2010 12:20:38 +0200 (CEST) Subject: [Python-checkins] r81785 - python/branches/py3k-cdecimal/Lib/test/decimal_extended_tests/randfloat.py Message-ID: <20100606102038.3D1B2EEA6D@mail.python.org> Author: stefan.krah Date: Sun Jun 6 12:20:38 2010 New Revision: 81785 Log: Test setting of Underflow in ln corner cases. Modified: python/branches/py3k-cdecimal/Lib/test/decimal_extended_tests/randfloat.py Modified: python/branches/py3k-cdecimal/Lib/test/decimal_extended_tests/randfloat.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/test/decimal_extended_tests/randfloat.py (original) +++ python/branches/py3k-cdecimal/Lib/test/decimal_extended_tests/randfloat.py Sun Jun 6 12:20:38 2010 @@ -204,6 +204,19 @@ '999999999999999999999999999999999990000000000000000' #... '000000000000000000000000000000000000000000000000000' #... '1', + + # tough cases for ln etc. + '1.000000000000000000000000000000000000000000000000' #... + '00000000000000000000000000000000000000000000000000' #... + '00100000000000000000000000000000000000000000000000' #... + '00000000000000000000000000000000000000000000000000' #... + '0001', + '0.999999999999999999999999999999999999999999999999' #... + '99999999999999999999999999999999999999999999999999' #... + '99899999999999999999999999999999999999999999999999' #... + '99999999999999999999999999999999999999999999999999' #... + '99999999999999999999999999999999999999999999999999' #... + '9999' ] From python-checkins at python.org Sun Jun 6 12:27:11 2010 From: python-checkins at python.org (stefan.krah) Date: Sun, 6 Jun 2010 12:27:11 +0200 (CEST) Subject: [Python-checkins] r81786 - python/branches/py3k-cdecimal/Lib/test/decimal_extended_tests/deccheck.py Message-ID: <20100606102711.97FBAEEA03@mail.python.org> Author: stefan.krah Date: Sun Jun 6 12:27:11 2010 New Revision: 81786 Log: Remove workaround for Python 2.5 from __hash__ and fix typos. Modified: python/branches/py3k-cdecimal/Lib/test/decimal_extended_tests/deccheck.py Modified: python/branches/py3k-cdecimal/Lib/test/decimal_extended_tests/deccheck.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/test/decimal_extended_tests/deccheck.py (original) +++ python/branches/py3k-cdecimal/Lib/test/decimal_extended_tests/deccheck.py Sun Jun 6 12:27:11 2010 @@ -313,15 +313,15 @@ return True def exp(self, result, operands): - if context.f.allcr: return False + if context.f._allcr: return False return self.un_resolve_ulp(result, "exp", operands) def log10(self, result, operands): - if context.f.allcr: return False + if context.f._allcr: return False return self.un_resolve_ulp(result, "log10", operands) def ln(self, result, operands): - if context.f.allcr: return False + if context.f._allcr: return False return self.un_resolve_ulp(result, "ln", operands) def __pow__(self, result, operands): @@ -615,19 +615,10 @@ return self.obj_binaryfunc(other, '__gt__') def __hash__(self): - global PY25_HASH_HAVE_WARNED if self.mpd.is_nan(): - return cdec(0) # for testing + return None # for testing raise TypeError('Cannot hash a NaN value.') - ret = None - try: # Python 2.5 can use exorbitant amounts of memory - ret = self.obj_unaryfunc('__hash__') - except MemoryError: - if not PY25_HASH_HAVE_WARNED: - sys.stderr.write("Out of memory while hashing %s: upgrade to Python 2.6\n" - % str(self.mpd)) - PY25_HASH_HAVE_WARNED = 1 - return ret + return self.obj_unaryfunc('__hash__') def __int__(self): # ValueError or OverflowError @@ -1301,15 +1292,15 @@ if '--medium' in sys.argv: base['expts'].append(('rand', 'rand')) base['samples'] = None - testspecs = [small, ieee, base] + testspecs = [small] + ieee + [base] if '--long' in sys.argv: base['expts'].append(('rand', 'rand')) base['samples'] = 5 - testspecs = [small, ieee, base] + testspecs = [small] + ieee + [base] elif '--all' in sys.argv: base['expts'].append(('rand', 'rand')) base['samples'] = 100 - testspecs = [small, ieee, base] + testspecs = [small] + ieee + [base] else: # --short rand_ieee = random.choice(ieee) base['iter'] = small['iter'] = rand_ieee['iter'] = 1 From python-checkins at python.org Sun Jun 6 13:45:18 2010 From: python-checkins at python.org (stefan.krah) Date: Sun, 6 Jun 2010 13:45:18 +0200 (CEST) Subject: [Python-checkins] r81787 - python/branches/py3k-cdecimal/setup.py Message-ID: <20100606114518.10220EE9B3@mail.python.org> Author: stefan.krah Date: Sun Jun 6 13:45:17 2010 New Revision: 81787 Log: New default: use thread local contexts. Modified: python/branches/py3k-cdecimal/setup.py Modified: python/branches/py3k-cdecimal/setup.py ============================================================================== --- python/branches/py3k-cdecimal/setup.py (original) +++ python/branches/py3k-cdecimal/setup.py Sun Jun 6 13:45:17 2010 @@ -1662,8 +1662,8 @@ define_macros.append(('ANSI', '1')) else: raise DistutilsError("cdecimal: unsupported architecture") - # Not recommended: TLS is very slow! - # define_macros.append(('USE_THREAD_LOCAL_STORAGE', 1)) + # Faster version without thread local contexts: + # define_macros.append(('WITHOUT_THREADS', 1)) if 'sunos' in platform and cc == 'cc': # suncc extra_compile_args.extend(['-erroff=E_ARGUEMENT_MISMATCH']) ext = Extension ( From python-checkins at python.org Sun Jun 6 22:05:20 2010 From: python-checkins at python.org (tarek.ziade) Date: Sun, 6 Jun 2010 22:05:20 +0200 (CEST) Subject: [Python-checkins] r81788 - in python/trunk: Doc/distutils/builtdist.rst Misc/NEWS Message-ID: <20100606200520.54201EEDFF@mail.python.org> Author: tarek.ziade Date: Sun Jun 6 22:05:20 2010 New Revision: 81788 Log: Fixed #8909: now the doc details the size of the bitmap used in distutils' bdist_wininst Modified: python/trunk/Doc/distutils/builtdist.rst python/trunk/Misc/NEWS Modified: python/trunk/Doc/distutils/builtdist.rst ============================================================================== --- python/trunk/Doc/distutils/builtdist.rst (original) +++ python/trunk/Doc/distutils/builtdist.rst Sun Jun 6 22:05:20 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 bitmap which must be a Windows +run, but you can also supply your own 152x161 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 Modified: python/trunk/Misc/NEWS ============================================================================== --- python/trunk/Misc/NEWS (original) +++ python/trunk/Misc/NEWS Sun Jun 6 22:05:20 2010 @@ -15,6 +15,12 @@ Library ------- +Documentation +------------- + +- Issues #8909: Added the size of the bitmap used in the installer created by + distutils' bdist_wininst. Patch by Anatoly Techtonik. + What's New in Python 2.7 Release Candidate 1? ============================================= From python-checkins at python.org Sun Jun 6 22:10:03 2010 From: python-checkins at python.org (tarek.ziade) Date: Sun, 6 Jun 2010 22:10:03 +0200 (CEST) Subject: [Python-checkins] r81789 - in python/branches/release26-maint: Doc/distutils/builtdist.rst Misc/NEWS Message-ID: <20100606201003.9E184EEE02@mail.python.org> Author: tarek.ziade Date: Sun Jun 6 22:10:03 2010 New Revision: 81789 Log: Merged revisions 81788 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81788 | tarek.ziade | 2010-06-06 22:05:20 +0200 (Sun, 06 Jun 2010) | 1 line Fixed #8909: now the doc details the size of the bitmap used in distutils' bdist_wininst ........ Modified: python/branches/release26-maint/ (props changed) python/branches/release26-maint/Doc/distutils/builtdist.rst python/branches/release26-maint/Misc/NEWS Modified: python/branches/release26-maint/Doc/distutils/builtdist.rst ============================================================================== --- python/branches/release26-maint/Doc/distutils/builtdist.rst (original) +++ python/branches/release26-maint/Doc/distutils/builtdist.rst Sun Jun 6 22:10:03 2010 @@ -318,7 +318,7 @@ option. By default the installer will display the cool "Python Powered" logo when it is -run, but you can also supply your own bitmap which must be a Windows +run, but you can also supply your own 152x161 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 Modified: python/branches/release26-maint/Misc/NEWS ============================================================================== --- python/branches/release26-maint/Misc/NEWS (original) +++ python/branches/release26-maint/Misc/NEWS Sun Jun 6 22:10:03 2010 @@ -282,6 +282,12 @@ - Issue #8193: Fix test_zlib failure with zlib 1.2.4. +Documentation +------------- + +- Issue #8909: Added the size of the bitmap used in the installer created by + distutils' bdist_wininst. Patch by Anatoly Techtonik. + What's New in Python 2.6.5? =========================== From python-checkins at python.org Sun Jun 6 22:18:42 2010 From: python-checkins at python.org (tarek.ziade) Date: Sun, 6 Jun 2010 22:18:42 +0200 (CEST) Subject: [Python-checkins] r81790 - in python/branches/py3k: Doc/distutils/builtdist.rst Misc/NEWS Message-ID: <20100606201842.6071BEEA5F@mail.python.org> Author: tarek.ziade Date: Sun Jun 6 22:18:42 2010 New Revision: 81790 Log: Merged revisions 81788 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81788 | tarek.ziade | 2010-06-06 22:05:20 +0200 (Sun, 06 Jun 2010) | 1 line Fixed #8909: now the doc details the size of the bitmap used in distutils' bdist_wininst ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Doc/distutils/builtdist.rst python/branches/py3k/Misc/NEWS Modified: python/branches/py3k/Doc/distutils/builtdist.rst ============================================================================== --- python/branches/py3k/Doc/distutils/builtdist.rst (original) +++ python/branches/py3k/Doc/distutils/builtdist.rst Sun Jun 6 22:18:42 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 bitmap which must be a Windows +run, but you can also supply your own 152x161 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 Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Sun Jun 6 22:18:42 2010 @@ -1421,6 +1421,9 @@ - Update python manual page (options -B, -O0, -s, environment variables PYTHONDONTWRITEBYTECODE, PYTHONNOUSERSITE). +- Issue #8909: Added the size of the bitmap used in the installer created by + distutils' bdist_wininst. Patch by Anatoly Techtonik. + Tests ----- From python-checkins at python.org Sun Jun 6 22:23:10 2010 From: python-checkins at python.org (tarek.ziade) Date: Sun, 6 Jun 2010 22:23:10 +0200 (CEST) Subject: [Python-checkins] r81791 - in python/branches/release31-maint: Doc/distutils/builtdist.rst Misc/NEWS Message-ID: <20100606202310.C96FAEEB38@mail.python.org> Author: tarek.ziade Date: Sun Jun 6 22:23:10 2010 New Revision: 81791 Log: Merged revisions 81790 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ................ r81790 | tarek.ziade | 2010-06-06 22:18:42 +0200 (Sun, 06 Jun 2010) | 9 lines Merged revisions 81788 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81788 | tarek.ziade | 2010-06-06 22:05:20 +0200 (Sun, 06 Jun 2010) | 1 line Fixed #8909: now the doc details the size of the bitmap used in distutils' bdist_wininst ........ ................ Modified: python/branches/release31-maint/ (props changed) python/branches/release31-maint/Doc/distutils/builtdist.rst python/branches/release31-maint/Misc/NEWS Modified: python/branches/release31-maint/Doc/distutils/builtdist.rst ============================================================================== --- python/branches/release31-maint/Doc/distutils/builtdist.rst (original) +++ python/branches/release31-maint/Doc/distutils/builtdist.rst Sun Jun 6 22:23:10 2010 @@ -321,7 +321,7 @@ option. By default the installer will display the cool "Python Powered" logo when it is -run, but you can also supply your own bitmap which must be a Windows +run, but you can also supply your own 152x161 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 Modified: python/branches/release31-maint/Misc/NEWS ============================================================================== --- python/branches/release31-maint/Misc/NEWS (original) +++ python/branches/release31-maint/Misc/NEWS Sun Jun 6 22:23:10 2010 @@ -774,6 +774,9 @@ - Update python manual page (options -B, -O0, -s, environment variables PYTHONDONTWRITEBYTECODE, PYTHONNOUSERSITE). +- Issue #8909: Added the size of the bitmap used in the installer created by + distutils' bdist_wininst. Patch by Anatoly Techtonik. + What's New in Python 3.1.1? =========================== From python-checkins at python.org Sun Jun 6 22:27:51 2010 From: python-checkins at python.org (victor.stinner) Date: Sun, 6 Jun 2010 22:27:51 +0200 (CEST) Subject: [Python-checkins] r81792 - python/branches/py3k/Python/getargs.c Message-ID: <20100606202751.D28F4EEB3C@mail.python.org> Author: victor.stinner Date: Sun Jun 6 22:27:51 2010 New Revision: 81792 Log: Simplify getbuffer(): convertbuffer() fails anyway if bf_getbuffer is NULL Modified: python/branches/py3k/Python/getargs.c Modified: python/branches/py3k/Python/getargs.c ============================================================================== --- python/branches/py3k/Python/getargs.c (original) +++ python/branches/py3k/Python/getargs.c Sun Jun 6 22:27:51 2010 @@ -1410,7 +1410,7 @@ static Py_ssize_t convertbuffer(PyObject *arg, void **p, char **errmsg) { - PyBufferProcs *pb = arg->ob_type->tp_as_buffer; + PyBufferProcs *pb = Py_TYPE(arg)->tp_as_buffer; Py_ssize_t count; Py_buffer view; @@ -1438,31 +1438,23 @@ static int getbuffer(PyObject *arg, Py_buffer *view, char **errmsg) { - void *buf; - Py_ssize_t count; - PyBufferProcs *pb = arg->ob_type->tp_as_buffer; + PyBufferProcs *pb = Py_TYPE(arg)->tp_as_buffer; if (pb == NULL) { *errmsg = "bytes or buffer"; return -1; } - if (pb->bf_getbuffer) { - if (PyObject_GetBuffer(arg, view, 0) < 0) { - *errmsg = "convertible to a buffer"; - return -1; - } - if (!PyBuffer_IsContiguous(view, 'C')) { - *errmsg = "contiguous buffer"; - return -1; - } - return 0; + if (pb->bf_getbuffer == NULL) { + *errmsg = "convertible to a buffer"; + return -1; } - - count = convertbuffer(arg, &buf, errmsg); - if (count < 0) { + if (PyObject_GetBuffer(arg, view, 0) < 0) { *errmsg = "convertible to a buffer"; - return count; + return -1; + } + if (!PyBuffer_IsContiguous(view, 'C')) { + *errmsg = "contiguous buffer"; + return -1; } - PyBuffer_FillInfo(view, NULL, buf, count, 1, 0); return 0; } From python-checkins at python.org Sun Jun 6 22:33:05 2010 From: python-checkins at python.org (victor.stinner) Date: Sun, 6 Jun 2010 22:33:05 +0200 (CEST) Subject: [Python-checkins] r81793 - python/branches/release31-maint Message-ID: <20100606203305.80CFFEBB5@mail.python.org> Author: victor.stinner Date: Sun Jun 6 22:33:05 2010 New Revision: 81793 Log: Blocked revisions 81792 via svnmerge ........ r81792 | victor.stinner | 2010-06-06 22:27:51 +0200 (dim., 06 juin 2010) | 2 lines Simplify getbuffer(): convertbuffer() fails anyway if bf_getbuffer is NULL ........ Modified: python/branches/release31-maint/ (props changed) From python-checkins at python.org Sun Jun 6 22:38:02 2010 From: python-checkins at python.org (victor.stinner) Date: Sun, 6 Jun 2010 22:38:02 +0200 (CEST) Subject: [Python-checkins] r81794 - python/branches/py3k/Python/getargs.c Message-ID: <20100606203802.93F58EEE35@mail.python.org> Author: victor.stinner Date: Sun Jun 6 22:38:02 2010 New Revision: 81794 Log: convertsimple(): call PyErr_NoMemory() on PyMem_NEW() failure Raise a more revelant error (MemoryError instead of TypeError) Modified: python/branches/py3k/Python/getargs.c Modified: python/branches/py3k/Python/getargs.c ============================================================================== --- python/branches/py3k/Python/getargs.c (original) +++ python/branches/py3k/Python/getargs.c Sun Jun 6 22:38:02 2010 @@ -1172,6 +1172,7 @@ *buffer = PyMem_NEW(char, size + 1); if (*buffer == NULL) { Py_DECREF(s); + PyErr_NoMemory(); return converterr( "(memory error)", arg, msgbuf, bufsize); @@ -1215,6 +1216,7 @@ *buffer = PyMem_NEW(char, size + 1); if (*buffer == NULL) { Py_DECREF(s); + PyErr_NoMemory(); return converterr("(memory error)", arg, msgbuf, bufsize); } From python-checkins at python.org Sun Jun 6 22:38:57 2010 From: python-checkins at python.org (victor.stinner) Date: Sun, 6 Jun 2010 22:38:57 +0200 (CEST) Subject: [Python-checkins] r81795 - python/branches/release31-maint Message-ID: <20100606203857.231B3EEB39@mail.python.org> Author: victor.stinner Date: Sun Jun 6 22:38:57 2010 New Revision: 81795 Log: Blocked revisions 81794 via svnmerge ........ r81794 | victor.stinner | 2010-06-06 22:38:02 +0200 (dim., 06 juin 2010) | 4 lines convertsimple(): call PyErr_NoMemory() on PyMem_NEW() failure Raise a more revelant error (MemoryError instead of TypeError) ........ Modified: python/branches/release31-maint/ (props changed) From solipsis at pitrou.net Mon Jun 7 01:23:42 2010 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Mon, 7 Jun 2010 01:23:42 +0200 (CEST) Subject: [Python-checkins] Daily py3k reference leaks (r81794): sum=0 Message-ID: <20100606232342.9F65B17758@ns6635.ovh.net> py3k results for svn r81794 (hg cset 805a4e38517f) -------------------------------------------------- Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/py3k/refleaks/reflogIlGttn', '-x'] From python-checkins at python.org Mon Jun 7 12:46:04 2010 From: python-checkins at python.org (stefan.krah) Date: Mon, 7 Jun 2010 12:46:04 +0200 (CEST) Subject: [Python-checkins] r81796 - in python/branches/py3k-cdecimal: Doc/c-api/init.rst Doc/c-api/sys.rst Doc/distutils/builtdist.rst Doc/extending/newtypes.rst Doc/howto/descriptor.rst Doc/howto/index.rst Doc/library/argparse.rst Doc/library/datetime.rst Doc/library/decimal.rst Doc/library/dis.rst Doc/library/fcntl.rst Doc/library/ftplib.rst Doc/library/functions.rst Doc/library/getopt.rst Doc/library/hashlib.rst Doc/library/io.rst Doc/library/json.rst Doc/library/multiprocessing.rst Doc/library/optparse.rst Doc/library/os.rst Doc/library/socket.rst Doc/library/sqlite3.rst Doc/library/ssl.rst Doc/library/stdtypes.rst Doc/library/subprocess.rst Doc/library/symtable.rst Doc/library/sys.rst Doc/library/sysconfig.rst Doc/library/syslog.rst Doc/library/telnetlib.rst Doc/library/tempfile.rst Doc/library/time.rst Doc/library/unittest.rst Doc/library/urllib.parse.rst Doc/library/urllib.request.rst Doc/library/winreg.rst Doc/reference/datamodel.rst Doc/tools/sphinxext/pyspecific.py Doc/tutorial/datastructures.rst Doc/whatsnew/3.2.rst Include/longobject.h Include/pyport.h Include/sysmodule.h Lib/_abcoll.py Lib/argparse.py Lib/base64.py Lib/codecs.py Lib/decimal.py Lib/distutils/log.py Lib/distutils/tests/test_log.py Lib/distutils/unixccompiler.py Lib/email/charset.py Lib/email/encoders.py Lib/email/test/test_email.py Lib/encodings/utf_16.py Lib/encodings/utf_32.py Lib/fractions.py Lib/ftplib.py Lib/functools.py Lib/html/parser.py Lib/http/client.py Lib/lib2to3/refactor.py Lib/linecache.py Lib/pipes.py Lib/sqlite3/test/dbapi.py Lib/ssl.py Lib/subprocess.py Lib/sysconfig.py Lib/tabnanny.py Lib/tarfile.py Lib/test/regrtest.py Lib/test/test_argparse.py Lib/test/test_base64.py Lib/test/test_builtin.py Lib/test/test_codecs.py Lib/test/test_collections.py Lib/test/test_complex.py Lib/test/test_datetime.py Lib/test/test_decimal.py Lib/test/test_descr.py Lib/test/test_enumerate.py Lib/test/test_float.py Lib/test/test_ftplib.py Lib/test/test_gdb.py Lib/test/test_htmlparser.py Lib/test/test_httplib.py Lib/test/test_linecache.py Lib/test/test_long.py Lib/test/test_numeric_tower.py Lib/test/test_os.py Lib/test/test_pipes.py Lib/test/test_socketserver.py Lib/test/test_ssl.py Lib/test/test_subprocess.py Lib/test/test_sys.py Lib/test/test_sysconfig.py Lib/test/test_tarfile.py Lib/test/test_tcl.py Lib/test/test_urllib2.py Lib/test/test_warnings.py Lib/test/test_winreg.py Lib/test/test_winsound.py Lib/test/testtar.tar Lib/tkinter/_fix.py Lib/unittest/case.py Lib/unittest/loader.py Lib/unittest/suite.py Lib/unittest/test/test_case.py Lib/unittest/test/test_setups.py Lib/unittest/util.py Lib/urllib/request.py Lib/webbrowser.py Mac/Tools/pythonw.c Misc/ACKS Misc/NEWS Misc/developers.txt Modules/_multiprocessing/multiprocessing.h Modules/_sqlite/connection.c Modules/_ssl.c Modules/config.c.in Modules/datetimemodule.c Modules/main.c Modules/timemodule.c Objects/abstract.c Objects/complexobject.c Objects/longobject.c Objects/object.c Objects/typeobject.c PC/winreg.c Python/_warnings.c Python/ceval.c Python/getargs.c Python/pythonrun.c Python/sysmodule.c Tools/gdb/libpython.py Tools/i18n/msgfmt.py Tools/scripts/serve.py configure configure.in setup.py Message-ID: <20100607104604.16021EEE8F@mail.python.org> Author: stefan.krah Date: Mon Jun 7 12:46:02 2010 New Revision: 81796 Log: Merged revisions 81352,81356,81358-81361,81364-81368,81370,81372,81375,81378,81387,81392-81393,81397,81400,81403,81406,81410,81417-81418,81421,81424,81427,81435,81438,81442,81446,81452,81455,81457,81461,81470,81474,81476,81481,81485-81486,81491,81493,81495,81498,81504,81511,81513-81514,81519,81522,81526,81528,81532-81533,81535,81538,81541,81545,81547-81548,81550,81553,81556-81557,81560,81564-81565,81568,81572,81575,81581,81583,81585,81588,81590,81595,81600,81604,81607,81609,81611-81613,81623,81625,81628,81630,81632,81638,81642,81647,81650,81654,81656,81660,81665,81670,81673,81682,81685,81689,81694-81695,81698-81699,81703,81708,81711,81713,81725,81730-81731,81737,81742-81743,81746,81748,81751,81754-81755,81757,81762,81765-81766,81768,81771,81778-81782,81790,81792,81794 via svnmerge from svn+ssh://pythondev at svn.python.org/python/branches/py3k ................ r81352 | stefan.krah | 2010-05-19 17:52:31 +0200 (Wed, 19 May 2010) | 9 lines Merged revisions 81350 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81350 | stefan.krah | 2010-05-19 17:46:39 +0200 (Wed, 19 May 2010) | 1 line Fix typos in docstrings. ........ ................ r81356 | stefan.krah | 2010-05-19 18:09:41 +0200 (Wed, 19 May 2010) | 9 lines Merged revisions 81354 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81354 | stefan.krah | 2010-05-19 17:59:40 +0200 (Wed, 19 May 2010) | 3 lines Fix typo. ........ ................ r81358 | victor.stinner | 2010-05-19 18:53:30 +0200 (Wed, 19 May 2010) | 4 lines Issue #8589: Decode PYTHONWARNINGS environment variable with the file system encoding and surrogateespace error handler instead of the locale encoding to be consistent with os.environ. Add PySys_AddWarnOptionUnicode() function. ................ r81359 | victor.stinner | 2010-05-19 19:00:07 +0200 (Wed, 19 May 2010) | 4 lines Issue #8663: distutils.log emulates backslashreplace error handler. Fix compilation in a non-ASCII directory if stdout encoding is ASCII (eg. if stdout is not a TTY). ................ r81360 | victor.stinner | 2010-05-19 19:11:19 +0200 (Wed, 19 May 2010) | 5 lines regrtest.py: call replace_stdout() before the first call to print() print("== ", os.getcwd()) fails if the current working directory is not ASCII whereas sys.stdout encoding is ASCII. ................ r81361 | victor.stinner | 2010-05-19 19:15:50 +0200 (Wed, 19 May 2010) | 2 lines Oops, add the new test_log.py for distutils test suite (missing part of r81359) ................ r81364 | victor.stinner | 2010-05-19 22:40:50 +0200 (Wed, 19 May 2010) | 3 lines Issue #8766: Initialize _warnings module before importing the first module. Fix a crash if an empty directory called "encodings" exists in sys.path. ................ r81365 | georg.brandl | 2010-05-19 22:57:08 +0200 (Wed, 19 May 2010) | 77 lines Merged revisions 80030,80067,80069,80080-80081,80084,80432-80433,80465-80470,81059,81065-81067 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r80030 | georg.brandl | 2010-04-13 08:43:54 +0200 (Di, 13 Apr 2010) | 1 line Get rid of multi-row cells. ........ r80067 | georg.brandl | 2010-04-14 10:53:38 +0200 (Mi, 14 Apr 2010) | 1 line #5341: typo. ........ r80069 | georg.brandl | 2010-04-14 15:50:31 +0200 (Mi, 14 Apr 2010) | 1 line Add an x-ref to where the O_ constants are documented and move the SEEK_ constants after lseek(). ........ r80080 | georg.brandl | 2010-04-14 21:16:38 +0200 (Mi, 14 Apr 2010) | 1 line #8399: add note about Windows and O_BINARY. ........ r80081 | georg.brandl | 2010-04-14 23:34:44 +0200 (Mi, 14 Apr 2010) | 1 line #5250: document __instancecheck__ and __subclasscheck__. I hope the part about the class/metaclass distinction is understandable. ........ r80084 | georg.brandl | 2010-04-14 23:46:45 +0200 (Mi, 14 Apr 2010) | 1 line Fix missing. ........ r80432 | georg.brandl | 2010-04-24 10:56:58 +0200 (Sa, 24 Apr 2010) | 1 line Markup fixes. ........ r80433 | georg.brandl | 2010-04-24 11:08:10 +0200 (Sa, 24 Apr 2010) | 1 line #7507: quote "!" in pipes.quote(); it is a special character for some shells. ........ r80465 | georg.brandl | 2010-04-25 12:29:17 +0200 (So, 25 Apr 2010) | 1 line Remove LaTeXy index entry syntax. ........ r80466 | georg.brandl | 2010-04-25 12:54:42 +0200 (So, 25 Apr 2010) | 1 line Patch from Tim Hatch: Better cross-referencing in socket and winreg docs. ........ r80467 | georg.brandl | 2010-04-25 12:55:16 +0200 (So, 25 Apr 2010) | 1 line Patch from Tim Hatch: Remove reference to winreg being the fabled high-level registry interface. ........ r80468 | georg.brandl | 2010-04-25 12:55:58 +0200 (So, 25 Apr 2010) | 1 line Patch from Tim Hatch: Minor spelling changes to _winreg docs. ........ r80469 | georg.brandl | 2010-04-25 12:56:41 +0200 (So, 25 Apr 2010) | 1 line Fix code example to have valid syntax so that it can be highlighted. ........ r80470 | georg.brandl | 2010-04-25 12:57:15 +0200 (So, 25 Apr 2010) | 1 line Patch from Tim Hatch: Make socket setblocking <-> settimeout examples symmetric. ........ r81059 | georg.brandl | 2010-05-10 23:02:51 +0200 (Mo, 10 Mai 2010) | 1 line #8642: fix wrong function name. ........ r81065 | georg.brandl | 2010-05-10 23:46:50 +0200 (Mo, 10 Mai 2010) | 1 line Fix reference direction. ........ r81066 | georg.brandl | 2010-05-10 23:50:57 +0200 (Mo, 10 Mai 2010) | 1 line Consolidate deprecation messages. ........ r81067 | georg.brandl | 2010-05-10 23:51:33 +0200 (Mo, 10 Mai 2010) | 1 line Fix typo. ........ ................ r81366 | georg.brandl | 2010-05-19 22:58:02 +0200 (Wed, 19 May 2010) | 61 lines Recorded merge of revisions 80030,80067,80069,80080-80081,80084,80432-80433,80465,80470,81059,81065-81067 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r80030 | georg.brandl | 2010-04-13 08:43:54 +0200 (Di, 13 Apr 2010) | 1 line Get rid of multi-row cells. ........ r80067 | georg.brandl | 2010-04-14 10:53:38 +0200 (Mi, 14 Apr 2010) | 1 line #5341: typo. ........ r80069 | georg.brandl | 2010-04-14 15:50:31 +0200 (Mi, 14 Apr 2010) | 1 line Add an x-ref to where the O_ constants are documented and move the SEEK_ constants after lseek(). ........ r80080 | georg.brandl | 2010-04-14 21:16:38 +0200 (Mi, 14 Apr 2010) | 1 line #8399: add note about Windows and O_BINARY. ........ r80081 | georg.brandl | 2010-04-14 23:34:44 +0200 (Mi, 14 Apr 2010) | 1 line #5250: document __instancecheck__ and __subclasscheck__. I hope the part about the class/metaclass distinction is understandable. ........ r80084 | georg.brandl | 2010-04-14 23:46:45 +0200 (Mi, 14 Apr 2010) | 1 line Fix missing. ........ r80432 | georg.brandl | 2010-04-24 10:56:58 +0200 (Sa, 24 Apr 2010) | 1 line Markup fixes. ........ r80433 | georg.brandl | 2010-04-24 11:08:10 +0200 (Sa, 24 Apr 2010) | 1 line #7507: quote "!" in pipes.quote(); it is a special character for some shells. ........ r80465 | georg.brandl | 2010-04-25 12:29:17 +0200 (So, 25 Apr 2010) | 1 line Remove LaTeXy index entry syntax. ........ r80470 | georg.brandl | 2010-04-25 12:57:15 +0200 (So, 25 Apr 2010) | 1 line Patch from Tim Hatch: Make socket setblocking <-> settimeout examples symmetric. ........ r81059 | georg.brandl | 2010-05-10 23:02:51 +0200 (Mo, 10 Mai 2010) | 1 line #8642: fix wrong function name. ........ r81065 | georg.brandl | 2010-05-10 23:46:50 +0200 (Mo, 10 Mai 2010) | 1 line Fix reference direction. ........ r81066 | georg.brandl | 2010-05-10 23:50:57 +0200 (Mo, 10 Mai 2010) | 1 line Consolidate deprecation messages. ........ r81067 | georg.brandl | 2010-05-10 23:51:33 +0200 (Mo, 10 Mai 2010) | 1 line Fix typo. ........ ................ r81367 | georg.brandl | 2010-05-19 23:03:51 +0200 (Wed, 19 May 2010) | 21 lines Recorded merge of revisions 80466-80469 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r80466 | georg.brandl | 2010-04-25 12:54:42 +0200 (So, 25 Apr 2010) | 1 line Patch from Tim Hatch: Better cross-referencing in socket and winreg docs. ........ r80467 | georg.brandl | 2010-04-25 12:55:16 +0200 (So, 25 Apr 2010) | 1 line Patch from Tim Hatch: Remove reference to winreg being the fabled high-level registry interface. ........ r80468 | georg.brandl | 2010-04-25 12:55:58 +0200 (So, 25 Apr 2010) | 1 line Patch from Tim Hatch: Minor spelling changes to _winreg docs. ........ r80469 | georg.brandl | 2010-04-25 12:56:41 +0200 (So, 25 Apr 2010) | 1 line Fix code example to have valid syntax so that it can be highlighted. ........ ................ r81368 | georg.brandl | 2010-05-19 23:06:36 +0200 (Wed, 19 May 2010) | 9 lines Merged revisions 80068 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r80068 | georg.brandl | 2010-04-14 10:56:01 +0200 (Mi, 14 Apr 2010) | 1 line #5341: fix typo and adapt docstring syntax. ........ ................ r81370 | georg.brandl | 2010-05-19 23:39:51 +0200 (Wed, 19 May 2010) | 1 line Add descriptor HOWTO to py3k docs. ................ r81372 | tarek.ziade | 2010-05-20 00:25:00 +0200 (Thu, 20 May 2010) | 9 lines Merged revisions 81371 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81371 | tarek.ziade | 2010-05-20 00:20:14 +0200 (Thu, 20 May 2010) | 1 line #8759: Fixed user paths in sysconfig for posix and os2 schemes ........ ................ r81375 | victor.stinner | 2010-05-20 01:04:56 +0200 (Thu, 20 May 2010) | 9 lines Issue #8559: improve unicode support of (gdb) libpython.py * Escape non printable characters (use locale.getpreferredencoding()) * Fix support of surrogate pairs * test_gdb.py: use ascii() instead of repr() in gdb program arguments to avoid encoding issues * Fix test_strings() of test_gdb.py for encoding different than UTF-8 (eg. ACSII) ................ r81378 | victor.stinner | 2010-05-20 13:30:37 +0200 (Thu, 20 May 2010) | 14 lines Blocked revisions 81377 via svnmerge ........ r81377 | victor.stinner | 2010-05-20 13:29:45 +0200 (jeu., 20 mai 2010) | 8 lines libpython.py: fix support of non-BMP unicode characters Forward port some code from Python3: * join surrogate pairs if sizeof(Py_UNICODE)==2 * Enable non-BMP test on narrow builds using u"\U0001D121" instead of unichr(0x1D121) ........ ................ r81387 | benjamin.peterson | 2010-05-21 00:29:43 +0200 (Fri, 21 May 2010) | 9 lines Merged revisions 81385 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81385 | benjamin.peterson | 2010-05-20 17:23:37 -0500 (Thu, 20 May 2010) | 1 line fix extra 't' #8778 ........ ................ r81392 | antoine.pitrou | 2010-05-21 11:56:06 +0200 (Fri, 21 May 2010) | 5 lines Issue #4870: Add an `options` attribute to SSL contexts, as well as several ``OP_*`` constants to the `ssl` module. This allows to selectively disable protocol versions, when used in combination with `PROTOCOL_SSLv23`. ................ r81393 | victor.stinner | 2010-05-21 12:52:08 +0200 (Fri, 21 May 2010) | 3 lines Issue #8774: tabnanny uses the encoding cookie (#coding:...) to use the correct encoding ................ r81397 | mark.dickinson | 2010-05-21 16:55:26 +0200 (Fri, 21 May 2010) | 10 lines Issue #8748: Fix two issues with comparisons between complex and integer objects. (1) The comparison could incorrectly return True in some cases (2**53+1 == complex(2**53) == 2**53), breaking transivity of equality. (2) The comparison raised an OverflowError for large integers, leading to unpredictable exceptions when combining integers and complex objects in sets or dicts. Patch by Meador Inge. ................ r81400 | antoine.pitrou | 2010-05-21 19:25:34 +0200 (Fri, 21 May 2010) | 12 lines Merged revisions 81398 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81398 | antoine.pitrou | 2010-05-21 19:12:38 +0200 (ven., 21 mai 2010) | 6 lines Issue #5753: A new C API function, :cfunc:`PySys_SetArgvEx`, allows embedders of the interpreter to set sys.argv without also modifying sys.path. This helps fix `CVE-2008-5983 `_. ........ ................ r81403 | victor.stinner | 2010-05-21 22:13:12 +0200 (Fri, 21 May 2010) | 5 lines Issue #8780: Fix a regression introduced by r78946 in subprocess on Windows Ensure that stdout / stderr is inherited from the parent if stdout=PIPE / stderr=PIPE is not used. ................ r81406 | georg.brandl | 2010-05-21 22:28:13 +0200 (Fri, 21 May 2010) | 9 lines Merged revisions 81404 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81404 | georg.brandl | 2010-05-21 22:24:45 +0200 (Fr, 21 Mai 2010) | 1 line #8783: replace link to now dead hash collision FAQ. ........ ................ r81410 | georg.brandl | 2010-05-21 22:45:12 +0200 (Fri, 21 May 2010) | 1 line Remove redundant example. ................ r81417 | benjamin.peterson | 2010-05-21 22:55:22 +0200 (Fri, 21 May 2010) | 9 lines Merged revisions 81414 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81414 | benjamin.peterson | 2010-05-21 15:51:45 -0500 (Fri, 21 May 2010) | 1 line return NotImplemented from Mapping when comparing to a non-mapping #8729 ........ ................ r81418 | georg.brandl | 2010-05-21 22:57:33 +0200 (Fri, 21 May 2010) | 9 lines Recorded merge of revisions 81415 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81415 | georg.brandl | 2010-05-21 22:52:46 +0200 (Fr, 21 Mai 2010) | 1 line typo ........ ................ r81421 | georg.brandl | 2010-05-21 23:01:32 +0200 (Fri, 21 May 2010) | 1 line Fix variable name in example. ................ r81424 | georg.brandl | 2010-05-21 23:03:02 +0200 (Fri, 21 May 2010) | 8 lines Blocked revisions 81419 via svnmerge ........ r81419 | georg.brandl | 2010-05-21 22:58:12 +0200 (Fr, 21 Mai 2010) | 1 line Add missing parameter in SimpleXMLRPCServer signature. ........ ................ r81427 | georg.brandl | 2010-05-21 23:12:07 +0200 (Fri, 21 May 2010) | 1 line Fix signatures for the various TemporaryFile class^Wfunctions. ................ r81435 | georg.brandl | 2010-05-21 23:33:23 +0200 (Fri, 21 May 2010) | 9 lines Merged revisions 81431 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81431 | georg.brandl | 2010-05-21 23:30:47 +0200 (Fr, 21 Mai 2010) | 1 line #8707: remove duplicate paragraph part. ........ ................ r81438 | benjamin.peterson | 2010-05-21 23:45:06 +0200 (Fri, 21 May 2010) | 25 lines Merged revisions 81428-81429,81432-81433,81437 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81428 | benjamin.peterson | 2010-05-21 16:16:12 -0500 (Fri, 21 May 2010) | 1 line use addCleanup ........ r81429 | benjamin.peterson | 2010-05-21 16:17:22 -0500 (Fri, 21 May 2010) | 1 line fix name ........ r81432 | benjamin.peterson | 2010-05-21 16:31:24 -0500 (Fri, 21 May 2010) | 1 line ensure the last line has a trailing newline #8782 ........ r81433 | benjamin.peterson | 2010-05-21 16:32:49 -0500 (Fri, 21 May 2010) | 1 line remove debugging rubish ........ r81437 | benjamin.peterson | 2010-05-21 16:35:44 -0500 (Fri, 21 May 2010) | 1 line simplify and modernize updatecache() ........ ................ r81442 | georg.brandl | 2010-05-21 23:48:27 +0200 (Fri, 21 May 2010) | 9 lines Merged revisions 81440 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81440 | georg.brandl | 2010-05-21 23:47:05 +0200 (Fr, 21 Mai 2010) | 1 line Correct info for Semaphore.acquire() semantics under OSX. ........ ................ r81446 | georg.brandl | 2010-05-21 23:49:47 +0200 (Fri, 21 May 2010) | 9 lines Merged revisions 81443 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81443 | georg.brandl | 2010-05-21 23:48:57 +0200 (Fr, 21 Mai 2010) | 1 line typo ........ ................ r81452 | georg.brandl | 2010-05-22 00:04:32 +0200 (Sat, 22 May 2010) | 9 lines Merged revisions 81450 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81450 | georg.brandl | 2010-05-22 00:03:29 +0200 (Sa, 22 Mai 2010) | 1 line #8709: mention Windows support for os.devnull. ........ ................ r81455 | victor.stinner | 2010-05-22 00:52:10 +0200 (Sat, 22 May 2010) | 9 lines Blocked revisions 81454 via svnmerge ........ r81454 | victor.stinner | 2010-05-22 00:50:28 +0200 (sam., 22 mai 2010) | 3 lines Issue #5640: Fix Shift-JIS incremental encoder for error handlers different than strict ........ ................ r81457 | victor.stinner | 2010-05-22 01:45:42 +0200 (Sat, 22 May 2010) | 3 lines Issue #3798: sys.exit(message) writes the message to sys.stderr file, instead of the C file stderr, to use stderr encoding and error handler ................ r81461 | victor.stinner | 2010-05-22 04:16:27 +0200 (Sat, 22 May 2010) | 10 lines Merged revisions 81459 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81459 | victor.stinner | 2010-05-22 04:11:07 +0200 (sam., 22 mai 2010) | 3 lines Issue #6268: Fix seek() method of codecs.open(), don't read the BOM twice after seek(0) ........ ................ r81470 | mark.dickinson | 2010-05-22 14:02:35 +0200 (Sat, 22 May 2010) | 1 line Issue #8749: remove unused code in Objects/object.c. Thanks Yaniv Aknin. ................ r81474 | victor.stinner | 2010-05-22 18:59:09 +0200 (Sat, 22 May 2010) | 20 lines Merged revisions 81471-81472 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81471 | victor.stinner | 2010-05-22 15:37:56 +0200 (sam., 22 mai 2010) | 7 lines Issue #6268: More bugfixes about BOM, UTF-16 and UTF-32 * Fix seek() method of codecs.open(), don't write the BOM twice after seek(0) * Fix reset() method of codecs, UTF-16, UTF-32 and StreamWriter classes * test_codecs: use "w+" mode instead of "wt+". "t" mode is not supported by Solaris or Windows, but does it really exist? I found it the in the issue. ........ r81472 | victor.stinner | 2010-05-22 15:44:25 +0200 (sam., 22 mai 2010) | 4 lines Fix my last commit (r81471) about codecs Rememder: don't touch the code just before a commit ........ ................ r81476 | mark.dickinson | 2010-05-22 20:35:36 +0200 (Sat, 22 May 2010) | 2 lines #Issue 8540: Make Context._clamp attribute public in decimal module. ................ r81481 | benjamin.peterson | 2010-05-22 20:59:24 +0200 (Sat, 22 May 2010) | 20 lines Merged revisions 81479 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ................ r81479 | benjamin.peterson | 2010-05-22 13:52:21 -0500 (Sat, 22 May 2010) | 13 lines Merged revisions 80937,81478 via svnmerge from svn+ssh://pythondev at svn.python.org/sandbox/trunk/2to3/lib2to3 ........ r80937 | benjamin.peterson | 2010-05-07 14:10:58 -0500 (Fri, 07 May 2010) | 1 line remove redundant unicode call ........ r81478 | benjamin.peterson | 2010-05-22 13:47:39 -0500 (Sat, 22 May 2010) | 1 line ensure doctests have some future_features ........ ................ ................ r81485 | mark.dickinson | 2010-05-23 15:26:48 +0200 (Sun, 23 May 2010) | 1 line Remove duplicate NEWS entry. ................ r81486 | mark.dickinson | 2010-05-23 15:33:13 +0200 (Sun, 23 May 2010) | 6 lines Issue #8188: Introduce a new scheme for computing hashes of numbers (instances of int, float, complex, decimal.Decimal and fractions.Fraction) that makes it easy to maintain the invariant that hash(x) == hash(y) whenever x and y have equal value. ................ r81491 | steven.bethard | 2010-05-24 05:21:08 +0200 (Mon, 24 May 2010) | 9 lines Merged revisions 81490 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81490 | steven.bethard | 2010-05-23 19:38:00 -0700 (Sun, 23 May 2010) | 1 line argparse documentation updates (including updates to optparse and getopt documentation that were promised in the PEP) ........ ................ r81493 | steven.bethard | 2010-05-24 05:47:38 +0200 (Mon, 24 May 2010) | 9 lines Merged revisions 81492 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81492 | steven.bethard | 2010-05-23 20:45:26 -0700 (Sun, 23 May 2010) | 1 line Fix default value for version help. Approved by Benjamin on python-dev: http://mail.python.org/pipermail/python-dev/2010-May/100231.html ........ ................ r81495 | antoine.pitrou | 2010-05-24 17:58:43 +0200 (Mon, 24 May 2010) | 3 lines Add a versionadded tag for SSL contexts. ................ r81498 | antoine.pitrou | 2010-05-24 23:20:20 +0200 (Mon, 24 May 2010) | 3 lines Document the context attribute of SSL sockets ................ r81504 | victor.stinner | 2010-05-24 23:46:25 +0200 (Mon, 24 May 2010) | 13 lines Recorded merge of revisions 81500-81501 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81500 | victor.stinner | 2010-05-24 23:33:24 +0200 (lun., 24 mai 2010) | 2 lines Issue #6662: Fix parsing of malformatted charref (&#bad;) ........ r81501 | victor.stinner | 2010-05-24 23:37:28 +0200 (lun., 24 mai 2010) | 2 lines Add the author of the last fix (Issue #6662) ........ ................ r81511 | benjamin.peterson | 2010-05-25 04:27:55 +0200 (Tue, 25 May 2010) | 8 lines Blocked revisions 81509 via svnmerge ........ r81509 | benjamin.peterson | 2010-05-24 21:23:32 -0500 (Mon, 24 May 2010) | 1 line correct default docs ........ ................ r81513 | tarek.ziade | 2010-05-25 11:44:36 +0200 (Tue, 25 May 2010) | 1 line Made sysconfig a script that displays useful information - #8770 ................ r81514 | tarek.ziade | 2010-05-25 11:47:06 +0200 (Tue, 25 May 2010) | 1 line added the list of public APIs in sysconfig ................ r81519 | r.david.murray | 2010-05-25 17:26:21 +0200 (Tue, 25 May 2010) | 13 lines Blocked revisions 81518 via svnmerge ........ r81518 | r.david.murray | 2010-05-25 11:20:46 -0400 (Tue, 25 May 2010) | 8 lines Issue 8143: sync unquote in urlparse with urllib; add comment about doing so. unquote is duplicated in the two files to avoid a circular reference. (This is fixed in Python3.) Updates keep getting made to the public unquote without fixing the urlparse one, however, so this fix syncs the two and adds a comment to both to make sure changes are applied to both. ........ ................ r81522 | r.david.murray | 2010-05-25 17:36:46 +0200 (Tue, 25 May 2010) | 9 lines Recorded merge of revisions 81521 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81521 | r.david.murray | 2010-05-25 11:32:06 -0400 (Tue, 25 May 2010) | 2 lines Issue 8818: urlparse/urlsplit keyword is 'scheme', not 'default_scheme'. ........ ................ r81526 | mark.dickinson | 2010-05-25 21:06:24 +0200 (Tue, 25 May 2010) | 10 lines Merged revisions 81525 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81525 | mark.dickinson | 2010-05-25 20:01:08 +0100 (Tue, 25 May 2010) | 3 lines Issue #8816: Extra tests for some built-in functions. These tests are ports of IronPython tests. Thanks Gregory Nofi. ........ ................ r81528 | mark.dickinson | 2010-05-25 21:46:20 +0200 (Tue, 25 May 2010) | 9 lines Merged revisions 81527 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81527 | mark.dickinson | 2010-05-25 20:44:49 +0100 (Tue, 25 May 2010) | 1 line Fix a NameError in test_enumerate. ........ ................ r81532 | martin.v.loewis | 2010-05-25 22:07:11 +0200 (Tue, 25 May 2010) | 9 lines Merged revisions 81531 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81531 | martin.v.loewis | 2010-05-25 22:06:02 +0200 (Di, 25 Mai 2010) | 2 lines Add Alexander Belopolsky. ........ ................ r81533 | victor.stinner | 2010-05-25 23:12:34 +0200 (Tue, 25 May 2010) | 3 lines Issue #4769: Fix main() function of the base64 module, use sys.stdin.buffer and sys.stdout.buffer (instead of sys.stdin and sys.stdout) to use the bytes API ................ r81535 | victor.stinner | 2010-05-26 00:17:22 +0200 (Wed, 26 May 2010) | 2 lines Fix the new TestMain.test_decode() of test_base64 for Windows ................ r81538 | victor.stinner | 2010-05-26 00:35:40 +0200 (Wed, 26 May 2010) | 11 lines Blocked revisions 81537 via svnmerge ........ r81537 | victor.stinner | 2010-05-26 00:30:32 +0200 (mer., 26 mai 2010) | 3 lines Issue #3798: Write sys.exit() message to sys.stderr to use stderr encoding and error handler, instead of writing to the C stderr file in utf-8 ........ py3k was already fixed by r81252. ................ r81541 | mark.dickinson | 2010-05-26 18:02:59 +0200 (Wed, 26 May 2010) | 4 lines Issue #8817: Expose round-to-nearest variant of divmod in _PyLong_Divmod_Near for use by the datetime module; also refactor long_round to use this function. ................ r81545 | victor.stinner | 2010-05-26 19:33:03 +0200 (Wed, 26 May 2010) | 9 lines Merged revisions 81543 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81543 | victor.stinner | 2010-05-26 19:25:28 +0200 (mer., 26 mai 2010) | 2 lines Issue #7449: Skip test_socketserver if threading support is disabled ........ ................ r81547 | brian.curtin | 2010-05-26 19:43:50 +0200 (Wed, 26 May 2010) | 6 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 ................ r81548 | giampaolo.rodola | 2010-05-26 20:06:04 +0200 (Wed, 26 May 2010) | 1 line Fix issue #8806: add SSL contexts support to ftplib ................ r81550 | giampaolo.rodola | 2010-05-26 20:21:26 +0200 (Wed, 26 May 2010) | 1 line fix wrong assertIs context ................ r81553 | mark.dickinson | 2010-05-26 21:14:01 +0200 (Wed, 26 May 2010) | 9 lines Merged revisions 81551 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81551 | mark.dickinson | 2010-05-26 20:06:33 +0100 (Wed, 26 May 2010) | 1 line Issue #8825: additional testcases for int(string, 0) and long(string, 0). ........ ................ r81556 | alexander.belopolsky | 2010-05-26 22:00:12 +0200 (Wed, 26 May 2010) | 10 lines Merged revisions 81555 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81555 | alexander.belopolsky | 2010-05-26 15:43:16 -0400 (Wed, 26 May 2010) | 3 lines Issue #7879: Do not test negative timestamps on any Windows platform including Windows CE. ........ ................ r81557 | mark.dickinson | 2010-05-26 22:07:58 +0200 (Wed, 26 May 2010) | 4 lines Issue #2844: Make int('42', n) consistently raise ValueError for invalid integers n (including n = -909). ................ r81560 | alexander.belopolsky | 2010-05-26 22:48:30 +0200 (Wed, 26 May 2010) | 10 lines Merged revisions 81559 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81559 | alexander.belopolsky | 2010-05-26 16:45:37 -0400 (Wed, 26 May 2010) | 3 lines Issue #7879: Skip negative timestamps test on any Windows platform using unittest.skipIf decorator. ........ ................ r81564 | mark.dickinson | 2010-05-27 21:45:50 +0200 (Thu, 27 May 2010) | 9 lines Merged revisions 81512 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81512 | brett.cannon | 2010-05-25 03:53:04 +0100 (Tue, 25 May 2010) | 1 line Make the contributor list alphabetical again. ........ ................ r81565 | mark.dickinson | 2010-05-27 21:47:53 +0200 (Thu, 27 May 2010) | 1 line Stefan Krah was missing from Misc/ACKS in the py3k branch. ................ r81568 | alexander.belopolsky | 2010-05-27 23:42:58 +0200 (Thu, 27 May 2010) | 10 lines Merged revisions 81566 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81566 | alexander.belopolsky | 2010-05-27 16:55:27 -0400 (Thu, 27 May 2010) | 3 lines Issue #7150: Raise OverflowError if the result of adding or subtracting timedelta from date or datetime falls outside of the MINYEAR:MAXYEAR range. ........ ................ r81572 | benjamin.peterson | 2010-05-28 00:32:22 +0200 (Fri, 28 May 2010) | 1 line correct default value in signature ................ r81575 | ezio.melotti | 2010-05-28 00:38:16 +0200 (Fri, 28 May 2010) | 9 lines Merged revisions 81318 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81318 | ezio.melotti | 2010-05-19 03:32:52 +0300 (Wed, 19 May 2010) | 1 line Fix typo in argparse doc. ........ ................ r81581 | benjamin.peterson | 2010-05-28 05:23:57 +0200 (Fri, 28 May 2010) | 12 lines Blocked revisions 81578-81579 via svnmerge ........ r81578 | benjamin.peterson | 2010-05-27 21:12:36 -0500 (Thu, 27 May 2010) | 1 line remove non-ascii coding per PEP 8 ........ r81579 | benjamin.peterson | 2010-05-27 22:10:31 -0500 (Thu, 27 May 2010) | 1 line 2to3 doesn't fix test_support #6583 ........ ................ r81583 | martin.v.loewis | 2010-05-28 17:44:20 +0200 (Fri, 28 May 2010) | 9 lines Merged revisions 81582 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81582 | martin.v.loewis | 2010-05-28 17:28:47 +0200 (Fr, 28 Mai 2010) | 2 lines Issue #1759169: Drop _XOPEN_SOURCE on Solaris. ........ ................ r81585 | brian.curtin | 2010-05-28 18:08:40 +0200 (Fri, 28 May 2010) | 10 lines Merged revisions 81584 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81584 | brian.curtin | 2010-05-28 10:49:21 -0500 (Fri, 28 May 2010) | 3 lines Fix #8405 for slow buildbots. Remove the sleep on startup and move the pipe communication into a loop to retry in case a buildbot gets even slower. ........ ................ r81588 | victor.stinner | 2010-05-28 23:55:10 +0200 (Fri, 28 May 2010) | 3 lines Issue #8837: Remove "O?" format of PyArg_Parse*() functions. The format is no used anymore and it was never documented. ................ r81590 | victor.stinner | 2010-05-29 02:13:06 +0200 (Sat, 29 May 2010) | 2 lines Remove dead code ................ r81595 | antoine.pitrou | 2010-05-29 14:08:25 +0200 (Sat, 29 May 2010) | 9 lines Merged revisions 81594 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81594 | antoine.pitrou | 2010-05-29 14:06:13 +0200 (sam., 29 mai 2010) | 3 lines Issue #8840: Make documentation for truncate() clearer ........ ................ r81600 | stefan.krah | 2010-05-29 14:59:18 +0200 (Sat, 29 May 2010) | 9 lines Merged revisions 81598 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81598 | stefan.krah | 2010-05-29 14:54:35 +0200 (Sat, 29 May 2010) | 1 line Fix typo ........ ................ r81604 | mark.dickinson | 2010-05-29 23:05:27 +0200 (Sat, 29 May 2010) | 9 lines Merged revisions 81602 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81602 | mark.dickinson | 2010-05-29 22:00:52 +0100 (Sat, 29 May 2010) | 1 line Untabify Modules/config.c.in. ........ ................ r81607 | mark.dickinson | 2010-05-30 14:12:56 +0200 (Sun, 30 May 2010) | 10 lines Blocked revisions 81606 via svnmerge ........ r81606 | mark.dickinson | 2010-05-30 13:12:25 +0100 (Sun, 30 May 2010) | 4 lines Issue #5211: Complete removal of implicit coercions for the complex type. Coercion for arithmetic operations was already removed in r78280, but that commit didn't remove coercion for rich comparisons. ........ ................ r81609 | mark.dickinson | 2010-05-30 14:17:39 +0200 (Sun, 30 May 2010) | 8 lines Blocked revisions 81608 via svnmerge ........ r81608 | mark.dickinson | 2010-05-30 13:17:11 +0100 (Sun, 30 May 2010) | 1 line Remove declaration for unused variable. ........ ................ r81611 | mark.dickinson | 2010-05-30 15:18:47 +0200 (Sun, 30 May 2010) | 10 lines Recorded merge of revisions 81610 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81610 | mark.dickinson | 2010-05-30 14:18:10 +0100 (Sun, 30 May 2010) | 3 lines Issue #8748: Fix incorrect results from comparisons between an integer and a complex instance. Based on a patch by Meador Inge. ........ ................ r81612 | benjamin.peterson | 2010-05-30 16:49:32 +0200 (Sun, 30 May 2010) | 1 line use atomic structures in non-thread version ................ r81613 | ronald.oussoren | 2010-05-30 17:46:48 +0200 (Sun, 30 May 2010) | 4 lines Remove conditional import of 'ic', that module was removed in the transition from python 2.x to python 3.x. ................ r81623 | antoine.pitrou | 2010-05-31 19:04:40 +0200 (Mon, 31 May 2010) | 9 lines Merged revisions 81621 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81621 | antoine.pitrou | 2010-05-31 19:01:01 +0200 (lun., 31 mai 2010) | 4 lines Improve documentation for getaddrinfo() (part of #8857) ........ ................ r81625 | alexander.belopolsky | 2010-05-31 19:33:47 +0200 (Mon, 31 May 2010) | 3 lines Issue #1289118: datetime.timedelta objects can now be multiplied by float and divided by float and int objects. ................ r81628 | r.david.murray | 2010-06-01 01:23:50 +0200 (Tue, 01 Jun 2010) | 9 lines Merged revisions 81587 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81587 | r.david.murray | 2010-05-28 14:17:20 -0400 (Fri, 28 May 2010) | 2 lines Make the ctl-C shutdown of serve.py prettier. ........ ................ r81630 | r.david.murray | 2010-06-01 03:11:18 +0200 (Tue, 01 Jun 2010) | 9 lines Merged revisions 81586 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81586 | r.david.murray | 2010-05-28 14:08:11 -0400 (Fri, 28 May 2010) | 2 lines Make reference to Generic Attribute Management a hyperlink. ........ ................ r81632 | r.david.murray | 2010-06-01 03:32:12 +0200 (Tue, 01 Jun 2010) | 4 lines #8845: expose sqlite3 inTransaction as RO in_transaction Connection attribute. Patch by R. David Murray, unit tests by Shashwat Anand. ................ r81638 | senthil.kumaran | 2010-06-01 14:53:48 +0200 (Tue, 01 Jun 2010) | 9 lines Merged revisions 81636 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81636 | senthil.kumaran | 2010-06-01 18:10:07 +0530 (Tue, 01 Jun 2010) | 3 lines Fix Issue8797 - urllib2 basic authentication fix for wrong passwords. It fails after 5 retries. ........ ................ r81642 | brian.curtin | 2010-06-01 15:49:19 +0200 (Tue, 01 Jun 2010) | 10 lines Merged revisions 81640 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81640 | brian.curtin | 2010-06-01 08:29:13 -0500 (Tue, 01 Jun 2010) | 3 lines Fix #8618. Ask the Windows mixer API if there are any playback devices configured before attempting to test PlaySound. ........ ................ r81647 | senthil.kumaran | 2010-06-02 04:29:00 +0200 (Wed, 02 Jun 2010) | 9 lines Merged revisions 81645 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81645 | senthil.kumaran | 2010-06-02 07:49:15 +0530 (Wed, 02 Jun 2010) | 3 lines Fix issue8788 - description of doseq parameter in urllib.urlencode ........ ................ r81650 | ronald.oussoren | 2010-06-02 05:50:56 +0200 (Wed, 02 Jun 2010) | 11 lines Merged revisions 81649 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81649 | ronald.oussoren | 2010-06-02 05:47:14 +0200 (Wed, 02 Jun 2010) | 5 lines Fix for issue8868: without this patch 'MacOS.WMAvailable()' will return False on MacOSX 10.5 or earlier and scripts won't be able to access GUI functionality. ........ ................ r81654 | antoine.pitrou | 2010-06-02 19:10:49 +0200 (Wed, 02 Jun 2010) | 10 lines Merged revisions 81652 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81652 | antoine.pitrou | 2010-06-02 19:08:47 +0200 (mer., 02 juin 2010) | 4 lines Issue #8873: add a documentation note about possible performance issues with the default of unbuffered IO in subprocess.Popen. ........ ................ r81656 | benjamin.peterson | 2010-06-02 20:10:09 +0200 (Wed, 02 Jun 2010) | 1 line remove description of LOAD_LOCALS #8874 ................ r81660 | r.david.murray | 2010-06-03 03:58:28 +0200 (Thu, 03 Jun 2010) | 25 lines Fix Charset.body_encode to encode to output_charset before calling base64mime. This means that what gets encoded in base64 is the encoded version of the unicode payload. This bug was revealed by a forward port of the tests from Issue 1368247, but the fix was completely different. Note that the merge is only of the tests, the doc changes were inappropriate since email5 expects unicode, not bytes. I'm also not convinced that quopri works correctly in email5, but that's a different issue. Merged revisions 81658 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81658 | r.david.murray | 2010-06-02 18:03:15 -0400 (Wed, 02 Jun 2010) | 9 lines #1368247: make set_charset/MIMEText automatically encode unicode _payload. Fixes (mysterious, to the end user) UnicodeErrors when using utf-8 as the charset and unicode as the _text argument. Also makes the way in which unicode gets encoded to quoted printable for other charsets more sane (it only worked by accident previously). The _payload now is encoded to the charset.output_charset if it is unicode. ........ ................ r81665 | lars.gustaebel | 2010-06-03 12:11:52 +0200 (Thu, 03 Jun 2010) | 11 lines Merged revisions 81663 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81663 | lars.gustaebel | 2010-06-03 11:56:22 +0200 (Thu, 03 Jun 2010) | 4 lines Issue #8833: tarfile created hard link entries with a size field != 0 by mistake. The associated testcase did not expose this bug because it was broken too. ........ ................ r81670 | lars.gustaebel | 2010-06-03 14:45:16 +0200 (Thu, 03 Jun 2010) | 14 lines Merged revisions 81667 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81667 | lars.gustaebel | 2010-06-03 14:34:14 +0200 (Thu, 03 Jun 2010) | 8 lines Issue #8741: Fixed the TarFile.makelink() method that is responsible for extracting symbolic and hard link entries as regular files as a work-around on platforms that do not support filesystem links. This stopped working reliably after a change in r74571. I also added a few tests for this functionality. ........ ................ r81673 | ronald.oussoren | 2010-06-03 16:42:25 +0200 (Thu, 03 Jun 2010) | 16 lines Merged revisions 81662 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81662 | ronald.oussoren | 2010-06-03 11:47:21 +0200 (Thu, 03 Jun 2010) | 9 lines Fix for issue #7724: ensure that distutils and python's own setup.py honor the MacOSX SDK when one is specified. This is needed to be able to build using the 10.4u SDK while running on OSX 10.6. This is a fixed version of the patch in r80963, I've tested this patch on OSX and Linux. ........ ................ r81682 | sean.reifschneider | 2010-06-04 03:51:38 +0200 (Fri, 04 Jun 2010) | 2 lines Issue8810: Clearing up docstring for tzinfo.utcoffset. ................ r81685 | r.david.murray | 2010-06-04 18:11:08 +0200 (Fri, 04 Jun 2010) | 4 lines #4768: store base64 encoded email body parts as text, not binary. Patch and tests by Forest Bond. ................ r81689 | senthil.kumaran | 2010-06-04 18:38:00 +0200 (Fri, 04 Jun 2010) | 9 lines Merged revisions 81687 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81687 | senthil.kumaran | 2010-06-04 22:02:14 +0530 (Fri, 04 Jun 2010) | 3 lines Fix issue6312 - close the resp object for HEAD response. ........ ................ r81694 | martin.v.loewis | 2010-06-04 19:20:56 +0200 (Fri, 04 Jun 2010) | 10 lines Merged revisions 81692 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81692 | martin.v.loewis | 2010-06-04 19:18:42 +0200 (Fr, 04 Jun 2010) | 3 lines Issue #8864: Define _XOPEN_SOURCE on Solaris for the multiprocessing module. ........ ................ r81695 | senthil.kumaran | 2010-06-04 19:27:11 +0200 (Fri, 04 Jun 2010) | 9 lines Merged revisions 81691 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81691 | senthil.kumaran | 2010-06-04 22:47:09 +0530 (Fri, 04 Jun 2010) | 3 lines test verifying the resp object is closed for HEAD response. ........ ................ r81698 | martin.v.loewis | 2010-06-04 20:14:42 +0200 (Fri, 04 Jun 2010) | 9 lines Merged revisions 81697 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81697 | martin.v.loewis | 2010-06-04 20:04:42 +0200 (Fr, 04 Jun 2010) | 2 lines Issue #5464: Implement plural forms in msgfmt.py. ........ ................ r81699 | martin.v.loewis | 2010-06-04 20:40:55 +0200 (Fri, 04 Jun 2010) | 2 lines Port to Python 3. ................ r81703 | martin.v.loewis | 2010-06-04 21:50:26 +0200 (Fri, 04 Jun 2010) | 10 lines Merged revisions 81701 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81701 | martin.v.loewis | 2010-06-04 21:39:07 +0200 (Fr, 04 Jun 2010) | 2 lines Issue #6470: Drop UNC prefix in FixTk.py Patch by Christop Gohlke and Amaury Forgeot d'Arc. ........ ................ r81708 | benjamin.peterson | 2010-06-05 02:45:37 +0200 (Sat, 05 Jun 2010) | 13 lines Merged revisions 81706-81707 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81706 | benjamin.peterson | 2010-06-04 19:32:50 -0500 (Fri, 04 Jun 2010) | 1 line properly lookup the __format__ special method ........ r81707 | benjamin.peterson | 2010-06-04 19:38:22 -0500 (Fri, 04 Jun 2010) | 1 line remove PyType_Ready call; float should be initialized in interpreter startup ........ ................ r81711 | benjamin.peterson | 2010-06-05 03:03:24 +0200 (Sat, 05 Jun 2010) | 13 lines Merged revisions 81709-81710 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81709 | benjamin.peterson | 2010-06-04 19:56:46 -0500 (Fri, 04 Jun 2010) | 1 line implement object.__format__ with PyObject_Format ........ r81710 | benjamin.peterson | 2010-06-04 20:00:10 -0500 (Fri, 04 Jun 2010) | 1 line fix ref counting ........ ................ r81713 | benjamin.peterson | 2010-06-05 04:11:45 +0200 (Sat, 05 Jun 2010) | 9 lines Merged revisions 81712 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81712 | benjamin.peterson | 2010-06-04 21:07:01 -0500 (Fri, 04 Jun 2010) | 1 line _PyObject_LookupSpecial returns a new reference ........ ................ r81725 | michael.foord | 2010-06-05 12:45:41 +0200 (Sat, 05 Jun 2010) | 9 lines Merged revisions 81724 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81724 | michael.foord | 2010-06-05 11:39:42 +0100 (Sat, 05 Jun 2010) | 1 line unittest TestLoader test discovery filename matching done in a method. This makes it easier to override the matching strategy in subclasses. No behaviour change in actual implementation. ........ ................ r81730 | michael.foord | 2010-06-05 13:27:52 +0200 (Sat, 05 Jun 2010) | 9 lines Merged revisions 81728 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81728 | michael.foord | 2010-06-05 12:23:51 +0100 (Sat, 05 Jun 2010) | 1 line Issue 8351. Suppress large diffs in unittest.TestCase.assertSequenceEqual. ........ ................ r81731 | michael.foord | 2010-06-05 13:30:23 +0200 (Sat, 05 Jun 2010) | 1 line Test fix to use floor division. Correction from merge in previous commit. ................ r81737 | mark.dickinson | 2010-06-05 13:53:11 +0200 (Sat, 05 Jun 2010) | 8 lines Blocked revisions 81736 via svnmerge ........ r81736 | mark.dickinson | 2010-06-05 12:52:24 +0100 (Sat, 05 Jun 2010) | 1 line Issue #8627: remove out-of-date warning about overriding __cmp__ ........ ................ r81742 | michael.foord | 2010-06-05 14:17:02 +0200 (Sat, 05 Jun 2010) | 9 lines Merged revisions 81739 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81739 | michael.foord | 2010-06-05 13:10:52 +0100 (Sat, 05 Jun 2010) | 1 line Removed the new max_diff argument to assertSequenceEqual. All unittest.TestCase assert methods that use difflib to produce failure messages now truncate overly long messages. New class attribute unittest.TestCase.maxDiff to configure this if necessary. Issue 8351. ........ ................ r81743 | mark.dickinson | 2010-06-05 14:38:00 +0200 (Sat, 05 Jun 2010) | 10 lines Blocked revisions 81740 via svnmerge ........ r81740 | mark.dickinson | 2010-06-05 13:14:43 +0100 (Sat, 05 Jun 2010) | 5 lines Issue #8627: Fix "XXX undetected error" from unchecked PyErr_WarnPy3k return. This is just a quick fix: if the warning is turned into an exception, the exception simply gets ignored. ........ ................ r81746 | mark.dickinson | 2010-06-05 14:52:23 +0200 (Sat, 05 Jun 2010) | 8 lines Blocked revisions 81744 via svnmerge ........ r81744 | mark.dickinson | 2010-06-05 13:51:21 +0100 (Sat, 05 Jun 2010) | 1 line Fix comment typo. ........ ................ r81748 | michael.foord | 2010-06-05 15:14:43 +0200 (Sat, 05 Jun 2010) | 9 lines Merged revisions 81747 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81747 | michael.foord | 2010-06-05 13:58:39 +0100 (Sat, 05 Jun 2010) | 1 line unittest.TestCase.assertDictEqual and assertMultilineEqual provide better default failure messages in the event of long diffs. ........ ................ r81751 | mark.dickinson | 2010-06-05 15:27:17 +0200 (Sat, 05 Jun 2010) | 8 lines Blocked revisions 81749 via svnmerge ........ r81749 | mark.dickinson | 2010-06-05 14:18:33 +0100 (Sat, 05 Jun 2010) | 2 lines Fix test_py3kwarn not to test for __cmp__-related DeprecationWarning. ........ ................ r81754 | michael.foord | 2010-06-05 15:49:56 +0200 (Sat, 05 Jun 2010) | 9 lines Merged revisions 81752 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81752 | michael.foord | 2010-06-05 14:38:16 +0100 (Sat, 05 Jun 2010) | 1 line unittest.TestCase assertion methods inform you when they have omitted an over long diff on failure. Issue 8351. ........ ................ r81755 | michael.foord | 2010-06-05 15:57:23 +0200 (Sat, 05 Jun 2010) | 9 lines Merged revisions 81753 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81753 | michael.foord | 2010-06-05 14:48:27 +0100 (Sat, 05 Jun 2010) | 1 line Fix unittest tests after previous commit. ........ ................ r81757 | alexander.belopolsky | 2010-06-05 17:04:51 +0200 (Sat, 05 Jun 2010) | 9 lines Merged revisions 81756 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81756 | alexander.belopolsky | 2010-06-05 10:54:26 -0400 (Sat, 05 Jun 2010) | 1 line Issue #8899: time.struct_time now has class and atribute docstrings. ........ ................ r81762 | michael.foord | 2010-06-05 21:58:25 +0200 (Sat, 05 Jun 2010) | 8 lines Blocked revisions 81761 via svnmerge ........ r81761 | michael.foord | 2010-06-05 20:51:38 +0100 (Sat, 05 Jun 2010) | 1 line Updated NEWS file. ........ ................ r81765 | michael.foord | 2010-06-05 23:01:08 +0200 (Sat, 05 Jun 2010) | 9 lines Merged revisions 81763 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81763 | michael.foord | 2010-06-05 21:33:43 +0100 (Sat, 05 Jun 2010) | 1 line Tests for unittest.TestCase.maxDiff. ........ ................ r81766 | michael.foord | 2010-06-05 23:12:23 +0200 (Sat, 05 Jun 2010) | 9 lines Merged revisions 81764 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81764 | michael.foord | 2010-06-05 21:59:00 +0100 (Sat, 05 Jun 2010) | 1 line Tests for issue 8302, skipped test in a setUpClass or a setUpModule are reported as skips rather than errors. ........ ................ r81768 | michael.foord | 2010-06-05 23:59:55 +0200 (Sat, 05 Jun 2010) | 9 lines Merged revisions 81767 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81767 | michael.foord | 2010-06-05 22:57:03 +0100 (Sat, 05 Jun 2010) | 1 line Documentation updates for issues 8302 and 8351 (truncating excessive diffs in unittest failure messages and reporting SkipTest exceptions in setUpClass and setUpModule as skips rather than errors). ........ ................ r81771 | michael.foord | 2010-06-06 01:59:34 +0200 (Sun, 06 Jun 2010) | 9 lines Merged revisions 81770 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81770 | michael.foord | 2010-06-06 00:58:40 +0100 (Sun, 06 Jun 2010) | 1 line Code formatting change. ........ ................ r81778 | benjamin.peterson | 2010-06-06 04:14:27 +0200 (Sun, 06 Jun 2010) | 16 lines Blocked revisions 81772-81773,81777 via svnmerge ........ r81772 | benjamin.peterson | 2010-06-05 19:22:09 -0500 (Sat, 05 Jun 2010) | 1 line bump version to 2.7 rc1 ........ r81773 | benjamin.peterson | 2010-06-05 19:49:27 -0500 (Sat, 05 Jun 2010) | 1 line update pydoc-topics ........ r81777 | benjamin.peterson | 2010-06-05 21:09:33 -0500 (Sat, 05 Jun 2010) | 1 line careening towards 2.7rc2 we go ........ ................ r81779 | benjamin.peterson | 2010-06-06 04:32:09 +0200 (Sun, 06 Jun 2010) | 13 lines Merged revisions 81774-81775 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81774 | benjamin.peterson | 2010-06-05 19:50:58 -0500 (Sat, 05 Jun 2010) | 1 line remove extra space ........ r81775 | benjamin.peterson | 2010-06-05 19:54:29 -0500 (Sat, 05 Jun 2010) | 1 line fix sphinx warning with an extra space ........ ................ r81780 | benjamin.peterson | 2010-06-06 04:40:38 +0200 (Sun, 06 Jun 2010) | 1 line fix typo ................ r81781 | benjamin.peterson | 2010-06-06 04:41:24 +0200 (Sun, 06 Jun 2010) | 1 line reST indentation nit ................ r81782 | benjamin.peterson | 2010-06-06 04:44:41 +0200 (Sun, 06 Jun 2010) | 1 line bltn-file-objects don't exist in python3 ................ r81790 | tarek.ziade | 2010-06-06 22:18:42 +0200 (Sun, 06 Jun 2010) | 9 lines Merged revisions 81788 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r81788 | tarek.ziade | 2010-06-06 22:05:20 +0200 (Sun, 06 Jun 2010) | 1 line Fixed #8909: now the doc details the size of the bitmap used in distutils' bdist_wininst ........ ................ r81792 | victor.stinner | 2010-06-06 22:27:51 +0200 (Sun, 06 Jun 2010) | 2 lines Simplify getbuffer(): convertbuffer() fails anyway if bf_getbuffer is NULL ................ r81794 | victor.stinner | 2010-06-06 22:38:02 +0200 (Sun, 06 Jun 2010) | 4 lines convertsimple(): call PyErr_NoMemory() on PyMem_NEW() failure Raise a more revelant error (MemoryError instead of TypeError) ................ Added: python/branches/py3k-cdecimal/Doc/howto/descriptor.rst - copied unchanged from r81794, /python/branches/py3k/Doc/howto/descriptor.rst python/branches/py3k-cdecimal/Lib/distutils/tests/test_log.py - copied unchanged from r81794, /python/branches/py3k/Lib/distutils/tests/test_log.py python/branches/py3k-cdecimal/Lib/test/test_numeric_tower.py - copied unchanged from r81794, /python/branches/py3k/Lib/test/test_numeric_tower.py Modified: python/branches/py3k-cdecimal/ (props changed) python/branches/py3k-cdecimal/Doc/c-api/init.rst python/branches/py3k-cdecimal/Doc/c-api/sys.rst python/branches/py3k-cdecimal/Doc/distutils/builtdist.rst python/branches/py3k-cdecimal/Doc/extending/newtypes.rst python/branches/py3k-cdecimal/Doc/howto/index.rst python/branches/py3k-cdecimal/Doc/library/argparse.rst python/branches/py3k-cdecimal/Doc/library/datetime.rst python/branches/py3k-cdecimal/Doc/library/decimal.rst python/branches/py3k-cdecimal/Doc/library/dis.rst python/branches/py3k-cdecimal/Doc/library/fcntl.rst python/branches/py3k-cdecimal/Doc/library/ftplib.rst python/branches/py3k-cdecimal/Doc/library/functions.rst python/branches/py3k-cdecimal/Doc/library/getopt.rst python/branches/py3k-cdecimal/Doc/library/hashlib.rst python/branches/py3k-cdecimal/Doc/library/io.rst python/branches/py3k-cdecimal/Doc/library/json.rst python/branches/py3k-cdecimal/Doc/library/multiprocessing.rst python/branches/py3k-cdecimal/Doc/library/optparse.rst python/branches/py3k-cdecimal/Doc/library/os.rst python/branches/py3k-cdecimal/Doc/library/socket.rst python/branches/py3k-cdecimal/Doc/library/sqlite3.rst python/branches/py3k-cdecimal/Doc/library/ssl.rst python/branches/py3k-cdecimal/Doc/library/stdtypes.rst python/branches/py3k-cdecimal/Doc/library/subprocess.rst python/branches/py3k-cdecimal/Doc/library/symtable.rst python/branches/py3k-cdecimal/Doc/library/sys.rst python/branches/py3k-cdecimal/Doc/library/sysconfig.rst python/branches/py3k-cdecimal/Doc/library/syslog.rst python/branches/py3k-cdecimal/Doc/library/telnetlib.rst python/branches/py3k-cdecimal/Doc/library/tempfile.rst python/branches/py3k-cdecimal/Doc/library/time.rst python/branches/py3k-cdecimal/Doc/library/unittest.rst python/branches/py3k-cdecimal/Doc/library/urllib.parse.rst python/branches/py3k-cdecimal/Doc/library/urllib.request.rst python/branches/py3k-cdecimal/Doc/library/winreg.rst python/branches/py3k-cdecimal/Doc/reference/datamodel.rst python/branches/py3k-cdecimal/Doc/tools/sphinxext/pyspecific.py python/branches/py3k-cdecimal/Doc/tutorial/datastructures.rst python/branches/py3k-cdecimal/Doc/whatsnew/3.2.rst python/branches/py3k-cdecimal/Include/longobject.h python/branches/py3k-cdecimal/Include/pyport.h python/branches/py3k-cdecimal/Include/sysmodule.h python/branches/py3k-cdecimal/Lib/_abcoll.py python/branches/py3k-cdecimal/Lib/argparse.py python/branches/py3k-cdecimal/Lib/base64.py python/branches/py3k-cdecimal/Lib/codecs.py python/branches/py3k-cdecimal/Lib/decimal.py python/branches/py3k-cdecimal/Lib/distutils/log.py python/branches/py3k-cdecimal/Lib/distutils/unixccompiler.py python/branches/py3k-cdecimal/Lib/email/charset.py python/branches/py3k-cdecimal/Lib/email/encoders.py python/branches/py3k-cdecimal/Lib/email/test/test_email.py python/branches/py3k-cdecimal/Lib/encodings/utf_16.py python/branches/py3k-cdecimal/Lib/encodings/utf_32.py python/branches/py3k-cdecimal/Lib/fractions.py python/branches/py3k-cdecimal/Lib/ftplib.py python/branches/py3k-cdecimal/Lib/functools.py python/branches/py3k-cdecimal/Lib/html/parser.py python/branches/py3k-cdecimal/Lib/http/client.py python/branches/py3k-cdecimal/Lib/lib2to3/refactor.py python/branches/py3k-cdecimal/Lib/linecache.py python/branches/py3k-cdecimal/Lib/pipes.py python/branches/py3k-cdecimal/Lib/sqlite3/test/dbapi.py python/branches/py3k-cdecimal/Lib/ssl.py python/branches/py3k-cdecimal/Lib/subprocess.py python/branches/py3k-cdecimal/Lib/sysconfig.py python/branches/py3k-cdecimal/Lib/tabnanny.py python/branches/py3k-cdecimal/Lib/tarfile.py python/branches/py3k-cdecimal/Lib/test/regrtest.py python/branches/py3k-cdecimal/Lib/test/test_argparse.py python/branches/py3k-cdecimal/Lib/test/test_base64.py python/branches/py3k-cdecimal/Lib/test/test_builtin.py python/branches/py3k-cdecimal/Lib/test/test_codecs.py python/branches/py3k-cdecimal/Lib/test/test_collections.py python/branches/py3k-cdecimal/Lib/test/test_complex.py python/branches/py3k-cdecimal/Lib/test/test_datetime.py python/branches/py3k-cdecimal/Lib/test/test_decimal.py python/branches/py3k-cdecimal/Lib/test/test_descr.py python/branches/py3k-cdecimal/Lib/test/test_enumerate.py python/branches/py3k-cdecimal/Lib/test/test_float.py python/branches/py3k-cdecimal/Lib/test/test_ftplib.py python/branches/py3k-cdecimal/Lib/test/test_gdb.py python/branches/py3k-cdecimal/Lib/test/test_htmlparser.py python/branches/py3k-cdecimal/Lib/test/test_httplib.py python/branches/py3k-cdecimal/Lib/test/test_linecache.py python/branches/py3k-cdecimal/Lib/test/test_long.py python/branches/py3k-cdecimal/Lib/test/test_os.py python/branches/py3k-cdecimal/Lib/test/test_pipes.py python/branches/py3k-cdecimal/Lib/test/test_socketserver.py python/branches/py3k-cdecimal/Lib/test/test_ssl.py python/branches/py3k-cdecimal/Lib/test/test_subprocess.py python/branches/py3k-cdecimal/Lib/test/test_sys.py python/branches/py3k-cdecimal/Lib/test/test_sysconfig.py python/branches/py3k-cdecimal/Lib/test/test_tarfile.py python/branches/py3k-cdecimal/Lib/test/test_tcl.py python/branches/py3k-cdecimal/Lib/test/test_urllib2.py python/branches/py3k-cdecimal/Lib/test/test_warnings.py python/branches/py3k-cdecimal/Lib/test/test_winreg.py python/branches/py3k-cdecimal/Lib/test/test_winsound.py python/branches/py3k-cdecimal/Lib/test/testtar.tar python/branches/py3k-cdecimal/Lib/tkinter/_fix.py python/branches/py3k-cdecimal/Lib/unittest/case.py python/branches/py3k-cdecimal/Lib/unittest/loader.py python/branches/py3k-cdecimal/Lib/unittest/suite.py python/branches/py3k-cdecimal/Lib/unittest/test/test_case.py python/branches/py3k-cdecimal/Lib/unittest/test/test_setups.py python/branches/py3k-cdecimal/Lib/unittest/util.py python/branches/py3k-cdecimal/Lib/urllib/request.py python/branches/py3k-cdecimal/Lib/webbrowser.py python/branches/py3k-cdecimal/Mac/Tools/pythonw.c python/branches/py3k-cdecimal/Misc/ACKS python/branches/py3k-cdecimal/Misc/NEWS python/branches/py3k-cdecimal/Misc/developers.txt python/branches/py3k-cdecimal/Modules/_multiprocessing/multiprocessing.h python/branches/py3k-cdecimal/Modules/_sqlite/connection.c python/branches/py3k-cdecimal/Modules/_ssl.c python/branches/py3k-cdecimal/Modules/config.c.in python/branches/py3k-cdecimal/Modules/datetimemodule.c python/branches/py3k-cdecimal/Modules/main.c python/branches/py3k-cdecimal/Modules/timemodule.c python/branches/py3k-cdecimal/Objects/abstract.c python/branches/py3k-cdecimal/Objects/complexobject.c python/branches/py3k-cdecimal/Objects/longobject.c python/branches/py3k-cdecimal/Objects/object.c python/branches/py3k-cdecimal/Objects/typeobject.c python/branches/py3k-cdecimal/PC/winreg.c python/branches/py3k-cdecimal/Python/_warnings.c python/branches/py3k-cdecimal/Python/ceval.c python/branches/py3k-cdecimal/Python/getargs.c python/branches/py3k-cdecimal/Python/pythonrun.c python/branches/py3k-cdecimal/Python/sysmodule.c python/branches/py3k-cdecimal/Tools/gdb/libpython.py python/branches/py3k-cdecimal/Tools/i18n/msgfmt.py python/branches/py3k-cdecimal/Tools/scripts/serve.py python/branches/py3k-cdecimal/configure python/branches/py3k-cdecimal/configure.in python/branches/py3k-cdecimal/setup.py Modified: python/branches/py3k-cdecimal/Doc/c-api/init.rst ============================================================================== --- python/branches/py3k-cdecimal/Doc/c-api/init.rst (original) +++ python/branches/py3k-cdecimal/Doc/c-api/init.rst Mon Jun 7 12:46:02 2010 @@ -22,6 +22,7 @@ module: sys triple: module; search; path single: PySys_SetArgv() + single: PySys_SetArgvEx() single: Py_Finalize() Initialize the Python interpreter. In an application embedding Python, this @@ -31,7 +32,7 @@ the table of loaded modules (``sys.modules``), and creates the fundamental modules :mod:`builtins`, :mod:`__main__` and :mod:`sys`. It also initializes the module search path (``sys.path``). It does not set ``sys.argv``; use - :cfunc:`PySys_SetArgv` for that. This is a no-op when called for a second time + :cfunc:`PySys_SetArgvEx` for that. This is a no-op when called for a second time (without calling :cfunc:`Py_Finalize` first). There is no return value; it is a fatal error if the initialization fails. @@ -337,7 +338,7 @@ ``sys.version``. -.. cfunction:: void PySys_SetArgv(int argc, wchar_t **argv) +.. cfunction:: void PySys_SetArgvEx(int argc, wchar_t **argv, int updatepath) .. index:: single: main() @@ -352,14 +353,41 @@ string. If this function fails to initialize :data:`sys.argv`, a fatal condition is signalled using :cfunc:`Py_FatalError`. - This function also prepends the executed script's path to :data:`sys.path`. - If no script is executed (in the case of calling ``python -c`` or just the - interactive interpreter), the empty string is used instead. + If *updatepath* is zero, this is all the function does. If *updatepath* + is non-zero, the function also modifies :data:`sys.path` according to the + following algorithm: + + - If the name of an existing script is passed in ``argv[0]``, the absolute + path of the directory where the script is located is prepended to + :data:`sys.path`. + - Otherwise (that is, if *argc* is 0 or ``argv[0]`` doesn't point + to an existing file name), an empty string is prepended to + :data:`sys.path`, which is the same as prepending the current working + directory (``"."``). + + .. note:: + It is recommended that applications embedding the Python interpreter + for purposes other than executing a single script pass 0 as *updatepath*, + and update :data:`sys.path` themselves if desired. + See `CVE-2008-5983 `_. + + On versions before 3.1.3, you can achieve the same effect by manually + popping the first :data:`sys.path` element after having called + :cfunc:`PySys_SetArgv`, for example using:: + + PyRun_SimpleString("import sys; sys.path.pop(0)\n"); + + .. versionadded:: 3.1.3 .. XXX impl. doesn't seem consistent in allowing 0/NULL for the params; check w/ Guido. +.. cfunction:: void PySys_SetArgv(int argc, wchar_t **argv) + + This function works like :cfunc:`PySys_SetArgv` with *updatepath* set to 1. + + .. cfunction:: void Py_SetPythonHome(wchar_t *home) Set the default "home" directory, that is, the location of the standard Modified: python/branches/py3k-cdecimal/Doc/c-api/sys.rst ============================================================================== --- python/branches/py3k-cdecimal/Doc/c-api/sys.rst (original) +++ python/branches/py3k-cdecimal/Doc/c-api/sys.rst Mon Jun 7 12:46:02 2010 @@ -81,6 +81,10 @@ Append *s* to :data:`sys.warnoptions`. +.. cfunction:: void PySys_AddWarnOptionUnicode(PyObject *unicode) + + Append *unicode* to :data:`sys.warnoptions`. + .. cfunction:: void PySys_SetPath(wchar_t *path) Set :data:`sys.path` to a list object of paths found in *path* which should Modified: python/branches/py3k-cdecimal/Doc/distutils/builtdist.rst ============================================================================== --- python/branches/py3k-cdecimal/Doc/distutils/builtdist.rst (original) +++ python/branches/py3k-cdecimal/Doc/distutils/builtdist.rst Mon Jun 7 12:46:02 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 bitmap which must be a Windows +run, but you can also supply your own 152x161 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 Modified: python/branches/py3k-cdecimal/Doc/extending/newtypes.rst ============================================================================== --- python/branches/py3k-cdecimal/Doc/extending/newtypes.rst (original) +++ python/branches/py3k-cdecimal/Doc/extending/newtypes.rst Mon Jun 7 12:46:02 2010 @@ -430,7 +430,7 @@ Noddy_members, /* tp_members */ Each member definition has a member name, type, offset, access flags and -documentation string. See the "Generic Attribute Management" section below for +documentation string. See the :ref:`Generic-Attribute-Management` section below for details. A disadvantage of this approach is that it doesn't provide a way to restrict the @@ -1078,6 +1078,8 @@ not been updated to use some of the new generic mechanism that is available. +.. _generic-attribute-management: + Generic Attribute Management ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Modified: python/branches/py3k-cdecimal/Doc/howto/index.rst ============================================================================== --- python/branches/py3k-cdecimal/Doc/howto/index.rst (original) +++ python/branches/py3k-cdecimal/Doc/howto/index.rst Mon Jun 7 12:46:02 2010 @@ -16,6 +16,7 @@ advocacy.rst cporting.rst curses.rst + descriptor.rst doanddont.rst functional.rst regex.rst Modified: python/branches/py3k-cdecimal/Doc/library/argparse.rst ============================================================================== --- python/branches/py3k-cdecimal/Doc/library/argparse.rst (original) +++ python/branches/py3k-cdecimal/Doc/library/argparse.rst Mon Jun 7 12:46:02 2010 @@ -452,7 +452,7 @@ By default, :class:`ArgumentParser` objects uses ``sys.argv[0]`` to determine how to display the name of the program in help messages. This default is almost -always desirable because it will make the help messages match how the pgoram was +always desirable because it will make the help messages match how the program was invoked on the command line. For example, consider a file named ``myprogram.py`` with the following code:: @@ -672,8 +672,8 @@ >>> import argparse >>> parser = argparse.ArgumentParser(prog='PROG') - >>> parser.add_argument('-v', '--version', action='version', version='%(prog)s 2.0') - >>> parser.parse_args(['-v']) + >>> parser.add_argument('--version', action='version', version='%(prog)s 2.0') + >>> parser.parse_args(['--version']) PROG 2.0 You can also specify an arbitrary action by passing an object that implements @@ -1725,3 +1725,6 @@ * Replace strings with implicit arguments such as ``%default`` or ``%prog`` with the standard python syntax to use dictionaries to format strings, that is, ``%(default)s`` and ``%(prog)s``. + +* Replace the OptionParser constructor ``version`` argument with a call to + ``parser.add_argument('--version', action='version', version='')`` Modified: python/branches/py3k-cdecimal/Doc/library/datetime.rst ============================================================================== --- python/branches/py3k-cdecimal/Doc/library/datetime.rst (original) +++ python/branches/py3k-cdecimal/Doc/library/datetime.rst Mon Jun 7 12:46:02 2010 @@ -220,12 +220,20 @@ | | In general, *t1* \* i == *t1* \* (i-1) + *t1* | | | is true. (1) | +--------------------------------+-----------------------------------------------+ +| ``t1 = t2 * f or t1 = f * t2`` | Delta multiplied by a float. The result is | +| | rounded to the nearest multiple of | +| | timedelta.resolution using round-half-to-even.| ++--------------------------------+-----------------------------------------------+ | ``f = t2 / t3`` | Division (3) of *t2* by *t3*. Returns a | | | :class:`float` object. | +--------------------------------+-----------------------------------------------+ +| ``t1 = t2 / f or t1 = t2 / i`` | Delta divided by a float or an int. The result| +| | is rounded to the nearest multiple of | +| | timedelta.resolution using round-half-to-even.| ++--------------------------------+-----------------------------------------------+ | ``t1 = t2 // i`` or | The floor is computed and the remainder (if | | ``t1 = t2 // t3`` | any) is thrown away. In the second case, an | -| | integer is returned (3) | +| | integer is returned. (3) | +--------------------------------+-----------------------------------------------+ | ``t1 = t2 % t3`` | The remainder is computed as a | | | :class:`timedelta` object. (3) | @@ -267,7 +275,9 @@ .. versionadded:: 3.2 Floor division and true division of a :class:`timedelta` object by another :class:`timedelta` object are now supported, as are - remainder operations and the :func:`divmod` function. + remainder operations and the :func:`divmod` function. True + division and multiplication of a :class:`timedelta` object by + a :class:`float` object are now supported. Comparisons of :class:`timedelta` objects are supported with the Modified: python/branches/py3k-cdecimal/Doc/library/decimal.rst ============================================================================== --- python/branches/py3k-cdecimal/Doc/library/decimal.rst (original) +++ python/branches/py3k-cdecimal/Doc/library/decimal.rst Mon Jun 7 12:46:02 2010 @@ -122,7 +122,7 @@ >>> from decimal import * >>> getcontext() Context(prec=28, rounding=ROUND_HALF_EVEN, Emin=-999999999, Emax=999999999, - capitals=1, flags=[], traps=[Overflow, DivisionByZero, + capitals=1, clamp=0, flags=[], traps=[Overflow, DivisionByZero, InvalidOperation]) >>> getcontext().prec = 7 # Set a new precision @@ -244,7 +244,7 @@ >>> ExtendedContext Context(prec=9, rounding=ROUND_HALF_EVEN, Emin=-999999999, Emax=999999999, - capitals=1, flags=[], traps=[]) + capitals=1, clamp=0, flags=[], traps=[]) >>> setcontext(ExtendedContext) >>> Decimal(1) / Decimal(7) Decimal('0.142857143') @@ -269,7 +269,7 @@ Decimal('3.14159292') >>> getcontext() Context(prec=9, rounding=ROUND_HALF_EVEN, Emin=-999999999, Emax=999999999, - capitals=1, flags=[Inexact, Rounded], traps=[]) + capitals=1, clamp=0, flags=[Inexact, Rounded], traps=[]) The *flags* entry shows that the rational approximation to :const:`Pi` was rounded (digits beyond the context precision were thrown away) and that the @@ -874,7 +874,7 @@ This context is used by the :class:`Context` constructor as a prototype for new contexts. Changing a field (such a precision) has the effect of changing the - default for new contexts creating by the :class:`Context` constructor. + default for new contexts created by the :class:`Context` constructor. This context is most useful in multi-threaded environments. Changing one of the fields before threads are started has the effect of setting system-wide @@ -891,7 +891,7 @@ :class:`Context` constructor. -.. class:: Context(prec=None, rounding=None, traps=None, flags=None, Emin=None, Emax=None, capitals=1) +.. class:: Context(prec=None, rounding=None, traps=None, flags=None, Emin=None, Emax=None, capitals=None, clamp=None) Creates a new context. If a field is not specified or is :const:`None`, the default values are copied from the :const:`DefaultContext`. If the *flags* @@ -922,6 +922,23 @@ :const:`1`, exponents are printed with a capital :const:`E`; otherwise, a lowercase :const:`e` is used: :const:`Decimal('6.02e+23')`. + The *clamp* field is either :const:`0` (the default) or :const:`1`. + If set to :const:`1`, the exponent ``e`` of a :class:`Decimal` + instance representable in this context is strictly limited to the + range ``Emin - prec + 1 <= e <= Emax - prec + 1``. If *clamp* is + :const:`0` then a weaker condition holds: the adjusted exponent of + the :class:`Decimal` instance is at most ``Emax``. When *clamp* is + :const:`1`, a large normal number will, where possible, have its + exponent reduced and a corresponding number of zeros added to its + coefficient, in order to fit the exponent constraints; this + preserves the value of the number but loses information about + significant trailing zeros. For example:: + + >>> Context(prec=6, Emax=999, clamp=1).create_decimal('1.23e999') + Decimal('1.23000E+999') + + A *clamp* value of :const:`1` allows compatibility with the + fixed-width decimal interchange formats specified in IEEE 754. The :class:`Context` class defines several general purpose methods as well as a large number of methods for doing arithmetic directly in a given context. Modified: python/branches/py3k-cdecimal/Doc/library/dis.rst ============================================================================== --- python/branches/py3k-cdecimal/Doc/library/dis.rst (original) +++ python/branches/py3k-cdecimal/Doc/library/dis.rst Mon Jun 7 12:46:02 2010 @@ -383,13 +383,6 @@ the stack so that it is available for further iterations of the loop. -.. opcode:: LOAD_LOCALS () - - Pushes a reference to the locals of the current scope on the stack. This is used - in the code for a class definition: After the class body is evaluated, the - locals are passed to the class definition. - - .. opcode:: RETURN_VALUE () Returns with TOS to the caller of the function. Modified: python/branches/py3k-cdecimal/Doc/library/fcntl.rst ============================================================================== --- python/branches/py3k-cdecimal/Doc/library/fcntl.rst (original) +++ python/branches/py3k-cdecimal/Doc/library/fcntl.rst Mon Jun 7 12:46:02 2010 @@ -8,8 +8,8 @@ .. index:: - pair: UNIX at Unix; file control - pair: UNIX at Unix; I/O control + pair: UNIX; file control + pair: UNIX; I/O control This module performs file control and I/O control on file descriptors. It is an interface to the :cfunc:`fcntl` and :cfunc:`ioctl` Unix routines. Modified: python/branches/py3k-cdecimal/Doc/library/ftplib.rst ============================================================================== --- python/branches/py3k-cdecimal/Doc/library/ftplib.rst (original) +++ python/branches/py3k-cdecimal/Doc/library/ftplib.rst Mon Jun 7 12:46:02 2010 @@ -65,7 +65,7 @@ Support for the :keyword:`with` statement was added. -.. class:: FTP_TLS(host='', user='', passwd='', acct='', [keyfile[, certfile[, timeout]]]) +.. class:: FTP_TLS(host='', user='', passwd='', acct='', [keyfile[, certfile[, context[, timeout]]]]) A :class:`FTP` subclass which adds TLS support to FTP as described in :rfc:`4217`. @@ -74,6 +74,9 @@ explicitly ask for it by calling the :meth:`prot_p` method. *keyfile* and *certfile* are optional -- they can contain a PEM formatted private key and certificate chain file name for the SSL connection. + *context* parameter is a :class:`ssl.SSLContext` object which allows + bundling SSL configuration options, certificates and private keys into a + single (potentially long-lived) structure. .. versionadded:: 3.2 @@ -122,7 +125,7 @@ The set of all exceptions (as a tuple) that methods of :class:`FTP` instances may raise as a result of problems with the FTP connection (as opposed to programming errors made by the caller). This set includes the - four exceptions listed below as well as :exc:`socket.error` and + four exceptions listed above as well as :exc:`socket.error` and :exc:`IOError`. .. seealso:: Modified: python/branches/py3k-cdecimal/Doc/library/functions.rst ============================================================================== --- python/branches/py3k-cdecimal/Doc/library/functions.rst (original) +++ python/branches/py3k-cdecimal/Doc/library/functions.rst Mon Jun 7 12:46:02 2010 @@ -1227,7 +1227,7 @@ True -.. function:: __import__(name, globals={}, locals={}, fromlist=[], level=-1) +.. function:: __import__(name, globals={}, locals={}, fromlist=[], level=0) .. index:: statement: import Modified: python/branches/py3k-cdecimal/Doc/library/getopt.rst ============================================================================== --- python/branches/py3k-cdecimal/Doc/library/getopt.rst (original) +++ python/branches/py3k-cdecimal/Doc/library/getopt.rst Mon Jun 7 12:46:02 2010 @@ -5,6 +5,12 @@ :synopsis: Portable parser for command line options; support both short and long option names. +.. note:: + The :mod:`getopt` module is a parser for command line options whose API is + designed to be familiar to users of the C :cfunc:`getopt` function. Users who + are unfamiliar with the C :cfunc:`getopt` function or who would like to write + less code and get better help and error messages should consider using the + :mod:`argparse` module instead. This module helps scripts to parse the command line arguments in ``sys.argv``. It supports the same conventions as the Unix :cfunc:`getopt` function (including @@ -136,9 +142,21 @@ if __name__ == "__main__": main() +Note that an equivalent command line interface could be produced with less code +and more informative help and error messages by using the :mod:`argparse` module:: + + import argparse + + if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument('-o', '--output') + parser.add_argument('-v', dest='verbose', action='store_true') + args = parser.parse_args() + # ... do something with args.output ... + # ... do something with args.verbose .. .. seealso:: - Module :mod:`optparse` - More object-oriented command line option parsing. + Module :mod:`argparse` + Alternative command line option and argument parsing library. Modified: python/branches/py3k-cdecimal/Doc/library/hashlib.rst ============================================================================== --- python/branches/py3k-cdecimal/Doc/library/hashlib.rst (original) +++ python/branches/py3k-cdecimal/Doc/library/hashlib.rst Mon Jun 7 12:46:02 2010 @@ -151,7 +151,7 @@ http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf The FIPS 180-2 publication on Secure Hash Algorithms. - http://www.cryptography.com/cnews/hash.html - Hash Collision FAQ with information on which algorithms have known issues and + http://en.wikipedia.org/wiki/Cryptographic_hash_function#Cryptographic_hash_algorithms + Wikipedia article with information on which algorithms have known issues and what that means regarding their use. Modified: python/branches/py3k-cdecimal/Doc/library/io.rst ============================================================================== --- python/branches/py3k-cdecimal/Doc/library/io.rst (original) +++ python/branches/py3k-cdecimal/Doc/library/io.rst Mon Jun 7 12:46:02 2010 @@ -240,7 +240,7 @@ Flush and close this stream. This method has no effect if the file is already closed. Once the file is closed, any operation on the file - (e.g. reading or writing) will raise an :exc:`ValueError`. + (e.g. reading or writing) will raise a :exc:`ValueError`. As a convenience, it is allowed to call this method more than once; only the first call, however, will have an effect. @@ -314,10 +314,12 @@ .. method:: truncate(size=None) - Truncate the file to at most *size* bytes. *size* defaults to the current - file position, as returned by :meth:`tell`. Note that the current file - position isn't changed; if you want to change it to the new end of - file, you have to :meth:`seek()` explicitly. + Resize the stream to the given *size* in bytes (or the current position + if *size* is not specified). The current stream position isn't changed. + This resizing can extend or reduce the current file size. In case of + extension, the contents of the new file area depend on the platform + (on most systems, additional bytes are zero-filled, on Windows they're + undetermined). The new file size is returned. .. method:: writable() Modified: python/branches/py3k-cdecimal/Doc/library/json.rst ============================================================================== --- python/branches/py3k-cdecimal/Doc/library/json.rst (original) +++ python/branches/py3k-cdecimal/Doc/library/json.rst Mon Jun 7 12:46:02 2010 @@ -209,7 +209,7 @@ specified. Encodings that are not ASCII based (such as UCS-2) are not allowed and should be decoded to :class:`str` first. - The other arguments have the same meaning as in :func:`dump`. + The other arguments have the same meaning as in :func:`load`. Encoders and decoders Modified: python/branches/py3k-cdecimal/Doc/library/multiprocessing.rst ============================================================================== --- python/branches/py3k-cdecimal/Doc/library/multiprocessing.rst (original) +++ python/branches/py3k-cdecimal/Doc/library/multiprocessing.rst Mon Jun 7 12:46:02 2010 @@ -837,7 +837,7 @@ A bounded semaphore object: a clone of :class:`threading.BoundedSemaphore`. - (On Mac OS X this is indistinguishable from :class:`Semaphore` because + (On Mac OS X, this is indistinguishable from :class:`Semaphore` because ``sem_getvalue()`` is not implemented on that platform). .. class:: Condition([lock]) @@ -879,9 +879,8 @@ specifies a timeout in seconds. If *block* is ``False`` then *timeout* is ignored. -.. note:: - On OS/X ``sem_timedwait`` is unsupported, so timeout arguments for the - aforementioned :meth:`acquire` methods will be ignored on OS/X. + On Mac OS X, ``sem_timedwait`` is unsupported, so calling ``acquire()`` with + a timeout will emulate that function's behavior using a sleeping loop. .. note:: Modified: python/branches/py3k-cdecimal/Doc/library/optparse.rst ============================================================================== --- python/branches/py3k-cdecimal/Doc/library/optparse.rst (original) +++ python/branches/py3k-cdecimal/Doc/library/optparse.rst Mon Jun 7 12:46:02 2010 @@ -3,6 +3,12 @@ .. module:: optparse :synopsis: Command-line option parsing library. + :deprecated: + +.. deprecated:: 2.7 + The :mod:`optparse` module is deprecated and will not be developed further; + development will continue with the :mod:`argparse` module. + .. moduleauthor:: Greg Ward .. sectionauthor:: Greg Ward Modified: python/branches/py3k-cdecimal/Doc/library/os.rst ============================================================================== --- python/branches/py3k-cdecimal/Doc/library/os.rst (original) +++ python/branches/py3k-cdecimal/Doc/library/os.rst Mon Jun 7 12:46:02 2010 @@ -697,6 +697,14 @@ Availability: Unix, Windows. +.. data:: SEEK_SET + SEEK_CUR + SEEK_END + + Parameters to the :func:`lseek` function. Their values are 0, 1, and 2, + respectively. Availability: Windows, Unix. + + .. function:: open(file, flags[, mode]) Open the file *file* and set various flags according to *flags* and possibly @@ -706,7 +714,8 @@ For a description of the flag and mode values, see the C run-time documentation; flag constants (like :const:`O_RDONLY` and :const:`O_WRONLY`) are defined in - this module too (see below). + this module too (see :ref:`open-constants`). In particular, on Windows adding + :const:`O_BINARY` is needed to open files in binary mode. Availability: Unix, Windows. @@ -794,6 +803,12 @@ :func:`fdopen`, or :data:`sys.stdout` or :data:`sys.stderr`, use its :meth:`~file.write` method. + +.. _open-constants: + +``open()`` flag constants +~~~~~~~~~~~~~~~~~~~~~~~~~ + The following constants are options for the *flags* parameter to the :func:`~os.open` function. They can be combined using the bitwise OR operator ``|``. Some of them are not available on all platforms. For descriptions of @@ -845,14 +860,6 @@ the C library. -.. data:: SEEK_SET - SEEK_CUR - SEEK_END - - Parameters to the :func:`lseek` function. Their values are 0, 1, and 2, - respectively. Availability: Windows, Unix. - - .. _os-file-dir: Files and Directories @@ -2187,8 +2194,8 @@ .. data:: devnull - The file path of the null device. For example: ``'/dev/null'`` for POSIX. - Also available via :mod:`os.path`. + The file path of the null device. For example: ``'/dev/null'`` for + POSIX, ``'nul'`` for Windows. Also available via :mod:`os.path`. .. _os-miscfunc: Modified: python/branches/py3k-cdecimal/Doc/library/socket.rst ============================================================================== --- python/branches/py3k-cdecimal/Doc/library/socket.rst (original) +++ python/branches/py3k-cdecimal/Doc/library/socket.rst Mon Jun 7 12:46:02 2010 @@ -89,8 +89,9 @@ and out-of-memory conditions can be raised; errors related to socket or address semantics raise the error :exc:`socket.error`. -Non-blocking mode is supported through :meth:`setblocking`. A generalization of -this based on timeouts is supported through :meth:`settimeout`. +Non-blocking mode is supported through :meth:`~socket.setblocking`. A +generalization of this based on timeouts is supported through +:meth:`~socket.settimeout`. The module :mod:`socket` exports the following constants and functions: @@ -210,27 +211,44 @@ *source_address* was added. -.. function:: getaddrinfo(host, port[, family[, socktype[, proto[, flags]]]]) +.. function:: getaddrinfo(host, port, family=0, socktype=0, proto=0, flags=0) - Resolves the *host*/*port* argument, into a sequence of 5-tuples that contain - all the necessary arguments for creating the corresponding socket. *host* is a domain - name, a string representation of an IPv4/v6 address or ``None``. *port* is a string - service name such as ``'http'``, a numeric port number or ``None``. - The rest of the arguments are optional and must be numeric if specified. - By passing ``None`` as the value of *host* and *port*, , you can pass ``NULL`` to the C API. + Translate the *host*/*port* argument into a sequence of 5-tuples that contain + all the necessary arguments for creating a socket connected to that service. + *host* is a domain name, a string representation of an IPv4/v6 address + or ``None``. *port* is a string service name such as ``'http'``, a numeric + port number or ``None``. By passing ``None`` as the value of *host* + and *port*, you can pass ``NULL`` to the underlying C API. + + The *family*, *socktype* and *proto* arguments can be optionally specified + in order to narrow the list of addresses returned. Passing zero as a + value for each of these arguments selects the full range of results. + The *flags* argument can be one or several of the ``AI_*`` constants, + and will influence how results are computed and returned. + For example, :const:`AI_NUMERICHOST` will disable domain name resolution + and will raise an error if *host* is a domain name. - The :func:`getaddrinfo` function returns a list of 5-tuples with the following - structure: + The function returns a list of 5-tuples with the following structure: ``(family, socktype, proto, canonname, sockaddr)`` - *family*, *socktype*, *proto* are all integers and are meant to be passed to the - :func:`socket` function. *canonname* is a string representing the canonical name - of the *host*. It can be a numeric IPv4/v6 address when :const:`AI_CANONNAME` is - specified for a numeric *host*. *sockaddr* is a tuple describing a socket - address, as described above. See the source for :mod:`socket` and other - library modules for a typical usage of the function. - + In these tuples, *family*, *socktype*, *proto* are all integers and are + meant to be passed to the :func:`socket` function. *canonname* will be + a string representing the canonical name of the *host* if + :const:`AI_CANONNAME` is part of the *flags* argument; else *canonname* + will be empty. *sockaddr* is a tuple describing a socket address, whose + format depends on the returned *family* (a ``(address, port)`` 2-tuple for + :const:`AF_INET`, a ``(address, port, flow info, scope id)`` 4-tuple for + :const:`AF_INET6`), and is meant to be passed to the :meth:`socket.connect` + method. + + The following example fetches address information for a hypothetical TCP + connection to ``www.python.org`` on port 80 (results may differ on your + system if IPv6 isn't enabled):: + + >>> socket.getaddrinfo("www.python.org", 80, 0, 0, socket.SOL_TCP) + [(2, 1, 6, '', ('82.94.164.162', 80)), + (10, 1, 6, '', ('2001:888:2000:d::a2', 80, 0, 0))] .. function:: getfqdn([name]) @@ -559,7 +577,9 @@ :platform: Windows The :meth:`ioctl` method is a limited interface to the WSAIoctl system - interface. Please refer to the MSDN documentation for more information. + interface. Please refer to the `Win32 documentation + `_ for more + information. On other platforms, the generic :func:`fcntl.fcntl` and :func:`fcntl.ioctl` functions may be used; they accept a socket object as their first argument. @@ -662,7 +682,7 @@ blocking mode. In non-blocking mode, if a :meth:`recv` call doesn't find any data, or if a :meth:`send` call can't immediately dispose of the data, a :exc:`error` exception is raised; in blocking mode, the calls block until they - can proceed. ``s.setblocking(0)`` is equivalent to ``s.settimeout(0)``; + can proceed. ``s.setblocking(0)`` is equivalent to ``s.settimeout(0.0)``; ``s.setblocking(1)`` is equivalent to ``s.settimeout(None)``. @@ -691,21 +711,21 @@ non-blocking mode, operations fail (with an error that is unfortunately system-dependent) if they cannot be completed immediately. In timeout mode, operations fail if they cannot be completed within the timeout specified for the -socket or if the system returns an error. The :meth:`setblocking` method is simply -a shorthand for certain :meth:`settimeout` calls. +socket or if the system returns an error. The :meth:`~socket.setblocking` +method is simply a shorthand for certain :meth:`~socket.settimeout` calls. Timeout mode internally sets the socket in non-blocking mode. The blocking and timeout modes are shared between file descriptors and socket objects that refer to the same network endpoint. A consequence of this is that file objects -returned by the :meth:`makefile` method must only be used when the socket is in -blocking mode; in timeout or non-blocking mode file operations that cannot be -completed immediately will fail. - -Note that the :meth:`connect` operation is subject to the timeout setting, and -in general it is recommended to call :meth:`settimeout` before calling -:meth:`connect` or pass a timeout parameter to :meth:`create_connection`. -The system network stack may return a connection timeout error -of its own regardless of any Python socket timeout setting. +returned by the :meth:`~socket.makefile` method must only be used when the +socket is in blocking mode; in timeout or non-blocking mode file operations +that cannot be completed immediately will fail. + +Note that the :meth:`~socket.connect` operation is subject to the timeout +setting, and in general it is recommended to call :meth:`~socket.settimeout` +before calling :meth:`~socket.connect` or pass a timeout parameter to +:meth:`create_connection`. The system network stack may return a connection +timeout error of its own regardless of any Python socket timeout setting. .. method:: socket.setsockopt(level, optname, value) @@ -727,8 +747,8 @@ are disallowed. If *how* is :const:`SHUT_RDWR`, further sends and receives are disallowed. -Note that there are no methods :meth:`read` or :meth:`write`; use :meth:`recv` -and :meth:`send` without *flags* argument instead. +Note that there are no methods :meth:`read` or :meth:`write`; use +:meth:`~socket.recv` and :meth:`~socket.send` without *flags* argument instead. Socket objects also have these (read-only) attributes that correspond to the values given to the :class:`socket` constructor. @@ -757,11 +777,12 @@ Here are four minimal example programs using the TCP/IP protocol: a server that echoes all data that it receives back (servicing only one client), and a client using it. Note that a server must perform the sequence :func:`socket`, -:meth:`bind`, :meth:`listen`, :meth:`accept` (possibly repeating the -:meth:`accept` to service more than one client), while a client only needs the -sequence :func:`socket`, :meth:`connect`. Also note that the server does not -:meth:`send`/:meth:`recv` on the socket it is listening on but on the new -socket returned by :meth:`accept`. +:meth:`~socket.bind`, :meth:`~socket.listen`, :meth:`~socket.accept` (possibly +repeating the :meth:`~socket.accept` to service more than one client), while a +client only needs the sequence :func:`socket`, :meth:`~socket.connect`. Also +note that the server does not :meth:`~socket.send`/:meth:`~socket.recv` on the +socket it is listening on but on the new socket returned by +:meth:`~socket.accept`. The first two examples support IPv4 only. :: Modified: python/branches/py3k-cdecimal/Doc/library/sqlite3.rst ============================================================================== --- python/branches/py3k-cdecimal/Doc/library/sqlite3.rst (original) +++ python/branches/py3k-cdecimal/Doc/library/sqlite3.rst Mon Jun 7 12:46:02 2010 @@ -227,6 +227,13 @@ one of "DEFERRED", "IMMEDIATE" or "EXCLUSIVE". See section :ref:`sqlite3-controlling-transactions` for a more detailed explanation. +.. attribute:: Connection.in_transaction + + .. versionadded:: 3.2 + + :const:`True` if a transaction is active (there are uncommitted changes), + :const:`False` otherwise. Read-only attribute. + .. method:: Connection.cursor([cursorClass]) @@ -806,7 +813,8 @@ before executing that command. There are two reasons for doing that. The first is that some of these commands don't work within transactions. The other reason is that sqlite3 needs to keep track of the transaction state (if a transaction -is active or not). +is active or not). The current transaction state is exposed through the +:attr:`Connection.in_transaction` attribute of the connection object. You can control which kind of ``BEGIN`` statements sqlite3 implicitly executes (or none at all) via the *isolation_level* parameter to the :func:`connect` Modified: python/branches/py3k-cdecimal/Doc/library/ssl.rst ============================================================================== --- python/branches/py3k-cdecimal/Doc/library/ssl.rst (original) +++ python/branches/py3k-cdecimal/Doc/library/ssl.rst Mon Jun 7 12:46:02 2010 @@ -257,6 +257,37 @@ modern version, and probably the best choice for maximum protection, if both sides can speak it. +.. data:: OP_ALL + + Enables workarounds for various bugs present in other SSL implementations. + This option is set by default. + + .. versionadded:: 3.2 + +.. data:: OP_NO_SSLv2 + + Prevents an SSLv2 connection. This option is only applicable in + conjunction with :const:`PROTOCOL_SSLv23`. It prevents the peers from + choosing SSLv2 as the protocol version. + + .. versionadded:: 3.2 + +.. data:: OP_NO_SSLv3 + + Prevents an SSLv3 connection. This option is only applicable in + conjunction with :const:`PROTOCOL_SSLv23`. It prevents the peers from + choosing SSLv3 as the protocol version. + + .. versionadded:: 3.2 + +.. data:: OP_NO_TLSv1 + + Prevents a TLSv1 connection. This option is only applicable in + conjunction with :const:`PROTOCOL_SSLv23`. It prevents the peers from + choosing TLSv1 as the protocol version. + + .. versionadded:: 3.2 + .. data:: OPENSSL_VERSION The version string of the OpenSSL library loaded by the interpreter:: @@ -376,9 +407,21 @@ other side of the connection, rather than the original socket. +.. attribute:: SSLSocket.context + + The :class:`SSLContext` object this SSL socket is tied to. If the SSL + socket was created using the top-level :func:`wrap_socket` function + (rather than :meth:`SSLContext.wrap_socket`), this is a custom context + object created for this SSL socket. + + .. versionadded:: 3.2 + + SSL Contexts ------------ +.. versionadded:: 3.2 + .. class:: SSLContext(protocol) An object holding various data longer-lived than single SSL connections, @@ -440,6 +483,17 @@ and *suppress_ragged_eofs* have the same meaning as in the top-level :func:`wrap_socket` function. +.. attribute:: SSLContext.options + + An integer representing the set of SSL options enabled on this context. + The default value is :data:`OP_ALL`, but you can specify other options + such as :data:`OP_NO_SSLv2` by ORing them together. + + .. note:: + With versions of OpenSSL older than 0.9.8m, it is only possible + to set options, not to clear them. Attempting to clear an option + (by resetting the corresponding bits) will raise a ``ValueError``. + .. attribute:: SSLContext.protocol The protocol version chosen when constructing the context. This attribute @@ -794,6 +848,20 @@ equivalent unless anonymous ciphers are enabled (they are disabled by default). +Protocol versions +^^^^^^^^^^^^^^^^^ + +SSL version 2 is considered insecure and is therefore dangerous to use. If +you want maximum compatibility between clients and servers, it is recommended +to use :const:`PROTOCOL_SSLv23` as the protocol version and then disable +SSLv2 explicitly using the :data:`SSLContext.options` attribute:: + + context = ssl.SSLContext(ssl.PROTOCOL_SSLv23) + context.options |= ssl.OP_NO_SSLv2 + +The SSL context created above will allow SSLv3 and TLSv1 connections, but +not SSLv2. + .. seealso:: Modified: python/branches/py3k-cdecimal/Doc/library/stdtypes.rst ============================================================================== --- python/branches/py3k-cdecimal/Doc/library/stdtypes.rst (original) +++ python/branches/py3k-cdecimal/Doc/library/stdtypes.rst Mon Jun 7 12:46:02 2010 @@ -595,6 +595,109 @@ '0x1.d380000000000p+11' +.. _numeric-hash: + +Hashing of numeric types +------------------------ + +For numbers ``x`` and ``y``, possibly of different types, it's a requirement +that ``hash(x) == hash(y)`` whenever ``x == y`` (see the :meth:`__hash__` +method documentation for more details). For ease of implementation and +efficiency across a variety of numeric types (including :class:`int`, +:class:`float`, :class:`decimal.Decimal` and :class:`fractions.Fraction`) +Python's hash for numeric types is based on a single mathematical function +that's defined for any rational number, and hence applies to all instances of +:class:`int` and :class:`fraction.Fraction`, and all finite instances of +:class:`float` and :class:`decimal.Decimal`. Essentially, this function is +given by reduction modulo ``P`` for a fixed prime ``P``. The value of ``P`` is +made available to Python as the :attr:`modulus` attribute of +:data:`sys.hash_info`. + +.. impl-detail:: + + Currently, the prime used is ``P = 2**31 - 1`` on machines with 32-bit C + longs and ``P = 2**61 - 1`` on machines with 64-bit C longs. + +Here are the rules in detail: + + - If ``x = m / n`` is a nonnegative rational number and ``n`` is not divisible + by ``P``, define ``hash(x)`` as ``m * invmod(n, P) % P``, where ``invmod(n, + P)`` gives the inverse of ``n`` modulo ``P``. + + - If ``x = m / n`` is a nonnegative rational number and ``n`` is + divisible by ``P`` (but ``m`` is not) then ``n`` has no inverse + modulo ``P`` and the rule above doesn't apply; in this case define + ``hash(x)`` to be the constant value ``sys.hash_info.inf``. + + - If ``x = m / n`` is a negative rational number define ``hash(x)`` + as ``-hash(-x)``. If the resulting hash is ``-1``, replace it with + ``-2``. + + - The particular values ``sys.hash_info.inf``, ``-sys.hash_info.inf`` + and ``sys.hash_info.nan`` are used as hash values for positive + infinity, negative infinity, or nans (respectively). (All hashable + nans have the same hash value.) + + - For a :class:`complex` number ``z``, the hash values of the real + and imaginary parts are combined by computing ``hash(z.real) + + sys.hash_info.imag * hash(z.imag)``, reduced modulo + ``2**sys.hash_info.width`` so that it lies in + ``range(-2**(sys.hash_info.width - 1), 2**(sys.hash_info.width - + 1))``. Again, if the result is ``-1``, it's replaced with ``-2``. + + +To clarify the above rules, here's some example Python code, +equivalent to the builtin hash, for computing the hash of a rational +number, :class:`float`, or :class:`complex`:: + + + import sys, math + + def hash_fraction(m, n): + """Compute the hash of a rational number m / n. + + Assumes m and n are integers, with n positive. + Equivalent to hash(fractions.Fraction(m, n)). + + """ + P = sys.hash_info.modulus + # Remove common factors of P. (Unnecessary if m and n already coprime.) + while m % P == n % P == 0: + m, n = m // P, n // P + + if n % P == 0: + hash_ = sys.hash_info.inf + else: + # Fermat's Little Theorem: pow(n, P-1, P) is 1, so + # pow(n, P-2, P) gives the inverse of n modulo P. + hash_ = (abs(m) % P) * pow(n, P - 2, P) % P + if m < 0: + hash_ = -hash_ + if hash_ == -1: + hash_ = -2 + return hash_ + + def hash_float(x): + """Compute the hash of a float x.""" + + if math.isnan(x): + return sys.hash_info.nan + elif math.isinf(x): + return sys.hash_info.inf if x > 0 else -sys.hash_info.inf + else: + return hash_fraction(*x.as_integer_ratio()) + + def hash_complex(z): + """Compute the hash of a complex number z.""" + + hash_ = hash_float(z.real) + sys.hash_info.imag * hash_float(z.imag) + # do a signed reduction modulo 2**sys.hash_info.width + M = 2**(sys.hash_info.width - 1) + hash_ = (hash_ & (M - 1)) - (hash & M) + if hash_ == -1: + hash_ == -2 + return hash_ + .. _typeiter: Iterator Types Modified: python/branches/py3k-cdecimal/Doc/library/subprocess.rst ============================================================================== --- python/branches/py3k-cdecimal/Doc/library/subprocess.rst (original) +++ python/branches/py3k-cdecimal/Doc/library/subprocess.rst Mon Jun 7 12:46:02 2010 @@ -89,6 +89,12 @@ size. A negative *bufsize* means to use the system default, which usually means fully buffered. The default value for *bufsize* is :const:`0` (unbuffered). + .. note:: + + If you experience performance issues, it is recommended that you try to + enable buffering by setting *bufsize* to either -1 or a large enough + positive value (such as 4096). + The *executable* argument specifies the program to execute. It is very seldom needed: Usually, the program to execute is defined by the *args* argument. If ``shell=True``, the *executable* argument specifies which shell to use. On Unix, Modified: python/branches/py3k-cdecimal/Doc/library/symtable.rst ============================================================================== --- python/branches/py3k-cdecimal/Doc/library/symtable.rst (original) +++ python/branches/py3k-cdecimal/Doc/library/symtable.rst Mon Jun 7 12:46:02 2010 @@ -67,7 +67,7 @@ Return ``True`` if the block uses ``exec``. - .. method:: has_import_start() + .. method:: has_import_star() Return ``True`` if the block uses a starred from-import. Modified: python/branches/py3k-cdecimal/Doc/library/sys.rst ============================================================================== --- python/branches/py3k-cdecimal/Doc/library/sys.rst (original) +++ python/branches/py3k-cdecimal/Doc/library/sys.rst Mon Jun 7 12:46:02 2010 @@ -446,6 +446,30 @@ Changed to a named tuple and added *service_pack_minor*, *service_pack_major*, *suite_mask*, and *product_type*. + +.. data:: hash_info + + A structseq giving parameters of the numeric hash implementation. For + more details about hashing of numeric types, see :ref:`numeric-hash`. + + +---------------------+--------------------------------------------------+ + | attribute | explanation | + +=====================+==================================================+ + | :const:`width` | width in bits used for hash values | + +---------------------+--------------------------------------------------+ + | :const:`modulus` | prime modulus P used for numeric hash scheme | + +---------------------+--------------------------------------------------+ + | :const:`inf` | hash value returned for a positive infinity | + +---------------------+--------------------------------------------------+ + | :const:`nan` | hash value returned for a nan | + +---------------------+--------------------------------------------------+ + | :const:`imag` | multiplier used for the imaginary part of a | + | | complex number | + +---------------------+--------------------------------------------------+ + + .. versionadded:: 3.2 + + .. data:: hexversion The version number encoded as a single integer. This is guaranteed to increase Modified: python/branches/py3k-cdecimal/Doc/library/sysconfig.rst ============================================================================== --- python/branches/py3k-cdecimal/Doc/library/sysconfig.rst (original) +++ python/branches/py3k-cdecimal/Doc/library/sysconfig.rst Mon Jun 7 12:46:02 2010 @@ -216,3 +216,35 @@ .. function:: get_config_h_filename() Return the path of :file:`pyconfig.h`. + +Using :mod:`sysconfig` as a script +---------------------------------- + +You can use :mod:`sysconfig` as a script with Python's *-m* option:: + + $ python -m sysconfig + Platform: "macosx-10.4-i386" + Python version: "3.2" + Current installation scheme: "posix_prefix" + + Paths: + data = "/usr/local" + include = "/Users/tarek/Dev/svn.python.org/py3k/Include" + platinclude = "." + platlib = "/usr/local/lib/python3.2/site-packages" + platstdlib = "/usr/local/lib/python3.2" + purelib = "/usr/local/lib/python3.2/site-packages" + scripts = "/usr/local/bin" + stdlib = "/usr/local/lib/python3.2" + + Variables: + AC_APPLE_UNIVERSAL_BUILD = "0" + AIX_GENUINE_CPLUSPLUS = "0" + AR = "ar" + ARFLAGS = "rc" + ASDLGEN = "./Parser/asdl_c.py" + ... + +This call will print in the standard output the information returned by +:func:`get_platform`, :func:`get_python_version`, :func:`get_path` and +:func:`get_config_vars`. Modified: python/branches/py3k-cdecimal/Doc/library/syslog.rst ============================================================================== --- python/branches/py3k-cdecimal/Doc/library/syslog.rst (original) +++ python/branches/py3k-cdecimal/Doc/library/syslog.rst Mon Jun 7 12:46:02 2010 @@ -10,66 +10,63 @@ Refer to the Unix manual pages for a detailed description of the ``syslog`` facility. -This module wraps the system ``syslog`` module. A pure Python -library that can speak to a syslog server is available in -the :mod:`logging.handlers` module as :class:`SysLogHandler`. +This module wraps the system ``syslog`` family of routines. A pure Python +library that can speak to a syslog server is available in the +:mod:`logging.handlers` module as :class:`SysLogHandler`. The module defines the following functions: .. function:: syslog([priority,] message) - Send the string *message* to the system logger. A trailing newline is - added if necessary. Each message is tagged with a priority composed - of a *facility* and a *level*. The optional *priority* argument, which - defaults to :const:`LOG_INFO`, determines the message priority. If the - facility is not encoded in *priority* using logical-or (``LOG_INFO | - LOG_USER``), the value given in the :func:`openlog` call is used. + Send the string *message* to the system logger. A trailing newline is added + if necessary. Each message is tagged with a priority composed of a + *facility* and a *level*. The optional *priority* argument, which defaults + to :const:`LOG_INFO`, determines the message priority. If the facility is + not encoded in *priority* using logical-or (``LOG_INFO | LOG_USER``), the + value given in the :func:`openlog` call is used. - If :func:`openlog` has not been called prior to the call to - :func:'syslog', ``openlog()`` will be called with no arguments. + If :func:`openlog` has not been called prior to the call to :func:`syslog`, + ``openlog()`` will be called with no arguments. .. function:: openlog([ident[, logopt[, facility]]]) - Logging options of subsequent :func:`syslog` calls can be set by - calling :func:`openlog`. :func:`syslog` will call :func:`openlog` - with no arguments if the log is not currently open. - - The optional *ident* keyword argument is a string which is prepended - to every message, and defaults to ''sys.argv[0]'' with leading - path components stripped. The optional *logopt* keyword argument - (default=0) is a bit field - see below for possible values to combine. - The optional *facility* keyword argument (default=:const:`LOG_USER`) - sets the default facility for messages which do not have a facility - explicitly encoded. - - .. versionchanged::3.2 - In previous versions, keyword arguments were not allowed, and *ident* - was required. The default for *ident* was dependent on the system - libraries, and often was ''python'' instead of the name of the - python program file. + Logging options of subsequent :func:`syslog` calls can be set by calling + :func:`openlog`. :func:`syslog` will call :func:`openlog` with no arguments + if the log is not currently open. + + The optional *ident* keyword argument is a string which is prepended to every + message, and defaults to ``sys.argv[0]`` with leading path components + stripped. The optional *logopt* keyword argument (default is 0) is a bit + field -- see below for possible values to combine. The optional *facility* + keyword argument (default is :const:`LOG_USER`) sets the default facility for + messages which do not have a facility explicitly encoded. + + .. versionchanged:: 3.2 + In previous versions, keyword arguments were not allowed, and *ident* was + required. The default for *ident* was dependent on the system libraries, + and often was ``python`` instead of the name of the python program file. .. function:: closelog() - Reset the syslog module values and call the system library - ''closelog()''. + Reset the syslog module values and call the system library ``closelog()``. - This causes the module to behave as it does when initially imported. - For example, :func:'openlog' will be called on the first :func:'syslog' - call (if :func:'openlog' hasn't already been called), and *ident* - and other :func:'openlog' parameters are reset to defaults. + This causes the module to behave as it does when initially imported. For + example, :func:`openlog` will be called on the first :func:`syslog` call (if + :func:`openlog` hasn't already been called), and *ident* and other + :func:`openlog` parameters are reset to defaults. .. function:: setlogmask(maskpri) - Set the priority mask to *maskpri* and return the previous mask value. - Calls to :func:`syslog` with a priority level not set in *maskpri* - are ignored. The default is to log all priorities. The function - ``LOG_MASK(pri)`` calculates the mask for the individual priority - *pri*. The function ``LOG_UPTO(pri)`` calculates the mask for all - priorities up to and including *pri*. + Set the priority mask to *maskpri* and return the previous mask value. Calls + to :func:`syslog` with a priority level not set in *maskpri* are ignored. + The default is to log all priorities. The function ``LOG_MASK(pri)`` + calculates the mask for the individual priority *pri*. The function + ``LOG_UPTO(pri)`` calculates the mask for all priorities up to and including + *pri*. The module defines the following constants: @@ -100,11 +97,11 @@ syslog.syslog('Processing started') if error: - syslog.syslog(syslog.LOG_ERR, 'Processing started') + syslog.syslog(syslog.LOG_ERR, 'Processing started') -An example of setting some log options, these would include the process ID -in logged messages, and write the messages to the destination facility -used for mail logging:: +An example of setting some log options, these would include the process ID in +logged messages, and write the messages to the destination facility used for +mail logging:: syslog.openlog(logopt=syslog.LOG_PID, facility=syslog.LOG_MAIL) syslog.syslog('E-mail processing initiated...') Modified: python/branches/py3k-cdecimal/Doc/library/telnetlib.rst ============================================================================== --- python/branches/py3k-cdecimal/Doc/library/telnetlib.rst (original) +++ python/branches/py3k-cdecimal/Doc/library/telnetlib.rst Mon Jun 7 12:46:02 2010 @@ -27,16 +27,11 @@ :class:`Telnet` represents a connection to a Telnet server. The instance is initially not connected by default; the :meth:`open` method must be used to establish a connection. Alternatively, the host name and optional port - and timeout can be passed to the constructor, in which case the connection to - the server will be established before the constructor returns. The optional - *timeout* parameter specifies a timeout in seconds for the connection attempt (if - not specified, the global default timeout setting will be used). - number can be passed to the constructor, to, in which case the connection to - the server will be established before the constructor returns. The optional + the server will be established before the constructor returns. The optional *timeout* parameter specifies a timeout in seconds for blocking operations - like the connection attempt (if not specified, or passed as None, the global - default timeout setting will be used). + like the connection attempt (if not specified, the global default timeout + setting will be used). Do not reopen an already connected instance. Modified: python/branches/py3k-cdecimal/Doc/library/tempfile.rst ============================================================================== --- python/branches/py3k-cdecimal/Doc/library/tempfile.rst (original) +++ python/branches/py3k-cdecimal/Doc/library/tempfile.rst Mon Jun 7 12:46:02 2010 @@ -27,8 +27,7 @@ The module defines the following user-callable functions: - -.. function:: TemporaryFile(mode='w+b', bufsize=-1, suffix='', prefix='tmp', dir=None) +.. function:: TemporaryFile(mode='w+b', buffering=None, encoding=None, newline=None, suffix='', prefix='tmp', dir=None) Return a file-like object that can be used as a temporary storage area. The file is created using :func:`mkstemp`. It will be destroyed as soon @@ -41,8 +40,8 @@ The *mode* parameter defaults to ``'w+b'`` so that the file created can be read and written without being closed. Binary mode is used so that it behaves consistently on all platforms without regard for the data that is - stored. *bufsize* defaults to ``-1``, meaning that the operating system - default is used. + stored. *buffering*, *encoding* and *newline* are interpreted as for + :func:`open`. The *dir*, *prefix* and *suffix* parameters are passed to :func:`mkstemp`. @@ -52,7 +51,7 @@ :keyword:`with` statement, just like a normal file. -.. function:: NamedTemporaryFile(mode='w+b', bufsize=-1, suffix='', prefix='tmp', dir=None, delete=True) +.. function:: NamedTemporaryFile(mode='w+b', buffering=None, encoding=None, newline=None, suffix='', prefix='tmp', dir=None, delete=True) This function operates exactly as :func:`TemporaryFile` does, except that the file is guaranteed to have a visible name in the file system (on @@ -67,7 +66,7 @@ be used in a :keyword:`with` statement, just like a normal file. -.. function:: SpooledTemporaryFile(max_size=0, mode='w+b', bufsize=-1, suffix='', prefix='tmp', dir=None) +.. function:: SpooledTemporaryFile(max_size=0, mode='w+b', buffering=None, encoding=None, newline=None, suffix='', prefix='tmp', dir=None) This function operates exactly as :func:`TemporaryFile` does, except that data is spooled in memory until the file size exceeds *max_size*, or Modified: python/branches/py3k-cdecimal/Doc/library/time.rst ============================================================================== --- python/branches/py3k-cdecimal/Doc/library/time.rst (original) +++ python/branches/py3k-cdecimal/Doc/library/time.rst Mon Jun 7 12:46:02 2010 @@ -81,30 +81,31 @@ :func:`gmtime`, :func:`localtime`, and :func:`strptime` also offer attribute names for individual fields. - +-------+------------------+------------------------------+ - | Index | Attribute | Values | - +=======+==================+==============================+ - | 0 | :attr:`tm_year` | (for example, 1993) | - +-------+------------------+------------------------------+ - | 1 | :attr:`tm_mon` | range [1,12] | - +-------+------------------+------------------------------+ - | 2 | :attr:`tm_mday` | range [1,31] | - +-------+------------------+------------------------------+ - | 3 | :attr:`tm_hour` | range [0,23] | - +-------+------------------+------------------------------+ - | 4 | :attr:`tm_min` | range [0,59] | - +-------+------------------+------------------------------+ - | 5 | :attr:`tm_sec` | range [0,61]; see **(1)** in | - | | | :func:`strftime` description | - +-------+------------------+------------------------------+ - | 6 | :attr:`tm_wday` | range [0,6], Monday is 0 | - +-------+------------------+------------------------------+ - | 7 | :attr:`tm_yday` | range [1,366] | - +-------+------------------+------------------------------+ - | 8 | :attr:`tm_isdst` | 0, 1 or -1; see below | - +-------+------------------+------------------------------+ + +-------+-------------------+---------------------------------+ + | Index | Attribute | Values | + +=======+===================+=================================+ + | 0 | :attr:`tm_year` | (for example, 1993) | + +-------+-------------------+---------------------------------+ + | 1 | :attr:`tm_mon` | range [1, 12] | + +-------+-------------------+---------------------------------+ + | 2 | :attr:`tm_mday` | range [1, 31] | + +-------+-------------------+---------------------------------+ + | 3 | :attr:`tm_hour` | range [0, 23] | + +-------+-------------------+---------------------------------+ + | 4 | :attr:`tm_min` | range [0, 59] | + +-------+-------------------+---------------------------------+ + | 5 | :attr:`tm_sec` | range [0, 61]; see **(1)** in | + | | | :func:`strftime` description | + +-------+-------------------+---------------------------------+ + | 6 | :attr:`tm_wday` | range [0, 6], Monday is 0 | + +-------+-------------------+---------------------------------+ + | 7 | :attr:`tm_yday` | range [1, 366] | + +-------+-------------------+---------------------------------+ + | 8 | :attr:`tm_isdst` | 0, 1 or -1; see below | + +-------+-------------------+---------------------------------+ - Note that unlike the C structure, the month value is a range of 1-12, not 0-11. + Note that unlike the C structure, the month value is a range of [1, 12], + not [0, 11]. A year value will be handled as described under "Year 2000 (Y2K) issues" above. A ``-1`` argument as the daylight savings flag, passed to :func:`mktime` will usually result in the correct daylight savings state to be filled in. Modified: python/branches/py3k-cdecimal/Doc/library/unittest.rst ============================================================================== --- python/branches/py3k-cdecimal/Doc/library/unittest.rst (original) +++ python/branches/py3k-cdecimal/Doc/library/unittest.rst Mon Jun 7 12:46:02 2010 @@ -749,7 +749,7 @@ .. method:: skipTest(reason) - Calling this during the a test method or :meth:`setUp` skips the current + Calling this during a test method or :meth:`setUp` skips the current test. See :ref:`unittest-skipping` for more information. .. versionadded:: 3.1 @@ -773,8 +773,7 @@ will be *msg* if given, otherwise it will be :const:`None`. .. deprecated:: 3.1 - :meth:`failUnless`; use one of the ``assert`` variants. - :meth:`assert_`; use :meth:`assertTrue`. + :meth:`failUnless` and :meth:`assert_`; use :meth:`assertTrue`. .. method:: assertEqual(first, second, msg=None) @@ -1169,6 +1168,21 @@ .. versionadded:: 3.1 + .. attribute:: maxDiff + + This attribute controls the maximum length of diffs output by assert + methods that report diffs on failure. It defaults to 80*8 characters. + Assert methods affected by this attribute are + :meth:`assertSequenceEqual` (including all the sequence comparison + methods that delegate to it), :meth:`assertDictEqual` and + :meth:`assertMultiLineEqual`. + + Setting ``maxDiff`` to None means that there is no maximum length of + diffs. + + .. versionadded:: 3.2 + + Testing frameworks can use the following methods to collect information on the test: @@ -1863,7 +1877,9 @@ If an exception is raised during a ``setUpClass`` then the tests in the class are not run and the ``tearDownClass`` is not run. Skipped classes will not -have ``setUpClass`` or ``tearDownClass`` run. +have ``setUpClass`` or ``tearDownClass`` run. If the exception is a +``SkipTest`` exception then the class will be reported as having been skipped +instead of as an error. setUpModule and tearDownModule @@ -1878,7 +1894,9 @@ closeConnection() If an exception is raised in a ``setUpModule`` then none of the tests in the -module will be run and the ``tearDownModule`` will not be run. +module will be run and the ``tearDownModule`` will not be run. If the exception is a +``SkipTest`` exception then the module will be reported as having been skipped +instead of as an error. Signal Handling Modified: python/branches/py3k-cdecimal/Doc/library/urllib.parse.rst ============================================================================== --- python/branches/py3k-cdecimal/Doc/library/urllib.parse.rst (original) +++ python/branches/py3k-cdecimal/Doc/library/urllib.parse.rst Mon Jun 7 12:46:02 2010 @@ -26,7 +26,7 @@ The :mod:`urllib.parse` module defines the following functions: -.. function:: urlparse(urlstring, default_scheme='', allow_fragments=True) +.. function:: urlparse(urlstring, scheme='', allow_fragments=True) Parse a URL into six components, returning a 6-tuple. This corresponds to the general structure of a URL: ``scheme://netloc/path;parameters?query#fragment``. @@ -48,7 +48,7 @@ >>> o.geturl() 'http://www.cwi.nl:80/%7Eguido/Python.html' - If the *default_scheme* argument is specified, it gives the default addressing + If the *scheme* argument is specified, it gives the default addressing scheme, to be used only if the URL does not specify one. The default value for this argument is the empty string. @@ -142,7 +142,7 @@ states that these are equivalent). -.. function:: urlsplit(urlstring, default_scheme='', allow_fragments=True) +.. function:: urlsplit(urlstring, scheme='', allow_fragments=True) This is similar to :func:`urlparse`, but does not split the params from the URL. This should generally be used instead of :func:`urlparse` if the more recent URL @@ -312,19 +312,21 @@ .. function:: urlencode(query, doseq=False) - 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. If the optional parameter *doseq* is present and - evaluates to true, individual ``key=value`` pairs are generated for each element - of the sequence. 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 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 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. .. seealso:: Modified: python/branches/py3k-cdecimal/Doc/library/urllib.request.rst ============================================================================== --- python/branches/py3k-cdecimal/Doc/library/urllib.request.rst (original) +++ python/branches/py3k-cdecimal/Doc/library/urllib.request.rst Mon Jun 7 12:46:02 2010 @@ -604,7 +604,7 @@ method on the currently installed global :class:`OpenerDirector`). The optional *timeout* parameter specifies a timeout in seconds for blocking operations like the connection attempt (if not specified, the global default - timeout setting will be usedi). The timeout feature actually works only for + timeout setting will be used). The timeout feature actually works only for HTTP, HTTPS, FTP and FTPS connections). @@ -1079,7 +1079,7 @@ >>> import urllib.request >>> f = urllib.request.urlopen('http://www.python.org/') - >>> print(fp.read(100).decode('utf-8')) + >>> print(f.read(100).decode('utf-8')) ` is used +to ensure that the handles are closed correctly, even if the programmer neglects +to explicitly close them. This module offers the following functions: .. function:: CloseKey(hkey) - Closes a previously opened registry key. The hkey argument specifies a + Closes a previously opened registry key. The *hkey* argument specifies a previously opened key. .. note:: - If *hkey* is not closed using this method (or via :meth:`hkey.Close() `), - it is closed when the *hkey* object is destroyed by Python. + + If *hkey* is not closed using this method (or via :meth:`hkey.Close() + `), it is closed when the *hkey* object is destroyed by + Python. .. function:: ConnectRegistry(computer_name, key) @@ -109,7 +111,7 @@ The :func:`DeleteKeyEx` function is implemented with the RegDeleteKeyEx Windows API function, which is specific to 64-bit versions of Windows. See the `RegDeleteKeyEx documentation - `__. + `__. *key* is an already open key, or one of the predefined :ref:`HKEY_* constants `. @@ -120,7 +122,7 @@ *res* is a reserved integer, and must be zero. The default is zero. - *sam* is an integer that specifies an access mask that describes the + *sam* is an integer that specifies an access mask that describes the desired security access for the key. Default is :const:`KEY_ALL_ACCESS`. See :ref:`Access Rights ` for other allowed values. @@ -183,13 +185,15 @@ | | registry type | +-------+--------------------------------------------+ | ``2`` | An integer that identifies the type of the | - | | value data | + | | value data (see table in docs for | + | | :meth:`SetValueEx`) | +-------+--------------------------------------------+ .. function:: ExpandEnvironmentStrings(str) - Expands environment strings %NAME% in unicode string like :const:`REG_EXPAND_SZ`:: + Expands environment variable placeholders ``%NAME%`` in strings like + :const:`REG_EXPAND_SZ`:: >>> ExpandEnvironmentStrings('%windir%') 'C:\\Windows' @@ -223,23 +227,20 @@ *key* is a handle returned by :func:`ConnectRegistry` or one of the constants :const:`HKEY_USERS` or :const:`HKEY_LOCAL_MACHINE`. - *sub_key* is a string that identifies the sub_key to load. + *sub_key* is a string that identifies the subkey to load. *file_name* is the name of the file to load registry data from. This file must have been created with the :func:`SaveKey` function. Under the file allocation table (FAT) file system, the filename may not have an extension. - A call to LoadKey() fails if the calling process does not have the - :const:`SE_RESTORE_PRIVILEGE` privilege. Note that privileges are different than + A call to :func:`LoadKey` fails if the calling process does not have the + :const:`SE_RESTORE_PRIVILEGE` privilege. Note that privileges are different from permissions -- see the `RegLoadKey documentation `__ for more details. If *key* is a handle returned by :func:`ConnectRegistry`, then the path - specified in *fileName* is relative to the remote computer. - - The Win32 documentation implies *key* must be in the :const:`HKEY_USER` or - :const:`HKEY_LOCAL_MACHINE` tree. This may or may not be true. + specified in *file_name* is relative to the remote computer. .. function:: OpenKey(key, sub_key[, res[, sam]]) @@ -254,8 +255,8 @@ *res* is a reserved integer, and must be zero. The default is zero. *sam* is an integer that specifies an access mask that describes the desired - security access for the key. Default is :const:`KEY_READ`. See - :ref:`Access Rights ` for other allowed values. + security access for the key. Default is :const:`KEY_READ`. See :ref:`Access + Rights ` for other allowed values. The result is a new handle to the specified key. @@ -327,7 +328,8 @@ | ``0`` | The value of the registry item. | +-------+-----------------------------------------+ | ``1`` | An integer giving the registry type for | - | | this value. | + | | this value (see table in docs for | + | | :meth:`SetValueEx`) | +-------+-----------------------------------------+ @@ -338,10 +340,10 @@ *key* is an already open key, or one of the predefined :ref:`HKEY_* constants `. - *file_name* is the name of the file to save registry data to. This file cannot - already exist. If this filename includes an extension, it cannot be used on file - allocation table (FAT) file systems by the :meth:`LoadKey`, :meth:`ReplaceKey` - or :meth:`RestoreKey` methods. + *file_name* is the name of the file to save registry data to. This file + cannot already exist. If this filename includes an extension, it cannot be + used on file allocation table (FAT) file systems by the :meth:`LoadKey` + method. If *key* represents a key on a remote computer, the path described by *file_name* is relative to the remote computer. The caller of this method must @@ -411,16 +413,16 @@ .. function:: DisableReflectionKey(key) Disables registry reflection for 32-bit processes running on a 64-bit - Operating System. + operating system. - *key* is an already open key, or one of the predefined - :ref:`HKEY_* constants `. + *key* is an already open key, or one of the predefined :ref:`HKEY_* constants + `. - Will generally raise :exc:`NotImplemented` if executed on a 32-bit - Operating System. + Will generally raise :exc:`NotImplemented` if executed on a 32-bit operating + system. If the key is not on the reflection list, the function succeeds but has no - effect. Disabling reflection for a key does not affect reflection of any + effect. Disabling reflection for a key does not affect reflection of any subkeys. @@ -428,11 +430,11 @@ Restores registry reflection for the specified disabled key. - *key* is an already open key, or one of the predefined - :ref:`HKEY_* constants `. + *key* is an already open key, or one of the predefined :ref:`HKEY_* constants + `. - Will generally raise :exc:`NotImplemented` if executed on a 32-bit - Operating System. + Will generally raise :exc:`NotImplemented` if executed on a 32-bit operating + system. Restoring reflection for a key does not affect reflection of any subkeys. @@ -447,7 +449,7 @@ Returns ``True`` if reflection is disabled. Will generally raise :exc:`NotImplemented` if executed on a 32-bit - Operating System. + operating system. .. _constants: @@ -646,7 +648,7 @@ This object wraps a Windows HKEY object, automatically closing it when the object is destroyed. To guarantee cleanup, you can call either the -:meth:`Close` method on the object, or the :func:`CloseKey` function. +:meth:`~PyHKEY.Close` method on the object, or the :func:`CloseKey` function. All registry functions in this module return one of these objects. @@ -666,8 +668,8 @@ Handle objects can be converted to an integer (e.g., using the built-in :func:`int` function), in which case the underlying Windows handle value is -returned. You can also use the :meth:`Detach` method to return the integer -handle, and also disconnect the Windows handle from the handle object. +returned. You can also use the :meth:`~PyHKEY.Detach` method to return the +integer handle, and also disconnect the Windows handle from the handle object. .. method:: PyHKEY.Close() @@ -692,11 +694,12 @@ .. method:: PyHKEY.__enter__() PyHKEY.__exit__(\*exc_info) - The HKEY object implements :meth:`__enter__` and :meth:`__exit__` and thus - supports the context protocol for the :keyword:`with` statement:: + The HKEY object implements :meth:`~object.__enter__` and + :meth:`~object.__exit__` and thus supports the context protocol for the + :keyword:`with` statement:: with OpenKey(HKEY_LOCAL_MACHINE, "foo") as key: - # ... work with key ... + ... # work with key will automatically close *key* when control leaves the :keyword:`with` block. Modified: python/branches/py3k-cdecimal/Doc/reference/datamodel.rst ============================================================================== --- python/branches/py3k-cdecimal/Doc/reference/datamodel.rst (original) +++ python/branches/py3k-cdecimal/Doc/reference/datamodel.rst Mon Jun 7 12:46:02 2010 @@ -1587,6 +1587,46 @@ called *members*. +Customizing instance and subclass checks +---------------------------------------- + +The following methods are used to override the default behavior of the +:func:`isinstance` and :func:`issubclass` built-in functions. + +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 +ABCs. + +.. method:: class.__instancecheck__(self, instance) + + Return true if *instance* should be considered a (direct or indirect) + instance of *class*. If defined, called to implement ``isinstance(instance, + class)``. + + +.. method:: class.__subclasscheck__(self, subclass) + + Return true if *subclass* should be considered a (direct or indirect) + subclass of *class*. If defined, called to implement ``issubclass(subclass, + class)``. + + +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 +case the instance is itself a class. + +.. seealso:: + + :pep:`3119` - Introducing Abstract Base Classes + Includes the specification for customizing :func:`isinstance` and + :func:`issubclass` behavior through :meth:`__instancecheck__` and + :meth:`__subclasscheck__`, with motivation for this functionality in the + context of adding Abstract Base Classes (see the :mod:`abc` module) to the + language. + + .. _callable-types: Emulating callable objects Modified: python/branches/py3k-cdecimal/Doc/tools/sphinxext/pyspecific.py ============================================================================== --- python/branches/py3k-cdecimal/Doc/tools/sphinxext/pyspecific.py (original) +++ python/branches/py3k-cdecimal/Doc/tools/sphinxext/pyspecific.py Mon Jun 7 12:46:02 2010 @@ -78,7 +78,7 @@ 'assert', 'assignment', 'atom-identifiers', 'atom-literals', 'attribute-access', 'attribute-references', 'augassign', 'binary', 'bitwise', 'bltin-code-objects', 'bltin-ellipsis-object', - 'bltin-file-objects', 'bltin-null-object', 'bltin-type-objects', 'booleans', + 'bltin-null-object', 'bltin-type-objects', 'booleans', 'break', 'callable-types', 'calls', 'class', 'comparisons', 'compound', 'context-managers', 'continue', 'conversions', 'customization', 'debugger', 'del', 'dict', 'dynamic-features', 'else', 'exceptions', 'execmodel', Modified: python/branches/py3k-cdecimal/Doc/tutorial/datastructures.rst ============================================================================== --- python/branches/py3k-cdecimal/Doc/tutorial/datastructures.rst (original) +++ python/branches/py3k-cdecimal/Doc/tutorial/datastructures.rst Mon Jun 7 12:46:02 2010 @@ -377,10 +377,7 @@ Here is a brief demonstration:: - >>> basket = {'apple', 'orange', 'apple', 'pear', 'orange', 'banana'} - >>> print(basket) - {'orange', 'banana', 'pear', 'apple'} - >>> fruit = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana'] + >>> basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana'] >>> fruit = set(basket) # create a set without duplicates >>> fruit {'orange', 'pear', 'apple', 'banana'} Modified: python/branches/py3k-cdecimal/Doc/whatsnew/3.2.rst ============================================================================== --- python/branches/py3k-cdecimal/Doc/whatsnew/3.2.rst (original) +++ python/branches/py3k-cdecimal/Doc/whatsnew/3.2.rst Mon Jun 7 12:46:02 2010 @@ -100,6 +100,18 @@ (Contributed by Tarek Ziade.) +* The *sqlite3* module has some new features: + + * XXX *enable_load_extension* + + * XXX *load_extension* + + * New :class:`~sqlite3.Connection` attribute + :attr:`~sqlite3.Connection.in_transaction` is :const:`True` when there + are uncommitted changes, and :const:`False` otherwise. (Contributed + by R. David Murray and Shashwat Anand, :issue:`8845`.) + + Multi-threading =============== Modified: python/branches/py3k-cdecimal/Include/longobject.h ============================================================================== --- python/branches/py3k-cdecimal/Include/longobject.h (original) +++ python/branches/py3k-cdecimal/Include/longobject.h Mon Jun 7 12:46:02 2010 @@ -101,6 +101,14 @@ */ PyAPI_FUNC(size_t) _PyLong_NumBits(PyObject *v); +/* _PyLong_Divmod_Near. Given integers a and b, compute the nearest + integer q to the exact quotient a / b, rounding to the nearest even integer + in the case of a tie. Return (q, r), where r = a - q*b. The remainder r + will satisfy abs(r) <= abs(b)/2, with equality possible only if q is + even. +*/ +PyAPI_FUNC(PyObject *) _PyLong_Divmod_Near(PyObject *, PyObject *); + /* _PyLong_FromByteArray: View the n unsigned bytes as a binary integer in base 256, and return a Python long with the same numeric value. If n is 0, the integer is 0. Else: Modified: python/branches/py3k-cdecimal/Include/pyport.h ============================================================================== --- python/branches/py3k-cdecimal/Include/pyport.h (original) +++ python/branches/py3k-cdecimal/Include/pyport.h Mon Jun 7 12:46:02 2010 @@ -126,6 +126,20 @@ #endif #endif +/* Parameters used for the numeric hash implementation. See notes for + _PyHash_Double in Objects/object.c. Numeric hashes are based on + reduction modulo the prime 2**_PyHASH_BITS - 1. */ + +#if SIZEOF_LONG >= 8 +#define _PyHASH_BITS 61 +#else +#define _PyHASH_BITS 31 +#endif +#define _PyHASH_MODULUS ((1UL << _PyHASH_BITS) - 1) +#define _PyHASH_INF 314159 +#define _PyHASH_NAN 0 +#define _PyHASH_IMAG 1000003UL + /* uintptr_t is the C9X name for an unsigned integral type such that a * legitimate void* can be cast to uintptr_t and then back to void* again * without loss of information. Similarly for intptr_t, wrt a signed Modified: python/branches/py3k-cdecimal/Include/sysmodule.h ============================================================================== --- python/branches/py3k-cdecimal/Include/sysmodule.h (original) +++ python/branches/py3k-cdecimal/Include/sysmodule.h Mon Jun 7 12:46:02 2010 @@ -10,6 +10,7 @@ PyAPI_FUNC(PyObject *) PySys_GetObject(const char *); PyAPI_FUNC(int) PySys_SetObject(const char *, PyObject *); PyAPI_FUNC(void) PySys_SetArgv(int, wchar_t **); +PyAPI_FUNC(void) PySys_SetArgvEx(int, wchar_t **, int); PyAPI_FUNC(void) PySys_SetPath(const wchar_t *); PyAPI_FUNC(void) PySys_WriteStdout(const char *format, ...) @@ -21,6 +22,7 @@ PyAPI_FUNC(void) PySys_ResetWarnOptions(void); PyAPI_FUNC(void) PySys_AddWarnOption(const wchar_t *); +PyAPI_FUNC(void) PySys_AddWarnOptionUnicode(PyObject *); PyAPI_FUNC(int) PySys_HasWarnOptions(void); #ifdef __cplusplus Modified: python/branches/py3k-cdecimal/Lib/_abcoll.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/_abcoll.py (original) +++ python/branches/py3k-cdecimal/Lib/_abcoll.py Mon Jun 7 12:46:02 2010 @@ -376,8 +376,9 @@ return ValuesView(self) def __eq__(self, other): - return isinstance(other, Mapping) and \ - dict(self.items()) == dict(other.items()) + if not isinstance(other, Mapping): + return NotImplemented + return dict(self.items()) == dict(other.items()) def __ne__(self, other): return not (self == other) Modified: python/branches/py3k-cdecimal/Lib/argparse.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/argparse.py (original) +++ python/branches/py3k-cdecimal/Lib/argparse.py Mon Jun 7 12:46:02 2010 @@ -987,7 +987,7 @@ version=None, dest=SUPPRESS, default=SUPPRESS, - help=None): + help="show program's version number and exit"): super(_VersionAction, self).__init__( option_strings=option_strings, dest=dest, Modified: python/branches/py3k-cdecimal/Lib/base64.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/base64.py (original) +++ python/branches/py3k-cdecimal/Lib/base64.py Mon Jun 7 12:46:02 2010 @@ -383,9 +383,9 @@ if o == '-u': func = decode if o == '-t': test(); return if args and args[0] != '-': - func(open(args[0], 'rb'), sys.stdout) + func(open(args[0], 'rb'), sys.stdout.buffer) else: - func(sys.stdin, sys.stdout) + func(sys.stdin.buffer, sys.stdout.buffer) def test(): Modified: python/branches/py3k-cdecimal/Lib/codecs.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/codecs.py (original) +++ python/branches/py3k-cdecimal/Lib/codecs.py Mon Jun 7 12:46:02 2010 @@ -374,6 +374,11 @@ """ pass + def seek(self, offset, whence=0): + self.stream.seek(offset, whence) + if whence == 0 and offset == 0: + self.reset() + def __getattr__(self, name, getattr=getattr): @@ -606,8 +611,8 @@ Resets the codec buffers used for keeping state. """ - self.reset() self.stream.seek(offset, whence) + self.reset() def __next__(self): @@ -699,6 +704,12 @@ self.reader.reset() self.writer.reset() + def seek(self, offset, whence=0): + self.stream.seek(offset, whence) + self.reader.reset() + if whence == 0 and offset == 0: + self.writer.reset() + def __getattr__(self, name, getattr=getattr): Modified: python/branches/py3k-cdecimal/Lib/decimal.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/decimal.py (original) +++ python/branches/py3k-cdecimal/Lib/decimal.py Mon Jun 7 12:46:02 2010 @@ -164,7 +164,7 @@ anything, though. handle -- Called when context._raise_error is called and the - trap_enabler is set. First argument is self, second is the + trap_enabler is not set. First argument is self, second is the context. More arguments can be given, those being after the explanation in _raise_error (For example, context._raise_error(NewError, '(-x)!', self._sign) would @@ -862,7 +862,7 @@ # that specified by IEEE 754. def __eq__(self, other, context=None): - other = _convert_other(other, allow_float=True) + other = _convert_other(other, allow_float = True) if other is NotImplemented: return other if self._check_nans(other, context): @@ -870,7 +870,7 @@ return self._cmp(other) == 0 def __ne__(self, other, context=None): - other = _convert_other(other, allow_float=True) + other = _convert_other(other, allow_float = True) if other is NotImplemented: return other if self._check_nans(other, context): @@ -879,7 +879,7 @@ def __lt__(self, other, context=None): - other = _convert_other(other, allow_float=True) + other = _convert_other(other, allow_float = True) if other is NotImplemented: return other ans = self._compare_check_nans(other, context) @@ -888,7 +888,7 @@ return self._cmp(other) < 0 def __le__(self, other, context=None): - other = _convert_other(other, allow_float=True) + other = _convert_other(other, allow_float = True) if other is NotImplemented: return other ans = self._compare_check_nans(other, context) @@ -897,7 +897,7 @@ return self._cmp(other) <= 0 def __gt__(self, other, context=None): - other = _convert_other(other, allow_float=True) + other = _convert_other(other, allow_float = True) if other is NotImplemented: return other ans = self._compare_check_nans(other, context) @@ -906,7 +906,7 @@ return self._cmp(other) > 0 def __ge__(self, other, context=None): - other = _convert_other(other, allow_float=True) + other = _convert_other(other, allow_float = True) if other is NotImplemented: return other ans = self._compare_check_nans(other, context) @@ -935,55 +935,28 @@ def __hash__(self): """x.__hash__() <==> hash(x)""" - # Decimal integers must hash the same as the ints - # - # The hash of a nonspecial noninteger Decimal must depend only - # on the value of that Decimal, and not on its representation. - # For example: hash(Decimal('100E-1')) == hash(Decimal('10')). - - # Equality comparisons involving signaling nans can raise an - # exception; since equality checks are implicitly and - # unpredictably used when checking set and dict membership, we - # prevent signaling nans from being used as set elements or - # dict keys by making __hash__ raise an exception. + + # In order to make sure that the hash of a Decimal instance + # agrees with the hash of a numerically equal integer, float + # or Fraction, we follow the rules for numeric hashes outlined + # in the documentation. (See library docs, 'Built-in Types'). if self._is_special: if self.is_snan(): raise TypeError('Cannot hash a signaling NaN value.') elif self.is_nan(): - # 0 to match hash(float('nan')) - return 0 + return _PyHASH_NAN else: - # values chosen to match hash(float('inf')) and - # hash(float('-inf')). if self._sign: - return -271828 + return -_PyHASH_INF else: - return 314159 + return _PyHASH_INF - # In Python 2.7, we're allowing comparisons (but not - # arithmetic operations) between floats and Decimals; so if - # a Decimal instance is exactly representable as a float then - # its hash should match that of the float. - self_as_float = float(self) - if Decimal.from_float(self_as_float) == self: - return hash(self_as_float) - - if self._isinteger(): - op = _WorkRep(self.to_integral_value()) - # to make computation feasible for Decimals with large - # exponent, we use the fact that hash(n) == hash(m) for - # any two nonzero integers n and m such that (i) n and m - # have the same sign, and (ii) n is congruent to m modulo - # 2**64-1. So we can replace hash((-1)**s*c*10**e) with - # hash((-1)**s*c*pow(10, e, 2**64-1). - return hash((-1)**op.sign*op.int*pow(10, op.exp, 2**64-1)) - # The value of a nonzero nonspecial Decimal instance is - # faithfully represented by the triple consisting of its sign, - # its adjusted exponent, and its coefficient with trailing - # zeros removed. - return hash((self._sign, - self._exp+len(self._int), - self._int.rstrip('0'))) + if self._exp >= 0: + exp_hash = pow(10, self._exp, _PyHASH_MODULUS) + else: + exp_hash = pow(_PyHASH_10INV, -self._exp, _PyHASH_MODULUS) + hash_ = int(self._int) * exp_hash % _PyHASH_MODULUS + return hash_ if self >= 0 else -hash_ def as_tuple(self): """Represents the number as a triple tuple. @@ -1611,9 +1584,9 @@ """Decapitate the payload of a NaN to fit the context""" payload = self._int - # maximum length of payload is precision if _clamp=0, - # precision-1 if _clamp=1. - max_payload_len = context.prec - context._clamp + # maximum length of payload is precision if clamp=0, + # precision-1 if clamp=1. + max_payload_len = context.prec - context.clamp if len(payload) > max_payload_len: payload = payload[len(payload)-max_payload_len:].lstrip('0') return _dec_from_triple(self._sign, payload, self._exp, True) @@ -1638,11 +1611,11 @@ return Decimal(self) # if self is zero then exponent should be between Etiny and - # Emax if _clamp==0, and between Etiny and Etop if _clamp==1. + # Emax if clamp==0, and between Etiny and Etop if clamp==1. Etiny = context.Etiny() Etop = context.Etop() if not self: - exp_max = [context.Emax, Etop][context._clamp] + exp_max = [context.Emax, Etop][context.clamp] new_exp = min(max(self._exp, Etiny), exp_max) if new_exp != self._exp: context._raise_error(Clamped) @@ -1702,8 +1675,8 @@ if self_is_subnormal: context._raise_error(Subnormal) - # fold down if _clamp == 1 and self has too few digits - if context._clamp == 1 and self._exp > Etop: + # fold down if clamp == 1 and self has too few digits + if context.clamp == 1 and self._exp > Etop: context._raise_error(Clamped) self_padded = self._int + '0'*(self._exp - Etop) return _dec_from_triple(self._sign, self_padded, Etop) @@ -2451,7 +2424,7 @@ if not dup: return _dec_from_triple(dup._sign, '0', 0) - exp_max = [context.Emax, context.Etop()][context._clamp] + exp_max = [context.Emax, context.Etop()][context.clamp] end = len(dup._int) exp = dup._exp while dup._int[end-1] == '0' and exp < exp_max: @@ -3828,13 +3801,13 @@ Emax - Maximum exponent capitals - If 1, 1*10^1 is printed as 1E+1. If 0, printed as 1e1 - _clamp - If 1, change exponents if too high (Default 0) + clamp - If 1, change exponents if too high (Default 0) """ def __init__(self, prec=None, rounding=None, traps=None, flags=None, Emin=None, Emax=None, - capitals=None, _clamp=0, + capitals=None, clamp=None, _ignored_flags=None): if flags is None: flags = [] @@ -3855,7 +3828,8 @@ """Show the current context.""" s = [] s.append('Context(prec=%(prec)d, rounding=%(rounding)s, ' - 'Emin=%(Emin)d, Emax=%(Emax)d, capitals=%(capitals)d' + 'Emin=%(Emin)d, Emax=%(Emax)d, capitals=%(capitals)d, ' + 'clamp=%(clamp)d' % vars(self)) names = [f.__name__ for f, v in self.flags.items() if v] s.append('flags=[' + ', '.join(names) + ']') @@ -3872,23 +3846,45 @@ """Returns a shallow copy from self.""" nc = Context(self.prec, self.rounding, self.traps, self.flags, self.Emin, self.Emax, - self.capitals, self._clamp, self._ignored_flags) + self.capitals, self.clamp, self._ignored_flags) return nc def copy(self): """Returns a deep copy from self.""" nc = Context(self.prec, self.rounding, self.traps.copy(), self.flags.copy(), self.Emin, self.Emax, - self.capitals, self._clamp, self._ignored_flags) + self.capitals, self.clamp, self._ignored_flags) return nc __copy__ = copy + # _clamp is provided for backwards compatibility with third-party + # code. May be removed in Python >= 3.3. + def _get_clamp(self): + "_clamp mirrors the clamp attribute. Its use is deprecated." + import warnings + warnings.warn('Use of the _clamp attribute is deprecated. ' + 'Please use clamp instead.', + DeprecationWarning) + return self.clamp + + def _set_clamp(self, clamp): + "_clamp mirrors the clamp attribute. Its use is deprecated." + import warnings + warnings.warn('Use of the _clamp attribute is deprecated. ' + 'Please use clamp instead.', + DeprecationWarning) + self.clamp = clamp + + # don't bother with _del_clamp; no sane 3rd party code should + # be deleting the _clamp attribute + _clamp = property(_get_clamp, _set_clamp) + def _raise_error(self, condition, explanation = None, *args): """Handles an error If the flag is in _ignored_flags, returns the default response. Otherwise, it sets the flag, then, if the corresponding - trap_enabler is set, it reaises the exception. Otherwise, it returns + trap_enabler is set, it reraises the exception. Otherwise, it returns the default value after setting the flag. """ error = _condition_map.get(condition, condition) @@ -3965,7 +3961,7 @@ "permitted.") d = Decimal(num, context=self) - if d._isnan() and len(d._int) > self.prec - self._clamp: + if d._isnan() and len(d._int) > self.prec - self.clamp: return self._raise_error(ConversionSyntax, "diagnostic info too long in NaN") return d._fix(self) @@ -5875,7 +5871,8 @@ flags=[], Emax=999999999, Emin=-999999999, - capitals=1 + capitals=1, + clamp=0 ) # Pre-made alternate contexts offered by the specification @@ -6194,6 +6191,17 @@ # _SignedInfinity[sign] is infinity w/ that sign _SignedInfinity = (_Infinity, _NegativeInfinity) +# Constants related to the hash implementation; hash(x) is based +# on the reduction of x modulo _PyHASH_MODULUS +import sys +_PyHASH_MODULUS = sys.hash_info.modulus +# hash values to use for positive and negative infinities, and nans +_PyHASH_INF = sys.hash_info.inf +_PyHASH_NAN = sys.hash_info.nan +del sys + +# _PyHASH_10INV is the inverse of 10 modulo the prime _PyHASH_MODULUS +_PyHASH_10INV = pow(10, _PyHASH_MODULUS - 2, _PyHASH_MODULUS) if __name__ == '__main__': Modified: python/branches/py3k-cdecimal/Lib/distutils/log.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/distutils/log.py (original) +++ python/branches/py3k-cdecimal/Lib/distutils/log.py Mon Jun 7 12:46:02 2010 @@ -27,6 +27,10 @@ stream = sys.stderr else: stream = sys.stdout + if stream.errors == 'strict': + # emulate backslashreplace error handler + encoding = stream.encoding + msg = msg.encode(encoding, "backslashreplace").decode(encoding) stream.write('%s\n' % msg) stream.flush() Modified: python/branches/py3k-cdecimal/Lib/distutils/unixccompiler.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/distutils/unixccompiler.py (original) +++ python/branches/py3k-cdecimal/Lib/distutils/unixccompiler.py Mon Jun 7 12:46:02 2010 @@ -15,7 +15,7 @@ __revision__ = "$Id$" -import os, sys +import os, sys, re from distutils.dep_util import newer from distutils.ccompiler import \ @@ -320,10 +320,31 @@ dylib_f = self.library_filename(lib, lib_type='dylib') static_f = self.library_filename(lib, lib_type='static') + if sys.platform == 'darwin': + # On OSX users can specify an alternate SDK using + # '-isysroot', calculate the SDK root if it is specified + # (and use it further on) + _sysconfig = __import__('sysconfig') + cflags = _sysconfig.get_config_var('CFLAGS') + m = re.search(r'-isysroot\s+(\S+)', cflags) + if m is None: + sysroot = '/' + else: + sysroot = m.group(1) + + + for dir in dirs: shared = os.path.join(dir, shared_f) dylib = os.path.join(dir, dylib_f) static = os.path.join(dir, static_f) + + if sys.platform == 'darwin' and ( + dir.startswith('/System/') or dir.startswith('/usr/')): + 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) + # We're second-guessing the linker here, with not much hard # data to go on: GCC seems to prefer the shared library, so I'm # assuming that *all* Unix C compilers do. And of course I'm Modified: python/branches/py3k-cdecimal/Lib/email/charset.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/email/charset.py (original) +++ python/branches/py3k-cdecimal/Lib/email/charset.py Mon Jun 7 12:46:02 2010 @@ -377,6 +377,8 @@ """ # 7bit/8bit encodings return the string unchanged (module conversions) if self.body_encoding is BASE64: + if isinstance(string, str): + string = string.encode(self.output_charset) return email.base64mime.body_encode(string) elif self.body_encoding is QP: return email.quoprimime.body_encode(string) Modified: python/branches/py3k-cdecimal/Lib/email/encoders.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/email/encoders.py (original) +++ python/branches/py3k-cdecimal/Lib/email/encoders.py Mon Jun 7 12:46:02 2010 @@ -29,7 +29,7 @@ Also, add an appropriate Content-Transfer-Encoding header. """ orig = msg.get_payload() - encdata = _bencode(orig) + encdata = str(_bencode(orig), 'ascii') msg.set_payload(encdata) msg['Content-Transfer-Encoding'] = 'base64' Modified: python/branches/py3k-cdecimal/Lib/email/test/test_email.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/email/test/test_email.py (original) +++ python/branches/py3k-cdecimal/Lib/email/test/test_email.py Mon Jun 7 12:46:02 2010 @@ -535,7 +535,7 @@ # whose output character set is 7bit gets a transfer-encoding # of 7bit. eq = self.assertEqual - msg = MIMEText('\xca\xb8', _charset='euc-jp') + msg = MIMEText('?', _charset='euc-jp') eq(msg['content-transfer-encoding'], '7bit') @@ -970,7 +970,8 @@ def test_encoding(self): payload = self._au.get_payload() - self.assertEqual(base64.decodebytes(payload), self._audiodata) + self.assertEqual(base64.decodebytes(bytes(payload, 'ascii')), + self._audiodata) def test_checkSetMinor(self): au = MIMEAudio(self._audiodata, 'fish') @@ -1010,7 +1011,8 @@ def test_encoding(self): payload = self._im.get_payload() - self.assertEqual(base64.decodebytes(payload), self._imgdata) + self.assertEqual(base64.decodebytes(bytes(payload, 'ascii')), + self._imgdata) def test_checkSetMinor(self): im = MIMEImage(self._imgdata, 'fish') @@ -1050,7 +1052,7 @@ eq = self.assertEqual bytes = b'\xfa\xfb\xfc\xfd\xfe\xff' msg = MIMEApplication(bytes) - eq(msg.get_payload(), b'+vv8/f7/') + eq(msg.get_payload(), '+vv8/f7/') eq(msg.get_payload(decode=True), bytes) @@ -1080,6 +1082,33 @@ eq(msg.get_charset().input_charset, 'us-ascii') eq(msg['content-type'], 'text/plain; charset="us-ascii"') + def test_7bit_input(self): + eq = self.assertEqual + msg = MIMEText('hello there', _charset='us-ascii') + eq(msg.get_charset().input_charset, 'us-ascii') + eq(msg['content-type'], 'text/plain; charset="us-ascii"') + + def test_7bit_input_no_charset(self): + eq = self.assertEqual + msg = MIMEText('hello there') + eq(msg.get_charset(), 'us-ascii') + eq(msg['content-type'], 'text/plain; charset="us-ascii"') + self.assertTrue('hello there' in msg.as_string()) + + def test_utf8_input(self): + teststr = '\u043a\u0438\u0440\u0438\u043b\u0438\u0446\u0430' + eq = self.assertEqual + msg = MIMEText(teststr, _charset='utf-8') + eq(msg.get_charset().output_charset, 'utf-8') + eq(msg['content-type'], 'text/plain; charset="utf-8"') + eq(msg.get_payload(decode=True), teststr.encode('utf-8')) + + @unittest.skip("can't fix because of backward compat in email5, " + "will fix in email6") + def test_utf8_input_no_charset(self): + teststr = '\u043a\u0438\u0440\u0438\u043b\u0438\u0446\u0430' + self.assertRaises(UnicodeEncodeError, MIMEText, teststr) + # Test complicated multipart/* messages Modified: python/branches/py3k-cdecimal/Lib/encodings/utf_16.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/encodings/utf_16.py (original) +++ python/branches/py3k-cdecimal/Lib/encodings/utf_16.py Mon Jun 7 12:46:02 2010 @@ -103,17 +103,23 @@ class StreamWriter(codecs.StreamWriter): def __init__(self, stream, errors='strict'): - self.bom_written = False codecs.StreamWriter.__init__(self, stream, errors) + self.encoder = None + + def reset(self): + codecs.StreamWriter.reset(self) + self.encoder = None def encode(self, input, errors='strict'): - self.bom_written = True - result = codecs.utf_16_encode(input, errors) - if sys.byteorder == 'little': - self.encode = codecs.utf_16_le_encode + if self.encoder is None: + result = codecs.utf_16_encode(input, errors) + if sys.byteorder == 'little': + self.encoder = codecs.utf_16_le_encode + else: + self.encoder = codecs.utf_16_be_encode + return result else: - self.encode = codecs.utf_16_be_encode - return result + return self.encoder(input, errors) class StreamReader(codecs.StreamReader): Modified: python/branches/py3k-cdecimal/Lib/encodings/utf_32.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/encodings/utf_32.py (original) +++ python/branches/py3k-cdecimal/Lib/encodings/utf_32.py Mon Jun 7 12:46:02 2010 @@ -98,17 +98,23 @@ class StreamWriter(codecs.StreamWriter): def __init__(self, stream, errors='strict'): - self.bom_written = False + self.encoder = None codecs.StreamWriter.__init__(self, stream, errors) + def reset(self): + codecs.StreamWriter.reset(self) + self.encoder = None + def encode(self, input, errors='strict'): - self.bom_written = True - result = codecs.utf_32_encode(input, errors) - if sys.byteorder == 'little': - self.encode = codecs.utf_32_le_encode + if self.encoder is None: + result = codecs.utf_32_encode(input, errors) + if sys.byteorder == 'little': + self.encoder = codecs.utf_32_le_encode + else: + self.encoder = codecs.utf_32_be_encode + return result else: - self.encode = codecs.utf_32_be_encode - return result + return self.encoder(input, errors) class StreamReader(codecs.StreamReader): Modified: python/branches/py3k-cdecimal/Lib/fractions.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/fractions.py (original) +++ python/branches/py3k-cdecimal/Lib/fractions.py Mon Jun 7 12:46:02 2010 @@ -8,6 +8,7 @@ import numbers import operator import re +import sys __all__ = ['Fraction', 'gcd'] @@ -23,6 +24,12 @@ a, b = b, a%b return a +# Constants related to the hash implementation; hash(x) is based +# on the reduction of x modulo the prime _PyHASH_MODULUS. +_PyHASH_MODULUS = sys.hash_info.modulus +# Value to be used for rationals that reduce to infinity modulo +# _PyHASH_MODULUS. +_PyHASH_INF = sys.hash_info.inf _RATIONAL_FORMAT = re.compile(r""" \A\s* # optional whitespace at the start, then @@ -528,16 +535,22 @@ """ # XXX since this method is expensive, consider caching the result - if self._denominator == 1: - # Get integers right. - return hash(self._numerator) - # Expensive check, but definitely correct. - if self == float(self): - return hash(float(self)) + + # In order to make sure that the hash of a Fraction agrees + # with the hash of a numerically equal integer, float or + # Decimal instance, we follow the rules for numeric hashes + # outlined in the documentation. (See library docs, 'Built-in + # Types'). + + # dinv is the inverse of self._denominator modulo the prime + # _PyHASH_MODULUS, or 0 if self._denominator is divisible by + # _PyHASH_MODULUS. + dinv = pow(self._denominator, _PyHASH_MODULUS - 2, _PyHASH_MODULUS) + if not dinv: + hash_ = _PyHASH_INF else: - # Use tuple's hash to avoid a high collision rate on - # simple fractions. - return hash((self._numerator, self._denominator)) + hash_ = abs(self._numerator) * dinv % _PyHASH_MODULUS + return hash_ if self >= 0 else -hash_ def __eq__(a, b): """a == b""" Modified: python/branches/py3k-cdecimal/Lib/ftplib.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/ftplib.py (original) +++ python/branches/py3k-cdecimal/Lib/ftplib.py Mon Jun 7 12:46:02 2010 @@ -638,9 +638,17 @@ ssl_version = ssl.PROTOCOL_TLSv1 def __init__(self, host='', user='', passwd='', acct='', keyfile=None, - certfile=None, timeout=_GLOBAL_DEFAULT_TIMEOUT): + certfile=None, context=None, + timeout=_GLOBAL_DEFAULT_TIMEOUT): + if context is not None and keyfile is not None: + raise ValueError("context and keyfile arguments are mutually " + "exclusive") + if context is not None and certfile is not None: + raise ValueError("context and certfile arguments are mutually " + "exclusive") self.keyfile = keyfile self.certfile = certfile + self.context = context self._prot_p = False FTP.__init__(self, host, user, passwd, acct, timeout) @@ -657,8 +665,12 @@ resp = self.voidcmd('AUTH TLS') else: resp = self.voidcmd('AUTH SSL') - self.sock = ssl.wrap_socket(self.sock, self.keyfile, self.certfile, - ssl_version=self.ssl_version) + if self.context is not None: + self.sock = self.context.wrap_socket(self.sock) + else: + self.sock = ssl.wrap_socket(self.sock, self.keyfile, + self.certfile, + ssl_version=self.ssl_version) self.file = self.sock.makefile(mode='r', encoding=self.encoding) return resp @@ -689,8 +701,11 @@ def ntransfercmd(self, cmd, rest=None): conn, size = FTP.ntransfercmd(self, cmd, rest) if self._prot_p: - conn = ssl.wrap_socket(conn, self.keyfile, self.certfile, - ssl_version=self.ssl_version) + if self.context is not None: + conn = self.context.wrap_socket(conn) + else: + conn = ssl.wrap_socket(conn, self.keyfile, self.certfile, + ssl_version=self.ssl_version) return conn, size def retrbinary(self, cmd, callback, blocksize=8192, rest=None): Modified: python/branches/py3k-cdecimal/Lib/functools.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/functools.py (original) +++ python/branches/py3k-cdecimal/Lib/functools.py Mon Jun 7 12:46:02 2010 @@ -51,7 +51,7 @@ assigned=assigned, updated=updated) def total_ordering(cls): - 'Class decorator that fills-in missing ordering methods' + """Class decorator that fills in missing ordering methods""" convert = { '__lt__': [('__gt__', lambda self, other: other < self), ('__le__', lambda self, other: not other < self), @@ -78,7 +78,7 @@ return cls def cmp_to_key(mycmp): - 'Convert a cmp= function into a key= function' + """Convert a cmp= function into a key= function""" class K(object): def __init__(self, obj, *args): self.obj = obj Modified: python/branches/py3k-cdecimal/Lib/html/parser.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/html/parser.py (original) +++ python/branches/py3k-cdecimal/Lib/html/parser.py Mon Jun 7 12:46:02 2010 @@ -175,6 +175,9 @@ i = self.updatepos(i, k) continue else: + if ";" in rawdata[i:]: #bail by consuming &# + self.handle_data(rawdata[0:2]) + i = self.updatepos(i, 2) break elif startswith('&', i): match = entityref.match(rawdata, i) Modified: python/branches/py3k-cdecimal/Lib/http/client.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/http/client.py (original) +++ python/branches/py3k-cdecimal/Lib/http/client.py Mon Jun 7 12:46:02 2010 @@ -488,6 +488,7 @@ return b"" if self._method == "HEAD": + self.close() return b"" if self.chunked: Modified: python/branches/py3k-cdecimal/Lib/lib2to3/refactor.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/lib2to3/refactor.py (original) +++ python/branches/py3k-cdecimal/Lib/lib2to3/refactor.py Mon Jun 7 12:46:02 2010 @@ -564,7 +564,9 @@ This is necessary to get correct line number / offset information in the parser diagnostics and embedded into the parse tree. """ - return self.driver.parse_tokens(self.wrap_toks(block, lineno, indent)) + tree = self.driver.parse_tokens(self.wrap_toks(block, lineno, indent)) + tree.future_features = frozenset() + return tree def wrap_toks(self, block, lineno, indent): """Wraps a tokenize stream to systematically modify start/end.""" Modified: python/branches/py3k-cdecimal/Lib/linecache.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/linecache.py (original) +++ python/branches/py3k-cdecimal/Lib/linecache.py Mon Jun 7 12:46:02 2010 @@ -73,13 +73,13 @@ if filename in cache: del cache[filename] - if not filename or filename[0] + filename[-1] == '<>': + if not filename or (filename.startswith('<') and filename.endswith('>')): return [] fullname = filename try: stat = os.stat(fullname) - except os.error as msg: + except OSError: basename = filename # Try for a __loader__, if available @@ -114,20 +114,23 @@ fullname = os.path.join(dirname, basename) except (TypeError, AttributeError): # Not sufficiently string-like to do anything useful with. + continue + try: + stat = os.stat(fullname) + break + except os.error: pass - else: - try: - stat = os.stat(fullname) - break - except os.error: - pass else: - # No luck return [] - with open(fullname, 'rb') as fp: - coding, line = tokenize.detect_encoding(fp.readline) - with open(fullname, 'r', encoding=coding) as fp: - lines = fp.readlines() + try: + with open(fullname, 'rb') as fp: + coding, line = tokenize.detect_encoding(fp.readline) + with open(fullname, 'r', encoding=coding) as fp: + lines = fp.readlines() + except IOError: + pass + if lines and not lines[-1].endswith('\n'): + lines[-1] += '\n' size, mtime = stat.st_size, stat.st_mtime cache[filename] = size, mtime, lines, fullname return lines Modified: python/branches/py3k-cdecimal/Lib/pipes.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/pipes.py (original) +++ python/branches/py3k-cdecimal/Lib/pipes.py Mon Jun 7 12:46:02 2010 @@ -249,11 +249,11 @@ # Reliably quote a string as a single argument for /bin/sh -_safechars = string.ascii_letters + string.digits + '!@%_-+=:,./' # Safe unquoted -_funnychars = '"`$\\' # Unsafe inside "double quotes" +# Safe unquoted +_safechars = frozenset(string.ascii_letters + string.digits + '@%_-+=:,./') def quote(file): - ''' return a shell-escaped version of the file string ''' + """Return a shell-escaped version of the file string.""" for c in file: if c not in _safechars: break @@ -261,11 +261,6 @@ if not file: return "''" return file - if '\'' not in file: - return '\'' + file + '\'' - res = '' - for c in file: - if c in _funnychars: - c = '\\' + c - res = res + c - return '"' + res + '"' + # use single quotes, and put single quotes into double quotes + # the string $'b is then quoted as '$'"'"'b' + return "'" + file.replace("'", "'\"'\"'") + "'" Modified: python/branches/py3k-cdecimal/Lib/sqlite3/test/dbapi.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/sqlite3/test/dbapi.py (original) +++ python/branches/py3k-cdecimal/Lib/sqlite3/test/dbapi.py Mon Jun 7 12:46:02 2010 @@ -84,6 +84,7 @@ "NotSupportedError is not a subclass of DatabaseError") class ConnectionTests(unittest.TestCase): + def setUp(self): self.cx = sqlite.connect(":memory:") cu = self.cx.cursor() @@ -140,6 +141,28 @@ self.assertEqual(self.cx.ProgrammingError, sqlite.ProgrammingError) self.assertEqual(self.cx.NotSupportedError, sqlite.NotSupportedError) + def CheckInTransaction(self): + # Can't use db from setUp because we want to test initial state. + cx = sqlite.connect(":memory:") + cu = cx.cursor() + self.assertEqual(cx.in_transaction, False) + cu.execute("create table transactiontest(id integer primary key, name text)") + self.assertEqual(cx.in_transaction, False) + cu.execute("insert into transactiontest(name) values (?)", ("foo",)) + self.assertEqual(cx.in_transaction, True) + cu.execute("select name from transactiontest where name=?", ["foo"]) + row = cu.fetchone() + self.assertEqual(cx.in_transaction, True) + cx.commit() + self.assertEqual(cx.in_transaction, False) + cu.execute("select name from transactiontest where name=?", ["foo"]) + row = cu.fetchone() + self.assertEqual(cx.in_transaction, False) + + def CheckInTransactionRO(self): + with self.assertRaises(AttributeError): + self.cx.in_transaction = True + class CursorTests(unittest.TestCase): def setUp(self): self.cx = sqlite.connect(":memory:") Modified: python/branches/py3k-cdecimal/Lib/ssl.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/ssl.py (original) +++ python/branches/py3k-cdecimal/Lib/ssl.py Mon Jun 7 12:46:02 2010 @@ -63,6 +63,7 @@ from _ssl import CERT_NONE, CERT_OPTIONAL, CERT_REQUIRED from _ssl import (PROTOCOL_SSLv2, PROTOCOL_SSLv3, PROTOCOL_SSLv23, PROTOCOL_TLSv1) +from _ssl import OP_ALL, OP_NO_SSLv2, OP_NO_SSLv3, OP_NO_TLSv1 from _ssl import RAND_status, RAND_egd, RAND_add from _ssl import ( SSL_ERROR_ZERO_RETURN, Modified: python/branches/py3k-cdecimal/Lib/subprocess.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/subprocess.py (original) +++ python/branches/py3k-cdecimal/Lib/subprocess.py Mon Jun 7 12:46:02 2010 @@ -843,7 +843,7 @@ # Process startup details if startupinfo is None: startupinfo = STARTUPINFO() - if None not in (p2cread, c2pwrite, errwrite): + if -1 not in (p2cread, c2pwrite, errwrite): startupinfo.dwFlags |= _subprocess.STARTF_USESTDHANDLES startupinfo.hStdInput = p2cread startupinfo.hStdOutput = c2pwrite Modified: python/branches/py3k-cdecimal/Lib/sysconfig.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/sysconfig.py (original) +++ python/branches/py3k-cdecimal/Lib/sysconfig.py Mon Jun 7 12:46:02 2010 @@ -5,6 +5,10 @@ import os from os.path import pardir, realpath +__all__ = ['parse_config_h', 'get_config_h_filename', 'get_scheme_names', + 'get_path_names', 'get_paths', 'get_path', 'get_config_vars', + 'get_config_var', 'get_platform', 'get_python_version'] + _INSTALL_SCHEMES = { 'posix_prefix': { 'stdlib': '{base}/lib/python{py_version_short}', @@ -47,10 +51,10 @@ 'data' : '{base}', }, 'os2_home': { - 'stdlib': '{userbase}/lib/python/{py_version_short}', - 'platstdlib': '{userbase}/lib/python/{py_version_short}', - 'purelib': '{userbase}/lib/python/{py_version_short}/site-packages', - 'platlib': '{userbase}/lib/python/{py_version_short}/site-packages', + 'stdlib': '{userbase}/lib/python{py_version_short}', + 'platstdlib': '{userbase}/lib/python{py_version_short}', + 'purelib': '{userbase}/lib/python{py_version_short}/site-packages', + 'platlib': '{userbase}/lib/python{py_version_short}/site-packages', 'include': '{userbase}/include/python{py_version_short}', 'scripts': '{userbase}/bin', 'data' : '{userbase}', @@ -65,10 +69,10 @@ 'data' : '{userbase}', }, 'posix_user': { - 'stdlib': '{userbase}/lib/python/{py_version_short}', - 'platstdlib': '{userbase}/lib/python/{py_version_short}', - 'purelib': '{userbase}/lib/python/{py_version_short}/site-packages', - 'platlib': '{userbase}/lib/python/{py_version_short}/site-packages', + 'stdlib': '{userbase}/lib/python{py_version_short}', + 'platstdlib': '{userbase}/lib/python{py_version_short}', + 'purelib': '{userbase}/lib/python{py_version_short}/site-packages', + 'platlib': '{userbase}/lib/python{py_version_short}/site-packages', 'include': '{userbase}/include/python{py_version_short}', 'scripts': '{userbase}/bin', 'data' : '{userbase}', @@ -686,3 +690,22 @@ def get_python_version(): return _PY_VERSION_SHORT + +def _print_dict(title, data): + for index, (key, value) in enumerate(sorted(data.items())): + if index == 0: + print('{0}: '.format(title)) + print('\t{0} = "{1}"'.format(key, value)) + +def _main(): + """Displays all information sysconfig detains.""" + print('Platform: "{0}"'.format(get_platform())) + print('Python version: "{0}"'.format(get_python_version())) + print('Current installation scheme: "{0}"'.format(_get_default_scheme())) + print('') + _print_dict('Paths', get_paths()) + print('') + _print_dict('Variables', get_config_vars()) + +if __name__ == '__main__': + _main() Modified: python/branches/py3k-cdecimal/Lib/tabnanny.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/tabnanny.py (original) +++ python/branches/py3k-cdecimal/Lib/tabnanny.py Mon Jun 7 12:46:02 2010 @@ -93,8 +93,11 @@ check(fullname) return + with open(file, 'rb') as f: + encoding, lines = tokenize.detect_encoding(f.readline) + try: - f = open(file) + f = open(file, encoding=encoding) except IOError as msg: errprint("%r: I/O Error: %s" % (file, msg)) return Modified: python/branches/py3k-cdecimal/Lib/tarfile.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/tarfile.py (original) +++ python/branches/py3k-cdecimal/Lib/tarfile.py Mon Jun 7 12:46:02 2010 @@ -1920,7 +1920,7 @@ tarinfo.mode = stmd tarinfo.uid = statres.st_uid tarinfo.gid = statres.st_gid - if stat.S_ISREG(stmd): + if type == REGTYPE: tarinfo.size = statres.st_size else: tarinfo.size = 0 @@ -2163,8 +2163,7 @@ raise StreamError("cannot extract (sym)link as file object") else: # A (sym)link's file object is its target's file object. - return self.extractfile(self._getmember(tarinfo.linkname, - tarinfo)) + return self.extractfile(self._find_link_target(tarinfo)) else: # If there's no data associated with the member (directory, chrdev, # blkdev, etc.), return None instead of a file object. @@ -2273,27 +2272,21 @@ (platform limitation), we try to make a copy of the referenced file instead of a link. """ - try: + if hasattr(os, "symlink") and hasattr(os, "link"): + # For systems that support symbolic and hard links. if tarinfo.issym(): os.symlink(tarinfo.linkname, targetpath) else: # See extract(). - os.link(tarinfo._link_target, targetpath) - except AttributeError: - if tarinfo.issym(): - linkpath = os.path.dirname(tarinfo.name) + "/" + \ - tarinfo.linkname - else: - linkpath = tarinfo.linkname - + if os.path.exists(tarinfo._link_target): + os.link(tarinfo._link_target, targetpath) + else: + self._extract_member(self._find_link_target(tarinfo), targetpath) + else: try: - self._extract_member(self.getmember(linkpath), targetpath) - except (EnvironmentError, KeyError) as e: - linkpath = linkpath.replace("/", os.sep) - try: - shutil.copy2(linkpath, targetpath) - except EnvironmentError as e: - raise IOError("link could not be created") + self._extract_member(self._find_link_target(tarinfo), targetpath) + except KeyError: + raise ExtractError("unable to resolve link inside archive") def chown(self, tarinfo, targetpath): """Set owner of targetpath according to tarinfo. @@ -2392,21 +2385,28 @@ #-------------------------------------------------------------------------- # Little helper methods: - def _getmember(self, name, tarinfo=None): + def _getmember(self, name, tarinfo=None, normalize=False): """Find an archive member by name from bottom to top. If tarinfo is given, it is used as the starting point. """ # Ensure that all members have been loaded. members = self.getmembers() - if tarinfo is None: - end = len(members) - else: - end = members.index(tarinfo) + # Limit the member search list up to tarinfo. + if tarinfo is not None: + members = members[:members.index(tarinfo)] - for i in range(end - 1, -1, -1): - if name == members[i].name: - return members[i] + if normalize: + name = os.path.normpath(name) + + for member in reversed(members): + if normalize: + member_name = os.path.normpath(member.name) + else: + member_name = member.name + + if name == member_name: + return member def _load(self): """Read through the entire archive file and look for readable @@ -2427,6 +2427,25 @@ if mode is not None and self.mode not in mode: raise IOError("bad operation for mode %r" % self.mode) + def _find_link_target(self, tarinfo): + """Find the target member of a symlink or hardlink member in the + archive. + """ + if tarinfo.issym(): + # Always search the entire archive. + linkname = os.path.dirname(tarinfo.name) + "/" + tarinfo.linkname + limit = None + else: + # Search the archive before the link, because a hard link is + # just a reference to an already archived file. + linkname = tarinfo.linkname + limit = tarinfo + + member = self._getmember(linkname, tarinfo=limit, normalize=True) + if member is None: + raise KeyError("linkname %r not found" % linkname) + return member + def __iter__(self): """Provide an iterator object. """ Modified: python/branches/py3k-cdecimal/Lib/test/regrtest.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/test/regrtest.py (original) +++ python/branches/py3k-cdecimal/Lib/test/regrtest.py Mon Jun 7 12:46:02 2010 @@ -258,6 +258,8 @@ on the command line. """ + replace_stdout() + support.record_original_stdout(sys.stdout) try: opts, args = getopt.getopt(sys.argv[1:], 'hvqxsSrf:lu:t:TD:NLR:FwWM:nj:', @@ -376,7 +378,6 @@ elif o in ('-j', '--multiprocess'): use_mp = int(a) elif o == '--slaveargs': - replace_stdout() args, kwargs = json.loads(a) try: result = runtest(*args, **kwargs) @@ -515,8 +516,6 @@ else: tests = iter(selected) - replace_stdout() - if use_mp: try: from threading import Thread Modified: python/branches/py3k-cdecimal/Lib/test/test_argparse.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/test/test_argparse.py (original) +++ python/branches/py3k-cdecimal/Lib/test/test_argparse.py Mon Jun 7 12:46:02 2010 @@ -3688,6 +3688,25 @@ ''' version = '' +class TestHelpVersionAction(HelpTestCase): + """Test the default help for the version action""" + + parser_signature = Sig(prog='PROG', description='description') + argument_signatures = [Sig('-V', '--version', action='version', version='3.6')] + argument_group_signatures = [] + usage = '''\ + usage: PROG [-h] [-V] + ''' + help = usage + '''\ + + description + + optional arguments: + -h, --help show this help message and exit + -V, --version show program's version number and exit + ''' + version = '' + # ===================================== # Optional/Positional constructor tests # ===================================== Modified: python/branches/py3k-cdecimal/Lib/test/test_base64.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/test/test_base64.py (original) +++ python/branches/py3k-cdecimal/Lib/test/test_base64.py Mon Jun 7 12:46:02 2010 @@ -2,6 +2,8 @@ from test import support import base64 import binascii +import sys +import subprocess @@ -208,6 +210,38 @@ +class TestMain(unittest.TestCase): + def get_output(self, *args, **options): + args = (sys.executable, '-m', 'base64') + args + return subprocess.check_output(args, **options) + + def test_encode_decode(self): + output = self.get_output('-t') + self.assertSequenceEqual(output.splitlines(), ( + b"b'Aladdin:open sesame'", + br"b'QWxhZGRpbjpvcGVuIHNlc2FtZQ==\n'", + b"b'Aladdin:open sesame'", + )) + + def test_encode_file(self): + with open(support.TESTFN, 'wb') as fp: + fp.write(b'a\xffb\n') + + output = self.get_output('-e', support.TESTFN) + self.assertEquals(output.rstrip(), b'Yf9iCg==') + + with open(support.TESTFN, 'rb') as fp: + output = self.get_output('-e', stdin=fp) + self.assertEquals(output.rstrip(), b'Yf9iCg==') + + def test_decode(self): + with open(support.TESTFN, 'wb') as fp: + fp.write(b'Yf9iCg==') + output = self.get_output('-d', support.TESTFN) + self.assertEquals(output.rstrip(), b'a\xffb') + + + def test_main(): support.run_unittest(__name__) Modified: python/branches/py3k-cdecimal/Lib/test/test_builtin.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/test/test_builtin.py (original) +++ python/branches/py3k-cdecimal/Lib/test/test_builtin.py Mon Jun 7 12:46:02 2010 @@ -124,6 +124,16 @@ self.assertEqual(abs(-3.14), 3.14) # str self.assertRaises(TypeError, abs, 'a') + # bool + self.assertEqual(abs(True), 1) + self.assertEqual(abs(False), 0) + # other + self.assertRaises(TypeError, abs) + self.assertRaises(TypeError, abs, None) + class AbsClass(object): + def __abs__(self): + return -5 + self.assertEqual(abs(AbsClass()), -5) def test_all(self): self.assertEqual(all([2, 4, 6]), True) @@ -600,6 +610,8 @@ def __len__(self): return sys.maxsize + 1 self.assertRaises(OverflowError, len, HugeLen()) + class NoLenMethod(object): pass + self.assertRaises(TypeError, len, NoLenMethod()) def test_map(self): self.assertEqual( @@ -1187,6 +1199,11 @@ b = 2 return vars() + class C_get_vars(object): + def getDict(self): + return {'a':2} + __dict__ = property(fget=getDict) + def test_vars(self): self.assertEqual(set(vars()), set(dir())) import sys @@ -1195,6 +1212,7 @@ self.assertEqual(self.get_vars_f2(), {'a': 1, 'b': 2}) self.assertRaises(TypeError, vars, 42, 42) self.assertRaises(TypeError, vars, 42) + self.assertEqual(vars(self.C_get_vars()), {'a':2}) def test_zip(self): a = (1, 2, 3) Modified: python/branches/py3k-cdecimal/Lib/test/test_codecs.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/test/test_codecs.py (original) +++ python/branches/py3k-cdecimal/Lib/test/test_codecs.py Mon Jun 7 12:46:02 2010 @@ -1594,6 +1594,62 @@ b"\xe4\xeb\xef\xf6\xfc") +class BomTest(unittest.TestCase): + def test_seek0(self): + data = "1234567890" + tests = ("utf-16", + "utf-16-le", + "utf-16-be", + "utf-32", + "utf-32-le", + "utf-32-be") + for encoding in tests: + # Check if the BOM is written only once + with codecs.open(support.TESTFN, 'w+', encoding=encoding) as f: + f.write(data) + f.write(data) + f.seek(0) + self.assertEquals(f.read(), data * 2) + f.seek(0) + self.assertEquals(f.read(), data * 2) + + # Check that the BOM is written after a seek(0) + with codecs.open(support.TESTFN, 'w+', encoding=encoding) as f: + f.write(data[0]) + self.assertNotEquals(f.tell(), 0) + f.seek(0) + f.write(data) + f.seek(0) + self.assertEquals(f.read(), data) + + # (StreamWriter) Check that the BOM is written after a seek(0) + with codecs.open(support.TESTFN, 'w+', encoding=encoding) as f: + f.writer.write(data[0]) + self.assertNotEquals(f.writer.tell(), 0) + f.writer.seek(0) + f.writer.write(data) + f.seek(0) + self.assertEquals(f.read(), data) + + # Check that the BOM is not written after a seek() at a position + # different than the start + with codecs.open(support.TESTFN, 'w+', encoding=encoding) as f: + f.write(data) + f.seek(f.tell()) + f.write(data) + f.seek(0) + self.assertEquals(f.read(), data * 2) + + # (StreamWriter) Check that the BOM is not written after a seek() + # at a position different than the start + with codecs.open(support.TESTFN, 'w+', encoding=encoding) as f: + f.writer.write(data) + f.writer.seek(f.writer.tell()) + f.writer.write(data) + f.seek(0) + self.assertEquals(f.read(), data * 2) + + def test_main(): support.run_unittest( UTF32Test, @@ -1621,6 +1677,7 @@ WithStmtTest, TypesTest, SurrogateEscapeTest, + BomTest, ) Modified: python/branches/py3k-cdecimal/Lib/test/test_collections.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/test/test_collections.py (original) +++ python/branches/py3k-cdecimal/Lib/test/test_collections.py Mon Jun 7 12:46:02 2010 @@ -1,6 +1,6 @@ """Unit tests for collections.py.""" -import unittest, doctest +import unittest, doctest, operator import inspect from test import support from collections import namedtuple, Counter, OrderedDict @@ -246,6 +246,37 @@ self.assertNotIsInstance(C(), abc) self.assertFalse(issubclass(C, abc)) + def validate_comparison(self, instance): + ops = ['lt', 'gt', 'le', 'ge', 'ne', 'or', 'and', 'xor', 'sub'] + operators = {} + for op in ops: + name = '__' + op + '__' + operators[name] = getattr(operator, name) + + class Other: + def __init__(self): + self.right_side = False + def __eq__(self, other): + self.right_side = True + return True + __lt__ = __eq__ + __gt__ = __eq__ + __le__ = __eq__ + __ge__ = __eq__ + __ne__ = __eq__ + __ror__ = __eq__ + __rand__ = __eq__ + __rxor__ = __eq__ + __rsub__ = __eq__ + + for name, op in operators.items(): + if not hasattr(instance, name): + continue + other = Other() + op(instance, other) + self.assertTrue(other.right_side,'Right side not called for %s.%s' + % (type(instance), name)) + class TestOneTrickPonyABCs(ABCTestCase): def test_Hashable(self): @@ -420,6 +451,14 @@ self.assertIsInstance(sample(), Set) self.assertTrue(issubclass(sample, Set)) self.validate_abstract_methods(Set, '__contains__', '__iter__', '__len__') + class MySet(Set): + def __contains__(self, x): + return False + def __len__(self): + return 0 + def __iter__(self): + return iter([]) + self.validate_comparison(MySet()) def test_hash_Set(self): class OneTwoThreeSet(Set): @@ -483,6 +522,14 @@ self.assertTrue(issubclass(sample, Mapping)) self.validate_abstract_methods(Mapping, '__contains__', '__iter__', '__len__', '__getitem__') + class MyMapping(collections.Mapping): + def __len__(self): + return 0 + def __getitem__(self, i): + raise IndexError + def __iter__(self): + return iter(()) + self.validate_comparison(MyMapping()) def test_MutableMapping(self): for sample in [dict]: Modified: python/branches/py3k-cdecimal/Lib/test/test_complex.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/test/test_complex.py (original) +++ python/branches/py3k-cdecimal/Lib/test/test_complex.py Mon Jun 7 12:46:02 2010 @@ -110,12 +110,18 @@ self.assertRaises(TypeError, complex.__floordiv__, 3+0j, 0+0j) def test_richcompare(self): - self.assertRaises(OverflowError, complex.__eq__, 1+1j, 1<<10000) + self.assertIs(complex.__eq__(1+1j, 1<<10000), False) self.assertIs(complex.__lt__(1+1j, None), NotImplemented) self.assertIs(complex.__eq__(1+1j, 1+1j), True) self.assertIs(complex.__eq__(1+1j, 2+2j), False) self.assertIs(complex.__ne__(1+1j, 1+1j), False) self.assertIs(complex.__ne__(1+1j, 2+2j), True) + for i in range(1, 100): + f = i / 100.0 + self.assertIs(complex.__eq__(f+0j, f), True) + self.assertIs(complex.__ne__(f+0j, f), False) + self.assertIs(complex.__eq__(complex(f, f), f), False) + self.assertIs(complex.__ne__(complex(f, f), f), True) self.assertIs(complex.__lt__(1+1j, 2+2j), NotImplemented) self.assertIs(complex.__le__(1+1j, 2+2j), NotImplemented) self.assertIs(complex.__gt__(1+1j, 2+2j), NotImplemented) @@ -129,6 +135,23 @@ self.assertIs(operator.ne(1+1j, 1+1j), False) self.assertIs(operator.ne(1+1j, 2+2j), True) + def test_richcompare_boundaries(self): + def check(n, deltas, is_equal, imag = 0.0): + for delta in deltas: + i = n + delta + z = complex(i, imag) + self.assertIs(complex.__eq__(z, i), is_equal(delta)) + self.assertIs(complex.__ne__(z, i), not is_equal(delta)) + # For IEEE-754 doubles the following should hold: + # x in [2 ** (52 + i), 2 ** (53 + i + 1)] -> x mod 2 ** i == 0 + # where the interval is representable, of course. + for i in range(1, 10): + pow = 52 + i + mult = 2 ** i + check(2 ** pow, range(1, 101), lambda delta: delta % mult == 0) + check(2 ** pow, range(1, 101), lambda delta: False, float(i)) + check(2 ** 53, range(-100, 0), lambda delta: True) + def test_mod(self): # % is no longer supported on complex numbers self.assertRaises(TypeError, (1+1j).__mod__, 0+0j) Modified: python/branches/py3k-cdecimal/Lib/test/test_datetime.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/test/test_datetime.py (original) +++ python/branches/py3k-cdecimal/Lib/test/test_datetime.py Mon Jun 7 12:46:02 2010 @@ -3,7 +3,7 @@ See http://www.zope.org/Members/fdrake/DateTimeWiki/TestCases """ -import os +import sys import pickle import unittest @@ -25,6 +25,16 @@ OTHERSTUFF = (10, 34.5, "abc", {}, [], ()) +# XXX Copied from test_float. +INF = float("inf") +NAN = float("nan") + +# decorator for skipping tests on non-IEEE 754 platforms +requires_IEEE_754 = unittest.skipUnless( + float.__getformat__("double").startswith("IEEE"), + "test requires IEEE 754 doubles") + + ############################################################################# # module tests @@ -225,6 +235,36 @@ eq(c//1000, td(0, 0, 1)) eq(a//10, td(0, 7*24*360)) eq(a//3600000, td(0, 0, 7*24*1000)) + eq(a/0.5, td(14)) + eq(b/0.5, td(0, 120)) + eq(a/7, td(1)) + eq(b/10, td(0, 6)) + eq(c/1000, td(0, 0, 1)) + eq(a/10, td(0, 7*24*360)) + eq(a/3600000, td(0, 0, 7*24*1000)) + + # Multiplication by float + us = td(microseconds=1) + eq((3*us) * 0.5, 2*us) + eq((5*us) * 0.5, 2*us) + eq(0.5 * (3*us), 2*us) + eq(0.5 * (5*us), 2*us) + eq((-3*us) * 0.5, -2*us) + eq((-5*us) * 0.5, -2*us) + + # Division by int and float + eq((3*us) / 2, 2*us) + eq((5*us) / 2, 2*us) + eq((-3*us) / 2.0, -2*us) + eq((-5*us) / 2.0, -2*us) + eq((3*us) / -2, -2*us) + eq((5*us) / -2, -2*us) + eq((3*us) / -2.0, -2*us) + eq((5*us) / -2.0, -2*us) + for i in range(-10, 10): + eq((i*us/3)//us, round(i/3)) + for i in range(-10, 10): + eq((i*us/-3)//us, round(i/-3)) def test_disallowed_computations(self): a = timedelta(42) @@ -236,20 +276,19 @@ self.assertRaises(TypeError, lambda: i+a) self.assertRaises(TypeError, lambda: i-a) - # Mul/div by float isn't supported. - x = 2.3 - self.assertRaises(TypeError, lambda: a*x) - self.assertRaises(TypeError, lambda: x*a) - self.assertRaises(TypeError, lambda: a/x) - self.assertRaises(TypeError, lambda: x/a) - self.assertRaises(TypeError, lambda: a // x) - self.assertRaises(TypeError, lambda: x // a) - # Division of int by timedelta doesn't make sense. # Division by zero doesn't make sense. zero = 0 self.assertRaises(TypeError, lambda: zero // a) self.assertRaises(ZeroDivisionError, lambda: a // zero) + self.assertRaises(ZeroDivisionError, lambda: a / zero) + self.assertRaises(ZeroDivisionError, lambda: a / 0.0) + + @requires_IEEE_754 + def test_disallowed_special(self): + a = timedelta(42) + self.assertRaises(ValueError, a.__mul__, NAN) + self.assertRaises(ValueError, a.__truediv__, NAN) def test_basic_attributes(self): days, seconds, us = 1, 7, 31 @@ -410,6 +449,19 @@ self.assertRaises(OverflowError, lambda: -timedelta.max) + day = timedelta(1) + self.assertRaises(OverflowError, day.__mul__, 10**9) + self.assertRaises(OverflowError, day.__mul__, 1e9) + self.assertRaises(OverflowError, day.__truediv__, 1e-20) + self.assertRaises(OverflowError, day.__truediv__, 1e-10) + self.assertRaises(OverflowError, day.__truediv__, 9e-10) + + @requires_IEEE_754 + def _test_overflow_special(self): + day = timedelta(1) + self.assertRaises(OverflowError, day.__mul__, INF) + self.assertRaises(OverflowError, day.__mul__, -INF) + def test_microsecond_rounding(self): td = timedelta eq = self.assertEqual @@ -489,7 +541,7 @@ self.assertRaises(ZeroDivisionError, truediv, t, zerotd) self.assertRaises(ZeroDivisionError, floordiv, t, zerotd) - self.assertRaises(TypeError, truediv, t, 2) + # self.assertRaises(TypeError, truediv, t, 2) # note: floor division of a timedelta by an integer *is* # currently permitted. @@ -761,15 +813,16 @@ def test_overflow(self): tiny = self.theclass.resolution - dt = self.theclass.min + tiny - dt -= tiny # no problem - self.assertRaises(OverflowError, dt.__sub__, tiny) - self.assertRaises(OverflowError, dt.__add__, -tiny) - - dt = self.theclass.max - tiny - dt += tiny # no problem - self.assertRaises(OverflowError, dt.__add__, tiny) - self.assertRaises(OverflowError, dt.__sub__, -tiny) + for delta in [tiny, timedelta(1), timedelta(2)]: + dt = self.theclass.min + delta + dt -= delta # no problem + self.assertRaises(OverflowError, dt.__sub__, delta) + self.assertRaises(OverflowError, dt.__add__, -delta) + + dt = self.theclass.max - delta + dt += delta # no problem + self.assertRaises(OverflowError, dt.__add__, delta) + self.assertRaises(OverflowError, dt.__sub__, -delta) def test_fromtimestamp(self): import time @@ -1554,19 +1607,14 @@ for insane in -1e200, 1e200: self.assertRaises(ValueError, self.theclass.utcfromtimestamp, insane) - + @unittest.skipIf(sys.platform == "win32", "Windows doesn't accept negative timestamps") def test_negative_float_fromtimestamp(self): - # Windows doesn't accept negative timestamps - if os.name == "nt": - return # The result is tz-dependent; at least test that this doesn't # fail (like it did before bug 1646728 was fixed). self.theclass.fromtimestamp(-1.05) + @unittest.skipIf(sys.platform == "win32", "Windows doesn't accept negative timestamps") def test_negative_float_utcfromtimestamp(self): - # Windows doesn't accept negative timestamps - if os.name == "nt": - return d = self.theclass.utcfromtimestamp(-1.05) self.assertEquals(d, self.theclass(1969, 12, 31, 23, 59, 58, 950000)) Modified: python/branches/py3k-cdecimal/Lib/test/test_decimal.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/test/test_decimal.py (original) +++ python/branches/py3k-cdecimal/Lib/test/test_decimal.py Mon Jun 7 12:46:02 2010 @@ -27,11 +27,13 @@ import math import os, sys import operator +import warnings import pickle, copy import unittest from decimal import * import numbers from test.support import run_unittest, run_doctest, is_resource_enabled +from test.support import check_warnings import random try: import threading @@ -412,7 +414,7 @@ def change_max_exponent(self, exp): self.context.Emax = exp def change_clamp(self, clamp): - self.context._clamp = clamp + self.context.clamp = clamp @@ -1815,6 +1817,26 @@ self.assertNotEqual(id(c.flags), id(d.flags)) self.assertNotEqual(id(c.traps), id(d.traps)) + def test__clamp(self): + # In Python 3.2, the private attribute `_clamp` was made + # public (issue 8540), with the old `_clamp` becoming a + # property wrapping `clamp`. For the duration of Python 3.2 + # only, the attribute should be gettable/settable via both + # `clamp` and `_clamp`; in Python 3.3, `_clamp` should be + # removed. + c = Context(clamp = 0) + self.assertEqual(c.clamp, 0) + + with check_warnings(("", DeprecationWarning)): + c._clamp = 1 + self.assertEqual(c.clamp, 1) + with check_warnings(("", DeprecationWarning)): + self.assertEqual(c._clamp, 1) + c.clamp = 0 + self.assertEqual(c.clamp, 0) + with check_warnings(("", DeprecationWarning)): + self.assertEqual(c._clamp, 0) + def test_abs(self): c = Context() d = c.abs(Decimal(-1)) Modified: python/branches/py3k-cdecimal/Lib/test/test_descr.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/test/test_descr.py (original) +++ python/branches/py3k-cdecimal/Lib/test/test_descr.py Mon Jun 7 12:46:02 2010 @@ -1557,6 +1557,8 @@ self.assertEqual(key, "hi") return 4 def swallow(*args): pass + def format_impl(self, spec): + return "hello" # It would be nice to have every special method tested here, but I'm # only listing the ones I can remember outside of typeobject.c, since it @@ -1575,6 +1577,7 @@ ("__enter__", run_context, iden, set(), {"__exit__" : swallow}), ("__exit__", run_context, swallow, set(), {"__enter__" : iden}), ("__complex__", complex, complex_num, set(), {}), + ("__format__", format, format_impl, set(), {}), ] class Checker(object): Modified: python/branches/py3k-cdecimal/Lib/test/test_enumerate.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/test/test_enumerate.py (original) +++ python/branches/py3k-cdecimal/Lib/test/test_enumerate.py Mon Jun 7 12:46:02 2010 @@ -198,6 +198,18 @@ self.fail("non-callable __reversed__ didn't raise!") self.assertEqual(rc, sys.getrefcount(r)) + def test_objmethods(self): + # Objects must have __len__() and __getitem__() implemented. + class NoLen(object): + def __getitem__(self): return 1 + nl = NoLen() + self.assertRaises(TypeError, reversed, nl) + + class NoGetItem(object): + def __len__(self): return 2 + ngi = NoGetItem() + self.assertRaises(TypeError, reversed, ngi) + class EnumerateStartTestCase(EnumerateTestCase): @@ -227,7 +239,7 @@ if verbose and hasattr(sys, "gettotalrefcount"): counts = [None] * 5 for i in range(len(counts)): - support.run_unittest(*testclasses) + support.run_unittest(__name__) counts[i] = sys.gettotalrefcount() print(counts) Modified: python/branches/py3k-cdecimal/Lib/test/test_float.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/test/test_float.py (original) +++ python/branches/py3k-cdecimal/Lib/test/test_float.py Mon Jun 7 12:46:02 2010 @@ -914,15 +914,6 @@ self.assertFalse(NAN.is_inf()) self.assertFalse((0.).is_inf()) - def test_hash_inf(self): - # the actual values here should be regarded as an - # implementation detail, but they need to be - # identical to those used in the Decimal module. - self.assertEqual(hash(float('inf')), 314159) - self.assertEqual(hash(float('-inf')), -271828) - self.assertEqual(hash(float('nan')), 0) - - fromHex = float.fromhex toHex = float.hex class HexFloatTestCase(unittest.TestCase): Modified: python/branches/py3k-cdecimal/Lib/test/test_ftplib.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/test/test_ftplib.py (original) +++ python/branches/py3k-cdecimal/Lib/test/test_ftplib.py Mon Jun 7 12:46:02 2010 @@ -719,6 +719,29 @@ finally: self.client.ssl_version = ssl.PROTOCOL_TLSv1 + def test_context(self): + self.client.quit() + ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) + self.assertRaises(ValueError, ftplib.FTP_TLS, keyfile=CERTFILE, + context=ctx) + self.assertRaises(ValueError, ftplib.FTP_TLS, certfile=CERTFILE, + context=ctx) + self.assertRaises(ValueError, ftplib.FTP_TLS, certfile=CERTFILE, + keyfile=CERTFILE, context=ctx) + + self.client = ftplib.FTP_TLS(context=ctx, timeout=2) + self.client.connect(self.server.host, self.server.port) + self.assertNotIsInstance(self.client.sock, ssl.SSLSocket) + self.client.auth() + self.assertIs(self.client.sock.context, ctx) + self.assertIsInstance(self.client.sock, ssl.SSLSocket) + + self.client.prot_p() + sock = self.client.transfercmd('list') + self.assertIs(sock.context, ctx) + self.assertIsInstance(sock, ssl.SSLSocket) + sock.close() + class TestTimeouts(TestCase): Modified: python/branches/py3k-cdecimal/Lib/test/test_gdb.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/test/test_gdb.py (original) +++ python/branches/py3k-cdecimal/Lib/test/test_gdb.py Mon Jun 7 12:46:02 2010 @@ -8,6 +8,7 @@ import subprocess import sys import unittest +import locale from test.support import run_unittest, findfile @@ -177,7 +178,7 @@ def assertGdbRepr(self, val, exp_repr=None, cmds_after_breakpoint=None): # Ensure that gdb's rendering of the value in a debugged process # matches repr(value) in this process: - gdb_repr, gdb_output = self.get_gdb_repr('id(' + repr(val) + ')', + gdb_repr, gdb_output = self.get_gdb_repr('id(' + ascii(val) + ')', cmds_after_breakpoint) if not exp_repr: exp_repr = repr(val) @@ -226,31 +227,35 @@ def test_strings(self): 'Verify the pretty-printing of unicode strings' + encoding = locale.getpreferredencoding() + def check_repr(text): + try: + text.encode(encoding) + printable = True + except UnicodeEncodeError: + self.assertGdbRepr(text, ascii(text)) + else: + self.assertGdbRepr(text) + self.assertGdbRepr('') self.assertGdbRepr('And now for something hopefully the same') self.assertGdbRepr('string with embedded NUL here \0 and then some more text') # Test printing a single character: # U+2620 SKULL AND CROSSBONES - self.assertGdbRepr('\u2620') + check_repr('\u2620') # Test printing a Japanese unicode string # (I believe this reads "mojibake", using 3 characters from the CJK # Unified Ideographs area, followed by U+3051 HIRAGANA LETTER KE) - self.assertGdbRepr('\u6587\u5b57\u5316\u3051') + check_repr('\u6587\u5b57\u5316\u3051') # Test a character outside the BMP: # U+1D121 MUSICAL SYMBOL C CLEF # This is: # UTF-8: 0xF0 0x9D 0x84 0xA1 # UTF-16: 0xD834 0xDD21 - if sys.maxunicode == 0x10FFFF: - # wide unicode: - self.assertGdbRepr(chr(0x1D121)) - else: - # narrow unicode: - self.assertGdbRepr(chr(0x1D121), - "'\\U0000d834\\U0000dd21'") + check_repr(chr(0x1D121)) def test_tuples(self): 'Verify the pretty-printing of tuples' Modified: python/branches/py3k-cdecimal/Lib/test/test_htmlparser.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/test/test_htmlparser.py (original) +++ python/branches/py3k-cdecimal/Lib/test/test_htmlparser.py Mon Jun 7 12:46:02 2010 @@ -136,6 +136,13 @@ ("data", "\n"), ]) + def test_malformatted_charref(self): + self._run_check("

&#bad;

", [ + ("starttag", "p", []), + ("data", "&#bad;"), + ("endtag", "p"), + ]) + def test_unclosed_entityref(self): self._run_check("&entityref foo", [ ("entityref", "entityref"), Modified: python/branches/py3k-cdecimal/Lib/test/test_httplib.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/test/test_httplib.py (original) +++ python/branches/py3k-cdecimal/Lib/test/test_httplib.py Mon Jun 7 12:46:02 2010 @@ -239,7 +239,7 @@ self.assertEquals(resp.read(), b'') self.assertEquals(resp.status, 200) self.assertEquals(resp.reason, 'OK') - resp.close() + self.assertTrue(resp.isclosed()) def test_negative_content_length(self): sock = FakeSocket( Modified: python/branches/py3k-cdecimal/Lib/test/test_linecache.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/test/test_linecache.py (original) +++ python/branches/py3k-cdecimal/Lib/test/test_linecache.py Mon Jun 7 12:46:02 2010 @@ -31,6 +31,11 @@ ''' +SOURCE_3 = ''' +def f(): + return 3''' # No ending newline + + class LineCacheTests(unittest.TestCase): def test_getline(self): @@ -63,6 +68,13 @@ empty = linecache.getlines('a/b/c/__init__.py') self.assertEquals(empty, []) + def test_no_ending_newline(self): + self.addCleanup(support.unlink, support.TESTFN) + with open(support.TESTFN, "w") as fp: + fp.write(SOURCE_3) + lines = linecache.getlines(support.TESTFN) + self.assertEqual(lines, ["\n", "def f():\n", " return 3\n"]) + def test_clearcache(self): cached = [] for entry in TESTS: @@ -81,39 +93,36 @@ def test_checkcache(self): getline = linecache.getline - try: - # Create a source file and cache its contents - source_name = support.TESTFN + '.py' - with open(source_name, 'w') as source: - source.write(SOURCE_1) - getline(source_name, 1) - - # Keep a copy of the old contents - source_list = [] - with open(source_name) as source: - for index, line in enumerate(source): - self.assertEquals(line, getline(source_name, index + 1)) - source_list.append(line) + # Create a source file and cache its contents + source_name = support.TESTFN + '.py' + self.addCleanup(support.unlink, source_name) + with open(source_name, 'w') as source: + source.write(SOURCE_1) + getline(source_name, 1) + + # Keep a copy of the old contents + source_list = [] + with open(source_name) as source: + for index, line in enumerate(source): + self.assertEquals(line, getline(source_name, index + 1)) + source_list.append(line) - with open(source_name, 'w') as source: - source.write(SOURCE_2) + with open(source_name, 'w') as source: + source.write(SOURCE_2) - # Try to update a bogus cache entry - linecache.checkcache('dummy') + # Try to update a bogus cache entry + linecache.checkcache('dummy') - # Check that the cache matches the old contents - for index, line in enumerate(source_list): + # Check that the cache matches the old contents + for index, line in enumerate(source_list): + self.assertEquals(line, getline(source_name, index + 1)) + + # Update the cache and check whether it matches the new source file + linecache.checkcache(source_name) + with open(source_name) as source: + for index, line in enumerate(source): self.assertEquals(line, getline(source_name, index + 1)) - - # Update the cache and check whether it matches the new source file - linecache.checkcache(source_name) - with open(source_name) as source: - for index, line in enumerate(source): - self.assertEquals(line, getline(source_name, index + 1)) - source_list.append(line) - - finally: - support.unlink(source_name) + source_list.append(line) def test_main(): support.run_unittest(LineCacheTests) Modified: python/branches/py3k-cdecimal/Lib/test/test_long.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/test/test_long.py (original) +++ python/branches/py3k-cdecimal/Lib/test/test_long.py Mon Jun 7 12:46:02 2010 @@ -330,6 +330,31 @@ # ... but it's just a normal digit if base >= 22 self.assertEqual(int('1L', 22), 43) + # tests with base 0 + self.assertEqual(int('000', 0), 0) + self.assertEqual(int('0o123', 0), 83) + self.assertEqual(int('0x123', 0), 291) + self.assertEqual(int('0b100', 0), 4) + self.assertEqual(int(' 0O123 ', 0), 83) + self.assertEqual(int(' 0X123 ', 0), 291) + self.assertEqual(int(' 0B100 ', 0), 4) + self.assertEqual(int('0', 0), 0) + self.assertEqual(int('+0', 0), 0) + self.assertEqual(int('-0', 0), 0) + self.assertEqual(int('00', 0), 0) + self.assertRaises(ValueError, int, '08', 0) + self.assertRaises(ValueError, int, '-012395', 0) + + # invalid bases + invalid_bases = [-909, + 2**31-1, 2**31, -2**31, -2**31-1, + 2**63-1, 2**63, -2**63, -2**63-1, + 2**100, -2**100, + ] + for base in invalid_bases: + self.assertRaises(ValueError, int, '42', base) + + def test_conversion(self): class JustLong: Modified: python/branches/py3k-cdecimal/Lib/test/test_os.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/test/test_os.py (original) +++ python/branches/py3k-cdecimal/Lib/test/test_os.py Mon Jun 7 12:46:02 2010 @@ -933,20 +933,64 @@ @unittest.skipUnless(sys.platform == "win32", "Win32 specific tests") class Win32KillTests(unittest.TestCase): - def _kill(self, sig, *args): - # Send a subprocess a signal (or in some cases, just an int to be - # the return value) - proc = subprocess.Popen(*args) + def _kill(self, sig): + # Start sys.executable as a subprocess and communicate from the + # subprocess to the parent that the interpreter is ready. When it + # becomes ready, send *sig* via os.kill to the subprocess and check + # that the return code is equal to *sig*. + import ctypes + from ctypes import wintypes + import msvcrt + + # Since we can't access the contents of the process' stdout until the + # process has exited, use PeekNamedPipe to see what's inside stdout + # without waiting. This is done so we can tell that the interpreter + # is started and running at a point where it could handle a signal. + PeekNamedPipe = ctypes.windll.kernel32.PeekNamedPipe + PeekNamedPipe.restype = wintypes.BOOL + PeekNamedPipe.argtypes = (wintypes.HANDLE, # Pipe handle + ctypes.POINTER(ctypes.c_char), # stdout buf + wintypes.DWORD, # Buffer size + ctypes.POINTER(wintypes.DWORD), # bytes read + ctypes.POINTER(wintypes.DWORD), # bytes avail + ctypes.POINTER(wintypes.DWORD)) # bytes left + msg = "running" + proc = subprocess.Popen([sys.executable, "-c", + "import sys;" + "sys.stdout.write('{}');" + "sys.stdout.flush();" + "input()".format(msg)], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + stdin=subprocess.PIPE) + + count, max = 0, 100 + while count < max and proc.poll() is None: + # Create a string buffer to store the result of stdout from the pipe + buf = ctypes.create_string_buffer(len(msg)) + # Obtain the text currently in proc.stdout + # Bytes read/avail/left are left as NULL and unused + rslt = PeekNamedPipe(msvcrt.get_osfhandle(proc.stdout.fileno()), + buf, ctypes.sizeof(buf), None, None, None) + self.assertNotEqual(rslt, 0, "PeekNamedPipe failed") + if buf.value: + self.assertEqual(msg, buf.value.decode()) + break + time.sleep(0.1) + count += 1 + else: + self.fail("Did not receive communication from the subprocess") + os.kill(proc.pid, sig) self.assertEqual(proc.wait(), sig) def test_kill_sigterm(self): # SIGTERM doesn't mean anything special, but make sure it works - self._kill(signal.SIGTERM, [sys.executable]) + self._kill(signal.SIGTERM) def test_kill_int(self): # os.kill on Windows can take an int which gets set as the exit code - self._kill(100, [sys.executable]) + self._kill(100) def _kill_with_event(self, event, name): # Run a script which has console control handling enabled. Modified: python/branches/py3k-cdecimal/Lib/test/test_pipes.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/test/test_pipes.py (original) +++ python/branches/py3k-cdecimal/Lib/test/test_pipes.py Mon Jun 7 12:46:02 2010 @@ -70,9 +70,10 @@ self.assertEqual(open(TESTFN).read(), d) def testQuoting(self): - safeunquoted = string.ascii_letters + string.digits + '!@%_-+=:,./' - unsafe = '"`$\\' + safeunquoted = string.ascii_letters + string.digits + '@%_-+=:,./' + unsafe = '"`$\\!' + self.assertEqual(pipes.quote(''), "''") self.assertEqual(pipes.quote(safeunquoted), safeunquoted) self.assertEqual(pipes.quote('test file name'), "'test file name'") for u in unsafe: @@ -80,9 +81,7 @@ "'test%sname'" % u) for u in unsafe: self.assertEqual(pipes.quote("test%s'name'" % u), - '"test\\%s\'name\'"' % u) - - self.assertEqual(pipes.quote(''), "''") + "'test%s'\"'\"'name'\"'\"''" % u) def testRepr(self): t = pipes.Template() Modified: python/branches/py3k-cdecimal/Lib/test/test_socketserver.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/test/test_socketserver.py (original) +++ python/branches/py3k-cdecimal/Lib/test/test_socketserver.py Mon Jun 7 12:46:02 2010 @@ -61,6 +61,7 @@ testcase.assertEquals(72 << 8, status) + at unittest.skipUnless(threading, 'Threading required for this test.') class SocketServerTest(unittest.TestCase): """Test all socket servers.""" Modified: python/branches/py3k-cdecimal/Lib/test/test_ssl.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/test/test_ssl.py (original) +++ python/branches/py3k-cdecimal/Lib/test/test_ssl.py Mon Jun 7 12:46:02 2010 @@ -57,6 +57,14 @@ if support.verbose: sys.stdout.write(prefix + exc_format) +def can_clear_options(): + # 0.9.8m or higher + return ssl.OPENSSL_VERSION_INFO >= (0, 9, 8, 13, 15) + +def no_sslv2_implies_sslv3_hello(): + # 0.9.7h or higher + return ssl.OPENSSL_VERSION_INFO >= (0, 9, 7, 8, 15) + class BasicSocketTests(unittest.TestCase): @@ -189,6 +197,26 @@ with self.assertRaisesRegexp(ssl.SSLError, "No cipher can be selected"): ctx.set_ciphers("^$:,;?*'dorothyx") + def test_options(self): + ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) + # OP_ALL is the default value + self.assertEqual(ssl.OP_ALL, ctx.options) + ctx.options |= ssl.OP_NO_SSLv2 + self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2, + ctx.options) + ctx.options |= ssl.OP_NO_SSLv3 + self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3, + ctx.options) + if can_clear_options(): + ctx.options = (ctx.options & ~ssl.OP_NO_SSLv2) | ssl.OP_NO_TLSv1 + self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3, + ctx.options) + ctx.options = 0 + self.assertEqual(0, ctx.options) + else: + with self.assertRaises(ValueError): + ctx.options = 0 + def test_verify(self): ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) # Default value @@ -445,12 +473,8 @@ def wrap_conn(self): try: - self.sslconn = ssl.wrap_socket(self.sock, server_side=True, - certfile=self.server.certificate, - ssl_version=self.server.protocol, - ca_certs=self.server.cacerts, - cert_reqs=self.server.certreqs, - ciphers=self.server.ciphers) + self.sslconn = self.server.context.wrap_socket( + self.sock, server_side=True) except ssl.SSLError: # XXX Various errors can have happened here, for example # a mismatching protocol version, an invalid certificate, @@ -462,7 +486,7 @@ self.close() return False else: - if self.server.certreqs == ssl.CERT_REQUIRED: + if self.server.context.verify_mode == ssl.CERT_REQUIRED: cert = self.sslconn.getpeercert() if support.verbose and self.server.chatty: sys.stdout.write(" client cert is " + pprint.pformat(cert) + "\n") @@ -542,19 +566,24 @@ # harness, we want to stop the server self.server.stop() - def __init__(self, certificate, ssl_version=None, + def __init__(self, certificate=None, ssl_version=None, certreqs=None, cacerts=None, chatty=True, connectionchatty=False, starttls_server=False, - ciphers=None): - if ssl_version is None: - ssl_version = ssl.PROTOCOL_TLSv1 - if certreqs is None: - certreqs = ssl.CERT_NONE - self.certificate = certificate - self.protocol = ssl_version - self.certreqs = certreqs - self.cacerts = cacerts - self.ciphers = ciphers + ciphers=None, context=None): + if context: + self.context = context + else: + self.context = ssl.SSLContext(ssl_version + if ssl_version is not None + else ssl.PROTOCOL_TLSv1) + self.context.verify_mode = (certreqs if certreqs is not None + else ssl.CERT_NONE) + if cacerts: + self.context.load_verify_locations(cacerts) + if certificate: + self.context.load_cert_chain(certificate) + if ciphers: + self.context.set_ciphers(ciphers) self.chatty = chatty self.connectionchatty = connectionchatty self.starttls_server = starttls_server @@ -820,18 +849,13 @@ server.stop() server.join() - def server_params_test(certfile, protocol, certreqs, cacertsfile, - client_certfile, client_protocol=None, indata=b"FOO\n", - ciphers=None, chatty=True, connectionchatty=False): + def server_params_test(client_context, server_context, indata=b"FOO\n", + chatty=True, connectionchatty=False): """ Launch a server, connect a client to it and try various reads and writes. """ - server = ThreadedEchoServer(certfile, - certreqs=certreqs, - ssl_version=protocol, - cacerts=cacertsfile, - ciphers=ciphers, + server = ThreadedEchoServer(context=server_context, chatty=chatty, connectionchatty=False) flag = threading.Event() @@ -839,15 +863,8 @@ # wait for it to start flag.wait() # try to connect - if client_protocol is None: - client_protocol = protocol try: - s = ssl.wrap_socket(socket.socket(), - certfile=client_certfile, - ca_certs=cacertsfile, - ciphers=ciphers, - cert_reqs=certreqs, - ssl_version=client_protocol) + s = client_context.wrap_socket(socket.socket()) s.connect((HOST, server.port)) for arg in [indata, bytearray(indata), memoryview(indata)]: if connectionchatty: @@ -873,10 +890,8 @@ server.stop() server.join() - def try_protocol_combo(server_protocol, - client_protocol, - expect_success, - certsreqs=None): + def try_protocol_combo(server_protocol, client_protocol, expect_success, + certsreqs=None, server_options=0, client_options=0): if certsreqs is None: certsreqs = ssl.CERT_NONE certtype = { @@ -890,14 +905,21 @@ (ssl.get_protocol_name(client_protocol), ssl.get_protocol_name(server_protocol), certtype)) - try: + client_context = ssl.SSLContext(client_protocol) + client_context.options = ssl.OP_ALL | client_options + server_context = ssl.SSLContext(server_protocol) + server_context.options = ssl.OP_ALL | server_options + for ctx in (client_context, server_context): + ctx.verify_mode = certsreqs # NOTE: we must enable "ALL" ciphers, otherwise an SSLv23 client # will send an SSLv3 hello (rather than SSLv2) starting from # OpenSSL 1.0.0 (see issue #8322). - server_params_test(CERTFILE, server_protocol, certsreqs, - CERTFILE, CERTFILE, client_protocol, - ciphers="ALL", chatty=False, - connectionchatty=False) + ctx.set_ciphers("ALL") + ctx.load_cert_chain(CERTFILE) + ctx.load_verify_locations(CERTFILE) + try: + server_params_test(client_context, server_context, + chatty=False, connectionchatty=False) # Protocol mismatch can result in either an SSLError, or a # "Connection reset by peer" error. except ssl.SSLError: @@ -920,30 +942,27 @@ """Basic test of an SSL client connecting to a server""" if support.verbose: sys.stdout.write("\n") - server_params_test(CERTFILE, ssl.PROTOCOL_TLSv1, ssl.CERT_NONE, - CERTFILE, CERTFILE, ssl.PROTOCOL_TLSv1, - chatty=True, connectionchatty=True) + for protocol in PROTOCOLS: + context = ssl.SSLContext(protocol) + context.load_cert_chain(CERTFILE) + server_params_test(context, context, + chatty=True, connectionchatty=True) def test_getpeercert(self): if support.verbose: sys.stdout.write("\n") - s2 = socket.socket() - server = ThreadedEchoServer(CERTFILE, - certreqs=ssl.CERT_NONE, - ssl_version=ssl.PROTOCOL_SSLv23, - cacerts=CERTFILE, - chatty=False) + context = ssl.SSLContext(ssl.PROTOCOL_SSLv23) + context.verify_mode = ssl.CERT_REQUIRED + context.load_verify_locations(CERTFILE) + context.load_cert_chain(CERTFILE) + server = ThreadedEchoServer(context=context, chatty=False) flag = threading.Event() server.start(flag) # wait for it to start flag.wait() # try to connect try: - s = ssl.wrap_socket(socket.socket(), - certfile=CERTFILE, - ca_certs=CERTFILE, - cert_reqs=ssl.CERT_REQUIRED, - ssl_version=ssl.PROTOCOL_SSLv23) + s = context.wrap_socket(socket.socket()) s.connect((HOST, server.port)) cert = s.getpeercert() self.assertTrue(cert, "Can't get peer certificate.") @@ -1031,6 +1050,15 @@ try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True) try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False) try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False) + # SSLv23 client with specific SSL options + if no_sslv2_implies_sslv3_hello(): + # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs + try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False, + client_options=ssl.OP_NO_SSLv2) + try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True, + client_options=ssl.OP_NO_SSLv3) + try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True, + client_options=ssl.OP_NO_TLSv1) def test_protocol_sslv23(self): """Connecting to an SSLv23 server with various client options""" @@ -1056,6 +1084,16 @@ try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, ssl.CERT_REQUIRED) try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED) + # Server with specific SSL options + try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, False, + server_options=ssl.OP_NO_SSLv3) + # Will choose TLSv1 + try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True, + server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3) + try_protocol_combo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, False, + server_options=ssl.OP_NO_TLSv1) + + def test_protocol_sslv3(self): """Connecting to an SSLv3 server with various client options""" if support.verbose: @@ -1066,6 +1104,10 @@ try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False) try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False) try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False) + if no_sslv2_implies_sslv3_hello(): + # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs + try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, True, + client_options=ssl.OP_NO_SSLv2) def test_protocol_tlsv1(self): """Connecting to a TLSv1 server with various client options""" Modified: python/branches/py3k-cdecimal/Lib/test/test_subprocess.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/test/test_subprocess.py (original) +++ python/branches/py3k-cdecimal/Lib/test/test_subprocess.py Mon Jun 7 12:46:02 2010 @@ -535,6 +535,17 @@ if c.exception.errno != 2: # ignore "no such file" raise c.exception + def test_issue8780(self): + # Ensure that stdout is inherited from the parent + # if stdout=PIPE is not used + code = ';'.join(( + 'import subprocess, sys', + 'retcode = subprocess.call(' + "[sys.executable, '-c', 'print(\"Hello World!\")'])", + 'assert retcode == 0')) + output = subprocess.check_output([sys.executable, '-c', code]) + self.assert_(output.startswith(b'Hello World!'), ascii(output)) + # context manager class _SuppressCoreFiles(object): Modified: python/branches/py3k-cdecimal/Lib/test/test_sys.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/test/test_sys.py (original) +++ python/branches/py3k-cdecimal/Lib/test/test_sys.py Mon Jun 7 12:46:02 2010 @@ -146,9 +146,9 @@ "raise SystemExit(47)"]) self.assertEqual(rc, 47) - def check_exit_message(code, expected): + def check_exit_message(code, expected, env=None): process = subprocess.Popen([sys.executable, "-c", code], - stderr=subprocess.PIPE) + stderr=subprocess.PIPE, env=env) stdout, stderr = process.communicate() self.assertEqual(process.returncode, 1) self.assertTrue(stderr.startswith(expected), @@ -166,6 +166,14 @@ r'import sys; sys.exit("surrogates:\uDCFF")', b"surrogates:\\udcff") + # test that the unicode message is encoded to the stderr encoding + # instead of the default encoding (utf8) + env = os.environ.copy() + env['PYTHONIOENCODING'] = 'latin-1' + check_exit_message( + r'import sys; sys.exit("h\xe9")', + b"h\xe9", env=env) + def test_getdefaultencoding(self): self.assertRaises(TypeError, sys.getdefaultencoding, 42) # can't check more than the type, as the user might have changed it @@ -418,6 +426,23 @@ self.assertEqual(type(sys.int_info.bits_per_digit), int) self.assertEqual(type(sys.int_info.sizeof_digit), int) self.assertIsInstance(sys.hexversion, int) + + self.assertEqual(len(sys.hash_info), 5) + self.assertLess(sys.hash_info.modulus, 2**sys.hash_info.width) + # sys.hash_info.modulus should be a prime; we do a quick + # probable primality test (doesn't exclude the possibility of + # a Carmichael number) + for x in range(1, 100): + self.assertEqual( + pow(x, sys.hash_info.modulus-1, sys.hash_info.modulus), + 1, + "sys.hash_info.modulus {} is a non-prime".format( + sys.hash_info.modulus) + ) + self.assertIsInstance(sys.hash_info.inf, int) + self.assertIsInstance(sys.hash_info.nan, int) + self.assertIsInstance(sys.hash_info.imag, int) + self.assertIsInstance(sys.maxsize, int) self.assertIsInstance(sys.maxunicode, int) self.assertIsInstance(sys.platform, str) Modified: python/branches/py3k-cdecimal/Lib/test/test_sysconfig.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/test/test_sysconfig.py (original) +++ python/branches/py3k-cdecimal/Lib/test/test_sysconfig.py Mon Jun 7 12:46:02 2010 @@ -11,13 +11,14 @@ import shutil from copy import copy, deepcopy -from test.support import run_unittest, TESTFN, unlink, get_attribute +from test.support import (run_unittest, TESTFN, unlink, get_attribute, + captured_stdout) import sysconfig from sysconfig import (get_paths, get_platform, get_config_vars, get_path, get_path_names, _INSTALL_SCHEMES, _get_default_scheme, _expand_vars, - get_scheme_names) + get_scheme_names, get_config_var, _main) class TestSysConfig(unittest.TestCase): @@ -254,6 +255,22 @@ finally: unlink(link) + def test_user_similar(self): + # Issue 8759 : make sure the posix scheme for the users + # is similar to the global posix_prefix one + base = get_config_var('base') + user = get_config_var('userbase') + for name in ('stdlib', 'platstdlib', 'purelib', 'platlib'): + global_path = get_path(name, 'posix_prefix') + user_path = get_path(name, 'posix_user') + self.assertEquals(user_path, global_path.replace(base, user)) + + def test_main(self): + # just making sure _main() runs and returns things in the stdout + with captured_stdout() as output: + _main() + self.assertTrue(len(output.getvalue().split('\n')) > 0) + def test_main(): run_unittest(TestSysConfig) Modified: python/branches/py3k-cdecimal/Lib/test/test_tarfile.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/test/test_tarfile.py (original) +++ python/branches/py3k-cdecimal/Lib/test/test_tarfile.py Mon Jun 7 12:46:02 2010 @@ -133,6 +133,26 @@ "read() after readline() failed") fobj.close() + # Test if symbolic and hard links are resolved by extractfile(). The + # test link members each point to a regular member whose data is + # supposed to be exported. + def _test_fileobj_link(self, lnktype, regtype): + a = self.tar.extractfile(lnktype) + b = self.tar.extractfile(regtype) + self.assertEqual(a.name, b.name) + + def test_fileobj_link1(self): + self._test_fileobj_link("ustar/lnktype", "ustar/regtype") + + def test_fileobj_link2(self): + self._test_fileobj_link("./ustar/linktest2/lnktype", "ustar/linktest1/regtype") + + def test_fileobj_symlink1(self): + self._test_fileobj_link("ustar/symtype", "ustar/regtype") + + def test_fileobj_symlink2(self): + self._test_fileobj_link("./ustar/linktest2/symtype", "ustar/linktest1/regtype") + class CommonReadTest(ReadTest): @@ -661,10 +681,14 @@ if hasattr(os, "link"): link = os.path.join(TEMPDIR, "link") target = os.path.join(TEMPDIR, "link_target") - open(target, "wb").close() + fobj = open(target, "wb") + fobj.write(b"aaa") + fobj.close() os.link(target, link) try: tar = tarfile.open(tmpname, self.mode) + # Record the link target in the inodes list. + tar.gettarinfo(target) tarinfo = tar.gettarinfo(link) self.assertEqual(tarinfo.size, 0) finally: @@ -1374,6 +1398,29 @@ fobj.close() +class LinkEmulationTest(ReadTest): + + # Test for issue #8741 regression. On platforms that do not support + # symbolic or hard links tarfile tries to extract these types of members as + # the regular files they point to. + def _test_link_extraction(self, name): + self.tar.extract(name, TEMPDIR) + data = open(os.path.join(TEMPDIR, name), "rb").read() + self.assertEqual(md5sum(data), md5_regtype) + + def test_hardlink_extraction1(self): + self._test_link_extraction("ustar/lnktype") + + def test_hardlink_extraction2(self): + self._test_link_extraction("./ustar/linktest2/lnktype") + + def test_symlink_extraction1(self): + self._test_link_extraction("ustar/symtype") + + def test_symlink_extraction2(self): + self._test_link_extraction("./ustar/linktest2/symtype") + + class GzipMiscReadTest(MiscReadTest): tarname = gzipname mode = "r:gz" @@ -1459,6 +1506,8 @@ if hasattr(os, "link"): tests.append(HardlinkTest) + else: + tests.append(LinkEmulationTest) fobj = open(tarname, "rb") data = fobj.read() Modified: python/branches/py3k-cdecimal/Lib/test/test_tcl.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/test/test_tcl.py (original) +++ python/branches/py3k-cdecimal/Lib/test/test_tcl.py Mon Jun 7 12:46:02 2010 @@ -127,6 +127,31 @@ tcl = self.interp self.assertRaises(TclError,tcl.eval,'package require DNE') + def testLoadWithUNC(self): + import sys + if sys.platform != 'win32': + return + + # Build a UNC path from the regular path. + # Something like + # \\%COMPUTERNAME%\c$\python27\python.exe + + fullname = os.path.abspath(sys.executable) + if fullname[1] != ':': + return + unc_name = r'\\%s\%s$\%s' % (os.environ['COMPUTERNAME'], + fullname[0], + fullname[3:]) + + with test_support.EnvironmentVarGuard() as env: + env.unset("TCL_LIBRARY") + f = os.popen('%s -c "import Tkinter; print Tkinter"' % (unc_name,)) + + self.assert_('Tkinter.py' in f.read()) + # exit code must be zero + self.assertEqual(f.close(), None) + + def test_main(): support.run_unittest(TclTest, TkinterTest) Modified: python/branches/py3k-cdecimal/Lib/test/test_urllib2.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/test/test_urllib2.py (original) +++ python/branches/py3k-cdecimal/Lib/test/test_urllib2.py Mon Jun 7 12:46:02 2010 @@ -1151,7 +1151,6 @@ self.assertEqual(len(http_handler.requests), 1) self.assertFalse(http_handler.requests[0].has_header(auth_header)) - class MiscTests(unittest.TestCase): def test_build_opener(self): Modified: python/branches/py3k-cdecimal/Lib/test/test_warnings.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/test/test_warnings.py (original) +++ python/branches/py3k-cdecimal/Lib/test/test_warnings.py Mon Jun 7 12:46:02 2010 @@ -738,20 +738,38 @@ module = py_warnings +class BootstrapTest(unittest.TestCase): + def test_issue_8766(self): + # "import encodings" emits a warning whereas the warnings is not loaded + # or not completly loaded (warnings imports indirectly encodings by + # importing linecache) yet + with support.temp_cwd() as cwd, support.temp_cwd('encodings'): + env = os.environ.copy() + env['PYTHONPATH'] = cwd + + # encodings loaded by initfsencoding() + retcode = subprocess.call([sys.executable, '-c', 'pass'], env=env) + self.assertEqual(retcode, 0) + + # Use -W to load warnings module at startup + retcode = subprocess.call( + [sys.executable, '-c', 'pass', '-W', 'always'], + env=env) + self.assertEqual(retcode, 0) + def test_main(): py_warnings.onceregistry.clear() c_warnings.onceregistry.clear() - support.run_unittest(CFilterTests, - PyFilterTests, - CWarnTests, - PyWarnTests, - CWCmdLineTests, PyWCmdLineTests, - _WarningsTests, - CWarningsDisplayTests, PyWarningsDisplayTests, - CCatchWarningTests, PyCatchWarningTests, - CEnvironmentVariableTests, - PyEnvironmentVariableTests - ) + support.run_unittest( + CFilterTests, PyFilterTests, + CWarnTests, PyWarnTests, + CWCmdLineTests, PyWCmdLineTests, + _WarningsTests, + CWarningsDisplayTests, PyWarningsDisplayTests, + CCatchWarningTests, PyCatchWarningTests, + CEnvironmentVariableTests, PyEnvironmentVariableTests, + BootstrapTest, + ) if __name__ == "__main__": Modified: python/branches/py3k-cdecimal/Lib/test/test_winreg.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/test/test_winreg.py (original) +++ python/branches/py3k-cdecimal/Lib/test/test_winreg.py Mon Jun 7 12:46:02 2010 @@ -5,6 +5,7 @@ import os, sys import unittest from test import support +threading = support.import_module("threading") from platform import machine # Do this first so test will be skipped if module doesn't exist @@ -227,6 +228,58 @@ except WindowsError: self.assertEqual(h.handle, 0) + def test_changing_value(self): + # Issue2810: A race condition in 2.6 and 3.1 may cause + # EnumValue or QueryValue to throw "WindowsError: More data is + # available" + done = False + + class VeryActiveThread(threading.Thread): + def run(self): + with CreateKey(HKEY_CURRENT_USER, test_key_name) as key: + use_short = True + long_string = 'x'*2000 + while not done: + s = 'x' if use_short else long_string + use_short = not use_short + SetValue(key, 'changing_value', REG_SZ, s) + + thread = VeryActiveThread() + thread.start() + try: + with CreateKey(HKEY_CURRENT_USER, + test_key_name+'\\changing_value') as key: + for _ in range(1000): + num_subkeys, num_values, t = QueryInfoKey(key) + for i in range(num_values): + name = EnumValue(key, i) + QueryValue(key, name[0]) + finally: + done = True + thread.join() + DeleteKey(HKEY_CURRENT_USER, test_key_name+'\\changing_value') + DeleteKey(HKEY_CURRENT_USER, test_key_name) + + def test_long_key(self): + # Issue2810, in 2.6 and 3.1 when the key name was exactly 256 + # characters, EnumKey threw "WindowsError: More data is + # available" + name = 'x'*256 + try: + with CreateKey(HKEY_CURRENT_USER, test_key_name) as key: + SetValue(key, name, REG_SZ, 'x') + num_subkeys, num_values, t = QueryInfoKey(key) + EnumKey(key, 0) + finally: + DeleteKey(HKEY_CURRENT_USER, '\\'.join((test_key_name, name))) + DeleteKey(HKEY_CURRENT_USER, test_key_name) + + def test_dynamic_key(self): + # Issue2810, when the value is dynamically generated, these + # throw "WindowsError: More data is available" in 2.6 and 3.1 + EnumValue(HKEY_PERFORMANCE_DATA, 0) + QueryValueEx(HKEY_PERFORMANCE_DATA, "") + # Reflection requires XP x64/Vista at a minimum. XP doesn't have this stuff # or DeleteKeyEx so make sure their use raises NotImplementedError @unittest.skipUnless(WIN_VER < (5, 2), "Requires Windows XP") Modified: python/branches/py3k-cdecimal/Lib/test/test_winsound.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/test/test_winsound.py (original) +++ python/branches/py3k-cdecimal/Lib/test/test_winsound.py Mon Jun 7 12:46:02 2010 @@ -6,6 +6,7 @@ import time import os import subprocess +import ctypes winsound = support.import_module('winsound') import winreg @@ -13,6 +14,11 @@ def has_sound(sound): """Find out if a particular event is configured with a default sound""" try: + # Ask the mixer API for the number of devices it knows about. + # When there are no devices, PlaySound will fail. + if ctypes.windll.winmm.mixerGetNumDevs() is 0: + return False + key = winreg.OpenKeyEx(winreg.HKEY_CURRENT_USER, "AppEvents\Schemes\Apps\.Default\{0}\.Default".format(sound)) value = winreg.EnumValue(key, 0)[1] Modified: python/branches/py3k-cdecimal/Lib/test/testtar.tar ============================================================================== Binary files. No diff available. Modified: python/branches/py3k-cdecimal/Lib/tkinter/_fix.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/tkinter/_fix.py (original) +++ python/branches/py3k-cdecimal/Lib/tkinter/_fix.py Mon Jun 7 12:46:02 2010 @@ -42,6 +42,8 @@ # Ignore leading \\?\ if s.startswith("\\\\?\\"): s = s[4:] + if s.startswith("UNC"): + s = "\\" + s[3:] return s prefix = os.path.join(sys.prefix,"tcl") Modified: python/branches/py3k-cdecimal/Lib/unittest/case.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/unittest/case.py (original) +++ python/branches/py3k-cdecimal/Lib/unittest/case.py Mon Jun 7 12:46:02 2010 @@ -14,6 +14,9 @@ __unittest = True +DIFF_OMITTED = ('\nDiff is %s characters long. ' + 'Set self.maxDiff to None to see it.') + class SkipTest(Exception): """ Raise this exception in a test to skip it. @@ -169,6 +172,12 @@ longMessage = False + # This attribute sets the maximum length of a diff in failure messsages + # by assert methods using difflib. It is looked up as an instance attribute + # so can be configured by individual tests if required. + + maxDiff = 80*8 + # Attribute used by TestSuite for classSetUp _classSetupFailed = False @@ -694,12 +703,21 @@ except (TypeError, IndexError, NotImplementedError): differing += ('Unable to index element %d ' 'of second %s\n' % (len1, seq_type_name)) - standardMsg = differing + '\n' + '\n'.join( + standardMsg = differing + diffMsg = '\n' + '\n'.join( difflib.ndiff(pprint.pformat(seq1).splitlines(), pprint.pformat(seq2).splitlines())) + + standardMsg = self._truncateMessage(standardMsg, diffMsg) msg = self._formatMessage(msg, standardMsg) self.fail(msg) + def _truncateMessage(self, message, diff): + max_diff = self.maxDiff + if max_diff is None or len(diff) <= max_diff: + return message + diff + return message + (DIFF_OMITTED % len(diff)) + def assertListEqual(self, list1, list2, msg=None): """A list-specific equality assertion. @@ -798,9 +816,11 @@ self.assert_(isinstance(d2, dict), 'Second argument is not a dictionary') if d1 != d2: - standardMsg = ('\n' + '\n'.join(difflib.ndiff( + standardMsg = '%s != %s' % (safe_repr(d1, True), safe_repr(d2, True)) + diff = ('\n' + '\n'.join(difflib.ndiff( pprint.pformat(d1).splitlines(), pprint.pformat(d2).splitlines()))) + standardMsg = self._truncateMessage(standardMsg, diff) self.fail(self._formatMessage(msg, standardMsg)) def assertDictContainsSubset(self, expected, actual, msg=None): @@ -917,8 +937,10 @@ 'Second argument is not a string')) if first != second: - standardMsg = '\n' + ''.join(difflib.ndiff(first.splitlines(True), + standardMsg = '%s != %s' % (safe_repr(first, True), safe_repr(second, True)) + diff = '\n' + ''.join(difflib.ndiff(first.splitlines(True), second.splitlines(True))) + standardMsg = self._truncateMessage(standardMsg, diff) self.fail(self._formatMessage(msg, standardMsg)) def assertLess(self, a, b, msg=None): Modified: python/branches/py3k-cdecimal/Lib/unittest/loader.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/unittest/loader.py (original) +++ python/branches/py3k-cdecimal/Lib/unittest/loader.py Mon Jun 7 12:46:02 2010 @@ -235,6 +235,10 @@ __import__(name) return sys.modules[name] + def _match_path(self, path, full_path, pattern): + # override this method to use alternative matching strategy + return fnmatch(path, pattern) + def _find_tests(self, start_dir, pattern): """Used by discovery. Yields test suites it loads.""" paths = os.listdir(start_dir) @@ -245,26 +249,26 @@ if not VALID_MODULE_NAME.match(path): # valid Python identifiers only continue - - if fnmatch(path, pattern): - # if the test file matches, load it - name = self._get_name_from_path(full_path) - try: - module = self._get_module_from_name(name) - except: - yield _make_failed_import_test(name, self.suiteClass) - else: - mod_file = os.path.abspath(getattr(module, '__file__', full_path)) - realpath = os.path.splitext(mod_file)[0] - fullpath_noext = os.path.splitext(full_path)[0] - if realpath.lower() != fullpath_noext.lower(): - module_dir = os.path.dirname(realpath) - mod_name = os.path.splitext(os.path.basename(full_path))[0] - expected_dir = os.path.dirname(full_path) - msg = ("%r module incorrectly imported from %r. Expected %r. " - "Is this module globally installed?") - raise ImportError(msg % (mod_name, module_dir, expected_dir)) - yield self.loadTestsFromModule(module) + if not self._match_path(path, full_path, pattern): + continue + # if the test file matches, load it + name = self._get_name_from_path(full_path) + try: + module = self._get_module_from_name(name) + except: + yield _make_failed_import_test(name, self.suiteClass) + else: + mod_file = os.path.abspath(getattr(module, '__file__', full_path)) + realpath = os.path.splitext(mod_file)[0] + fullpath_noext = os.path.splitext(full_path)[0] + if realpath.lower() != fullpath_noext.lower(): + module_dir = os.path.dirname(realpath) + mod_name = os.path.splitext(os.path.basename(full_path))[0] + expected_dir = os.path.dirname(full_path) + msg = ("%r module incorrectly imported from %r. Expected %r. " + "Is this module globally installed?") + raise ImportError(msg % (mod_name, module_dir, expected_dir)) + yield self.loadTestsFromModule(module) elif os.path.isdir(full_path): if not os.path.isfile(os.path.join(full_path, '__init__.py')): continue Modified: python/branches/py3k-cdecimal/Lib/unittest/suite.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/unittest/suite.py (original) +++ python/branches/py3k-cdecimal/Lib/unittest/suite.py Mon Jun 7 12:46:02 2010 @@ -127,9 +127,11 @@ if setUpClass is not None: try: setUpClass() - except: + except Exception as e: currentClass._classSetupFailed = True - self._addClassSetUpError(result, currentClass) + className = util.strclass(currentClass) + errorName = 'setUpClass (%s)' % className + self._addClassOrModuleLevelException(result, e, errorName) def _get_previous_module(self, result): previousModule = None @@ -157,10 +159,18 @@ if setUpModule is not None: try: setUpModule() - except: + except Exception as e: result._moduleSetUpFailed = True - error = _ErrorHolder('setUpModule (%s)' % currentModule) - result.addError(error, sys.exc_info()) + errorName = 'setUpModule (%s)' % currentModule + self._addClassOrModuleLevelException(result, e, errorName) + + def _addClassOrModuleLevelException(self, result, exception, errorName): + error = _ErrorHolder(errorName) + addSkip = getattr(result, 'addSkip', None) + if addSkip is not None and isinstance(exception, case.SkipTest): + addSkip(error, str(exception)) + else: + result.addError(error, sys.exc_info()) def _handleModuleTearDown(self, result): previousModule = self._get_previous_module(result) @@ -178,9 +188,9 @@ if tearDownModule is not None: try: tearDownModule() - except: - error = _ErrorHolder('tearDownModule (%s)' % previousModule) - result.addError(error, sys.exc_info()) + except Exception as e: + errorName = 'tearDownModule (%s)' % previousModule + self._addClassOrModuleLevelException(result, e, errorName) def _tearDownPreviousClass(self, test, result): previousClass = getattr(result, '_previousTestClass', None) @@ -198,18 +208,11 @@ if tearDownClass is not None: try: tearDownClass() - except: - self._addClassTearDownError(result) + except Exception as e: + className = util.strclass(previousClass) + errorName = 'tearDownClass (%s)' % className + self._addClassOrModuleLevelException(result, e, errorName) - def _addClassTearDownError(self, result): - className = util.strclass(result._previousTestClass) - error = _ErrorHolder('classTearDown (%s)' % className) - result.addError(error, sys.exc_info()) - - def _addClassSetUpError(self, result, klass): - className = util.strclass(klass) - error = _ErrorHolder('classSetUp (%s)' % className) - result.addError(error, sys.exc_info()) class _ErrorHolder(object): Modified: python/branches/py3k-cdecimal/Lib/unittest/test/test_case.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/unittest/test/test_case.py (original) +++ python/branches/py3k-cdecimal/Lib/unittest/test/test_case.py Mon Jun 7 12:46:02 2010 @@ -1,3 +1,5 @@ +import difflib +import pprint import re import sys @@ -589,6 +591,84 @@ self.assertRaises(self.failureException, self.assertDictEqual, [], d) self.assertRaises(self.failureException, self.assertDictEqual, 1, 1) + def testAssertSequenceEqualMaxDiff(self): + self.assertEqual(self.maxDiff, 80*8) + seq1 = 'a' + 'x' * 80**2 + seq2 = 'b' + 'x' * 80**2 + diff = '\n'.join(difflib.ndiff(pprint.pformat(seq1).splitlines(), + pprint.pformat(seq2).splitlines())) + # the +1 is the leading \n added by assertSequenceEqual + omitted = unittest.case.DIFF_OMITTED % (len(diff) + 1,) + + self.maxDiff = len(diff)//2 + try: + + self.assertSequenceEqual(seq1, seq2) + except self.failureException as e: + msg = e.args[0] + else: + self.fail('assertSequenceEqual did not fail.') + self.assertTrue(len(msg) < len(diff)) + self.assertIn(omitted, msg) + + self.maxDiff = len(diff) * 2 + try: + self.assertSequenceEqual(seq1, seq2) + except self.failureException as e: + msg = e.args[0] + else: + self.fail('assertSequenceEqual did not fail.') + self.assertTrue(len(msg) > len(diff)) + self.assertNotIn(omitted, msg) + + self.maxDiff = None + try: + self.assertSequenceEqual(seq1, seq2) + except self.failureException as e: + msg = e.args[0] + else: + self.fail('assertSequenceEqual did not fail.') + self.assertTrue(len(msg) > len(diff)) + self.assertNotIn(omitted, msg) + + def testTruncateMessage(self): + self.maxDiff = 1 + message = self._truncateMessage('foo', 'bar') + omitted = unittest.case.DIFF_OMITTED % len('bar') + self.assertEqual(message, 'foo' + omitted) + + self.maxDiff = None + message = self._truncateMessage('foo', 'bar') + self.assertEqual(message, 'foobar') + + self.maxDiff = 4 + message = self._truncateMessage('foo', 'bar') + self.assertEqual(message, 'foobar') + + def testAssertDictEqualTruncates(self): + test = unittest.TestCase('assertEqual') + def truncate(msg, diff): + return 'foo' + test._truncateMessage = truncate + try: + test.assertDictEqual({}, {1: 0}) + except self.failureException as e: + self.assertEqual(str(e), 'foo') + else: + self.fail('assertDictEqual did not fail') + + def testAssertMultiLineEqualTruncates(self): + test = unittest.TestCase('assertEqual') + def truncate(msg, diff): + return 'foo' + test._truncateMessage = truncate + try: + test.assertMultiLineEqual('foo', 'bar') + except self.failureException as e: + self.assertEqual(str(e), 'foo') + else: + self.fail('assertMultiLineEqual did not fail') + def testAssertItemsEqual(self): a = object() self.assertItemsEqual([1, 2, 3], [3, 2, 1]) @@ -739,7 +819,7 @@ A test case is the smallest unit of testing. [...] You may provide your own implementation that does not subclass from TestCase, of course. """ - sample_text_error = """ + sample_text_error = """\ - http://www.python.org/doc/2.3/lib/module-unittest.html ? ^ + http://www.python.org/doc/2.4.1/lib/module-unittest.html @@ -750,13 +830,16 @@ ? +++++++++++++++++++++ + own implementation that does not subclass from TestCase, of course. """ - + self.maxDiff = None try: self.assertMultiLineEqual(sample_text, revised_sample_text) except self.failureException as e: + # need to remove the first line of the error message + error = str(e).split('\n', 1)[1] + # no fair testing ourself with ourself, and assertEqual is used for strings # so can't use assertEqual either. Just use assertTrue. - self.assertTrue(sample_text_error == str(e)) + self.assertTrue(sample_text_error == error) def testAssertIsNone(self): self.assertIsNone(None) Modified: python/branches/py3k-cdecimal/Lib/unittest/test/test_setups.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/unittest/test/test_setups.py (original) +++ python/branches/py3k-cdecimal/Lib/unittest/test/test_setups.py Mon Jun 7 12:46:02 2010 @@ -111,7 +111,7 @@ self.assertEqual(len(result.errors), 1) error, _ = result.errors[0] self.assertEqual(str(error), - 'classSetUp (%s.BrokenTest)' % __name__) + 'setUpClass (%s.BrokenTest)' % __name__) def test_error_in_teardown_class(self): class Test(unittest.TestCase): @@ -144,7 +144,7 @@ error, _ = result.errors[0] self.assertEqual(str(error), - 'classTearDown (%s.Test)' % __name__) + 'tearDownClass (%s.Test)' % __name__) def test_class_not_torndown_when_setup_fails(self): class Test(unittest.TestCase): @@ -398,3 +398,46 @@ self.assertEqual(len(result.errors), 1) error, _ = result.errors[0] self.assertEqual(str(error), 'tearDownModule (Module)') + + def test_skiptest_in_setupclass(self): + class Test(unittest.TestCase): + @classmethod + def setUpClass(cls): + raise unittest.SkipTest('foo') + def test_one(self): + pass + def test_two(self): + pass + + result = self.runTests(Test) + self.assertEqual(result.testsRun, 0) + self.assertEqual(len(result.errors), 0) + self.assertEqual(len(result.skipped), 1) + skipped = result.skipped[0][0] + self.assertEqual(str(skipped), 'setUpClass (%s.Test)' % __name__) + + def test_skiptest_in_setupmodule(self): + class Test(unittest.TestCase): + def test_one(self): + pass + def test_two(self): + pass + + class Module(object): + @staticmethod + def setUpModule(): + raise unittest.SkipTest('foo') + + Test.__module__ = 'Module' + sys.modules['Module'] = Module + + result = self.runTests(Test) + self.assertEqual(result.testsRun, 0) + self.assertEqual(len(result.errors), 0) + self.assertEqual(len(result.skipped), 1) + skipped = result.skipped[0][0] + self.assertEqual(str(skipped), 'setUpModule (Module)') + + +if __name__ == '__main__': + unittest.main() Modified: python/branches/py3k-cdecimal/Lib/unittest/util.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/unittest/util.py (original) +++ python/branches/py3k-cdecimal/Lib/unittest/util.py Mon Jun 7 12:46:02 2010 @@ -2,12 +2,16 @@ __unittest = True - -def safe_repr(obj): +_MAX_LENGTH = 80 +def safe_repr(obj, short=False): try: - return repr(obj) + result = repr(obj) except Exception: - return object.__repr__(obj) + result = object.__repr__(obj) + if not short or len(result) < _MAX_LENGTH: + return result + return result[:_MAX_LENGTH] + ' [truncated]...' + def strclass(cls): return "%s.%s" % (cls.__module__, cls.__name__) Modified: python/branches/py3k-cdecimal/Lib/urllib/request.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/urllib/request.py (original) +++ python/branches/py3k-cdecimal/Lib/urllib/request.py Mon Jun 7 12:46:02 2010 @@ -775,12 +775,21 @@ password_mgr = HTTPPasswordMgr() self.passwd = password_mgr self.add_password = self.passwd.add_password + self.retried = 0 def http_error_auth_reqed(self, authreq, host, req, headers): # host may be an authority (without userinfo) or a URL with an # authority # XXX could be multiple headers authreq = headers.get(authreq, None) + + if self.retried > 5: + # retry sending the username:password 5 times before failing. + raise HTTPError(req.get_full_url(), 401, "basic auth failed", + headers, None) + else: + self.retried += 1 + if authreq: mo = AbstractBasicAuthHandler.rx.search(authreq) if mo: Modified: python/branches/py3k-cdecimal/Lib/webbrowser.py ============================================================================== --- python/branches/py3k-cdecimal/Lib/webbrowser.py (original) +++ python/branches/py3k-cdecimal/Lib/webbrowser.py Mon Jun 7 12:46:02 2010 @@ -540,18 +540,6 @@ # Platform support for MacOS # -try: - import ic -except ImportError: - pass -else: - class InternetConfig(BaseBrowser): - def open(self, url, new=0, autoraise=True): - ic.launchurl(url) - return True # Any way to get status? - - register("internet-config", InternetConfig, update_tryorder=-1) - if sys.platform == 'darwin': # Adapted from patch submitted to SourceForge by Steven J. Burr class MacOSX(BaseBrowser): Modified: python/branches/py3k-cdecimal/Mac/Tools/pythonw.c ============================================================================== --- python/branches/py3k-cdecimal/Mac/Tools/pythonw.c (original) +++ python/branches/py3k-cdecimal/Mac/Tools/pythonw.c Mon Jun 7 12:46:02 2010 @@ -151,6 +151,14 @@ main(int argc, char **argv) { char* exec_path = get_python_path(); + /* + * Let argv[0] refer to the new interpreter. This is needed to + * get the effect we want on OSX 10.5 or earlier. That is, without + * changing argv[0] the real interpreter won't have access to + * the Window Server. + */ + argv[0] = exec_path; + #ifdef HAVE_SPAWN_H /* We're weak-linking to posix-spawnv to ensure that * an executable build on 10.5 can work on 10.4. Modified: python/branches/py3k-cdecimal/Misc/ACKS ============================================================================== --- python/branches/py3k-cdecimal/Misc/ACKS (original) +++ python/branches/py3k-cdecimal/Misc/ACKS Mon Jun 7 12:46:02 2010 @@ -19,6 +19,7 @@ Kevin Altis Joe Amenta Mark Anacker +Shashwat Anand Anders Andersen John Anderson Erik Anders?n @@ -82,6 +83,7 @@ Paul Boddie Matthew Boedicker David Bolen +Forest Bond Gawain Bolton Gregory Bond Jurjen Bos @@ -363,6 +365,7 @@ Eric Huss Jeremy Hylton Gerhard H?ring +Fredrik H??rd Mihai Ibanescu Lars Immisch Meador Inge @@ -424,6 +427,7 @@ Damon Kohler Joseph Koshy Maksim Kozyarchuk +Stefan Krah Bob Kras Holger Krekel Michael Kremer Modified: python/branches/py3k-cdecimal/Misc/NEWS ============================================================================== --- python/branches/py3k-cdecimal/Misc/NEWS (original) +++ python/branches/py3k-cdecimal/Misc/NEWS Mon Jun 7 12:46:02 2010 @@ -12,6 +12,31 @@ Core and Builtins ----------------- +- Issue #8837: Remove "O?" format of PyArg_Parse*() functions. The format is no + used anymore and it was never documented. + +- Issue #2844: Make int('42', n) consistently raise ValueError for + invalid integers n (including n = -909). + +- Issue #8188: Introduce a new scheme for computing hashes of numbers + (instances of int, float, complex, decimal.Decimal and + fractions.Fraction) that makes it easy to maintain the invariant + that hash(x) == hash(y) whenever x and y have equal value. + +- Issue #8748: Fix two issues with comparisons between complex and integer + objects. (1) The comparison could incorrectly return True in some cases + (2**53+1 == complex(2**53) == 2**53), breaking transivity of equality. + (2) The comparison raised an OverflowError for large integers, leading + to unpredictable exceptions when combining integers and complex objects + in sets or dicts. + +- Issue #8766: Initialize _warnings module before importing the first module. + Fix a crash if an empty directory called "encodings" exists in sys.path. + +- Issue #8589: Decode PYTHONWARNINGS environment variable with the file system + encoding and surrogateespace error handler instead of the locale encoding to + be consistent with os.environ. Add PySys_AddWarnOptionUnicode() function. + - PyObject_Dump() encodes unicode objects to utf8 with backslashreplace (instead of strict) error handler to escape surrogates @@ -31,6 +56,8 @@ PyUnicode_FromString() to support surrogates in the filename and use the right encoding +- Issue #7507: Quote "!" in pipes.quote(); it is special to some shells. + - PyUnicode_DecodeFSDefaultAndSize() uses surrogateescape error handler - Issue #8419: Prevent the dict constructor from accepting non-string keyword @@ -312,6 +339,11 @@ C-API ----- +- Issue #5753: A new C API function, :cfunc:`PySys_SetArgvEx`, allows + embedders of the interpreter to set sys.argv without also modifying + sys.path. This helps fix `CVE-2008-5983 + `_. + - Add PyArg_ValidateKeywordArguments, which checks if all keyword arguments are strings in an efficient manner. @@ -366,6 +398,74 @@ Library ------- +- Issue #8899: time.struct_time now has class and atribute docstrings. + +- Issue #6470: Drop UNC prefix in FixTk. + +- Issue #4768: base64 encoded email body parts were incorrectly stored as + binary strings. They are now correctly converted to strings. + +- Issue #8833: tarfile created hard link entries with a size field != 0 by + mistake. + +- Charset.body_encode now correctly handles base64 encoding by encoding + with the output_charset before calling base64mime.encode. Passes the + tests from 2.x issue 1368247. + +- Issue #8845: sqlite3 Connection objects now have a read-only in_transaction + attribute that is True iff there are uncommitted changes. + +- Issue #1289118: datetime.timedelta objects can now be multiplied by float + and divided by float and int objects. Results are rounded to the nearest + multiple of timedelta.resolution with ties resolved using round-half-to-even + method. + +- Issue #7150: Raise OverflowError if the result of adding or subtracting + timedelta from date or datetime falls outside of the MINYEAR:MAXYEAR range. + +- Issue #8806: add SSL contexts support to ftplib. + +- Issue #4769: Fix main() function of the base64 module, use sys.stdin.buffer + and sys.stdout.buffer (instead of sys.stdin and sys.stdout) to use the bytes + API + +- Issue #8770: now sysconfig displays information when it's called as + a script. Initial idea by Sridhar Ratnakumar. + +- Issue #6662: Fix parsing of malformatted charref (&#bad;), patch written by + Fredrik H??rd + +- Issue #8540: Decimal module: rename the Context._clamp attribute to + Context.clamp and make it public. This is useful in creating + contexts that correspond to the decimal interchange formats + specified in IEEE 754. + +- Issue #6268: Fix seek() method of codecs.open(), don't read or write the BOM + twice after seek(0). Fix also reset() method of codecs, UTF-16, UTF-32 and + StreamWriter classes. + +- Issue #3798: sys.exit(message) writes the message to sys.stderr file, instead + of the C file stderr, to use stderr encoding and error handler + +- Issue #8782: Add a trailing newline in linecache.updatecache to the last line + of files without one. + +- Issue #8729: Return NotImplemented from collections.Mapping.__eq__ when + comparing to a non-mapping. + +- Issue #8774: tabnanny uses the encoding cookie (#coding:...) to use the + correct encoding + +- Issue #4870: Add an `options` attribute to SSL contexts, as well as + several ``OP_*`` constants to the `ssl` module. This allows to selectively + disable protocol versions, when used in combination with `PROTOCOL_SSLv23`. + +- Issue #8759: Fixed user paths in sysconfig for posix and os2 schemes. + +- Issue #8663: distutils.log emulates backslashreplace error handler. Fix + compilation in a non-ASCII directory if stdout encoding is ASCII (eg. if + stdout is not a TTY). + - Issue #8513: os.get_exec_path() supports b'PATH' key and bytes value. subprocess.Popen() and os._execvpe() support bytes program name. Add os.supports_bytes_environ flag: True if the native OS type of the environment @@ -442,7 +542,7 @@ - Issue #8354: The siginterrupt setting is now preserved for all signals, not just SIGCHLD. -- Issue #7192: webbrowser.get("firefox") now wors on Mac OS X, as does +- Issue #7192: webbrowser.get("firefox") now works on Mac OS X, as does webbrowser.get("safari"). - Issue #8464: tarfile no longer creates files with execute permissions set @@ -1153,6 +1253,9 @@ Extension Modules ----------------- +- Issue #2810: Fix cases where the Windows registry API returns + ERROR_MORE_DATA, requiring a re-try in order to get the complete result. + - Issue #8692: Optimize math.factorial: replace the previous naive algorithm with an improved 'binary-split' algorithm that uses fewer multiplications and allows many of the multiplications to be @@ -1229,6 +1332,9 @@ Build ----- +- Issue #1759169, #8864: Drop _XOPEN_SOURCE on Solaris, define it for + multiprocessing only. + - Issue #8625: Turn off optimization in --with-pydebug builds with gcc. (Optimization was unintentionally turned on in gcc --with-pydebug builds as a result of the issue #1628484 fix, @@ -1315,9 +1421,14 @@ - Update python manual page (options -B, -O0, -s, environment variables PYTHONDONTWRITEBYTECODE, PYTHONNOUSERSITE). +- Issue #8909: Added the size of the bitmap used in the installer created by + distutils' bdist_wininst. Patch by Anatoly Techtonik. + Tests ----- +- Issue #7449: Skip test_socketserver if threading support is disabled + - Issue #8672: Add a zlib test ensuring that an incomplete stream can be handled by a decompressor object without errors (it returns incomplete uncompressed data). @@ -1444,6 +1555,8 @@ Tools/Demos ----------- +- Issue #5464: Implement plural forms in msgfmt.py. + - iobench (a file I/O benchmark) and ccbench (a concurrency benchmark) were added to the `Tools/` directory. They were previously living in the sandbox. Modified: python/branches/py3k-cdecimal/Misc/developers.txt ============================================================================== --- python/branches/py3k-cdecimal/Misc/developers.txt (original) +++ python/branches/py3k-cdecimal/Misc/developers.txt Mon Jun 7 12:46:02 2010 @@ -20,6 +20,9 @@ Permissions History ------------------- +- Alexander Belopolsky was given commit access on May 25 2010 + by MvL at suggestion of Mark Dickinson. + - Tim Golden was given commit access on April 21 2010 by MvL, at suggestion of Michael Foord. Modified: python/branches/py3k-cdecimal/Modules/_multiprocessing/multiprocessing.h ============================================================================== --- python/branches/py3k-cdecimal/Modules/_multiprocessing/multiprocessing.h (original) +++ python/branches/py3k-cdecimal/Modules/_multiprocessing/multiprocessing.h Mon Jun 7 12:46:02 2010 @@ -3,6 +3,12 @@ #define PY_SSIZE_T_CLEAN +#ifdef __sun +/* The control message API is only available on Solaris + if XPG 4.2 or later is requested. */ +#define _XOPEN_SOURCE 500 +#endif + #include "Python.h" #include "structmember.h" #include "pythread.h" Modified: python/branches/py3k-cdecimal/Modules/_sqlite/connection.c ============================================================================== --- python/branches/py3k-cdecimal/Modules/_sqlite/connection.c (original) +++ python/branches/py3k-cdecimal/Modules/_sqlite/connection.c Mon Jun 7 12:46:02 2010 @@ -23,6 +23,7 @@ #include "cache.h" #include "module.h" +#include "structmember.h" #include "connection.h" #include "statement.h" #include "cursor.h" @@ -1551,6 +1552,7 @@ {"NotSupportedError", T_OBJECT, offsetof(pysqlite_Connection, NotSupportedError), READONLY}, {"row_factory", T_OBJECT, offsetof(pysqlite_Connection, row_factory)}, {"text_factory", T_OBJECT, offsetof(pysqlite_Connection, text_factory)}, + {"in_transaction", T_BOOL, offsetof(pysqlite_Connection, inTransaction), READONLY}, {NULL} }; Modified: python/branches/py3k-cdecimal/Modules/_ssl.c ============================================================================== --- python/branches/py3k-cdecimal/Modules/_ssl.c (original) +++ python/branches/py3k-cdecimal/Modules/_ssl.c Mon Jun 7 12:46:02 2010 @@ -113,6 +113,13 @@ # undef HAVE_OPENSSL_RAND #endif +/* SSL_CTX_clear_options() and SSL_clear_options() were first added in OpenSSL 0.9.8m */ +#if OPENSSL_VERSION_NUMBER >= 0x009080dfL +# define HAVE_SSL_CTX_CLEAR_OPTIONS +#else +# undef HAVE_SSL_CTX_CLEAR_OPTIONS +#endif + typedef struct { PyObject_HEAD SSL_CTX *ctx; @@ -1514,6 +1521,35 @@ } static PyObject * +get_options(PySSLContext *self, void *c) +{ + return PyLong_FromLong(SSL_CTX_get_options(self->ctx)); +} + +static int +set_options(PySSLContext *self, PyObject *arg, void *c) +{ + long new_opts, opts, set, clear; + if (!PyArg_Parse(arg, "l", &new_opts)) + return -1; + opts = SSL_CTX_get_options(self->ctx); + clear = opts & ~new_opts; + set = ~opts & new_opts; + if (clear) { +#ifdef HAVE_SSL_CTX_CLEAR_OPTIONS + SSL_CTX_clear_options(self->ctx, clear); +#else + PyErr_SetString(PyExc_ValueError, + "can't clear options before OpenSSL 0.9.8m"); + return -1; +#endif + } + if (set) + SSL_CTX_set_options(self->ctx, set); + return 0; +} + +static PyObject * load_cert_chain(PySSLContext *self, PyObject *args, PyObject *kwds) { char *kwlist[] = {"certfile", "keyfile", NULL}; @@ -1636,6 +1672,8 @@ } static PyGetSetDef context_getsetlist[] = { + {"options", (getter) get_options, + (setter) set_options, NULL}, {"verify_mode", (getter) get_verify_mode, (setter) set_verify_mode, NULL}, {NULL}, /* sentinel */ @@ -1953,6 +1991,12 @@ PyModule_AddIntConstant(m, "PROTOCOL_TLSv1", PY_SSL_VERSION_TLS1); + /* protocol options */ + PyModule_AddIntConstant(m, "OP_ALL", SSL_OP_ALL); + PyModule_AddIntConstant(m, "OP_NO_SSLv2", SSL_OP_NO_SSLv2); + PyModule_AddIntConstant(m, "OP_NO_SSLv3", SSL_OP_NO_SSLv3); + PyModule_AddIntConstant(m, "OP_NO_TLSv1", SSL_OP_NO_TLSv1); + /* OpenSSL version */ /* SSLeay() gives us the version of the library linked against, which could be different from the headers version. Modified: python/branches/py3k-cdecimal/Modules/config.c.in ============================================================================== --- python/branches/py3k-cdecimal/Modules/config.c.in (original) +++ python/branches/py3k-cdecimal/Modules/config.c.in Mon Jun 7 12:46:02 2010 @@ -34,28 +34,28 @@ /* -- ADDMODULE MARKER 2 -- */ - /* This module lives in marshal.c */ - {"marshal", PyMarshal_Init}, + /* This module lives in marshal.c */ + {"marshal", PyMarshal_Init}, - /* This lives in import.c */ - {"imp", PyInit_imp}, + /* This lives in import.c */ + {"imp", PyInit_imp}, - /* This lives in Python/Python-ast.c */ - {"_ast", PyInit__ast}, + /* This lives in Python/Python-ast.c */ + {"_ast", PyInit__ast}, - /* These entries are here for sys.builtin_module_names */ - {"__main__", NULL}, - {"builtins", NULL}, - {"sys", NULL}, + /* These entries are here for sys.builtin_module_names */ + {"__main__", NULL}, + {"builtins", NULL}, + {"sys", NULL}, - /* This lives in gcmodule.c */ - {"gc", PyInit_gc}, + /* This lives in gcmodule.c */ + {"gc", PyInit_gc}, - /* This lives in _warnings.c */ - {"_warnings", _PyWarnings_Init}, + /* This lives in _warnings.c */ + {"_warnings", _PyWarnings_Init}, - /* Sentinel */ - {0, 0} + /* Sentinel */ + {0, 0} }; Modified: python/branches/py3k-cdecimal/Modules/datetimemodule.c ============================================================================== --- python/branches/py3k-cdecimal/Modules/datetimemodule.c (original) +++ python/branches/py3k-cdecimal/Modules/datetimemodule.c Mon Jun 7 12:46:02 2010 @@ -30,6 +30,7 @@ #define MINYEAR 1 #define MAXYEAR 9999 +#define MAXORDINAL 3652059 /* date(9999,12,31).toordinal() */ /* Nine decimal digits is easy to communicate, and leaves enough room * so that two delta days can be added w/o fear of overflowing a signed @@ -151,6 +152,25 @@ return (long)x; } +/* Nearest integer to m / n for integers m and n. Half-integer results + * are rounded to even. + */ +static PyObject * +divide_nearest(PyObject *m, PyObject *n) +{ + PyObject *result; + PyObject *temp; + + temp = _PyLong_Divmod_Near(m, n); + if (temp == NULL) + return NULL; + result = PyTuple_GET_ITEM(temp, 0); + Py_INCREF(result); + Py_DECREF(temp); + + return result; +} + /* --------------------------------------------------------------------------- * General calendrical helper functions */ @@ -480,7 +500,7 @@ * The input values must be such that the internals don't overflow. * The way this routine is used, we don't get close. */ -static void +static int normalize_y_m_d(int *y, int *m, int *d) { int dim; /* # of days in month */ @@ -534,11 +554,23 @@ else { int ordinal = ymd_to_ord(*y, *m, 1) + *d - 1; - ord_to_ymd(ordinal, y, m, d); + if (ordinal < 1 || ordinal > MAXORDINAL) { + goto error; + } else { + ord_to_ymd(ordinal, y, m, d); + return 0; + } } } assert(*m > 0); assert(*d > 0); + if (MINYEAR <= *y && *y <= MAXYEAR) + return 0; + error: + PyErr_SetString(PyExc_OverflowError, + "date value out of range"); + return -1; + } /* Fiddle out-of-bounds months and days so that the result makes some kind @@ -548,17 +580,7 @@ static int normalize_date(int *year, int *month, int *day) { - int result; - - normalize_y_m_d(year, month, day); - if (MINYEAR <= *year && *year <= MAXYEAR) - result = 0; - else { - PyErr_SetString(PyExc_OverflowError, - "date value out of range"); - result = -1; - } - return result; + return normalize_y_m_d(year, month, day); } /* Force all the datetime fields into range. The parameters are both @@ -1645,6 +1667,37 @@ } static PyObject * +multiply_float_timedelta(PyObject *floatobj, PyDateTime_Delta *delta) +{ + PyObject *result = NULL; + PyObject *pyus_in = NULL, *temp, *pyus_out; + PyObject *ratio = NULL; + + pyus_in = delta_to_microseconds(delta); + if (pyus_in == NULL) + return NULL; + ratio = PyObject_CallMethod(floatobj, "as_integer_ratio", NULL); + if (ratio == NULL) + goto error; + temp = PyNumber_Multiply(pyus_in, PyTuple_GET_ITEM(ratio, 0)); + Py_DECREF(pyus_in); + pyus_in = NULL; + if (temp == NULL) + goto error; + pyus_out = divide_nearest(temp, PyTuple_GET_ITEM(ratio, 1)); + Py_DECREF(temp); + if (pyus_out == NULL) + goto error; + result = microseconds_to_delta(pyus_out); + Py_DECREF(pyus_out); + error: + Py_XDECREF(pyus_in); + Py_XDECREF(ratio); + + return result; +} + +static PyObject * divide_timedelta_int(PyDateTime_Delta *delta, PyObject *intobj) { PyObject *pyus_in; @@ -1712,6 +1765,55 @@ } static PyObject * +truedivide_timedelta_float(PyDateTime_Delta *delta, PyObject *f) +{ + PyObject *result = NULL; + PyObject *pyus_in = NULL, *temp, *pyus_out; + PyObject *ratio = NULL; + + pyus_in = delta_to_microseconds(delta); + if (pyus_in == NULL) + return NULL; + ratio = PyObject_CallMethod(f, "as_integer_ratio", NULL); + if (ratio == NULL) + goto error; + temp = PyNumber_Multiply(pyus_in, PyTuple_GET_ITEM(ratio, 1)); + Py_DECREF(pyus_in); + pyus_in = NULL; + if (temp == NULL) + goto error; + pyus_out = divide_nearest(temp, PyTuple_GET_ITEM(ratio, 0)); + Py_DECREF(temp); + if (pyus_out == NULL) + goto error; + result = microseconds_to_delta(pyus_out); + Py_DECREF(pyus_out); + error: + Py_XDECREF(pyus_in); + Py_XDECREF(ratio); + + return result; +} + +static PyObject * +truedivide_timedelta_int(PyDateTime_Delta *delta, PyObject *i) +{ + PyObject *result; + PyObject *pyus_in, *pyus_out; + pyus_in = delta_to_microseconds(delta); + if (pyus_in == NULL) + return NULL; + pyus_out = divide_nearest(pyus_in, i); + Py_DECREF(pyus_in); + if (pyus_out == NULL) + return NULL; + result = microseconds_to_delta(pyus_out); + Py_DECREF(pyus_out); + + return result; +} + +static PyObject * delta_add(PyObject *left, PyObject *right) { PyObject *result = Py_NotImplemented; @@ -1835,10 +1937,16 @@ if (PyLong_Check(right)) result = multiply_int_timedelta(right, (PyDateTime_Delta *) left); + else if (PyFloat_Check(right)) + result = multiply_float_timedelta(right, + (PyDateTime_Delta *) left); } else if (PyLong_Check(left)) result = multiply_int_timedelta(left, - (PyDateTime_Delta *) right); + (PyDateTime_Delta *) right); + else if (PyFloat_Check(left)) + result = multiply_float_timedelta(left, + (PyDateTime_Delta *) right); if (result == Py_NotImplemented) Py_INCREF(result); @@ -1877,6 +1985,12 @@ result = truedivide_timedelta_timedelta( (PyDateTime_Delta *)left, (PyDateTime_Delta *)right); + else if (PyFloat_Check(right)) + result = truedivide_timedelta_float( + (PyDateTime_Delta *)left, right); + else if (PyLong_Check(right)) + result = truedivide_timedelta_int( + (PyDateTime_Delta *)left, right); } if (result == Py_NotImplemented) @@ -3109,8 +3223,8 @@ PyDoc_STR("datetime -> string name of time zone.")}, {"utcoffset", (PyCFunction)tzinfo_utcoffset, METH_O, - PyDoc_STR("datetime -> minutes east of UTC (negative for " - "west of UTC).")}, + PyDoc_STR("datetime -> timedelta showing offset from UTC, negative " + "values indicating West of UTC")}, {"dst", (PyCFunction)tzinfo_dst, METH_O, PyDoc_STR("datetime -> DST offset in minutes east of UTC.")}, Modified: python/branches/py3k-cdecimal/Modules/main.c ============================================================================== --- python/branches/py3k-cdecimal/Modules/main.c (original) +++ python/branches/py3k-cdecimal/Modules/main.c Mon Jun 7 12:46:02 2010 @@ -425,7 +425,7 @@ #else if ((p = Py_GETENV("PYTHONWARNINGS")) && *p != '\0') { char *buf, *oldloc; - wchar_t *warning; + PyObject *warning; /* settle for strtok here as there's no one standard C89 wcstok */ @@ -437,9 +437,10 @@ oldloc = strdup(setlocale(LC_ALL, NULL)); setlocale(LC_ALL, ""); for (p = strtok(buf, ","); p != NULL; p = strtok(NULL, ",")) { - if ((warning = _Py_char2wchar(p)) != NULL) { - PySys_AddWarnOption(warning); - PyMem_Free(warning); + warning = PyUnicode_DecodeFSDefault(p); + if (warning != NULL) { + PySys_AddWarnOptionUnicode(warning); + Py_DECREF(warning); } } setlocale(LC_ALL, oldloc); Modified: python/branches/py3k-cdecimal/Modules/timemodule.c ============================================================================== --- python/branches/py3k-cdecimal/Modules/timemodule.c (original) +++ python/branches/py3k-cdecimal/Modules/timemodule.c Mon Jun 7 12:46:02 2010 @@ -208,21 +208,27 @@ a floating point number for subsecond precision."); static PyStructSequence_Field struct_time_type_fields[] = { - {"tm_year", NULL}, - {"tm_mon", NULL}, - {"tm_mday", NULL}, - {"tm_hour", NULL}, - {"tm_min", NULL}, - {"tm_sec", NULL}, - {"tm_wday", NULL}, - {"tm_yday", NULL}, - {"tm_isdst", NULL}, + {"tm_year", "year, for example, 1993"}, + {"tm_mon", "month of year, range [1, 12]"}, + {"tm_mday", "day of month, range [1, 31]"}, + {"tm_hour", "hours, range [0, 23]"}, + {"tm_min", "minutes, range [0, 59]"}, + {"tm_sec", "seconds, range [0, 61])"}, + {"tm_wday", "day of week, range [0, 6], Monday is 0"}, + {"tm_yday", "day of year, range [1, 366]"}, + {"tm_isdst", "1 if summer time is in effect, 0 if not, and -1 if unknown"}, {0} }; static PyStructSequence_Desc struct_time_type_desc = { "time.struct_time", - NULL, + "The time value as returned by gmtime(), localtime(), and strptime(), and\n" + " accepted by asctime(), mktime() and strftime(). May be considered as a\n" + " sequence of 9 integers.\n\n" + " Note that several fields' values are not the same as those defined by\n" + " the C language standard for struct tm. For example, the value of the\n" + " field tm_year is the actual year, not year - 1900. See individual\n" + " fields' descriptions for details.", struct_time_type_fields, 9, }; Modified: python/branches/py3k-cdecimal/Objects/abstract.c ============================================================================== --- python/branches/py3k-cdecimal/Objects/abstract.c (original) +++ python/branches/py3k-cdecimal/Objects/abstract.c Mon Jun 7 12:46:02 2010 @@ -693,48 +693,37 @@ PyObject * PyObject_Format(PyObject *obj, PyObject *format_spec) { - static PyObject * str__format__ = NULL; PyObject *meth; PyObject *empty = NULL; PyObject *result = NULL; - - /* Initialize cached value */ - if (str__format__ == NULL) { - /* Initialize static variable needed by _PyType_Lookup */ - str__format__ = PyUnicode_FromString("__format__"); - if (str__format__ == NULL) - goto done; - } + static PyObject *format_cache = NULL; /* If no format_spec is provided, use an empty string */ if (format_spec == NULL) { - empty = PyUnicode_FromUnicode(NULL, 0); - format_spec = empty; + empty = PyUnicode_FromUnicode(NULL, 0); + format_spec = empty; } - /* Make sure the type is initialized. float gets initialized late */ - if (Py_TYPE(obj)->tp_dict == NULL) - if (PyType_Ready(Py_TYPE(obj)) < 0) - goto done; - /* Find the (unbound!) __format__ method (a borrowed reference) */ - meth = _PyType_Lookup(Py_TYPE(obj), str__format__); + meth = _PyObject_LookupSpecial(obj, "__format__", &format_cache); if (meth == NULL) { - PyErr_Format(PyExc_TypeError, - "Type %.100s doesn't define __format__", - Py_TYPE(obj)->tp_name); + if (!PyErr_Occurred()) + PyErr_Format(PyExc_TypeError, + "Type %.100s doesn't define __format__", + Py_TYPE(obj)->tp_name); goto done; } - /* And call it, binding it to the value */ - result = PyObject_CallFunctionObjArgs(meth, obj, format_spec, NULL); + /* And call it. */ + result = PyObject_CallFunctionObjArgs(meth, format_spec, NULL); + Py_DECREF(meth); if (result && !PyUnicode_Check(result)) { - PyErr_SetString(PyExc_TypeError, - "__format__ method did not return string"); - Py_DECREF(result); - result = NULL; - goto done; + PyErr_SetString(PyExc_TypeError, + "__format__ method did not return string"); + Py_DECREF(result); + result = NULL; + goto done; } done: Modified: python/branches/py3k-cdecimal/Objects/complexobject.c ============================================================================== --- python/branches/py3k-cdecimal/Objects/complexobject.c (original) +++ python/branches/py3k-cdecimal/Objects/complexobject.c Mon Jun 7 12:46:02 2010 @@ -403,12 +403,12 @@ static long complex_hash(PyComplexObject *v) { - long hashreal, hashimag, combined; - hashreal = _Py_HashDouble(v->cval.real); - if (hashreal == -1) + unsigned long hashreal, hashimag, combined; + hashreal = (unsigned long)_Py_HashDouble(v->cval.real); + if (hashreal == (unsigned long)-1) return -1; - hashimag = _Py_HashDouble(v->cval.imag); - if (hashimag == -1) + hashimag = (unsigned long)_Py_HashDouble(v->cval.imag); + if (hashimag == (unsigned long)-1) return -1; /* Note: if the imaginary part is 0, hashimag is 0 now, * so the following returns hashreal unchanged. This is @@ -416,10 +416,10 @@ * compare equal must have the same hash value, so that * hash(x + 0*j) must equal hash(x). */ - combined = hashreal + 1000003 * hashimag; - if (combined == -1) - combined = -2; - return combined; + combined = hashreal + _PyHASH_IMAG * hashimag; + if (combined == (unsigned long)-1) + combined = (unsigned long)-2; + return (long)combined; } /* This macro may return! */ @@ -620,22 +620,58 @@ complex_richcompare(PyObject *v, PyObject *w, int op) { PyObject *res; - Py_complex i, j; - TO_COMPLEX(v, i); - TO_COMPLEX(w, j); + Py_complex i; + int equal; if (op != Py_EQ && op != Py_NE) { - Py_INCREF(Py_NotImplemented); - return Py_NotImplemented; + goto Unimplemented; + } + + assert(PyComplex_Check(v)); + TO_COMPLEX(v, i); + + if (PyLong_Check(w)) { + /* Check for 0.0 imaginary part first to avoid the rich + * comparison when possible. + */ + if (i.imag == 0.0) { + PyObject *j, *sub_res; + j = PyFloat_FromDouble(i.real); + if (j == NULL) + return NULL; + + sub_res = PyObject_RichCompare(j, w, op); + Py_DECREF(j); + return sub_res; + } + else { + equal = 0; + } } + else if (PyFloat_Check(w)) { + equal = (i.real == PyFloat_AsDouble(w) && i.imag == 0.0); + } + else if (PyComplex_Check(w)) { + Py_complex j; - if ((i.real == j.real && i.imag == j.imag) == (op == Py_EQ)) - res = Py_True; + TO_COMPLEX(w, j); + equal = (i.real == j.real && i.imag == j.imag); + } + else { + goto Unimplemented; + } + + if (equal == (op == Py_EQ)) + res = Py_True; else - res = Py_False; + res = Py_False; Py_INCREF(res); return res; + +Unimplemented: + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; } static PyObject * Modified: python/branches/py3k-cdecimal/Objects/longobject.c ============================================================================== --- python/branches/py3k-cdecimal/Objects/longobject.c (original) +++ python/branches/py3k-cdecimal/Objects/longobject.c Mon Jun 7 12:46:02 2010 @@ -2571,18 +2571,37 @@ sign = -1; i = -(i); } - /* The following loop produces a C unsigned long x such that x is - congruent to the absolute value of v modulo ULONG_MAX. The - resulting x is nonzero if and only if v is. */ while (--i >= 0) { - /* Force a native long #-bits (32 or 64) circular shift */ - x = (x >> (8*SIZEOF_LONG-PyLong_SHIFT)) | (x << PyLong_SHIFT); + /* Here x is a quantity in the range [0, _PyHASH_MODULUS); we + want to compute x * 2**PyLong_SHIFT + v->ob_digit[i] modulo + _PyHASH_MODULUS. + + The computation of x * 2**PyLong_SHIFT % _PyHASH_MODULUS + amounts to a rotation of the bits of x. To see this, write + + x * 2**PyLong_SHIFT = y * 2**_PyHASH_BITS + z + + where y = x >> (_PyHASH_BITS - PyLong_SHIFT) gives the top + PyLong_SHIFT bits of x (those that are shifted out of the + original _PyHASH_BITS bits, and z = (x << PyLong_SHIFT) & + _PyHASH_MODULUS gives the bottom _PyHASH_BITS - PyLong_SHIFT + bits of x, shifted up. Then since 2**_PyHASH_BITS is + congruent to 1 modulo _PyHASH_MODULUS, y*2**_PyHASH_BITS is + congruent to y modulo _PyHASH_MODULUS. So + + x * 2**PyLong_SHIFT = y + z (mod _PyHASH_MODULUS). + + The right-hand side is just the result of rotating the + _PyHASH_BITS bits of x left by PyLong_SHIFT places; since + not all _PyHASH_BITS bits of x are 1s, the same is true + after rotation, so 0 <= y+z < _PyHASH_MODULUS and y + z is + the reduction of x*2**PyLong_SHIFT modulo + _PyHASH_MODULUS. */ + x = ((x << PyLong_SHIFT) & _PyHASH_MODULUS) | + (x >> (_PyHASH_BITS - PyLong_SHIFT)); x += v->ob_digit[i]; - /* If the addition above overflowed we compensate by - incrementing. This preserves the value modulo - ULONG_MAX. */ - if (x < v->ob_digit[i]) - x++; + if (x >= _PyHASH_MODULUS) + x -= _PyHASH_MODULUS; } x = x * sign; if (x == (unsigned long)-1) @@ -4079,23 +4098,34 @@ static PyObject * long_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { - PyObject *x = NULL; - int base = -909; /* unlikely! */ + PyObject *obase = NULL, *x = NULL; + long base; + int overflow; static char *kwlist[] = {"x", "base", 0}; if (type != &PyLong_Type) return long_subtype_new(type, args, kwds); /* Wimp out */ - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oi:int", kwlist, - &x, &base)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO:int", kwlist, + &x, &obase)) return NULL; if (x == NULL) return PyLong_FromLong(0L); - if (base == -909) + if (obase == NULL) return PyNumber_Long(x); - else if (PyUnicode_Check(x)) + + base = PyLong_AsLongAndOverflow(obase, &overflow); + if (base == -1 && PyErr_Occurred()) + return NULL; + if (overflow || (base != 0 && base < 2) || base > 36) { + PyErr_SetString(PyExc_ValueError, + "int() arg 2 must be >= 2 and <= 36"); + return NULL; + } + + if (PyUnicode_Check(x)) return PyLong_FromUnicode(PyUnicode_AS_UNICODE(x), PyUnicode_GET_SIZE(x), - base); + (int)base); else if (PyByteArray_Check(x) || PyBytes_Check(x)) { /* Since PyLong_FromString doesn't have a length parameter, * check here for possible NULs in the string. */ @@ -4110,10 +4140,10 @@ x is a bytes or buffer, *and* a base is given. */ PyErr_Format(PyExc_ValueError, "invalid literal for int() with base %d: %R", - base, x); + (int)base, x); return NULL; } - return PyLong_FromString(string, NULL, base); + return PyLong_FromString(string, NULL, (int)base); } else { PyErr_SetString(PyExc_TypeError, @@ -4182,140 +4212,169 @@ PyUnicode_GET_SIZE(format_spec)); } +/* Return a pair (q, r) such that a = b * q + r, and + abs(r) <= abs(b)/2, with equality possible only if q is even. + In other words, q == a / b, rounded to the nearest integer using + round-half-to-even. */ + +PyObject * +_PyLong_Divmod_Near(PyObject *a, PyObject *b) +{ + PyLongObject *quo = NULL, *rem = NULL; + PyObject *one = NULL, *twice_rem, *result, *temp; + int cmp, quo_is_odd, quo_is_neg; + + /* Equivalent Python code: + + def divmod_near(a, b): + q, r = divmod(a, b) + # round up if either r / b > 0.5, or r / b == 0.5 and q is odd. + # The expression r / b > 0.5 is equivalent to 2 * r > b if b is + # positive, 2 * r < b if b negative. + greater_than_half = 2*r > b if b > 0 else 2*r < b + exactly_half = 2*r == b + if greater_than_half or exactly_half and q % 2 == 1: + q += 1 + r -= b + return q, r + + */ + if (!PyLong_Check(a) || !PyLong_Check(b)) { + PyErr_SetString(PyExc_TypeError, + "non-integer arguments in division"); + return NULL; + } + + /* Do a and b have different signs? If so, quotient is negative. */ + quo_is_neg = (Py_SIZE(a) < 0) != (Py_SIZE(b) < 0); + + one = PyLong_FromLong(1L); + if (one == NULL) + return NULL; + + if (long_divrem((PyLongObject*)a, (PyLongObject*)b, &quo, &rem) < 0) + goto error; + + /* compare twice the remainder with the divisor, to see + if we need to adjust the quotient and remainder */ + twice_rem = long_lshift((PyObject *)rem, one); + if (twice_rem == NULL) + goto error; + if (quo_is_neg) { + temp = long_neg((PyLongObject*)twice_rem); + Py_DECREF(twice_rem); + twice_rem = temp; + if (twice_rem == NULL) + goto error; + } + cmp = long_compare((PyLongObject *)twice_rem, (PyLongObject *)b); + Py_DECREF(twice_rem); + + quo_is_odd = Py_SIZE(quo) != 0 && ((quo->ob_digit[0] & 1) != 0); + if ((Py_SIZE(b) < 0 ? cmp < 0 : cmp > 0) || (cmp == 0 && quo_is_odd)) { + /* fix up quotient */ + if (quo_is_neg) + temp = long_sub(quo, (PyLongObject *)one); + else + temp = long_add(quo, (PyLongObject *)one); + Py_DECREF(quo); + quo = (PyLongObject *)temp; + if (quo == NULL) + goto error; + /* and remainder */ + if (quo_is_neg) + temp = long_add(rem, (PyLongObject *)b); + else + temp = long_sub(rem, (PyLongObject *)b); + Py_DECREF(rem); + rem = (PyLongObject *)temp; + if (rem == NULL) + goto error; + } + + result = PyTuple_New(2); + if (result == NULL) + goto error; + + /* PyTuple_SET_ITEM steals references */ + PyTuple_SET_ITEM(result, 0, (PyObject *)quo); + PyTuple_SET_ITEM(result, 1, (PyObject *)rem); + Py_DECREF(one); + return result; + + error: + Py_XDECREF(quo); + Py_XDECREF(rem); + Py_XDECREF(one); + return NULL; +} + static PyObject * long_round(PyObject *self, PyObject *args) { - PyObject *o_ndigits=NULL, *temp; - PyLongObject *pow=NULL, *q=NULL, *r=NULL, *ndigits=NULL, *one; - int errcode; - digit q_mod_4; - - /* Notes on the algorithm: to round to the nearest 10**n (n positive), - the straightforward method is: - - (1) divide by 10**n - (2) round to nearest integer (round to even in case of tie) - (3) multiply result by 10**n. - - But the rounding step involves examining the fractional part of the - quotient to see whether it's greater than 0.5 or not. Since we - want to do the whole calculation in integer arithmetic, it's - simpler to do: - - (1) divide by (10**n)/2 - (2) round to nearest multiple of 2 (multiple of 4 in case of tie) - (3) multiply result by (10**n)/2. - - Then all we need to know about the fractional part of the quotient - arising in step (2) is whether it's zero or not. - - Doing both a multiplication and division is wasteful, and is easily - avoided if we just figure out how much to adjust the original input - by to do the rounding. - - Here's the whole algorithm expressed in Python. - - def round(self, ndigits = None): - """round(int, int) -> int""" - if ndigits is None or ndigits >= 0: - return self - pow = 10**-ndigits >> 1 - q, r = divmod(self, pow) - self -= r - if (q & 1 != 0): - if (q & 2 == r == 0): - self -= pow - else: - self += pow - return self + PyObject *o_ndigits=NULL, *temp, *result, *ndigits; - */ + /* To round an integer m to the nearest 10**n (n positive), we make use of + * the divmod_near operation, defined by: + * + * divmod_near(a, b) = (q, r) + * + * where q is the nearest integer to the quotient a / b (the + * nearest even integer in the case of a tie) and r == a - q * b. + * Hence q * b = a - r is the nearest multiple of b to a, + * preferring even multiples in the case of a tie. + * + * So the nearest multiple of 10**n to m is: + * + * m - divmod_near(m, 10**n)[1]. + */ if (!PyArg_ParseTuple(args, "|O", &o_ndigits)) return NULL; if (o_ndigits == NULL) return long_long(self); - ndigits = (PyLongObject *)PyNumber_Index(o_ndigits); + ndigits = PyNumber_Index(o_ndigits); if (ndigits == NULL) return NULL; + /* if ndigits >= 0 then no rounding is necessary; return self unchanged */ if (Py_SI