mirror of
https://github.com/python/cpython.git
synced 2025-10-02 21:25:24 +00:00
Merged revisions 74779-74786,74793,74795,74811,74860-74861,74863,74876,74886,74896,74901,74903,74908,74912,74930,74933,74943,74946,74952-74955,75015,75019,75032,75068,75076,75095,75098,75102,75129,75139,75230 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk ........ r74779 | michael.foord | 2009-09-13 11:13:36 -0500 (Sun, 13 Sep 2009) | 1 line Change to tutorial wording for reading text / binary files on Windows. Issue #6301. ........ r74780 | michael.foord | 2009-09-13 11:40:02 -0500 (Sun, 13 Sep 2009) | 1 line Objects that compare equal automatically pass or fail assertAlmostEqual and assertNotAlmostEqual tests on unittest.TestCase. Issue 6567. ........ r74781 | michael.foord | 2009-09-13 11:46:19 -0500 (Sun, 13 Sep 2009) | 1 line Note that sys._getframe is not guaranteed to exist in all implementations of Python, and a corresponding note in inspect.currentframe. Issue 6712. ........ r74782 | michael.foord | 2009-09-13 12:07:46 -0500 (Sun, 13 Sep 2009) | 1 line Tutorial tweaks. Issue 6849. ........ r74783 | michael.foord | 2009-09-13 12:28:35 -0500 (Sun, 13 Sep 2009) | 1 line unittest.TestLoader.loadTestsFromName honors the loader suiteClass attribute. Issue 6866. ........ r74784 | georg.brandl | 2009-09-13 13:15:07 -0500 (Sun, 13 Sep 2009) | 1 line Typo fix. ........ r74785 | michael.foord | 2009-09-13 14:07:03 -0500 (Sun, 13 Sep 2009) | 1 line Test discovery in unittest will only attempt to import modules that are importable; i.e. their names are valid Python identifiers. If an import fails during discovery this will be recorded as an error and test discovery will continue. Issue 6568. ........ r74786 | michael.foord | 2009-09-13 14:08:18 -0500 (Sun, 13 Sep 2009) | 1 line Remove an extraneous space in unittest documentation. ........ r74793 | georg.brandl | 2009-09-14 09:50:47 -0500 (Mon, 14 Sep 2009) | 1 line #6908: fix association of hashlib hash attributes. ........ r74795 | benjamin.peterson | 2009-09-14 22:36:26 -0500 (Mon, 14 Sep 2009) | 1 line Py_SetPythonHome uses static storage #6913 ........ r74811 | georg.brandl | 2009-09-15 15:26:59 -0500 (Tue, 15 Sep 2009) | 1 line Add Armin Ronacher. ........ r74860 | benjamin.peterson | 2009-09-16 21:46:54 -0500 (Wed, 16 Sep 2009) | 1 line kill bare except ........ r74861 | benjamin.peterson | 2009-09-16 22:18:28 -0500 (Wed, 16 Sep 2009) | 1 line pep 8 defaults ........ r74863 | benjamin.peterson | 2009-09-16 22:27:33 -0500 (Wed, 16 Sep 2009) | 1 line rationalize a bit ........ r74876 | georg.brandl | 2009-09-17 11:15:53 -0500 (Thu, 17 Sep 2009) | 1 line #6932: remove paragraph that advises relying on __del__ being called. ........ r74886 | benjamin.peterson | 2009-09-17 16:33:46 -0500 (Thu, 17 Sep 2009) | 1 line use macros ........ r74896 | georg.brandl | 2009-09-18 02:22:41 -0500 (Fri, 18 Sep 2009) | 1 line #6936: for interactive use, quit() is just fine. ........ r74901 | georg.brandl | 2009-09-18 04:14:52 -0500 (Fri, 18 Sep 2009) | 1 line #6905: use better exception messages in inspect when the argument is of the wrong type. ........ r74903 | georg.brandl | 2009-09-18 04:18:27 -0500 (Fri, 18 Sep 2009) | 1 line #6938: "ident" is always a string, so use a format code which works. ........ r74908 | georg.brandl | 2009-09-18 08:57:11 -0500 (Fri, 18 Sep 2009) | 1 line Use str.format() to fix beginner's mistake with %-style string formatting. ........ r74912 | georg.brandl | 2009-09-18 11:19:56 -0500 (Fri, 18 Sep 2009) | 1 line Optimize optimization and fix method name in docstring. ........ r74930 | georg.brandl | 2009-09-18 16:21:41 -0500 (Fri, 18 Sep 2009) | 1 line #6925: rewrite docs for locals() and vars() a bit. ........ r74933 | georg.brandl | 2009-09-18 16:35:59 -0500 (Fri, 18 Sep 2009) | 1 line #6930: clarify description about byteorder handling in UTF decoder routines. ........ r74943 | georg.brandl | 2009-09-19 02:35:07 -0500 (Sat, 19 Sep 2009) | 1 line #6944: the argument to PyArg_ParseTuple should be a tuple, otherwise a SystemError is set. Also clean up another usage of PyArg_ParseTuple. ........ r74946 | georg.brandl | 2009-09-19 03:43:16 -0500 (Sat, 19 Sep 2009) | 1 line Update bug tracker reference. ........ r74952 | georg.brandl | 2009-09-19 05:42:34 -0500 (Sat, 19 Sep 2009) | 1 line #6946: fix duplicate index entries for datetime classes. ........ r74953 | georg.brandl | 2009-09-19 07:04:16 -0500 (Sat, 19 Sep 2009) | 1 line Fix references to threading.enumerate(). ........ r74954 | georg.brandl | 2009-09-19 08:13:56 -0500 (Sat, 19 Sep 2009) | 1 line Add Doug. ........ r74955 | georg.brandl | 2009-09-19 08:20:49 -0500 (Sat, 19 Sep 2009) | 1 line Add Mark Summerfield. ........ r75015 | georg.brandl | 2009-09-22 05:55:08 -0500 (Tue, 22 Sep 2009) | 1 line Fix encoding name. ........ r75019 | vinay.sajip | 2009-09-22 12:23:41 -0500 (Tue, 22 Sep 2009) | 1 line Fixed a typo, and added sections on optimization and using arbitrary objects as messages. ........ r75032 | benjamin.peterson | 2009-09-22 17:15:28 -0500 (Tue, 22 Sep 2009) | 1 line fix typos/rephrase ........ r75068 | benjamin.peterson | 2009-09-25 21:57:59 -0500 (Fri, 25 Sep 2009) | 1 line comment out ugly xxx ........ r75076 | vinay.sajip | 2009-09-26 09:53:32 -0500 (Sat, 26 Sep 2009) | 1 line Tidied up name of parameter in StreamHandler ........ r75095 | michael.foord | 2009-09-27 14:15:41 -0500 (Sun, 27 Sep 2009) | 1 line Test creation moved from TestProgram.parseArgs to TestProgram.createTests exclusively. Issue 6956. ........ r75098 | michael.foord | 2009-09-27 15:08:23 -0500 (Sun, 27 Sep 2009) | 1 line Documentation improvement for load_tests protocol in unittest. Issue 6515. ........ r75102 | skip.montanaro | 2009-09-27 21:12:27 -0500 (Sun, 27 Sep 2009) | 3 lines Patch from Thomas Barr so that csv.Sniffer will set doublequote property. Closes issue 6606. ........ r75129 | vinay.sajip | 2009-09-29 02:08:54 -0500 (Tue, 29 Sep 2009) | 1 line Issue #7014: logging: Improved IronPython 2.6 compatibility. ........ r75139 | raymond.hettinger | 2009-09-29 13:53:24 -0500 (Tue, 29 Sep 2009) | 3 lines Issue 7008: Better document str.title and show how to work around the apostrophe problem. ........ r75230 | benjamin.peterson | 2009-10-04 08:38:38 -0500 (Sun, 04 Oct 2009) | 1 line test logging ........
This commit is contained in:
parent
bd27aef8a0
commit
4ac9ce4f9a
35 changed files with 391 additions and 164 deletions
|
@ -371,6 +371,10 @@ Initialization, Finalization, and Threads
|
||||||
Set the default "home" directory, that is, the location of the standard
|
Set the default "home" directory, that is, the location of the standard
|
||||||
Python libraries. The libraries are searched in
|
Python libraries. The libraries are searched in
|
||||||
:file:`{home}/lib/python{version}` and :file:`{home}/lib/python{version}`.
|
:file:`{home}/lib/python{version}` and :file:`{home}/lib/python{version}`.
|
||||||
|
The argument should point to a zero-terminated character string in static
|
||||||
|
storage whose contents will not change for the duration of the program's
|
||||||
|
execution. No code in the Python interpreter will change the contents of
|
||||||
|
this storage.
|
||||||
|
|
||||||
|
|
||||||
.. cfunction:: w_char* Py_GetPythonHome()
|
.. cfunction:: w_char* Py_GetPythonHome()
|
||||||
|
|
|
@ -476,10 +476,13 @@ These are the UTF-32 codec APIs:
|
||||||
*byteorder == 0: native order
|
*byteorder == 0: native order
|
||||||
*byteorder == 1: big endian
|
*byteorder == 1: big endian
|
||||||
|
|
||||||
and then switches if the first four bytes of the input data are a byte order mark
|
If ``*byteorder`` is zero, and the first four bytes of the input data are a
|
||||||
(BOM) and the specified byte order is native order. This BOM is not copied into
|
byte order mark (BOM), the decoder switches to this byte order and the BOM is
|
||||||
the resulting Unicode string. After completion, *\*byteorder* is set to the
|
not copied into the resulting Unicode string. If ``*byteorder`` is ``-1`` or
|
||||||
current byte order at the end of input data.
|
``1``, any byte order mark is copied to the output.
|
||||||
|
|
||||||
|
After completion, *\*byteorder* is set to the current byte order at the end
|
||||||
|
of input data.
|
||||||
|
|
||||||
In a narrow build codepoints outside the BMP will be decoded as surrogate pairs.
|
In a narrow build codepoints outside the BMP will be decoded as surrogate pairs.
|
||||||
|
|
||||||
|
@ -500,8 +503,7 @@ These are the UTF-32 codec APIs:
|
||||||
.. cfunction:: PyObject* PyUnicode_EncodeUTF32(const Py_UNICODE *s, Py_ssize_t size, const char *errors, int byteorder)
|
.. cfunction:: PyObject* PyUnicode_EncodeUTF32(const Py_UNICODE *s, Py_ssize_t size, const char *errors, int byteorder)
|
||||||
|
|
||||||
Return a Python bytes object holding the UTF-32 encoded value of the Unicode
|
Return a Python bytes object holding the UTF-32 encoded value of the Unicode
|
||||||
data in *s*. If *byteorder* is not ``0``, output is written according to the
|
data in *s*. Output is written according to the following byte order::
|
||||||
following byte order::
|
|
||||||
|
|
||||||
byteorder == -1: little endian
|
byteorder == -1: little endian
|
||||||
byteorder == 0: native byte order (writes a BOM mark)
|
byteorder == 0: native byte order (writes a BOM mark)
|
||||||
|
@ -541,10 +543,14 @@ These are the UTF-16 codec APIs:
|
||||||
*byteorder == 0: native order
|
*byteorder == 0: native order
|
||||||
*byteorder == 1: big endian
|
*byteorder == 1: big endian
|
||||||
|
|
||||||
and then switches if the first two bytes of the input data are a byte order mark
|
If ``*byteorder`` is zero, and the first two bytes of the input data are a
|
||||||
(BOM) and the specified byte order is native order. This BOM is not copied into
|
byte order mark (BOM), the decoder switches to this byte order and the BOM is
|
||||||
the resulting Unicode string. After completion, *\*byteorder* is set to the
|
not copied into the resulting Unicode string. If ``*byteorder`` is ``-1`` or
|
||||||
current byte order at the end of input data.
|
``1``, any byte order mark is copied to the output (where it will result in
|
||||||
|
either a ``\ufeff`` or a ``\ufffe`` character).
|
||||||
|
|
||||||
|
After completion, *\*byteorder* is set to the current byte order at the end
|
||||||
|
of input data.
|
||||||
|
|
||||||
If *byteorder* is *NULL*, the codec starts in native order mode.
|
If *byteorder* is *NULL*, the codec starts in native order mode.
|
||||||
|
|
||||||
|
@ -563,8 +569,7 @@ These are the UTF-16 codec APIs:
|
||||||
.. cfunction:: PyObject* PyUnicode_EncodeUTF16(const Py_UNICODE *s, Py_ssize_t size, const char *errors, int byteorder)
|
.. cfunction:: PyObject* PyUnicode_EncodeUTF16(const Py_UNICODE *s, Py_ssize_t size, const char *errors, int byteorder)
|
||||||
|
|
||||||
Return a Python bytes object holding the UTF-16 encoded value of the Unicode
|
Return a Python bytes object holding the UTF-16 encoded value of the Unicode
|
||||||
data in *s*. If *byteorder* is not ``0``, output is written according to the
|
data in *s*. Output is written according to the following byte order::
|
||||||
following byte order::
|
|
||||||
|
|
||||||
byteorder == -1: little endian
|
byteorder == -1: little endian
|
||||||
byteorder == 0: native byte order (writes a BOM mark)
|
byteorder == 0: native byte order (writes a BOM mark)
|
||||||
|
|
|
@ -597,8 +597,10 @@ units as well as normal text:
|
||||||
An important bit of information about an API that a user should be aware of
|
An important bit of information about an API that a user should be aware of
|
||||||
when using whatever bit of API the warning pertains to. The content of the
|
when using whatever bit of API the warning pertains to. The content of the
|
||||||
directive should be written in complete sentences and include all appropriate
|
directive should be written in complete sentences and include all appropriate
|
||||||
punctuation. This should only be chosen over ``note`` for information
|
punctuation. In the interest of not scaring users away from pages filled
|
||||||
regarding the possibility of crashes, data loss, or security implications.
|
with warnings, this directive should only be chosen over ``note`` for
|
||||||
|
information regarding the possibility of crashes, data loss, or security
|
||||||
|
implications.
|
||||||
|
|
||||||
.. describe:: versionadded
|
.. describe:: versionadded
|
||||||
|
|
||||||
|
|
|
@ -988,7 +988,7 @@ particular, the following variants typically exist:
|
||||||
+-----------------+--------------------------------+--------------------------------+
|
+-----------------+--------------------------------+--------------------------------+
|
||||||
| cp1255 | windows-1255 | Hebrew |
|
| cp1255 | windows-1255 | Hebrew |
|
||||||
+-----------------+--------------------------------+--------------------------------+
|
+-----------------+--------------------------------+--------------------------------+
|
||||||
| cp1256 | windows1256 | Arabic |
|
| cp1256 | windows-1256 | Arabic |
|
||||||
+-----------------+--------------------------------+--------------------------------+
|
+-----------------+--------------------------------+--------------------------------+
|
||||||
| cp1257 | windows-1257 | Baltic languages |
|
| cp1257 | windows-1257 | Baltic languages |
|
||||||
+-----------------+--------------------------------+--------------------------------+
|
+-----------------+--------------------------------+--------------------------------+
|
||||||
|
|
|
@ -63,6 +63,7 @@ Available Types
|
||||||
|
|
||||||
|
|
||||||
.. class:: date
|
.. class:: date
|
||||||
|
:noindex:
|
||||||
|
|
||||||
An idealized naive date, assuming the current Gregorian calendar always was, and
|
An idealized naive date, assuming the current Gregorian calendar always was, and
|
||||||
always will be, in effect. Attributes: :attr:`year`, :attr:`month`, and
|
always will be, in effect. Attributes: :attr:`year`, :attr:`month`, and
|
||||||
|
@ -70,6 +71,7 @@ Available Types
|
||||||
|
|
||||||
|
|
||||||
.. class:: time
|
.. class:: time
|
||||||
|
:noindex:
|
||||||
|
|
||||||
An idealized time, independent of any particular day, assuming that every day
|
An idealized time, independent of any particular day, assuming that every day
|
||||||
has exactly 24\*60\*60 seconds (there is no notion of "leap seconds" here).
|
has exactly 24\*60\*60 seconds (there is no notion of "leap seconds" here).
|
||||||
|
@ -78,6 +80,7 @@ Available Types
|
||||||
|
|
||||||
|
|
||||||
.. class:: datetime
|
.. class:: datetime
|
||||||
|
:noindex:
|
||||||
|
|
||||||
A combination of a date and a time. Attributes: :attr:`year`, :attr:`month`,
|
A combination of a date and a time. Attributes: :attr:`year`, :attr:`month`,
|
||||||
:attr:`day`, :attr:`hour`, :attr:`minute`, :attr:`second`, :attr:`microsecond`,
|
:attr:`day`, :attr:`hour`, :attr:`minute`, :attr:`second`, :attr:`microsecond`,
|
||||||
|
@ -85,6 +88,7 @@ Available Types
|
||||||
|
|
||||||
|
|
||||||
.. class:: timedelta
|
.. class:: timedelta
|
||||||
|
:noindex:
|
||||||
|
|
||||||
A duration expressing the difference between two :class:`date`, :class:`time`,
|
A duration expressing the difference between two :class:`date`, :class:`time`,
|
||||||
or :class:`datetime` instances to microsecond resolution.
|
or :class:`datetime` instances to microsecond resolution.
|
||||||
|
|
|
@ -600,16 +600,12 @@ are always available. They are listed here in alphabetical order.
|
||||||
.. function:: locals()
|
.. function:: locals()
|
||||||
|
|
||||||
Update and return a dictionary representing the current local symbol table.
|
Update and return a dictionary representing the current local symbol table.
|
||||||
|
Free variables are returned by :func:`locals` when it is called in function
|
||||||
|
blocks, but not in class blocks.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
The contents of this dictionary should not be modified; changes may not
|
The contents of this dictionary should not be modified; changes may not
|
||||||
affect the values of local variables used by the interpreter.
|
affect the values of local and free variables used by the interpreter.
|
||||||
|
|
||||||
Free variables are returned by :func:`locals` when it is called in a function
|
|
||||||
block. Modifications of free variables may not affect the values used by the
|
|
||||||
interpreter. Free variables are not returned in class blocks.
|
|
||||||
|
|
||||||
|
|
||||||
.. function:: map(function, iterable, ...)
|
.. function:: map(function, iterable, ...)
|
||||||
|
|
||||||
|
@ -1176,10 +1172,10 @@ are always available. They are listed here in alphabetical order.
|
||||||
|
|
||||||
.. function:: vars([object])
|
.. function:: vars([object])
|
||||||
|
|
||||||
Without arguments, return a dictionary corresponding to the current local symbol
|
Without an argument, act like :func:`locals`.
|
||||||
table. With a module, class or class instance object as argument (or anything
|
|
||||||
else that has a :attr:`__dict__` attribute), returns a dictionary corresponding
|
With a module, class or class instance object as argument (or anything else that
|
||||||
to the object's symbol table.
|
has a :attr:`__dict__` attribute), return that attribute.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
The returned dictionary should not be modified:
|
The returned dictionary should not be modified:
|
||||||
|
|
|
@ -86,11 +86,11 @@ The following values are provided as constant attributes of the hash objects
|
||||||
returned by the constructors:
|
returned by the constructors:
|
||||||
|
|
||||||
|
|
||||||
.. data:: digest_size
|
.. data:: hash.digest_size
|
||||||
|
|
||||||
The size of the resulting hash in bytes.
|
The size of the resulting hash in bytes.
|
||||||
|
|
||||||
.. data:: block_size
|
.. data:: hash.block_size
|
||||||
|
|
||||||
The internal block size of the hash algorithm in bytes.
|
The internal block size of the hash algorithm in bytes.
|
||||||
|
|
||||||
|
|
|
@ -508,6 +508,11 @@ line.
|
||||||
|
|
||||||
Return the frame object for the caller's stack frame.
|
Return the frame object for the caller's stack frame.
|
||||||
|
|
||||||
|
This function relies on Python stack frame support in the interpreter, which
|
||||||
|
isn't guaranteed to exist in all implementations of Python. If running in
|
||||||
|
an implementation without Python stack frame support this function returns
|
||||||
|
``None``.
|
||||||
|
|
||||||
|
|
||||||
.. function:: stack(context=1)
|
.. function:: stack(context=1)
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,7 @@ default handler so that debug messages are written to a file::
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
LOG_FILENAME = '/tmp/logging_example.out'
|
LOG_FILENAME = '/tmp/logging_example.out'
|
||||||
logging.basicConfig(filename=LOG_FILENAME,level=logging.DEBUG,)
|
logging.basicConfig(filename=LOG_FILENAME,level=logging.DEBUG)
|
||||||
|
|
||||||
logging.debug('This message should go to the log file')
|
logging.debug('This message should go to the log file')
|
||||||
|
|
||||||
|
@ -1493,6 +1493,55 @@ printed on the console; on the server side, you should see something like::
|
||||||
69 myapp.area2 WARNING Jail zesty vixen who grabbed pay from quack.
|
69 myapp.area2 WARNING Jail zesty vixen who grabbed pay from quack.
|
||||||
69 myapp.area2 ERROR The five boxing wizards jump quickly.
|
69 myapp.area2 ERROR The five boxing wizards jump quickly.
|
||||||
|
|
||||||
|
Using arbitrary objects as messages
|
||||||
|
-----------------------------------
|
||||||
|
|
||||||
|
In the preceding sections and examples, it has been assumed that the message
|
||||||
|
passed when logging the event is a string. However, this is not the only
|
||||||
|
possibility. You can pass an arbitrary object as a message, and its
|
||||||
|
:meth:`__str__` method will be called when the logging system needs to convert
|
||||||
|
it to a string representation. In fact, if you want to, you can avoid
|
||||||
|
computing a string representation altogether - for example, the
|
||||||
|
:class:`SocketHandler` emits an event by pickling it and sending it over the
|
||||||
|
wire.
|
||||||
|
|
||||||
|
Optimization
|
||||||
|
------------
|
||||||
|
|
||||||
|
Formatting of message arguments is deferred until it cannot be avoided.
|
||||||
|
However, computing the arguments passed to the logging method can also be
|
||||||
|
expensive, and you may want to avoid doing it if the logger will just throw
|
||||||
|
away your event. To decide what to do, you can call the :meth:`isEnabledFor`
|
||||||
|
method which takes a level argument and returns true if the event would be
|
||||||
|
created by the Logger for that level of call. You can write code like this::
|
||||||
|
|
||||||
|
if logger.isEnabledFor(logging.DEBUG):
|
||||||
|
logger.debug("Message with %s, %s", expensive_func1(),
|
||||||
|
expensive_func2())
|
||||||
|
|
||||||
|
so that if the logger's threshold is set above ``DEBUG``, the calls to
|
||||||
|
:func:`expensive_func1` and :func:`expensive_func2` are never made.
|
||||||
|
|
||||||
|
There are other optimizations which can be made for specific applications which
|
||||||
|
need more precise control over what logging information is collected. Here's a
|
||||||
|
list of things you can do to avoid processing during logging which you don't
|
||||||
|
need:
|
||||||
|
|
||||||
|
+-----------------------------------------------+----------------------------------------+
|
||||||
|
| What you don't want to collect | How to avoid collecting it |
|
||||||
|
+===============================================+========================================+
|
||||||
|
| Information about where calls were made from. | Set ``logging._srcfile`` to ``None``. |
|
||||||
|
+-----------------------------------------------+----------------------------------------+
|
||||||
|
| Threading information. | Set ``logging.logThreads`` to ``0``. |
|
||||||
|
+-----------------------------------------------+----------------------------------------+
|
||||||
|
| Process information. | Set ``logging.logProcesses`` to ``0``. |
|
||||||
|
+-----------------------------------------------+----------------------------------------+
|
||||||
|
|
||||||
|
Also note that the core logging module only includes the basic handlers. If
|
||||||
|
you don't import :mod:`logging.handlers` and :mod:`logging.config`, they won't
|
||||||
|
take up any memory.
|
||||||
|
|
||||||
|
.. _handler:
|
||||||
|
|
||||||
Handler Objects
|
Handler Objects
|
||||||
---------------
|
---------------
|
||||||
|
@ -1608,9 +1657,9 @@ file-like object (or, more precisely, any object which supports :meth:`write`
|
||||||
and :meth:`flush` methods).
|
and :meth:`flush` methods).
|
||||||
|
|
||||||
|
|
||||||
.. class:: StreamHandler(strm=None)
|
.. class:: StreamHandler(stream=None)
|
||||||
|
|
||||||
Returns a new instance of the :class:`StreamHandler` class. If *strm* is
|
Returns a new instance of the :class:`StreamHandler` class. If *stream* is
|
||||||
specified, the instance will use it for logging output; otherwise, *sys.stderr*
|
specified, the instance will use it for logging output; otherwise, *sys.stderr*
|
||||||
will be used.
|
will be used.
|
||||||
|
|
||||||
|
|
|
@ -27,27 +27,39 @@ lots of shared sub-objects. The keys are ordinary strings.
|
||||||
|
|
||||||
Because of Python semantics, a shelf cannot know when a mutable
|
Because of Python semantics, a shelf cannot know when a mutable
|
||||||
persistent-dictionary entry is modified. By default modified objects are
|
persistent-dictionary entry is modified. By default modified objects are
|
||||||
written only when assigned to the shelf (see :ref:`shelve-example`). If
|
written only when assigned to the shelf (see :ref:`shelve-example`). If the
|
||||||
the optional *writeback* parameter is set to *True*, all entries accessed
|
optional *writeback* parameter is set to *True*, all entries accessed are
|
||||||
are cached in memory, and written back at close time; this can make it
|
cached in memory, and written back on :meth:`sync` and :meth:`close`; this
|
||||||
handier to mutate mutable entries in the persistent dictionary, but, if
|
can make it handier to mutate mutable entries in the persistent dictionary,
|
||||||
many entries are accessed, it can consume vast amounts of memory for the
|
but, if many entries are accessed, it can consume vast amounts of memory for
|
||||||
cache, and it can make the close operation very slow since all accessed
|
the cache, and it can make the close operation very slow since all accessed
|
||||||
entries are written back (there is no way to determine which accessed
|
entries are written back (there is no way to determine which accessed entries
|
||||||
entries are mutable, nor which ones were actually mutated).
|
are mutable, nor which ones were actually mutated).
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
Do not rely on the shelf being closed automatically; always call
|
||||||
|
:meth:`close` explicitly when you don't need it any more, or use a
|
||||||
|
:keyword:`with` statement with :func:`contextlib.closing`.
|
||||||
|
|
||||||
|
|
||||||
Shelf 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:
|
Two additional methods are supported:
|
||||||
|
|
||||||
|
|
||||||
.. method:: Shelf.sync()
|
.. method:: Shelf.sync()
|
||||||
|
|
||||||
Write back all entries in the cache if the shelf was opened with *writeback* set
|
Write back all entries in the cache if the shelf was opened with *writeback*
|
||||||
to *True*. Also empty the cache and synchronize the persistent dictionary on
|
set to :const:`True`. Also empty the cache and synchronize the persistent
|
||||||
disk, if feasible. This is called automatically when the shelf is closed with
|
dictionary on disk, if feasible. This is called automatically when the shelf
|
||||||
:meth:`close`.
|
is closed with :meth:`close`.
|
||||||
|
|
||||||
|
.. method:: Shelf.close()
|
||||||
|
|
||||||
|
Synchronize and close the persistent *dict* object. Operations on a closed
|
||||||
|
shelf will fail with a :exc:`ValueError`.
|
||||||
|
|
||||||
|
|
||||||
.. seealso::
|
.. seealso::
|
||||||
|
|
||||||
|
@ -71,11 +83,6 @@ Restrictions
|
||||||
database should be fairly small, and in rare cases key collisions may cause
|
database should be fairly small, and in rare cases key collisions may cause
|
||||||
the database to refuse updates.
|
the database to refuse updates.
|
||||||
|
|
||||||
* Depending on the implementation, closing a persistent dictionary may or may
|
|
||||||
not be necessary to flush changes to disk. The :meth:`__del__` method of the
|
|
||||||
:class:`Shelf` class calls the :meth:`close` method, so the programmer generally
|
|
||||||
need not do this explicitly.
|
|
||||||
|
|
||||||
* The :mod:`shelve` module does not support *concurrent* read/write access to
|
* The :mod:`shelve` module does not support *concurrent* read/write access to
|
||||||
shelved objects. (Multiple simultaneous read accesses are safe.) When a
|
shelved objects. (Multiple simultaneous read accesses are safe.) When a
|
||||||
program has a shelf open for writing, no other program should have it open for
|
program has a shelf open for writing, no other program should have it open for
|
||||||
|
|
|
@ -1149,6 +1149,8 @@ functions based on regular expressions.
|
||||||
>>> titlecase("they're bill's friends.")
|
>>> titlecase("they're bill's friends.")
|
||||||
"They're Bill's Friends."
|
"They're Bill's Friends."
|
||||||
|
|
||||||
|
For 8-bit strings, this method is locale-dependent.
|
||||||
|
|
||||||
|
|
||||||
.. method:: str.translate(map)
|
.. method:: str.translate(map)
|
||||||
|
|
||||||
|
|
|
@ -337,12 +337,12 @@ always available.
|
||||||
does not have to hold true for third-party extensions as it is implementation
|
does not have to hold true for third-party extensions as it is implementation
|
||||||
specific.
|
specific.
|
||||||
|
|
||||||
The *default* argument allows to define a value which will be returned
|
If given, *default* will be returned if the object does not provide means to
|
||||||
if the object type does not provide means to retrieve the size and would
|
retrieve the size. Otherwise a `TypeError` will be raised.
|
||||||
cause a `TypeError`.
|
|
||||||
|
|
||||||
:func:`getsizeof` calls the object's __sizeof__ method and adds an additional
|
:func:`getsizeof` calls the object's ``__sizeof__`` method and adds an
|
||||||
garbage collector overhead if the object is managed by the garbage collector.
|
additional garbage collector overhead if the object is managed by the garbage
|
||||||
|
collector.
|
||||||
|
|
||||||
|
|
||||||
.. function:: _getframe([depth])
|
.. function:: _getframe([depth])
|
||||||
|
@ -352,7 +352,8 @@ always available.
|
||||||
that is deeper than the call stack, :exc:`ValueError` is raised. The default
|
that is deeper than the call stack, :exc:`ValueError` is raised. The default
|
||||||
for *depth* is zero, returning the frame at the top of the call stack.
|
for *depth* is zero, returning the frame at the top of the call stack.
|
||||||
|
|
||||||
This function should be used for internal and specialized purposes only.
|
This function should be used for internal and specialized purposes only. It
|
||||||
|
is not guaranteed to exist in all implementations of Python.
|
||||||
|
|
||||||
|
|
||||||
.. function:: getprofile()
|
.. function:: getprofile()
|
||||||
|
|
|
@ -89,7 +89,7 @@ technique using a separate :func:`tcgetattr` call and a :keyword:`try` ...
|
||||||
:keyword:`finally` statement to ensure that the old tty attributes are restored
|
:keyword:`finally` statement to ensure that the old tty attributes are restored
|
||||||
exactly no matter what happens::
|
exactly no matter what happens::
|
||||||
|
|
||||||
def getpass(prompt = "Password: "):
|
def getpass(prompt="Password: "):
|
||||||
import termios, sys
|
import termios, sys
|
||||||
fd = sys.stdin.fileno()
|
fd = sys.stdin.fileno()
|
||||||
old = termios.tcgetattr(fd)
|
old = termios.tcgetattr(fd)
|
||||||
|
|
|
@ -23,7 +23,7 @@ This module defines the following functions and objects:
|
||||||
.. function:: active_count()
|
.. function:: active_count()
|
||||||
|
|
||||||
Return the number of :class:`Thread` objects currently alive. The returned
|
Return the number of :class:`Thread` objects currently alive. The returned
|
||||||
count is equal to the length of the list returned by :func:`enumerate`.
|
count is equal to the length of the list returned by :func:`.enumerate`.
|
||||||
|
|
||||||
|
|
||||||
.. function:: Condition()
|
.. function:: Condition()
|
||||||
|
@ -301,7 +301,7 @@ impossible to detect the termination of alien threads.
|
||||||
|
|
||||||
Roughly, a thread is alive from the moment the :meth:`start` method
|
Roughly, a thread is alive from the moment the :meth:`start` method
|
||||||
returns until its :meth:`run` method terminates. The module function
|
returns until its :meth:`run` method terminates. The module function
|
||||||
:func:`enumerate` returns a list of all alive threads.
|
:func:`.enumerate` returns a list of all alive threads.
|
||||||
|
|
||||||
.. attribute:: daemon
|
.. attribute:: daemon
|
||||||
|
|
||||||
|
|
|
@ -728,6 +728,9 @@ Test cases
|
||||||
compare equal, the test will fail with the explanation given by *msg*, or
|
compare equal, the test will fail with the explanation given by *msg*, or
|
||||||
:const:`None`.
|
:const:`None`.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.2
|
||||||
|
Objects that compare equal are automatically almost equal.
|
||||||
|
|
||||||
.. deprecated:: 3.1
|
.. deprecated:: 3.1
|
||||||
:meth:`failUnlessAlmostEqual`.
|
:meth:`failUnlessAlmostEqual`.
|
||||||
|
|
||||||
|
@ -744,6 +747,9 @@ Test cases
|
||||||
compare equal, the test will fail with the explanation given by *msg*, or
|
compare equal, the test will fail with the explanation given by *msg*, or
|
||||||
:const:`None`.
|
:const:`None`.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.2
|
||||||
|
Objects that compare equal automatically fail.
|
||||||
|
|
||||||
.. deprecated:: 3.1
|
.. deprecated:: 3.1
|
||||||
:meth:`failIfAlmostEqual`.
|
:meth:`failIfAlmostEqual`.
|
||||||
|
|
||||||
|
@ -1244,18 +1250,23 @@ Loading and running tests
|
||||||
|
|
||||||
Find and return all test modules from the specified start directory,
|
Find and return all test modules from the specified start directory,
|
||||||
recursing into subdirectories to find them. Only test files that match
|
recursing into subdirectories to find them. Only test files that match
|
||||||
*pattern* will be loaded. (Using shell style pattern matching.)
|
*pattern* will be loaded. (Using shell style pattern matching.) Only
|
||||||
|
module names that are importable (i.e. are valid Python identifiers) will
|
||||||
|
be loaded.
|
||||||
|
|
||||||
All test modules must be importable from the top level of the project. If
|
All test modules must be importable from the top level of the project. If
|
||||||
the start directory is not the top level directory then the top level
|
the start directory is not the top level directory then the top level
|
||||||
directory must be specified separately.
|
directory must be specified separately.
|
||||||
|
|
||||||
|
If importing a module fails, for example due to a syntax error, then this
|
||||||
|
will be recorded as a single error and discovery will continue.
|
||||||
|
|
||||||
If a test package name (directory with :file:`__init__.py`) matches the
|
If a test package name (directory with :file:`__init__.py`) matches the
|
||||||
pattern then the package will be checked for a ``load_tests``
|
pattern then the package will be checked for a ``load_tests``
|
||||||
function. If this exists then it will be called with *loader*, *tests*,
|
function. If this exists then it will be called with *loader*, *tests*,
|
||||||
*pattern*.
|
*pattern*.
|
||||||
|
|
||||||
If load_tests exists then discovery does *not* recurse into the package,
|
If load_tests exists then discovery does *not* recurse into the package,
|
||||||
``load_tests`` is responsible for loading all tests in the package.
|
``load_tests`` is responsible for loading all tests in the package.
|
||||||
|
|
||||||
The pattern is deliberately not stored as a loader attribute so that
|
The pattern is deliberately not stored as a loader attribute so that
|
||||||
|
@ -1263,6 +1274,7 @@ Loading and running tests
|
||||||
``load_tests`` does not need to pass this argument in to
|
``load_tests`` does not need to pass this argument in to
|
||||||
``loader.discover()``.
|
``loader.discover()``.
|
||||||
|
|
||||||
|
.. versionadded:: 2.7
|
||||||
|
|
||||||
The following attributes of a :class:`TestLoader` can be configured either by
|
The following attributes of a :class:`TestLoader` can be configured either by
|
||||||
subclassing or assignment on an instance:
|
subclassing or assignment on an instance:
|
||||||
|
@ -1518,6 +1530,10 @@ Loading and running tests
|
||||||
load_tests Protocol
|
load_tests Protocol
|
||||||
###################
|
###################
|
||||||
|
|
||||||
|
|
||||||
|
.. versionadded:: 2.7
|
||||||
|
|
||||||
|
|
||||||
Modules or packages can customize how tests are loaded from them during normal
|
Modules or packages can customize how tests are loaded from them during normal
|
||||||
test runs or test discovery by implementing a function called ``load_tests``.
|
test runs or test discovery by implementing a function called ``load_tests``.
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ command into the command prompt in a DOS box::
|
||||||
Typing an end-of-file character (:kbd:`Control-D` on Unix, :kbd:`Control-Z` on
|
Typing an end-of-file character (:kbd:`Control-D` on Unix, :kbd:`Control-Z` on
|
||||||
Windows) at the primary prompt causes the interpreter to exit with a zero exit
|
Windows) at the primary prompt causes the interpreter to exit with a zero exit
|
||||||
status. If that doesn't work, you can exit the interpreter by typing the
|
status. If that doesn't work, you can exit the interpreter by typing the
|
||||||
following commands: ``import sys; sys.exit()``.
|
following command: ``quit()``.
|
||||||
|
|
||||||
The interpreter's line-editing features usually aren't very sophisticated. On
|
The interpreter's line-editing features usually aren't very sophisticated. On
|
||||||
Unix, whoever installed the interpreter may have enabled support for the GNU
|
Unix, whoever installed the interpreter may have enabled support for the GNU
|
||||||
|
|
|
@ -107,6 +107,10 @@ In most cases Python programmers do not use this facility since it introduces
|
||||||
an unknown set of names into the interpreter, possibly hiding some things
|
an unknown set of names into the interpreter, possibly hiding some things
|
||||||
you have already defined.
|
you have already defined.
|
||||||
|
|
||||||
|
Note that in general the practice of importing ``*`` from a module or package is
|
||||||
|
frowned upon, since it often causes poorly readable code. However, it is okay to
|
||||||
|
use it to save typing in interactive sessions.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
For efficiency reasons, each module is only imported once per interpreter
|
For efficiency reasons, each module is only imported once per interpreter
|
||||||
|
@ -445,14 +449,9 @@ Importing \* From a Package
|
||||||
|
|
||||||
Now what happens when the user writes ``from sound.effects import *``? Ideally,
|
Now what happens when the user writes ``from sound.effects import *``? Ideally,
|
||||||
one would hope that this somehow goes out to the filesystem, finds which
|
one would hope that this somehow goes out to the filesystem, finds which
|
||||||
submodules are present in the package, and imports them all. Unfortunately,
|
submodules are present in the package, and imports them all. This could take a
|
||||||
this operation does not work very well on Windows platforms, where the
|
long time and importing sub-modules might have unwanted side-effects that should
|
||||||
filesystem does not always have accurate information about the case of a
|
only happen when the sub-module is explicitly imported.
|
||||||
filename. On these platforms, there is no guaranteed way to know whether a file
|
|
||||||
:file:`ECHO.PY` should be imported as a module :mod:`echo`, :mod:`Echo` or
|
|
||||||
:mod:`ECHO`. (For example, Windows 95 has the annoying practice of showing all
|
|
||||||
file names with a capitalized first letter.) The DOS 8+3 filename restriction
|
|
||||||
adds another interesting problem for long module names.
|
|
||||||
|
|
||||||
The only solution is for the package author to provide an explicit index of the
|
The only solution is for the package author to provide an explicit index of the
|
||||||
package. The :keyword:`import` statement uses the following convention: if a package's
|
package. The :keyword:`import` statement uses the following convention: if a package's
|
||||||
|
@ -487,10 +486,9 @@ current namespace because they are defined in the :mod:`sound.effects` package
|
||||||
when the ``from...import`` statement is executed. (This also works when
|
when the ``from...import`` statement is executed. (This also works when
|
||||||
``__all__`` is defined.)
|
``__all__`` is defined.)
|
||||||
|
|
||||||
Note that in general the practice of importing ``*`` from a module or package is
|
Although certain modules are designed to export only names that follow certain
|
||||||
frowned upon, since it often causes poorly readable code. However, it is okay to
|
patterns when you use ``import *``, it is still considered bad practise in
|
||||||
use it to save typing in interactive sessions, and certain modules are designed
|
production code.
|
||||||
to export only names that follow certain patterns.
|
|
||||||
|
|
||||||
Remember, there is nothing wrong with using ``from Package import
|
Remember, there is nothing wrong with using ``from Package import
|
||||||
specific_submodule``! In fact, this is the recommended notation unless the
|
specific_submodule``! In fact, this is the recommended notation unless the
|
||||||
|
|
|
@ -505,6 +505,13 @@ changes, or look through the Subversion logs for all the details.
|
||||||
differences. :meth:`assertDictContainsSubset` checks whether
|
differences. :meth:`assertDictContainsSubset` checks whether
|
||||||
all of the key/value pairs in *first* are found in *second*.
|
all of the key/value pairs in *first* are found in *second*.
|
||||||
|
|
||||||
|
* :meth:`assertAlmostEqual` and :meth:`assertNotAlmostEqual` short-circuit
|
||||||
|
(automatically pass or fail without checking decimal places) if the objects
|
||||||
|
are equal.
|
||||||
|
|
||||||
|
* :meth:`loadTestsFromName` properly honors the ``suiteClass`` attribute of
|
||||||
|
the :class:`TestLoader`. (Fixed by Mark Roddy; :issue:`6866`.)
|
||||||
|
|
||||||
* A new hook, :meth:`addTypeEqualityFunc` takes a type object and a
|
* A new hook, :meth:`addTypeEqualityFunc` takes a type object and a
|
||||||
function. The :meth:`assertEqual` method will use the function
|
function. The :meth:`assertEqual` method will use the function
|
||||||
when both of the objects being compared are of the specified type.
|
when both of the objects being compared are of the specified type.
|
||||||
|
|
22
Lib/csv.py
22
Lib/csv.py
|
@ -165,7 +165,7 @@ class Sniffer:
|
||||||
Returns a dialect (or None) corresponding to the sample
|
Returns a dialect (or None) corresponding to the sample
|
||||||
"""
|
"""
|
||||||
|
|
||||||
quotechar, delimiter, skipinitialspace = \
|
quotechar, doublequote, delimiter, skipinitialspace = \
|
||||||
self._guess_quote_and_delimiter(sample, delimiters)
|
self._guess_quote_and_delimiter(sample, delimiters)
|
||||||
if not delimiter:
|
if not delimiter:
|
||||||
delimiter, skipinitialspace = self._guess_delimiter(sample,
|
delimiter, skipinitialspace = self._guess_delimiter(sample,
|
||||||
|
@ -179,8 +179,8 @@ class Sniffer:
|
||||||
lineterminator = '\r\n'
|
lineterminator = '\r\n'
|
||||||
quoting = QUOTE_MINIMAL
|
quoting = QUOTE_MINIMAL
|
||||||
# escapechar = ''
|
# escapechar = ''
|
||||||
doublequote = False
|
|
||||||
|
|
||||||
|
dialect.doublequote = doublequote
|
||||||
dialect.delimiter = delimiter
|
dialect.delimiter = delimiter
|
||||||
# _csv.reader won't accept a quotechar of ''
|
# _csv.reader won't accept a quotechar of ''
|
||||||
dialect.quotechar = quotechar or '"'
|
dialect.quotechar = quotechar or '"'
|
||||||
|
@ -212,8 +212,8 @@ class Sniffer:
|
||||||
break
|
break
|
||||||
|
|
||||||
if not matches:
|
if not matches:
|
||||||
return ('', None, 0) # (quotechar, delimiter, skipinitialspace)
|
# (quotechar, doublequote, delimiter, skipinitialspace)
|
||||||
|
return ('', False, None, 0)
|
||||||
quotes = {}
|
quotes = {}
|
||||||
delims = {}
|
delims = {}
|
||||||
spaces = 0
|
spaces = 0
|
||||||
|
@ -248,7 +248,19 @@ class Sniffer:
|
||||||
delim = ''
|
delim = ''
|
||||||
skipinitialspace = 0
|
skipinitialspace = 0
|
||||||
|
|
||||||
return (quotechar, delim, skipinitialspace)
|
# if we see an extra quote between delimiters, we've got a
|
||||||
|
# double quoted format
|
||||||
|
dq_regexp = re.compile(r"((%(delim)s)|^)\W*%(quote)s[^%(delim)s\n]*%(quote)s[^%(delim)s\n]*%(quote)s\W*((%(delim)s)|$)" % \
|
||||||
|
{'delim':delim, 'quote':quotechar}, re.MULTILINE)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if dq_regexp.search(data):
|
||||||
|
doublequote = True
|
||||||
|
else:
|
||||||
|
doublequote = False
|
||||||
|
|
||||||
|
return (quotechar, doublequote, delim, skipinitialspace)
|
||||||
|
|
||||||
|
|
||||||
def _guess_delimiter(self, data, delimiters):
|
def _guess_delimiter(self, data, delimiters):
|
||||||
|
|
|
@ -51,7 +51,7 @@ def unix_getpass(prompt='Password: ', stream=None):
|
||||||
# If that fails, see if stdin can be controlled.
|
# If that fails, see if stdin can be controlled.
|
||||||
try:
|
try:
|
||||||
fd = sys.stdin.fileno()
|
fd = sys.stdin.fileno()
|
||||||
except:
|
except (AttributeError, ValueError):
|
||||||
passwd = fallback_getpass(prompt, stream)
|
passwd = fallback_getpass(prompt, stream)
|
||||||
input = sys.stdin
|
input = sys.stdin
|
||||||
if not stream:
|
if not stream:
|
||||||
|
|
|
@ -398,12 +398,12 @@ def getfile(object):
|
||||||
if ismodule(object):
|
if ismodule(object):
|
||||||
if hasattr(object, '__file__'):
|
if hasattr(object, '__file__'):
|
||||||
return object.__file__
|
return object.__file__
|
||||||
raise TypeError('arg is a built-in module')
|
raise TypeError('{!r} is a built-in module'.format(object))
|
||||||
if isclass(object):
|
if isclass(object):
|
||||||
object = sys.modules.get(object.__module__)
|
object = sys.modules.get(object.__module__)
|
||||||
if hasattr(object, '__file__'):
|
if hasattr(object, '__file__'):
|
||||||
return object.__file__
|
return object.__file__
|
||||||
raise TypeError('arg is a built-in class')
|
raise TypeError('{!r} is a built-in class'.format(object))
|
||||||
if ismethod(object):
|
if ismethod(object):
|
||||||
object = object.__func__
|
object = object.__func__
|
||||||
if isfunction(object):
|
if isfunction(object):
|
||||||
|
@ -414,8 +414,8 @@ def getfile(object):
|
||||||
object = object.f_code
|
object = object.f_code
|
||||||
if iscode(object):
|
if iscode(object):
|
||||||
return object.co_filename
|
return object.co_filename
|
||||||
raise TypeError('arg is not a module, class, method, '
|
raise TypeError('{!r} is not a module, class, method, '
|
||||||
'function, traceback, frame, or code object')
|
'function, traceback, frame, or code object'.format(object))
|
||||||
|
|
||||||
ModuleInfo = namedtuple('ModuleInfo', 'name suffix mode module_type')
|
ModuleInfo = namedtuple('ModuleInfo', 'name suffix mode module_type')
|
||||||
|
|
||||||
|
@ -747,7 +747,7 @@ def _getfullargs(co):
|
||||||
names of the * and ** arguments or None."""
|
names of the * and ** arguments or None."""
|
||||||
|
|
||||||
if not iscode(co):
|
if not iscode(co):
|
||||||
raise TypeError('arg is not a code object')
|
raise TypeError('{!r} is not a code object'.format(co))
|
||||||
|
|
||||||
nargs = co.co_argcount
|
nargs = co.co_argcount
|
||||||
names = co.co_varnames
|
names = co.co_varnames
|
||||||
|
@ -811,7 +811,7 @@ def getfullargspec(func):
|
||||||
if ismethod(func):
|
if ismethod(func):
|
||||||
func = func.__func__
|
func = func.__func__
|
||||||
if not isfunction(func):
|
if not isfunction(func):
|
||||||
raise TypeError('arg is not a Python function')
|
raise TypeError('{!r} is not a Python function'.format(func))
|
||||||
args, varargs, kwonlyargs, varkw = _getfullargs(func.__code__)
|
args, varargs, kwonlyargs, varkw = _getfullargs(func.__code__)
|
||||||
return FullArgSpec(args, varargs, varkw, func.__defaults__,
|
return FullArgSpec(args, varargs, varkw, func.__defaults__,
|
||||||
kwonlyargs, func.__kwdefaults__, func.__annotations__)
|
kwonlyargs, func.__kwdefaults__, func.__annotations__)
|
||||||
|
@ -944,7 +944,7 @@ def getframeinfo(frame, context=1):
|
||||||
else:
|
else:
|
||||||
lineno = frame.f_lineno
|
lineno = frame.f_lineno
|
||||||
if not isframe(frame):
|
if not isframe(frame):
|
||||||
raise TypeError('arg is not a frame or traceback object')
|
raise TypeError('{!r} is not a frame or traceback object'.format(frame))
|
||||||
|
|
||||||
filename = getsourcefile(frame) or getfile(frame)
|
filename = getsourcefile(frame) or getfile(frame)
|
||||||
if context > 0:
|
if context > 0:
|
||||||
|
|
|
@ -282,11 +282,14 @@ class LogRecord:
|
||||||
else:
|
else:
|
||||||
self.thread = None
|
self.thread = None
|
||||||
self.threadName = None
|
self.threadName = None
|
||||||
if logMultiprocessing:
|
if not logMultiprocessing:
|
||||||
from multiprocessing import current_process
|
|
||||||
self.processName = current_process().name
|
|
||||||
else:
|
|
||||||
self.processName = None
|
self.processName = None
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
from multiprocessing import current_process
|
||||||
|
self.processName = current_process().name
|
||||||
|
except ImportError:
|
||||||
|
self.processName = None
|
||||||
if logProcesses and hasattr(os, 'getpid'):
|
if logProcesses and hasattr(os, 'getpid'):
|
||||||
self.process = os.getpid()
|
self.process = os.getpid()
|
||||||
else:
|
else:
|
||||||
|
@ -745,16 +748,16 @@ class StreamHandler(Handler):
|
||||||
sys.stdout or sys.stderr may be used.
|
sys.stdout or sys.stderr may be used.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, strm=None):
|
def __init__(self, stream=None):
|
||||||
"""
|
"""
|
||||||
Initialize the handler.
|
Initialize the handler.
|
||||||
|
|
||||||
If strm is not specified, sys.stderr is used.
|
If stream is not specified, sys.stderr is used.
|
||||||
"""
|
"""
|
||||||
Handler.__init__(self)
|
Handler.__init__(self)
|
||||||
if strm is None:
|
if stream is None:
|
||||||
strm = sys.stderr
|
stream = sys.stderr
|
||||||
self.stream = strm
|
self.stream = stream
|
||||||
|
|
||||||
def flush(self):
|
def flush(self):
|
||||||
"""
|
"""
|
||||||
|
@ -1124,7 +1127,11 @@ class Logger(Filterer):
|
||||||
Find the stack frame of the caller so that we can note the source
|
Find the stack frame of the caller so that we can note the source
|
||||||
file name, line number and function name.
|
file name, line number and function name.
|
||||||
"""
|
"""
|
||||||
f = currentframe().f_back
|
f = currentframe()
|
||||||
|
#On some versions of IronPython, currentframe() returns None if
|
||||||
|
#IronPython isn't run with -X:Frames.
|
||||||
|
if f is not None:
|
||||||
|
f = f.f_back
|
||||||
rv = "(unknown file)", 0, "(unknown function)"
|
rv = "(unknown file)", 0, "(unknown function)"
|
||||||
while hasattr(f, "f_code"):
|
while hasattr(f, "f_code"):
|
||||||
co = f.f_code
|
co = f.f_code
|
||||||
|
@ -1156,7 +1163,8 @@ class Logger(Filterer):
|
||||||
"""
|
"""
|
||||||
if _srcfile:
|
if _srcfile:
|
||||||
#IronPython doesn't track Python frames, so findCaller throws an
|
#IronPython doesn't track Python frames, so findCaller throws an
|
||||||
#exception. We trap it here so that IronPython can use logging.
|
#exception on some versions of IronPython. We trap it here so that
|
||||||
|
#IronPython can use logging.
|
||||||
try:
|
try:
|
||||||
fn, lno, func = self.findCaller()
|
fn, lno, func = self.findCaller()
|
||||||
except ValueError:
|
except ValueError:
|
||||||
|
|
|
@ -413,7 +413,7 @@ class Server(object):
|
||||||
self.id_to_refcount[ident] -= 1
|
self.id_to_refcount[ident] -= 1
|
||||||
if self.id_to_refcount[ident] == 0:
|
if self.id_to_refcount[ident] == 0:
|
||||||
del self.id_to_obj[ident], self.id_to_refcount[ident]
|
del self.id_to_obj[ident], self.id_to_refcount[ident]
|
||||||
util.debug('disposing of obj with id %d', ident)
|
util.debug('disposing of obj with id %r', ident)
|
||||||
finally:
|
finally:
|
||||||
self.mutex.release()
|
self.mutex.release()
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
"""
|
"""
|
||||||
# This module is maintained by Marc-Andre Lemburg <mal@egenix.com>.
|
# This module is maintained by Marc-Andre Lemburg <mal@egenix.com>.
|
||||||
# If you find problems, please submit bug reports/patches via the
|
# If you find problems, please submit bug reports/patches via the
|
||||||
# Python SourceForge Project Page and assign them to "lemburg".
|
# Python bug tracker (http://bugs.python.org) and assign them to "lemburg".
|
||||||
#
|
#
|
||||||
# Still needed:
|
# Still needed:
|
||||||
# * more support for WinCE
|
# * more support for WinCE
|
||||||
|
|
|
@ -82,6 +82,7 @@ class AllTest(unittest.TestCase):
|
||||||
self.check_all("keyword")
|
self.check_all("keyword")
|
||||||
self.check_all("linecache")
|
self.check_all("linecache")
|
||||||
self.check_all("locale")
|
self.check_all("locale")
|
||||||
|
self.check_all("logging")
|
||||||
self.check_all("macpath")
|
self.check_all("macpath")
|
||||||
self.check_all("macurl2path")
|
self.check_all("macurl2path")
|
||||||
self.check_all("mailbox")
|
self.check_all("mailbox")
|
||||||
|
|
|
@ -767,7 +767,7 @@ Stonecutters Seafood and Chop House, Lemont, IL, 12/19/02, Week Back
|
||||||
'Harry''s':'Arlington Heights':'IL':'2/1/03':'Kimi Hayes'
|
'Harry''s':'Arlington Heights':'IL':'2/1/03':'Kimi Hayes'
|
||||||
'Shark City':'Glendale Heights':'IL':'12/28/02':'Prezence'
|
'Shark City':'Glendale Heights':'IL':'12/28/02':'Prezence'
|
||||||
'Tommy''s Place':'Blue Island':'IL':'12/28/02':'Blue Sunday/White Crow'
|
'Tommy''s Place':'Blue Island':'IL':'12/28/02':'Blue Sunday/White Crow'
|
||||||
'Stonecutters Seafood and Chop House':'Lemont':'IL':'12/19/02':'Week Back'
|
'Stonecutters ''Seafood'' and Chop House':'Lemont':'IL':'12/19/02':'Week Back'
|
||||||
"""
|
"""
|
||||||
header = '''\
|
header = '''\
|
||||||
"venue","city","state","date","performers"
|
"venue","city","state","date","performers"
|
||||||
|
@ -826,6 +826,13 @@ Stonecutters Seafood and Chop House, Lemont, IL, 12/19/02, Week Back
|
||||||
self.assertEqual(dialect.delimiter, "|")
|
self.assertEqual(dialect.delimiter, "|")
|
||||||
self.assertEqual(dialect.quotechar, "'")
|
self.assertEqual(dialect.quotechar, "'")
|
||||||
|
|
||||||
|
def test_doublequote(self):
|
||||||
|
sniffer = csv.Sniffer()
|
||||||
|
dialect = sniffer.sniff(self.header)
|
||||||
|
self.assertFalse(dialect.doublequote)
|
||||||
|
dialect = sniffer.sniff(self.sample2)
|
||||||
|
self.assertTrue(dialect.doublequote)
|
||||||
|
|
||||||
if not hasattr(sys, "gettotalrefcount"):
|
if not hasattr(sys, "gettotalrefcount"):
|
||||||
if support.verbose: print("*** skipping leakage tests ***")
|
if support.verbose: print("*** skipping leakage tests ***")
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -291,7 +291,7 @@ class GeneralModuleTests(unittest.TestCase):
|
||||||
# On some versions, this loses a reference
|
# On some versions, this loses a reference
|
||||||
orig = sys.getrefcount(__name__)
|
orig = sys.getrefcount(__name__)
|
||||||
socket.getnameinfo(__name__,0)
|
socket.getnameinfo(__name__,0)
|
||||||
except SystemError:
|
except TypeError:
|
||||||
if sys.getrefcount(__name__) != orig:
|
if sys.getrefcount(__name__) != orig:
|
||||||
self.fail("socket.getnameinfo loses a reference")
|
self.fail("socket.getnameinfo loses a reference")
|
||||||
|
|
||||||
|
|
|
@ -554,6 +554,47 @@ class Test_TestLoader(TestCase):
|
||||||
self.assertTrue(isinstance(suite, loader.suiteClass))
|
self.assertTrue(isinstance(suite, loader.suiteClass))
|
||||||
self.assertEqual(list(suite), [testcase_1])
|
self.assertEqual(list(suite), [testcase_1])
|
||||||
|
|
||||||
|
# "The specifier name is a ``dotted name'' that may resolve ... to
|
||||||
|
# ... a callable object which returns a TestCase ... instance"
|
||||||
|
#*****************************************************************
|
||||||
|
#Override the suiteClass attribute to ensure that the suiteClass
|
||||||
|
#attribute is used
|
||||||
|
def test_loadTestsFromName__callable__TestCase_instance_ProperSuiteClass(self):
|
||||||
|
class SubTestSuite(unittest.TestSuite):
|
||||||
|
pass
|
||||||
|
m = types.ModuleType('m')
|
||||||
|
testcase_1 = unittest.FunctionTestCase(lambda: None)
|
||||||
|
def return_TestCase():
|
||||||
|
return testcase_1
|
||||||
|
m.return_TestCase = return_TestCase
|
||||||
|
|
||||||
|
loader = unittest.TestLoader()
|
||||||
|
loader.suiteClass = SubTestSuite
|
||||||
|
suite = loader.loadTestsFromName('return_TestCase', m)
|
||||||
|
self.assertTrue(isinstance(suite, loader.suiteClass))
|
||||||
|
self.assertEqual(list(suite), [testcase_1])
|
||||||
|
|
||||||
|
# "The specifier name is a ``dotted name'' that may resolve ... to
|
||||||
|
# ... a test method within a test case class"
|
||||||
|
#*****************************************************************
|
||||||
|
#Override the suiteClass attribute to ensure that the suiteClass
|
||||||
|
#attribute is used
|
||||||
|
def test_loadTestsFromName__relative_testmethod_ProperSuiteClass(self):
|
||||||
|
class SubTestSuite(unittest.TestSuite):
|
||||||
|
pass
|
||||||
|
m = types.ModuleType('m')
|
||||||
|
class MyTestCase(unittest.TestCase):
|
||||||
|
def test(self):
|
||||||
|
pass
|
||||||
|
m.testcase_1 = MyTestCase
|
||||||
|
|
||||||
|
loader = unittest.TestLoader()
|
||||||
|
loader.suiteClass=SubTestSuite
|
||||||
|
suite = loader.loadTestsFromName('testcase_1.test', m)
|
||||||
|
self.assertTrue(isinstance(suite, loader.suiteClass))
|
||||||
|
|
||||||
|
self.assertEqual(list(suite), [MyTestCase('test')])
|
||||||
|
|
||||||
# "The specifier name is a ``dotted name'' that may resolve ... to
|
# "The specifier name is a ``dotted name'' that may resolve ... to
|
||||||
# ... a callable object which returns a TestCase or TestSuite instance"
|
# ... a callable object which returns a TestCase or TestSuite instance"
|
||||||
#
|
#
|
||||||
|
@ -2953,6 +2994,11 @@ class Test_Assertions(TestCase):
|
||||||
self.assertRaises(self.failureException,
|
self.assertRaises(self.failureException,
|
||||||
self.assertNotAlmostEqual, 0, .1+.1j, places=0)
|
self.assertNotAlmostEqual, 0, .1+.1j, places=0)
|
||||||
|
|
||||||
|
self.assertAlmostEqual(float('inf'), float('inf'))
|
||||||
|
self.assertRaises(self.failureException, self.assertNotAlmostEqual,
|
||||||
|
float('inf'), float('inf'))
|
||||||
|
|
||||||
|
|
||||||
def test_assertRaises(self):
|
def test_assertRaises(self):
|
||||||
def _raise(e):
|
def _raise(e):
|
||||||
raise e
|
raise e
|
||||||
|
@ -3387,31 +3433,18 @@ class Test_TextTestRunner(TestCase):
|
||||||
class TestDiscovery(TestCase):
|
class TestDiscovery(TestCase):
|
||||||
|
|
||||||
# Heavily mocked tests so I can avoid hitting the filesystem
|
# Heavily mocked tests so I can avoid hitting the filesystem
|
||||||
def test_get_module_from_path(self):
|
def test_get_name_from_path(self):
|
||||||
loader = unittest.TestLoader()
|
loader = unittest.TestLoader()
|
||||||
|
|
||||||
old_import = __import__
|
|
||||||
def restore_import():
|
|
||||||
builtins.__import__ = old_import
|
|
||||||
builtins.__import__ = lambda *_: None
|
|
||||||
self.addCleanup(restore_import)
|
|
||||||
|
|
||||||
expected_module = object()
|
|
||||||
def del_module():
|
|
||||||
del sys.modules['bar.baz']
|
|
||||||
sys.modules['bar.baz'] = expected_module
|
|
||||||
self.addCleanup(del_module)
|
|
||||||
|
|
||||||
loader._top_level_dir = '/foo'
|
loader._top_level_dir = '/foo'
|
||||||
module = loader._get_module_from_path('/foo/bar/baz.py')
|
name = loader._get_name_from_path('/foo/bar/baz.py')
|
||||||
self.assertEqual(module, expected_module)
|
self.assertEqual(name, 'bar.baz')
|
||||||
|
|
||||||
if not __debug__:
|
if not __debug__:
|
||||||
# asserts are off
|
# asserts are off
|
||||||
return
|
return
|
||||||
|
|
||||||
with self.assertRaises(AssertionError):
|
with self.assertRaises(AssertionError):
|
||||||
loader._get_module_from_path('/bar/baz.py')
|
loader._get_name_from_path('/bar/baz.py')
|
||||||
|
|
||||||
def test_find_tests(self):
|
def test_find_tests(self):
|
||||||
loader = unittest.TestLoader()
|
loader = unittest.TestLoader()
|
||||||
|
@ -3427,7 +3460,7 @@ class TestDiscovery(TestCase):
|
||||||
os.path.isdir = original_isdir
|
os.path.isdir = original_isdir
|
||||||
|
|
||||||
path_lists = [['test1.py', 'test2.py', 'not_a_test.py', 'test_dir',
|
path_lists = [['test1.py', 'test2.py', 'not_a_test.py', 'test_dir',
|
||||||
'test.foo', 'another_dir'],
|
'test.foo', 'test-not-a-module.py', 'another_dir'],
|
||||||
['test3.py', 'test4.py', ]]
|
['test3.py', 'test4.py', ]]
|
||||||
os.listdir = lambda path: path_lists.pop(0)
|
os.listdir = lambda path: path_lists.pop(0)
|
||||||
self.addCleanup(restore_listdir)
|
self.addCleanup(restore_listdir)
|
||||||
|
@ -3443,16 +3476,16 @@ class TestDiscovery(TestCase):
|
||||||
os.path.isfile = isfile
|
os.path.isfile = isfile
|
||||||
self.addCleanup(restore_isfile)
|
self.addCleanup(restore_isfile)
|
||||||
|
|
||||||
loader._get_module_from_path = lambda path: path + ' module'
|
loader._get_module_from_name = lambda path: path + ' module'
|
||||||
loader.loadTestsFromModule = lambda module: module + ' tests'
|
loader.loadTestsFromModule = lambda module: module + ' tests'
|
||||||
|
|
||||||
loader._top_level_dir = '/foo'
|
loader._top_level_dir = '/foo'
|
||||||
suite = list(loader._find_tests('/foo', 'test*.py'))
|
suite = list(loader._find_tests('/foo', 'test*.py'))
|
||||||
|
|
||||||
expected = [os.path.join('/foo', name) + ' module tests' for name in
|
expected = [name + ' module tests' for name in
|
||||||
('test1.py', 'test2.py')]
|
('test1', 'test2')]
|
||||||
expected.extend([os.path.join('/foo', 'test_dir', name) + ' module tests' for name in
|
expected.extend([('test_dir.%s' % name) + ' module tests' for name in
|
||||||
('test3.py', 'test4.py')])
|
('test3', 'test4')])
|
||||||
self.assertEqual(suite, expected)
|
self.assertEqual(suite, expected)
|
||||||
|
|
||||||
def test_find_tests_with_package(self):
|
def test_find_tests_with_package(self):
|
||||||
|
@ -3495,7 +3528,7 @@ class TestDiscovery(TestCase):
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
return self.path == other.path
|
return self.path == other.path
|
||||||
|
|
||||||
loader._get_module_from_path = lambda path: Module(path)
|
loader._get_module_from_name = lambda name: Module(name)
|
||||||
def loadTestsFromModule(module, use_load_tests):
|
def loadTestsFromModule(module, use_load_tests):
|
||||||
if use_load_tests:
|
if use_load_tests:
|
||||||
raise self.failureException('use_load_tests should be False for packages')
|
raise self.failureException('use_load_tests should be False for packages')
|
||||||
|
@ -3510,15 +3543,12 @@ class TestDiscovery(TestCase):
|
||||||
# We should have loaded tests from the test_directory package by calling load_tests
|
# We should have loaded tests from the test_directory package by calling load_tests
|
||||||
# and directly from the test_directory2 package
|
# and directly from the test_directory2 package
|
||||||
self.assertEqual(suite,
|
self.assertEqual(suite,
|
||||||
['load_tests',
|
['load_tests', 'test_directory2' + ' module tests'])
|
||||||
os.path.join('/foo', 'test_directory2') + ' module tests'])
|
self.assertEqual(Module.paths, ['test_directory', 'test_directory2'])
|
||||||
self.assertEqual(Module.paths, [os.path.join('/foo', 'test_directory'),
|
|
||||||
os.path.join('/foo', 'test_directory2')])
|
|
||||||
|
|
||||||
# load_tests should have been called once with loader, tests and pattern
|
# load_tests should have been called once with loader, tests and pattern
|
||||||
self.assertEqual(Module.load_tests_args,
|
self.assertEqual(Module.load_tests_args,
|
||||||
[(loader, os.path.join('/foo', 'test_directory') + ' module tests',
|
[(loader, 'test_directory' + ' module tests', 'test*')])
|
||||||
'test*')])
|
|
||||||
|
|
||||||
def test_discover(self):
|
def test_discover(self):
|
||||||
loader = unittest.TestLoader()
|
loader = unittest.TestLoader()
|
||||||
|
@ -3558,6 +3588,25 @@ class TestDiscovery(TestCase):
|
||||||
self.assertEqual(loader._top_level_dir, top_level_dir)
|
self.assertEqual(loader._top_level_dir, top_level_dir)
|
||||||
self.assertEqual(_find_tests_args, [(start_dir, 'pattern')])
|
self.assertEqual(_find_tests_args, [(start_dir, 'pattern')])
|
||||||
|
|
||||||
|
def test_discover_with_modules_that_fail_to_import(self):
|
||||||
|
loader = unittest.TestLoader()
|
||||||
|
|
||||||
|
listdir = os.listdir
|
||||||
|
os.listdir = lambda _: ['test_this_does_not_exist.py']
|
||||||
|
isfile = os.path.isfile
|
||||||
|
os.path.isfile = lambda _: True
|
||||||
|
def restore():
|
||||||
|
os.path.isfile = isfile
|
||||||
|
os.listdir = listdir
|
||||||
|
self.addCleanup(restore)
|
||||||
|
|
||||||
|
suite = loader.discover('.')
|
||||||
|
self.assertEqual(suite.countTestCases(), 1)
|
||||||
|
test = list(list(suite)[0])[0] # extract test from suite
|
||||||
|
|
||||||
|
with self.assertRaises(ImportError):
|
||||||
|
test.test_this_does_not_exist()
|
||||||
|
|
||||||
def test_command_line_handling_parseArgs(self):
|
def test_command_line_handling_parseArgs(self):
|
||||||
# Haha - take that uninstantiable class
|
# Haha - take that uninstantiable class
|
||||||
program = object.__new__(TestProgram)
|
program = object.__new__(TestProgram)
|
||||||
|
|
|
@ -135,7 +135,7 @@ class TextWrapper:
|
||||||
"""_split(text : string) -> [string]
|
"""_split(text : string) -> [string]
|
||||||
|
|
||||||
Split the text to wrap into indivisible chunks. Chunks are
|
Split the text to wrap into indivisible chunks. Chunks are
|
||||||
not quite the same as words; see wrap_chunks() for full
|
not quite the same as words; see _wrap_chunks() for full
|
||||||
details. As an example, the text
|
details. As an example, the text
|
||||||
Look, goof-ball -- use the -b option!
|
Look, goof-ball -- use the -b option!
|
||||||
breaks into the following chunks:
|
breaks into the following chunks:
|
||||||
|
@ -163,9 +163,9 @@ class TextWrapper:
|
||||||
space to two.
|
space to two.
|
||||||
"""
|
"""
|
||||||
i = 0
|
i = 0
|
||||||
pat = self.sentence_end_re
|
patsearch = self.sentence_end_re.search
|
||||||
while i < len(chunks)-1:
|
while i < len(chunks)-1:
|
||||||
if chunks[i+1] == " " and pat.search(chunks[i]):
|
if chunks[i+1] == " " and patsearch(chunks[i]):
|
||||||
chunks[i+1] = " "
|
chunks[i+1] = " "
|
||||||
i += 2
|
i += 2
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -468,7 +468,13 @@ class TestCase(object):
|
||||||
|
|
||||||
Note that decimal places (from zero) are usually not the same
|
Note that decimal places (from zero) are usually not the same
|
||||||
as significant digits (measured from the most signficant digit).
|
as significant digits (measured from the most signficant digit).
|
||||||
|
|
||||||
|
If the two objects compare equal then they will automatically
|
||||||
|
compare almost equal.
|
||||||
"""
|
"""
|
||||||
|
if first == second:
|
||||||
|
# shortcut for ite
|
||||||
|
return
|
||||||
if round(abs(second-first), places) != 0:
|
if round(abs(second-first), places) != 0:
|
||||||
standardMsg = '%r != %r within %r places' % (first, second, places)
|
standardMsg = '%r != %r within %r places' % (first, second, places)
|
||||||
msg = self._formatMessage(msg, standardMsg)
|
msg = self._formatMessage(msg, standardMsg)
|
||||||
|
@ -481,8 +487,10 @@ class TestCase(object):
|
||||||
|
|
||||||
Note that decimal places (from zero) are usually not the same
|
Note that decimal places (from zero) are usually not the same
|
||||||
as significant digits (measured from the most signficant digit).
|
as significant digits (measured from the most signficant digit).
|
||||||
|
|
||||||
|
Objects that are equal automatically fail.
|
||||||
"""
|
"""
|
||||||
if round(abs(second-first), places) == 0:
|
if (first == second) or round(abs(second-first), places) == 0:
|
||||||
standardMsg = '%r == %r within %r places' % (first, second, places)
|
standardMsg = '%r == %r within %r places' % (first, second, places)
|
||||||
msg = self._formatMessage(msg, standardMsg)
|
msg = self._formatMessage(msg, standardMsg)
|
||||||
raise self.failureException(msg)
|
raise self.failureException(msg)
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
"""Loading unittests."""
|
"""Loading unittests."""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
import re
|
||||||
import sys
|
import sys
|
||||||
|
import traceback
|
||||||
import types
|
import types
|
||||||
|
|
||||||
from fnmatch import fnmatch
|
from fnmatch import fnmatch
|
||||||
|
@ -9,6 +11,26 @@ from fnmatch import fnmatch
|
||||||
from . import case, suite, util
|
from . import case, suite, util
|
||||||
|
|
||||||
|
|
||||||
|
# what about .pyc or .pyo (etc)
|
||||||
|
# we would need to avoid loading the same tests multiple times
|
||||||
|
# from '.py', '.pyc' *and* '.pyo'
|
||||||
|
VALID_MODULE_NAME = re.compile(r'[_a-z]\w*\.py$', re.IGNORECASE)
|
||||||
|
|
||||||
|
|
||||||
|
def _make_failed_import_test(name, suiteClass):
|
||||||
|
message = 'Failed to import test module: %s' % name
|
||||||
|
if hasattr(traceback, 'format_exc'):
|
||||||
|
# Python 2.3 compatibility
|
||||||
|
# format_exc returns two frames of discover.py as well
|
||||||
|
message += '\n%s' % traceback.format_exc()
|
||||||
|
|
||||||
|
def testImportFailure(self):
|
||||||
|
raise ImportError(message)
|
||||||
|
attrs = {name: testImportFailure}
|
||||||
|
ModuleImportFailure = type('ModuleImportFailure', (case.TestCase,), attrs)
|
||||||
|
return suiteClass((ModuleImportFailure(name),))
|
||||||
|
|
||||||
|
|
||||||
class TestLoader(object):
|
class TestLoader(object):
|
||||||
"""
|
"""
|
||||||
This class is responsible for loading tests according to various criteria
|
This class is responsible for loading tests according to various criteria
|
||||||
|
@ -79,7 +101,7 @@ class TestLoader(object):
|
||||||
inst = parent(name)
|
inst = parent(name)
|
||||||
# static methods follow a different path
|
# static methods follow a different path
|
||||||
if not isinstance(getattr(inst, name), types.FunctionType):
|
if not isinstance(getattr(inst, name), types.FunctionType):
|
||||||
return suite.TestSuite([inst])
|
return self.suiteClass([inst])
|
||||||
elif isinstance(obj, suite.TestSuite):
|
elif isinstance(obj, suite.TestSuite):
|
||||||
return obj
|
return obj
|
||||||
if hasattr(obj, '__call__'):
|
if hasattr(obj, '__call__'):
|
||||||
|
@ -87,7 +109,7 @@ class TestLoader(object):
|
||||||
if isinstance(test, suite.TestSuite):
|
if isinstance(test, suite.TestSuite):
|
||||||
return test
|
return test
|
||||||
elif isinstance(test, case.TestCase):
|
elif isinstance(test, case.TestCase):
|
||||||
return suite.TestSuite([test])
|
return self.suiteClass([test])
|
||||||
else:
|
else:
|
||||||
raise TypeError("calling %s returned %s, not a test" %
|
raise TypeError("calling %s returned %s, not a test" %
|
||||||
(obj, test))
|
(obj, test))
|
||||||
|
@ -156,17 +178,17 @@ class TestLoader(object):
|
||||||
tests = list(self._find_tests(start_dir, pattern))
|
tests = list(self._find_tests(start_dir, pattern))
|
||||||
return self.suiteClass(tests)
|
return self.suiteClass(tests)
|
||||||
|
|
||||||
|
def _get_name_from_path(self, path):
|
||||||
def _get_module_from_path(self, path):
|
|
||||||
"""Load a module from a path relative to the top-level directory
|
|
||||||
of a project. Used by discovery."""
|
|
||||||
path = os.path.splitext(os.path.normpath(path))[0]
|
path = os.path.splitext(os.path.normpath(path))[0]
|
||||||
|
|
||||||
relpath = os.path.relpath(path, self._top_level_dir)
|
_relpath = os.path.relpath(path, self._top_level_dir)
|
||||||
assert not os.path.isabs(relpath), "Path must be within the project"
|
assert not os.path.isabs(_relpath), "Path must be within the project"
|
||||||
assert not relpath.startswith('..'), "Path must be within the project"
|
assert not _relpath.startswith('..'), "Path must be within the project"
|
||||||
|
|
||||||
name = relpath.replace(os.path.sep, '.')
|
name = _relpath.replace(os.path.sep, '.')
|
||||||
|
return name
|
||||||
|
|
||||||
|
def _get_module_from_name(self, name):
|
||||||
__import__(name)
|
__import__(name)
|
||||||
return sys.modules[name]
|
return sys.modules[name]
|
||||||
|
|
||||||
|
@ -176,14 +198,20 @@ class TestLoader(object):
|
||||||
|
|
||||||
for path in paths:
|
for path in paths:
|
||||||
full_path = os.path.join(start_dir, path)
|
full_path = os.path.join(start_dir, path)
|
||||||
# what about __init__.pyc or pyo (etc)
|
if os.path.isfile(full_path):
|
||||||
# we would need to avoid loading the same tests multiple times
|
if not VALID_MODULE_NAME.match(path):
|
||||||
# from '.py', '.pyc' *and* '.pyo'
|
# valid Python identifiers only
|
||||||
if os.path.isfile(full_path) and path.lower().endswith('.py'):
|
continue
|
||||||
|
|
||||||
if fnmatch(path, pattern):
|
if fnmatch(path, pattern):
|
||||||
# if the test file matches, load it
|
# if the test file matches, load it
|
||||||
module = self._get_module_from_path(full_path)
|
name = self._get_name_from_path(full_path)
|
||||||
yield self.loadTestsFromModule(module)
|
try:
|
||||||
|
module = self._get_module_from_name(name)
|
||||||
|
except:
|
||||||
|
yield _make_failed_import_test(name, self.suiteClass)
|
||||||
|
else:
|
||||||
|
yield self.loadTestsFromModule(module)
|
||||||
elif os.path.isdir(full_path):
|
elif os.path.isdir(full_path):
|
||||||
if not os.path.isfile(os.path.join(full_path, '__init__.py')):
|
if not os.path.isfile(os.path.join(full_path, '__init__.py')):
|
||||||
continue
|
continue
|
||||||
|
@ -192,7 +220,8 @@ class TestLoader(object):
|
||||||
tests = None
|
tests = None
|
||||||
if fnmatch(path, pattern):
|
if fnmatch(path, pattern):
|
||||||
# only check load_tests if the package directory itself matches the filter
|
# only check load_tests if the package directory itself matches the filter
|
||||||
package = self._get_module_from_path(full_path)
|
name = self._get_name_from_path(full_path)
|
||||||
|
package = self._get_module_from_name(name)
|
||||||
load_tests = getattr(package, 'load_tests', None)
|
load_tests = getattr(package, 'load_tests', None)
|
||||||
tests = self.loadTestsFromModule(package, use_load_tests=False)
|
tests = self.loadTestsFromModule(package, use_load_tests=False)
|
||||||
|
|
||||||
|
|
|
@ -109,9 +109,9 @@ class TestProgram(object):
|
||||||
if opt in ('-v','--verbose'):
|
if opt in ('-v','--verbose'):
|
||||||
self.verbosity = 2
|
self.verbosity = 2
|
||||||
if len(args) == 0 and self.defaultTest is None:
|
if len(args) == 0 and self.defaultTest is None:
|
||||||
self.test = self.testLoader.loadTestsFromModule(self.module)
|
# createTests will load tests from self.module
|
||||||
return
|
self.testNames = None
|
||||||
if len(args) > 0:
|
elif len(args) > 0:
|
||||||
self.testNames = args
|
self.testNames = args
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
# to support python -m unittest ...
|
# to support python -m unittest ...
|
||||||
|
@ -123,8 +123,11 @@ class TestProgram(object):
|
||||||
self.usageExit(msg)
|
self.usageExit(msg)
|
||||||
|
|
||||||
def createTests(self):
|
def createTests(self):
|
||||||
self.test = self.testLoader.loadTestsFromNames(self.testNames,
|
if self.testNames is None:
|
||||||
self.module)
|
self.test = self.testLoader.loadTestsFromModule(self.module)
|
||||||
|
else:
|
||||||
|
self.test = self.testLoader.loadTestsFromNames(self.testNames,
|
||||||
|
self.module)
|
||||||
|
|
||||||
def _do_discovery(self, argv, Loader=loader.TestLoader):
|
def _do_discovery(self, argv, Loader=loader.TestLoader):
|
||||||
# handle command line args for test discovery
|
# handle command line args for test discovery
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
"""TestSuite"""
|
"""TestSuite"""
|
||||||
|
|
||||||
from . import case
|
from . import case
|
||||||
|
from . import util
|
||||||
|
|
||||||
|
|
||||||
class TestSuite(object):
|
class TestSuite(object):
|
||||||
|
@ -17,7 +18,7 @@ class TestSuite(object):
|
||||||
self.addTests(tests)
|
self.addTests(tests)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<%s tests=%s>" % (_strclass(self.__class__), list(self))
|
return "<%s tests=%s>" % (util.strclass(self.__class__), list(self))
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
if not isinstance(other, self.__class__):
|
if not isinstance(other, self.__class__):
|
||||||
|
|
|
@ -20,6 +20,9 @@ for details. When the agreement is signed, please note it in this log.
|
||||||
Permissions History
|
Permissions History
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
|
- Doug Hellmann was given SVN access on September 19 2009 by GFB, at
|
||||||
|
suggestion of Jesse Noller, for documentation work.
|
||||||
|
|
||||||
- Ezio Melotti was given SVN access on June 7 2009 by GFB, for work on and
|
- Ezio Melotti was given SVN access on June 7 2009 by GFB, for work on and
|
||||||
fixes to the documentation.
|
fixes to the documentation.
|
||||||
|
|
||||||
|
@ -109,6 +112,13 @@ Permissions History
|
||||||
- Jeffrey Yasskin was given SVN access on 9 August 2007 by NCN,
|
- Jeffrey Yasskin was given SVN access on 9 August 2007 by NCN,
|
||||||
for his work on PEPs and other general patches.
|
for his work on PEPs and other general patches.
|
||||||
|
|
||||||
|
- Mark Summerfield was given SVN access on 1 August 2007 by GFB,
|
||||||
|
for work on documentation.
|
||||||
|
|
||||||
|
- Armin Ronacher was given SVN access on 23 July 2007 by GFB,
|
||||||
|
for work on the documentation toolset. He now maintains the
|
||||||
|
ast module.
|
||||||
|
|
||||||
- Senthil Kumaran was given SVN access on 16 June 2007 by MvL,
|
- Senthil Kumaran was given SVN access on 16 June 2007 by MvL,
|
||||||
for his Summer-of-Code project, mentored by Skip Montanaro.
|
for his Summer-of-Code project, mentored by Skip Montanaro.
|
||||||
|
|
||||||
|
|
|
@ -3909,8 +3909,13 @@ socket_getnameinfo(PyObject *self, PyObject *args)
|
||||||
flags = flowinfo = scope_id = 0;
|
flags = flowinfo = scope_id = 0;
|
||||||
if (!PyArg_ParseTuple(args, "Oi:getnameinfo", &sa, &flags))
|
if (!PyArg_ParseTuple(args, "Oi:getnameinfo", &sa, &flags))
|
||||||
return NULL;
|
return NULL;
|
||||||
if (!PyArg_ParseTuple(sa, "si|ii",
|
if (!PyTuple_Check(sa)) {
|
||||||
&hostp, &port, &flowinfo, &scope_id))
|
PyErr_SetString(PyExc_TypeError,
|
||||||
|
"getnameinfo() argument 1 must be a tuple");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (!PyArg_ParseTuple(sa, "si|ii",
|
||||||
|
&hostp, &port, &flowinfo, &scope_id))
|
||||||
return NULL;
|
return NULL;
|
||||||
PyOS_snprintf(pbuf, sizeof(pbuf), "%d", port);
|
PyOS_snprintf(pbuf, sizeof(pbuf), "%d", port);
|
||||||
memset(&hints, 0, sizeof(hints));
|
memset(&hints, 0, sizeof(hints));
|
||||||
|
@ -3933,9 +3938,7 @@ socket_getnameinfo(PyObject *self, PyObject *args)
|
||||||
switch (res->ai_family) {
|
switch (res->ai_family) {
|
||||||
case AF_INET:
|
case AF_INET:
|
||||||
{
|
{
|
||||||
char *t1;
|
if (PyTuple_GET_SIZE(sa) != 2) {
|
||||||
int t2;
|
|
||||||
if (PyArg_ParseTuple(sa, "si", &t1, &t2) == 0) {
|
|
||||||
PyErr_SetString(socket_error,
|
PyErr_SetString(socket_error,
|
||||||
"IPv4 sockaddr must be 2 tuple");
|
"IPv4 sockaddr must be 2 tuple");
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue