summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Doc/distutils/packageindex.rst31
-rw-r--r--Doc/distutils/uploading.rst12
-rw-r--r--Doc/library/bdb.rst5
-rw-r--r--Doc/library/ftplib.rst18
-rw-r--r--Doc/library/functions.rst45
-rw-r--r--Doc/library/httplib.rst16
-rw-r--r--Doc/library/pdb.rst6
-rw-r--r--Doc/library/smtplib.rst30
-rw-r--r--Doc/library/socket.rst10
-rw-r--r--Doc/library/socketserver.rst4
-rw-r--r--Doc/library/stdtypes.rst13
-rw-r--r--Doc/library/telnetlib.rst16
-rw-r--r--Doc/library/tempfile.rst5
-rw-r--r--Doc/library/textwrap.rst18
-rw-r--r--Doc/library/tk.rst3
-rw-r--r--Doc/library/urllib2.rst21
-rw-r--r--Doc/tutorial/modules.rst2
-rw-r--r--Lib/bdb.py33
-rw-r--r--Lib/distutils/command/register.py95
-rw-r--r--Lib/distutils/command/upload.py41
-rw-r--r--Lib/distutils/config.py4
-rw-r--r--Lib/distutils/core.py1
-rw-r--r--Lib/distutils/dist.py7
-rw-r--r--Lib/distutils/tests/test_config.py103
-rw-r--r--Lib/distutils/tests/test_dist.py46
-rw-r--r--Lib/distutils/tests/test_upload.py34
-rw-r--r--Lib/io.py12
-rw-r--r--Lib/pdb.doc4
-rwxr-xr-xLib/pdb.py13
-rw-r--r--Lib/test/test_marshal.py8
-rw-r--r--Lib/test/test_support.py33
-rw-r--r--Lib/test/test_textwrap.py8
-rw-r--r--Lib/textwrap.py28
-rw-r--r--Misc/ACKS2
-rw-r--r--Misc/NEWS6
-rw-r--r--Objects/stringobject.c4
-rw-r--r--Objects/unicodeobject.c5
-rw-r--r--Python/marshal.c5
38 files changed, 557 insertions, 190 deletions
diff --git a/Doc/distutils/packageindex.rst b/Doc/distutils/packageindex.rst
index 8242012..ef81d64 100644
--- a/Doc/distutils/packageindex.rst
+++ b/Doc/distutils/packageindex.rst
@@ -55,11 +55,40 @@ The .pypirc file
The format of the :file:`.pypirc` file is as follows::
- [server-login]
+ [distutils]
+ index-servers =
+ pypi
+
+ [pypi]
repository: <repository-url>
username: <username>
password: <password>
*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
+
diff --git a/Doc/distutils/uploading.rst b/Doc/distutils/uploading.rst
index 5be4130..d960656 100644
--- a/Doc/distutils/uploading.rst
+++ b/Doc/distutils/uploading.rst
@@ -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
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
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
which key to use for signing using the :option:`--identity=*name*` option.
-Other :command:`upload` options include :option:`--repository=*url*` (which
-lets you override the repository setting from :file:`$HOME/.pypirc`), and
+Other :command:`upload` options include :option:`--repository=*url*`
+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
server for help in debugging upload problems).
-
diff --git a/Doc/library/bdb.rst b/Doc/library/bdb.rst
index f04b671..fefb2ad 100644
--- a/Doc/library/bdb.rst
+++ b/Doc/library/bdb.rst
@@ -207,6 +207,11 @@ The :mod:`bdb` module also defines two classes:
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])
Start debugging from *frame*. If *frame* is not specified, debugging
diff --git a/Doc/library/ftplib.rst b/Doc/library/ftplib.rst
index 41bdcd8..99aae0d 100644
--- a/Doc/library/ftplib.rst
+++ b/Doc/library/ftplib.rst
@@ -40,11 +40,12 @@ The module defines the following items:
.. class:: FTP([host[, user[, passwd[, acct[, timeout]]]]])
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 ``login(user, passwd, acct)`` is made (where *passwd* and *acct*
- default to the empty string when not given). The optional *timeout* parameter
- specifies a timeout in seconds for the connection attempt (if is not specified,
- or passed as None, the global default timeout setting will be used).
+ method call ``connect(host)`` is made. When *user* is given, additionally
+ the method call ``login(user, passwd, acct)`` is made (where *passwd* and
+ *acct* default to the empty string when not given). The optional *timeout*
+ parameter specifies a timeout in seconds for blocking operations like the
+ connection attempt (if is not specified, or passed as None, the global
+ default timeout setting will be used).
.. attribute:: all_errors
@@ -122,9 +123,10 @@ followed by ``lines`` for the text version or ``binary`` for the binary version.
made.
The optional *timeout* parameter specifies a timeout in seconds for the
- connection attempt. If is not specified, or passed as None, the object timeout
- is used (the timeout that you passed when instantiating the class); if the
- object timeout is also None, the global default timeout setting will be used.
+ connection attempt. If is not specified, or passed as None, the object
+ timeout is used (the timeout that you passed when instantiating the class);
+ if the object timeout is also None, the global default timeout setting will
+ be used.
.. method:: FTP.getwelcome()
diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst
index 129aa3c..9ccc59c 100644
--- a/Doc/library/functions.rst
+++ b/Doc/library/functions.rst
@@ -848,10 +848,15 @@ are always available. They are listed here in alphabetical order.
use is to define a managed attribute x::
class C(object):
- def __init__(self): self._x = None
- def getx(self): return self._x
- def setx(self, value): self._x = value
- def delx(self): del self._x
+ def __init__(self):
+ self._x = None
+
+ 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.")
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."""
return self._voltage
- turns the :meth:`voltage` method into a "getter" for a read-only attribute with
- the same name.
+ turns the :meth:`voltage` method into a "getter" for a read-only attribute
+ 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
diff --git a/Doc/library/httplib.rst b/Doc/library/httplib.rst
index 03fe681..16b74ee 100644
--- a/Doc/library/httplib.rst
+++ b/Doc/library/httplib.rst
@@ -27,14 +27,14 @@ The module provides the following classes:
.. class:: HTTPConnection(host[, port[, strict[, timeout]]])
An :class:`HTTPConnection` instance represents one transaction with an HTTP
- server. It should be instantiated passing it a host and optional port number.
- If no port number is passed, the port is extracted from the host string if it
- has the form ``host:port``, else the default HTTP port (80) is used. When True,
- the optional parameter *strict* causes ``BadStatusLine`` to be raised if the
- status line can't be parsed as a valid HTTP/1.0 or 1.1 status line. If the
- optional *timeout* parameter is given, connection attempts will timeout after
- that many seconds (if it is not given or ``None``, the global default timeout
- setting is used).
+ server. It should be instantiated passing it a host and optional port
+ number. If no port number is passed, the port is extracted from the host
+ string if it has the form ``host:port``, else the default HTTP port (80) is
+ used. When True, the optional parameter *strict* causes ``BadStatusLine`` to
+ be raised if the status line can't be parsed as a valid HTTP/1.0 or 1.1
+ status line. If the optional *timeout* parameter is given, blocking
+ operations (like connection attempts) will timeout after that many seconds
+ (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
at the same host and port::
diff --git a/Doc/library/pdb.rst b/Doc/library/pdb.rst
index df8cf6c..ba6c1b5 100644
--- a/Doc/library/pdb.rst
+++ b/Doc/library/pdb.rst
@@ -261,6 +261,12 @@ n(ext)
inside a called function, while ``next`` executes called functions at (nearly)
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)
Continue execution until the current function returns.
diff --git a/Doc/library/smtplib.rst b/Doc/library/smtplib.rst
index d4dd43f..602edb6 100644
--- a/Doc/library/smtplib.rst
+++ b/Doc/library/smtplib.rst
@@ -19,13 +19,14 @@ Protocol) and :rfc:`1869` (SMTP Service Extensions).
.. class:: SMTP([host[, port[, local_hostname[, timeout]]]])
- A :class:`SMTP` instance encapsulates an SMTP connection. It has methods that
- support a full repertoire of SMTP and ESMTP operations. If the optional host and
- port parameters are given, the SMTP :meth:`connect` method is called with those
- parameters during initialization. An :exc:`SMTPConnectError` is raised if the
- specified host doesn't respond correctly. The optional *timeout* parameter
- specifies a timeout in seconds for the connection attempt (if not specified, or
- passed as None, the global default timeout setting will be used).
+ A :class:`SMTP` instance encapsulates an SMTP connection. It has methods
+ that support a full repertoire of SMTP and ESMTP operations. If the optional
+ host and port parameters are given, the SMTP :meth:`connect` method is called
+ with those parameters during initialization. An :exc:`SMTPConnectError` is
+ raised if the specified host doesn't respond correctly. The optional
+ *timeout* parameter specifies a timeout in seconds for blocking operations
+ 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,
: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
: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
- appropriate. If *host* is not specified, the local host is used. If *port* is
- omitted, the standard SMTP-over-SSL port (465) is used. *keyfile* and *certfile*
- are also optional, and can contain a PEM formatted private key and certificate
- chain file for the SSL connection. The optional *timeout* parameter specifies a
- timeout in seconds for the connection attempt (if not specified, or passed as
- None, the global default timeout setting will be used).
+ required from the beginning of the connection and using :meth:`starttls` is
+ not appropriate. If *host* is not specified, the local host is used. If
+ *port* is omitted, the standard SMTP-over-SSL port (465) is used. *keyfile*
+ and *certfile* are also optional, and can contain a PEM formatted private key
+ and certificate chain file for the SSL connection. The optional *timeout*
+ parameter specifies a timeout in seconds for blocking operations like the
+ connection attempt (if not specified, or passed as None, the global default
+ timeout setting will be used).
.. class:: LMTP([host[, port[, local_hostname]]])
diff --git a/Doc/library/socket.rst b/Doc/library/socket.rst
index d7164da..8fefce6 100644
--- a/Doc/library/socket.rst
+++ b/Doc/library/socket.rst
@@ -213,9 +213,9 @@ The module :mod:`socket` exports the following constants and functions:
service name (like ``'http'``), a numeric port number or ``None``.
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
- ``NULL`` to the C API. The :func:`getaddrinfo` function returns a list of
- 5-tuples with the following structure:
+ *host* and *port*, by passing ``None``, you can pass ``NULL`` to the C API.
+ The :func:`getaddrinfo` function returns a list of 5-tuples with the following
+ structure:
``(family, socktype, proto, canonname, sockaddr)``
@@ -785,7 +785,7 @@ sends traffic to the first one connected successfully. ::
import socket
import sys
- HOST = '' # Symbolic name meaning all available interfaces
+ HOST = None # Symbolic name meaning all available interfaces
PORT = 50007 # Arbitrary non-privileged port
s = None
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
-sockets on Windows. The example requires administrator priviliges to modify
+sockets on Windows. The example requires administrator privileges to modify
the interface::
import socket
diff --git a/Doc/library/socketserver.rst b/Doc/library/socketserver.rst
index b7ce818..e24b429 100644
--- a/Doc/library/socketserver.rst
+++ b/Doc/library/socketserver.rst
@@ -155,7 +155,7 @@ Server Objects
.. data:: address_family
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
@@ -199,7 +199,7 @@ The server classes support the following class variables:
.. data:: socket_type
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
diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst
index ce6aab3..09549ad 100644
--- a/Doc/library/stdtypes.rst
+++ b/Doc/library/stdtypes.rst
@@ -1114,7 +1114,7 @@ The conversion flag characters are:
+---------+---------------------------------------------------------------------+
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:
@@ -1125,13 +1125,13 @@ The conversion types are:
+------------+-----------------------------------------------------+-------+
| ``'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) |
+------------+-----------------------------------------------------+-------+
@@ -1193,6 +1193,9 @@ Notes:
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
that ``'\0'`` is the end of the string.
diff --git a/Doc/library/telnetlib.rst b/Doc/library/telnetlib.rst
index 4c8ce45..8c8ddbb 100644
--- a/Doc/library/telnetlib.rst
+++ b/Doc/library/telnetlib.rst
@@ -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
initially not connected by default; the :meth:`open` method must be used to
- establish a connection. Alternatively, the host name and optional port number
- can be passed to the constructor, to, in which case the connection to the server
- will be established before the constructor returns. The optional *timeout*
- parameter specifies a timeout in seconds for the connection attempt (if not
- specified, or passed as None, the global default timeout setting will be used).
+ establish a connection. Alternatively, the host name and optional port
+ number can be passed to the constructor, to, in which case the connection to
+ the server will be established before the constructor returns. The optional
+ *timeout* parameter specifies a timeout in seconds for blocking operations
+ 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.
@@ -121,8 +122,9 @@ Telnet Objects
Connect to a host. The optional second argument is the port number, which
defaults to the standard Telnet port (23). The optional *timeout* parameter
- specifies a timeout in seconds for the connection attempt (if not specified, or
- passed as None, the global default timeout setting will be used).
+ specifies a timeout in seconds for blocking operations like the connection
+ 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.
diff --git a/Doc/library/tempfile.rst b/Doc/library/tempfile.rst
index 25d5acb..69b05ce 100644
--- a/Doc/library/tempfile.rst
+++ b/Doc/library/tempfile.rst
@@ -156,11 +156,6 @@ The module defines the following user-callable functions:
: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
<open file '<fdopen>', mode 'w+b' at 0x384698>
>>> f.name
diff --git a/Doc/library/textwrap.rst b/Doc/library/textwrap.rst
index 243e43c..a18a801 100644
--- a/Doc/library/textwrap.rst
+++ b/Doc/library/textwrap.rst
@@ -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
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
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
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
module-level convenience functions:
-
.. method:: wrap(text)
Wraps the single paragraph in *text* (a string) so every line is at most
diff --git a/Doc/library/tk.rst b/Doc/library/tk.rst
index 3e2f100..8451f6d 100644
--- a/Doc/library/tk.rst
+++ b/Doc/library/tk.rst
@@ -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
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
libraries, see the :ref:`other-gui-packages` section.
diff --git a/Doc/library/urllib2.rst b/Doc/library/urllib2.rst
index 7987007..143fe50 100644
--- a/Doc/library/urllib2.rst
+++ b/Doc/library/urllib2.rst
@@ -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
returns a string in this format.
- The optional *timeout* parameter specifies a timeout in seconds for the
- connection attempt (if not specified, or passed as None, the global default
- timeout setting will be used). This actually only work for HTTP, HTTPS, FTP and
- FTPS connections.
+ The optional *timeout* parameter specifies a timeout in seconds for blocking
+ operations like the connection attempt (if not specified, or passed as
+ ``None``, the global default timeout setting will be used). This actually
+ only works for HTTP, HTTPS, FTP and FTPS connections.
This function returns a file-like object with two additional methods:
@@ -399,12 +399,13 @@ OpenerDirector Objects
.. method:: OpenerDirector.open(url[, data][, timeout])
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
- same as those of :func:`urlopen` (which simply calls the :meth:`open` method on
- the currently installed global :class:`OpenerDirector`). The optional *timeout*
- parameter specifies a timeout in seconds for the connection attempt (if not
- specified, or passed as None, the global default timeout setting will be used;
- this actually only work for HTTP, HTTPS, FTP and FTPS connections).
+ passing the given *data*. Arguments, return values and exceptions raised are
+ the same as those of :func:`urlopen` (which simply calls the :meth:`open`
+ method on the currently installed global :class:`OpenerDirector`). The
+ optional *timeout* parameter specifies a timeout in seconds for blocking
+ operations like the connection attempt (if not specified, or passed as
+ ``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[, ...]])
diff --git a/Doc/tutorial/modules.rst b/Doc/tutorial/modules.rst
index 4d06df2..68e0258 100644
--- a/Doc/tutorial/modules.rst
+++ b/Doc/tutorial/modules.rst
@@ -111,7 +111,7 @@ you have already defined.
For efficiency reasons, each module is only imported once per interpreter
session. Therefore, if you change your modules, you must restart the
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:
diff --git a/Lib/bdb.py b/Lib/bdb.py
index e55031e..b8a20ec 100644
--- a/Lib/bdb.py
+++ b/Lib/bdb.py
@@ -37,9 +37,7 @@ class Bdb:
import linecache
linecache.checkcache()
self.botframe = None
- self.stopframe = None
- self.returnframe = None
- self.quitting = 0
+ self._set_stopinfo(None, None)
def trace_dispatch(self, frame, event, arg):
if self.quitting:
@@ -100,7 +98,7 @@ class Bdb:
# (CT) stopframe may now also be None, see dispatch_call.
# (CT) the former test for None is therefore removed from here.
if frame is self.stopframe:
- return True
+ return frame.f_lineno >= self.stoplineno
while frame is not None and frame is not self.stopframe:
if frame is self.botframe:
return True
@@ -156,26 +154,31 @@ class Bdb:
but only if we are to stop at or just below this level."""
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
# 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):
"""Stop after one line of code."""
- self.stopframe = None
- self.returnframe = None
- self.quitting = 0
+ self._set_stopinfo(None,None)
def set_next(self, frame):
"""Stop on the next line in or below the given frame."""
- self.stopframe = frame
- self.returnframe = None
- self.quitting = 0
+ self._set_stopinfo(frame, None)
def set_return(self, frame):
"""Stop when returning from the given frame."""
- self.stopframe = frame.f_back
- self.returnframe = frame
- self.quitting = 0
+ self._set_stopinfo(frame.f_back, frame)
def set_trace(self, frame=None):
"""Start debugging from `frame`.
@@ -194,9 +197,7 @@ class Bdb:
def set_continue(self):
# Don't stop except at breakpoints or when finished
- self.stopframe = self.botframe
- self.returnframe = None
- self.quitting = 0
+ self._set_stopinfo(self.botframe, None)
if not self.breaks:
# no breakpoints; run without debugger overhead
sys.settrace(None)
diff --git a/Lib/distutils/command/register.py b/Lib/distutils/command/register.py
index b6a36f5..89cb2d4 100644
--- a/Lib/distutils/command/register.py
+++ b/Lib/distutils/command/register.py
@@ -8,42 +8,34 @@ Implements the Distutils 'register' command (register with the repository).
__revision__ = "$Id$"
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 import log
def raw_input(prompt):
sys.stdout.write(prompt)
sys.stdout.flush()
return sys.stdin.readline()
-class register(Command):
+class register(PyPIRCCommand):
description = ("register the distribution with the Python package index")
-
- DEFAULT_REPOSITORY = 'http://pypi.python.org/pypi'
-
- user_options = [
- ('repository=', 'r',
- "url of repository [default: %s]"%DEFAULT_REPOSITORY),
+ user_options = PyPIRCCommand.user_options + [
('list-classifiers', None,
'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):
- self.repository = None
- self.show_response = 0
+ PyPIRCCommand.initialize_options(self)
self.list_classifiers = 0
- def finalize_options(self):
- if self.repository is None:
- self.repository = self.DEFAULT_REPOSITORY
-
def run(self):
+ self.finalize_options()
+ self._set_config()
self.check_metadata()
if self.dry_run:
self.verify_metadata()
@@ -82,6 +74,23 @@ class register(Command):
"or (maintainer and maintainer_email) " +
"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):
''' 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'))
print('Server response (%s): %s'%(code, result))
+
def send_metadata(self):
''' 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,
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:
- [server-login]
+ [distutils]
+ index-servers =
+ pypi
+
+ [pypi]
username: fred
password: sekrit
@@ -119,21 +133,15 @@ class register(Command):
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
# config
- config = None
- if 'HOME' in os.environ:
- rc = os.path.join(os.environ['HOME'], '.pypirc')
- if os.path.exists(rc):
- print('Using PyPI login from %s'%rc)
- config = ConfigParser.ConfigParser()
- config.read(rc)
- username = config.get('server-login', 'username')
- password = config.get('server-login', 'password')
- choice = '1'
+ if self.has_config:
+ choice = '1'
+ username = self.username
+ password = self.password
+ else:
+ choice = 'x'
+ username = password = ''
# get the user's login info
choices = '1 2 3 4'.split()
@@ -160,32 +168,24 @@ Your selection [default 1]: ''', end=' ')
# set up the authentication
auth = urllib2.HTTPPasswordMgr()
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
code, result = self.post_to_server(self.build_post_data('submit'),
auth)
print('Server response (%s): %s'%(code, result))
# possibly save the login
- if 'HOME' in os.environ and config is None and code == 200:
- rc = os.path.join(os.environ['HOME'], '.pypirc')
+ if not self.has_config and code == 200:
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'
while choice.lower() not in 'yn':
choice = raw_input('Save your login (y/N)?')
if not choice:
choice = 'n'
if choice.lower() == 'y':
- f = open(rc, 'w')
- f.write('[server-login]\nusername:%s\npassword:%s\n'%(
- username, password))
- f.close()
- try:
- os.chmod(rc, 0o600)
- except:
- pass
+ self._store_pypirc(username, password)
+
elif choice == '2':
data = {':action': 'user'}
data['name'] = data['password'] = data['email'] = ''
@@ -248,7 +248,8 @@ Your selection [default 1]: ''', end=' ')
def post_to_server(self, data, auth=None):
''' 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
boundary = '--------------GHSKFJDLGDS7543FJKLFHRE75642756743254'
sep_boundary = '\n--' + boundary
diff --git a/Lib/distutils/command/upload.py b/Lib/distutils/command/upload.py
index 23999ae..603336c 100644
--- a/Lib/distutils/command/upload.py
+++ b/Lib/distutils/command/upload.py
@@ -3,7 +3,7 @@
Implements the Distutils 'upload' subcommand (upload package to PyPI)."""
from distutils.errors import *
-from distutils.core import Command
+from distutils.core import PyPIRCCommand
from distutils.spawn import spawn
from distutils import log
from hashlib import md5
@@ -15,53 +15,38 @@ import httplib
import base64
import urlparse
-class upload(Command):
+class upload(PyPIRCCommand):
description = "upload binary package to PyPI"
- DEFAULT_REPOSITORY = 'http://pypi.python.org/pypi'
-
- user_options = [
- ('repository=', 'r',
- "url of repository [default: %s]" % DEFAULT_REPOSITORY),
- ('show-response', None,
- 'display full response text from server'),
+ user_options = PyPIRCCommand.user_options + [
('sign', 's',
'sign files to upload using gpg'),
('identity=', 'i', 'GPG identity used to sign files'),
]
- boolean_options = ['show-response', 'sign']
+
+ boolean_options = PyPIRCCommand.boolean_options + ['sign']
def initialize_options(self):
+ PyPIRCCommand.initialize_options(self)
self.username = ''
self.password = ''
- self.repository = ''
self.show_response = 0
self.sign = False
self.identity = None
def finalize_options(self):
+ PyPIRCCommand.finalize_options(self)
if self.identity and not self.sign:
raise DistutilsOptionError(
"Must use --sign for --identity to have meaning"
)
- if 'HOME' in os.environ:
- rc = os.path.join(os.environ['HOME'], '.pypirc')
- if os.path.exists(rc):
- self.announce('Using PyPI login from %s' % rc)
- config = ConfigParser.ConfigParser({
- 'username':'',
- '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
+ config = self._read_pypirc()
+ if config != {}:
+ self.username = config['username']
+ self.password = config['password']
+ self.repository = config['repository']
+ self.realm = config['realm']
def run(self):
if not self.distribution.dist_files:
diff --git a/Lib/distutils/config.py b/Lib/distutils/config.py
index e9ba402..a625aec 100644
--- a/Lib/distutils/config.py
+++ b/Lib/distutils/config.py
@@ -49,7 +49,7 @@ class PyPIRCCommand(Command):
finally:
f.close()
try:
- os.chmod(rc, 0600)
+ os.chmod(rc, 0o600)
except OSError:
# should do something better here
pass
@@ -58,7 +58,7 @@ class PyPIRCCommand(Command):
"""Reads the .pypirc file."""
rc = self._get_rc_file()
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
realm = self.realm or self.DEFAULT_REALM
diff --git a/Lib/distutils/core.py b/Lib/distutils/core.py
index a4c5e18..6e48920 100644
--- a/Lib/distutils/core.py
+++ b/Lib/distutils/core.py
@@ -17,6 +17,7 @@ from distutils.util import grok_environment_error
# Mainly import these so setup scripts can "from distutils.core import" them.
from distutils.dist import Distribution
from distutils.cmd import Command
+from distutils.config import PyPIRCCommand
from distutils.extension import Extension
# This is a barebones help message generated displayed when the user
diff --git a/Lib/distutils/dist.py b/Lib/distutils/dist.py
index 847eb90..ddde909 100644
--- a/Lib/distutils/dist.py
+++ b/Lib/distutils/dist.py
@@ -334,10 +334,9 @@ Common commands: (see '--help-commands' for more)
user_filename = "pydistutils.cfg"
# And look for the user config file
- if 'HOME' in os.environ:
- user_file = os.path.join(os.environ.get('HOME'), user_filename)
- if os.path.isfile(user_file):
- files.append(user_file)
+ user_file = os.path.join(os.path.expanduser('~'), user_filename)
+ if os.path.isfile(user_file):
+ files.append(user_file)
# All platforms support local setup.cfg
local_file = "setup.cfg"
diff --git a/Lib/distutils/tests/test_config.py b/Lib/distutils/tests/test_config.py
new file mode 100644
index 0000000..016ba4c
--- /dev/null
+++ b/Lib/distutils/tests/test_config.py
@@ -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")
diff --git a/Lib/distutils/tests/test_dist.py b/Lib/distutils/tests/test_dist.py
index 91acf45..81459ac 100644
--- a/Lib/distutils/tests/test_dist.py
+++ b/Lib/distutils/tests/test_dist.py
@@ -55,6 +55,7 @@ class DistributionTestCase(unittest.TestCase):
self.assertEqual(d.get_command_packages(), ["distutils.command"])
def test_command_packages_cmdline(self):
+ from distutils.tests.test_dist import test_dist
sys.argv.extend(["--command-packages",
"foo.bar,distutils.tests",
"test_dist",
@@ -179,9 +180,54 @@ class MetadataTestCase(unittest.TestCase):
dist.metadata.write_pkg_file(sio)
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():
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(DistributionTestCase))
suite.addTest(unittest.makeSuite(MetadataTestCase))
return suite
+
+if __name__ == "__main__":
+ unittest.main(defaultTest="test_suite")
diff --git a/Lib/distutils/tests/test_upload.py b/Lib/distutils/tests/test_upload.py
new file mode 100644
index 0000000..b05ab1f
--- /dev/null
+++ b/Lib/distutils/tests/test_upload.py
@@ -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")
diff --git a/Lib/io.py b/Lib/io.py
index d5c8dfe..207e428 100644
--- a/Lib/io.py
+++ b/Lib/io.py
@@ -813,14 +813,14 @@ class _BytesIO(BufferedIOBase):
n = len(b)
if n == 0:
return 0
- newpos = self._pos + n
- if newpos > len(self._buffer):
+ pos = self._pos
+ if pos > len(self._buffer):
# Inserts null bytes between the current end of the file
# and the new write position.
- padding = b'\x00' * (newpos - len(self._buffer) - n)
- self._buffer[self._pos:newpos - n] = padding
- self._buffer[self._pos:newpos] = b
- self._pos = newpos
+ padding = b'\x00' * (pos - len(self._buffer))
+ self._buffer += padding
+ self._buffer[pos:pos + n] = b
+ self._pos += n
return n
def seek(self, pos, whence=0):
diff --git a/Lib/pdb.doc b/Lib/pdb.doc
index c513954..0d32800 100644
--- a/Lib/pdb.doc
+++ b/Lib/pdb.doc
@@ -128,6 +128,10 @@ n(ext)
Continue execution until the next line in the current function
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)
Continue execution until the current function returns.
diff --git a/Lib/pdb.py b/Lib/pdb.py
index d77ea28..7e1edb5 100755
--- a/Lib/pdb.py
+++ b/Lib/pdb.py
@@ -611,6 +611,11 @@ class Pdb(bdb.Bdb, cmd.Cmd):
self.lineno = None
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):
self.set_step()
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
(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):
self.help_n()
diff --git a/Lib/test/test_marshal.py b/Lib/test/test_marshal.py
index 66545e0..838207a 100644
--- a/Lib/test/test_marshal.py
+++ b/Lib/test/test_marshal.py
@@ -199,6 +199,14 @@ class BugsTestCase(unittest.TestCase):
subtyp = type('subtyp', (typ,), {})
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():
test_support.run_unittest(IntTestCase,
FloatTestCase,
diff --git a/Lib/test/test_support.py b/Lib/test/test_support.py
index 27a01ea..c4084bb 100644
--- a/Lib/test/test_support.py
+++ b/Lib/test/test_support.py
@@ -409,6 +409,39 @@ def catch_warning(module=warnings, record=True):
module.showwarning = original_showwarning
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 to help protect the environment variable properly. Can be used as
diff --git a/Lib/test/test_textwrap.py b/Lib/test/test_textwrap.py
index dc97d40..1a9761a 100644
--- a/Lib/test/test_textwrap.py
+++ b/Lib/test/test_textwrap.py
@@ -351,6 +351,14 @@ What a mess!
["Hello", " ", "there", " ", "--", " ", "you", " ", "goof-",
"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):
# Ensure that width <= 0 is caught.
text = "Whatever, it doesn't matter."
diff --git a/Lib/textwrap.py b/Lib/textwrap.py
index b5f87efc..6a2021d 100644
--- a/Lib/textwrap.py
+++ b/Lib/textwrap.py
@@ -55,6 +55,10 @@ class TextWrapper:
break_long_words (default: true)
Break words longer than 'width'. If false, those words will not
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 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'(?<=[\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
r'[\.\!\?]' # sentence-ending punct.
r'[\"\']?' # optional end-of-quote
- r'\Z') # end of chunk
+ r'\Z') # end of chunk
def __init__(self,
@@ -90,7 +101,8 @@ class TextWrapper:
replace_whitespace=True,
fix_sentence_endings=False,
break_long_words=True,
- drop_whitespace=True):
+ drop_whitespace=True,
+ break_on_hyphens=True):
self.width = width
self.initial_indent = initial_indent
self.subsequent_indent = subsequent_indent
@@ -99,6 +111,7 @@ class TextWrapper:
self.fix_sentence_endings = fix_sentence_endings
self.break_long_words = break_long_words
self.drop_whitespace = drop_whitespace
+ self.break_on_hyphens = break_on_hyphens
# -- Private methods -----------------------------------------------
@@ -128,8 +141,15 @@ class TextWrapper:
breaks into the following chunks:
'Look,', ' ', 'goof-', 'ball', ' ', '--', ' ',
'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]
return chunks
diff --git a/Misc/ACKS b/Misc/ACKS
index 4aa0101..19210a0 100644
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -588,6 +588,7 @@ Nick Russo
Hajime Saitou
Rich Salz
Kevin Samborn
+Ilya Sandler
Ty Sarna
Ben Sayer
Michael Scharf
@@ -757,3 +758,4 @@ Siebren van der Zee
Uwe Zessin
Amaury Forgeot d'Arc
Peter Åstrand
+Tarek ZiadŽ
diff --git a/Misc/NEWS b/Misc/NEWS
index 31b2678..3208a69 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -28,13 +28,15 @@ Extension Modules
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
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
OverflowError.
+- The ConfigParser module has been renamed to configparser.
+
- Issue 2865: webbrowser.open() works again in a KDE environment.
- The multifile module has been removed.
@@ -71,6 +73,8 @@ Library
- os.path.walk has been removed in favor of os.walk
+- pdb gained the "until" command.
+
Build
-----
diff --git a/Objects/stringobject.c b/Objects/stringobject.c
index 3aee28e..0cc48c3 100644
--- a/Objects/stringobject.c
+++ b/Objects/stringobject.c
@@ -1134,8 +1134,8 @@ PyDoc_STRVAR(split__doc__,
"B.split([sep[, maxsplit]]) -> list of bytes\n\
\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\
-(space, tab, return, newline, formfeed, vertical tab).\n\
+If sep is not specified or is None, B is split on ASCII whitespace\n\
+characters (space, tab, return, newline, formfeed, vertical tab).\n\
If maxsplit is given, at most maxsplit splits are done.");
static PyObject *
diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c
index 08e832f..9ea9a88 100644
--- a/Objects/unicodeobject.c
+++ b/Objects/unicodeobject.c
@@ -7729,8 +7729,9 @@ PyDoc_STRVAR(split__doc__,
\n\
Return a list of the words in S, using sep as the\n\
delimiter string. If maxsplit is given, at most maxsplit\n\
-splits are done. If sep is not specified or is None,\n\
-any whitespace string is a separator.");
+splits are done. If sep is not specified or is None, any\n\
+whitespace string is a separator and leading and trailing\n\
+whitespace is stripped before splitting.");
static PyObject*
unicode_split(PyUnicodeObject *self, PyObject *args)
diff --git a/Python/marshal.c b/Python/marshal.c
index 22f84a8..ce828da 100644
--- a/Python/marshal.c
+++ b/Python/marshal.c
@@ -68,7 +68,10 @@ w_more(int c, WFILE *p)
if (p->str == NULL)
return; /* An error already occurred */
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) {
p->ptr = p->end = NULL;
}