mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
Merged revisions 70768,71657,71721,71729,71794,71976,72036-72037,72079,72085,72131-72134,72191,72197-72198,72219,72221,72225,72303,72434,72467,72476 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk ........ r70768 | andrew.kuchling | 2009-03-30 17:29:15 -0500 (Mon, 30 Mar 2009) | 1 line Typo fixes ........ r71657 | vinay.sajip | 2009-04-16 14:07:37 -0500 (Thu, 16 Apr 2009) | 1 line Issue #5768: Change to Unicode output logic and test case for same. ........ r71721 | benjamin.peterson | 2009-04-18 14:26:19 -0500 (Sat, 18 Apr 2009) | 1 line fix a few nits in unittest.py #5771 ........ r71729 | benjamin.peterson | 2009-04-18 16:03:10 -0500 (Sat, 18 Apr 2009) | 1 line move test to a more appropiate one ........ r71794 | vinay.sajip | 2009-04-22 07:10:47 -0500 (Wed, 22 Apr 2009) | 2 lines Issue #5170: Fixed regression caused when fixing #5768. ........ r71976 | mark.dickinson | 2009-04-26 14:54:55 -0500 (Sun, 26 Apr 2009) | 2 lines Fix typo in function name ........ r72036 | georg.brandl | 2009-04-27 12:04:23 -0500 (Mon, 27 Apr 2009) | 1 line #5848: small unittest doc patch. ........ r72037 | georg.brandl | 2009-04-27 12:09:53 -0500 (Mon, 27 Apr 2009) | 1 line #5840: dont claim we dont support TLS. ........ r72079 | r.david.murray | 2009-04-28 14:02:55 -0500 (Tue, 28 Apr 2009) | 2 lines Remove spurious 'u'. ........ r72085 | georg.brandl | 2009-04-28 16:48:35 -0500 (Tue, 28 Apr 2009) | 1 line Make the doctests in the docs pass, except for those in the turtle module. ........ r72131 | benjamin.peterson | 2009-04-29 17:43:35 -0500 (Wed, 29 Apr 2009) | 1 line fix test_shutil on ZFS #5676 ........ r72132 | georg.brandl | 2009-04-29 17:44:07 -0500 (Wed, 29 Apr 2009) | 1 line #5878: fix repr of re object. ........ r72133 | benjamin.peterson | 2009-04-29 17:44:15 -0500 (Wed, 29 Apr 2009) | 1 line make sure mode is removable while cleaning up test droppings ........ r72134 | benjamin.peterson | 2009-04-29 19:06:33 -0500 (Wed, 29 Apr 2009) | 1 line make sure to close file ........ r72191 | michael.foord | 2009-05-02 06:43:06 -0500 (Sat, 02 May 2009) | 9 lines Adds an exit parameter to unittest.main(). If False main no longer calls sys.exit. Closes issue 3379. Michael Foord ........ r72197 | benjamin.peterson | 2009-05-02 11:24:37 -0500 (Sat, 02 May 2009) | 1 line don't let sys.argv be used in the tests ........ r72198 | andrew.kuchling | 2009-05-02 12:12:15 -0500 (Sat, 02 May 2009) | 1 line Add items ........ r72219 | michael.foord | 2009-05-02 15:15:05 -0500 (Sat, 02 May 2009) | 8 lines Add addCleanup and doCleanups to unittest.TestCase. Closes issue 5679. Michael Foord ........ r72221 | benjamin.peterson | 2009-05-02 15:26:53 -0500 (Sat, 02 May 2009) | 1 line add myself ........ r72225 | michael.foord | 2009-05-02 17:43:34 -0500 (Sat, 02 May 2009) | 1 line ........ r72303 | benjamin.peterson | 2009-05-04 19:55:24 -0500 (Mon, 04 May 2009) | 1 line using sys._getframe(x), where x > 0 doesnt' work on IronPython ........ r72434 | r.david.murray | 2009-05-07 13:09:58 -0500 (Thu, 07 May 2009) | 2 lines Pre-opened test file needs to be opened in binary mode. ........ r72467 | georg.brandl | 2009-05-08 07:17:34 -0500 (Fri, 08 May 2009) | 1 line Fix name. ........ r72476 | thomas.heller | 2009-05-08 15:09:40 -0500 (Fri, 08 May 2009) | 4 lines Add a file that contains diffs between offical libffi files and the files in this repository. Should make it easier to merge new libffi versions. ........
This commit is contained in:
parent
8a282d175b
commit
25c95f1298
22 changed files with 910 additions and 146 deletions
|
@ -416,10 +416,9 @@ the I/O is waiting for the I/O operation to complete.
|
||||||
The Python interpreter needs to keep some bookkeeping information separate per
|
The Python interpreter needs to keep some bookkeeping information separate per
|
||||||
thread --- for this it uses a data structure called :ctype:`PyThreadState`.
|
thread --- for this it uses a data structure called :ctype:`PyThreadState`.
|
||||||
There's one global variable, however: the pointer to the current
|
There's one global variable, however: the pointer to the current
|
||||||
:ctype:`PyThreadState` structure. While most thread packages have a way to
|
:ctype:`PyThreadState` structure. Before the addition of :dfn:`thread-local
|
||||||
store "per-thread global data," Python's internal platform independent thread
|
storage` (:dfn:`TLS`) the current thread state had to be manipulated
|
||||||
abstraction doesn't support this yet. Therefore, the current thread state must
|
explicitly.
|
||||||
be manipulated explicitly.
|
|
||||||
|
|
||||||
This is easy enough in most cases. Most code manipulating the global
|
This is easy enough in most cases. Most code manipulating the global
|
||||||
interpreter lock has the following simple structure::
|
interpreter lock has the following simple structure::
|
||||||
|
|
|
@ -473,7 +473,7 @@ Here's a sample usage of the ``generate_ints()`` generator:
|
||||||
|
|
||||||
>>> gen = generate_ints(3)
|
>>> gen = generate_ints(3)
|
||||||
>>> gen
|
>>> gen
|
||||||
<generator object at ...>
|
<generator object generate_ints at ...>
|
||||||
>>> next(gen)
|
>>> next(gen)
|
||||||
0
|
0
|
||||||
>>> next(gen)
|
>>> next(gen)
|
||||||
|
|
|
@ -264,7 +264,7 @@ performing string substitutions. ::
|
||||||
>>> import re
|
>>> import re
|
||||||
>>> p = re.compile('ab*')
|
>>> p = re.compile('ab*')
|
||||||
>>> p
|
>>> p
|
||||||
<re.RegexObject instance at 80b4150>
|
<_sre.SRE_Pattern object at 80b4150>
|
||||||
|
|
||||||
:func:`re.compile` also accepts an optional *flags* argument, used to enable
|
:func:`re.compile` also accepts an optional *flags* argument, used to enable
|
||||||
various special features and syntax variations. We'll go over the available
|
various special features and syntax variations. We'll go over the available
|
||||||
|
|
|
@ -352,6 +352,7 @@ and off individually. They are described here in more detail.
|
||||||
:synopsis: the 2to3 library
|
:synopsis: the 2to3 library
|
||||||
.. moduleauthor:: Guido van Rossum
|
.. moduleauthor:: Guido van Rossum
|
||||||
.. moduleauthor:: Collin Winter
|
.. moduleauthor:: Collin Winter
|
||||||
|
.. moduleauthor:: Benjamin Peterson <benjamin@python.org>
|
||||||
|
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
|
@ -169,7 +169,7 @@ For example::
|
||||||
class is similar to bags or multisets in other languages.
|
class is similar to bags or multisets in other languages.
|
||||||
|
|
||||||
Elements are counted from an *iterable* or initialized from another
|
Elements are counted from an *iterable* or initialized from another
|
||||||
*mapping* (or counter)::
|
*mapping* (or counter):
|
||||||
|
|
||||||
>>> c = Counter() # a new, empty counter
|
>>> c = Counter() # a new, empty counter
|
||||||
>>> c = Counter('gallahad') # a new counter from an iterable
|
>>> c = Counter('gallahad') # a new counter from an iterable
|
||||||
|
@ -177,7 +177,7 @@ For example::
|
||||||
>>> c = Counter(cats=4, dogs=8) # a new counter from keyword args
|
>>> c = Counter(cats=4, dogs=8) # a new counter from keyword args
|
||||||
|
|
||||||
Counter objects have a dictionary interface except that they return a zero
|
Counter objects have a dictionary interface except that they return a zero
|
||||||
count for missing items instead of raising a :exc:`KeyError`::
|
count for missing items instead of raising a :exc:`KeyError`:
|
||||||
|
|
||||||
>>> c = Counter(['eggs', 'ham'])
|
>>> c = Counter(['eggs', 'ham'])
|
||||||
>>> c['bacon'] # count of a missing element is zero
|
>>> c['bacon'] # count of a missing element is zero
|
||||||
|
@ -210,7 +210,7 @@ For example::
|
||||||
Return a list of the *n* most common elements and their counts from the
|
Return a list of the *n* most common elements and their counts from the
|
||||||
most common to the least. If *n* is not specified, :func:`most_common`
|
most common to the least. If *n* is not specified, :func:`most_common`
|
||||||
returns *all* elements in the counter. Elements with equal counts are
|
returns *all* elements in the counter. Elements with equal counts are
|
||||||
ordered arbitrarily::
|
ordered arbitrarily:
|
||||||
|
|
||||||
>>> Counter('abracadabra').most_common(3)
|
>>> Counter('abracadabra').most_common(3)
|
||||||
[('a', 5), ('r', 2), ('b', 2)]
|
[('a', 5), ('r', 2), ('b', 2)]
|
||||||
|
|
|
@ -1746,7 +1746,7 @@ the :const:`Inexact` trap is set, it is also useful for validation:
|
||||||
>>> Decimal('3.214').quantize(TWOPLACES, context=Context(traps=[Inexact]))
|
>>> Decimal('3.214').quantize(TWOPLACES, context=Context(traps=[Inexact]))
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
Inexact
|
Inexact: None
|
||||||
|
|
||||||
Q. Once I have valid two place inputs, how do I maintain that invariant
|
Q. Once I have valid two place inputs, how do I maintain that invariant
|
||||||
throughout an application?
|
throughout an application?
|
||||||
|
|
|
@ -165,12 +165,12 @@ Basic Usage
|
||||||
document) to a Python object.
|
document) to a Python object.
|
||||||
|
|
||||||
*object_hook* is an optional function that will be called with the result of
|
*object_hook* is an optional function that will be called with the result of
|
||||||
any object literal decode (a :class:`dict`). The return value of
|
any object literal decoded (a :class:`dict`). The return value of
|
||||||
*object_hook* will be used instead of the :class:`dict`. This feature can be used
|
*object_hook* will be used instead of the :class:`dict`. This feature can be used
|
||||||
to implement custom decoders (e.g. JSON-RPC class hinting).
|
to implement custom decoders (e.g. JSON-RPC class hinting).
|
||||||
|
|
||||||
*object_pairs_hook* is an optional function that will be called with the
|
*object_pairs_hook* is an optional function that will be called with the
|
||||||
result of any object literal decode with an ordered list of pairs. The
|
result of any object literal decoded with an ordered list of pairs. The
|
||||||
return value of *object_pairs_hook* will be used instead of the
|
return value of *object_pairs_hook* will be used instead of the
|
||||||
:class:`dict`. This feature can be used to implement custom decoders that
|
:class:`dict`. This feature can be used to implement custom decoders that
|
||||||
rely on the order that the key and value pairs are decoded (for example,
|
rely on the order that the key and value pairs are decoded (for example,
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
:mod:`shelve` --- Python object persistence
|
:mod:`shelve` --- Python object persistence
|
||||||
===========================================
|
===========================================
|
||||||
|
|
||||||
|
@ -35,7 +34,7 @@ lots of shared sub-objects. The keys are ordinary strings.
|
||||||
accessed entries are written back (there is no way to determine which accessed
|
accessed entries are written back (there is no way to determine which accessed
|
||||||
entries are mutable, nor which ones were actually mutated).
|
entries are mutable, nor which ones were actually mutated).
|
||||||
|
|
||||||
Shelve objects support all methods supported by dictionaries. This eases the
|
Shelf objects support all methods supported by dictionaries. This eases the
|
||||||
transition from dictionary based scripts to those requiring persistent storage.
|
transition from dictionary based scripts to those requiring persistent storage.
|
||||||
|
|
||||||
One additional method is supported:
|
One additional method is supported:
|
||||||
|
|
|
@ -174,13 +174,13 @@ This module also defines four shortcut functions:
|
||||||
:attr:`returncode`
|
:attr:`returncode`
|
||||||
attribute and output in the :attr:`output` attribute.
|
attribute and output in the :attr:`output` attribute.
|
||||||
|
|
||||||
The arguments are the same as for the :class:`Popen` constructor. Example:
|
The arguments are the same as for the :class:`Popen` constructor. Example::
|
||||||
|
|
||||||
>>> subprocess.check_output(["ls", "-l", "/dev/null"])
|
>>> subprocess.check_output(["ls", "-l", "/dev/null"])
|
||||||
'crw-rw-rw- 1 root root 1, 3 Oct 18 2007 /dev/null\n'
|
'crw-rw-rw- 1 root root 1, 3 Oct 18 2007 /dev/null\n'
|
||||||
|
|
||||||
The stdout argument is not allowed as it is used internally.
|
The stdout argument is not allowed as it is used internally.
|
||||||
To capture standard error in the result, use stderr=subprocess.STDOUT.
|
To capture standard error in the result, use ``stderr=subprocess.STDOUT``::
|
||||||
|
|
||||||
>>> subprocess.check_output(
|
>>> subprocess.check_output(
|
||||||
["/bin/sh", "-c", "ls non_existent_file ; exit 0"],
|
["/bin/sh", "-c", "ls non_existent_file ; exit 0"],
|
||||||
|
|
|
@ -228,7 +228,7 @@ The output for the example would look similar to this:
|
||||||
*** extract_tb:
|
*** extract_tb:
|
||||||
[('<doctest...>', 10, '<module>', 'lumberjack()'),
|
[('<doctest...>', 10, '<module>', 'lumberjack()'),
|
||||||
('<doctest...>', 4, 'lumberjack', 'bright_side_of_death()'),
|
('<doctest...>', 4, 'lumberjack', 'bright_side_of_death()'),
|
||||||
(u'<doctest...>', 7, 'bright_side_of_death', 'return tuple()[0]')]
|
('<doctest...>', 7, 'bright_side_of_death', 'return tuple()[0]')]
|
||||||
*** format_tb:
|
*** format_tb:
|
||||||
[' File "<doctest...>", line 10, in <module>\n lumberjack()\n',
|
[' File "<doctest...>", line 10, in <module>\n lumberjack()\n',
|
||||||
' File "<doctest...>", line 4, in lumberjack\n bright_side_of_death()\n',
|
' File "<doctest...>", line 4, in lumberjack\n bright_side_of_death()\n',
|
||||||
|
|
|
@ -954,7 +954,6 @@ Test cases
|
||||||
along with the method name.
|
along with the method name.
|
||||||
|
|
||||||
.. versionchanged:: 3.1
|
.. versionchanged:: 3.1
|
||||||
|
|
||||||
In earlier versions this only returned the first line of the test
|
In earlier versions this only returned the first line of the test
|
||||||
method's docstring, if available or the :const:`None`. That led to
|
method's docstring, if available or the :const:`None`. That led to
|
||||||
undesirable behavior of not printing the test name when someone was
|
undesirable behavior of not printing the test name when someone was
|
||||||
|
@ -978,6 +977,36 @@ Test cases
|
||||||
.. versionadded:: 3.1
|
.. versionadded:: 3.1
|
||||||
|
|
||||||
|
|
||||||
|
.. method:: addCleanup(function[, *args[, **kwargs]])
|
||||||
|
|
||||||
|
Add a function to be called after :meth:`tearDown` to cleanup resources
|
||||||
|
used during the test. Functions will be called in reverse order to the
|
||||||
|
order they are added (LIFO). They are called with any arguments and
|
||||||
|
keyword arguments passed into :meth:`addCleanup` when they are
|
||||||
|
added.
|
||||||
|
|
||||||
|
If :meth:`setUp` fails, meaning that :meth:`tearDown` is not called,
|
||||||
|
then any cleanup functions added will still be called.
|
||||||
|
|
||||||
|
.. versionadded:: 2.7
|
||||||
|
|
||||||
|
|
||||||
|
.. method:: doCleanups()
|
||||||
|
|
||||||
|
This method is called uncoditionally after :meth:`tearDown`, or
|
||||||
|
after :meth:`setUp` if :meth:`setUp` raises an exception.
|
||||||
|
|
||||||
|
It is responsible for calling all the cleanup functions added by
|
||||||
|
:meth:`addCleanup`. If you need cleanup functions to be called
|
||||||
|
*prior* to :meth:`tearDown` then you can call :meth:`doCleanups`
|
||||||
|
yourself.
|
||||||
|
|
||||||
|
:meth:`doCleanups` pops methods off the stack of cleanup
|
||||||
|
functions one at a time, so it can be called at any time.
|
||||||
|
|
||||||
|
.. versionadded:: 2.7
|
||||||
|
|
||||||
|
|
||||||
.. class:: FunctionTestCase(testFunc[, setUp[, tearDown[, description]]])
|
.. class:: FunctionTestCase(testFunc[, setUp[, tearDown[, description]]])
|
||||||
|
|
||||||
This class implements the portion of the :class:`TestCase` interface which
|
This class implements the portion of the :class:`TestCase` interface which
|
||||||
|
@ -1046,6 +1075,20 @@ Grouping tests
|
||||||
Return the number of tests represented by this test object, including all
|
Return the number of tests represented by this test object, including all
|
||||||
individual tests and sub-suites.
|
individual tests and sub-suites.
|
||||||
|
|
||||||
|
|
||||||
|
.. method:: __iter__()
|
||||||
|
|
||||||
|
Tests grouped by a :class:`TestSuite` are always accessed by iteration.
|
||||||
|
Subclasses can lazily provide tests by overriding :meth:`__iter__`. Note
|
||||||
|
that this method maybe called several times on a single suite
|
||||||
|
(for example when counting tests or comparing for equality)
|
||||||
|
so the tests returned must be the same for repeated iterations.
|
||||||
|
|
||||||
|
.. versionchanged:: 2.7
|
||||||
|
In earlier versions the :class:`TestSuite` accessed tests directly rather
|
||||||
|
than through iteration, so overriding :meth:`__iter__` wasn't sufficient
|
||||||
|
for providing tests.
|
||||||
|
|
||||||
In the typical usage of a :class:`TestSuite` object, the :meth:`run` method
|
In the typical usage of a :class:`TestSuite` object, the :meth:`run` method
|
||||||
is invoked by a :class:`TestRunner` rather than by the end-user test harness.
|
is invoked by a :class:`TestRunner` rather than by the end-user test harness.
|
||||||
|
|
||||||
|
@ -1190,7 +1233,6 @@ Loading and running tests
|
||||||
holding formatted tracebacks. Each tuple represents a test which raised an
|
holding formatted tracebacks. Each tuple represents a test which raised an
|
||||||
unexpected exception.
|
unexpected exception.
|
||||||
|
|
||||||
|
|
||||||
.. attribute:: failures
|
.. attribute:: failures
|
||||||
|
|
||||||
A list containing 2-tuples of :class:`TestCase` instances and strings
|
A list containing 2-tuples of :class:`TestCase` instances and strings
|
||||||
|
@ -1266,6 +1308,20 @@ Loading and running tests
|
||||||
The default implementation does nothing.
|
The default implementation does nothing.
|
||||||
|
|
||||||
|
|
||||||
|
.. method:: startTestRun(test)
|
||||||
|
|
||||||
|
Called once before any tests are executed.
|
||||||
|
|
||||||
|
.. versionadded:: 2.7
|
||||||
|
|
||||||
|
|
||||||
|
.. method:: stopTestRun(test)
|
||||||
|
|
||||||
|
Called once before any tests are executed.
|
||||||
|
|
||||||
|
.. versionadded:: 2.7
|
||||||
|
|
||||||
|
|
||||||
.. method:: addError(test, err)
|
.. method:: addError(test, err)
|
||||||
|
|
||||||
Called when the test case *test* raises an unexpected exception *err* is a
|
Called when the test case *test* raises an unexpected exception *err* is a
|
||||||
|
@ -1335,8 +1391,14 @@ Loading and running tests
|
||||||
has a few configurable parameters, but is essentially very simple. Graphical
|
has a few configurable parameters, but is essentially very simple. Graphical
|
||||||
applications which run test suites should provide alternate implementations.
|
applications which run test suites should provide alternate implementations.
|
||||||
|
|
||||||
|
.. method:: _makeResult()
|
||||||
|
|
||||||
.. function:: main([module[, defaultTest[, argv[, testRunner[, testLoader]]]]])
|
This method returns the instance of ``TestResult`` used by :meth:`run`.
|
||||||
|
It is not intended to be called directly, but can be overridden in
|
||||||
|
subclasses to provide a custom ``TestResult``.
|
||||||
|
|
||||||
|
|
||||||
|
.. function:: main([module[, defaultTest[, argv[, testRunner[, testLoader[, exit]]]]]])
|
||||||
|
|
||||||
A command-line program that runs a set of tests; this is primarily for making
|
A command-line program that runs a set of tests; this is primarily for making
|
||||||
test modules conveniently executable. The simplest use for this function is to
|
test modules conveniently executable. The simplest use for this function is to
|
||||||
|
@ -1346,4 +1408,18 @@ Loading and running tests
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
||||||
The *testRunner* argument can either be a test runner class or an already
|
The *testRunner* argument can either be a test runner class or an already
|
||||||
created instance of it.
|
created instance of it. By default ``main`` calls :func:`sys.exit` with
|
||||||
|
an exit code indicating success or failure of the tests run.
|
||||||
|
|
||||||
|
``main`` supports being used from the interactive interpreter by passing in the
|
||||||
|
argument ``exit=False``. This displays the result on standard output without
|
||||||
|
calling :func:`sys.exit`::
|
||||||
|
|
||||||
|
>>> from unittest import main
|
||||||
|
>>> main(module='test_module', exit=False)
|
||||||
|
|
||||||
|
Calling ``main`` actually returns an instance of the ``TestProgram`` class.
|
||||||
|
This stores the result of the tests run as the ``result`` attribute.
|
||||||
|
|
||||||
|
.. versionchanged:: 2.7
|
||||||
|
The ``exit`` parameter was added.
|
||||||
|
|
|
@ -121,6 +121,31 @@ Some smaller changes made to the core Python language are:
|
||||||
|
|
||||||
(Contributed by Fredrik Johansson and Victor Stinner; :issue:`3439`.)
|
(Contributed by Fredrik Johansson and Victor Stinner; :issue:`3439`.)
|
||||||
|
|
||||||
|
* Conversions from long integers and regular integers to floating
|
||||||
|
point now round differently, returning the floating-point number
|
||||||
|
closest to the number. This doesn't matter for small integers that
|
||||||
|
can be converted exactly, but for large numbers that will
|
||||||
|
unavoidably lose precision, Python 2.7 will now approximate more
|
||||||
|
closely. For example, Python 2.6 computed the following::
|
||||||
|
|
||||||
|
>>> n = 295147905179352891391
|
||||||
|
>>> float(n)
|
||||||
|
2.9514790517935283e+20
|
||||||
|
>>> n - long(float(n))
|
||||||
|
65535L
|
||||||
|
|
||||||
|
Python 2.7's floating-point result is larger, but much closer to the
|
||||||
|
true value::
|
||||||
|
|
||||||
|
>>> n = 295147905179352891391
|
||||||
|
>>> float(n)
|
||||||
|
2.9514790517935289e+20
|
||||||
|
>>> n-long(float(n)
|
||||||
|
... )
|
||||||
|
-1L
|
||||||
|
|
||||||
|
(Implemented by Mark Dickinson; :issue:`3166`.)
|
||||||
|
|
||||||
* The :class:`bytearray` type's :meth:`translate` method will
|
* The :class:`bytearray` type's :meth:`translate` method will
|
||||||
now accept ``None`` as its first argument. (Fixed by Georg Brandl;
|
now accept ``None`` as its first argument. (Fixed by Georg Brandl;
|
||||||
:issue:`4759`.)
|
:issue:`4759`.)
|
||||||
|
@ -220,7 +245,10 @@ changes, or look through the Subversion logs for all the details.
|
||||||
* New class: the :class:`Counter` class in the :mod:`collections` module is
|
* New class: the :class:`Counter` class in the :mod:`collections` module is
|
||||||
useful for tallying data. :class:`Counter` instances behave mostly
|
useful for tallying data. :class:`Counter` instances behave mostly
|
||||||
like dictionaries but return zero for missing keys instead of
|
like dictionaries but return zero for missing keys instead of
|
||||||
raising a :exc:`KeyError`::
|
raising a :exc:`KeyError`:
|
||||||
|
|
||||||
|
.. doctest::
|
||||||
|
:options: +NORMALIZE_WHITESPACE
|
||||||
|
|
||||||
>>> from collections import Counter
|
>>> from collections import Counter
|
||||||
>>> c = Counter()
|
>>> c = Counter()
|
||||||
|
@ -247,7 +275,7 @@ changes, or look through the Subversion logs for all the details.
|
||||||
'a', 'a', ' ', ' ', ' ', ' ', ' ', ' ',
|
'a', 'a', ' ', ' ', ' ', ' ', ' ', ' ',
|
||||||
'e', 'e', 'e', 'e', 'e', 'g', 'f', 'i', 'i',
|
'e', 'e', 'e', 'e', 'e', 'g', 'f', 'i', 'i',
|
||||||
'h', 'h', 'm', 'l', 'l', 'o', 'n', 'p', 's',
|
'h', 'h', 'm', 'l', 'l', 'o', 'n', 'p', 's',
|
||||||
's', 's', 'r', 't', 't', 'x']
|
's', 's', 'r', 't', 't', 'x'
|
||||||
|
|
||||||
Contributed by Raymond Hettinger; :issue:`1696199`.
|
Contributed by Raymond Hettinger; :issue:`1696199`.
|
||||||
|
|
||||||
|
@ -257,6 +285,7 @@ changes, or look through the Subversion logs for all the details.
|
||||||
renamed to legal names that are derived from the field's
|
renamed to legal names that are derived from the field's
|
||||||
position within the list of fields:
|
position within the list of fields:
|
||||||
|
|
||||||
|
>>> from collections import namedtuple
|
||||||
>>> T = namedtuple('T', ['field1', '$illegal', 'for', 'field2'], rename=True)
|
>>> T = namedtuple('T', ['field1', '$illegal', 'for', 'field2'], rename=True)
|
||||||
>>> T._fields
|
>>> T._fields
|
||||||
('field1', '_1', '_2', 'field2')
|
('field1', '_1', '_2', 'field2')
|
||||||
|
@ -294,6 +323,10 @@ changes, or look through the Subversion logs for all the details.
|
||||||
``Decimal('0.1000000000000000055511151231257827021181583404541015625')``.
|
``Decimal('0.1000000000000000055511151231257827021181583404541015625')``.
|
||||||
(Implemented by Raymond Hettinger; :issue:`4796`.)
|
(Implemented by Raymond Hettinger; :issue:`4796`.)
|
||||||
|
|
||||||
|
* The :class:`Fraction` class will now accept two rational numbers
|
||||||
|
as arguments to its constructor.
|
||||||
|
(Implemented by Mark Dickinson; :issue:`5812`.)
|
||||||
|
|
||||||
* New function: the :mod:`gc` module's :func:`is_tracked` returns
|
* New function: the :mod:`gc` module's :func:`is_tracked` returns
|
||||||
true if a given instance is tracked by the garbage collector, false
|
true if a given instance is tracked by the garbage collector, false
|
||||||
otherwise. (Contributed by Antoine Pitrou; :issue:`4688`.)
|
otherwise. (Contributed by Antoine Pitrou; :issue:`4688`.)
|
||||||
|
@ -419,6 +452,13 @@ changes, or look through the Subversion logs for all the details.
|
||||||
|
|
||||||
(Implemented by Antoine Pitrou; :issue:`4444`.)
|
(Implemented by Antoine Pitrou; :issue:`4444`.)
|
||||||
|
|
||||||
|
The methods :meth:`addCleanup` and :meth:`doCleanups` were added.
|
||||||
|
:meth:`addCleanup` allows you to add cleanup functions that
|
||||||
|
will be called unconditionally (after :meth:`setUp` if
|
||||||
|
:meth:`setUp` fails, otherwise after :meth:`tearDown`). This allows
|
||||||
|
for much simpler resource allocation and deallocation during tests.
|
||||||
|
:issue:`5679`
|
||||||
|
|
||||||
A number of new methods were added that provide more specialized
|
A number of new methods were added that provide more specialized
|
||||||
tests. Many of these methods were written by Google engineers
|
tests. Many of these methods were written by Google engineers
|
||||||
for use in their test suites; Gregory P. Smith, Michael Foord, and
|
for use in their test suites; Gregory P. Smith, Michael Foord, and
|
||||||
|
@ -473,6 +513,14 @@ changes, or look through the Subversion logs for all the details.
|
||||||
to provide additional information about why the two objects are
|
to provide additional information about why the two objects are
|
||||||
matching, much as the new sequence comparison methods do.
|
matching, much as the new sequence comparison methods do.
|
||||||
|
|
||||||
|
:func:`unittest.main` now takes an optional ``exit`` argument.
|
||||||
|
If False ``main`` doesn't call :func:`sys.exit` allowing it to
|
||||||
|
be used from the interactive interpreter. :issue:`3379`.
|
||||||
|
|
||||||
|
:class:`TestResult` has new :meth:`startTestRun` and
|
||||||
|
:meth:`stopTestRun` methods; called immediately before
|
||||||
|
and after a test run. :issue:`5728` by Robert Collins.
|
||||||
|
|
||||||
* The :func:`is_zipfile` function in the :mod:`zipfile` module will now
|
* The :func:`is_zipfile` function in the :mod:`zipfile` module will now
|
||||||
accept a file object, in addition to the path names accepted in earlier
|
accept a file object, in addition to the path names accepted in earlier
|
||||||
versions. (Contributed by Gabriel Genellina; :issue:`4756`.)
|
versions. (Contributed by Gabriel Genellina; :issue:`4756`.)
|
||||||
|
@ -553,6 +601,10 @@ Changes to Python's build process and to the C API include:
|
||||||
is particularly useful for asynchronous IO operations.
|
is particularly useful for asynchronous IO operations.
|
||||||
(Contributed by Kristjan Valur Jonsson; :issue:`4293`.)
|
(Contributed by Kristjan Valur Jonsson; :issue:`4293`.)
|
||||||
|
|
||||||
|
* Global symbols defined by the :mod:`ctypes` module are now prefixed
|
||||||
|
with ``Py`, or with ``_ctypes``. (Implemented by Thomas
|
||||||
|
Heller; :issue:`3102`.)
|
||||||
|
|
||||||
* The :program:`configure` script now checks for floating-point rounding bugs
|
* The :program:`configure` script now checks for floating-point rounding bugs
|
||||||
on certain 32-bit Intel chips and defines a :cmacro:`X87_DOUBLE_ROUNDING`
|
on certain 32-bit Intel chips and defines a :cmacro:`X87_DOUBLE_ROUNDING`
|
||||||
preprocessor definition. No code currently uses this definition,
|
preprocessor definition. No code currently uses this definition,
|
||||||
|
@ -591,10 +643,10 @@ Other Changes and Fixes
|
||||||
|
|
||||||
* When importing a module from a :file:`.pyc` or :file:`.pyo` file
|
* When importing a module from a :file:`.pyc` or :file:`.pyo` file
|
||||||
with an existing :file:`.py` counterpart, the :attr:`co_filename`
|
with an existing :file:`.py` counterpart, the :attr:`co_filename`
|
||||||
attributes of all code objects if the original filename is obsolete,
|
attributes of the resulting code objects are overwritten when the
|
||||||
which can happen if the file has been renamed, moved, or is accessed
|
original filename is obsolete. This can happen if the file has been
|
||||||
through different paths. (Patch by Ziga Seilnacht and Jean-Paul
|
renamed, moved, or is accessed through different paths. (Patch by
|
||||||
Calderone; :issue:`1180193`.)
|
Ziga Seilnacht and Jean-Paul Calderone; :issue:`1180193`.)
|
||||||
|
|
||||||
* The :file:`regrtest.py` script now takes a :option:`--randseed=`
|
* The :file:`regrtest.py` script now takes a :option:`--randseed=`
|
||||||
switch that takes an integer that will be used as the random seed
|
switch that takes an integer that will be used as the random seed
|
||||||
|
|
|
@ -271,9 +271,12 @@ def namedtuple(typename, field_names, verbose=False, rename=False):
|
||||||
|
|
||||||
# For pickling to work, the __module__ variable needs to be set to the frame
|
# For pickling to work, the __module__ variable needs to be set to the frame
|
||||||
# where the named tuple is created. Bypass this step in enviroments where
|
# where the named tuple is created. Bypass this step in enviroments where
|
||||||
# sys._getframe is not defined (Jython for example).
|
# sys._getframe is not defined (Jython for example) or sys._getframe is not
|
||||||
if hasattr(_sys, '_getframe'):
|
# defined for arguments greater than 0 (IronPython).
|
||||||
|
try:
|
||||||
result.__module__ = _sys._getframe(1).f_globals.get('__name__', '__main__')
|
result.__module__ = _sys._getframe(1).f_globals.get('__name__', '__main__')
|
||||||
|
except (AttributeError, ValueError):
|
||||||
|
pass
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
|
@ -756,7 +756,7 @@ class StreamHandler(Handler):
|
||||||
The record is then written to the stream with a trailing newline. If
|
The record is then written to the stream with a trailing newline. If
|
||||||
exception information is present, it is formatted using
|
exception information is present, it is formatted using
|
||||||
traceback.print_exception and appended to the stream. If the stream
|
traceback.print_exception and appended to the stream. If the stream
|
||||||
has an 'encoding' attribute, it is used to encode the message before
|
has an 'encoding' attribute, it is used to determine how to do the
|
||||||
output to the stream.
|
output to the stream.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
|
@ -767,11 +767,21 @@ class StreamHandler(Handler):
|
||||||
stream.write(fs % msg)
|
stream.write(fs % msg)
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
if (isinstance(msg, unicode) or
|
if (isinstance(msg, unicode) and
|
||||||
getattr(stream, 'encoding', None) is None):
|
getattr(stream, 'encoding', None)):
|
||||||
|
fs = fs.decode(stream.encoding)
|
||||||
|
try:
|
||||||
stream.write(fs % msg)
|
stream.write(fs % msg)
|
||||||
|
except UnicodeEncodeError:
|
||||||
|
#Printing to terminals sometimes fails. For example,
|
||||||
|
#with an encoding of 'cp1251', the above write will
|
||||||
|
#work if written to a stream opened or wrapped by
|
||||||
|
#the codecs module, but fail when writing to a
|
||||||
|
#terminal even when the codepage is set to cp1251.
|
||||||
|
#An extra encoding step seems to be needed.
|
||||||
|
stream.write((fs % msg).encode(stream.encoding))
|
||||||
else:
|
else:
|
||||||
stream.write(fs % msg.encode(stream.encoding))
|
stream.write(fs % msg)
|
||||||
except UnicodeError:
|
except UnicodeError:
|
||||||
stream.write(fs % msg.encode("UTF-8"))
|
stream.write(fs % msg.encode("UTF-8"))
|
||||||
self.flush()
|
self.flush()
|
||||||
|
|
|
@ -663,6 +663,7 @@ def runtest_inner(test, generate, verbose, quiet, test_times,
|
||||||
|
|
||||||
def cleanup_test_droppings(testname, verbose):
|
def cleanup_test_droppings(testname, verbose):
|
||||||
import shutil
|
import shutil
|
||||||
|
import stat
|
||||||
|
|
||||||
# Try to clean up junk commonly left behind. While tests shouldn't leave
|
# Try to clean up junk commonly left behind. While tests shouldn't leave
|
||||||
# any files or directories behind, when a test fails that can be tedious
|
# any files or directories behind, when a test fails that can be tedious
|
||||||
|
@ -687,6 +688,10 @@ def cleanup_test_droppings(testname, verbose):
|
||||||
if verbose:
|
if verbose:
|
||||||
print("%r left behind %s %r" % (testname, kind, name))
|
print("%r left behind %s %r" % (testname, kind, name))
|
||||||
try:
|
try:
|
||||||
|
# if we have chmod, fix possible permissions problems
|
||||||
|
# that might prevent cleanup
|
||||||
|
if (hasattr(os, 'chmod')):
|
||||||
|
os.chmod(name, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO)
|
||||||
nuker(name)
|
nuker(name)
|
||||||
except Exception as msg:
|
except Exception as msg:
|
||||||
print(("%r left behind %s %r and it couldn't be "
|
print(("%r left behind %s %r and it couldn't be "
|
||||||
|
|
|
@ -27,7 +27,7 @@ class AIFCTest(unittest.TestCase):
|
||||||
def test_skipunknown(self):
|
def test_skipunknown(self):
|
||||||
#Issue 2245
|
#Issue 2245
|
||||||
#This file contains chunk types aifc doesn't recognize.
|
#This file contains chunk types aifc doesn't recognize.
|
||||||
f = aifc.open(self.sndfilepath)
|
self.f = aifc.open(self.sndfilepath)
|
||||||
|
|
||||||
def test_params(self):
|
def test_params(self):
|
||||||
f = self.f = aifc.open(self.sndfilepath)
|
f = self.f = aifc.open(self.sndfilepath)
|
||||||
|
|
|
@ -3585,31 +3585,6 @@ order (MRO) for bases """
|
||||||
self.assertEqual(e.a, 2)
|
self.assertEqual(e.a, 2)
|
||||||
self.assertEqual(C2.__subclasses__(), [D])
|
self.assertEqual(C2.__subclasses__(), [D])
|
||||||
|
|
||||||
# stuff that shouldn't:
|
|
||||||
class L(list):
|
|
||||||
pass
|
|
||||||
|
|
||||||
try:
|
|
||||||
L.__bases__ = (dict,)
|
|
||||||
except TypeError:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
self.fail("shouldn't turn list subclass into dict subclass")
|
|
||||||
|
|
||||||
try:
|
|
||||||
list.__bases__ = (dict,)
|
|
||||||
except TypeError:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
self.fail("shouldn't be able to assign to list.__bases__")
|
|
||||||
|
|
||||||
try:
|
|
||||||
D.__bases__ = (C2, list)
|
|
||||||
except TypeError:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
assert 0, "best_base calculation found wanting"
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
del D.__bases__
|
del D.__bases__
|
||||||
except (TypeError, AttributeError):
|
except (TypeError, AttributeError):
|
||||||
|
@ -3657,6 +3632,36 @@ order (MRO) for bases """
|
||||||
if tp is not object:
|
if tp is not object:
|
||||||
self.assertEqual(len(tp.__bases__), 1, tp)
|
self.assertEqual(len(tp.__bases__), 1, tp)
|
||||||
|
|
||||||
|
class L(list):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class C(object):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class D(C):
|
||||||
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
L.__bases__ = (dict,)
|
||||||
|
except TypeError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
self.fail("shouldn't turn list subclass into dict subclass")
|
||||||
|
|
||||||
|
try:
|
||||||
|
list.__bases__ = (dict,)
|
||||||
|
except TypeError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
self.fail("shouldn't be able to assign to list.__bases__")
|
||||||
|
|
||||||
|
try:
|
||||||
|
D.__bases__ = (C, list)
|
||||||
|
except TypeError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
assert 0, "best_base calculation found wanting"
|
||||||
|
|
||||||
|
|
||||||
def test_mutable_bases_with_failing_mro(self):
|
def test_mutable_bases_with_failing_mro(self):
|
||||||
# Testing mutable bases with failing mro...
|
# Testing mutable bases with failing mro...
|
||||||
|
|
|
@ -894,6 +894,7 @@ class EncodingTest(BaseTest):
|
||||||
message = '\u0434\u043e \u0441\u0432\u0438\u0434\u0430\u043d\u0438\u044f'
|
message = '\u0434\u043e \u0441\u0432\u0438\u0434\u0430\u043d\u0438\u044f'
|
||||||
#Ensure it's written in a Cyrillic encoding
|
#Ensure it's written in a Cyrillic encoding
|
||||||
writer_class = codecs.getwriter('cp1251')
|
writer_class = codecs.getwriter('cp1251')
|
||||||
|
writer_class.encoding = 'cp1251'
|
||||||
stream = io.BytesIO()
|
stream = io.BytesIO()
|
||||||
writer = writer_class(stream, 'strict')
|
writer = writer_class(stream, 'strict')
|
||||||
handler = logging.StreamHandler(writer)
|
handler = logging.StreamHandler(writer)
|
||||||
|
|
|
@ -46,9 +46,23 @@ class TestShutil(unittest.TestCase):
|
||||||
shutil.rmtree(TESTFN)
|
shutil.rmtree(TESTFN)
|
||||||
|
|
||||||
def check_args_to_onerror(self, func, arg, exc):
|
def check_args_to_onerror(self, func, arg, exc):
|
||||||
|
# test_rmtree_errors deliberately runs rmtree
|
||||||
|
# on a directory that is chmod 400, which will fail.
|
||||||
|
# This function is run when shutil.rmtree fails.
|
||||||
|
# 99.9% of the time it initially fails to remove
|
||||||
|
# a file in the directory, so the first time through
|
||||||
|
# func is os.remove.
|
||||||
|
# However, some Linux machines running ZFS on
|
||||||
|
# FUSE experienced a failure earlier in the process
|
||||||
|
# at os.listdir. The first failure may legally
|
||||||
|
# be either.
|
||||||
if self.errorState == 0:
|
if self.errorState == 0:
|
||||||
self.assertEqual(func, os.remove)
|
if func is os.remove:
|
||||||
self.assertEqual(arg, self.childpath)
|
self.assertEqual(arg, self.childpath)
|
||||||
|
else:
|
||||||
|
self.assertIs(func, os.listdir,
|
||||||
|
"func must be either os.remove or os.listdir")
|
||||||
|
self.assertEqual(arg, TESTFN)
|
||||||
self.failUnless(issubclass(exc[0], OSError))
|
self.failUnless(issubclass(exc[0], OSError))
|
||||||
self.errorState = 1
|
self.errorState = 1
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -9,9 +9,10 @@ Still need testing:
|
||||||
import re
|
import re
|
||||||
from test import support
|
from test import support
|
||||||
import unittest
|
import unittest
|
||||||
from unittest import TestCase
|
from unittest import TestCase, TestProgram
|
||||||
import types
|
import types
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
|
import io
|
||||||
|
|
||||||
### Support code
|
### Support code
|
||||||
################################################################
|
################################################################
|
||||||
|
@ -25,10 +26,18 @@ class LoggingResult(unittest.TestResult):
|
||||||
self._events.append('startTest')
|
self._events.append('startTest')
|
||||||
super().startTest(test)
|
super().startTest(test)
|
||||||
|
|
||||||
|
def startTestRun(self):
|
||||||
|
self._events.append('startTestRun')
|
||||||
|
super(LoggingResult, self).startTestRun()
|
||||||
|
|
||||||
def stopTest(self, test):
|
def stopTest(self, test):
|
||||||
self._events.append('stopTest')
|
self._events.append('stopTest')
|
||||||
super().stopTest(test)
|
super().stopTest(test)
|
||||||
|
|
||||||
|
def stopTestRun(self):
|
||||||
|
self._events.append('stopTestRun')
|
||||||
|
super(LoggingResult, self).stopTestRun()
|
||||||
|
|
||||||
def addFailure(self, *args):
|
def addFailure(self, *args):
|
||||||
self._events.append('addFailure')
|
self._events.append('addFailure')
|
||||||
super().addFailure(*args)
|
super().addFailure(*args)
|
||||||
|
@ -1826,6 +1835,12 @@ class Test_TestResult(TestCase):
|
||||||
self.assertEqual(result.testsRun, 1)
|
self.assertEqual(result.testsRun, 1)
|
||||||
self.assertEqual(result.shouldStop, False)
|
self.assertEqual(result.shouldStop, False)
|
||||||
|
|
||||||
|
# "Called before and after tests are run. The default implementation does nothing."
|
||||||
|
def test_startTestRun_stopTestRun(self):
|
||||||
|
result = unittest.TestResult()
|
||||||
|
result.startTestRun()
|
||||||
|
result.stopTestRun()
|
||||||
|
|
||||||
# "addSuccess(test)"
|
# "addSuccess(test)"
|
||||||
# ...
|
# ...
|
||||||
# "Called when the test case test succeeds"
|
# "Called when the test case test succeeds"
|
||||||
|
@ -1973,6 +1988,53 @@ class Foo(unittest.TestCase):
|
||||||
class Bar(Foo):
|
class Bar(Foo):
|
||||||
def test2(self): pass
|
def test2(self): pass
|
||||||
|
|
||||||
|
class LoggingTestCase(unittest.TestCase):
|
||||||
|
"""A test case which logs its calls."""
|
||||||
|
|
||||||
|
def __init__(self, events):
|
||||||
|
super(LoggingTestCase, self).__init__('test')
|
||||||
|
self.events = events
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.events.append('setUp')
|
||||||
|
|
||||||
|
def test(self):
|
||||||
|
self.events.append('test')
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
self.events.append('tearDown')
|
||||||
|
|
||||||
|
class ResultWithNoStartTestRunStopTestRun(object):
|
||||||
|
"""An object honouring TestResult before startTestRun/stopTestRun."""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.failures = []
|
||||||
|
self.errors = []
|
||||||
|
self.testsRun = 0
|
||||||
|
self.skipped = []
|
||||||
|
self.expectedFailures = []
|
||||||
|
self.unexpectedSuccesses = []
|
||||||
|
self.shouldStop = False
|
||||||
|
|
||||||
|
def startTest(self, test):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def stopTest(self, test):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def addError(self, test):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def addFailure(self, test):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def addSuccess(self, test):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def wasSuccessful(self):
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
################################################################
|
################################################################
|
||||||
### /Support code for Test_TestCase
|
### /Support code for Test_TestCase
|
||||||
|
|
||||||
|
@ -2067,21 +2129,32 @@ class Test_TestCase(TestCase, TestEquality, TestHashing):
|
||||||
events = []
|
events = []
|
||||||
result = LoggingResult(events)
|
result = LoggingResult(events)
|
||||||
|
|
||||||
class Foo(unittest.TestCase):
|
class Foo(LoggingTestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
events.append('setUp')
|
super(Foo, self).setUp()
|
||||||
raise RuntimeError('raised by Foo.setUp')
|
raise RuntimeError('raised by Foo.setUp')
|
||||||
|
|
||||||
def test(self):
|
Foo(events).run(result)
|
||||||
events.append('test')
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
events.append('tearDown')
|
|
||||||
|
|
||||||
Foo('test').run(result)
|
|
||||||
expected = ['startTest', 'setUp', 'addError', 'stopTest']
|
expected = ['startTest', 'setUp', 'addError', 'stopTest']
|
||||||
self.assertEqual(events, expected)
|
self.assertEqual(events, expected)
|
||||||
|
|
||||||
|
# "With a temporary result stopTestRun is called when setUp errors.
|
||||||
|
def test_run_call_order__error_in_setUp_default_result(self):
|
||||||
|
events = []
|
||||||
|
|
||||||
|
class Foo(LoggingTestCase):
|
||||||
|
def defaultTestResult(self):
|
||||||
|
return LoggingResult(self.events)
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(Foo, self).setUp()
|
||||||
|
raise RuntimeError('raised by Foo.setUp')
|
||||||
|
|
||||||
|
Foo(events).run()
|
||||||
|
expected = ['startTestRun', 'startTest', 'setUp', 'addError',
|
||||||
|
'stopTest', 'stopTestRun']
|
||||||
|
self.assertEqual(events, expected)
|
||||||
|
|
||||||
# "When a setUp() method is defined, the test runner will run that method
|
# "When a setUp() method is defined, the test runner will run that method
|
||||||
# prior to each test. Likewise, if a tearDown() method is defined, the
|
# prior to each test. Likewise, if a tearDown() method is defined, the
|
||||||
# test runner will invoke that method after each test. In the example,
|
# test runner will invoke that method after each test. In the example,
|
||||||
|
@ -2093,20 +2166,32 @@ class Test_TestCase(TestCase, TestEquality, TestHashing):
|
||||||
events = []
|
events = []
|
||||||
result = LoggingResult(events)
|
result = LoggingResult(events)
|
||||||
|
|
||||||
class Foo(unittest.TestCase):
|
class Foo(LoggingTestCase):
|
||||||
def setUp(self):
|
|
||||||
events.append('setUp')
|
|
||||||
|
|
||||||
def test(self):
|
def test(self):
|
||||||
events.append('test')
|
super(Foo, self).test()
|
||||||
raise RuntimeError('raised by Foo.test')
|
raise RuntimeError('raised by Foo.test')
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
events.append('tearDown')
|
|
||||||
|
|
||||||
expected = ['startTest', 'setUp', 'test', 'addError', 'tearDown',
|
expected = ['startTest', 'setUp', 'test', 'addError', 'tearDown',
|
||||||
'stopTest']
|
'stopTest']
|
||||||
Foo('test').run(result)
|
Foo(events).run(result)
|
||||||
|
self.assertEqual(events, expected)
|
||||||
|
|
||||||
|
# "With a default result, an error in the test still results in stopTestRun
|
||||||
|
# being called."
|
||||||
|
def test_run_call_order__error_in_test_default_result(self):
|
||||||
|
events = []
|
||||||
|
|
||||||
|
class Foo(LoggingTestCase):
|
||||||
|
def defaultTestResult(self):
|
||||||
|
return LoggingResult(self.events)
|
||||||
|
|
||||||
|
def test(self):
|
||||||
|
super(Foo, self).test()
|
||||||
|
raise RuntimeError('raised by Foo.test')
|
||||||
|
|
||||||
|
expected = ['startTestRun', 'startTest', 'setUp', 'test', 'addError',
|
||||||
|
'tearDown', 'stopTest', 'stopTestRun']
|
||||||
|
Foo(events).run()
|
||||||
self.assertEqual(events, expected)
|
self.assertEqual(events, expected)
|
||||||
|
|
||||||
# "When a setUp() method is defined, the test runner will run that method
|
# "When a setUp() method is defined, the test runner will run that method
|
||||||
|
@ -2120,20 +2205,30 @@ class Test_TestCase(TestCase, TestEquality, TestHashing):
|
||||||
events = []
|
events = []
|
||||||
result = LoggingResult(events)
|
result = LoggingResult(events)
|
||||||
|
|
||||||
class Foo(unittest.TestCase):
|
class Foo(LoggingTestCase):
|
||||||
def setUp(self):
|
|
||||||
events.append('setUp')
|
|
||||||
|
|
||||||
def test(self):
|
def test(self):
|
||||||
events.append('test')
|
super(Foo, self).test()
|
||||||
self.fail('raised by Foo.test')
|
self.fail('raised by Foo.test')
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
events.append('tearDown')
|
|
||||||
|
|
||||||
expected = ['startTest', 'setUp', 'test', 'addFailure', 'tearDown',
|
expected = ['startTest', 'setUp', 'test', 'addFailure', 'tearDown',
|
||||||
'stopTest']
|
'stopTest']
|
||||||
Foo('test').run(result)
|
Foo(events).run(result)
|
||||||
|
self.assertEqual(events, expected)
|
||||||
|
|
||||||
|
# "When a test fails with a default result stopTestRun is still called."
|
||||||
|
def test_run_call_order__failure_in_test_default_result(self):
|
||||||
|
|
||||||
|
class Foo(LoggingTestCase):
|
||||||
|
def defaultTestResult(self):
|
||||||
|
return LoggingResult(self.events)
|
||||||
|
def test(self):
|
||||||
|
super(Foo, self).test()
|
||||||
|
self.fail('raised by Foo.test')
|
||||||
|
|
||||||
|
expected = ['startTestRun', 'startTest', 'setUp', 'test', 'addFailure',
|
||||||
|
'tearDown', 'stopTest', 'stopTestRun']
|
||||||
|
events = []
|
||||||
|
Foo(events).run()
|
||||||
self.assertEqual(events, expected)
|
self.assertEqual(events, expected)
|
||||||
|
|
||||||
# "When a setUp() method is defined, the test runner will run that method
|
# "When a setUp() method is defined, the test runner will run that method
|
||||||
|
@ -2147,22 +2242,44 @@ class Test_TestCase(TestCase, TestEquality, TestHashing):
|
||||||
events = []
|
events = []
|
||||||
result = LoggingResult(events)
|
result = LoggingResult(events)
|
||||||
|
|
||||||
class Foo(unittest.TestCase):
|
class Foo(LoggingTestCase):
|
||||||
def setUp(self):
|
|
||||||
events.append('setUp')
|
|
||||||
|
|
||||||
def test(self):
|
|
||||||
events.append('test')
|
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
events.append('tearDown')
|
super(Foo, self).tearDown()
|
||||||
raise RuntimeError('raised by Foo.tearDown')
|
raise RuntimeError('raised by Foo.tearDown')
|
||||||
|
|
||||||
Foo('test').run(result)
|
Foo(events).run(result)
|
||||||
expected = ['startTest', 'setUp', 'test', 'tearDown', 'addError',
|
expected = ['startTest', 'setUp', 'test', 'tearDown', 'addError',
|
||||||
'stopTest']
|
'stopTest']
|
||||||
self.assertEqual(events, expected)
|
self.assertEqual(events, expected)
|
||||||
|
|
||||||
|
# "When tearDown errors with a default result stopTestRun is still called."
|
||||||
|
def test_run_call_order__error_in_tearDown_default_result(self):
|
||||||
|
|
||||||
|
class Foo(LoggingTestCase):
|
||||||
|
def defaultTestResult(self):
|
||||||
|
return LoggingResult(self.events)
|
||||||
|
def tearDown(self):
|
||||||
|
super(Foo, self).tearDown()
|
||||||
|
raise RuntimeError('raised by Foo.tearDown')
|
||||||
|
|
||||||
|
events = []
|
||||||
|
Foo(events).run()
|
||||||
|
expected = ['startTestRun', 'startTest', 'setUp', 'test', 'tearDown',
|
||||||
|
'addError', 'stopTest', 'stopTestRun']
|
||||||
|
self.assertEqual(events, expected)
|
||||||
|
|
||||||
|
# "TestCase.run() still works when the defaultTestResult is a TestResult
|
||||||
|
# that does not support startTestRun and stopTestRun.
|
||||||
|
def test_run_call_order_default_result(self):
|
||||||
|
|
||||||
|
class Foo(unittest.TestCase):
|
||||||
|
def defaultTestResult(self):
|
||||||
|
return ResultWithNoStartTestRunStopTestRun()
|
||||||
|
def test(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
Foo('test').run()
|
||||||
|
|
||||||
# "This class attribute gives the exception raised by the test() method.
|
# "This class attribute gives the exception raised by the test() method.
|
||||||
# If a test framework needs to use a specialized exception, possibly to
|
# If a test framework needs to use a specialized exception, possibly to
|
||||||
# carry additional information, it must subclass this exception in
|
# carry additional information, it must subclass this exception in
|
||||||
|
@ -2253,7 +2370,9 @@ class Test_TestCase(TestCase, TestEquality, TestHashing):
|
||||||
self.failUnless(isinstance(Foo().id(), str))
|
self.failUnless(isinstance(Foo().id(), str))
|
||||||
|
|
||||||
# "If result is omitted or None, a temporary result object is created
|
# "If result is omitted or None, a temporary result object is created
|
||||||
# and used, but is not made available to the caller"
|
# and used, but is not made available to the caller. As TestCase owns the
|
||||||
|
# temporary result startTestRun and stopTestRun are called.
|
||||||
|
|
||||||
def test_run__uses_defaultTestResult(self):
|
def test_run__uses_defaultTestResult(self):
|
||||||
events = []
|
events = []
|
||||||
|
|
||||||
|
@ -2267,7 +2386,8 @@ class Test_TestCase(TestCase, TestEquality, TestHashing):
|
||||||
# Make run() find a result object on its own
|
# Make run() find a result object on its own
|
||||||
Foo('test').run()
|
Foo('test').run()
|
||||||
|
|
||||||
expected = ['startTest', 'test', 'addSuccess', 'stopTest']
|
expected = ['startTestRun', 'startTest', 'test', 'addSuccess',
|
||||||
|
'stopTest', 'stopTestRun']
|
||||||
self.assertEqual(events, expected)
|
self.assertEqual(events, expected)
|
||||||
|
|
||||||
def testShortDescriptionWithoutDocstring(self):
|
def testShortDescriptionWithoutDocstring(self):
|
||||||
|
@ -3012,6 +3132,220 @@ class TestLongMessage(TestCase):
|
||||||
"^unexpectedly identical: None : oops$"])
|
"^unexpectedly identical: None : oops$"])
|
||||||
|
|
||||||
|
|
||||||
|
class TestCleanUp(TestCase):
|
||||||
|
|
||||||
|
def testCleanUp(self):
|
||||||
|
class TestableTest(TestCase):
|
||||||
|
def testNothing(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
test = TestableTest('testNothing')
|
||||||
|
self.assertEqual(test._cleanups, [])
|
||||||
|
|
||||||
|
cleanups = []
|
||||||
|
|
||||||
|
def cleanup1(*args, **kwargs):
|
||||||
|
cleanups.append((1, args, kwargs))
|
||||||
|
|
||||||
|
def cleanup2(*args, **kwargs):
|
||||||
|
cleanups.append((2, args, kwargs))
|
||||||
|
|
||||||
|
test.addCleanup(cleanup1, 1, 2, 3, four='hello', five='goodbye')
|
||||||
|
test.addCleanup(cleanup2)
|
||||||
|
|
||||||
|
self.assertEqual(test._cleanups,
|
||||||
|
[(cleanup1, (1, 2, 3), dict(four='hello', five='goodbye')),
|
||||||
|
(cleanup2, (), {})])
|
||||||
|
|
||||||
|
result = test.doCleanups()
|
||||||
|
self.assertTrue(result)
|
||||||
|
|
||||||
|
self.assertEqual(cleanups, [(2, (), {}), (1, (1, 2, 3), dict(four='hello', five='goodbye'))])
|
||||||
|
|
||||||
|
def testCleanUpWithErrors(self):
|
||||||
|
class TestableTest(TestCase):
|
||||||
|
def testNothing(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class MockResult(object):
|
||||||
|
errors = []
|
||||||
|
def addError(self, test, exc_info):
|
||||||
|
self.errors.append((test, exc_info))
|
||||||
|
|
||||||
|
result = MockResult()
|
||||||
|
test = TestableTest('testNothing')
|
||||||
|
test._result = result
|
||||||
|
|
||||||
|
exc1 = Exception('foo')
|
||||||
|
exc2 = Exception('bar')
|
||||||
|
def cleanup1():
|
||||||
|
raise exc1
|
||||||
|
|
||||||
|
def cleanup2():
|
||||||
|
raise exc2
|
||||||
|
|
||||||
|
test.addCleanup(cleanup1)
|
||||||
|
test.addCleanup(cleanup2)
|
||||||
|
|
||||||
|
self.assertFalse(test.doCleanups())
|
||||||
|
|
||||||
|
(test1, (Type1, instance1, _)), (test2, (Type2, instance2, _)) = reversed(MockResult.errors)
|
||||||
|
self.assertEqual((test1, Type1, instance1), (test, Exception, exc1))
|
||||||
|
self.assertEqual((test2, Type2, instance2), (test, Exception, exc2))
|
||||||
|
|
||||||
|
def testCleanupInRun(self):
|
||||||
|
blowUp = False
|
||||||
|
ordering = []
|
||||||
|
|
||||||
|
class TestableTest(TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
ordering.append('setUp')
|
||||||
|
if blowUp:
|
||||||
|
raise Exception('foo')
|
||||||
|
|
||||||
|
def testNothing(self):
|
||||||
|
ordering.append('test')
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
ordering.append('tearDown')
|
||||||
|
|
||||||
|
test = TestableTest('testNothing')
|
||||||
|
|
||||||
|
def cleanup1():
|
||||||
|
ordering.append('cleanup1')
|
||||||
|
def cleanup2():
|
||||||
|
ordering.append('cleanup2')
|
||||||
|
test.addCleanup(cleanup1)
|
||||||
|
test.addCleanup(cleanup2)
|
||||||
|
|
||||||
|
def success(some_test):
|
||||||
|
self.assertEqual(some_test, test)
|
||||||
|
ordering.append('success')
|
||||||
|
|
||||||
|
result = unittest.TestResult()
|
||||||
|
result.addSuccess = success
|
||||||
|
|
||||||
|
test.run(result)
|
||||||
|
self.assertEqual(ordering, ['setUp', 'test', 'tearDown',
|
||||||
|
'cleanup2', 'cleanup1', 'success'])
|
||||||
|
|
||||||
|
blowUp = True
|
||||||
|
ordering = []
|
||||||
|
test = TestableTest('testNothing')
|
||||||
|
test.addCleanup(cleanup1)
|
||||||
|
test.run(result)
|
||||||
|
self.assertEqual(ordering, ['setUp', 'cleanup1'])
|
||||||
|
|
||||||
|
|
||||||
|
class Test_TestProgram(TestCase):
|
||||||
|
|
||||||
|
# Horrible white box test
|
||||||
|
def testNoExit(self):
|
||||||
|
result = object()
|
||||||
|
test = object()
|
||||||
|
|
||||||
|
class FakeRunner(object):
|
||||||
|
def run(self, test):
|
||||||
|
self.test = test
|
||||||
|
return result
|
||||||
|
|
||||||
|
runner = FakeRunner()
|
||||||
|
|
||||||
|
try:
|
||||||
|
oldParseArgs = TestProgram.parseArgs
|
||||||
|
TestProgram.parseArgs = lambda *args: None
|
||||||
|
TestProgram.test = test
|
||||||
|
|
||||||
|
program = TestProgram(testRunner=runner, exit=False)
|
||||||
|
|
||||||
|
self.assertEqual(program.result, result)
|
||||||
|
self.assertEqual(runner.test, test)
|
||||||
|
|
||||||
|
finally:
|
||||||
|
TestProgram.parseArgs = oldParseArgs
|
||||||
|
del TestProgram.test
|
||||||
|
|
||||||
|
|
||||||
|
class FooBar(unittest.TestCase):
|
||||||
|
def testPass(self):
|
||||||
|
assert True
|
||||||
|
def testFail(self):
|
||||||
|
assert False
|
||||||
|
|
||||||
|
class FooBarLoader(unittest.TestLoader):
|
||||||
|
"""Test loader that returns a suite containing FooBar."""
|
||||||
|
def loadTestsFromModule(self, module):
|
||||||
|
return self.suiteClass(
|
||||||
|
[self.loadTestsFromTestCase(Test_TestProgram.FooBar)])
|
||||||
|
|
||||||
|
|
||||||
|
def test_NonExit(self):
|
||||||
|
program = unittest.main(exit=False,
|
||||||
|
argv=["foobar"],
|
||||||
|
testRunner=unittest.TextTestRunner(stream=io.StringIO()),
|
||||||
|
testLoader=self.FooBarLoader())
|
||||||
|
self.assertTrue(hasattr(program, 'result'))
|
||||||
|
|
||||||
|
|
||||||
|
def test_Exit(self):
|
||||||
|
self.assertRaises(
|
||||||
|
SystemExit,
|
||||||
|
unittest.main,
|
||||||
|
argv=["foobar"],
|
||||||
|
testRunner=unittest.TextTestRunner(stream=io.StringIO()),
|
||||||
|
exit=True,
|
||||||
|
testLoader=self.FooBarLoader())
|
||||||
|
|
||||||
|
|
||||||
|
def test_ExitAsDefault(self):
|
||||||
|
self.assertRaises(
|
||||||
|
SystemExit,
|
||||||
|
unittest.main,
|
||||||
|
argv=["foobar"],
|
||||||
|
testRunner=unittest.TextTestRunner(stream=io.StringIO()),
|
||||||
|
testLoader=self.FooBarLoader())
|
||||||
|
|
||||||
|
|
||||||
|
class Test_TextTestRunner(TestCase):
|
||||||
|
"""Tests for TextTestRunner."""
|
||||||
|
|
||||||
|
def test_works_with_result_without_startTestRun_stopTestRun(self):
|
||||||
|
class OldTextResult(ResultWithNoStartTestRunStopTestRun):
|
||||||
|
separator2 = ''
|
||||||
|
def printErrors(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class Runner(unittest.TextTestRunner):
|
||||||
|
def __init__(self):
|
||||||
|
super(Runner, self).__init__(io.StringIO())
|
||||||
|
|
||||||
|
def _makeResult(self):
|
||||||
|
return OldTextResult()
|
||||||
|
|
||||||
|
runner = Runner()
|
||||||
|
runner.run(unittest.TestSuite())
|
||||||
|
|
||||||
|
def test_startTestRun_stopTestRun_called(self):
|
||||||
|
class LoggingTextResult(LoggingResult):
|
||||||
|
separator2 = ''
|
||||||
|
def printErrors(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class LoggingRunner(unittest.TextTestRunner):
|
||||||
|
def __init__(self, events):
|
||||||
|
super(LoggingRunner, self).__init__(io.StringIO())
|
||||||
|
self._events = events
|
||||||
|
|
||||||
|
def _makeResult(self):
|
||||||
|
return LoggingTextResult(self._events)
|
||||||
|
|
||||||
|
events = []
|
||||||
|
runner = LoggingRunner(events)
|
||||||
|
runner.run(unittest.TestSuite())
|
||||||
|
expected = ['startTestRun', 'stopTestRun']
|
||||||
|
self.assertEqual(events, expected)
|
||||||
|
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
## Main
|
## Main
|
||||||
######################################################################
|
######################################################################
|
||||||
|
@ -3019,7 +3353,8 @@ class TestLongMessage(TestCase):
|
||||||
def test_main():
|
def test_main():
|
||||||
support.run_unittest(Test_TestCase, Test_TestLoader,
|
support.run_unittest(Test_TestCase, Test_TestLoader,
|
||||||
Test_TestSuite, Test_TestResult, Test_FunctionTestCase,
|
Test_TestSuite, Test_TestResult, Test_FunctionTestCase,
|
||||||
Test_TestSkipping, Test_Assertions, TestLongMessage)
|
Test_TestSkipping, Test_Assertions, TestLongMessage,
|
||||||
|
Test_TestProgram, TestCleanUp)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
test_main()
|
test_main()
|
||||||
|
|
|
@ -173,10 +173,22 @@ class TestResult(object):
|
||||||
"Called when the given test is about to be run"
|
"Called when the given test is about to be run"
|
||||||
self.testsRun = self.testsRun + 1
|
self.testsRun = self.testsRun + 1
|
||||||
|
|
||||||
|
def startTestRun(self):
|
||||||
|
"""Called once before any tests are executed.
|
||||||
|
|
||||||
|
See startTest for a method called before each test.
|
||||||
|
"""
|
||||||
|
|
||||||
def stopTest(self, test):
|
def stopTest(self, test):
|
||||||
"Called when the given test has been run"
|
"Called when the given test has been run"
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def stopTestRun(self):
|
||||||
|
"""Called once after all tests are executed.
|
||||||
|
|
||||||
|
See stopTest for a method called after each test.
|
||||||
|
"""
|
||||||
|
|
||||||
def addError(self, test, err):
|
def addError(self, test, err):
|
||||||
"""Called when an error has occurred. 'err' is a tuple of values as
|
"""Called when an error has occurred. 'err' is a tuple of values as
|
||||||
returned by sys.exc_info().
|
returned by sys.exc_info().
|
||||||
|
@ -262,7 +274,7 @@ class _AssertRaisesContext(object):
|
||||||
def __enter__(self):
|
def __enter__(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def __exit__(self, exc_type, exc_value, traceback):
|
def __exit__(self, exc_type, exc_value, tb):
|
||||||
if exc_type is None:
|
if exc_type is None:
|
||||||
try:
|
try:
|
||||||
exc_name = self.expected.__name__
|
exc_name = self.expected.__name__
|
||||||
|
@ -341,12 +353,14 @@ class TestCase(object):
|
||||||
not have a method with the specified name.
|
not have a method with the specified name.
|
||||||
"""
|
"""
|
||||||
self._testMethodName = methodName
|
self._testMethodName = methodName
|
||||||
|
self._result = None
|
||||||
try:
|
try:
|
||||||
testMethod = getattr(self, methodName)
|
testMethod = getattr(self, methodName)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
raise ValueError("no such test method in %s: %s" % \
|
raise ValueError("no such test method in %s: %s" % \
|
||||||
(self.__class__, methodName))
|
(self.__class__, methodName))
|
||||||
self._testMethodDoc = testMethod.__doc__
|
self._testMethodDoc = testMethod.__doc__
|
||||||
|
self._cleanups = []
|
||||||
|
|
||||||
# Map types to custom assertEqual functions that will compare
|
# Map types to custom assertEqual functions that will compare
|
||||||
# instances of said type in more detail to generate a more useful
|
# instances of said type in more detail to generate a more useful
|
||||||
|
@ -373,6 +387,14 @@ class TestCase(object):
|
||||||
"""
|
"""
|
||||||
self._type_equality_funcs[typeobj] = _AssertWrapper(function)
|
self._type_equality_funcs[typeobj] = _AssertWrapper(function)
|
||||||
|
|
||||||
|
def addCleanup(self, function, *args, **kwargs):
|
||||||
|
"""Add a function, with arguments, to be called when the test is
|
||||||
|
completed. Functions added are called on a LIFO basis and are
|
||||||
|
called after tearDown on test failure or success.
|
||||||
|
|
||||||
|
Cleanup items are called even if setUp fails (unlike tearDown)."""
|
||||||
|
self._cleanups.append((function, args, kwargs))
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
"Hook method for setting up the test fixture before exercising it."
|
"Hook method for setting up the test fixture before exercising it."
|
||||||
pass
|
pass
|
||||||
|
@ -428,21 +450,25 @@ class TestCase(object):
|
||||||
(_strclass(self.__class__), self._testMethodName)
|
(_strclass(self.__class__), self._testMethodName)
|
||||||
|
|
||||||
def run(self, result=None):
|
def run(self, result=None):
|
||||||
|
orig_result = result
|
||||||
if result is None:
|
if result is None:
|
||||||
result = self.defaultTestResult()
|
result = self.defaultTestResult()
|
||||||
|
startTestRun = getattr(result, 'startTestRun', None)
|
||||||
|
if startTestRun is not None:
|
||||||
|
startTestRun()
|
||||||
|
|
||||||
|
self._result = result
|
||||||
result.startTest(self)
|
result.startTest(self)
|
||||||
testMethod = getattr(self, self._testMethodName)
|
testMethod = getattr(self, self._testMethodName)
|
||||||
try:
|
try:
|
||||||
|
success = False
|
||||||
try:
|
try:
|
||||||
self.setUp()
|
self.setUp()
|
||||||
except SkipTest as e:
|
except SkipTest as e:
|
||||||
result.addSkip(self, str(e))
|
result.addSkip(self, str(e))
|
||||||
return
|
|
||||||
except Exception:
|
except Exception:
|
||||||
result.addError(self, sys.exc_info())
|
result.addError(self, sys.exc_info())
|
||||||
return
|
else:
|
||||||
|
|
||||||
success = False
|
|
||||||
try:
|
try:
|
||||||
testMethod()
|
testMethod()
|
||||||
except self.failureException:
|
except self.failureException:
|
||||||
|
@ -463,10 +489,31 @@ class TestCase(object):
|
||||||
except Exception:
|
except Exception:
|
||||||
result.addError(self, sys.exc_info())
|
result.addError(self, sys.exc_info())
|
||||||
success = False
|
success = False
|
||||||
|
|
||||||
|
cleanUpSuccess = self.doCleanups()
|
||||||
|
success = success and cleanUpSuccess
|
||||||
if success:
|
if success:
|
||||||
result.addSuccess(self)
|
result.addSuccess(self)
|
||||||
finally:
|
finally:
|
||||||
result.stopTest(self)
|
result.stopTest(self)
|
||||||
|
if orig_result is None:
|
||||||
|
stopTestRun = getattr(result, 'stopTestRun', None)
|
||||||
|
if stopTestRun is not None:
|
||||||
|
stopTestRun()
|
||||||
|
|
||||||
|
def doCleanups(self):
|
||||||
|
"""Execute all cleanup functions. Normally called for you after
|
||||||
|
tearDown."""
|
||||||
|
result = self._result
|
||||||
|
ok = True
|
||||||
|
while self._cleanups:
|
||||||
|
function, args, kwargs = self._cleanups.pop(-1)
|
||||||
|
try:
|
||||||
|
function(*args, **kwargs)
|
||||||
|
except Exception:
|
||||||
|
ok = False
|
||||||
|
result.addError(self, sys.exc_info())
|
||||||
|
return ok
|
||||||
|
|
||||||
def __call__(self, *args, **kwds):
|
def __call__(self, *args, **kwds):
|
||||||
return self.run(*args, **kwds)
|
return self.run(*args, **kwds)
|
||||||
|
@ -1037,7 +1084,7 @@ class TestSuite(object):
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
if not isinstance(other, self.__class__):
|
if not isinstance(other, self.__class__):
|
||||||
return NotImplemented
|
return NotImplemented
|
||||||
return self._tests == other._tests
|
return list(self) == list(other)
|
||||||
|
|
||||||
def __ne__(self, other):
|
def __ne__(self, other):
|
||||||
return not self == other
|
return not self == other
|
||||||
|
@ -1160,8 +1207,7 @@ class FunctionTestCase(TestCase):
|
||||||
self._testFunc, self._description))
|
self._testFunc, self._description))
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "%s (%s)" % (_strclass(self.__class__),
|
return "%s (%s)" % (_strclass(self.__class__), self._testFunc.__name__)
|
||||||
self.__testFunc.__name__)
|
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<%s testFunc=%s>" % (_strclass(self.__class__), self._testFunc)
|
return "<%s testFunc=%s>" % (_strclass(self.__class__), self._testFunc)
|
||||||
|
@ -1449,7 +1495,15 @@ class TextTestRunner(object):
|
||||||
"Run the given test case or test suite."
|
"Run the given test case or test suite."
|
||||||
result = self._makeResult()
|
result = self._makeResult()
|
||||||
startTime = time.time()
|
startTime = time.time()
|
||||||
|
startTestRun = getattr(result, 'startTestRun', None)
|
||||||
|
if startTestRun is not None:
|
||||||
|
startTestRun()
|
||||||
|
try:
|
||||||
test(result)
|
test(result)
|
||||||
|
finally:
|
||||||
|
stopTestRun = getattr(result, 'stopTestRun', None)
|
||||||
|
if stopTestRun is not None:
|
||||||
|
stopTestRun()
|
||||||
stopTime = time.time()
|
stopTime = time.time()
|
||||||
timeTaken = stopTime - startTime
|
timeTaken = stopTime - startTime
|
||||||
result.printErrors()
|
result.printErrors()
|
||||||
|
@ -1511,7 +1565,7 @@ Examples:
|
||||||
"""
|
"""
|
||||||
def __init__(self, module='__main__', defaultTest=None,
|
def __init__(self, module='__main__', defaultTest=None,
|
||||||
argv=None, testRunner=TextTestRunner,
|
argv=None, testRunner=TextTestRunner,
|
||||||
testLoader=defaultTestLoader):
|
testLoader=defaultTestLoader, exit=True):
|
||||||
if isinstance(module, str):
|
if isinstance(module, str):
|
||||||
self.module = __import__(module)
|
self.module = __import__(module)
|
||||||
for part in module.split('.')[1:]:
|
for part in module.split('.')[1:]:
|
||||||
|
@ -1520,6 +1574,8 @@ Examples:
|
||||||
self.module = module
|
self.module = module
|
||||||
if argv is None:
|
if argv is None:
|
||||||
argv = sys.argv
|
argv = sys.argv
|
||||||
|
|
||||||
|
self.exit = exit
|
||||||
self.verbosity = 1
|
self.verbosity = 1
|
||||||
self.defaultTest = defaultTest
|
self.defaultTest = defaultTest
|
||||||
self.testRunner = testRunner
|
self.testRunner = testRunner
|
||||||
|
@ -1571,8 +1627,9 @@ Examples:
|
||||||
else:
|
else:
|
||||||
# it is assumed to be a TestRunner instance
|
# it is assumed to be a TestRunner instance
|
||||||
testRunner = self.testRunner
|
testRunner = self.testRunner
|
||||||
result = testRunner.run(self.test)
|
self.result = testRunner.run(self.test)
|
||||||
sys.exit(not result.wasSuccessful())
|
if self.exit:
|
||||||
|
sys.exit(not self.result.wasSuccessful())
|
||||||
|
|
||||||
main = TestProgram
|
main = TestProgram
|
||||||
|
|
||||||
|
|
207
Modules/_ctypes/libffi.diff
Normal file
207
Modules/_ctypes/libffi.diff
Normal file
|
@ -0,0 +1,207 @@
|
||||||
|
This file contains the diffs between the files in the libffi
|
||||||
|
subdirectory and the 'official' source files from
|
||||||
|
ftp://sourceware.org/pub/libffi/libffi-3.0.5.tar.gz
|
||||||
|
|
||||||
|
Index: libffi/aclocal.m4
|
||||||
|
===================================================================
|
||||||
|
--- libffi/aclocal.m4 (working copy)
|
||||||
|
+++ libffi/aclocal.m4 (revision 72475)
|
||||||
|
@@ -1155,7 +1155,7 @@
|
||||||
|
test -n "$_LT_AC_TAGVAR(runpath_var, $1)" || \
|
||||||
|
test "X$_LT_AC_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then
|
||||||
|
|
||||||
|
- # We can hardcode non-existant directories.
|
||||||
|
+ # We can hardcode non-existent directories.
|
||||||
|
if test "$_LT_AC_TAGVAR(hardcode_direct, $1)" != no &&
|
||||||
|
# If the only mechanism to avoid hardcoding is shlibpath_var, we
|
||||||
|
# have to relink, otherwise we might link with an installed library
|
||||||
|
Index: libffi/configure.ac
|
||||||
|
===================================================================
|
||||||
|
--- libffi/configure.ac (working copy)
|
||||||
|
+++ libffi/configure.ac (revision 72475)
|
||||||
|
@@ -1,4 +1,7 @@
|
||||||
|
dnl Process this with autoconf to create configure
|
||||||
|
+#
|
||||||
|
+# file from libffi - slightly patched for ctypes
|
||||||
|
+#
|
||||||
|
|
||||||
|
AC_PREREQ(2.59)
|
||||||
|
|
||||||
|
@@ -83,6 +86,9 @@
|
||||||
|
i?86-*-solaris2.1[[0-9]]*)
|
||||||
|
TARGET=X86_64; TARGETDIR=x86
|
||||||
|
;;
|
||||||
|
+ i*86-*-nto-qnx*)
|
||||||
|
+ TARGET=X86; TARGETDIR=x86
|
||||||
|
+ ;;
|
||||||
|
i?86-*-*)
|
||||||
|
TARGET=X86; TARGETDIR=x86
|
||||||
|
;;
|
||||||
|
@@ -100,10 +106,10 @@
|
||||||
|
;;
|
||||||
|
|
||||||
|
mips-sgi-irix5.* | mips-sgi-irix6.*)
|
||||||
|
- TARGET=MIPS; TARGETDIR=mips
|
||||||
|
+ TARGET=MIPS_IRIX; TARGETDIR=mips
|
||||||
|
;;
|
||||||
|
mips*-*-linux*)
|
||||||
|
- TARGET=MIPS; TARGETDIR=mips
|
||||||
|
+ TARGET=MIPS_LINUX; TARGETDIR=mips
|
||||||
|
;;
|
||||||
|
|
||||||
|
powerpc*-*-linux* | powerpc-*-sysv*)
|
||||||
|
@@ -156,7 +162,7 @@
|
||||||
|
AC_MSG_ERROR(["libffi has not been ported to $host."])
|
||||||
|
fi
|
||||||
|
|
||||||
|
-AM_CONDITIONAL(MIPS, test x$TARGET = xMIPS)
|
||||||
|
+AM_CONDITIONAL(MIPS,[expr x$TARGET : 'xMIPS' > /dev/null])
|
||||||
|
AM_CONDITIONAL(SPARC, test x$TARGET = xSPARC)
|
||||||
|
AM_CONDITIONAL(X86, test x$TARGET = xX86)
|
||||||
|
AM_CONDITIONAL(X86_FREEBSD, test x$TARGET = xX86_FREEBSD)
|
||||||
|
@@ -360,6 +366,10 @@
|
||||||
|
|
||||||
|
AC_CONFIG_LINKS(include/ffitarget.h:src/$TARGETDIR/ffitarget.h)
|
||||||
|
|
||||||
|
-AC_CONFIG_FILES(include/Makefile include/ffi.h Makefile testsuite/Makefile man/Makefile libffi.pc)
|
||||||
|
+AC_CONFIG_FILES(include/ffi.h)
|
||||||
|
|
||||||
|
+AC_CONFIG_LINKS(include/ffi_common.h:include/ffi_common.h)
|
||||||
|
+
|
||||||
|
+AC_CONFIG_FILES(fficonfig.py)
|
||||||
|
+
|
||||||
|
AC_OUTPUT
|
||||||
|
Index: libffi/configure
|
||||||
|
===================================================================
|
||||||
|
--- libffi/configure (working copy)
|
||||||
|
+++ libffi/configure (revision 72475)
|
||||||
|
@@ -9546,7 +9546,7 @@
|
||||||
|
test -n "$runpath_var" || \
|
||||||
|
test "X$hardcode_automatic" = "Xyes" ; then
|
||||||
|
|
||||||
|
- # We can hardcode non-existant directories.
|
||||||
|
+ # We can hardcode non-existent directories.
|
||||||
|
if test "$hardcode_direct" != no &&
|
||||||
|
# If the only mechanism to avoid hardcoding is shlibpath_var, we
|
||||||
|
# have to relink, otherwise we might link with an installed library
|
||||||
|
@@ -13514,7 +13514,7 @@
|
||||||
|
test -n "$runpath_var_CXX" || \
|
||||||
|
test "X$hardcode_automatic_CXX" = "Xyes" ; then
|
||||||
|
|
||||||
|
- # We can hardcode non-existant directories.
|
||||||
|
+ # We can hardcode non-existent directories.
|
||||||
|
if test "$hardcode_direct_CXX" != no &&
|
||||||
|
# If the only mechanism to avoid hardcoding is shlibpath_var, we
|
||||||
|
# have to relink, otherwise we might link with an installed library
|
||||||
|
@@ -16117,7 +16117,7 @@
|
||||||
|
test -n "$runpath_var_F77" || \
|
||||||
|
test "X$hardcode_automatic_F77" = "Xyes" ; then
|
||||||
|
|
||||||
|
- # We can hardcode non-existant directories.
|
||||||
|
+ # We can hardcode non-existent directories.
|
||||||
|
if test "$hardcode_direct_F77" != no &&
|
||||||
|
# If the only mechanism to avoid hardcoding is shlibpath_var, we
|
||||||
|
# have to relink, otherwise we might link with an installed library
|
||||||
|
@@ -18720,7 +18720,7 @@
|
||||||
|
test -n "$runpath_var_GCJ" || \
|
||||||
|
test "X$hardcode_automatic_GCJ" = "Xyes" ; then
|
||||||
|
|
||||||
|
- # We can hardcode non-existant directories.
|
||||||
|
+ # We can hardcode non-existent directories.
|
||||||
|
if test "$hardcode_direct_GCJ" != no &&
|
||||||
|
# If the only mechanism to avoid hardcoding is shlibpath_var, we
|
||||||
|
# have to relink, otherwise we might link with an installed library
|
||||||
|
@@ -20406,6 +20406,9 @@
|
||||||
|
i?86-*-solaris2.1[0-9]*)
|
||||||
|
TARGET=X86_64; TARGETDIR=x86
|
||||||
|
;;
|
||||||
|
+ i*86-*-nto-qnx*)
|
||||||
|
+ TARGET=X86; TARGETDIR=x86
|
||||||
|
+ ;;
|
||||||
|
i?86-*-*)
|
||||||
|
TARGET=X86; TARGETDIR=x86
|
||||||
|
;;
|
||||||
|
@@ -20423,10 +20426,10 @@
|
||||||
|
;;
|
||||||
|
|
||||||
|
mips-sgi-irix5.* | mips-sgi-irix6.*)
|
||||||
|
- TARGET=MIPS; TARGETDIR=mips
|
||||||
|
+ TARGET=MIPS_IRIX; TARGETDIR=mips
|
||||||
|
;;
|
||||||
|
mips*-*-linux*)
|
||||||
|
- TARGET=MIPS; TARGETDIR=mips
|
||||||
|
+ TARGET=MIPS_LINUX; TARGETDIR=mips
|
||||||
|
;;
|
||||||
|
|
||||||
|
powerpc*-*-linux* | powerpc-*-sysv*)
|
||||||
|
@@ -20481,7 +20484,7 @@
|
||||||
|
{ (exit 1); exit 1; }; }
|
||||||
|
fi
|
||||||
|
|
||||||
|
- if test x$TARGET = xMIPS; then
|
||||||
|
+ if expr x$TARGET : 'xMIPS' > /dev/null; then
|
||||||
|
MIPS_TRUE=
|
||||||
|
MIPS_FALSE='#'
|
||||||
|
else
|
||||||
|
@@ -22712,9 +22715,15 @@
|
||||||
|
ac_config_links="$ac_config_links include/ffitarget.h:src/$TARGETDIR/ffitarget.h"
|
||||||
|
|
||||||
|
|
||||||
|
-ac_config_files="$ac_config_files include/Makefile include/ffi.h Makefile testsuite/Makefile man/Makefile libffi.pc"
|
||||||
|
+ac_config_files="$ac_config_files include/ffi.h"
|
||||||
|
|
||||||
|
|
||||||
|
+ac_config_links="$ac_config_links include/ffi_common.h:include/ffi_common.h"
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+ac_config_files="$ac_config_files fficonfig.py"
|
||||||
|
+
|
||||||
|
+
|
||||||
|
cat >confcache <<\_ACEOF
|
||||||
|
# This file is a shell script that caches the results of configure
|
||||||
|
# tests run on this system so they can be shared between configure
|
||||||
|
@@ -23498,12 +23507,9 @@
|
||||||
|
"include") CONFIG_COMMANDS="$CONFIG_COMMANDS include" ;;
|
||||||
|
"src") CONFIG_COMMANDS="$CONFIG_COMMANDS src" ;;
|
||||||
|
"include/ffitarget.h") CONFIG_LINKS="$CONFIG_LINKS include/ffitarget.h:src/$TARGETDIR/ffitarget.h" ;;
|
||||||
|
- "include/Makefile") CONFIG_FILES="$CONFIG_FILES include/Makefile" ;;
|
||||||
|
"include/ffi.h") CONFIG_FILES="$CONFIG_FILES include/ffi.h" ;;
|
||||||
|
- "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
|
||||||
|
- "testsuite/Makefile") CONFIG_FILES="$CONFIG_FILES testsuite/Makefile" ;;
|
||||||
|
- "man/Makefile") CONFIG_FILES="$CONFIG_FILES man/Makefile" ;;
|
||||||
|
- "libffi.pc") CONFIG_FILES="$CONFIG_FILES libffi.pc" ;;
|
||||||
|
+ "include/ffi_common.h") CONFIG_LINKS="$CONFIG_LINKS include/ffi_common.h:include/ffi_common.h" ;;
|
||||||
|
+ "fficonfig.py") CONFIG_FILES="$CONFIG_FILES fficonfig.py" ;;
|
||||||
|
|
||||||
|
*) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
|
||||||
|
echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
|
||||||
|
Index: libffi/src/x86/ffi.c
|
||||||
|
===================================================================
|
||||||
|
--- libffi/src/x86/ffi.c (working copy)
|
||||||
|
+++ libffi/src/x86/ffi.c (revision 72475)
|
||||||
|
@@ -388,10 +388,10 @@
|
||||||
|
return FFI_BAD_ABI;
|
||||||
|
}
|
||||||
|
|
||||||
|
- // we currently don't support certain kinds of arguments for raw
|
||||||
|
+ /* we currently don't support certain kinds of arguments for raw
|
||||||
|
// closures. This should be implemented by a separate assembly language
|
||||||
|
// routine, since it would require argument processing, something we
|
||||||
|
- // don't do now for performance.
|
||||||
|
+ // don't do now for performance. */
|
||||||
|
|
||||||
|
for (i = cif->nargs-1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
Index: libffi/src/x86/ffi64.c
|
||||||
|
===================================================================
|
||||||
|
--- libffi/src/x86/ffi64.c (working copy)
|
||||||
|
+++ libffi/src/x86/ffi64.c (revision 72475)
|
||||||
|
@@ -52,7 +52,7 @@
|
||||||
|
/* Register class used for passing given 64bit part of the argument.
|
||||||
|
These represent classes as documented by the PS ABI, with the exception
|
||||||
|
of SSESF, SSEDF classes, that are basically SSE class, just gcc will
|
||||||
|
- use SF or DFmode move instead of DImode to avoid reformating penalties.
|
||||||
|
+ use SF or DFmode move instead of DImode to avoid reformatting penalties.
|
||||||
|
|
||||||
|
Similary we play games with INTEGERSI_CLASS to use cheaper SImode moves
|
||||||
|
whenever possible (upper half does contain padding). */
|
Loading…
Add table
Add a link
Reference in a new issue