Merged revisions 57221-57391 via svnmerge from

svn+ssh://pythondev@svn.python.org/python/trunk

........
  r57227 | facundo.batista | 2007-08-20 17:16:21 -0700 (Mon, 20 Aug 2007) | 5 lines


  Catch ProtocolError exceptions and include the header information in
  test output (to make it easier to debug test failures caused by
  problems in the server). [GSoC - Alan McIntyre]
........
  r57229 | mark.hammond | 2007-08-20 18:04:47 -0700 (Mon, 20 Aug 2007) | 5 lines

  [ 1761786 ] distutils.util.get_platform() return value on 64bit Windows
  As discussed on distutils-sig: Allows the generated installer name on
  64bit Windows platforms to be different than the name generated for
  32bit Windows platforms.
........
  r57230 | mark.hammond | 2007-08-20 18:05:16 -0700 (Mon, 20 Aug 2007) | 5 lines

  [ 1761786 ] distutils.util.get_platform() return value on 64bit Windows
  As discussed on distutils-sig: Allows the generated installer name on
  64bit Windows platforms to be different than the name generated for
  32bit Windows platforms.
........
  r57253 | georg.brandl | 2007-08-20 23:01:18 -0700 (Mon, 20 Aug 2007) | 2 lines

  Demand version 2.5.1 since 2.5 has a bug with codecs.open context managers.
........
  r57254 | georg.brandl | 2007-08-20 23:03:43 -0700 (Mon, 20 Aug 2007) | 2 lines

  Revert accidental checkins from last commit.
........
  r57255 | georg.brandl | 2007-08-20 23:07:08 -0700 (Mon, 20 Aug 2007) | 2 lines

  Bug #1777160: mention explicitly that e.g. -1**2 is -1.
........
  r57256 | georg.brandl | 2007-08-20 23:12:19 -0700 (Mon, 20 Aug 2007) | 3 lines

  Bug #1777168: replace operator names "opa"... with "op1"... and mark everything up as literal,
  to enhance readability.
........
  r57259 | facundo.batista | 2007-08-21 09:57:18 -0700 (Tue, 21 Aug 2007) | 8 lines


  Added test for behavior of operations on an unconnected SMTP object,
  and tests for NOOP, RSET, and VRFY. Corrected typo in a comment for
  testNonnumericPort. Added a check for constructing SMTP objects when
  non-numeric ports are included in the host name. Derived a server from
  SMTPServer to test various ESMTP/SMTP capabilities. Check that a
  second HELO to DebuggingServer returns an error. [GSoC - Alan McIntyre]
........
  r57279 | skip.montanaro | 2007-08-22 12:02:16 -0700 (Wed, 22 Aug 2007) | 2 lines

  Note that BeOS is unsupported as of Python 2.6.
........
  r57280 | skip.montanaro | 2007-08-22 12:05:21 -0700 (Wed, 22 Aug 2007) | 1 line

  whoops - need to check in configure as well
........
  r57284 | alex.martelli | 2007-08-22 14:14:17 -0700 (Wed, 22 Aug 2007) | 5 lines

  Fix compile.c so that it records 0.0 and -0.0 as separate constants in a code
  object's co_consts tuple; add a test to show that the previous behavior (where
  these two constants were "collapsed" into one) causes serious malfunctioning.
........
  r57286 | gregory.p.smith | 2007-08-22 14:32:34 -0700 (Wed, 22 Aug 2007) | 3 lines

  stop leaving log.0000001 __db.00* and xxx.db turds in developer
  sandboxes when bsddb3 tests are run.
........
  r57301 | jeffrey.yasskin | 2007-08-22 16:14:27 -0700 (Wed, 22 Aug 2007) | 3 lines

  When setup.py fails to find the necessary bits to build some modules, have it
  print a slightly more informative message.
........
  r57320 | brett.cannon | 2007-08-23 07:53:17 -0700 (Thu, 23 Aug 2007) | 2 lines

  Make test_runpy re-entrant.
........
  r57324 | georg.brandl | 2007-08-23 10:54:11 -0700 (Thu, 23 Aug 2007) | 2 lines

  Bug #1768121: fix wrong/missing opcode docs.
........
  r57326 | georg.brandl | 2007-08-23 10:57:05 -0700 (Thu, 23 Aug 2007) | 2 lines

  Bug #1766421: "return code" vs. "status code".
........
  r57328 | georg.brandl | 2007-08-23 11:08:06 -0700 (Thu, 23 Aug 2007) | 2 lines

  Second half of #1752175: #ifdef out references to PyImport_DynLoadFiletab if HAVE_DYNAMIC_LOADING is not defined.
........
  r57331 | georg.brandl | 2007-08-23 11:11:33 -0700 (Thu, 23 Aug 2007) | 2 lines

  Use try-except-finally in contextlib.
........
  r57343 | georg.brandl | 2007-08-23 13:35:00 -0700 (Thu, 23 Aug 2007) | 2 lines

  Bug #1697820: document that the old slice protocol is still used by builtin types.
........
  r57345 | georg.brandl | 2007-08-23 13:40:01 -0700 (Thu, 23 Aug 2007) | 2 lines

  Bug #1573854: fix docs for sqlite3 cursor rowcount attr.
........
  r57347 | georg.brandl | 2007-08-23 13:50:23 -0700 (Thu, 23 Aug 2007) | 2 lines

  Bug #1694833: fix imp.find_module() docs wrt. packages.
........
  r57348 | georg.brandl | 2007-08-23 13:53:28 -0700 (Thu, 23 Aug 2007) | 2 lines

  Bug #1594966: fix misleading usage example
........
  r57349 | georg.brandl | 2007-08-23 13:55:44 -0700 (Thu, 23 Aug 2007) | 2 lines

  Clarify wording a bit.
........
  r57351 | georg.brandl | 2007-08-23 14:18:44 -0700 (Thu, 23 Aug 2007) | 2 lines

  Bug #1752332: httplib no longer uses socket.getaddrinfo().
........
  r57352 | georg.brandl | 2007-08-23 14:21:36 -0700 (Thu, 23 Aug 2007) | 2 lines

  Bug #1734111: document struct.Struct.size.
........
  r57353 | georg.brandl | 2007-08-23 14:27:57 -0700 (Thu, 23 Aug 2007) | 2 lines

  Bug #1688564: document os.path.join's absolute path behavior in the docstring.
........
  r57354 | georg.brandl | 2007-08-23 14:36:05 -0700 (Thu, 23 Aug 2007) | 2 lines

  Bug #1625381: clarify match vs search introduction.
........
  r57355 | georg.brandl | 2007-08-23 14:42:54 -0700 (Thu, 23 Aug 2007) | 2 lines

  Bug #1758696: more info about descriptors.
........
  r57357 | georg.brandl | 2007-08-23 14:55:57 -0700 (Thu, 23 Aug 2007) | 2 lines

  Patch #1779550: remove redundant code in logging.
........
  r57378 | gregory.p.smith | 2007-08-23 22:11:38 -0700 (Thu, 23 Aug 2007) | 2 lines

  Fix bug 1725856.
........
  r57382 | georg.brandl | 2007-08-23 23:10:01 -0700 (Thu, 23 Aug 2007) | 2 lines

  uuid creation is now threadsafe, backport from py3k rev. 57375.
........
  r57389 | georg.brandl | 2007-08-24 04:47:37 -0700 (Fri, 24 Aug 2007) | 2 lines

  Bug #1765375: fix stripping of unwanted LDFLAGS.
........
  r57391 | guido.van.rossum | 2007-08-24 07:53:14 -0700 (Fri, 24 Aug 2007) | 2 lines

  Fix silly typo in test name.
........
This commit is contained in:
Guido van Rossum 2007-08-24 16:32:05 +00:00
parent 07aec08a01
commit 04110fb859
25 changed files with 443 additions and 153 deletions

View File

@ -474,10 +474,29 @@ Miscellaneous opcodes.
Creates a new class object. TOS is the methods dictionary, TOS1 the tuple of Creates a new class object. TOS is the methods dictionary, TOS1 the tuple of
the names of the base classes, and TOS2 the class name. the names of the base classes, and TOS2 the class name.
.. opcode:: WITH_CLEANUP ()
Cleans up the stack when a :keyword:`with` statement block exits. TOS is the
context manager's :meth:`__exit__` bound method. Below that are 1--3 values
indicating how/why the finally clause was entered:
* SECOND = None
* (SECOND, THIRD) = (WHY_{RETURN,CONTINUE}), retval
* SECOND = WHY_\*; no retval below it
* (SECOND, THIRD, FOURTH) = exc_info()
In the last case, ``TOS(SECOND, THIRD, FOURTH)`` is called, otherwise
``TOS(None, None, None)``.
In addition, if the stack represents an exception, *and* the function call
returns a 'true' value, this information is "zapped", to prevent ``END_FINALLY``
from re-raising the exception. (But non-local gotos should still be resumed.)
All of the following opcodes expect arguments. An argument is two bytes, with All of the following opcodes expect arguments. An argument is two bytes, with
the more significant byte last. the more significant byte last.
.. opcode:: STORE_NAME (namei) .. opcode:: STORE_NAME (namei)
Implements ``name = TOS``. *namei* is the index of *name* in the attribute Implements ``name = TOS``. *namei* is the index of *name* in the attribute
@ -722,11 +741,10 @@ the more significant byte last.
.. opcode:: MAKE_CLOSURE (argc) .. opcode:: MAKE_CLOSURE (argc)
Creates a new function object, sets its *__closure__* slot, and pushes it on the Creates a new function object, sets its *__closure__* slot, and pushes it on
stack. TOS is the code associated with the function. If the code object has N the stack. TOS is the code associated with the function, TOS1 the tuple
free variables, the next N items on the stack are the cells for these variables. containing cells for the closure's free variables. The function also has
The function also has *argc* default parameters, where are found before the *argc* default parameters, which are found below the cells.
cells.
.. opcode:: BUILD_SLICE (argc) .. opcode:: BUILD_SLICE (argc)

View File

@ -69,11 +69,6 @@ Here's a complete but small example module::
OverflowError: n too large OverflowError: n too large
""" """
.. % allow LaTeX to break here.
::
import math import math
if not n >= 0: if not n >= 0:
raise ValueError("n must be >= 0") raise ValueError("n must be >= 0")
@ -88,12 +83,10 @@ Here's a complete but small example module::
factor += 1 factor += 1
return result return result
def _test():
import doctest
doctest.testmod()
if __name__ == "__main__": if __name__ == "__main__":
_test() import doctest
doctest.testmod()
If you run :file:`example.py` directly from the command line, :mod:`doctest` If you run :file:`example.py` directly from the command line, :mod:`doctest`
works its magic:: works its magic::
@ -131,12 +124,10 @@ And so on, eventually ending with::
... ...
OverflowError: n too large OverflowError: n too large
ok ok
1 items had no tests:
__main__._test
2 items passed all tests: 2 items passed all tests:
1 tests in __main__ 1 tests in __main__
8 tests in __main__.factorial 8 tests in __main__.factorial
9 tests in 3 items. 9 tests in 2 items.
9 passed and 0 failed. 9 passed and 0 failed.
Test passed. Test passed.
$ $
@ -156,13 +147,10 @@ Simple Usage: Checking Examples in Docstrings
The simplest way to start using doctest (but not necessarily the way you'll The simplest way to start using doctest (but not necessarily the way you'll
continue to do it) is to end each module :mod:`M` with:: continue to do it) is to end each module :mod:`M` with::
def _test(): if __name__ == "__main__":
import doctest import doctest
doctest.testmod() doctest.testmod()
if __name__ == "__main__":
_test()
:mod:`doctest` then examines docstrings in module :mod:`M`. :mod:`doctest` then examines docstrings in module :mod:`M`.
Running the module as a script causes the examples in the docstrings to get Running the module as a script causes the examples in the docstrings to get

View File

@ -22,63 +22,73 @@ This module provides an interface to the mechanisms used to implement the
.. function:: get_suffixes() .. function:: get_suffixes()
Return a list of triples, each describing a particular type of module. Each Return a list of 3-element tuples, each describing a particular type of
triple has the form ``(suffix, mode, type)``, where *suffix* is a string to be module. Each triple has the form ``(suffix, mode, type)``, where *suffix* is
appended to the module name to form the filename to search for, *mode* is the a string to be appended to the module name to form the filename to search
mode string to pass to the built-in :func:`open` function to open the file (this for, *mode* is the mode string to pass to the built-in :func:`open` function
can be ``'r'`` for text files or ``'rb'`` for binary files), and *type* is the to open the file (this can be ``'r'`` for text files or ``'rb'`` for binary
file type, which has one of the values :const:`PY_SOURCE`, :const:`PY_COMPILED`, files), and *type* is the file type, which has one of the values
or :const:`C_EXTENSION`, described below. :const:`PY_SOURCE`, :const:`PY_COMPILED`, or :const:`C_EXTENSION`, described
below.
.. function:: find_module(name[, path]) .. function:: find_module(name[, path])
Try to find the module *name* on the search path *path*. If *path* is a list of Try to find the module *name* on the search path *path*. If *path* is a list
directory names, each directory is searched for files with any of the suffixes of directory names, each directory is searched for files with any of the
returned by :func:`get_suffixes` above. Invalid names in the list are silently suffixes returned by :func:`get_suffixes` above. Invalid names in the list
ignored (but all list items must be strings). If *path* is omitted or ``None``, are silently ignored (but all list items must be strings). If *path* is
the list of directory names given by ``sys.path`` is searched, but first it omitted or ``None``, the list of directory names given by ``sys.path`` is
searches a few special places: it tries to find a built-in module with the given searched, but first it searches a few special places: it tries to find a
name (:const:`C_BUILTIN`), then a frozen module (:const:`PY_FROZEN`), and on built-in module with the given name (:const:`C_BUILTIN`), then a frozen
some systems some other places are looked in as well (on the Mac, it looks for a module (:const:`PY_FROZEN`), and on some systems some other places are looked
resource (:const:`PY_RESOURCE`); on Windows, it looks in the registry which may in as well (on the Mac, it looks for a resource (:const:`PY_RESOURCE`); on
point to a specific file). Windows, it looks in the registry which may point to a specific file).
If search is successful, the return value is a triple ``(file, pathname, If search is successful, the return value is a 3-element tuple ``(file,
description)`` where *file* is an open file object positioned at the beginning, pathname, description)``:
*pathname* is the pathname of the file found, and *description* is a triple as
*file* is an open file object positioned at the beginning, *pathname* is the
pathname of the file found, and *description* is a 3-element tuple as
contained in the list returned by :func:`get_suffixes` describing the kind of contained in the list returned by :func:`get_suffixes` describing the kind of
module found. If the module does not live in a file, the returned *file* is module found.
``None``, *filename* is the empty string, and the *description* tuple contains
empty strings for its suffix and mode; the module type is as indicate in
parentheses above. If the search is unsuccessful, :exc:`ImportError` is raised.
Other exceptions indicate problems with the arguments or environment.
This function does not handle hierarchical module names (names containing dots). If the module does not live in a file, the returned *file* is ``None``,
In order to find *P*.*M*, that is, submodule *M* of package *P*, use *pathname* is the empty string, and the *description* tuple contains empty
strings for its suffix and mode; the module type is indicated as given in
parentheses above. If the search is unsuccessful, :exc:`ImportError` is
raised. Other exceptions indicate problems with the arguments or
environment.
If the module is a package, *file* is ``None``, *pathname* is the package
path and the last item in the *description* tuple is :const:`PKG_DIRECTORY`.
This function does not handle hierarchical module names (names containing
dots). In order to find *P*.*M*, that is, submodule *M* of package *P*, use
:func:`find_module` and :func:`load_module` to find and load package *P*, and :func:`find_module` and :func:`load_module` to find and load package *P*, and
then use :func:`find_module` with the *path* argument set to ``P.__path__``. then use :func:`find_module` with the *path* argument set to ``P.__path__``.
When *P* itself has a dotted name, apply this recipe recursively. When *P* itself has a dotted name, apply this recipe recursively.
.. function:: load_module(name, file, filename, description) .. function:: load_module(name, file, pathname, description)
Load a module that was previously found by :func:`find_module` (or by an Load a module that was previously found by :func:`find_module` (or by an
otherwise conducted search yielding compatible results). This function does otherwise conducted search yielding compatible results). This function does
more than importing the module: if the module was already imported, it will more than importing the module: if the module was already imported, it will
reload the module! The *name* argument indicates the full module name (including reload the module! The *name* argument indicates the full
the package name, if this is a submodule of a package). The *file* argument is module name (including the package name, if this is a submodule of a
an open file, and *filename* is the corresponding file name; these can be package). The *file* argument is an open file, and *pathname* is the
``None`` and ``''``, respectively, when the module is not being loaded from a corresponding file name; these can be ``None`` and ``''``, respectively, when
file. The *description* argument is a tuple, as would be returned by the module is a package or not being loaded from a file. The *description*
:func:`get_suffixes`, describing what kind of module must be loaded. argument is a tuple, as would be returned by :func:`get_suffixes`, describing
what kind of module must be loaded.
If the load is successful, the return value is the module object; otherwise, an If the load is successful, the return value is the module object; otherwise,
exception (usually :exc:`ImportError`) is raised. an exception (usually :exc:`ImportError`) is raised.
**Important:** the caller is responsible for closing the *file* argument, if it **Important:** the caller is responsible for closing the *file* argument, if
was not ``None``, even when an exception is raised. This is best done using a it was not ``None``, even when an exception is raised. This is best done
:keyword:`try` ... :keyword:`finally` statement. using a :keyword:`try` ... :keyword:`finally` statement.
.. function:: new_module(name) .. function:: new_module(name)

View File

@ -393,12 +393,12 @@ Matching vs Searching
Python offers two different primitive operations based on regular expressions: Python offers two different primitive operations based on regular expressions:
match and search. If you are accustomed to Perl's semantics, the search **match** checks for a match only at the beginning of the string, while
operation is what you're looking for. See the :func:`search` function and **search** checks for a match anywhere in the string (this is what Perl does
corresponding method of compiled regular expression objects. by default).
Note that match may differ from search using a regular expression beginning with Note that match may differ from search even when using a regular expression
``'^'``: ``'^'`` matches only at the start of the string, or in beginning with ``'^'``: ``'^'`` matches only at the start of the string, or in
:const:`MULTILINE` mode also immediately following a newline. The "match" :const:`MULTILINE` mode also immediately following a newline. The "match"
operation succeeds only if the pattern matches at the start of the string operation succeeds only if the pattern matches at the start of the string
regardless of mode, or at the starting position given by the optional *pos* regardless of mode, or at the starting position given by the optional *pos*

View File

@ -197,7 +197,7 @@ The module :mod:`socket` exports the following constants and functions:
:func:`socket` function. *canonname* is a string representing the canonical name :func:`socket` function. *canonname* is a string representing the canonical name
of the *host*. It can be a numeric IPv4/v6 address when :const:`AI_CANONNAME` is of the *host*. It can be a numeric IPv4/v6 address when :const:`AI_CANONNAME` is
specified for a numeric *host*. *sockaddr* is a tuple describing a socket specified for a numeric *host*. *sockaddr* is a tuple describing a socket
address, as described above. See the source for the :mod:`httplib` and other address, as described above. See the source for :mod:`socket` and other
library modules for a typical usage of the function. library modules for a typical usage of the function.
.. versionadded:: 2.2 .. versionadded:: 2.2

View File

@ -440,9 +440,6 @@ A :class:`Cursor` instance has the following attributes and methods:
attribute, the database engine's own support for the determination of "rows attribute, the database engine's own support for the determination of "rows
affected"/"rows selected" is quirky. affected"/"rows selected" is quirky.
For ``SELECT`` statements, :attr:`rowcount` is always None because we cannot
determine the number of rows a query produced until all rows were fetched.
For ``DELETE`` statements, SQLite reports :attr:`rowcount` as 0 if you make a For ``DELETE`` statements, SQLite reports :attr:`rowcount` as 0 if you make a
``DELETE FROM table`` without any condition. ``DELETE FROM table`` without any condition.
@ -453,6 +450,9 @@ A :class:`Cursor` instance has the following attributes and methods:
case no executeXX() has been performed on the cursor or the rowcount of the last case no executeXX() has been performed on the cursor or the rowcount of the last
operation is not determinable by the interface". operation is not determinable by the interface".
This includes ``SELECT`` statements because we cannot determine the number of
rows a query produced until all rows were fetched.
.. _sqlite3-types: .. _sqlite3-types:

View File

@ -290,3 +290,8 @@ Compiled Struct objects support the following methods and attributes:
The format string used to construct this Struct object. The format string used to construct this Struct object.
.. attribute:: Struct.size
The calculated size of the struct (and hence of the string) corresponding
to :attr:`format`.

View File

@ -1544,11 +1544,11 @@ Super Binding
``A.__dict__['m'].__get__(obj, A)``. ``A.__dict__['m'].__get__(obj, A)``.
For instance bindings, the precedence of descriptor invocation depends on the For instance bindings, the precedence of descriptor invocation depends on the
which descriptor methods are defined. Data descriptors define both which descriptor methods are defined. Normally, data descriptors define both
:meth:`__get__` and :meth:`__set__`. Non-data descriptors have just the :meth:`__get__` and :meth:`__set__`, while non-data descriptors have just the
:meth:`__get__` method. Data descriptors always override a redefinition in an :meth:`__get__` method. Data descriptors always override a redefinition in an
instance dictionary. In contrast, non-data descriptors can be overridden by instance dictionary. In contrast, non-data descriptors can be overridden by
instances. instances. [#]_
Python methods (including :func:`staticmethod` and :func:`classmethod`) are Python methods (including :func:`staticmethod` and :func:`classmethod`) are
implemented as non-data descriptors. Accordingly, instances can redefine and implemented as non-data descriptors. Accordingly, instances can redefine and
@ -1817,6 +1817,9 @@ objects. Immutable sequences methods should at most only define
.. deprecated:: 2.0 .. deprecated:: 2.0
Support slice objects as parameters to the :meth:`__getitem__` method. Support slice objects as parameters to the :meth:`__getitem__` method.
(However, built-in types in CPython currently still implement
:meth:`__getslice__`. Therefore, you have to override it in derived
classes when implementing slicing.)
Called to implement evaluation of ``self[i:j]``. The returned object should be Called to implement evaluation of ``self[i:j]``. The returned object should be
of the same type as *self*. Note that missing *i* or *j* in the slice of the same type as *self*. Note that missing *i* or *j* in the slice
@ -2112,6 +2115,13 @@ For more information on context managers, see :ref:`typecontextmanager`.
.. [#] This, and other statements, are only roughly true for instances of new-style .. [#] This, and other statements, are only roughly true for instances of new-style
classes. classes.
.. [#] A descriptor can define any combination of :meth:`__get__`,
:meth:`__set__` and :meth:`__delete__`. If it does not define :meth:`__get__`,
then accessing the attribute even on an instance will return the descriptor
object itself. If the descriptor defines :meth:`__set__` and/or
:meth:`__delete__`, it is a data descriptor; if it defines neither, it is a
non-data descriptor.
.. [#] For operands of the same type, it is assumed that if the non-reflected method .. [#] For operands of the same type, it is assumed that if the non-reflected method
(such as :meth:`__add__`) fails the operation is not supported, which is why the (such as :meth:`__add__`) fails the operation is not supported, which is why the
reflected method is not called. reflected method is not called.

View File

@ -741,7 +741,7 @@ less tightly than unary operators on its right. The syntax is:
Thus, in an unparenthesized sequence of power and unary operators, the operators Thus, in an unparenthesized sequence of power and unary operators, the operators
are evaluated from right to left (this does not constrain the evaluation order are evaluated from right to left (this does not constrain the evaluation order
for the operands). for the operands): ``-1**2`` results in ``-1``.
The power operator has the same semantics as the built-in :func:`pow` function, The power operator has the same semantics as the built-in :func:`pow` function,
when called with two arguments: it yields its left argument raised to the power when called with two arguments: it yields its left argument raised to the power
@ -959,12 +959,12 @@ Comparisons can be chained arbitrarily, e.g., ``x < y <= z`` is equivalent to
``x < y and y <= z``, except that ``y`` is evaluated only once (but in both ``x < y and y <= z``, except that ``y`` is evaluated only once (but in both
cases ``z`` is not evaluated at all when ``x < y`` is found to be false). cases ``z`` is not evaluated at all when ``x < y`` is found to be false).
Formally, if *a*, *b*, *c*, ..., *y*, *z* are expressions and *opa*, *opb*, ..., Formally, if *a*, *b*, *c*, ..., *y*, *z* are expressions and *op1*, *op2*, ...,
*opy* are comparison operators, then *a opa b opb c* ...*y opy z* is equivalent *opN* are comparison operators, then ``a op1 b op2 c ... y opN z`` is equivalent
to *a opa b* :keyword:`and` *b opb c* :keyword:`and` ... *y opy z*, except that to ``a op1 b and b op2 c and ... y opN z``, except that each expression is
each expression is evaluated at most once. evaluated at most once.
Note that *a opa b opb c* doesn't imply any kind of comparison between *a* and Note that ``a op1 b op2 c`` doesn't imply any kind of comparison between *a* and
*c*, so that, e.g., ``x < y > z`` is perfectly legal (though perhaps not *c*, so that, e.g., ``x < y > z`` is perfectly legal (though perhaps not
pretty). pretty).

View File

@ -11,9 +11,9 @@
if __name__ == '__main__': if __name__ == '__main__':
if sys.version_info[:3] < (2, 5, 0): if sys.version_info[:3] < (2, 5, 1):
print >>sys.stderr, """\ print >>sys.stderr, """\
Error: Sphinx needs to be executed with Python 2.5 or newer Error: Sphinx needs to be executed with Python 2.5.1 or newer
(If you run this from the Makefile, you can set the PYTHON variable (If you run this from the Makefile, you can set the PYTHON variable
to the path of an alternative interpreter executable, e.g., to the path of an alternative interpreter executable, e.g.,
``make html PYTHON=python2.5``). ``make html PYTHON=python2.5``).

View File

@ -104,7 +104,6 @@ def nested(*managers):
exits = [] exits = []
vars = [] vars = []
exc = (None, None, None) exc = (None, None, None)
try:
try: try:
for mgr in managers: for mgr in managers:
exit = mgr.__exit__ exit = mgr.__exit__

View File

@ -633,7 +633,8 @@ def add_ui(self):
def get_installer_filename(self, fullname): def get_installer_filename(self, fullname):
# Factored out to allow overriding in subclasses # Factored out to allow overriding in subclasses
plat = get_platform()
installer_name = os.path.join(self.dist_dir, installer_name = os.path.join(self.dist_dir,
"%s.win32-py%s.msi" % "%s.%s-py%s.msi" %
(fullname, self.target_version)) (fullname, plat, self.target_version))
return installer_name return installer_name

View File

@ -29,8 +29,27 @@ def get_platform ():
irix-5.3 irix-5.3
irix64-6.2 irix64-6.2
For non-POSIX platforms, currently just returns 'sys.platform'. Windows will return one of:
win-x86_64 (64bit Windows on x86_64 (AMD64))
win-ia64 (64bit Windows on Itanium)
win32 (all others - specifically, sys.platform is returned)
For other non-POSIX platforms, currently just returns 'sys.platform'.
""" """
if os.name == 'nt':
# sniff sys.version for architecture.
prefix = " bit ("
i = string.find(sys.version, prefix)
if i == -1:
return sys.platform
j = string.find(sys.version, ")", i)
look = sys.version[i+len(prefix):j].lower()
if look=='amd64':
return 'win-x86_64'
if look=='itanium':
return 'win-ia64'
return sys.platform
if os.name != "posix" or not hasattr(os, 'uname'): if os.name != "posix" or not hasattr(os, 'uname'):
# XXX what about the architecture? NT is Intel or Alpha, # XXX what about the architecture? NT is Intel or Alpha,
# Mac OS is M68k or PPC, etc. # Mac OS is M68k or PPC, etc.

View File

@ -975,9 +975,7 @@ def debug(self, msg, *args, **kwargs):
logger.debug("Houston, we have a %s", "thorny problem", exc_info=1) logger.debug("Houston, we have a %s", "thorny problem", exc_info=1)
""" """
if self.manager.disable >= DEBUG: if self.isEnabledFor(DEBUG):
return
if DEBUG >= self.getEffectiveLevel():
self._log(DEBUG, msg, args, **kwargs) self._log(DEBUG, msg, args, **kwargs)
def info(self, msg, *args, **kwargs): def info(self, msg, *args, **kwargs):
@ -989,9 +987,7 @@ def info(self, msg, *args, **kwargs):
logger.info("Houston, we have a %s", "interesting problem", exc_info=1) logger.info("Houston, we have a %s", "interesting problem", exc_info=1)
""" """
if self.manager.disable >= INFO: if self.isEnabledFor(INFO):
return
if INFO >= self.getEffectiveLevel():
self._log(INFO, msg, args, **kwargs) self._log(INFO, msg, args, **kwargs)
def warning(self, msg, *args, **kwargs): def warning(self, msg, *args, **kwargs):
@ -1003,8 +999,6 @@ def warning(self, msg, *args, **kwargs):
logger.warning("Houston, we have a %s", "bit of a problem", exc_info=1) logger.warning("Houston, we have a %s", "bit of a problem", exc_info=1)
""" """
if self.manager.disable >= WARNING:
return
if self.isEnabledFor(WARNING): if self.isEnabledFor(WARNING):
self._log(WARNING, msg, args, **kwargs) self._log(WARNING, msg, args, **kwargs)
@ -1019,8 +1013,6 @@ def error(self, msg, *args, **kwargs):
logger.error("Houston, we have a %s", "major problem", exc_info=1) logger.error("Houston, we have a %s", "major problem", exc_info=1)
""" """
if self.manager.disable >= ERROR:
return
if self.isEnabledFor(ERROR): if self.isEnabledFor(ERROR):
self._log(ERROR, msg, args, **kwargs) self._log(ERROR, msg, args, **kwargs)
@ -1039,9 +1031,7 @@ def critical(self, msg, *args, **kwargs):
logger.critical("Houston, we have a %s", "major disaster", exc_info=1) logger.critical("Houston, we have a %s", "major disaster", exc_info=1)
""" """
if self.manager.disable >= CRITICAL: if self.isEnabledFor(CRITICAL):
return
if CRITICAL >= self.getEffectiveLevel():
self._log(CRITICAL, msg, args, **kwargs) self._log(CRITICAL, msg, args, **kwargs)
fatal = critical fatal = critical
@ -1060,8 +1050,6 @@ def log(self, level, msg, *args, **kwargs):
raise TypeError, "level must be an integer" raise TypeError, "level must be an integer"
else: else:
return return
if self.manager.disable >= level:
return
if self.isEnabledFor(level): if self.isEnabledFor(level):
self._log(level, msg, args, **kwargs) self._log(level, msg, args, **kwargs)

View File

@ -59,7 +59,9 @@ def isabs(s):
# Join two (or more) paths. # Join two (or more) paths.
def join(a, *p): def join(a, *p):
"""Join two or more pathname components, inserting "\\" as needed""" """Join two or more pathname components, inserting "\\" as needed.
If any component is an absolute path, all previous path components
will be discarded."""
path = a path = a
for b in p: for b in p:
b_wins = 0 # set to 1 iff b makes path irrelevant b_wins = 0 # set to 1 iff b makes path irrelevant

View File

@ -56,7 +56,9 @@ def isabs(s):
# Insert a '/' unless the first part is empty or already ends in '/'. # Insert a '/' unless the first part is empty or already ends in '/'.
def join(a, *p): def join(a, *p):
"""Join two or more pathname components, inserting '/' as needed""" """Join two or more pathname components, inserting '/' as needed.
If any component is an absolute path, all previous path components
will be discarded."""
path = a path = a
for b in p: for b in p:
if b.startswith('/'): if b.startswith('/'):

View File

@ -401,7 +401,8 @@ def ehlo(self, name=''):
return (code,msg) return (code,msg)
self.does_esmtp=1 self.does_esmtp=1
#parse the ehlo response -ddm #parse the ehlo response -ddm
resp=self.ehlo_resp.split('\n') assert isinstance(self.ehlo_resp, bytes), repr(self.ehlo_resp)
resp=self.ehlo_resp.decode("latin-1").split('\n')
del resp[0] del resp[0]
for each in resp: for each in resp:
# To be able to communicate with as many SMTP servers as possible, # To be able to communicate with as many SMTP servers as possible,

View File

@ -1003,7 +1003,7 @@ def test_bool(self):
self.failUnless(self.theclass.min) self.failUnless(self.theclass.min)
self.failUnless(self.theclass.max) self.failUnless(self.theclass.max)
def test_srftime_out_of_range(self): def test_strftime_out_of_range(self):
# For nasty technical reasons, we can't handle years before 1900. # For nasty technical reasons, we can't handle years before 1900.
cls = self.theclass cls = self.theclass
self.assertEqual(cls(1900, 1, 1).strftime("%Y"), "1900") self.assertEqual(cls(1900, 1, 1).strftime("%Y"), "1900")

View File

@ -81,6 +81,7 @@ def test_float_specials_dont_unpack(self):
# on an IEEE platform, all we guarantee is that bit patterns # on an IEEE platform, all we guarantee is that bit patterns
# representing infinities or NaNs do not raise an exception; all else # representing infinities or NaNs do not raise an exception; all else
# is accident (today). # is accident (today).
# let's also try to guarantee that -0.0 and 0.0 don't get confused.
class IEEEFormatTestCase(unittest.TestCase): class IEEEFormatTestCase(unittest.TestCase):
if float.__getformat__("double").startswith("IEEE"): if float.__getformat__("double").startswith("IEEE"):
@ -99,6 +100,20 @@ def test_float_specials_do_unpack(self):
('<f', LE_FLOAT_NAN)]: ('<f', LE_FLOAT_NAN)]:
struct.unpack(fmt, data) struct.unpack(fmt, data)
if float.__getformat__("double").startswith("IEEE"):
def test_negative_zero(self):
import math
def pos_pos():
return 0.0, math.atan2(0.0, -1)
def pos_neg():
return 0.0, math.atan2(-0.0, -1)
def neg_pos():
return -0.0, math.atan2(0.0, -1)
def neg_neg():
return -0.0, math.atan2(-0.0, -1)
self.assertEquals(pos_pos(), neg_pos())
self.assertEquals(pos_neg(), neg_neg())
def test_main(): def test_main():
test_support.run_unittest( test_support.run_unittest(

View File

@ -4,7 +4,7 @@
import os.path import os.path
import sys import sys
import tempfile import tempfile
from test.test_support import verbose, run_unittest from test.test_support import verbose, run_unittest, forget
from runpy import _run_module_code, run_module from runpy import _run_module_code, run_module
# Set up the test code and expected results # Set up the test code and expected results
@ -156,6 +156,7 @@ def _del_pkg(self, top, depth, mod_name):
def _check_module(self, depth): def _check_module(self, depth):
pkg_dir, mod_fname, mod_name = ( pkg_dir, mod_fname, mod_name = (
self._make_pkg("x=1\n", depth)) self._make_pkg("x=1\n", depth))
forget(mod_name)
try: try:
if verbose: print("Running from source:", mod_name) if verbose: print("Running from source:", mod_name)
d1 = run_module(mod_name) # Read from source d1 = run_module(mod_name) # Read from source

View File

@ -1,4 +1,5 @@
import asyncore import asyncore
import email.utils
import socket import socket
import threading import threading
import smtpd import smtpd
@ -75,6 +76,15 @@ def testBasic2(self):
smtp = smtplib.SMTP("%s:%s" % (HOST, PORT)) smtp = smtplib.SMTP("%s:%s" % (HOST, PORT))
smtp.sock.close() smtp.sock.close()
def testNotConnected(self):
# Test various operations on an unconnected SMTP object that
# should raise exceptions (at present the attempt in SMTP.send
# to reference the nonexistent 'sock' attribute of the SMTP object
# causes an AttributeError)
smtp = smtplib.SMTP()
self.assertRaises(AttributeError, smtp.ehlo)
self.assertRaises(AttributeError, smtp.send, 'test msg')
def testLocalHostName(self): def testLocalHostName(self):
# check that supplied local_hostname is used # check that supplied local_hostname is used
smtp = smtplib.SMTP(HOST, PORT, local_hostname="testhost") smtp = smtplib.SMTP(HOST, PORT, local_hostname="testhost")
@ -82,9 +92,11 @@ def testLocalHostName(self):
smtp.sock.close() smtp.sock.close()
def testNonnumericPort(self): def testNonnumericPort(self):
# check that non-numeric port raises ValueError # check that non-numeric port raises socket.error
self.assertRaises(socket.error, smtplib.SMTP, self.assertRaises(socket.error, smtplib.SMTP,
"localhost", "bogus") "localhost", "bogus")
self.assertRaises(socket.error, smtplib.SMTP,
"localhost:bogus")
def testTimeoutDefault(self): def testTimeoutDefault(self):
# default # default
@ -110,9 +122,9 @@ def testTimeoutNone(self):
smtp.sock.close() smtp.sock.close()
# Test server using smtpd.DebuggingServer # Test server thread using the specified SMTP server class
def debugging_server(serv_evt, client_evt): def debugging_server(server_class, serv_evt, client_evt):
serv = smtpd.DebuggingServer(("", 0), ('nowhere', -1)) serv = server_class(("", 0), ('nowhere', -1))
global PORT global PORT
PORT = serv.getsockname()[1] PORT = serv.getsockname()[1]
@ -148,11 +160,12 @@ def debugging_server(serv_evt, client_evt):
MSG_BEGIN = '---------- MESSAGE FOLLOWS ----------\n' MSG_BEGIN = '---------- MESSAGE FOLLOWS ----------\n'
MSG_END = '------------ END MESSAGE ------------\n' MSG_END = '------------ END MESSAGE ------------\n'
# Test behavior of smtpd.DebuggingServer # NOTE: Some SMTP objects in the tests below are created with a non-default
# NOTE: the SMTP objects are created with a non-default local_hostname # local_hostname argument to the constructor, since (on some systems) the FQDN
# argument to the constructor, since (on some systems) the FQDN lookup # lookup caused by the default local_hostname sometimes takes so long that the
# caused by the default local_hostname sometimes takes so long that the
# test server times out, causing the test to fail. # test server times out, causing the test to fail.
# Test behavior of smtpd.DebuggingServer
class DebuggingServerTests(TestCase): class DebuggingServerTests(TestCase):
def setUp(self): def setUp(self):
@ -163,7 +176,7 @@ def setUp(self):
self.serv_evt = threading.Event() self.serv_evt = threading.Event()
self.client_evt = threading.Event() self.client_evt = threading.Event()
serv_args = (self.serv_evt, self.client_evt) serv_args = (smtpd.DebuggingServer, self.serv_evt, self.client_evt)
threading.Thread(target=debugging_server, args=serv_args).start() threading.Thread(target=debugging_server, args=serv_args).start()
# wait until server thread has assigned a port number # wait until server thread has assigned a port number
@ -189,12 +202,42 @@ def testBasic(self):
smtp = smtplib.SMTP(HOST, PORT, local_hostname='localhost', timeout=3) smtp = smtplib.SMTP(HOST, PORT, local_hostname='localhost', timeout=3)
smtp.quit() smtp.quit()
def testEHLO(self): def testNOOP(self):
smtp = smtplib.SMTP(HOST, PORT, local_hostname='localhost', timeout=3)
expected = (250, b'Ok')
self.assertEqual(smtp.noop(), expected)
smtp.quit()
def testRSET(self):
smtp = smtplib.SMTP(HOST, PORT, local_hostname='localhost', timeout=3)
expected = (250, b'Ok')
self.assertEqual(smtp.rset(), expected)
smtp.quit()
def testNotImplemented(self):
# EHLO isn't implemented in DebuggingServer
smtp = smtplib.SMTP(HOST, PORT, local_hostname='localhost', timeout=3) smtp = smtplib.SMTP(HOST, PORT, local_hostname='localhost', timeout=3)
expected = (502, b'Error: command "EHLO" not implemented') expected = (502, b'Error: command "EHLO" not implemented')
self.assertEqual(smtp.ehlo(), expected) self.assertEqual(smtp.ehlo(), expected)
smtp.quit() smtp.quit()
def testVRFY(self):
# VRFY isn't implemented in DebuggingServer
smtp = smtplib.SMTP(HOST, PORT, local_hostname='localhost', timeout=3)
expected = (502, b'Error: command "VRFY" not implemented')
self.assertEqual(smtp.vrfy('nobody@nowhere.com'), expected)
self.assertEqual(smtp.verify('nobody@nowhere.com'), expected)
smtp.quit()
def testSecondHELO(self):
# check that a second HELO returns a message that it's a duplicate
# (this behavior is specific to smtpd.SMTPChannel)
smtp = smtplib.SMTP(HOST, PORT, local_hostname='localhost', timeout=3)
smtp.helo()
expected = (503, b'Duplicate HELO/EHLO')
self.assertEqual(smtp.helo(), expected)
smtp.quit()
def testHELP(self): def testHELP(self):
smtp = smtplib.SMTP(HOST, PORT, local_hostname='localhost', timeout=3) smtp = smtplib.SMTP(HOST, PORT, local_hostname='localhost', timeout=3)
self.assertEqual(smtp.help(), b'Error: command "HELP" not implemented') self.assertEqual(smtp.help(), b'Error: command "HELP" not implemented')
@ -214,6 +257,7 @@ def testSend(self):
self.assertEqual(self.output.getvalue(), mexpect) self.assertEqual(self.output.getvalue(), mexpect)
# test response of client to a non-successful HELO message
class BadHELOServerTests(TestCase): class BadHELOServerTests(TestCase):
def setUp(self): def setUp(self):
@ -243,9 +287,148 @@ def testFailingHELO(self):
self.assertRaises(smtplib.SMTPConnectError, smtplib.SMTP, self.assertRaises(smtplib.SMTPConnectError, smtplib.SMTP,
HOST, PORT, 'localhost', 3) HOST, PORT, 'localhost', 3)
sim_users = {'Mr.A@somewhere.com':'John A',
'Ms.B@somewhere.com':'Sally B',
'Mrs.C@somewhereesle.com':'Ruth C',
}
sim_lists = {'list-1':['Mr.A@somewhere.com','Mrs.C@somewhereesle.com'],
'list-2':['Ms.B@somewhere.com',],
}
# Simulated SMTP channel & server
class SimSMTPChannel(smtpd.SMTPChannel):
def smtp_EHLO(self, arg):
resp = '250-testhost\r\n' \
'250-EXPN\r\n' \
'250-SIZE 20000000\r\n' \
'250-STARTTLS\r\n' \
'250-DELIVERBY\r\n' \
'250 HELP'
self.push(resp)
def smtp_VRFY(self, arg):
# print '\nsmtp_VRFY(%r)\n' % arg
raw_addr = email.utils.parseaddr(arg)[1]
quoted_addr = smtplib.quoteaddr(arg)
if raw_addr in sim_users:
self.push('250 %s %s' % (sim_users[raw_addr], quoted_addr))
else:
self.push('550 No such user: %s' % arg)
def smtp_EXPN(self, arg):
# print '\nsmtp_EXPN(%r)\n' % arg
list_name = email.utils.parseaddr(arg)[1].lower()
if list_name in sim_lists:
user_list = sim_lists[list_name]
for n, user_email in enumerate(user_list):
quoted_addr = smtplib.quoteaddr(user_email)
if n < len(user_list) - 1:
self.push('250-%s %s' % (sim_users[user_email], quoted_addr))
else:
self.push('250 %s %s' % (sim_users[user_email], quoted_addr))
else:
self.push('550 No access for you!')
class SimSMTPServer(smtpd.SMTPServer):
def handle_accept(self):
conn, addr = self.accept()
channel = SimSMTPChannel(self, conn, addr)
def process_message(self, peer, mailfrom, rcpttos, data):
pass
# Test various SMTP & ESMTP commands/behaviors that require a simulated server
# (i.e., something with more features than DebuggingServer)
class SMTPSimTests(TestCase):
def setUp(self):
self.serv_evt = threading.Event()
self.client_evt = threading.Event()
serv_args = (SimSMTPServer, self.serv_evt, self.client_evt)
threading.Thread(target=debugging_server, args=serv_args).start()
# wait until server thread has assigned a port number
n = 500
while PORT is None and n > 0:
time.sleep(0.01)
n -= 1
# wait a little longer (sometimes connections are refused
# on slow machines without this additional wait)
time.sleep(0.5)
def tearDown(self):
# indicate that the client is finished
self.client_evt.set()
# wait for the server thread to terminate
self.serv_evt.wait()
def testBasic(self):
# smoke test
smtp = smtplib.SMTP(HOST, PORT, local_hostname='localhost', timeout=3)
smtp.quit()
def testEHLO(self):
smtp = smtplib.SMTP(HOST, PORT, local_hostname='localhost', timeout=3)
# no features should be present before the EHLO
self.assertEqual(smtp.esmtp_features, {})
# features expected from the test server
expected_features = {'expn':'',
'size': '20000000',
'starttls': '',
'deliverby': '',
'help': '',
}
smtp.ehlo()
self.assertEqual(smtp.esmtp_features, expected_features)
for k in expected_features:
self.assertTrue(smtp.has_extn(k))
self.assertFalse(smtp.has_extn('unsupported-feature'))
smtp.quit()
def testVRFY(self):
smtp = smtplib.SMTP(HOST, PORT, local_hostname='localhost', timeout=3)
for email, name in sim_users.items():
expected_known = (250, bytes('%s %s' %
(name, smtplib.quoteaddr(email))))
self.assertEqual(smtp.vrfy(email), expected_known)
u = 'nobody@nowhere.com'
expected_unknown = (550, bytes('No such user: %s'
% smtplib.quoteaddr(u)))
self.assertEqual(smtp.vrfy(u), expected_unknown)
smtp.quit()
def testEXPN(self):
smtp = smtplib.SMTP(HOST, PORT, local_hostname='localhost', timeout=3)
for listname, members in sim_lists.items():
users = []
for m in members:
users.append('%s %s' % (sim_users[m], smtplib.quoteaddr(m)))
expected_known = (250, bytes('\n'.join(users)))
self.assertEqual(smtp.expn(listname), expected_known)
u = 'PSU-Members-List'
expected_unknown = (550, b'No access for you!')
self.assertEqual(smtp.expn(u), expected_unknown)
smtp.quit()
def test_main(verbose=None): def test_main(verbose=None):
test_support.run_unittest(GeneralTests, DebuggingServerTests, test_support.run_unittest(GeneralTests, DebuggingServerTests,
BadHELOServerTests) BadHELOServerTests, SMTPSimTests)
if __name__ == '__main__': if __name__ == '__main__':
test_main() test_main()

View File

@ -303,29 +303,46 @@ def tearDown(self):
SimpleXMLRPCServer.SimpleXMLRPCServer._send_traceback_header = False SimpleXMLRPCServer.SimpleXMLRPCServer._send_traceback_header = False
def test_simple1(self): def test_simple1(self):
try:
p = xmlrpclib.ServerProxy('http://localhost:%d' % PORT) p = xmlrpclib.ServerProxy('http://localhost:%d' % PORT)
self.assertEqual(p.pow(6,8), 6**8) self.assertEqual(p.pow(6,8), 6**8)
except xmlrpclib.ProtocolError, e:
# protocol error; provide additional information in test output
self.fail("%s\n%s" % (e, e.headers))
def test_introspection1(self): def test_introspection1(self):
try:
p = xmlrpclib.ServerProxy('http://localhost:%d' % PORT) p = xmlrpclib.ServerProxy('http://localhost:%d' % PORT)
meth = p.system.listMethods() meth = p.system.listMethods()
expected_methods = set(['pow', 'div', 'add', 'system.listMethods', expected_methods = set(['pow', 'div', 'add', 'system.listMethods',
'system.methodHelp', 'system.methodSignature', 'system.multicall']) 'system.methodHelp', 'system.methodSignature', 'system.multicall'])
self.assertEqual(set(meth), expected_methods) self.assertEqual(set(meth), expected_methods)
except xmlrpclib.ProtocolError, e:
# protocol error; provide additional information in test output
self.fail("%s\n%s" % (e, e.headers))
def test_introspection2(self): def test_introspection2(self):
try:
p = xmlrpclib.ServerProxy('http://localhost:%d' % PORT) p = xmlrpclib.ServerProxy('http://localhost:%d' % PORT)
divhelp = p.system.methodHelp('div') divhelp = p.system.methodHelp('div')
self.assertEqual(divhelp, 'This is the div function') self.assertEqual(divhelp, 'This is the div function')
except xmlrpclib.ProtocolError, e:
# protocol error; provide additional information in test output
self.fail("%s\n%s" % (e, e.headers))
def test_introspection3(self): def test_introspection3(self):
# the SimpleXMLRPCServer doesn't support signatures, but # the SimpleXMLRPCServer doesn't support signatures, but
# at least check that we can try # at least check that we can try
try:
p = xmlrpclib.ServerProxy('http://localhost:%d' % PORT) p = xmlrpclib.ServerProxy('http://localhost:%d' % PORT)
divsig = p.system.methodSignature('div') divsig = p.system.methodSignature('div')
self.assertEqual(divsig, 'signatures not supported') self.assertEqual(divsig, 'signatures not supported')
except xmlrpclib.ProtocolError, e:
# protocol error; provide additional information in test output
self.fail("%s\n%s" % (e, e.headers))
def test_multicall(self): def test_multicall(self):
try:
p = xmlrpclib.ServerProxy('http://localhost:%d' % PORT) p = xmlrpclib.ServerProxy('http://localhost:%d' % PORT)
multicall = xmlrpclib.MultiCall(p) multicall = xmlrpclib.MultiCall(p)
multicall.add(2,3) multicall.add(2,3)
@ -335,6 +352,9 @@ def test_multicall(self):
self.assertEqual(add_result, 2+3) self.assertEqual(add_result, 2+3)
self.assertEqual(pow_result, 6**8) self.assertEqual(pow_result, 6**8)
self.assertEqual(div_result, 127//42) self.assertEqual(div_result, 127//42)
except xmlrpclib.ProtocolError, e:
# protocol error; provide additional information in test output
self.fail("%s\n%s" % (e, e.headers))
# This is a contrived way to make a failure occur on the server side # This is a contrived way to make a failure occur on the server side
@ -375,9 +395,16 @@ def test_basic(self):
flagval = SimpleXMLRPCServer.SimpleXMLRPCServer._send_traceback_header flagval = SimpleXMLRPCServer.SimpleXMLRPCServer._send_traceback_header
self.assertEqual(flagval, False) self.assertEqual(flagval, False)
# test a call that won't fail just as a smoke test # enable traceback reporting
SimpleXMLRPCServer.SimpleXMLRPCServer._send_traceback_header = True
# test a call that shouldn't fail just as a smoke test
try:
p = xmlrpclib.ServerProxy('http://localhost:%d' % PORT) p = xmlrpclib.ServerProxy('http://localhost:%d' % PORT)
self.assertEqual(p.pow(6,8), 6**8) self.assertEqual(p.pow(6,8), 6**8)
except xmlrpclib.ProtocolError, e:
# protocol error; provide additional information in test output
self.fail("%s\n%s" % (e, e.headers))
def test_fail_no_info(self): def test_fail_no_info(self):
# use the broken message class # use the broken message class

View File

@ -914,7 +914,20 @@ compiler_add_o(struct compiler *c, PyObject *dict, PyObject *o)
Py_ssize_t arg; Py_ssize_t arg;
/* necessary to make sure types aren't coerced (e.g., int and long) */ /* necessary to make sure types aren't coerced (e.g., int and long) */
/* _and_ to distinguish 0.0 from -0.0 e.g. on IEEE platforms */
if (PyFloat_Check(o)) {
double d = PyFloat_AS_DOUBLE(o);
unsigned char* p = (unsigned char*) &d;
/* all we need is to make the tuple different in either the 0.0
* or -0.0 case from all others, just to avoid the "coercion".
*/
if (*p==0 && p[sizeof(double)-1]==0)
t = PyTuple_Pack(3, o, o->ob_type, Py_None);
else
t = PyTuple_Pack(2, o, o->ob_type); t = PyTuple_Pack(2, o, o->ob_type);
} else {
t = PyTuple_Pack(2, o, o->ob_type);
}
if (t == NULL) if (t == NULL)
return -1; return -1;

View File

@ -118,15 +118,19 @@ _PyImport_Init(void)
/* prepare _PyImport_Filetab: copy entries from /* prepare _PyImport_Filetab: copy entries from
_PyImport_DynLoadFiletab and _PyImport_StandardFiletab. _PyImport_DynLoadFiletab and _PyImport_StandardFiletab.
*/ */
#ifdef HAVE_DYNAMIC_LOADING
for (scan = _PyImport_DynLoadFiletab; scan->suffix != NULL; ++scan) for (scan = _PyImport_DynLoadFiletab; scan->suffix != NULL; ++scan)
++countD; ++countD;
#endif
for (scan = _PyImport_StandardFiletab; scan->suffix != NULL; ++scan) for (scan = _PyImport_StandardFiletab; scan->suffix != NULL; ++scan)
++countS; ++countS;
filetab = PyMem_NEW(struct filedescr, countD + countS + 1); filetab = PyMem_NEW(struct filedescr, countD + countS + 1);
if (filetab == NULL) if (filetab == NULL)
Py_FatalError("Can't initialize import file table."); Py_FatalError("Can't initialize import file table.");
#ifdef HAVE_DYNAMIC_LOADING
memcpy(filetab, _PyImport_DynLoadFiletab, memcpy(filetab, _PyImport_DynLoadFiletab,
countD * sizeof(struct filedescr)); countD * sizeof(struct filedescr));
#endif
memcpy(filetab + countD, _PyImport_StandardFiletab, memcpy(filetab + countD, _PyImport_StandardFiletab,
countS * sizeof(struct filedescr)); countS * sizeof(struct filedescr));
filetab[countD + countS].suffix = NULL; filetab[countD + countS].suffix = NULL;
@ -1321,7 +1325,7 @@ find_module(char *fullname, char *subname, PyObject *path, char *buf,
saved_namelen = namelen; saved_namelen = namelen;
#endif /* PYOS_OS2 */ #endif /* PYOS_OS2 */
for (fdp = _PyImport_Filetab; fdp->suffix != NULL; fdp++) { for (fdp = _PyImport_Filetab; fdp->suffix != NULL; fdp++) {
#if defined(PYOS_OS2) #if defined(PYOS_OS2) && defined(HAVE_DYNAMIC_LOADING)
/* OS/2 limits DLLs to 8 character names (w/o /* OS/2 limits DLLs to 8 character names (w/o
extension) extension)
* so if the name is longer than that and its a * so if the name is longer than that and its a

View File

@ -194,18 +194,21 @@ def print_three_column(lst):
for e, f, g in zip(lst[::3], lst[1::3], lst[2::3]): for e, f, g in zip(lst[::3], lst[1::3], lst[2::3]):
print("%-*s %-*s %-*s" % (longest, e, longest, f, print("%-*s %-*s %-*s" % (longest, e, longest, f,
longest, g)) longest, g))
print()
if missing: if missing:
print() print()
print("Failed to find the necessary bits to build these modules:") print("Failed to find the necessary bits to build these modules:")
print_three_column(missing) print_three_column(missing)
print("To find the necessary bits, look in setup.py in"
" detect_modules() for the module's name.")
print()
if self.failed: if self.failed:
failed = self.failed[:] failed = self.failed[:]
print() print()
print("Failed to build these modules:") print("Failed to build these modules:")
print_three_column(failed) print_three_column(failed)
print()
def build_extension(self, ext): def build_extension(self, ext):
@ -299,7 +302,8 @@ def detect_modules(self):
# strip out double-dashes first so that we don't end up with # strip out double-dashes first so that we don't end up with
# substituting "--Long" to "-Long" and thus lead to "ong" being # substituting "--Long" to "-Long" and thus lead to "ong" being
# used for a library directory. # used for a library directory.
env_val = re.sub(r'(^|\s+)-(-|(?!%s))' % arg_name[1], '', env_val) env_val = re.sub(r'(^|\s+)-(-|(?!%s))' % arg_name[1],
' ', env_val)
parser = optparse.OptionParser() parser = optparse.OptionParser()
# Make sure that allowing args interspersed with options is # Make sure that allowing args interspersed with options is
# allowed # allowed