From b186d0084c9f46042f44ed773f7552c3f35e6e91 Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Tue, 18 Mar 2008 15:15:01 +0000 Subject: Merged revisions 61431,61433-61436,61439,61444,61449-61450,61453,61458,61465,61468,61471-61474,61480,61483-61484,61488,61495-61496,61498,61503-61504,61507,61509-61510,61515-61518 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ........ r61431 | vinay.sajip | 2008-03-16 22:35:58 +0100 (So, 16 Mär 2008) | 1 line Clarified documentation on use of shutdown(). ........ r61433 | mark.summerfield | 2008-03-17 09:28:15 +0100 (Mo, 17 Mär 2008) | 5 lines Added a footnote to each pointing out that for XML output if an encoding string is given it should conform to the appropriate XML standards---for example, "UTF-8" is okay, but "UTF8" is not. ........ r61434 | eric.smith | 2008-03-17 12:01:01 +0100 (Mo, 17 Mär 2008) | 7 lines Issue 2264: empty float presentation type needs to have at least one digit past the decimal point. Added "Z" format_char to PyOS_ascii_formatd to support empty float presentation type. Renamed buf_size in PyOS_ascii_formatd to more accurately reflect it's meaning. Modified format.__float__ to use the new "Z" format as the default. Added test cases. ........ r61435 | eric.smith | 2008-03-17 13:14:29 +0100 (Mo, 17 Mär 2008) | 2 lines Reformated lines > 79 chars. Deleted unused macro ISXDIGIT. ........ r61436 | jeffrey.yasskin | 2008-03-17 15:40:53 +0100 (Mo, 17 Mär 2008) | 13 lines Allow Gnu gcc's to build python on OSX by removing -Wno-long-double, -no-cpp-precomp, and -mno-fused-madd from configure. * r22183 added -no-cpp-precomp, which http://gcc.gnu.org/ml/gcc/2005-12/msg00368.html claims hasn't been needed since gcc-3.1. * r25607 added -Wno-long-double to avoid a warning in Include/objimpl.h (issue 525481). The long double is still there, but OSX 10.4's gcc no longer warns about it. * r33666 fixed issue 775892 on OSX 10.3 by adding -mno-fused-madd, which changed the sign of some float 0s. Tim Peters said it wasn't a real issue anyway, and it no longer causes test failures. Fixes issue #1779871. ........ r61439 | martin.v.loewis | 2008-03-17 17:31:57 +0100 (Mo, 17 Mär 2008) | 2 lines Add Trent Nelson. ........ r61444 | travis.oliphant | 2008-03-17 18:36:12 +0100 (Mo, 17 Mär 2008) | 1 line Add necessary headers to back-port new buffer protocol to Python 2.6 ........ r61449 | gregory.p.smith | 2008-03-17 19:48:05 +0100 (Mo, 17 Mär 2008) | 8 lines Force zlib.crc32 and zlib.adler32 to return a signed integer on all platforms regardless of the native sizeof(long) used in the integer object. This somewhat odd behavior of returning a signed is maintained in 2.x for compatibility reasons of always returning an integer rather than a long object. Fixes Issue1202 for Python 2.6 ........ r61450 | neal.norwitz | 2008-03-17 20:02:45 +0100 (Mo, 17 Mär 2008) | 3 lines Use a buffer large enough to ensure we don't overrun, even if the value is outside the range we expect. ........ r61453 | steven.bethard | 2008-03-17 20:33:11 +0100 (Mo, 17 Mär 2008) | 1 line Document unicode.isnumeric() and unicode.isdecimal() (issue2326) ........ r61458 | neal.norwitz | 2008-03-17 21:22:43 +0100 (Mo, 17 Mär 2008) | 5 lines Issue 2321: reduce memory usage (increase the memory that is returned to the system) by using pymalloc for the data of unicode objects. Will backport. ........ r61465 | martin.v.loewis | 2008-03-17 22:55:30 +0100 (Mo, 17 Mär 2008) | 2 lines Add David Wolever. ........ r61468 | gregory.p.smith | 2008-03-18 01:20:01 +0100 (Di, 18 Mär 2008) | 3 lines Fix the IOError message text when opening a file with an invalid filename. Error reported by Ilan Schnell. ........ r61471 | brett.cannon | 2008-03-18 02:00:07 +0100 (Di, 18 Mär 2008) | 2 lines Convert test_strftime, test_getargs, and test_pep247 to use unittest. ........ r61472 | jeffrey.yasskin | 2008-03-18 02:09:59 +0100 (Di, 18 Mär 2008) | 2 lines Fix build on platforms that don't have intptr_t. Patch by Joseph Armbruster. ........ r61473 | brett.cannon | 2008-03-18 02:50:25 +0100 (Di, 18 Mär 2008) | 2 lines Convert test_dummy_threading and test_dbm to unittest. ........ r61474 | brett.cannon | 2008-03-18 02:58:56 +0100 (Di, 18 Mär 2008) | 2 lines Move test_extcall to doctest. ........ r61480 | brett.cannon | 2008-03-18 04:46:22 +0100 (Di, 18 Mär 2008) | 2 lines test_errno was a no-op test; now it actually tests things and uses unittest. ........ r61483 | brett.cannon | 2008-03-18 05:09:00 +0100 (Di, 18 Mär 2008) | 3 lines Remove our implementation of memmove() and strerror(); both are in the C89 standard library. ........ r61484 | brett.cannon | 2008-03-18 05:16:06 +0100 (Di, 18 Mär 2008) | 2 lines The output directory for tests that compare against stdout is now gone! ........ r61488 | jeffrey.yasskin | 2008-03-18 05:29:35 +0100 (Di, 18 Mär 2008) | 2 lines Block the "socket.ssl() is deprecated" warning from test_socket_ssl. ........ r61495 | jeffrey.yasskin | 2008-03-18 05:56:06 +0100 (Di, 18 Mär 2008) | 4 lines Speed test_thread up from 51.328s to 0.081s by reducing its sleep times. We still sleep at all to make it likely that all threads are active at the same time. ........ r61496 | jeffrey.yasskin | 2008-03-18 06:12:41 +0100 (Di, 18 Mär 2008) | 4 lines Speed up test_dict by about 10x by only checking selected dict literal sizes, instead of every integer from 0 to 400. Exhaustive testing wastes time without providing enough more assurance that the code is correct. ........ r61498 | neal.norwitz | 2008-03-18 06:20:29 +0100 (Di, 18 Mär 2008) | 1 line Try increasing the timeout to reduce the flakiness of this test. ........ r61503 | brett.cannon | 2008-03-18 06:43:04 +0100 (Di, 18 Mär 2008) | 2 lines Improve the error message for a test that failed on the S-390 Debian buildbot. ........ r61504 | jeffrey.yasskin | 2008-03-18 06:45:40 +0100 (Di, 18 Mär 2008) | 3 lines Add a -S/--slow flag to regrtest to have it print the 10 slowest tests with their times. ........ r61507 | neal.norwitz | 2008-03-18 07:03:46 +0100 (Di, 18 Mär 2008) | 1 line Add some info to the failure messages ........ r61509 | trent.nelson | 2008-03-18 08:02:12 +0100 (Di, 18 Mär 2008) | 1 line Issue 2286: bump up the stack size of the 64-bit debug python_d.exe to 2100000. The default value of 200000 causes a stack overflow at 1965 iterations of r_object() in marshal.c, 35 iterations before the 2000 limit enforced by MAX_MARSHAL_STACK_DEPTH. ........ r61510 | trent.nelson | 2008-03-18 08:32:47 +0100 (Di, 18 Mär 2008) | 5 lines The behaviour of winsound.Beep() seems to differ between different versions of Windows when there's either: a) no sound card entirely b) legacy beep driver has been disabled c) the legacy beep driver has been uninstalled Sometimes RuntimeErrors are raised, sometimes they're not. If _have_soundcard() returns False, don't expect winsound.Beep() to raise a RuntimeError, as this clearly isn't the case, as demonstrated by the various Win32 XP buildbots. ........ r61515 | martin.v.loewis | 2008-03-18 13:20:15 +0100 (Di, 18 Mär 2008) | 2 lines norwitz-amd64 (gentoo) has EREMOTEIO. ........ r61516 | martin.v.loewis | 2008-03-18 13:45:37 +0100 (Di, 18 Mär 2008) | 2 lines Add more Linux error codes. ........ r61517 | martin.v.loewis | 2008-03-18 14:05:03 +0100 (Di, 18 Mär 2008) | 2 lines Add WSA errors. ........ r61518 | martin.v.loewis | 2008-03-18 14:16:05 +0100 (Di, 18 Mär 2008) | 2 lines Note that the stderr output of the test is intentional. ........ --- Doc/library/logging.rst | 3 +- Doc/library/pyexpat.rst | 10 +- Doc/library/stdtypes.rst | 16 + Doc/library/xml.dom.minidom.rst | 14 +- Doc/library/xml.etree.elementtree.rst | 11 +- Include/pyerrors.h | 2 + Lib/test/output/test_cProfile | 92 ------ Lib/test/output/test_extcall | 117 -------- Lib/test/regrtest.py | 75 ++--- Lib/test/test_dbm.py | 83 ++---- Lib/test/test_dict.py | 10 +- Lib/test/test_dummy_threading.py | 108 ++++--- Lib/test/test_errno.py | 83 ++++-- Lib/test/test_extcall.py | 536 +++++++++++++++++----------------- Lib/test/test_parser.py | 3 + Lib/test/test_pep247.py | 105 ++++--- Lib/test/test_smtplib.py | 8 +- Lib/test/test_strftime.py | 315 +++++++++++--------- Lib/test/test_thread.py | 16 +- Lib/test/test_types.py | 9 + Lib/test/test_winsound.py | 12 +- Lib/test/test_zlib.py | 1 + Misc/developers.txt | 6 + Modules/datetimemodule.c | 2 +- Objects/stringlib/formatter.h | 7 +- Objects/unicodeobject.c | 38 +-- PCbuild/python.vcproj | 2 +- Python/memmove.c | 25 -- Python/pystrtod.c | 98 +++++-- Python/strerror.c | 19 -- configure | 105 ++++++- configure.in | 8 +- pyconfig.h.in | 3 - 33 files changed, 980 insertions(+), 962 deletions(-) delete mode 100644 Lib/test/output/test_cProfile delete mode 100644 Lib/test/output/test_extcall delete mode 100644 Python/memmove.c delete mode 100644 Python/strerror.c diff --git a/Doc/library/logging.rst b/Doc/library/logging.rst index a7693fb..8ffa301 100644 --- a/Doc/library/logging.rst +++ b/Doc/library/logging.rst @@ -724,7 +724,8 @@ functions. .. function:: shutdown() Informs the logging system to perform an orderly shutdown by flushing and - closing all handlers. + closing all handlers. This should be called at application exit and no + further use of the logging system should be made after this call. .. function:: setLoggerClass(klass) diff --git a/Doc/library/pyexpat.rst b/Doc/library/pyexpat.rst index 3a3305c..e19a4d5 100644 --- a/Doc/library/pyexpat.rst +++ b/Doc/library/pyexpat.rst @@ -62,7 +62,7 @@ The :mod:`xml.parsers.expat` module contains two functions: must be a string naming the encoding used by the XML data. Expat doesn't support as many encodings as Python does, and its repertoire of encodings can't be extended; it supports UTF-8, UTF-16, ISO-8859-1 (Latin1), and ASCII. If - *encoding* is given it will override the implicit or explicit encoding of the + *encoding* [1]_ is given it will override the implicit or explicit encoding of the document. Expat can optionally do XML namespace processing for you, enabled by providing a @@ -848,3 +848,11 @@ The ``errors`` object has the following attributes: .. data:: XML_ERROR_SUSPEND_PE :noindex: + +.. rubric:: Footnotes + +.. [#] The encoding string included in XML output should conform to the + appropriate standards. For example, "UTF-8" is valid, but "UTF8" is + not. See http://www.w3.org/TR/2006/REC-xml11-20060816/#NT-EncodingDecl + and http://www.iana.org/assignments/character-sets . + diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index 58905e0..f06ca2c 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -1000,6 +1000,22 @@ functions based on regular expressions. Return the numeric string left filled with zeros in a string of length *width*. A sign prefix is handled correctly. The original string is returned if *width* is less than ``len(s)``. + + +.. method:: str.isnumeric() + + Return ``True`` if there are only numeric characters in S, ``False`` + otherwise. Numeric characters include digit characters, and all characters + that have the Unicode numeric value property, e.g. U+2155, + VULGAR FRACTION ONE FIFTH. + + +.. method:: str.isdecimal() + + Return ``True`` if there are only decimal characters in S, ``False`` + otherwise. Decimal characters include digit characters, and all characters + that that can be used to form decimal-radix numbers, e.g. U+0660, + ARABIC-INDIC DIGIT ZERO. diff --git a/Doc/library/xml.dom.minidom.rst b/Doc/library/xml.dom.minidom.rst index 75f381e..de67d07 100644 --- a/Doc/library/xml.dom.minidom.rst +++ b/Doc/library/xml.dom.minidom.rst @@ -147,10 +147,10 @@ module documentation. This section lists the differences between the API and document. Encoding this string in an encoding other than UTF-8 is likely incorrect, since UTF-8 is the default encoding of XML. - With an explicit *encoding* argument, the result is a :class:`bytes` object - in the specified encoding. It is recommended that this argument is always - specified. To avoid :exc:`UnicodeError` exceptions in case of unrepresentable - text data, the encoding argument should be specified as "utf-8". + With an explicit *encoding* [1]_ argument, the result is a byte string in the + specified encoding. It is recommended that this argument is always specified. To + avoid :exc:`UnicodeError` exceptions in case of unrepresentable text data, the + encoding argument should be specified as "utf-8". .. method:: Node.toprettyxml([indent[, newl[, encoding]]]) @@ -252,3 +252,9 @@ The following interfaces have no implementation in :mod:`xml.dom.minidom`: Most of these reflect information in the XML document that is not of general utility to most DOM users. +.. rubric:: Footnotes + +.. [#] The encoding string included in XML output should conform to the + appropriate standards. For example, "UTF-8" is valid, but "UTF8" is + not. See http://www.w3.org/TR/2006/REC-xml11-20060816/#NT-EncodingDecl + and http://www.iana.org/assignments/character-sets . diff --git a/Doc/library/xml.etree.elementtree.rst b/Doc/library/xml.etree.elementtree.rst index 5590476..61bc559 100644 --- a/Doc/library/xml.etree.elementtree.rst +++ b/Doc/library/xml.etree.elementtree.rst @@ -357,7 +357,7 @@ ElementTree Objects .. method:: ElementTree.write(file[, encoding]) Writes the element tree to a file, as XML. *file* is a file name, or a file - object opened for writing. *encoding* is the output encoding (default is + object opened for writing. *encoding* [1]_ is the output encoding (default is US-ASCII). This is the XML file that is going to be manipulated:: @@ -510,3 +510,12 @@ This is an example of counting the maximum depth of an XML file:: >>> parser.feed(exampleXml) >>> parser.close() 4 + + +.. rubric:: Footnotes + +.. [#] The encoding string included in XML output should conform to the + appropriate standards. For example, "UTF-8" is valid, but "UTF8" is + not. See http://www.w3.org/TR/2006/REC-xml11-20060816/#NT-EncodingDecl + and http://www.iana.org/assignments/character-sets . + diff --git a/Include/pyerrors.h b/Include/pyerrors.h index ecbb059..6b520e2 100644 --- a/Include/pyerrors.h +++ b/Include/pyerrors.h @@ -152,6 +152,8 @@ PyAPI_DATA(PyObject *) PyExc_WindowsError; PyAPI_DATA(PyObject *) PyExc_VMSError; #endif +PyAPI_DATA(PyObject *) PyExc_BufferError; + PyAPI_DATA(PyObject *) PyExc_MemoryErrorInst; PyAPI_DATA(PyObject *) PyExc_RecursionErrorInst; diff --git a/Lib/test/output/test_cProfile b/Lib/test/output/test_cProfile deleted file mode 100644 index 1221c63..0000000 --- a/Lib/test/output/test_cProfile +++ /dev/null @@ -1,92 +0,0 @@ -test_cProfile - 124 function calls (104 primitive calls) in 1.000 CPU seconds - - Ordered by: standard name - - ncalls tottime percall cumtime percall filename:lineno(function) - 1 0.000 0.000 1.000 1.000 :1() - 2 0.000 0.000 0.000 0.000 io.py:1213(flush) - 1 0.000 0.000 0.000 0.000 io.py:269(flush) - 1 0.000 0.000 0.000 0.000 io.py:656(closed) - 1 0.000 0.000 0.000 0.000 io.py:874(flush) - 8 0.064 0.008 0.080 0.010 test_cProfile.py:103(subhelper) - 28 0.028 0.001 0.028 0.001 test_cProfile.py:115(__getattr__) - 1 0.270 0.270 1.000 1.000 test_cProfile.py:30(testfunc) - 23/3 0.150 0.007 0.170 0.057 test_cProfile.py:40(factorial) - 20 0.020 0.001 0.020 0.001 test_cProfile.py:53(mul) - 2 0.040 0.020 0.600 0.300 test_cProfile.py:60(helper) - 4 0.116 0.029 0.120 0.030 test_cProfile.py:78(helper1) - 2 0.000 0.000 0.140 0.070 test_cProfile.py:89(helper2_indirect) - 8 0.312 0.039 0.400 0.050 test_cProfile.py:93(helper2) - 1 0.000 0.000 1.000 1.000 {exec} - 12 0.000 0.000 0.012 0.001 {hasattr} - 4 0.000 0.000 0.000 0.000 {method 'append' of 'list' objects} - 1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects} - 4 0.000 0.000 0.000 0.000 {sys.exc_info} - - - Ordered by: standard name - -Function called... - ncalls tottime cumtime -:1() -> 1 0.270 1.000 test_cProfile.py:30(testfunc) -io.py:1213(flush) -> 1 0.000 0.000 io.py:269(flush) - 1 0.000 0.000 io.py:874(flush) -io.py:269(flush) -> -io.py:656(closed) -> -io.py:874(flush) -> 1 0.000 0.000 io.py:656(closed) -test_cProfile.py:103(subhelper) -> 16 0.016 0.016 test_cProfile.py:115(__getattr__) -test_cProfile.py:115(__getattr__) -> -test_cProfile.py:30(testfunc) -> 1 0.014 0.130 test_cProfile.py:40(factorial) - 2 0.040 0.600 test_cProfile.py:60(helper) -test_cProfile.py:40(factorial) -> 20/3 0.130 0.147 test_cProfile.py:40(factorial) - 20 0.020 0.020 test_cProfile.py:53(mul) -test_cProfile.py:53(mul) -> -test_cProfile.py:60(helper) -> 4 0.116 0.120 test_cProfile.py:78(helper1) - 2 0.000 0.140 test_cProfile.py:89(helper2_indirect) - 6 0.234 0.300 test_cProfile.py:93(helper2) -test_cProfile.py:78(helper1) -> 4 0.000 0.004 {hasattr} - 4 0.000 0.000 {method 'append' of 'list' objects} - 4 0.000 0.000 {sys.exc_info} -test_cProfile.py:89(helper2_indirect) -> 2 0.006 0.040 test_cProfile.py:40(factorial) - 2 0.078 0.100 test_cProfile.py:93(helper2) -test_cProfile.py:93(helper2) -> 8 0.064 0.080 test_cProfile.py:103(subhelper) - 8 0.000 0.008 {hasattr} -{exec} -> 1 0.000 1.000 :1() - 2 0.000 0.000 io.py:1213(flush) -{hasattr} -> 12 0.012 0.012 test_cProfile.py:115(__getattr__) -{method 'append' of 'list' objects} -> -{method 'disable' of '_lsprof.Profiler' objects} -> -{sys.exc_info} -> - - - Ordered by: standard name - -Function was called by... - ncalls tottime cumtime -:1() <- 1 0.000 1.000 {exec} -io.py:1213(flush) <- 2 0.000 0.000 {exec} -io.py:269(flush) <- 1 0.000 0.000 io.py:1213(flush) -io.py:656(closed) <- 1 0.000 0.000 io.py:874(flush) -io.py:874(flush) <- 1 0.000 0.000 io.py:1213(flush) -test_cProfile.py:103(subhelper) <- 8 0.064 0.080 test_cProfile.py:93(helper2) -test_cProfile.py:115(__getattr__) <- 16 0.016 0.016 test_cProfile.py:103(subhelper) - 12 0.012 0.012 {hasattr} -test_cProfile.py:30(testfunc) <- 1 0.270 1.000 :1() -test_cProfile.py:40(factorial) <- 1 0.014 0.130 test_cProfile.py:30(testfunc) - 20/3 0.130 0.147 test_cProfile.py:40(factorial) - 2 0.006 0.040 test_cProfile.py:89(helper2_indirect) -test_cProfile.py:53(mul) <- 20 0.020 0.020 test_cProfile.py:40(factorial) -test_cProfile.py:60(helper) <- 2 0.040 0.600 test_cProfile.py:30(testfunc) -test_cProfile.py:78(helper1) <- 4 0.116 0.120 test_cProfile.py:60(helper) -test_cProfile.py:89(helper2_indirect) <- 2 0.000 0.140 test_cProfile.py:60(helper) -test_cProfile.py:93(helper2) <- 6 0.234 0.300 test_cProfile.py:60(helper) - 2 0.078 0.100 test_cProfile.py:89(helper2_indirect) -{exec} <- -{hasattr} <- 4 0.000 0.004 test_cProfile.py:78(helper1) - 8 0.000 0.008 test_cProfile.py:93(helper2) -{method 'append' of 'list' objects} <- 4 0.000 0.000 test_cProfile.py:78(helper1) -{method 'disable' of '_lsprof.Profiler' objects} <- -{sys.exc_info} <- 4 0.000 0.000 test_cProfile.py:78(helper1) - - diff --git a/Lib/test/output/test_extcall b/Lib/test/output/test_extcall deleted file mode 100644 index 63f5b71..0000000 --- a/Lib/test/output/test_extcall +++ /dev/null @@ -1,117 +0,0 @@ -test_extcall -() {} -(1,) {} -(1, 2) {} -(1, 2, 3) {} -(1, 2, 3, 4, 5) {} -(1, 2, 3, 4, 5) {} -(1, 2, 3, 4, 5) {} -(1, 2, 3) {'a': 4, 'b': 5} -(1, 2, 3, 4, 5) {'a': 6, 'b': 7} -(1, 2, 3, 6, 7) {'a': 8, 'b': 9, 'x': 4, 'y': 5} -(1, 2, 3) {'a': 4, 'b': 5} -(1, 2, 3, 4, 5) {'a': 6, 'b': 7} -(1, 2, 3, 6, 7) {'a': 8, 'b': 9, 'x': 4, 'y': 5} -TypeError: g() takes at least 1 positional argument (0 given) -TypeError: g() takes at least 1 positional argument (0 given) -TypeError: g() takes at least 1 positional argument (0 given) -1 () {} -1 (2,) {} -1 (2, 3) {} -1 (2, 3, 4, 5) {} -0 (1, 2) {} -0 (1, 2, 3) {} -1 () {'a': 1, 'b': 2, 'c': 3, 'd': 4} -{'a': 1, 'b': 2, 'c': 3} -{'a': 1, 'b': 2, 'c': 3} -g() got multiple values for keyword argument 'x' -g() got multiple values for keyword argument 'b' -f() keywords must be strings -h() got an unexpected keyword argument 'e' -h() argument after * must be a sequence, not function -dir() argument after * must be a sequence, not function -NoneType object argument after * must be a sequence, not function -h() argument after ** must be a mapping, not function -dir() argument after ** must be a mapping, not function -NoneType object argument after ** must be a mapping, not function -dir() got multiple values for keyword argument 'b' -3 512 True -3 -3 -5 -5 -za () {} -> za() takes exactly 1 positional argument (0 given) -za () {'a': 'aa'} -> ok za aa B D E V a -za () {'d': 'dd'} -> za() got an unexpected keyword argument 'd' -za () {'a': 'aa', 'd': 'dd'} -> za() got an unexpected keyword argument 'd' -za () {'a': 'aa', 'b': 'bb', 'd': 'dd', 'e': 'ee'} -> za() got an unexpected keyword argument 'b' -za (1, 2) {} -> za() takes exactly 1 positional argument (2 given) -za (1, 2) {'a': 'aa'} -> za() takes exactly 1 non-keyword positional argument (2 given) -za (1, 2) {'d': 'dd'} -> za() takes exactly 1 non-keyword positional argument (2 given) -za (1, 2) {'a': 'aa', 'd': 'dd'} -> za() takes exactly 1 non-keyword positional argument (2 given) -za (1, 2) {'a': 'aa', 'b': 'bb', 'd': 'dd', 'e': 'ee'} -> za() takes exactly 1 non-keyword positional argument (2 given) -za (1, 2, 3, 4, 5) {} -> za() takes exactly 1 positional argument (5 given) -za (1, 2, 3, 4, 5) {'a': 'aa'} -> za() takes exactly 1 non-keyword positional argument (5 given) -za (1, 2, 3, 4, 5) {'d': 'dd'} -> za() takes exactly 1 non-keyword positional argument (5 given) -za (1, 2, 3, 4, 5) {'a': 'aa', 'd': 'dd'} -> za() takes exactly 1 non-keyword positional argument (5 given) -za (1, 2, 3, 4, 5) {'a': 'aa', 'b': 'bb', 'd': 'dd', 'e': 'ee'} -> za() takes exactly 1 non-keyword positional argument (5 given) -zade () {} -> zade() takes at least 1 positional argument (0 given) -zade () {'a': 'aa'} -> ok zade aa B d e V a -zade () {'d': 'dd'} -> zade() takes at least 1 non-keyword positional argument (0 given) -zade () {'a': 'aa', 'd': 'dd'} -> ok zade aa B dd e V d -zade () {'a': 'aa', 'b': 'bb', 'd': 'dd', 'e': 'ee'} -> zade() got an unexpected keyword argument 'b' -zade (1, 2) {} -> ok zade 1 B 2 e V e -zade (1, 2) {'a': 'aa'} -> zade() got multiple values for keyword argument 'a' -zade (1, 2) {'d': 'dd'} -> zade() got multiple values for keyword argument 'd' -zade (1, 2) {'a': 'aa', 'd': 'dd'} -> zade() got multiple values for keyword argument 'a' -zade (1, 2) {'a': 'aa', 'b': 'bb', 'd': 'dd', 'e': 'ee'} -> zade() got multiple values for keyword argument 'a' -zade (1, 2, 3, 4, 5) {} -> zade() takes at most 3 positional arguments (5 given) -zade (1, 2, 3, 4, 5) {'a': 'aa'} -> zade() takes at most 3 non-keyword positional arguments (5 given) -zade (1, 2, 3, 4, 5) {'d': 'dd'} -> zade() takes at most 3 non-keyword positional arguments (5 given) -zade (1, 2, 3, 4, 5) {'a': 'aa', 'd': 'dd'} -> zade() takes at most 3 non-keyword positional arguments (5 given) -zade (1, 2, 3, 4, 5) {'a': 'aa', 'b': 'bb', 'd': 'dd', 'e': 'ee'} -> zade() takes at most 3 non-keyword positional arguments (5 given) -zabk () {} -> zabk() takes exactly 2 positional arguments (0 given) -zabk () {'a': 'aa'} -> zabk() takes exactly 2 non-keyword positional arguments (1 given) -zabk () {'d': 'dd'} -> zabk() takes exactly 2 non-keyword positional arguments (0 given) -zabk () {'a': 'aa', 'd': 'dd'} -> zabk() takes exactly 2 non-keyword positional arguments (1 given) -zabk () {'a': 'aa', 'b': 'bb', 'd': 'dd', 'e': 'ee'} -> ok zabk aa bb D E V {'d': 'dd', 'e': 'ee'} -zabk (1, 2) {} -> ok zabk 1 2 D E V {} -zabk (1, 2) {'a': 'aa'} -> zabk() got multiple values for keyword argument 'a' -zabk (1, 2) {'d': 'dd'} -> ok zabk 1 2 D E V {'d': 'dd'} -zabk (1, 2) {'a': 'aa', 'd': 'dd'} -> zabk() got multiple values for keyword argument 'a' -zabk (1, 2) {'a': 'aa', 'b': 'bb', 'd': 'dd', 'e': 'ee'} -> zabk() got multiple values for keyword argument 'a' -zabk (1, 2, 3, 4, 5) {} -> zabk() takes exactly 2 positional arguments (5 given) -zabk (1, 2, 3, 4, 5) {'a': 'aa'} -> zabk() takes exactly 2 non-keyword positional arguments (5 given) -zabk (1, 2, 3, 4, 5) {'d': 'dd'} -> zabk() takes exactly 2 non-keyword positional arguments (5 given) -zabk (1, 2, 3, 4, 5) {'a': 'aa', 'd': 'dd'} -> zabk() takes exactly 2 non-keyword positional arguments (5 given) -zabk (1, 2, 3, 4, 5) {'a': 'aa', 'b': 'bb', 'd': 'dd', 'e': 'ee'} -> zabk() takes exactly 2 non-keyword positional arguments (5 given) -zabdv () {} -> zabdv() takes at least 2 positional arguments (0 given) -zabdv () {'a': 'aa'} -> zabdv() takes at least 2 non-keyword positional arguments (1 given) -zabdv () {'d': 'dd'} -> zabdv() takes at least 2 non-keyword positional arguments (0 given) -zabdv () {'a': 'aa', 'd': 'dd'} -> zabdv() takes at least 2 non-keyword positional arguments (1 given) -zabdv () {'a': 'aa', 'b': 'bb', 'd': 'dd', 'e': 'ee'} -> zabdv() got an unexpected keyword argument 'e' -zabdv (1, 2) {} -> ok zabdv 1 2 d E () e -zabdv (1, 2) {'a': 'aa'} -> zabdv() got multiple values for keyword argument 'a' -zabdv (1, 2) {'d': 'dd'} -> ok zabdv 1 2 dd E () d -zabdv (1, 2) {'a': 'aa', 'd': 'dd'} -> zabdv() got multiple values for keyword argument 'a' -zabdv (1, 2) {'a': 'aa', 'b': 'bb', 'd': 'dd', 'e': 'ee'} -> zabdv() got multiple values for keyword argument 'a' -zabdv (1, 2, 3, 4, 5) {} -> ok zabdv 1 2 3 E (4, 5) e -zabdv (1, 2, 3, 4, 5) {'a': 'aa'} -> zabdv() got multiple values for keyword argument 'a' -zabdv (1, 2, 3, 4, 5) {'d': 'dd'} -> zabdv() got multiple values for keyword argument 'd' -zabdv (1, 2, 3, 4, 5) {'a': 'aa', 'd': 'dd'} -> zabdv() got multiple values for keyword argument 'a' -zabdv (1, 2, 3, 4, 5) {'a': 'aa', 'b': 'bb', 'd': 'dd', 'e': 'ee'} -> zabdv() got multiple values for keyword argument 'a' -zabdevk () {} -> zabdevk() takes at least 2 positional arguments (0 given) -zabdevk () {'a': 'aa'} -> zabdevk() takes at least 2 non-keyword positional arguments (1 given) -zabdevk () {'d': 'dd'} -> zabdevk() takes at least 2 non-keyword positional arguments (0 given) -zabdevk () {'a': 'aa', 'd': 'dd'} -> zabdevk() takes at least 2 non-keyword positional arguments (1 given) -zabdevk () {'a': 'aa', 'b': 'bb', 'd': 'dd', 'e': 'ee'} -> ok zabdevk aa bb dd ee () {} -zabdevk (1, 2) {} -> ok zabdevk 1 2 d e () {} -zabdevk (1, 2) {'a': 'aa'} -> zabdevk() got multiple values for keyword argument 'a' -zabdevk (1, 2) {'d': 'dd'} -> ok zabdevk 1 2 dd e () {} -zabdevk (1, 2) {'a': 'aa', 'd': 'dd'} -> zabdevk() got multiple values for keyword argument 'a' -zabdevk (1, 2) {'a': 'aa', 'b': 'bb', 'd': 'dd', 'e': 'ee'} -> zabdevk() got multiple values for keyword argument 'a' -zabdevk (1, 2, 3, 4, 5) {} -> ok zabdevk 1 2 3 4 (5,) {} -zabdevk (1, 2, 3, 4, 5) {'a': 'aa'} -> zabdevk() got multiple values for keyword argument 'a' -zabdevk (1, 2, 3, 4, 5) {'d': 'dd'} -> zabdevk() got multiple values for keyword argument 'd' -zabdevk (1, 2, 3, 4, 5) {'a': 'aa', 'd': 'dd'} -> zabdevk() got multiple values for keyword argument 'a' -zabdevk (1, 2, 3, 4, 5) {'a': 'aa', 'b': 'bb', 'd': 'dd', 'e': 'ee'} -> zabdevk() got multiple values for keyword argument 'a' diff --git a/Lib/test/regrtest.py b/Lib/test/regrtest.py index cb7cf75..20d3777 100755 --- a/Lib/test/regrtest.py +++ b/Lib/test/regrtest.py @@ -12,10 +12,9 @@ Command line options: -w: verbose2 -- re-run failed tests in verbose mode -d: debug -- print traceback for failed tests -q: quiet -- don't print anything except if a test fails --g: generate -- write the output file for a test instead of comparing it -x: exclude -- arguments are tests to *exclude* -s: single -- run only a single test (see below) --S: start -- start running all the tests with the specified one first +-S: slow -- print the slowest 10 tests -r: random -- randomize test execution order -f: fromfile -- read names of tests to run from a file (see below) -l: findleaks -- if GC is available detect tests that leak memory @@ -127,14 +126,15 @@ example, to run all the tests except for the bsddb tests, give the option '-uall,-bsddb'. """ -import os -import sys import getopt +import os import random -import warnings import re import io +import sys +import time import traceback +import warnings from inspect import isabstract # I see no other way to suppress these warnings; @@ -186,8 +186,7 @@ def usage(msg): def main(tests=None, testdir=None, verbose=0, quiet=False, generate=False, exclude=False, single=False, randomize=False, fromfile=None, findleaks=False, use_resources=None, trace=False, coverdir='coverage', - runleaks=False, huntrleaks=None, verbose2=False, debug=False, - start=None): + runleaks=False, huntrleaks=False, verbose2=False, print_slow=False): """Execute a test suite. This also parses command-line options and modifies its behavior @@ -204,17 +203,17 @@ def main(tests=None, testdir=None, verbose=0, quiet=False, generate=False, command-line will be used. If that's empty, too, then all *.py files beginning with test_ will be used. - The other default arguments (verbose, quiet, generate, exclude, single, - randomize, findleaks, use_resources, trace and coverdir) allow programmers - calling main() directly to set the values that would normally be set by - flags on the command line. + The other default arguments (verbose, quiet, generate, exclude, + single, randomize, findleaks, use_resources, trace, coverdir, and + print_slow) allow programmers calling main() directly to set the + values that would normally be set by flags on the command line. """ test_support.record_original_stdout(sys.stdout) try: - opts, args = getopt.getopt(sys.argv[1:], 'dhvgqxsS:rf:lu:t:TD:NLR:wM:n', - ['help', 'verbose', 'quiet', 'generate', - 'exclude', 'single', 'random', 'fromfile', + opts, args = getopt.getopt(sys.argv[1:], 'hvgqxsSrf:lu:t:TD:NLR:wM:', + ['help', 'verbose', 'quiet', 'exclude', + 'single', 'slow', 'random', 'fromfile', 'findleaks', 'use=', 'threshold=', 'trace', 'coverdir=', 'nocoverdir', 'runleaks', 'huntrleaks=', 'verbose2', 'memlimit=', @@ -239,14 +238,14 @@ def main(tests=None, testdir=None, verbose=0, quiet=False, generate=False, elif o in ('-q', '--quiet'): quiet = True; verbose = 0 - elif o in ('-g', '--generate'): - generate = True elif o in ('-x', '--exclude'): exclude = True elif o in ('-S', '--start'): start = a elif o in ('-s', '--single'): single = True + elif o in ('-S', '--slow'): + print_slow = True elif o in ('-r', '--randomize'): randomize = True elif o in ('-f', '--fromfile'): @@ -376,18 +375,19 @@ def main(tests=None, testdir=None, verbose=0, quiet=False, generate=False, tests = tests or args or findtests(testdir, stdtests, nottests) if single: tests = tests[:1] - # Remove all the tests that precede start if it's set. - if start: - try: - del tests[:tests.index(start)] - except ValueError: - print("Couldn't find starting test (%s), using all tests" % start) + ## Remove all the tests that precede start if it's set. + #if start: + # try: + # del tests[:tests.index(start)] + # except ValueError: + # print("Couldn't find starting test (%s), using all tests" % start) if randomize: random.shuffle(tests) if trace: import trace tracer = trace.Trace(ignoredirs=[sys.prefix, sys.exec_prefix], trace=False, count=True) + test_times = [] test_support.verbose = verbose # Tell tests to be moderately quiet test_support.use_resources = use_resources save_modules = sys.modules.keys() @@ -398,12 +398,13 @@ def main(tests=None, testdir=None, verbose=0, quiet=False, generate=False, if trace: # If we're tracing code coverage, then we don't exit with status # if on a false return value from main. - tracer.runctx('runtest(test, generate, verbose, quiet, testdir)', + tracer.runctx('runtest(test, generate, verbose, quiet,' + ' test_times, testdir)', globals=globals(), locals=vars()) else: try: - ok = runtest(test, generate, verbose, quiet, testdir, - huntrleaks) + ok = runtest(test, generate, verbose, quiet, test_times, + testdir, huntrleaks) except KeyboardInterrupt: # print a newline separate from the ^C print() @@ -444,6 +445,11 @@ def main(tests=None, testdir=None, verbose=0, quiet=False, generate=False, if verbose: print("CAUTION: stdout isn't compared in verbose mode:") print("a test that passes in verbose mode may fail without it.") + if print_slow: + test_times.sort(reverse=True) + print("10 slowest tests:") + for time, test in test_times[:10]: + print("%s: %.1fs" % (test, time)) if bad: print(count(len(bad), "test"), "failed:") printlist(bad) @@ -537,15 +543,14 @@ def findtests(testdir=None, stdtests=STDTESTS, nottests=NOTTESTS): tests.sort() return stdtests + tests -def runtest(test, generate, verbose, quiet, testdir=None, - huntrleaks=None, debug=False): +def runtest(test, generate, verbose, quiet, test_times, + testdir=None, huntrleaks=False): """Run a single test. test -- the name of the test - generate -- if true, generate output, instead of running the test - and comparing it to a previously created output file verbose -- if true, print more messages quiet -- if true, don't print 'skipped' messages (probably redundant) + test_times -- a list of (time, test_name) pairs testdir -- test directory huntrleaks -- run multiple times to test for leaks; requires a debug build; a triple corresponding to -R's three arguments @@ -559,13 +564,13 @@ def runtest(test, generate, verbose, quiet, testdir=None, """ try: - return runtest_inner(test, generate, verbose, quiet, testdir, - huntrleaks, debug) + return runtest_inner(test, generate, verbose, quiet, test_times, + testdir, huntrleaks) finally: cleanup_test_droppings(test, verbose) -def runtest_inner(test, generate, verbose, quiet, - testdir=None, huntrleaks=None, debug=False): +def runtest_inner(test, generate, verbose, quiet, test_times, + testdir=None, huntrleaks=False, debug=False): test_support.unload(test) if not testdir: testdir = findtestdir() @@ -587,6 +592,7 @@ def runtest_inner(test, generate, verbose, quiet, else: # Always import it from the test package abstest = 'test.' + test + start_time = time.time() the_package = __import__(abstest, globals(), locals(), []) the_module = getattr(the_package, test) # Old tests run to completion simply as a side-effect of @@ -597,6 +603,8 @@ def runtest_inner(test, generate, verbose, quiet, indirect_test() if huntrleaks: dash_R(the_module, test, indirect_test, huntrleaks) + test_time = time.time() - start_time + test_times.append((test_time, test)) finally: sys.stdout = save_stdout except test_support.ResourceDenied as msg: @@ -648,6 +656,7 @@ def runtest_inner(test, generate, verbose, quiet, fp.close() else: expected = test + "\n" + expected = test + "\n" if output == expected or huntrleaks: return 1 print("test", test, "produced unexpected output:") diff --git a/Lib/test/test_dbm.py b/Lib/test/test_dbm.py index 1a40ef6..44b712c 100755 --- a/Lib/test/test_dbm.py +++ b/Lib/test/test_dbm.py @@ -1,61 +1,40 @@ -#! /usr/bin/env python -"""Test script for the dbm module - Roger E. Masse -""" +from test import test_support +import unittest import os +import random import dbm from dbm import error -from test.test_support import verbose, verify, TestSkipped, TESTFN -# make filename unique to allow multiple concurrent tests -# and to minimize the likelihood of a problem from an old file -filename = TESTFN - -def cleanup(): - for suffix in ['', '.pag', '.dir', '.db']: - try: - os.unlink(filename + suffix) - except OSError as e: - (errno, strerror) = e.errno, e.strerror - # if we can't delete the file because of permissions, - # nothing will work, so skip the test - if errno == 1: - raise TestSkipped('unable to remove: ' + filename + suffix) - -def test_keys(): - d = dbm.open(filename, 'c') - verify(d.keys() == []) - d[b'a'] = b'b' - d[b'12345678910'] = b'019237410982340912840198242' - d.keys() - if b'a' in d: - if verbose: - print('Test dbm keys: ', d.keys()) - - d.close() - -def test_modes(): - d = dbm.open(filename, 'r') - d.close() - d = dbm.open(filename, 'rw') - d.close() - d = dbm.open(filename, 'w') - d.close() - d = dbm.open(filename, 'n') - d.close() +class DbmTestCase(unittest.TestCase): + + def setUp(self): + self.filename = test_support.TESTFN + self.d = dbm.open(self.filename, 'c') + self.d.close() + + def tearDown(self): + for suffix in ['', '.pag', '.dir', '.db']: + test_support.unlink(self.filename + suffix) + + def test_keys(self): + self.d = dbm.open(self.filename, 'c') + self.assert_(self.d.keys() == []) + self.d['a'] = 'b' + self.d['12345678910'] = '019237410982340912840198242' + self.d.keys() + self.assert_(b'a' in self.d) + self.d.close() + + def test_modes(self): + for mode in ['r', 'rw', 'w', 'n']: + try: + self.d = dbm.open(self.filename, mode) + self.d.close() + except dbm.error: + self.fail() def test_main(): - cleanup() - try: - test_keys() - test_modes() - except: - cleanup() - raise - - cleanup() - - + test_support.run_unittest(DbmTestCase) if __name__ == '__main__': test_main() diff --git a/Lib/test/test_dict.py b/Lib/test/test_dict.py index 1997dc5..01d47da 100644 --- a/Lib/test/test_dict.py +++ b/Lib/test/test_dict.py @@ -13,12 +13,14 @@ class DictTest(unittest.TestCase): def test_literal_constructor(self): # check literal constructor for different sized dicts (to exercise the BUILD_MAP oparg - items = [] - for n in range(400): + for n in (0, 1, 6, 256, 400): + items = [(''.join([random.choice(string.ascii_letters) + for j in range(8)]), + i) + for i in range(n)] + random.shuffle(items) dictliteral = '{' + ', '.join('%r: %d' % item for item in items) + '}' self.assertEqual(eval(dictliteral), dict(items)) - items.append((''.join([random.choice(string.ascii_letters) for j in range(8)]), n)) - random.shuffle(items) def test_bool(self): self.assert_(not {}) diff --git a/Lib/test/test_dummy_threading.py b/Lib/test/test_dummy_threading.py index 6f16241..2d0dadd 100644 --- a/Lib/test/test_dummy_threading.py +++ b/Lib/test/test_dummy_threading.py @@ -1,71 +1,63 @@ -# Very rudimentary test of threading module - -# Create a bunch of threads, let each do some work, wait until all are done - -from test.test_support import verbose +from test import test_support +import unittest import dummy_threading as _threading import time +class DummyThreadingTestCase(unittest.TestCase): -class TestThread(_threading.Thread): + class TestThread(_threading.Thread): - def run(self): + def run(self): + global running + global sema + global mutex + # Uncomment if testing another module, such as the real 'threading' + # module. + #delay = random.random() * 2 + delay = 0 + if test_support.verbose: + print('task', self.getName(), 'will run for', delay, 'sec') + sema.acquire() + mutex.acquire() + running += 1 + if test_support.verbose: + print(running, 'tasks are running') + mutex.release() + time.sleep(delay) + if test_support.verbose: + print('task', self.getName(), 'done') + mutex.acquire() + running -= 1 + if test_support.verbose: + print(self.getName(), 'is finished.', running, 'tasks are running') + mutex.release() + sema.release() + + def setUp(self): + self.numtasks = 10 + global sema + sema = _threading.BoundedSemaphore(value=3) + global mutex + mutex = _threading.RLock() global running - # Uncomment if testing another module, such as the real 'threading' - # module. - #delay = random.random() * 2 - delay = 0 - if verbose: - print('task', self.getName(), 'will run for', delay, 'sec') - sema.acquire() - mutex.acquire() - running = running + 1 - if verbose: - print(running, 'tasks are running') - mutex.release() - time.sleep(delay) - if verbose: - print('task', self.getName(), 'done') - mutex.acquire() - running = running - 1 - if verbose: - print(self.getName(), 'is finished.', running, 'tasks are running') - mutex.release() - sema.release() + running = 0 + self.threads = [] -def starttasks(): - for i in range(numtasks): - t = TestThread(name=""%i) - threads.append(t) - t.start() + def test_tasks(self): + for i in range(self.numtasks): + t = self.TestThread(name=""%i) + self.threads.append(t) + t.start() + if test_support.verbose: + print('waiting for all tasks to complete') + for t in self.threads: + t.join() + if test_support.verbose: + print('all tasks done') def test_main(): - # This takes about n/3 seconds to run (about n/3 clumps of tasks, times - # about 1 second per clump). - global numtasks - numtasks = 10 - - # no more than 3 of the 10 can run at once - global sema - sema = _threading.BoundedSemaphore(value=3) - global mutex - mutex = _threading.RLock() - global running - running = 0 - - global threads - threads = [] - - starttasks() - - if verbose: - print('waiting for all tasks to complete') - for t in threads: - t.join() - if verbose: - print('all tasks done') - + test_support.run_unittest(DummyThreadingTestCase) if __name__ == '__main__': diff --git a/Lib/test/test_errno.py b/Lib/test/test_errno.py index 25937dc..70bbfbc 100755 --- a/Lib/test/test_errno.py +++ b/Lib/test/test_errno.py @@ -4,46 +4,83 @@ """ import errno -from test.test_support import verbose +from test import test_support +import unittest errors = ['E2BIG', 'EACCES', 'EADDRINUSE', 'EADDRNOTAVAIL', 'EADV', 'EAFNOSUPPORT', 'EAGAIN', 'EALREADY', 'EBADE', 'EBADF', 'EBADFD', 'EBADMSG', 'EBADR', 'EBADRQC', 'EBADSLT', 'EBFONT', 'EBUSY', 'ECHILD', 'ECHRNG', 'ECOMM', 'ECONNABORTED', 'ECONNREFUSED', 'ECONNRESET', - 'EDEADLK', 'EDEADLOCK', 'EDESTADDRREQ', 'EDOM', + 'EDEADLK', 'EDEADLOCK', 'EDESTADDRREQ', 'EDOTDOT', 'EDOM', 'EDQUOT', 'EEXIST', 'EFAULT', 'EFBIG', 'EHOSTDOWN', 'EHOSTUNREACH', 'EIDRM', 'EILSEQ', 'EINPROGRESS', - 'EINTR', 'EINVAL', 'EIO', 'EISCONN', 'EISDIR', + 'EINTR', 'EINVAL', 'EIO', 'EISCONN', 'EISDIR', 'EISNAM', 'EL2HLT', 'EL2NSYNC', 'EL3HLT', 'EL3RST', 'ELIBACC', 'ELIBBAD', 'ELIBEXEC', 'ELIBMAX', 'ELIBSCN', 'ELNRNG', 'ELOOP', 'EMFILE', 'EMLINK', 'EMSGSIZE', 'EMULTIHOP', - 'ENAMETOOLONG', 'ENETDOWN', 'ENETRESET', 'ENETUNREACH', + 'ENAMETOOLONG', 'ENAVAIL', 'ENETDOWN', 'ENETRESET', 'ENETUNREACH', 'ENFILE', 'ENOANO', 'ENOBUFS', 'ENOCSI', 'ENODATA', 'ENODEV', 'ENOENT', 'ENOEXEC', 'ENOLCK', 'ENOLINK', 'ENOMEM', 'ENOMSG', 'ENONET', 'ENOPKG', 'ENOPROTOOPT', 'ENOSPC', 'ENOSR', 'ENOSTR', 'ENOSYS', 'ENOTBLK', - 'ENOTCONN', 'ENOTDIR', 'ENOTEMPTY', 'ENOTOBACCO', 'ENOTSOCK', + 'ENOTCONN', 'ENOTDIR', 'ENOTEMPTY', 'ENOTNAM', 'ENOTOBACCO', 'ENOTSOCK', 'ENOTTY', 'ENOTUNIQ', 'ENXIO', 'EOPNOTSUPP', 'EOVERFLOW', 'EPERM', 'EPFNOSUPPORT', 'EPIPE', 'EPROTO', 'EPROTONOSUPPORT', 'EPROTOTYPE', - 'ERANGE', 'EREMCHG', 'EREMOTE', 'ERESTART', + 'ERANGE', 'EREMCHG', 'EREMOTE', 'EREMOTEIO', 'ERESTART', 'EROFS', 'ESHUTDOWN', 'ESOCKTNOSUPPORT', 'ESPIPE', 'ESRCH', 'ESRMNT', 'ESTALE', 'ESTRPIPE', 'ETIME', - 'ETIMEDOUT', 'ETOOMANYREFS', 'ETXTBSY', 'EUNATCH', - 'EUSERS', 'EWOULDBLOCK', 'EXDEV', 'EXFULL'] - -# -# This is a wee bit bogus since the module only conditionally adds -# errno constants if they have been defined by errno.h However, this -# test seems to work on SGI, Sparc & intel Solaris, and linux. -# -for error in errors: - try: - a = getattr(errno, error) - except AttributeError: - if verbose: - print('%s: not found' % error) - else: - if verbose: - print('%s: %d' % (error, a)) + 'ETIMEDOUT', 'ETOOMANYREFS', 'ETXTBSY', 'EUCLEAN', 'EUNATCH', + 'EUSERS', 'EWOULDBLOCK', 'EXDEV', 'EXFULL', + 'WSABASEERR', 'WSADESCRIPTIO', 'WSAEACCES', 'WSAEADDRINUSE', + 'WSAEADDRNOTAVAIL', 'WSAEAFNOSUPPORT', 'WSAEALREADY', + 'WSAEBADF', 'WSAECONNABORTED', 'WSAECONNREFUSED', + 'WSAECONNRESET', 'WSAEDESTADDRREQ', 'WSAEDISCON', + 'WSAEDQUOT', 'WSAEFAULT', 'WSAEHOSTDOWN', 'WSAEHOSTUNREACH', + 'WSAEINPROGRESS', 'WSAEINTR', 'WSAEINVAL', 'WSAEISCONN', + 'WSAELOOP', 'WSAEMFILE', 'WSAEMSGSIZE', 'WSAENAMETOOLONG', + 'WSAENETDOWN', 'WSAENETRESET', 'WSAENETUNREACH', + 'WSAENOBUFS', 'WSAENOPROTOOPT', 'WSAENOTCONN', + 'WSAENOTEMPTY', 'WSAENOTSOCK', 'WSAEOPNOTSUPP', + 'WSAEPFNOSUPPORT', 'WSAEPROCLIM', 'WSAEPROTONOSUPPORT', + 'WSAEPROTOTYPE', 'WSAEREMOTE', 'WSAESHUTDOWN', + 'WSAESOCKTNOSUPPORT', 'WSAESTALE', 'WSAETIMEDOUT', + 'WSAETOOMANYREFS', 'WSAEUSERS', 'WSAEWOULDBLOCK', + 'WSAGETASYNCBUFLE', 'WSAGETASYNCERRO', 'WSAGETSELECTERRO', + 'WSAGETSELECTEVEN', 'WSAHOS', 'WSAMAKEASYNCREPL', + 'WSAMAKESELECTREPL', 'WSAN', 'WSANOTINITIALISED', 'WSASY', + 'WSASYSNOTREADY', 'WSATR', 'WSAVERNOTSUPPORTED'] + + +class ErrnoAttributeTests(unittest.TestCase): + + def test_for_improper_attributes(self): + # No unexpected attributes should be on the module. + errors_set = set(errors) + for attribute in errno.__dict__.keys(): + if attribute.isupper(): + self.assert_(attribute in errors_set, + "%s is an unexpected error value" % attribute) + + def test_using_errorcode(self): + # Every key value in errno.errorcode should be on the module. + for value in errno.errorcode.values(): + self.assert_(hasattr(errno, value), 'no %s attr in errno' % value) + + +class ErrorcodeTests(unittest.TestCase): + + def test_attributes_in_errorcode(self): + for attribute in errno.__dict__.keys(): + if attribute.isupper(): + self.assert_(getattr(errno, attribute) in errno.errorcode, + 'no %s attr in errno.errorcode' % attribute) + + +def test_main(): + test_support.run_unittest(ErrnoAttributeTests, ErrorcodeTests) + + +if __name__ == '__main__': + test_main() diff --git a/Lib/test/test_extcall.py b/Lib/test/test_extcall.py index bad1440..b6dc144 100644 --- a/Lib/test/test_extcall.py +++ b/Lib/test/test_extcall.py @@ -1,274 +1,262 @@ -from test.test_support import verify, TestFailed, sortdict -from collections import UserDict, UserList - -def e(a, b): - print(a, b) - -def f(*a, **k): - print(a, sortdict(k)) - -def g(x, *y, **z): - print(x, y, sortdict(z)) - -def h(j=1, a=2, h=3): - print(j, a, h) - -f() -f(1) -f(1, 2) -f(1, 2, 3) - -f(1, 2, 3, *(4, 5)) -f(1, 2, 3, *[4, 5]) -f(1, 2, 3, *UserList([4, 5])) -f(1, 2, 3, **{'a':4, 'b':5}) -f(1, 2, 3, *(4, 5), **{'a':6, 'b':7}) -f(1, 2, 3, x=4, y=5, *(6, 7), **{'a':8, 'b':9}) - - -f(1, 2, 3, **UserDict(a=4, b=5)) -f(1, 2, 3, *(4, 5), **UserDict(a=6, b=7)) -f(1, 2, 3, x=4, y=5, *(6, 7), **UserDict(a=8, b=9)) - - -# Verify clearing of SF bug #733667 -try: - e(c=3) -except TypeError: - pass -else: - print("should raise TypeError: e() got an unexpected keyword argument 'c'") - -try: - g() -except TypeError as err: - print("TypeError:", err) -else: - print("should raise TypeError: not enough arguments; expected 1, got 0") - -try: - g(*()) -except TypeError as err: - print("TypeError:", err) -else: - print("should raise TypeError: not enough arguments; expected 1, got 0") - -try: - g(*(), **{}) -except TypeError as err: - print("TypeError:", err) -else: - print("should raise TypeError: not enough arguments; expected 1, got 0") - -g(1) -g(1, 2) -g(1, 2, 3) -g(1, 2, 3, *(4, 5)) -class Nothing: pass -try: - g(*Nothing()) -except TypeError as attr: - pass -else: - print("should raise TypeError") - -class Nothing: - def __len__(self): - return 5 -try: - g(*Nothing()) -except TypeError as attr: - pass -else: - print("should raise TypeError") - -class Nothing: - def __len__(self): - return 5 - def __getitem__(self, i): - if i < 3: - return i - else: - raise IndexError(i) -g(*Nothing()) - -class Nothing: - def __init__(self): - self.c = 0 - def __iter__(self): - return self -try: - g(*Nothing()) -except TypeError as attr: - pass -else: - print("should raise TypeError") - -class Nothing: - def __init__(self): - self.c = 0 - def __iter__(self): - return self - def __next__(self): - if self.c == 4: - raise StopIteration - c = self.c - self.c += 1 - return c -g(*Nothing()) - -# make sure the function call doesn't stomp on the dictionary? -d = {'a': 1, 'b': 2, 'c': 3} -d2 = d.copy() -verify(d == d2) -g(1, d=4, **d) -print(sortdict(d)) -print(sortdict(d2)) -verify(d == d2, "function call modified dictionary") - -# what about willful misconduct? -def saboteur(**kw): - kw['x'] = locals() # yields a cyclic kw - return kw -d = {} -kw = saboteur(a=1, **d) -verify(d == {}) -# break the cycle -del kw['x'] - -try: - g(1, 2, 3, **{'x':4, 'y':5}) -except TypeError as err: - print(err) -else: - print("should raise TypeError: keyword parameter redefined") - -try: - g(1, 2, 3, a=4, b=5, *(6, 7), **{'a':8, 'b':9}) -except TypeError as err: - print(err) -else: - print("should raise TypeError: keyword parameter redefined") - -try: - f(**{1:2}) -except TypeError as err: - print(err) -else: - print("should raise TypeError: keywords must be strings") - -try: - h(**{'e': 2}) -except TypeError as err: - print(err) -else: - print("should raise TypeError: unexpected keyword argument: e") - -try: - h(*h) -except TypeError as err: - print(err) -else: - print("should raise TypeError: * argument must be a tuple") - -try: - dir(*h) -except TypeError as err: - print(err) -else: - print("should raise TypeError: * argument must be a tuple") - -try: - None(*h) -except TypeError as err: - print(err) -else: - print("should raise TypeError: * argument must be a tuple") - -try: - h(**h) -except TypeError as err: - print(err) -else: - print("should raise TypeError: ** argument must be a dictionary") - -try: - dir(**h) -except TypeError as err: - print(err) -else: - print("should raise TypeError: ** argument must be a dictionary") - -try: - None(**h) -except TypeError as err: - print(err) -else: - print("should raise TypeError: ** argument must be a dictionary") - -try: - dir(b=1,**{'b':1}) -except TypeError as err: - print(err) -else: - print("should raise TypeError: dir() got multiple values for keyword argument 'b'") - -def f2(*a, **b): - return a, b - -d = {} -for i in range(512): - key = 'k%d' % i - d[key] = i -a, b = f2(1, *(2, 3), **d) -print(len(a), len(b), b == d) - -class Foo: - def method(self, arg1, arg2): - return arg1 + arg2 - -x = Foo() -print(Foo.method(*(x, 1, 2))) -print(Foo.method(x, *(1, 2))) -print(Foo.method(*(1, 2, 3))) -print(Foo.method(1, *(2, 3))) - -# A PyCFunction that takes only positional parameters should allow an -# empty keyword dictionary to pass without a complaint, but raise a -# TypeError if the dictionary is non-empty. -id(1, **{}) -try: - id(1, **{"foo": 1}) -except TypeError: - pass -else: - raise TestFailed('expected TypeError; no exception raised') - -a, b, d, e, v, k = 'A', 'B', 'D', 'E', 'V', 'K' -funcs = [] -maxargs = {} -for args in ['', 'a', 'ab']: - for defargs in ['', 'd', 'de']: - for vararg in ['', 'v']: - for kwarg in ['', 'k']: - name = 'z' + args + defargs + vararg + kwarg - arglist = list(args) + ['%s="%s"' % (x, x) for x in defargs] - if vararg: arglist.append('*' + vararg) - if kwarg: arglist.append('**' + kwarg) - decl = (('def %s(%s): print("ok %s", a, b, d, e, v, ' + - 'type(k) is type ("") and k or sortdict(k))') - % (name, ', '.join(arglist), name)) - exec(decl) - func = eval(name) - funcs.append(func) - maxargs[func] = len(args + defargs) - -for name in ['za', 'zade', 'zabk', 'zabdv', 'zabdevk']: - func = eval(name) - for args in [(), (1, 2), (1, 2, 3, 4, 5)]: - for kwargs in ['', 'a', 'd', 'ad', 'abde']: - kwdict = {} - for k in kwargs: kwdict[k] = k + k - print(func.__name__, args, sortdict(kwdict), '->', end=' ') - try: func(*args, **kwdict) - except TypeError as err: print(err) +"""Doctest for method/function calls. + +We're going the use these types for extra testing + + >>> from UserList import UserList + >>> from UserDict import UserDict + +We're defining four helper functions + + >>> def e(a,b): + ... print a, b + + >>> def f(*a, **k): + ... print a, test_support.sortdict(k) + + >>> def g(x, *y, **z): + ... print x, y, test_support.sortdict(z) + + >>> def h(j=1, a=2, h=3): + ... print j, a, h + +Argument list examples + + >>> f() + () {} + >>> f(1) + (1,) {} + >>> f(1, 2) + (1, 2) {} + >>> f(1, 2, 3) + (1, 2, 3) {} + >>> f(1, 2, 3, *(4, 5)) + (1, 2, 3, 4, 5) {} + >>> f(1, 2, 3, *[4, 5]) + (1, 2, 3, 4, 5) {} + >>> f(1, 2, 3, *UserList([4, 5])) + (1, 2, 3, 4, 5) {} + +Here we add keyword arguments + + >>> f(1, 2, 3, **{'a':4, 'b':5}) + (1, 2, 3) {'a': 4, 'b': 5} + >>> f(1, 2, 3, *[4, 5], **{'a':6, 'b':7}) + (1, 2, 3, 4, 5) {'a': 6, 'b': 7} + >>> f(1, 2, 3, x=4, y=5, *(6, 7), **{'a':8, 'b': 9}) + (1, 2, 3, 6, 7) {'a': 8, 'b': 9, 'x': 4, 'y': 5} + + >>> f(1, 2, 3, **UserDict(a=4, b=5)) + (1, 2, 3) {'a': 4, 'b': 5} + >>> f(1, 2, 3, *(4, 5), **UserDict(a=6, b=7)) + (1, 2, 3, 4, 5) {'a': 6, 'b': 7} + >>> f(1, 2, 3, x=4, y=5, *(6, 7), **UserDict(a=8, b=9)) + (1, 2, 3, 6, 7) {'a': 8, 'b': 9, 'x': 4, 'y': 5} + +Examples with invalid arguments (TypeErrors). We're also testing the function +names in the exception messages. + +Verify clearing of SF bug #733667 + + >>> e(c=4) + Traceback (most recent call last): + ... + TypeError: e() got an unexpected keyword argument 'c' + + >>> g() + Traceback (most recent call last): + ... + TypeError: g() takes at least 1 argument (0 given) + + >>> g(*()) + Traceback (most recent call last): + ... + TypeError: g() takes at least 1 argument (0 given) + + >>> g(*(), **{}) + Traceback (most recent call last): + ... + TypeError: g() takes at least 1 argument (0 given) + + >>> g(1) + 1 () {} + >>> g(1, 2) + 1 (2,) {} + >>> g(1, 2, 3) + 1 (2, 3) {} + >>> g(1, 2, 3, *(4, 5)) + 1 (2, 3, 4, 5) {} + + >>> class Nothing: pass + ... + >>> g(*Nothing()) + Traceback (most recent call last): + ... + TypeError: g() argument after * must be a sequence, not instance + + >>> class Nothing: + ... def __len__(self): return 5 + ... + + >>> g(*Nothing()) + Traceback (most recent call last): + ... + TypeError: g() argument after * must be a sequence, not instance + + >>> class Nothing(): + ... def __len__(self): return 5 + ... def __getitem__(self, i): + ... if i<3: return i + ... else: raise IndexError(i) + ... + + >>> g(*Nothing()) + 0 (1, 2) {} + + >>> class Nothing: + ... def __init__(self): self.c = 0 + ... def __iter__(self): return self + ... def next(self): + ... if self.c == 4: + ... raise StopIteration + ... c = self.c + ... self.c += 1 + ... return c + ... + + >>> g(*Nothing()) + 0 (1, 2, 3) {} + +Make sure that the function doesn't stomp the dictionary + + >>> d = {'a': 1, 'b': 2, 'c': 3} + >>> d2 = d.copy() + >>> g(1, d=4, **d) + 1 () {'a': 1, 'b': 2, 'c': 3, 'd': 4} + >>> d == d2 + True + +What about willful misconduct? + + >>> def saboteur(**kw): + ... kw['x'] = 'm' + ... return kw + + >>> d = {} + >>> kw = saboteur(a=1, **d) + >>> d + {} + + + >>> g(1, 2, 3, **{'x': 4, 'y': 5}) + Traceback (most recent call last): + ... + TypeError: g() got multiple values for keyword argument 'x' + + >>> f(**{1:2}) + Traceback (most recent call last): + ... + TypeError: f() keywords must be strings + + >>> h(**{'e': 2}) + Traceback (most recent call last): + ... + TypeError: h() got an unexpected keyword argument 'e' + + >>> h(*h) + Traceback (most recent call last): + ... + TypeError: h() argument after * must be a sequence, not function + + >>> dir(*h) + Traceback (most recent call last): + ... + TypeError: dir() argument after * must be a sequence, not function + + >>> None(*h) + Traceback (most recent call last): + ... + TypeError: NoneType object argument after * must be a sequence, \ +not function + + >>> h(**h) + Traceback (most recent call last): + ... + TypeError: h() argument after ** must be a mapping, not function + + >>> dir(**h) + Traceback (most recent call last): + ... + TypeError: dir() argument after ** must be a mapping, not function + + >>> None(**h) + Traceback (most recent call last): + ... + TypeError: NoneType object argument after ** must be a mapping, \ +not function + + >>> dir(b=1, **{'b': 1}) + Traceback (most recent call last): + ... + TypeError: dir() got multiple values for keyword argument 'b' + +Another helper function + + >>> def f2(*a, **b): + ... return a, b + + + >>> d = {} + >>> for i in xrange(512): + ... key = 'k%d' % i + ... d[key] = i + >>> a, b = f2(1, *(2,3), **d) + >>> len(a), len(b), b == d + (3, 512, True) + + >>> class Foo: + ... def method(self, arg1, arg2): + ... return arg1+arg2 + + >>> x = Foo() + >>> Foo.method(*(x, 1, 2)) + 3 + >>> Foo.method(x, *(1, 2)) + 3 + >>> Foo.method(*(1, 2, 3)) + Traceback (most recent call last): + ... + TypeError: unbound method method() must be called with Foo instance as \ +first argument (got int instance instead) + + >>> Foo.method(1, *[2, 3]) + Traceback (most recent call last): + ... + TypeError: unbound method method() must be called with Foo instance as \ +first argument (got int instance instead) + +A PyCFunction that takes only positional parameters shoud allow an +empty keyword dictionary to pass without a complaint, but raise a +TypeError if te dictionary is not empty + + >>> try: + ... silence = id(1, *{}) + ... True + ... except: + ... False + True + + >>> id(1, **{'foo': 1}) + Traceback (most recent call last): + ... + TypeError: id() takes no keyword arguments + +""" + +from test import test_support + +def test_main(): + import test_extcall # self import + test_support.run_doctest(test_extcall, True) + +if __name__ == '__main__': + test_main() diff --git a/Lib/test/test_parser.py b/Lib/test/test_parser.py index 054d6d2..7269ccb 100644 --- a/Lib/test/test_parser.py +++ b/Lib/test/test_parser.py @@ -1,5 +1,6 @@ import parser import unittest +import sys from test import test_support # @@ -465,6 +466,8 @@ class ParserStackLimitTestCase(unittest.TestCase): def test_trigger_memory_error(self): e = self._nested_expression(100) + print("Expecting 's_push: parser stack overflow' in next line", + file=sys.stderr) self.assertRaises(MemoryError, parser.expr, e) def test_main(): diff --git a/Lib/test/test_pep247.py b/Lib/test/test_pep247.py index 2a2d7ac..fb59d6a 100644 --- a/Lib/test/test_pep247.py +++ b/Lib/test/test_pep247.py @@ -1,56 +1,67 @@ -# -# Test suite to check compliance with PEP 247, the standard API for -# hashing algorithms. -# +""" +Test suite to check compilance with PEP 247, the standard API +for hashing algorithms +""" +import warnings +warnings.filterwarnings('ignore', 'the md5 module is deprecated.*', + DeprecationWarning) +warnings.filterwarnings('ignore', 'the sha module is deprecated.*', + DeprecationWarning) import hmac +import md5 +import sha +import unittest +from test import test_support -import hmac -from test.test_support import verbose - -def check_hash_module(module, key=None): - assert hasattr(module, 'digest_size'), "Must have digest_size" - assert (module.digest_size is None or - module.digest_size > 0), "digest_size must be None or positive" - - if key is not None: - obj1 = module.new(key) - obj2 = module.new(key, b"string") - - h1 = module.new(key, b"string").digest() - obj3 = module.new(key) ; obj3.update(b"string") ; h2 = obj3.digest() - assert h1 == h2, "Hashes must match" - - else: - obj1 = module.new() - obj2 = module.new(b"string") - - h1 = module.new(b"string").digest() - obj3 = module.new() ; obj3.update(b"string") ; h2 = obj3.digest() - assert h1 == h2, "Hashes must match" - - assert hasattr(obj1, 'digest_size'), "Objects must have digest_size attr" - if module.digest_size is not None: - assert obj1.digest_size == module.digest_size, "digest_size must match" - assert obj1.digest_size == len(h1), "digest_size must match actual size" - obj1.update(b"string") - obj_copy = obj1.copy() - assert obj1.digest() == obj_copy.digest(), "Copied objects must match" - assert obj1.hexdigest() == obj_copy.hexdigest(), \ - "Copied objects must match" - digest, hexdigest = obj1.digest(), obj1.hexdigest() - hd2 = "" - for byte in digest: - hd2 += "%02x" % byte - assert hd2 == hexdigest, "hexdigest doesn't appear correct" - - if verbose: - print('Module', module.__name__, 'seems to comply with PEP 247') +class Pep247Test(unittest.TestCase): + def check_module(self, module, key=None): + self.assert_(hasattr(module, 'digest_size')) + self.assert_(module.digest_size is None or module.digest_size > 0) + if not key is None: + obj1 = module.new(key) + obj2 = module.new(key, 'string') + h1 = module.new(key, 'string').digest() + obj3 = module.new(key) + obj3.update('string') + h2 = obj3.digest() + else: + obj1 = module.new() + obj2 = module.new('string') + h1 = module.new('string').digest() + obj3 = module.new() + obj3.update('string') + h2 = obj3.digest() + self.assertEquals(h1, h2) + self.assert_(hasattr(obj1, 'digest_size')) -def test_main(): - check_hash_module(hmac, key=b'abc') + if not module.digest_size is None: + self.assertEquals(obj1.digest_size, module.digest_size) + + self.assertEquals(obj1.digest_size, len(h1)) + obj1.update('string') + obj_copy = obj1.copy() + self.assertEquals(obj1.digest(), obj_copy.digest()) + self.assertEquals(obj1.hexdigest(), obj_copy.hexdigest()) + + digest, hexdigest = obj1.digest(), obj1.hexdigest() + hd2 = "" + for byte in digest: + hd2 += '%02x' % ord(byte) + self.assertEquals(hd2, hexdigest) + def test_md5(self): + self.check_module(md5) + + def test_sha(self): + self.check_module(sha) + + def test_hmac(self): + self.check_module(hmac, key='abc') + +def test_main(): + test_support.run_unittest(Pep247Test) if __name__ == '__main__': test_main() diff --git a/Lib/test/test_smtplib.py b/Lib/test/test_smtplib.py index a9d5672..e1c198f5 100644 --- a/Lib/test/test_smtplib.py +++ b/Lib/test/test_smtplib.py @@ -348,11 +348,11 @@ class SMTPSimTests(TestCase): def testBasic(self): # smoke test - smtp = smtplib.SMTP(HOST, PORT, local_hostname='localhost', timeout=3) + smtp = smtplib.SMTP(HOST, PORT, local_hostname='localhost', timeout=15) smtp.quit() def testEHLO(self): - smtp = smtplib.SMTP(HOST, PORT, local_hostname='localhost', timeout=3) + smtp = smtplib.SMTP(HOST, PORT, local_hostname='localhost', timeout=15) # no features should be present before the EHLO self.assertEqual(smtp.esmtp_features, {}) @@ -373,7 +373,7 @@ class SMTPSimTests(TestCase): smtp.quit() def testVRFY(self): - smtp = smtplib.SMTP(HOST, PORT, local_hostname='localhost', timeout=3) + smtp = smtplib.SMTP(HOST, PORT, local_hostname='localhost', timeout=15) for email, name in sim_users.items(): expected_known = (250, bytes('%s %s' % @@ -388,7 +388,7 @@ class SMTPSimTests(TestCase): smtp.quit() def testEXPN(self): - smtp = smtplib.SMTP(HOST, PORT, local_hostname='localhost', timeout=3) + smtp = smtplib.SMTP(HOST, PORT, local_hostname='localhost', timeout=15) for listname, members in sim_lists.items(): users = [] diff --git a/Lib/test/test_strftime.py b/Lib/test/test_strftime.py index 0870134..5af5a0c 100755 --- a/Lib/test/test_strftime.py +++ b/Lib/test/test_strftime.py @@ -1,158 +1,185 @@ -#! /usr/bin/env python - -# Sanity checker for time.strftime - -import time, calendar, sys, re -from test.test_support import verbose - -def main(): - global verbose - # For C Python, these tests expect C locale, so we try to set that - # explicitly. For Jython, Finn says we need to be in the US locale; my - # understanding is that this is the closest Java gets to C's "C" locale. - # Jython ought to supply an _locale module which Does The Right Thing, but - # this is the best we can do given today's state of affairs. - try: - import java - java.util.Locale.setDefault(java.util.Locale.US) - except ImportError: - # Can't do this first because it will succeed, even in Jython - import locale - locale.setlocale(locale.LC_TIME, 'C') - now = time.time() - strftest(now) - verbose = 0 - # Try a bunch of dates and times, chosen to vary through time of - # day and daylight saving time - for j in range(-5, 5): - for i in range(25): - strftest(now + (i + j*100)*23*3603) +""" +Unittest for time.strftime +""" + +import calendar +import sys +import os +import re +from test import test_support +import time +import unittest + + +# helper functions +def fixasctime(s): + if s[8] == ' ': + s = s[:8] + '0' + s[9:] + return s def escapestr(text, ampm): - """Escape text to deal with possible locale values that have regex - syntax while allowing regex syntax used for the comparison.""" + """ + Escape text to deal with possible locale values that have regex + syntax while allowing regex syntax used for comparison. + """ new_text = re.escape(text) new_text = new_text.replace(re.escape(ampm), ampm) - new_text = new_text.replace("\%", "%") - new_text = new_text.replace("\:", ":") - new_text = new_text.replace("\?", "?") + new_text = new_text.replace('\%', '%') + new_text = new_text.replace('\:', ':') + new_text = new_text.replace('\?', '?') return new_text -def strftest(now): - if verbose: - print("strftime test for", time.ctime(now)) - nowsecs = str(int(now))[:-1] - gmt = time.gmtime(now) - now = time.localtime(now) - - if now[3] < 12: ampm='(AM|am)' - else: ampm='(PM|pm)' - - jan1 = time.localtime(time.mktime((now[0], 1, 1, 0, 0, 0, 0, 1, 0))) - - try: - if now[8]: tz = time.tzname[1] - else: tz = time.tzname[0] - except AttributeError: - tz = '' - - if now[3] > 12: clock12 = now[3] - 12 - elif now[3] > 0: clock12 = now[3] - else: clock12 = 12 - - # Make sure any characters that could be taken as regex syntax is - # escaped in escapestr() - expectations = ( - ('%a', calendar.day_abbr[now[6]], 'abbreviated weekday name'), - ('%A', calendar.day_name[now[6]], 'full weekday name'), - ('%b', calendar.month_abbr[now[1]], 'abbreviated month name'), - ('%B', calendar.month_name[now[1]], 'full month name'), - # %c see below - ('%d', '%02d' % now[2], 'day of month as number (00-31)'), - ('%H', '%02d' % now[3], 'hour (00-23)'), - ('%I', '%02d' % clock12, 'hour (01-12)'), - ('%j', '%03d' % now[7], 'julian day (001-366)'), - ('%m', '%02d' % now[1], 'month as number (01-12)'), - ('%M', '%02d' % now[4], 'minute, (00-59)'), - ('%p', ampm, 'AM or PM as appropriate'), - ('%S', '%02d' % now[5], 'seconds of current time (00-60)'), - ('%U', '%02d' % ((now[7] + jan1[6])//7), - 'week number of the year (Sun 1st)'), - ('%w', '0?%d' % ((1+now[6]) % 7), 'weekday as a number (Sun 1st)'), - ('%W', '%02d' % ((now[7] + (jan1[6] - 1)%7)//7), - 'week number of the year (Mon 1st)'), - # %x see below - ('%X', '%02d:%02d:%02d' % (now[3], now[4], now[5]), '%H:%M:%S'), - ('%y', '%02d' % (now[0]%100), 'year without century'), - ('%Y', '%d' % now[0], 'year with century'), - # %Z see below - ('%%', '%', 'single percent sign'), - ) - nonstandard_expectations = ( - # These are standard but don't have predictable output - ('%c', fixasctime(time.asctime(now)), 'near-asctime() format'), - ('%x', '%02d/%02d/%02d' % (now[1], now[2], (now[0]%100)), - '%m/%d/%y %H:%M:%S'), - ('%Z', '%s' % tz, 'time zone name'), - - # These are some platform specific extensions - ('%D', '%02d/%02d/%02d' % (now[1], now[2], (now[0]%100)), 'mm/dd/yy'), - ('%e', '%2d' % now[2], 'day of month as number, blank padded ( 0-31)'), - ('%h', calendar.month_abbr[now[1]], 'abbreviated month name'), - ('%k', '%2d' % now[3], 'hour, blank padded ( 0-23)'), - ('%n', '\n', 'newline character'), - ('%r', '%02d:%02d:%02d %s' % (clock12, now[4], now[5], ampm), - '%I:%M:%S %p'), - ('%R', '%02d:%02d' % (now[3], now[4]), '%H:%M'), - ('%s', nowsecs, 'seconds since the Epoch in UCT'), - ('%t', '\t', 'tab character'), - ('%T', '%02d:%02d:%02d' % (now[3], now[4], now[5]), '%H:%M:%S'), - ('%3y', '%03d' % (now[0]%100), - 'year without century rendered using fieldwidth'), - ) +class StrftimeTest(unittest.TestCase): - if verbose: - print("Strftime test, platform: %s, Python version: %s" % \ - (sys.platform, sys.version.split()[0])) + def _update_variables(self, now): + # we must update the local variables on every cycle + self.gmt = time.gmtime(now) + now = time.localtime(now) + + if now[3] < 12: self.ampm='(AM|am)' + else: self.ampm='(PM|pm)' + + self.jan1 = time.localtime(time.mktime((now[0], 1, 1, 0, 0, 0, 0, 1, 0))) - for e in expectations: try: - result = time.strftime(e[0], now) - except ValueError as error: - print("Standard '%s' format gave error:" % e[0], error) - continue - if re.match(escapestr(e[1], ampm), result): continue - if not result or result[0] == '%': - print("Does not support standard '%s' format (%s)" % (e[0], e[2])) - else: - print("Conflict for %s (%s):" % (e[0], e[2])) - print(" Expected %s, but got %s" % (e[1], result)) - - for e in nonstandard_expectations: + if now[8]: self.tz = time.tzname[1] + else: self.tz = time.tzname[0] + except AttributeError: + self.tz = '' + + if now[3] > 12: self.clock12 = now[3] - 12 + elif now[3] > 0: self.clock12 = now[3] + else: self.clock12 = 12 + + self.now = now + + def setUp(self): try: - result = time.strftime(e[0], now) - except ValueError as result: - if verbose: - print("Error for nonstandard '%s' format (%s): %s" % \ - (e[0], e[2], str(result))) - continue - if re.match(escapestr(e[1], ampm), result): - if verbose: - print("Supports nonstandard '%s' format (%s)" % (e[0], e[2])) - elif not result or result[0] == '%': - if verbose: - print("Does not appear to support '%s' format (%s)" % (e[0], - e[2])) - else: - if verbose: - print("Conflict for nonstandard '%s' format (%s):" % (e[0], - e[2])) + import java + java.util.Locale.setDefault(java.util.Locale.US) + except ImportError: + import locale + locale.setlocale(locale.LC_TIME, 'C') + + def test_strftime(self): + now = time.time() + self._update_variables(now) + self.strftest1(now) + self.strftest2(now) + + if test_support.verbose: + print("Strftime test, platform: %s, Python version: %s" % \ + (sys.platform, sys.version.split()[0])) + + for j in range(-5, 5): + for i in range(25): + arg = now + (i+j*100)*23*3603 + self._update_variables(arg) + self.strftest1(arg) + self.strftest2(arg) + + def strftest1(self, now): + if test_support.verbose: + print("strftime test for", time.ctime(now)) + now = self.now + # Make sure any characters that could be taken as regex syntax is + # escaped in escapestr() + expectations = ( + ('%a', calendar.day_abbr[now[6]], 'abbreviated weekday name'), + ('%A', calendar.day_name[now[6]], 'full weekday name'), + ('%b', calendar.month_abbr[now[1]], 'abbreviated month name'), + ('%B', calendar.month_name[now[1]], 'full month name'), + # %c see below + ('%d', '%02d' % now[2], 'day of month as number (00-31)'), + ('%H', '%02d' % now[3], 'hour (00-23)'), + ('%I', '%02d' % self.clock12, 'hour (01-12)'), + ('%j', '%03d' % now[7], 'julian day (001-366)'), + ('%m', '%02d' % now[1], 'month as number (01-12)'), + ('%M', '%02d' % now[4], 'minute, (00-59)'), + ('%p', self.ampm, 'AM or PM as appropriate'), + ('%S', '%02d' % now[5], 'seconds of current time (00-60)'), + ('%U', '%02d' % ((now[7] + self.jan1[6])//7), + 'week number of the year (Sun 1st)'), + ('%w', '0?%d' % ((1+now[6]) % 7), 'weekday as a number (Sun 1st)'), + ('%W', '%02d' % ((now[7] + (self.jan1[6] - 1)%7)//7), + 'week number of the year (Mon 1st)'), + # %x see below + ('%X', '%02d:%02d:%02d' % (now[3], now[4], now[5]), '%H:%M:%S'), + ('%y', '%02d' % (now[0]%100), 'year without century'), + ('%Y', '%d' % now[0], 'year with century'), + # %Z see below + ('%%', '%', 'single percent sign'), + ) + + for e in expectations: + # musn't raise a value error + try: + result = time.strftime(e[0], now) + except ValueError as error: + print("Standard '%s' format gaver error:" % (e[0], error)) + continue + if re.match(escapestr(e[1], self.ampm), result): + continue + if not result or result[0] == '%': + print("Does not support standard '%s' format (%s)" % \ + (e[0], e[2])) + else: + print("Conflict for %s (%s):" % (e[0], e[2])) print(" Expected %s, but got %s" % (e[1], result)) -def fixasctime(s): - if s[8] == ' ': - s = s[:8] + '0' + s[9:] - return s + def strftest2(self, now): + nowsecs = str(int(now))[:-1] + now = self.now + + nonstandard_expectations = ( + # These are standard but don't have predictable output + ('%c', fixasctime(time.asctime(now)), 'near-asctime() format'), + ('%x', '%02d/%02d/%02d' % (now[1], now[2], (now[0]%100)), + '%m/%d/%y %H:%M:%S'), + ('%Z', '%s' % self.tz, 'time zone name'), + + # These are some platform specific extensions + ('%D', '%02d/%02d/%02d' % (now[1], now[2], (now[0]%100)), 'mm/dd/yy'), + ('%e', '%2d' % now[2], 'day of month as number, blank padded ( 0-31)'), + ('%h', calendar.month_abbr[now[1]], 'abbreviated month name'), + ('%k', '%2d' % now[3], 'hour, blank padded ( 0-23)'), + ('%n', '\n', 'newline character'), + ('%r', '%02d:%02d:%02d %s' % (self.clock12, now[4], now[5], self.ampm), + '%I:%M:%S %p'), + ('%R', '%02d:%02d' % (now[3], now[4]), '%H:%M'), + ('%s', nowsecs, 'seconds since the Epoch in UCT'), + ('%t', '\t', 'tab character'), + ('%T', '%02d:%02d:%02d' % (now[3], now[4], now[5]), '%H:%M:%S'), + ('%3y', '%03d' % (now[0]%100), + 'year without century rendered using fieldwidth'), + ) + -main() + for e in nonstandard_expectations: + try: + result = time.strftime(e[0], now) + except ValueError as result: + msg = "Error for nonstandard '%s' format (%s): %s" % \ + (e[0], e[2], str(result)) + if test_support.verbose: + print(msg) + continue + if re.match(escapestr(e[1], self.ampm), result): + if test_support.verbose: + print("Supports nonstandard '%s' format (%s)" % (e[0], e[2])) + elif not result or result[0] == '%': + if test_support.verbose: + print("Does not appear to support '%s' format (%s)" % \ + (e[0], e[2])) + else: + if test_support.verbose: + print("Conflict for nonstandard '%s' format (%s):" % \ + (e[0], e[2])) + print(" Expected %s, but got %s" % (e[1], result)) + +def test_main(): + test_support.run_unittest(StrftimeTest) + +if __name__ == '__main__': + test_main() diff --git a/Lib/test/test_thread.py b/Lib/test/test_thread.py index c89c5a1..01d6655 100644 --- a/Lib/test/test_thread.py +++ b/Lib/test/test_thread.py @@ -9,10 +9,13 @@ import time NUMTASKS = 10 NUMTRIPS = 3 +_print_mutex = thread.allocate_lock() + def verbose_print(arg): """Helper function for printing out debugging output.""" if test_support.verbose: - print(arg) + with _print_mutex: + print(arg) class BasicThreadTest(unittest.TestCase): @@ -36,8 +39,8 @@ class ThreadRunningTests(BasicThreadTest): def task(self, ident): with self.random_mutex: - delay = random.random() * NUMTASKS - verbose_print("task %s will run for %s" % (ident, round(delay, 1))) + delay = random.random() / 10000.0 + verbose_print("task %s will run for %sus" % (ident, round(delay*1e6))) time.sleep(delay) verbose_print("task %s done" % ident) with self.running_mutex: @@ -136,11 +139,12 @@ class BarrierTest(BasicThreadTest): # give it a good chance to enter the next # barrier before the others are all out # of the current one - delay = 0.001 + delay = 0 else: with self.random_mutex: - delay = random.random() * NUMTASKS - verbose_print("task %s will run for %s" % (ident, round(delay, 1))) + delay = random.random() / 10000.0 + verbose_print("task %s will run for %sus" % + (ident, round(delay * 1e6))) time.sleep(delay) verbose_print("task %s entering %s" % (ident, i)) self.bar.enter() diff --git a/Lib/test/test_types.py b/Lib/test/test_types.py index 654bc11..dae250e 100644 --- a/Lib/test/test_types.py +++ b/Lib/test/test_types.py @@ -451,6 +451,15 @@ class TypesTests(unittest.TestCase): test(1.1234e20, 'e', '1.123400e+20') test(1.1234e20, 'E', '1.123400E+20') + # No format code means use g, but must have a decimal + # and a number after the decimal. This is tricky, because + # a totaly empty format specifier means something else. + # So, just use a sign flag + test(1e200, '+g', '+1e+200') + test(1e200, '+', '+1.0e+200') + test(1.1e200, '+g', '+1.1e+200') + test(1.1e200, '+', '+1.1e+200') + # % formatting test(-1.0, '%', '-100.000000%') diff --git a/Lib/test/test_winsound.py b/Lib/test/test_winsound.py index 0d6ddf9..7cdc275 100644 --- a/Lib/test/test_winsound.py +++ b/Lib/test/test_winsound.py @@ -27,8 +27,16 @@ class BeepTest(unittest.TestCase): winsound.Beep(37, 75) winsound.Beep(32767, 75) else: - self.assertRaises(RuntimeError, winsound.Beep, 37, 75) - self.assertRaises(RuntimeError, winsound.Beep, 32767, 75) + # The behaviour of winsound.Beep() seems to differ between + # different versions of Windows when there's either a) no + # sound card entirely, b) legacy beep driver has been disabled, + # or c) the legacy beep driver has been uninstalled. Sometimes + # RuntimeErrors are raised, sometimes they're not. Meh. + try: + winsound.Beep(37, 75) + winsound.Beep(32767, 75) + except RuntimeError: + pass def test_increasingfrequency(self): if _have_soundcard(): diff --git a/Lib/test/test_zlib.py b/Lib/test/test_zlib.py index 6b7d4a6..0adf507 100644 --- a/Lib/test/test_zlib.py +++ b/Lib/test/test_zlib.py @@ -48,6 +48,7 @@ class ChecksumTestCase(unittest.TestCase): + class ExceptionTestCase(unittest.TestCase): # make sure we generate some expected errors def test_badlevel(self): diff --git a/Misc/developers.txt b/Misc/developers.txt index ba1c16b..7c9df33 100644 --- a/Misc/developers.txt +++ b/Misc/developers.txt @@ -17,6 +17,12 @@ the format to accommodate documentation needs as they arise. Permissions History ------------------- +- David Wolever was given SVN access on 17 March 2008 by MvL, + for 2to3 work. + +- Trent Nelson was given SVN access on 17 March 2008 by MvL, + for general contributions to Python. + - Mark Dickinson was given SVN access on 6 January 2008 by Facundo Batista for his work on mathemathics and number related issues. diff --git a/Modules/datetimemodule.c b/Modules/datetimemodule.c index 0317dbf..711adba 100644 --- a/Modules/datetimemodule.c +++ b/Modules/datetimemodule.c @@ -1173,7 +1173,7 @@ make_Zreplacement(PyObject *object, PyObject *tzinfoarg) static PyObject * make_freplacement(PyObject *object) { - char freplacement[7]; + char freplacement[64]; if (PyTime_Check(object)) sprintf(freplacement, "%06d", TIME_GET_MICROSECOND(object)); else if (PyDateTime_Check(object)) diff --git a/Objects/stringlib/formatter.h b/Objects/stringlib/formatter.h index e8e83f4..3ca14fa 100644 --- a/Objects/stringlib/formatter.h +++ b/Objects/stringlib/formatter.h @@ -925,11 +925,16 @@ FORMAT_FLOAT(PyObject *value, PyObject *args) } /* parse the format_spec */ - if (!parse_internal_render_format_spec(format_spec, &format, 'g')) + if (!parse_internal_render_format_spec(format_spec, &format, '\0')) goto done; /* type conversion? */ switch (format.type) { + case '\0': + /* 'Z' means like 'g', but with at least one decimal. See + PyOS_ascii_formatd */ + format.type = 'Z'; + /* Deliberate fall through to the next case statement */ case 'e': case 'E': case 'f': diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index dcad808..fc3ef76 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -272,7 +272,8 @@ int unicode_resize(register PyUnicodeObject *unicode, it contains). */ oldstr = unicode->str; - PyMem_RESIZE(unicode->str, Py_UNICODE, length + 1); + unicode->str = PyObject_REALLOC(unicode->str, + sizeof(Py_UNICODE) * (length + 1)); if (!unicode->str) { unicode->str = (Py_UNICODE *)oldstr; PyErr_NoMemory(); @@ -322,20 +323,23 @@ PyUnicodeObject *_PyUnicode_New(Py_ssize_t length) never downsize it. */ if ((unicode->length < length) && unicode_resize(unicode, length) < 0) { - PyMem_DEL(unicode->str); + PyObject_DEL(unicode->str); goto onError; } } else { - unicode->str = PyMem_NEW(Py_UNICODE, length + 1); + size_t new_size = sizeof(Py_UNICODE) * ((size_t)length + 1); + unicode->str = (Py_UNICODE*) PyObject_MALLOC(new_size); } PyObject_INIT(unicode, &PyUnicode_Type); } else { + size_t new_size; unicode = PyObject_New(PyUnicodeObject, &PyUnicode_Type); if (unicode == NULL) return NULL; - unicode->str = PyMem_NEW(Py_UNICODE, length + 1); + new_size = sizeof(Py_UNICODE) * ((size_t)length + 1); + unicode->str = (Py_UNICODE*) PyObject_MALLOC(new_size); } if (!unicode->str) { @@ -389,7 +393,7 @@ void unicode_dealloc(register PyUnicodeObject *unicode) numfree < PyUnicode_MAXFREELIST) { /* Keep-Alive optimization */ if (unicode->length >= KEEPALIVE_SIZE_LIMIT) { - PyMem_DEL(unicode->str); + PyObject_DEL(unicode->str); unicode->str = NULL; unicode->length = 0; } @@ -403,7 +407,7 @@ void unicode_dealloc(register PyUnicodeObject *unicode) numfree++; } else { - PyMem_DEL(unicode->str); + PyObject_DEL(unicode->str); Py_XDECREF(unicode->defenc); Py_TYPE(unicode)->tp_free((PyObject *)unicode); } @@ -640,7 +644,7 @@ PyUnicode_FromFormatV(const char *format, va_list vargs) /* step 2: allocate memory for the results of * PyObject_Str()/PyObject_Repr() calls */ if (callcount) { - callresults = PyMem_Malloc(sizeof(PyObject *)*callcount); + callresults = PyObject_Malloc(sizeof(PyObject *)*callcount); if (!callresults) { PyErr_NoMemory(); return NULL; @@ -787,7 +791,7 @@ PyUnicode_FromFormatV(const char *format, va_list vargs) } expand: if (abuffersize > 20) { - abuffer = PyMem_Malloc(abuffersize); + abuffer = PyObject_Malloc(abuffersize); if (!abuffer) { PyErr_NoMemory(); goto fail; @@ -950,9 +954,9 @@ PyUnicode_FromFormatV(const char *format, va_list vargs) end: if (callresults) - PyMem_Free(callresults); + PyObject_Free(callresults); if (abuffer) - PyMem_Free(abuffer); + PyObject_Free(abuffer); _PyUnicode_Resize(&string, s - PyUnicode_AS_UNICODE(string)); return string; fail: @@ -962,10 +966,10 @@ PyUnicode_FromFormatV(const char *format, va_list vargs) Py_DECREF(*callresult2); ++callresult2; } - PyMem_Free(callresults); + PyObject_Free(callresults); } if (abuffer) - PyMem_Free(abuffer); + PyObject_Free(abuffer); return NULL; } @@ -8277,8 +8281,8 @@ unicode_subscript(PyUnicodeObject* self, PyObject* item) return PyUnicode_FromUnicode(self->str + start, slicelength); } else { source_buf = PyUnicode_AS_UNICODE((PyObject*)self); - result_buf = (Py_UNICODE *)PyMem_MALLOC(slicelength* - sizeof(Py_UNICODE)); + result_buf = (Py_UNICODE *)PyObject_MALLOC(slicelength* + sizeof(Py_UNICODE)); if (result_buf == NULL) return PyErr_NoMemory(); @@ -8288,7 +8292,7 @@ unicode_subscript(PyUnicodeObject* self, PyObject* item) } result = PyUnicode_FromUnicode(result_buf, slicelength); - PyMem_FREE(result_buf); + PyObject_FREE(result_buf); return result; } } else { @@ -9030,7 +9034,7 @@ unicode_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds) Py_DECREF(tmp); return NULL; } - pnew->str = PyMem_NEW(Py_UNICODE, n+1); + pnew->str = (Py_UNICODE*) PyObject_MALLOC(sizeof(Py_UNICODE) * (n+1)); if (pnew->str == NULL) { _Py_ForgetReference((PyObject *)pnew); PyObject_Del(pnew); @@ -9147,7 +9151,7 @@ PyUnicode_ClearFreeList(void) PyUnicodeObject *v = u; u = *(PyUnicodeObject **)u; if (v->str) - PyMem_DEL(v->str); + PyObject_DEL(v->str); Py_XDECREF(v->defenc); PyObject_Del(v); numfree--; diff --git a/PCbuild/python.vcproj b/PCbuild/python.vcproj index 17b29a2..f5f4605 100644 --- a/PCbuild/python.vcproj +++ b/PCbuild/python.vcproj @@ -290,7 +290,7 @@ AdditionalDependencies="odbccp32.lib" OutputFile="$(OutDir)\python_d.exe" SubSystem="1" - StackReserveSize="2000000" + StackReserveSize="2100000" BaseAddress="0x1d000000" /> = dst+n || dst >= src+n) - return memcpy(dst, src, n); - if (src > dst) { - while (--n >= 0) - *dst++ = *src++; - } - else if (src < dst) { - src += n; - dst += n; - while (--n >= 0) - *--dst = *--src; - } - return realdst; -} diff --git a/Python/pystrtod.c b/Python/pystrtod.c index 16efa9d..2ca8402 100644 --- a/Python/pystrtod.c +++ b/Python/pystrtod.c @@ -7,7 +7,6 @@ #define ISSPACE(c) ((c) == ' ' || (c) == '\f' || (c) == '\n' || \ (c) == '\r' || (c) == '\t' || (c) == '\v') #define ISDIGIT(c) ((c) >= '0' && (c) <= '9') -#define ISXDIGIT(c) (ISDIGIT(c) || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F')) /** @@ -123,7 +122,8 @@ PyOS_ascii_strtod(const char *nptr, char **endptr) errno = EINVAL; return val; } - /* For the other cases, we need not convert the decimal point */ + /* For the other cases, we need not convert the decimal + point */ } /* Set errno to zero, so that we can distinguish zero results @@ -134,7 +134,8 @@ PyOS_ascii_strtod(const char *nptr, char **endptr) { char *copy, *c; - /* We need to convert the '.' to the locale specific decimal point */ + /* We need to convert the '.' to the locale specific decimal + point */ copy = (char *)PyMem_MALLOC(end - digits_pos + 1 + decimal_point_len); if (copy == NULL) { @@ -149,7 +150,8 @@ PyOS_ascii_strtod(const char *nptr, char **endptr) c += decimal_point_pos - digits_pos; memcpy(c, decimal_point, decimal_point_len); c += decimal_point_len; - memcpy(c, decimal_point_pos + 1, end - (decimal_point_pos + 1)); + memcpy(c, decimal_point_pos + 1, + end - (decimal_point_pos + 1)); c += end - (decimal_point_pos + 1); *c = 0; @@ -198,7 +200,7 @@ as necessary to represent the exponent. /** * PyOS_ascii_formatd: * @buffer: A buffer to place the resulting string in - * @buf_len: The length of the buffer. + * @buf_size: The length of the buffer. * @format: The printf()-style format to use for the * code to use for converting. * @d: The #gdouble to convert @@ -209,12 +211,14 @@ as necessary to represent the exponent. * specifiers are 'e', 'E', 'f', 'F', 'g', 'G', and 'n'. * * 'n' is the same as 'g', except it uses the current locale. + * 'Z' is the same as 'g', except it always has a decimal and + * at least one digit after the decimal. * * Return value: The pointer to the buffer with the converted string. **/ char * PyOS_ascii_formatd(char *buffer, - size_t buf_len, + size_t buf_size, const char *format, double d) { @@ -227,20 +231,13 @@ PyOS_ascii_formatd(char *buffer, can't modify it directly. FLOAT_FORMATBUFLEN should be longer than we ever need this to be. There's an upcoming check to ensure it's big enough. */ + /* Issue 2264: code 'Z' requires copying the format. 'Z' is 'g', but + also with at least one character past the decimal. */ char tmp_format[FLOAT_FORMATBUFLEN]; -/* g_return_val_if_fail (buffer != NULL, NULL); */ -/* g_return_val_if_fail (format[0] == '%', NULL); */ -/* g_return_val_if_fail (strpbrk (format + 1, "'l%") == NULL, NULL); */ - /* The last character in the format string must be the format char */ format_char = format[format_len - 1]; -/* g_return_val_if_fail (format_char == 'e' || format_char == 'E' || */ -/* format_char == 'f' || format_char == 'F' || */ -/* format_char == 'g' || format_char == 'G', */ -/* NULL); */ - if (format[0] != '%') return NULL; @@ -251,19 +248,24 @@ PyOS_ascii_formatd(char *buffer, if (strpbrk(format + 1, "'l%")) return NULL; + /* Also curious about this function is that it accepts format strings + like "%xg", which are invalid for floats. In general, the + interface to this function is not very good, but changing it is + difficult because it's a public API. */ + if (!(format_char == 'e' || format_char == 'E' || format_char == 'f' || format_char == 'F' || format_char == 'g' || format_char == 'G' || - format_char == 'n')) + format_char == 'n' || format_char == 'Z')) return NULL; - /* Map 'n' format_char to 'g', by copying the format string and - replacing the final 'n' with a 'g' */ - if (format_char == 'n') { + /* Map 'n' or 'Z' format_char to 'g', by copying the format string and + replacing the final char with a 'g' */ + if (format_char == 'n' || format_char == 'Z') { if (format_len + 1 >= sizeof(tmp_format)) { /* The format won't fit in our copy. Error out. In - practice, this will never happen and will be detected - by returning NULL */ + practice, this will never happen and will be + detected by returning NULL */ return NULL; } strcpy(tmp_format, format); @@ -271,8 +273,9 @@ PyOS_ascii_formatd(char *buffer, format = tmp_format; } + /* Have PyOS_snprintf do the hard work */ - PyOS_snprintf(buffer, buf_len, format, d); + PyOS_snprintf(buffer, buf_size, format, d); /* Get the current local, and find the decimal point character (or string?). Convert that string back to a dot. Do not do this if @@ -294,7 +297,8 @@ PyOS_ascii_formatd(char *buffer, while (isdigit(Py_CHARMASK(*p))) p++; - if (strncmp(p, decimal_point, decimal_point_len) == 0) { + if (strncmp(p, decimal_point, + decimal_point_len) == 0) { *p = '.'; p++; if (decimal_point_len > 1) { @@ -343,7 +347,8 @@ PyOS_ascii_formatd(char *buffer, if we can delete some of the leading zeros */ if (significant_digit_cnt < MIN_EXPONENT_DIGITS) significant_digit_cnt = MIN_EXPONENT_DIGITS; - extra_zeros_cnt = exponent_digit_cnt - significant_digit_cnt; + extra_zeros_cnt = exponent_digit_cnt - + significant_digit_cnt; /* Delete extra_zeros_cnt worth of characters from the front of the exponent */ @@ -360,7 +365,7 @@ PyOS_ascii_formatd(char *buffer, until there are 2, if there's enough room */ int zeros = MIN_EXPONENT_DIGITS - exponent_digit_cnt; if (start + zeros + exponent_digit_cnt + 1 - < buffer + buf_len) { + < buffer + buf_size) { memmove(start + zeros, start, exponent_digit_cnt + 1); memset(start, '0', zeros); @@ -368,6 +373,49 @@ PyOS_ascii_formatd(char *buffer, } } + /* If format_char is 'Z', make sure we have at least one character + after the decimal point (and make sure we have a decimal point). */ + if (format_char == 'Z') { + int insert_count = 0; + char* chars_to_insert; + + /* search for the first non-digit character */ + p = buffer; + while (*p && isdigit(Py_CHARMASK(*p))) + ++p; + + if (*p == '.') { + if (isdigit(Py_CHARMASK(*(p+1)))) { + /* Nothing to do, we already have a decimal + point and a digit after it */ + } + else { + /* We have a decimal point, but no following + digit. Insert a zero after the decimal. */ + ++p; + chars_to_insert = "0"; + insert_count = 1; + } + } + else { + chars_to_insert = ".0"; + insert_count = 2; + } + if (insert_count) { + size_t buf_len = strlen(buffer); + if (buf_len + insert_count + 1 >= buf_size) { + /* If there is not enough room in the buffer + for the additional text, just skip it. It's + not worth generating an error over. */ + } + else { + memmove(p + insert_count, p, + buffer + strlen(buffer) - p + 1); + memcpy(p, chars_to_insert, insert_count); + } + } + } + return buffer; } diff --git a/Python/strerror.c b/Python/strerror.c deleted file mode 100644 index 55f8342..0000000 --- a/Python/strerror.c +++ /dev/null @@ -1,19 +0,0 @@ - -/* PD implementation of strerror() for systems that don't have it. - Author: Guido van Rossum, CWI Amsterdam, Oct. 1990, . */ - -#include -#include "Python.h" - -extern int sys_nerr; -extern char *sys_errlist[]; - -char * -strerror(int err) -{ - static char buf[20]; - if (err >= 0 && err < sys_nerr) - return sys_errlist[err]; - PyOS_snprintf(buf, sizeof(buf), "Unknown errno %d", err); - return buf; -} diff --git a/configure b/configure index 5046065..a1f184c 100755 --- a/configure +++ b/configure @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.in Revision: 61238 . +# From configure.in Revision: 61306 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.61 for python 3.0. # @@ -4509,7 +4509,8 @@ echo "${ECHO_T}$ac_cv_no_strict_aliasing_ok" >&6; } ;; # is there any other compiler on Darwin besides gcc? Darwin*) - BASECFLAGS="$BASECFLAGS -Wno-long-double -no-cpp-precomp -mno-fused-madd" + # -Wno-long-double, -no-cpp-precomp, and -mno-fused-madd + # used to be here, but non-Apple gcc doesn't accept them. if test "${enable_universalsdk}"; then BASECFLAGS="-arch ppc -arch i386 -isysroot ${UNIVERSALSDK} ${BASECFLAGS}" fi @@ -17413,6 +17414,102 @@ fi done +# Stuff for expat. + +for ac_func in memmove +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + # check for long file support functions @@ -17517,9 +17614,7 @@ done - - -for ac_func in dup2 getcwd strdup strerror memmove +for ac_func in dup2 getcwd strdup do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` { echo "$as_me:$LINENO: checking for $ac_func" >&5 diff --git a/configure.in b/configure.in index 129b688..d402019 100644 --- a/configure.in +++ b/configure.in @@ -798,7 +798,8 @@ yes) ;; # is there any other compiler on Darwin besides gcc? Darwin*) - BASECFLAGS="$BASECFLAGS -Wno-long-double -no-cpp-precomp -mno-fused-madd" + # -Wno-long-double, -no-cpp-precomp, and -mno-fused-madd + # used to be here, but non-Apple gcc doesn't accept them. if test "${enable_universalsdk}"; then BASECFLAGS="-arch ppc -arch i386 -isysroot ${UNIVERSALSDK} ${BASECFLAGS}" fi @@ -2497,10 +2498,13 @@ AC_CHECK_FUNCS(forkpty,, ) ) +# Stuff for expat. +AC_CHECK_FUNCS(memmove) + # check for long file support functions AC_CHECK_FUNCS(fseek64 fseeko fstatvfs ftell64 ftello statvfs) -AC_REPLACE_FUNCS(dup2 getcwd strdup strerror memmove) +AC_REPLACE_FUNCS(dup2 getcwd strdup) AC_CHECK_FUNCS(getpgrp, AC_TRY_COMPILE([#include ], [getpgrp(0);], diff --git a/pyconfig.h.in b/pyconfig.h.in index 1a0460d..135da3f 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -571,9 +571,6 @@ /* Define to 1 if you have the `strdup' function. */ #undef HAVE_STRDUP -/* Define to 1 if you have the `strerror' function. */ -#undef HAVE_STRERROR - /* Define to 1 if you have the `strftime' function. */ #undef HAVE_STRFTIME -- cgit v0.12