Merged revisions 62998-63003,63005-63006,63009-63012,63014-63017,63019-63020,63022-63024,63026-63029,63031-63041,63043-63045,63047-63054,63056-63062 via svnmerge from

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

........
  r62998 | andrew.kuchling | 2008-05-10 15:51:55 -0400 (Sat, 10 May 2008) | 7 lines

  #1858 from Tarek Ziade:
  Allow multiple repositories in .pypirc; see http://wiki.python.org/moin/EnhancedPyPI
  for discussion.

  The patch is slightly revised from Tarek's last patch: I've simplified
  the PyPIRCCommand.finalize_options() method to not look at sys.argv.
  Tests still pass.
........
  r63000 | alexandre.vassalotti | 2008-05-10 15:59:16 -0400 (Sat, 10 May 2008) | 5 lines

  Cleaned up io._BytesIO.write().

  I am amazed that the old code, for inserting null-bytes, actually
  worked. Who wrote that thing? Oh, it is me... doh.
........
  r63002 | brett.cannon | 2008-05-10 16:52:01 -0400 (Sat, 10 May 2008) | 2 lines

  Revert r62998 as it broke the build (seems distutils.config is missing).
........
  r63014 | andrew.kuchling | 2008-05-10 18:12:38 -0400 (Sat, 10 May 2008) | 1 line

  #1858: add distutils.config module
........
  r63027 | brett.cannon | 2008-05-10 21:09:32 -0400 (Sat, 10 May 2008) | 2 lines

  Flesh out the 3.0 deprecation to suggest using the ctypes module.
........
  r63028 | skip.montanaro | 2008-05-10 22:59:30 -0400 (Sat, 10 May 2008) | 4 lines

  Copied two versions of the example from the interactive session.  Delete
  one.
........
  r63037 | georg.brandl | 2008-05-11 03:02:17 -0400 (Sun, 11 May 2008) | 2 lines

  reload() takes the module itself.
........
  r63038 | alexandre.vassalotti | 2008-05-11 03:06:04 -0400 (Sun, 11 May 2008) | 4 lines

  Added test framework for handling module renames.
  Factored the import guard in test_py3kwarn.TestStdlibRemovals into
  a context manager, namely test_support.CleanImport.
........
  r63039 | georg.brandl | 2008-05-11 03:06:05 -0400 (Sun, 11 May 2008) | 2 lines

  #2742: ``''`` is not converted to NULL in getaddrinfo.
........
  r63040 | alexandre.vassalotti | 2008-05-11 03:08:12 -0400 (Sun, 11 May 2008) | 2 lines

  Fixed typo in a comment of test_support.CleanImport.
........
  r63041 | alexandre.vassalotti | 2008-05-11 03:10:25 -0400 (Sun, 11 May 2008) | 2 lines

  Removed a dead line of code.
........
  r63043 | georg.brandl | 2008-05-11 04:47:53 -0400 (Sun, 11 May 2008) | 2 lines

  #2812: document property.getter/setter/deleter.
........
  r63049 | georg.brandl | 2008-05-11 05:06:30 -0400 (Sun, 11 May 2008) | 2 lines

  #1153769: document PEP 237 changes to string formatting.
........
  r63050 | georg.brandl | 2008-05-11 05:11:40 -0400 (Sun, 11 May 2008) | 2 lines

  #2809: elaborate str.split docstring a bit.
........
  r63051 | georg.brandl | 2008-05-11 06:13:59 -0400 (Sun, 11 May 2008) | 2 lines

  Fix typo.
........
  r63052 | georg.brandl | 2008-05-11 06:33:27 -0400 (Sun, 11 May 2008) | 2 lines

  #2709: clarification.
........
  r63053 | georg.brandl | 2008-05-11 06:42:28 -0400 (Sun, 11 May 2008) | 2 lines

  #2659: add ``break_on_hyphens`` to TextWrapper.
........
  r63057 | georg.brandl | 2008-05-11 06:59:39 -0400 (Sun, 11 May 2008) | 2 lines

  #2741: clarification of value range for address_family.
........
  r63058 | georg.brandl | 2008-05-11 07:09:35 -0400 (Sun, 11 May 2008) | 2 lines

  #2452: timeout is used for all blocking operations.
........
  r63059 | andrew.kuchling | 2008-05-11 09:33:56 -0400 (Sun, 11 May 2008) | 2 lines

  #1792: Improve performance of marshal.dumps() on large objects by increasing
  the size of the buffer more quickly.
........
  r63060 | andrew.kuchling | 2008-05-11 10:00:00 -0400 (Sun, 11 May 2008) | 1 line

  #1858: re-apply patch for this, adding the missing files
........
  r63061 | benjamin.peterson | 2008-05-11 10:13:25 -0400 (Sun, 11 May 2008) | 2 lines

  Add the "until" command to pdb
........
  r63062 | georg.brandl | 2008-05-11 10:17:13 -0400 (Sun, 11 May 2008) | 2 lines

  Add some sentence endings.
........
This commit is contained in:
Alexandre Vassalotti 2008-05-16 00:03:33 +00:00
parent a79e33e039
commit 5f8ced2b95
38 changed files with 557 additions and 190 deletions

View File

@ -55,11 +55,40 @@ The .pypirc file
The format of the :file:`.pypirc` file is as follows:: The format of the :file:`.pypirc` file is as follows::
[server-login] [distutils]
index-servers =
pypi
[pypi]
repository: <repository-url> repository: <repository-url>
username: <username> username: <username>
password: <password> password: <password>
*repository* can be omitted and defaults to ``http://www.python.org/pypi``. *repository* can be omitted and defaults to ``http://www.python.org/pypi``.
If you want to define another server a new section can be created::
[distutils]
index-servers =
pypi
other
[pypi]
repository: <repository-url>
username: <username>
password: <password>
[other]
repository: http://example.com/pypi
username: <username>
password: <password>
The command can then be called with the -r option::
python setup.py register -r http://example.com/pypi
Or even with the section name::
python setup.py register -r other

View File

@ -22,14 +22,20 @@ The :command:`upload` command uses the username, password, and repository URL
from the :file:`$HOME/.pypirc` file (see section :ref:`pypirc` for more on this from the :file:`$HOME/.pypirc` file (see section :ref:`pypirc` for more on this
file). file).
You can specify another PyPI server with the :option:`--repository=*url*` option::
python setup.py sdist bdist_wininst upload -r http://example.com/pypi
See section :ref:`pypirc` for more on defining several servers.
You can use the :option:`--sign` option to tell :command:`upload` to sign each You can use the :option:`--sign` option to tell :command:`upload` to sign each
uploaded file using GPG (GNU Privacy Guard). The :program:`gpg` program must uploaded file using GPG (GNU Privacy Guard). The :program:`gpg` program must
be available for execution on the system :envvar:`PATH`. You can also specify be available for execution on the system :envvar:`PATH`. You can also specify
which key to use for signing using the :option:`--identity=*name*` option. which key to use for signing using the :option:`--identity=*name*` option.
Other :command:`upload` options include :option:`--repository=*url*` (which Other :command:`upload` options include :option:`--repository=*url*`
lets you override the repository setting from :file:`$HOME/.pypirc`), and or :option:`--repository=*section*` where `url` is the url of the server
and `section` the name of the section in :file:`$HOME/.pypirc`, and
:option:`--show-response` (which displays the full response text from the PyPI :option:`--show-response` (which displays the full response text from the PyPI
server for help in debugging upload problems). server for help in debugging upload problems).

View File

@ -207,6 +207,11 @@ The :mod:`bdb` module also defines two classes:
Stop when returning from the given frame. Stop when returning from the given frame.
.. method:: set_until(frame)
Stop when the line with the line no greater than the current one is
reached or when returning from current frame
.. method:: set_trace([frame]) .. method:: set_trace([frame])
Start debugging from *frame*. If *frame* is not specified, debugging Start debugging from *frame*. If *frame* is not specified, debugging

View File

@ -40,11 +40,12 @@ The module defines the following items:
.. class:: FTP([host[, user[, passwd[, acct[, timeout]]]]]) .. class:: FTP([host[, user[, passwd[, acct[, timeout]]]]])
Return a new instance of the :class:`FTP` class. When *host* is given, the Return a new instance of the :class:`FTP` class. When *host* is given, the
method call ``connect(host)`` is made. When *user* is given, additionally the method call ``connect(host)`` is made. When *user* is given, additionally
method call ``login(user, passwd, acct)`` is made (where *passwd* and *acct* the method call ``login(user, passwd, acct)`` is made (where *passwd* and
default to the empty string when not given). The optional *timeout* parameter *acct* default to the empty string when not given). The optional *timeout*
specifies a timeout in seconds for the connection attempt (if is not specified, parameter specifies a timeout in seconds for blocking operations like the
or passed as None, the global default timeout setting will be used). connection attempt (if is not specified, or passed as None, the global
default timeout setting will be used).
.. attribute:: all_errors .. attribute:: all_errors
@ -122,9 +123,10 @@ followed by ``lines`` for the text version or ``binary`` for the binary version.
made. made.
The optional *timeout* parameter specifies a timeout in seconds for the The optional *timeout* parameter specifies a timeout in seconds for the
connection attempt. If is not specified, or passed as None, the object timeout connection attempt. If is not specified, or passed as None, the object
is used (the timeout that you passed when instantiating the class); if the timeout is used (the timeout that you passed when instantiating the class);
object timeout is also None, the global default timeout setting will be used. if the object timeout is also None, the global default timeout setting will
be used.
.. method:: FTP.getwelcome() .. method:: FTP.getwelcome()

View File

@ -848,10 +848,15 @@ are always available. They are listed here in alphabetical order.
use is to define a managed attribute x:: use is to define a managed attribute x::
class C(object): class C(object):
def __init__(self): self._x = None def __init__(self):
def getx(self): return self._x self._x = None
def setx(self, value): self._x = value
def delx(self): del self._x def getx(self):
return self._x
def setx(self, value):
self._x = value
def delx(self):
del self._x
x = property(getx, setx, delx, "I'm the 'x' property.") x = property(getx, setx, delx, "I'm the 'x' property.")
If given, *doc* will be the docstring of the property attribute. Otherwise, the If given, *doc* will be the docstring of the property attribute. Otherwise, the
@ -867,8 +872,36 @@ are always available. They are listed here in alphabetical order.
"""Get the current voltage.""" """Get the current voltage."""
return self._voltage return self._voltage
turns the :meth:`voltage` method into a "getter" for a read-only attribute with turns the :meth:`voltage` method into a "getter" for a read-only attribute
the same name. with the same name.
A property object has :attr:`getter`, :attr:`setter`, and :attr:`deleter`
methods usable as decorators that create a copy of the property with the
corresponding accessor function set to the decorated function. This is
best explained with an example::
class C(object):
def __init__(self): self._x = None
@property
def x(self):
"""I'm the 'x' property."""
return self._x
@x.setter
def x(self, value):
self._x = value
@x.deleter
def x(self):
del self._x
This code is exactly equivalent to the first example. Be sure to give the
additional functions the same name as the original property (``x`` in this
case.)
The returned property also has the attributes ``fget``, ``fset``, and
``fdel`` corresponding to the constructor arguments.
.. XXX does accept objects with __index__ too .. XXX does accept objects with __index__ too

View File

@ -27,14 +27,14 @@ The module provides the following classes:
.. class:: HTTPConnection(host[, port[, strict[, timeout]]]) .. class:: HTTPConnection(host[, port[, strict[, timeout]]])
An :class:`HTTPConnection` instance represents one transaction with an HTTP An :class:`HTTPConnection` instance represents one transaction with an HTTP
server. It should be instantiated passing it a host and optional port number. server. It should be instantiated passing it a host and optional port
If no port number is passed, the port is extracted from the host string if it number. If no port number is passed, the port is extracted from the host
has the form ``host:port``, else the default HTTP port (80) is used. When True, string if it has the form ``host:port``, else the default HTTP port (80) is
the optional parameter *strict* causes ``BadStatusLine`` to be raised if the used. When True, the optional parameter *strict* causes ``BadStatusLine`` to
status line can't be parsed as a valid HTTP/1.0 or 1.1 status line. If the be raised if the status line can't be parsed as a valid HTTP/1.0 or 1.1
optional *timeout* parameter is given, connection attempts will timeout after status line. If the optional *timeout* parameter is given, blocking
that many seconds (if it is not given or ``None``, the global default timeout operations (like connection attempts) will timeout after that many seconds
setting is used). (if it is not given or ``None``, the global default timeout setting is used).
For example, the following calls all create instances that connect to the server For example, the following calls all create instances that connect to the server
at the same host and port:: at the same host and port::

View File

@ -261,6 +261,12 @@ n(ext)
inside a called function, while ``next`` executes called functions at (nearly) inside a called function, while ``next`` executes called functions at (nearly)
full speed, only stopping at the next line in the current function.) full speed, only stopping at the next line in the current function.)
unt(il)
Continue execution until the line with the the line number greater than the
current one is reached or when returning from current frame.
.. versionadded:: 2.6
r(eturn) r(eturn)
Continue execution until the current function returns. Continue execution until the current function returns.

View File

@ -19,13 +19,14 @@ Protocol) and :rfc:`1869` (SMTP Service Extensions).
.. class:: SMTP([host[, port[, local_hostname[, timeout]]]]) .. class:: SMTP([host[, port[, local_hostname[, timeout]]]])
A :class:`SMTP` instance encapsulates an SMTP connection. It has methods that A :class:`SMTP` instance encapsulates an SMTP connection. It has methods
support a full repertoire of SMTP and ESMTP operations. If the optional host and that support a full repertoire of SMTP and ESMTP operations. If the optional
port parameters are given, the SMTP :meth:`connect` method is called with those host and port parameters are given, the SMTP :meth:`connect` method is called
parameters during initialization. An :exc:`SMTPConnectError` is raised if the with those parameters during initialization. An :exc:`SMTPConnectError` is
specified host doesn't respond correctly. The optional *timeout* parameter raised if the specified host doesn't respond correctly. The optional
specifies a timeout in seconds for the connection attempt (if not specified, or *timeout* parameter specifies a timeout in seconds for blocking operations
passed as None, the global default timeout setting will be used). like the connection attempt (if not specified, or passed as None, the global
default timeout setting will be used).
For normal use, you should only require the initialization/connect, For normal use, you should only require the initialization/connect,
:meth:`sendmail`, and :meth:`quit` methods. An example is included below. :meth:`sendmail`, and :meth:`quit` methods. An example is included below.
@ -35,13 +36,14 @@ Protocol) and :rfc:`1869` (SMTP Service Extensions).
A :class:`SMTP_SSL` instance behaves exactly the same as instances of A :class:`SMTP_SSL` instance behaves exactly the same as instances of
:class:`SMTP`. :class:`SMTP_SSL` should be used for situations where SSL is :class:`SMTP`. :class:`SMTP_SSL` should be used for situations where SSL is
required from the beginning of the connection and using :meth:`starttls` is not required from the beginning of the connection and using :meth:`starttls` is
appropriate. If *host* is not specified, the local host is used. If *port* is not appropriate. If *host* is not specified, the local host is used. If
omitted, the standard SMTP-over-SSL port (465) is used. *keyfile* and *certfile* *port* is omitted, the standard SMTP-over-SSL port (465) is used. *keyfile*
are also optional, and can contain a PEM formatted private key and certificate and *certfile* are also optional, and can contain a PEM formatted private key
chain file for the SSL connection. The optional *timeout* parameter specifies a and certificate chain file for the SSL connection. The optional *timeout*
timeout in seconds for the connection attempt (if not specified, or passed as parameter specifies a timeout in seconds for blocking operations like the
None, the global default timeout setting will be used). connection attempt (if not specified, or passed as None, the global default
timeout setting will be used).
.. class:: LMTP([host[, port[, local_hostname]]]) .. class:: LMTP([host[, port[, local_hostname]]])

View File

@ -213,9 +213,9 @@ The module :mod:`socket` exports the following constants and functions:
service name (like ``'http'``), a numeric port number or ``None``. service name (like ``'http'``), a numeric port number or ``None``.
The rest of the arguments are optional and must be numeric if specified. For The rest of the arguments are optional and must be numeric if specified. For
*host* and *port*, by passing either an empty string or ``None``, you can pass *host* and *port*, by passing ``None``, you can pass ``NULL`` to the C API.
``NULL`` to the C API. The :func:`getaddrinfo` function returns a list of The :func:`getaddrinfo` function returns a list of 5-tuples with the following
5-tuples with the following structure: structure:
``(family, socktype, proto, canonname, sockaddr)`` ``(family, socktype, proto, canonname, sockaddr)``
@ -785,7 +785,7 @@ sends traffic to the first one connected successfully. ::
import socket import socket
import sys import sys
HOST = '' # Symbolic name meaning all available interfaces HOST = None # Symbolic name meaning all available interfaces
PORT = 50007 # Arbitrary non-privileged port PORT = 50007 # Arbitrary non-privileged port
s = None s = None
for res in socket.getaddrinfo(HOST, PORT, socket.AF_UNSPEC, socket.SOCK_STREAM, 0, socket.AI_PASSIVE): for res in socket.getaddrinfo(HOST, PORT, socket.AF_UNSPEC, socket.SOCK_STREAM, 0, socket.AI_PASSIVE):
@ -847,7 +847,7 @@ sends traffic to the first one connected successfully. ::
The last example shows how to write a very simple network sniffer with raw The last example shows how to write a very simple network sniffer with raw
sockets on Windows. The example requires administrator priviliges to modify sockets on Windows. The example requires administrator privileges to modify
the interface:: the interface::
import socket import socket

View File

@ -155,7 +155,7 @@ Server Objects
.. data:: address_family .. data:: address_family
The family of protocols to which the server's socket belongs. The family of protocols to which the server's socket belongs.
:const:`socket.AF_INET` and :const:`socket.AF_UNIX` are two possible values. Common examples are :const:`socket.AF_INET` and :const:`socket.AF_UNIX`.
.. data:: RequestHandlerClass .. data:: RequestHandlerClass
@ -199,7 +199,7 @@ The server classes support the following class variables:
.. data:: socket_type .. data:: socket_type
The type of socket used by the server; :const:`socket.SOCK_STREAM` and The type of socket used by the server; :const:`socket.SOCK_STREAM` and
:const:`socket.SOCK_DGRAM` are two possible values. :const:`socket.SOCK_DGRAM` are two common values.
.. data:: timeout .. data:: timeout

View File

@ -1114,7 +1114,7 @@ The conversion flag characters are:
+---------+---------------------------------------------------------------------+ +---------+---------------------------------------------------------------------+
A length modifier (``h``, ``l``, or ``L``) may be present, but is ignored as it A length modifier (``h``, ``l``, or ``L``) may be present, but is ignored as it
is not necessary for Python. is not necessary for Python -- so e.g. ``%ld`` is identical to ``%d``.
The conversion types are: The conversion types are:
@ -1125,13 +1125,13 @@ The conversion types are:
+------------+-----------------------------------------------------+-------+ +------------+-----------------------------------------------------+-------+
| ``'i'`` | Signed integer decimal. | | | ``'i'`` | Signed integer decimal. | |
+------------+-----------------------------------------------------+-------+ +------------+-----------------------------------------------------+-------+
| ``'o'`` | Unsigned octal. | \(1) | | ``'o'`` | Signed octal value. | \(1) |
+------------+-----------------------------------------------------+-------+ +------------+-----------------------------------------------------+-------+
| ``'u'`` | Unsigned decimal. | | | ``'u'`` | Obselete type -- it is identical to ``'d'``. | \(7) |
+------------+-----------------------------------------------------+-------+ +------------+-----------------------------------------------------+-------+
| ``'x'`` | Unsigned hexadecimal (lowercase). | \(2) | | ``'x'`` | Signed hexadecimal (lowercase). | \(2) |
+------------+-----------------------------------------------------+-------+ +------------+-----------------------------------------------------+-------+
| ``'X'`` | Unsigned hexadecimal (uppercase). | \(2) | | ``'X'`` | Signed hexadecimal (uppercase). | \(2) |
+------------+-----------------------------------------------------+-------+ +------------+-----------------------------------------------------+-------+
| ``'e'`` | Floating point exponential format (lowercase). | \(3) | | ``'e'`` | Floating point exponential format (lowercase). | \(3) |
+------------+-----------------------------------------------------+-------+ +------------+-----------------------------------------------------+-------+
@ -1193,6 +1193,9 @@ Notes:
The precision determines the maximal number of characters used. The precision determines the maximal number of characters used.
(7)
See :pep:`237`.
Since Python strings have an explicit length, ``%s`` conversions do not assume Since Python strings have an explicit length, ``%s`` conversions do not assume
that ``'\0'`` is the end of the string. that ``'\0'`` is the end of the string.

View File

@ -27,11 +27,12 @@ Character), EL (Erase Line), GA (Go Ahead), SB (Subnegotiation Begin).
:class:`Telnet` represents a connection to a Telnet server. The instance is :class:`Telnet` represents a connection to a Telnet server. The instance is
initially not connected by default; the :meth:`open` method must be used to initially not connected by default; the :meth:`open` method must be used to
establish a connection. Alternatively, the host name and optional port number establish a connection. Alternatively, the host name and optional port
can be passed to the constructor, to, in which case the connection to the server number can be passed to the constructor, to, in which case the connection to
will be established before the constructor returns. The optional *timeout* the server will be established before the constructor returns. The optional
parameter specifies a timeout in seconds for the connection attempt (if not *timeout* parameter specifies a timeout in seconds for blocking operations
specified, or passed as None, the global default timeout setting will be used). like the connection attempt (if not specified, or passed as None, the global
default timeout setting will be used).
Do not reopen an already connected instance. Do not reopen an already connected instance.
@ -121,8 +122,9 @@ Telnet Objects
Connect to a host. The optional second argument is the port number, which Connect to a host. The optional second argument is the port number, which
defaults to the standard Telnet port (23). The optional *timeout* parameter defaults to the standard Telnet port (23). The optional *timeout* parameter
specifies a timeout in seconds for the connection attempt (if not specified, or specifies a timeout in seconds for blocking operations like the connection
passed as None, the global default timeout setting will be used). attempt (if not specified, or passed as None, the global default timeout
setting will be used).
Do not try to reopen an already connected instance. Do not try to reopen an already connected instance.

View File

@ -155,11 +155,6 @@ The module defines the following user-callable functions:
:func:`mktemp` usage can be replaced easily with :func:`mktemp` usage can be replaced easily with
:func:`NamedTemporaryFile`, passing it the `delete=False` parameter:: :func:`NamedTemporaryFile`, passing it the `delete=False` parameter::
>>> f = NamedTemporaryFile(delete=False)
>>> print f.name
>>> f.write("Hello World!\n")
>>> f.close()
>>> os.unlink(f.name)
>>> f = NamedTemporaryFile(delete=False) >>> f = NamedTemporaryFile(delete=False)
>>> f >>> f
<open file '<fdopen>', mode 'w+b' at 0x384698> <open file '<fdopen>', mode 'w+b' at 0x384698>

View File

@ -39,6 +39,10 @@ instance and calling a single method on it. That instance is not reused, so for
applications that wrap/fill many text strings, it will be more efficient for you applications that wrap/fill many text strings, it will be more efficient for you
to create your own :class:`TextWrapper` object. to create your own :class:`TextWrapper` object.
Text is preferably wrapped on whitespaces and right after the hyphens in
hyphenated words; only then will long words be broken if necessary, unless
:attr:`TextWrapper.break_long_words` is set to false.
An additional utility function, :func:`dedent`, is provided to remove An additional utility function, :func:`dedent`, is provided to remove
indentation from strings that have unwanted whitespace to the left of the text. indentation from strings that have unwanted whitespace to the left of the text.
@ -167,10 +171,22 @@ indentation from strings that have unwanted whitespace to the left of the text.
than :attr:`width`. (Long words will be put on a line by themselves, in than :attr:`width`. (Long words will be put on a line by themselves, in
order to minimize the amount by which :attr:`width` is exceeded.) order to minimize the amount by which :attr:`width` is exceeded.)
.. attribute:: break_on_hyphens
(default: ``True``) If true, wrapping will occur preferably on whitespaces
and right after hyphens in compound words, as it is customary in English.
If false, only whitespaces will be considered as potentially good places
for line breaks, but you need to set :attr:`break_long_words` to false if
you want truly insecable words. Default behaviour in previous versions
was to always allow breaking hyphenated words.
.. versionadded:: 2.6
:class:`TextWrapper` also provides two public methods, analogous to the :class:`TextWrapper` also provides two public methods, analogous to the
module-level convenience functions: module-level convenience functions:
.. method:: wrap(text) .. method:: wrap(text)
Wraps the single paragraph in *text* (a string) so every line is at most Wraps the single paragraph in *text* (a string) so every line is at most

View File

@ -23,7 +23,8 @@ mechanism which allows Python and Tcl to interact.
:mod:`Tkinter`'s chief virtues are that it is fast, and that it usually comes :mod:`Tkinter`'s chief virtues are that it is fast, and that it usually comes
bundled with Python. Although it has been used to create some very good bundled with Python. Although it has been used to create some very good
applications, including IDLE, it has weak documentation and an outdated look and applications, including IDLE, its standard documentation is weak (but there
are some good books and tutorials), and it has an outdated look and
feel. For more modern, better documented, and much more extensive GUI feel. For more modern, better documented, and much more extensive GUI
libraries, see the :ref:`other-gui-packages` section. libraries, see the :ref:`other-gui-packages` section.

View File

@ -26,10 +26,10 @@ The :mod:`urllib2` module defines the following functions:
:func:`urllib.urlencode` function takes a mapping or sequence of 2-tuples and :func:`urllib.urlencode` function takes a mapping or sequence of 2-tuples and
returns a string in this format. returns a string in this format.
The optional *timeout* parameter specifies a timeout in seconds for the The optional *timeout* parameter specifies a timeout in seconds for blocking
connection attempt (if not specified, or passed as None, the global default operations like the connection attempt (if not specified, or passed as
timeout setting will be used). This actually only work for HTTP, HTTPS, FTP and ``None``, the global default timeout setting will be used). This actually
FTPS connections. only works for HTTP, HTTPS, FTP and FTPS connections.
This function returns a file-like object with two additional methods: This function returns a file-like object with two additional methods:
@ -399,12 +399,13 @@ OpenerDirector Objects
.. method:: OpenerDirector.open(url[, data][, timeout]) .. method:: OpenerDirector.open(url[, data][, timeout])
Open the given *url* (which can be a request object or a string), optionally Open the given *url* (which can be a request object or a string), optionally
passing the given *data*. Arguments, return values and exceptions raised are the passing the given *data*. Arguments, return values and exceptions raised are
same as those of :func:`urlopen` (which simply calls the :meth:`open` method on the same as those of :func:`urlopen` (which simply calls the :meth:`open`
the currently installed global :class:`OpenerDirector`). The optional *timeout* method on the currently installed global :class:`OpenerDirector`). The
parameter specifies a timeout in seconds for the connection attempt (if not optional *timeout* parameter specifies a timeout in seconds for blocking
specified, or passed as None, the global default timeout setting will be used; operations like the connection attempt (if not specified, or passed as
this actually only work for HTTP, HTTPS, FTP and FTPS connections). ``None``, the global default timeout setting will be used; this actually only
works for HTTP, HTTPS, FTP and FTPS connections).
.. method:: OpenerDirector.error(proto[, arg[, ...]]) .. method:: OpenerDirector.error(proto[, arg[, ...]])

View File

@ -111,7 +111,7 @@ you have already defined.
For efficiency reasons, each module is only imported once per interpreter For efficiency reasons, each module is only imported once per interpreter
session. Therefore, if you change your modules, you must restart the session. Therefore, if you change your modules, you must restart the
interpreter -- or, if it's just one module you want to test interactively, interpreter -- or, if it's just one module you want to test interactively,
use :func:`reload`, e.g. ``reload('modulename')``. use :func:`reload`, e.g. ``reload(modulename)``.
.. _tut-modulesasscripts: .. _tut-modulesasscripts:

View File

@ -37,9 +37,7 @@ class Bdb:
import linecache import linecache
linecache.checkcache() linecache.checkcache()
self.botframe = None self.botframe = None
self.stopframe = None self._set_stopinfo(None, None)
self.returnframe = None
self.quitting = 0
def trace_dispatch(self, frame, event, arg): def trace_dispatch(self, frame, event, arg):
if self.quitting: if self.quitting:
@ -100,7 +98,7 @@ class Bdb:
# (CT) stopframe may now also be None, see dispatch_call. # (CT) stopframe may now also be None, see dispatch_call.
# (CT) the former test for None is therefore removed from here. # (CT) the former test for None is therefore removed from here.
if frame is self.stopframe: if frame is self.stopframe:
return True return frame.f_lineno >= self.stoplineno
while frame is not None and frame is not self.stopframe: while frame is not None and frame is not self.stopframe:
if frame is self.botframe: if frame is self.botframe:
return True return True
@ -156,26 +154,31 @@ class Bdb:
but only if we are to stop at or just below this level.""" but only if we are to stop at or just below this level."""
pass pass
def _set_stopinfo(self, stopframe, returnframe, stoplineno=-1):
self.stopframe = stopframe
self.returnframe = returnframe
self.quitting = 0
self.stoplineno = stoplineno
# Derived classes and clients can call the following methods # Derived classes and clients can call the following methods
# to affect the stepping state. # to affect the stepping state.
def set_until(self, frame): #the name "until" is borrowed from gdb
"""Stop when the line with the line no greater than the current one is
reached or when returning from current frame"""
self._set_stopinfo(frame, frame, frame.f_lineno+1)
def set_step(self): def set_step(self):
"""Stop after one line of code.""" """Stop after one line of code."""
self.stopframe = None self._set_stopinfo(None,None)
self.returnframe = None
self.quitting = 0
def set_next(self, frame): def set_next(self, frame):
"""Stop on the next line in or below the given frame.""" """Stop on the next line in or below the given frame."""
self.stopframe = frame self._set_stopinfo(frame, None)
self.returnframe = None
self.quitting = 0
def set_return(self, frame): def set_return(self, frame):
"""Stop when returning from the given frame.""" """Stop when returning from the given frame."""
self.stopframe = frame.f_back self._set_stopinfo(frame.f_back, frame)
self.returnframe = frame
self.quitting = 0
def set_trace(self, frame=None): def set_trace(self, frame=None):
"""Start debugging from `frame`. """Start debugging from `frame`.
@ -194,9 +197,7 @@ class Bdb:
def set_continue(self): def set_continue(self):
# Don't stop except at breakpoints or when finished # Don't stop except at breakpoints or when finished
self.stopframe = self.botframe self._set_stopinfo(self.botframe, None)
self.returnframe = None
self.quitting = 0
if not self.breaks: if not self.breaks:
# no breakpoints; run without debugger overhead # no breakpoints; run without debugger overhead
sys.settrace(None) sys.settrace(None)

View File

@ -8,42 +8,34 @@ Implements the Distutils 'register' command (register with the repository).
__revision__ = "$Id$" __revision__ = "$Id$"
import os, string, urllib2, getpass, urlparse import os, string, urllib2, getpass, urlparse
import io, configparser import io
from distutils.core import Command from distutils.core import PyPIRCCommand
from distutils.errors import * from distutils.errors import *
from distutils import log
def raw_input(prompt): def raw_input(prompt):
sys.stdout.write(prompt) sys.stdout.write(prompt)
sys.stdout.flush() sys.stdout.flush()
return sys.stdin.readline() return sys.stdin.readline()
class register(Command): class register(PyPIRCCommand):
description = ("register the distribution with the Python package index") description = ("register the distribution with the Python package index")
user_options = PyPIRCCommand.user_options + [
DEFAULT_REPOSITORY = 'http://pypi.python.org/pypi'
user_options = [
('repository=', 'r',
"url of repository [default: %s]"%DEFAULT_REPOSITORY),
('list-classifiers', None, ('list-classifiers', None,
'list the valid Trove classifiers'), 'list the valid Trove classifiers'),
('show-response', None,
'display full response text from server'),
] ]
boolean_options = ['verify', 'show-response', 'list-classifiers'] boolean_options = PyPIRCCommand.boolean_options + [
'verify', 'list-classifiers']
def initialize_options(self): def initialize_options(self):
self.repository = None PyPIRCCommand.initialize_options(self)
self.show_response = 0
self.list_classifiers = 0 self.list_classifiers = 0
def finalize_options(self):
if self.repository is None:
self.repository = self.DEFAULT_REPOSITORY
def run(self): def run(self):
self.finalize_options()
self._set_config()
self.check_metadata() self.check_metadata()
if self.dry_run: if self.dry_run:
self.verify_metadata() self.verify_metadata()
@ -82,6 +74,23 @@ class register(Command):
"or (maintainer and maintainer_email) " + "or (maintainer and maintainer_email) " +
"must be supplied") "must be supplied")
def _set_config(self):
''' Reads the configuration file and set attributes.
'''
config = self._read_pypirc()
if config != {}:
self.username = config['username']
self.password = config['password']
self.repository = config['repository']
self.realm = config['realm']
self.has_config = True
else:
if self.repository not in ('pypi', self.DEFAULT_REPOSITORY):
raise ValueError('%s not found in .pypirc' % self.repository)
if self.repository == 'pypi':
self.repository = self.DEFAULT_REPOSITORY
self.has_config = False
def classifiers(self): def classifiers(self):
''' Fetch the list of classifiers from the server. ''' Fetch the list of classifiers from the server.
''' '''
@ -95,6 +104,7 @@ class register(Command):
(code, result) = self.post_to_server(self.build_post_data('verify')) (code, result) = self.post_to_server(self.build_post_data('verify'))
print('Server response (%s): %s'%(code, result)) print('Server response (%s): %s'%(code, result))
def send_metadata(self): def send_metadata(self):
''' Send the metadata to the package index server. ''' Send the metadata to the package index server.
@ -104,10 +114,14 @@ class register(Command):
First we try to read the username/password from $HOME/.pypirc, First we try to read the username/password from $HOME/.pypirc,
which is a ConfigParser-formatted file with a section which is a ConfigParser-formatted file with a section
[server-login] containing username and password entries (both [distutils] containing username and password entries (both
in clear text). Eg: in clear text). Eg:
[server-login] [distutils]
index-servers =
pypi
[pypi]
username: fred username: fred
password: sekrit password: sekrit
@ -119,21 +133,15 @@ class register(Command):
3. set the password to a random string and email the user. 3. set the password to a random string and email the user.
''' '''
choice = 'x'
username = password = ''
# see if we can short-cut and get the username/password from the # see if we can short-cut and get the username/password from the
# config # config
config = None if self.has_config:
if 'HOME' in os.environ: choice = '1'
rc = os.path.join(os.environ['HOME'], '.pypirc') username = self.username
if os.path.exists(rc): password = self.password
print('Using PyPI login from %s'%rc) else:
config = ConfigParser.ConfigParser() choice = 'x'
config.read(rc) username = password = ''
username = config.get('server-login', 'username')
password = config.get('server-login', 'password')
choice = '1'
# get the user's login info # get the user's login info
choices = '1 2 3 4'.split() choices = '1 2 3 4'.split()
@ -160,32 +168,24 @@ Your selection [default 1]: ''', end=' ')
# set up the authentication # set up the authentication
auth = urllib2.HTTPPasswordMgr() auth = urllib2.HTTPPasswordMgr()
host = urlparse.urlparse(self.repository)[1] host = urlparse.urlparse(self.repository)[1]
auth.add_password('pypi', host, username, password) auth.add_password(self.realm, host, username, password)
# send the info to the server and report the result # send the info to the server and report the result
code, result = self.post_to_server(self.build_post_data('submit'), code, result = self.post_to_server(self.build_post_data('submit'),
auth) auth)
print('Server response (%s): %s'%(code, result)) print('Server response (%s): %s'%(code, result))
# possibly save the login # possibly save the login
if 'HOME' in os.environ and config is None and code == 200: if not self.has_config and code == 200:
rc = os.path.join(os.environ['HOME'], '.pypirc')
print('I can store your PyPI login so future submissions will be faster.') print('I can store your PyPI login so future submissions will be faster.')
print('(the login will be stored in %s)'%rc) print('(the login will be stored in %s)' % self._get_rc_file())
choice = 'X' choice = 'X'
while choice.lower() not in 'yn': while choice.lower() not in 'yn':
choice = raw_input('Save your login (y/N)?') choice = raw_input('Save your login (y/N)?')
if not choice: if not choice:
choice = 'n' choice = 'n'
if choice.lower() == 'y': if choice.lower() == 'y':
f = open(rc, 'w') self._store_pypirc(username, password)
f.write('[server-login]\nusername:%s\npassword:%s\n'%(
username, password))
f.close()
try:
os.chmod(rc, 0o600)
except:
pass
elif choice == '2': elif choice == '2':
data = {':action': 'user'} data = {':action': 'user'}
data['name'] = data['password'] = data['email'] = '' data['name'] = data['password'] = data['email'] = ''
@ -248,7 +248,8 @@ Your selection [default 1]: ''', end=' ')
def post_to_server(self, data, auth=None): def post_to_server(self, data, auth=None):
''' Post a query to the server, and return a string response. ''' Post a query to the server, and return a string response.
''' '''
self.announce('Registering %s to %s' % (data['name'],
self.repository), log.INFO)
# Build up the MIME payload for the urllib2 POST data # Build up the MIME payload for the urllib2 POST data
boundary = '--------------GHSKFJDLGDS7543FJKLFHRE75642756743254' boundary = '--------------GHSKFJDLGDS7543FJKLFHRE75642756743254'
sep_boundary = '\n--' + boundary sep_boundary = '\n--' + boundary

View File

@ -3,7 +3,7 @@
Implements the Distutils 'upload' subcommand (upload package to PyPI).""" Implements the Distutils 'upload' subcommand (upload package to PyPI)."""
from distutils.errors import * from distutils.errors import *
from distutils.core import Command from distutils.core import PyPIRCCommand
from distutils.spawn import spawn from distutils.spawn import spawn
from distutils import log from distutils import log
from hashlib import md5 from hashlib import md5
@ -15,53 +15,38 @@ import httplib
import base64 import base64
import urlparse import urlparse
class upload(Command): class upload(PyPIRCCommand):
description = "upload binary package to PyPI" description = "upload binary package to PyPI"
DEFAULT_REPOSITORY = 'http://pypi.python.org/pypi' user_options = PyPIRCCommand.user_options + [
user_options = [
('repository=', 'r',
"url of repository [default: %s]" % DEFAULT_REPOSITORY),
('show-response', None,
'display full response text from server'),
('sign', 's', ('sign', 's',
'sign files to upload using gpg'), 'sign files to upload using gpg'),
('identity=', 'i', 'GPG identity used to sign files'), ('identity=', 'i', 'GPG identity used to sign files'),
] ]
boolean_options = ['show-response', 'sign']
boolean_options = PyPIRCCommand.boolean_options + ['sign']
def initialize_options(self): def initialize_options(self):
PyPIRCCommand.initialize_options(self)
self.username = '' self.username = ''
self.password = '' self.password = ''
self.repository = ''
self.show_response = 0 self.show_response = 0
self.sign = False self.sign = False
self.identity = None self.identity = None
def finalize_options(self): def finalize_options(self):
PyPIRCCommand.finalize_options(self)
if self.identity and not self.sign: if self.identity and not self.sign:
raise DistutilsOptionError( raise DistutilsOptionError(
"Must use --sign for --identity to have meaning" "Must use --sign for --identity to have meaning"
) )
if 'HOME' in os.environ: config = self._read_pypirc()
rc = os.path.join(os.environ['HOME'], '.pypirc') if config != {}:
if os.path.exists(rc): self.username = config['username']
self.announce('Using PyPI login from %s' % rc) self.password = config['password']
config = ConfigParser.ConfigParser({ self.repository = config['repository']
'username':'', self.realm = config['realm']
'password':'',
'repository':''})
config.read(rc)
if not self.repository:
self.repository = config.get('server-login', 'repository')
if not self.username:
self.username = config.get('server-login', 'username')
if not self.password:
self.password = config.get('server-login', 'password')
if not self.repository:
self.repository = self.DEFAULT_REPOSITORY
def run(self): def run(self):
if not self.distribution.dist_files: if not self.distribution.dist_files:

View File

@ -49,7 +49,7 @@ class PyPIRCCommand(Command):
finally: finally:
f.close() f.close()
try: try:
os.chmod(rc, 0600) os.chmod(rc, 0o600)
except OSError: except OSError:
# should do something better here # should do something better here
pass pass
@ -58,7 +58,7 @@ class PyPIRCCommand(Command):
"""Reads the .pypirc file.""" """Reads the .pypirc file."""
rc = self._get_rc_file() rc = self._get_rc_file()
if os.path.exists(rc): if os.path.exists(rc):
print 'Using PyPI login from %s' % rc print('Using PyPI login from %s' % rc)
repository = self.repository or self.DEFAULT_REPOSITORY repository = self.repository or self.DEFAULT_REPOSITORY
realm = self.realm or self.DEFAULT_REALM realm = self.realm or self.DEFAULT_REALM

View File

@ -17,6 +17,7 @@ from distutils.util import grok_environment_error
# Mainly import these so setup scripts can "from distutils.core import" them. # Mainly import these so setup scripts can "from distutils.core import" them.
from distutils.dist import Distribution from distutils.dist import Distribution
from distutils.cmd import Command from distutils.cmd import Command
from distutils.config import PyPIRCCommand
from distutils.extension import Extension from distutils.extension import Extension
# This is a barebones help message generated displayed when the user # This is a barebones help message generated displayed when the user

View File

@ -334,10 +334,9 @@ Common commands: (see '--help-commands' for more)
user_filename = "pydistutils.cfg" user_filename = "pydistutils.cfg"
# And look for the user config file # And look for the user config file
if 'HOME' in os.environ: user_file = os.path.join(os.path.expanduser('~'), user_filename)
user_file = os.path.join(os.environ.get('HOME'), user_filename) if os.path.isfile(user_file):
if os.path.isfile(user_file): files.append(user_file)
files.append(user_file)
# All platforms support local setup.cfg # All platforms support local setup.cfg
local_file = "setup.cfg" local_file = "setup.cfg"

View File

@ -0,0 +1,103 @@
"""Tests for distutils.pypirc.pypirc."""
import sys
import os
import unittest
from distutils.core import PyPIRCCommand
from distutils.core import Distribution
from distutils.tests import support
PYPIRC = """\
[distutils]
index-servers =
server1
server2
[server1]
username:me
password:secret
[server2]
username:meagain
password: secret
realm:acme
repository:http://another.pypi/
"""
PYPIRC_OLD = """\
[server-login]
username:tarek
password:secret
"""
class PyPIRCCommandTestCase(support.TempdirManager, unittest.TestCase):
def setUp(self):
"""Patches the environment."""
if 'HOME' in os.environ:
self._old_home = os.environ['HOME']
else:
self._old_home = None
curdir = os.path.dirname(__file__)
os.environ['HOME'] = curdir
self.rc = os.path.join(curdir, '.pypirc')
self.dist = Distribution()
class command(PyPIRCCommand):
def __init__(self, dist):
PyPIRCCommand.__init__(self, dist)
def initialize_options(self):
pass
finalize_options = initialize_options
self._cmd = command
def tearDown(self):
"""Removes the patch."""
if self._old_home is None:
del os.environ['HOME']
else:
os.environ['HOME'] = self._old_home
if os.path.exists(self.rc):
os.remove(self.rc)
def test_server_registration(self):
# This test makes sure PyPIRCCommand knows how to:
# 1. handle several sections in .pypirc
# 2. handle the old format
# new format
f = open(self.rc, 'w')
try:
f.write(PYPIRC)
finally:
f.close()
cmd = self._cmd(self.dist)
config = cmd._read_pypirc()
config = list(sorted(config.items()))
waited = [('password', 'secret'), ('realm', 'pypi'),
('repository', 'http://pypi.python.org/pypi'),
('server', 'server1'), ('username', 'me')]
self.assertEquals(config, waited)
# old format
f = open(self.rc, 'w')
f.write(PYPIRC_OLD)
f.close()
config = cmd._read_pypirc()
config = list(sorted(config.items()))
waited = [('password', 'secret'), ('realm', 'pypi'),
('repository', 'http://pypi.python.org/pypi'),
('server', 'server-login'), ('username', 'tarek')]
self.assertEquals(config, waited)
def test_suite():
return unittest.makeSuite(PyPIRCCommandTestCase)
if __name__ == "__main__":
unittest.main(defaultTest="test_suite")

View File

@ -55,6 +55,7 @@ class DistributionTestCase(unittest.TestCase):
self.assertEqual(d.get_command_packages(), ["distutils.command"]) self.assertEqual(d.get_command_packages(), ["distutils.command"])
def test_command_packages_cmdline(self): def test_command_packages_cmdline(self):
from distutils.tests.test_dist import test_dist
sys.argv.extend(["--command-packages", sys.argv.extend(["--command-packages",
"foo.bar,distutils.tests", "foo.bar,distutils.tests",
"test_dist", "test_dist",
@ -179,9 +180,54 @@ class MetadataTestCase(unittest.TestCase):
dist.metadata.write_pkg_file(sio) dist.metadata.write_pkg_file(sio)
return sio.getvalue() return sio.getvalue()
def test_custom_pydistutils(self):
# fixes #2166
# make sure pydistutils.cfg is found
old = {}
for env in ('HOME', 'HOMEPATH', 'HOMEDRIVE'):
value = os.environ.get(env)
old[env] = value
if value is not None:
del os.environ[env]
if os.name == 'posix':
user_filename = ".pydistutils.cfg"
else:
user_filename = "pydistutils.cfg"
curdir = os.path.dirname(__file__)
user_filename = os.path.join(curdir, user_filename)
f = open(user_filename, 'w')
f.write('.')
f.close()
try:
dist = distutils.dist.Distribution()
# linux-style
if sys.platform in ('linux', 'darwin'):
os.environ['HOME'] = curdir
files = dist.find_config_files()
self.assert_(user_filename in files)
# win32-style
if sys.platform == 'win32':
# home drive should be found
os.environ['HOMEPATH'] = curdir
files = dist.find_config_files()
self.assert_(user_filename in files)
finally:
for key, value in old.items():
if value is None:
continue
os.environ[key] = value
os.remove(user_filename)
def test_suite(): def test_suite():
suite = unittest.TestSuite() suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(DistributionTestCase)) suite.addTest(unittest.makeSuite(DistributionTestCase))
suite.addTest(unittest.makeSuite(MetadataTestCase)) suite.addTest(unittest.makeSuite(MetadataTestCase))
return suite return suite
if __name__ == "__main__":
unittest.main(defaultTest="test_suite")

View File

@ -0,0 +1,34 @@
"""Tests for distutils.command.upload."""
import sys
import os
import unittest
from distutils.command.upload import upload
from distutils.core import Distribution
from distutils.tests import support
from distutils.tests.test_config import PYPIRC, PyPIRCCommandTestCase
class uploadTestCase(PyPIRCCommandTestCase):
def test_finalize_options(self):
# new format
f = open(self.rc, 'w')
f.write(PYPIRC)
f.close()
dist = Distribution()
cmd = upload(dist)
cmd.finalize_options()
for attr, waited in (('username', 'me'), ('password', 'secret'),
('realm', 'pypi'),
('repository', 'http://pypi.python.org/pypi')):
self.assertEquals(getattr(cmd, attr), waited)
def test_suite():
return unittest.makeSuite(uploadTestCase)
if __name__ == "__main__":
unittest.main(defaultTest="test_suite")

View File

@ -813,14 +813,14 @@ class _BytesIO(BufferedIOBase):
n = len(b) n = len(b)
if n == 0: if n == 0:
return 0 return 0
newpos = self._pos + n pos = self._pos
if newpos > len(self._buffer): if pos > len(self._buffer):
# Inserts null bytes between the current end of the file # Inserts null bytes between the current end of the file
# and the new write position. # and the new write position.
padding = b'\x00' * (newpos - len(self._buffer) - n) padding = b'\x00' * (pos - len(self._buffer))
self._buffer[self._pos:newpos - n] = padding self._buffer += padding
self._buffer[self._pos:newpos] = b self._buffer[pos:pos + n] = b
self._pos = newpos self._pos += n
return n return n
def seek(self, pos, whence=0): def seek(self, pos, whence=0):

View File

@ -128,6 +128,10 @@ n(ext)
Continue execution until the next line in the current function Continue execution until the next line in the current function
is reached or it returns. is reached or it returns.
unt(il)
Continue execution until the line with a number greater than the
current one is reached or until the current frame returns.
r(eturn) r(eturn)
Continue execution until the current function returns. Continue execution until the current function returns.

View File

@ -611,6 +611,11 @@ class Pdb(bdb.Bdb, cmd.Cmd):
self.lineno = None self.lineno = None
do_d = do_down do_d = do_down
def do_until(self, arg):
self.set_until(self.curframe)
return 1
do_unt = do_until
def do_step(self, arg): def do_step(self, arg):
self.set_step() self.set_step()
return 1 return 1
@ -958,6 +963,14 @@ i.e., the breakpoint is made unconditional.""", file=self.stdout)
Execute the current line, stop at the first possible occasion Execute the current line, stop at the first possible occasion
(either in a function that is called or in the current function).""", file=self.stdout) (either in a function that is called or in the current function).""", file=self.stdout)
def help_until(self):
self.help_unt()
def help_unt(self):
print("""unt(il)
Continue execution until the line with a number greater than the current
one is reached or until the current frame returns""")
def help_next(self): def help_next(self):
self.help_n() self.help_n()

View File

@ -199,6 +199,14 @@ class BugsTestCase(unittest.TestCase):
subtyp = type('subtyp', (typ,), {}) subtyp = type('subtyp', (typ,), {})
self.assertRaises(ValueError, marshal.dumps, subtyp()) self.assertRaises(ValueError, marshal.dumps, subtyp())
# Issue #1792 introduced a change in how marshal increases the size of its
# internal buffer; this test ensures that the new code is exercised.
def test_large_marshal(self):
size = int(1e6)
testString = 'abc' * size
marshal.dumps(testString)
def test_main(): def test_main():
test_support.run_unittest(IntTestCase, test_support.run_unittest(IntTestCase,
FloatTestCase, FloatTestCase,

View File

@ -409,6 +409,39 @@ def catch_warning(module=warnings, record=True):
module.showwarning = original_showwarning module.showwarning = original_showwarning
module.filters = original_filters module.filters = original_filters
class CleanImport(object):
"""Context manager to force import to return a new module reference.
This is useful for testing module-level behaviours, such as
the emission of a DepreciationWarning on import.
Use like this:
with CleanImport("foo"):
__import__("foo") # new reference
"""
def __init__(self, *module_names):
self.original_modules = sys.modules.copy()
for module_name in module_names:
if module_name in sys.modules:
module = sys.modules[module_name]
# It is possible that module_name is just an alias for
# another module (e.g. stub for modules renamed in 3.x).
# In that case, we also need delete the real module to clear
# the import cache.
if module.__name__ != module_name:
del sys.modules[module.__name__]
del sys.modules[module_name]
def __enter__(self):
return self
def __exit__(self, *ignore_exc):
sys.modules.update(self.original_modules)
class EnvironmentVarGuard(object): class EnvironmentVarGuard(object):
"""Class to help protect the environment variable properly. Can be used as """Class to help protect the environment variable properly. Can be used as

View File

@ -351,6 +351,14 @@ What a mess!
["Hello", " ", "there", " ", "--", " ", "you", " ", "goof-", ["Hello", " ", "there", " ", "--", " ", "you", " ", "goof-",
"ball,", " ", "use", " ", "the", " ", "-b", " ", "option!"]) "ball,", " ", "use", " ", "the", " ", "-b", " ", "option!"])
def test_break_on_hyphens(self):
# Ensure that the break_on_hyphens attributes work
text = "yaba daba-doo"
self.check_wrap(text, 10, ["yaba daba-", "doo"],
break_on_hyphens=True)
self.check_wrap(text, 10, ["yaba", "daba-doo"],
break_on_hyphens=False)
def test_bad_width(self): def test_bad_width(self):
# Ensure that width <= 0 is caught. # Ensure that width <= 0 is caught.
text = "Whatever, it doesn't matter." text = "Whatever, it doesn't matter."

View File

@ -55,6 +55,10 @@ class TextWrapper:
break_long_words (default: true) break_long_words (default: true)
Break words longer than 'width'. If false, those words will not Break words longer than 'width'. If false, those words will not
be broken, and some lines might be longer than 'width'. be broken, and some lines might be longer than 'width'.
break_on_hyphens (default: true)
Allow breaking hyphenated words. If true, wrapping will occur
preferably on whitespaces and right after hyphens part of
compound words.
drop_whitespace (default: true) drop_whitespace (default: true)
Drop leading and trailing whitespace from lines. Drop leading and trailing whitespace from lines.
""" """
@ -75,11 +79,18 @@ class TextWrapper:
r'[^\s\w]*\w+[a-zA-Z]-(?=\w+[a-zA-Z])|' # hyphenated words r'[^\s\w]*\w+[a-zA-Z]-(?=\w+[a-zA-Z])|' # hyphenated words
r'(?<=[\w\!\"\'\&\.\,\?])-{2,}(?=\w))') # em-dash r'(?<=[\w\!\"\'\&\.\,\?])-{2,}(?=\w))') # em-dash
# XXX this is not locale-aware # This less funky little regex just split on recognized spaces. E.g.
# "Hello there -- you goof-ball, use the -b option!"
# splits into
# Hello/ /there/ /--/ /you/ /goof-ball,/ /use/ /the/ /-b/ /option!/
wordsep_simple_re = re.compile(r'(\s+)')
# XXX this is not locale- or charset-aware -- string.lowercase
# is US-ASCII only (and therefore English-only)
sentence_end_re = re.compile(r'[a-z]' # lowercase letter sentence_end_re = re.compile(r'[a-z]' # lowercase letter
r'[\.\!\?]' # sentence-ending punct. r'[\.\!\?]' # sentence-ending punct.
r'[\"\']?' # optional end-of-quote r'[\"\']?' # optional end-of-quote
r'\Z') # end of chunk r'\Z') # end of chunk
def __init__(self, def __init__(self,
@ -90,7 +101,8 @@ class TextWrapper:
replace_whitespace=True, replace_whitespace=True,
fix_sentence_endings=False, fix_sentence_endings=False,
break_long_words=True, break_long_words=True,
drop_whitespace=True): drop_whitespace=True,
break_on_hyphens=True):
self.width = width self.width = width
self.initial_indent = initial_indent self.initial_indent = initial_indent
self.subsequent_indent = subsequent_indent self.subsequent_indent = subsequent_indent
@ -99,6 +111,7 @@ class TextWrapper:
self.fix_sentence_endings = fix_sentence_endings self.fix_sentence_endings = fix_sentence_endings
self.break_long_words = break_long_words self.break_long_words = break_long_words
self.drop_whitespace = drop_whitespace self.drop_whitespace = drop_whitespace
self.break_on_hyphens = break_on_hyphens
# -- Private methods ----------------------------------------------- # -- Private methods -----------------------------------------------
@ -128,8 +141,15 @@ class TextWrapper:
breaks into the following chunks: breaks into the following chunks:
'Look,', ' ', 'goof-', 'ball', ' ', '--', ' ', 'Look,', ' ', 'goof-', 'ball', ' ', '--', ' ',
'use', ' ', 'the', ' ', '-b', ' ', 'option!' 'use', ' ', 'the', ' ', '-b', ' ', 'option!'
if break_on_hyphens is True, or in:
'Look,', ' ', 'goof-ball', ' ', '--', ' ',
'use', ' ', 'the', ' ', '-b', ' ', option!'
otherwise.
""" """
chunks = self.wordsep_re.split(text) if self.break_on_hyphens is True:
chunks = self.wordsep_re.split(text)
else:
chunks = self.wordsep_simple_re.split(text)
chunks = [c for c in chunks if c] chunks = [c for c in chunks if c]
return chunks return chunks

View File

@ -588,6 +588,7 @@ Nick Russo
Hajime Saitou Hajime Saitou
Rich Salz Rich Salz
Kevin Samborn Kevin Samborn
Ilya Sandler
Ty Sarna Ty Sarna
Ben Sayer Ben Sayer
Michael Scharf Michael Scharf
@ -757,3 +758,4 @@ Siebren van der Zee
Uwe Zessin Uwe Zessin
Amaury Forgeot d'Arc Amaury Forgeot d'Arc
Peter Åstrand Peter Åstrand
Tarek Ziad<61>

View File

@ -28,13 +28,15 @@ Extension Modules
Library Library
------- -------
- The ConfigParser module has been renamed to configparser. - #2659: Added ``break_on_hyphens`` option to textwrap TextWrapper class.
- Issue #2487: change the semantics of math.ldexp(x, n) when n is too - Issue #2487: change the semantics of math.ldexp(x, n) when n is too
large to fit in a C long. ldexp(x, n) now returns a zero (with large to fit in a C long. ldexp(x, n) now returns a zero (with
suitable sign) if n is large and negative; previously, it raised suitable sign) if n is large and negative; previously, it raised
OverflowError. OverflowError.
- The ConfigParser module has been renamed to configparser.
- Issue 2865: webbrowser.open() works again in a KDE environment. - Issue 2865: webbrowser.open() works again in a KDE environment.
- The multifile module has been removed. - The multifile module has been removed.
@ -71,6 +73,8 @@ Library
- os.path.walk has been removed in favor of os.walk - os.path.walk has been removed in favor of os.walk
- pdb gained the "until" command.
Build Build
----- -----

View File

@ -1134,8 +1134,8 @@ PyDoc_STRVAR(split__doc__,
"B.split([sep[, maxsplit]]) -> list of bytes\n\ "B.split([sep[, maxsplit]]) -> list of bytes\n\
\n\ \n\
Return a list of the sections in B, using sep as the delimiter.\n\ Return a list of the sections in B, using sep as the delimiter.\n\
If sep is not given, B is split on ASCII whitespace characters\n\ If sep is not specified or is None, B is split on ASCII whitespace\n\
(space, tab, return, newline, formfeed, vertical tab).\n\ characters (space, tab, return, newline, formfeed, vertical tab).\n\
If maxsplit is given, at most maxsplit splits are done."); If maxsplit is given, at most maxsplit splits are done.");
static PyObject * static PyObject *

View File

@ -7729,8 +7729,9 @@ PyDoc_STRVAR(split__doc__,
\n\ \n\
Return a list of the words in S, using sep as the\n\ Return a list of the words in S, using sep as the\n\
delimiter string. If maxsplit is given, at most maxsplit\n\ delimiter string. If maxsplit is given, at most maxsplit\n\
splits are done. If sep is not specified or is None,\n\ splits are done. If sep is not specified or is None, any\n\
any whitespace string is a separator."); whitespace string is a separator and leading and trailing\n\
whitespace is stripped before splitting.");
static PyObject* static PyObject*
unicode_split(PyUnicodeObject *self, PyObject *args) unicode_split(PyUnicodeObject *self, PyObject *args)

View File

@ -68,7 +68,10 @@ w_more(int c, WFILE *p)
if (p->str == NULL) if (p->str == NULL)
return; /* An error already occurred */ return; /* An error already occurred */
size = PyString_Size(p->str); size = PyString_Size(p->str);
newsize = size + 1024; newsize = size + size + 1024;
if (newsize > 32*1024*1024) {
newsize = size + 1024*1024;
}
if (_PyString_Resize(&p->str, newsize) != 0) { if (_PyString_Resize(&p->str, newsize) != 0) {
p->ptr = p->end = NULL; p->ptr = p->end = NULL;
} }