diff --git a/Doc/library/logging.rst b/Doc/library/logging.rst index a7693fbe44f..8ffa3017cbf 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 3a3305c0fc5..e19a4d5852f 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 58905e03e50..f06ca2c6b82 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 75f381e5968..de67d075bae 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 55904765367..61bc55907a7 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 ecbb059799c..6b520e2aed2 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 1221c63eb87..00000000000 --- 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 63f5b7116ad..00000000000 --- 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 cb7cf7512ef..20d37778573 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 1a40ef6f434..44b712c3c6a 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 +class DbmTestCase(unittest.TestCase): -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 setUp(self): + self.filename = test_support.TESTFN + self.d = dbm.open(self.filename, 'c') + self.d.close() -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()) + def tearDown(self): + for suffix in ['', '.pag', '.dir', '.db']: + test_support.unlink(self.filename + suffix) - d.close() + 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(): - 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() + 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 1997dc53b3d..01d47da6593 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 6f162414927..2d0dadd4cc8 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 25937dc6128..70bbfbc1718 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'] + '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'] -# -# 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)) + +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 bad144004ee..b6dc144cfdd 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 +"""Doctest for method/function calls. -def e(a, b): - print(a, b) +We're going the use these types for extra testing -def f(*a, **k): - print(a, sortdict(k)) + >>> from UserList import UserList + >>> from UserDict import UserDict -def g(x, *y, **z): - print(x, y, sortdict(z)) +We're defining four helper functions -def h(j=1, a=2, h=3): - print(j, a, h) + >>> def e(a,b): + ... print a, b -f() -f(1) -f(1, 2) -f(1, 2, 3) + >>> def f(*a, **k): + ... print a, test_support.sortdict(k) -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}) + >>> 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 + {} -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)) + >>> 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 -# 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'") + >>> 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) -try: - g() -except TypeError as err: - print("TypeError:", err) -else: - print("should raise TypeError: not enough arguments; expected 1, got 0") + >>> class Foo: + ... def method(self, arg1, arg2): + ... return arg1+arg2 -try: - g(*()) -except TypeError as err: - print("TypeError:", err) -else: - print("should raise TypeError: not enough arguments; expected 1, got 0") + >>> 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) -try: - g(*(), **{}) -except TypeError as err: - print("TypeError:", err) -else: - print("should raise TypeError: not enough arguments; expected 1, got 0") + >>> 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) -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") +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 -class Nothing: - def __len__(self): - return 5 -try: - g(*Nothing()) -except TypeError as attr: - pass -else: - print("should raise TypeError") + >>> try: + ... silence = id(1, *{}) + ... True + ... except: + ... False + True -class Nothing: - def __len__(self): - return 5 - def __getitem__(self, i): - if i < 3: - return i - else: - raise IndexError(i) -g(*Nothing()) + >>> id(1, **{'foo': 1}) + Traceback (most recent call last): + ... + TypeError: id() takes no keyword arguments -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()) +from test import test_support -# 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") +def test_main(): + import test_extcall # self import + test_support.run_doctest(test_extcall, True) -# 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) +if __name__ == '__main__': + test_main() diff --git a/Lib/test/test_parser.py b/Lib/test/test_parser.py index 054d6d2c49e..7269ccb0121 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 2a2d7aca0a9..fb59d6a1ca9 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 +class Pep247Test(unittest.TestCase): -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" + 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')) - if key is not None: - obj1 = module.new(key) - obj2 = module.new(key, b"string") + if not module.digest_size is None: + self.assertEquals(obj1.digest_size, module.digest_size) - h1 = module.new(key, b"string").digest() - obj3 = module.new(key) ; obj3.update(b"string") ; h2 = obj3.digest() - assert h1 == h2, "Hashes must match" + 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()) - else: - obj1 = module.new() - obj2 = module.new(b"string") + digest, hexdigest = obj1.digest(), obj1.hexdigest() + hd2 = "" + for byte in digest: + hd2 += '%02x' % ord(byte) + self.assertEquals(hd2, hexdigest) - h1 = module.new(b"string").digest() - obj3 = module.new() ; obj3.update(b"string") ; h2 = obj3.digest() - assert h1 == h2, "Hashes must match" + def test_md5(self): + self.check_module(md5) - 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') + def test_sha(self): + self.check_module(sha) + def test_hmac(self): + self.check_module(hmac, key='abc') def test_main(): - check_hash_module(hmac, key=b'abc') - + 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 a9d56723963..e1c198f59a1 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 0870134d1f4..5af5a0c2c3b 100755 --- a/Lib/test/test_strftime.py +++ b/Lib/test/test_strftime.py @@ -1,158 +1,185 @@ -#! /usr/bin/env python +""" +Unittest for time.strftime +""" -# Sanity checker for time.strftime +import calendar +import sys +import os +import re +from test import test_support +import time +import unittest -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) - -def escapestr(text, ampm): - """Escape text to deal with possible locale values that have regex - syntax while allowing regex syntax used for the 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("\?", "?") - 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'), - ) - - if verbose: - print("Strftime test, platform: %s, Python version: %s" % \ - (sys.platform, sys.version.split()[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: - 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])) - print(" Expected %s, but got %s" % (e[1], result)) +# helper functions def fixasctime(s): if s[8] == ' ': s = s[:8] + '0' + s[9:] return s -main() +def escapestr(text, ampm): + """ + 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('\?', '?') + return new_text + + +class StrftimeTest(unittest.TestCase): + + 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))) + + try: + 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: + 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 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'), + ) + + + 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 c89c5a147e2..01d66552957 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 654bc1171b8..dae250e9cc5 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 0d6ddf9ca09..7cdc27534f3 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 6b7d4a6eb06..0adf507c849 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 ba1c16b8401..7c9df3394f0 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 0317dbfed16..711adba12ee 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 e8e83f4b798..3ca14fac816 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 dcad80896a1..fc3ef76efdf 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 17b29a20788..f5f460547e8 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 16efa9d3ab8..2ca84021d8b 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 55f8342ec45..00000000000 --- 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 5046065d246..a1f184c185f 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 129b6885f22..d402019278b 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 1a0460d8d3e..135da3f39a9 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