mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 05:31:20 +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,10 +245,13 @@ 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() | ||||||
|      >>> for letter in 'here is a sample of english text': |      >>> for letter in 'here is a sample of english text': | ||||||
|      ...   c[letter] += 1 |      ...   c[letter] += 1 | ||||||
|      ... |      ... | ||||||
|  | @ -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,7 +285,8 @@ 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: | ||||||
| 
 | 
 | ||||||
|      >>> T=namedtuple('T', ['field1', '$illegal', 'for', 'field2'], rename=True) |      >>> from collections import namedtuple | ||||||
|  |      >>> 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 __getnewargs__(self): | ||||||
| 
 | 
 | ||||||
|     # 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 @@ def emit(self, record): | ||||||
|         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 @@ def emit(self, record): | ||||||
|                 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 @@ def tearDown(self): | ||||||
|     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 @@ class E(D): | ||||||
|         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 @@ def test_builtin_bases(self): | ||||||
|             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 @@ def test_encoding_cyrillic_unicode(self): | ||||||
|         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 @@ def test_on_error(self): | ||||||
|             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 @@ | ||||||
| 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 @@ def startTest(self, test): | ||||||
|         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 @@ def test_1(self): | ||||||
|         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 @@ def test1(self): pass | ||||||
| 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 @@ def test_run_call_order__error_in_setUp(self): | ||||||
|         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 @@ def test_run_call_order__error_in_test(self): | ||||||
|         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 @@ def test_run_call_order__failure_in_test(self): | ||||||
|         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 @@ def test_run_call_order__error_in_tearDown(self): | ||||||
|         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 @@ def runTest(self): | ||||||
|         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 @@ def defaultTestResult(self): | ||||||
|         # 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 @@ def testAssertIsNot(self): | ||||||
|                              "^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 @@ def testAssertIsNot(self): | ||||||
| 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 @@ def startTest(self, test): | ||||||
|         "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 @@ def __init__(self, expected, test_case, callable_obj=None, | ||||||
|     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 @@ def __init__(self, methodName='runTest'): | ||||||
|            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 @@ def addTypeEqualityFunc(self, typeobj, function): | ||||||
|         """ |         """ | ||||||
|         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 @@ def __repr__(self): | ||||||
|                (_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 @@ def run(self, result=None): | ||||||
|                 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 @@ def __repr__(self): | ||||||
|     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 @@ def __hash__(self): | ||||||
|                      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 @@ def run(self, test): | ||||||
|         "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 @@ class TestProgram(object): | ||||||
| """ | """ | ||||||
|     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 @@ def __init__(self, module='__main__', defaultTest=None, | ||||||
|             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 @@ def runTests(self): | ||||||
|         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
	
	 Benjamin Peterson
						Benjamin Peterson