Merged revisions 60481,60485,60489-60492,60494-60496,60498-60499,60501-60503,60505-60506,60508-60509,60523-60524,60532,60543,60545,60547-60548,60552,60554,60556-60559,60561-60562,60569,60571-60572,60574,60576-60583,60585-60586,60589,60591,60594-60595,60597-60598,60600-60601,60606-60612,60615,60617,60619-60621,60623-60625,60627-60629,60631,60633,60635,60647,60650,60652,60654,60656,60658-60659,60664-60666,60668-60670,60672,60676,60678,60680-60683,60685-60686,60688,60690,60692-60694,60697-60700,60705-60706,60708,60711,60714,60720,60724-60730,60732,60736,60742,60744,60746,60748,60750-60751,60753,60756-60757,60759-60761,60763-60764,60766,60769-60770,60774-60784,60787-60789,60793,60796,60799-60809,60812-60813,60815-60821,60823-60826,60828-60829,60831-60834,60836,60838-60839,60846-60849,60852-60854,60856-60859,60861-60870,60874-60875,60880-60881,60886,60888-60890,60892,60894-60898,60900-60931,60933-60958 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk ........ r60901 | eric.smith | 2008-02-19 14:21:56 +0100 (Tue, 19 Feb 2008) | 1 line Added PEP 3101. ........ r60907 | georg.brandl | 2008-02-20 20:12:36 +0100 (Wed, 20 Feb 2008) | 2 lines Fixes contributed by Ori Avtalion. ........ r60909 | eric.smith | 2008-02-21 00:34:22 +0100 (Thu, 21 Feb 2008) | 1 line Trim leading zeros from a floating point exponent, per C99. See issue 1600. As far as I know, this only affects Windows. Add float type 'n' to PyOS_ascii_formatd (see PEP 3101 for 'n' description). ........ r60910 | eric.smith | 2008-02-21 00:39:28 +0100 (Thu, 21 Feb 2008) | 1 line Now that PyOS_ascii_formatd supports the 'n' format, simplify the float formatting code to just call it. ........ r60918 | andrew.kuchling | 2008-02-21 15:23:38 +0100 (Thu, 21 Feb 2008) | 2 lines Close manifest file. This change doesn't make any difference to CPython, but is a necessary fix for Jython. ........ r60921 | guido.van.rossum | 2008-02-21 18:46:16 +0100 (Thu, 21 Feb 2008) | 2 lines Remove news about float repr() -- issue 1580 is still in limbo. ........ r60923 | guido.van.rossum | 2008-02-21 19:18:37 +0100 (Thu, 21 Feb 2008) | 5 lines Removed uses of dict.has_key() from distutils, and uses of callable() from copy_reg.py, so the interpreter now starts up without warnings when '-3' is given. More work like this needs to be done in the rest of the stdlib. ........ r60924 | thomas.heller | 2008-02-21 19:28:48 +0100 (Thu, 21 Feb 2008) | 4 lines configure.ac: Remove the configure check for _Bool, it is already done in the top-level Python configure script. configure, fficonfig.h.in: regenerated. ........ r60925 | thomas.heller | 2008-02-21 19:52:20 +0100 (Thu, 21 Feb 2008) | 3 lines Replace 'has_key()' with 'in'. Replace 'raise Error, stuff' with 'raise Error(stuff)'. ........ r60927 | raymond.hettinger | 2008-02-21 20:24:53 +0100 (Thu, 21 Feb 2008) | 1 line Update more instances of has_key(). ........ r60928 | guido.van.rossum | 2008-02-21 20:46:35 +0100 (Thu, 21 Feb 2008) | 3 lines Fix a few typos and layout glitches (more work is needed). Move 2.5 news to Misc/HISTORY. ........ r60936 | georg.brandl | 2008-02-21 21:33:38 +0100 (Thu, 21 Feb 2008) | 2 lines #2079: typo in userdict docs. ........ r60938 | georg.brandl | 2008-02-21 21:38:13 +0100 (Thu, 21 Feb 2008) | 2 lines Part of #2154: minimal syntax fixes in doc example snippets. ........ r60942 | raymond.hettinger | 2008-02-22 04:16:42 +0100 (Fri, 22 Feb 2008) | 1 line First draft for itertools.product(). Docs and other updates forthcoming. ........ r60955 | nick.coghlan | 2008-02-22 11:54:06 +0100 (Fri, 22 Feb 2008) | 1 line Try to make command line error messages from runpy easier to understand (and suppress traceback cruft from the implicitly invoked runpy machinery) ........ r60956 | georg.brandl | 2008-02-22 13:31:45 +0100 (Fri, 22 Feb 2008) | 2 lines A lot more typo fixes by Ori Avtalion. ........ r60957 | georg.brandl | 2008-02-22 13:56:34 +0100 (Fri, 22 Feb 2008) | 2 lines Don't reference pyshell. ........ r60958 | georg.brandl | 2008-02-22 13:57:05 +0100 (Fri, 22 Feb 2008) | 2 lines Another fix. ........
This commit is contained in:
parent
86bc17944f
commit
c3f30c4337
|
@ -190,7 +190,7 @@ All integers are implemented as "long" integer objects of arbitrary size.
|
||||||
|
|
||||||
.. cfunction:: void* PyLong_AsVoidPtr(PyObject *pylong)
|
.. cfunction:: void* PyLong_AsVoidPtr(PyObject *pylong)
|
||||||
|
|
||||||
Convert a Python integer *pylong* to a C :ctype:`void` pointer. If *pylong*
|
Convert a Python integer *pylong* to a C :ctype:`void` pointer.
|
||||||
cannot be converted, an :exc:`OverflowError` will be raised. This is only
|
If *pylong* cannot be converted, an :exc:`OverflowError` will be raised. This
|
||||||
assured to produce a usable :ctype:`void` pointer for values created with
|
is only assured to produce a usable :ctype:`void` pointer for values created
|
||||||
:cfunc:`PyLong_FromVoidPtr`.
|
with :cfunc:`PyLong_FromVoidPtr`.
|
||||||
|
|
|
@ -8,7 +8,7 @@ Buffer Protocol
|
||||||
|
|
||||||
.. cfunction:: int PyObject_AsCharBuffer(PyObject *obj, const char **buffer, Py_ssize_t *buffer_len)
|
.. cfunction:: int PyObject_AsCharBuffer(PyObject *obj, const char **buffer, Py_ssize_t *buffer_len)
|
||||||
|
|
||||||
Returns a pointer to a read-only memory location useable as character- based
|
Returns a pointer to a read-only memory location usable as character-based
|
||||||
input. The *obj* argument must support the single-segment character buffer
|
input. The *obj* argument must support the single-segment character buffer
|
||||||
interface. On success, returns ``0``, sets *buffer* to the memory location and
|
interface. On success, returns ``0``, sets *buffer* to the memory location and
|
||||||
*buffer_len* to the buffer length. Returns ``-1`` and sets a :exc:`TypeError`
|
*buffer_len* to the buffer length. Returns ``-1`` and sets a :exc:`TypeError`
|
||||||
|
|
|
@ -560,7 +560,7 @@ The following three fields only exist if the
|
||||||
The :attr:`tp_traverse` pointer is used by the garbage collector to detect
|
The :attr:`tp_traverse` pointer is used by the garbage collector to detect
|
||||||
reference cycles. A typical implementation of a :attr:`tp_traverse` function
|
reference cycles. A typical implementation of a :attr:`tp_traverse` function
|
||||||
simply calls :cfunc:`Py_VISIT` on each of the instance's members that are Python
|
simply calls :cfunc:`Py_VISIT` on each of the instance's members that are Python
|
||||||
objects. For exampe, this is function :cfunc:`local_traverse` from the
|
objects. For example, this is function :cfunc:`local_traverse` from the
|
||||||
:mod:`thread` extension module::
|
:mod:`thread` extension module::
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|
|
@ -195,7 +195,7 @@ Distutils configuration files. Various options and sections in the
|
||||||
| | or --- & :option:`maintainer` and |
|
| | or --- & :option:`maintainer` and |
|
||||||
| | :option:`maintainer_email` |
|
| | :option:`maintainer_email` |
|
||||||
+------------------------------------------+----------------------------------------------+
|
+------------------------------------------+----------------------------------------------+
|
||||||
| Copyright | :option:`licence` |
|
| Copyright | :option:`license` |
|
||||||
+------------------------------------------+----------------------------------------------+
|
+------------------------------------------+----------------------------------------------+
|
||||||
| Url | :option:`url` |
|
| Url | :option:`url` |
|
||||||
+------------------------------------------+----------------------------------------------+
|
+------------------------------------------+----------------------------------------------+
|
||||||
|
|
|
@ -53,13 +53,13 @@ the web interface.
|
||||||
The .pypirc file
|
The .pypirc file
|
||||||
================
|
================
|
||||||
|
|
||||||
The format of the :file:`.pypirc` file is formated as follows::
|
The format of the :file:`.pypirc` file is as follows::
|
||||||
|
|
||||||
[server-login]
|
[server-login]
|
||||||
repository: <repository-url>
|
repository: <repository-url>
|
||||||
username: <username>
|
username: <username>
|
||||||
password: <password>
|
password: <password>
|
||||||
|
|
||||||
*repository* can be ommitted and defaults to ``http://www.python.org/pypi``.
|
*repository* can be omitted and defaults to ``http://www.python.org/pypi``.
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -185,7 +185,7 @@ If you have a number of extensions all in the same package (or all under the
|
||||||
same base package), use the :option:`ext_package` keyword argument to
|
same base package), use the :option:`ext_package` keyword argument to
|
||||||
:func:`setup`. For example, ::
|
:func:`setup`. For example, ::
|
||||||
|
|
||||||
setup(...
|
setup(...,
|
||||||
ext_package='pkg',
|
ext_package='pkg',
|
||||||
ext_modules=[Extension('foo', ['foo.c']),
|
ext_modules=[Extension('foo', ['foo.c']),
|
||||||
Extension('subpkg.bar', ['bar.c'])],
|
Extension('subpkg.bar', ['bar.c'])],
|
||||||
|
@ -214,7 +214,7 @@ extension.
|
||||||
This warning notwithstanding, options to SWIG can be currently passed like
|
This warning notwithstanding, options to SWIG can be currently passed like
|
||||||
this::
|
this::
|
||||||
|
|
||||||
setup(...
|
setup(...,
|
||||||
ext_modules=[Extension('_foo', ['foo.i'],
|
ext_modules=[Extension('_foo', ['foo.i'],
|
||||||
swig_opts=['-modern', '-I../include'])],
|
swig_opts=['-modern', '-I../include'])],
|
||||||
py_modules=['foo'],
|
py_modules=['foo'],
|
||||||
|
@ -443,7 +443,7 @@ option will allow the interpreter path to be explicitly overridden.
|
||||||
The :option:`scripts` option simply is a list of files to be handled in this
|
The :option:`scripts` option simply is a list of files to be handled in this
|
||||||
way. From the PyXML setup script::
|
way. From the PyXML setup script::
|
||||||
|
|
||||||
setup(...
|
setup(...,
|
||||||
scripts=['scripts/xmlproc_parse', 'scripts/xmlproc_val']
|
scripts=['scripts/xmlproc_parse', 'scripts/xmlproc_val']
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -499,7 +499,7 @@ anything which doesn't fit in the previous categories.
|
||||||
:option:`data_files` specifies a sequence of (*directory*, *files*) pairs in the
|
:option:`data_files` specifies a sequence of (*directory*, *files*) pairs in the
|
||||||
following way::
|
following way::
|
||||||
|
|
||||||
setup(...
|
setup(...,
|
||||||
data_files=[('bitmaps', ['bm/b1.gif', 'bm/b2.gif']),
|
data_files=[('bitmaps', ['bm/b1.gif', 'bm/b2.gif']),
|
||||||
('config', ['cfg/data.cfg']),
|
('config', ['cfg/data.cfg']),
|
||||||
('/etc/init.d', ['init-script'])]
|
('/etc/init.d', ['init-script'])]
|
||||||
|
@ -611,7 +611,7 @@ information is sometimes used to indicate sub-releases. These are
|
||||||
|
|
||||||
:option:`classifiers` are specified in a python list::
|
:option:`classifiers` are specified in a python list::
|
||||||
|
|
||||||
setup(...
|
setup(...,
|
||||||
classifiers=[
|
classifiers=[
|
||||||
'Development Status :: 4 - Beta',
|
'Development Status :: 4 - Beta',
|
||||||
'Environment :: Console',
|
'Environment :: Console',
|
||||||
|
|
|
@ -276,7 +276,7 @@ language, but it boils down to three conditions:
|
||||||
product in any way.
|
product in any way.
|
||||||
|
|
||||||
* If something goes wrong, you can't sue for damages. Practically all software
|
* If something goes wrong, you can't sue for damages. Practically all software
|
||||||
licences contain this condition.
|
licenses contain this condition.
|
||||||
|
|
||||||
Notice that you don't have to provide source code for anything that contains
|
Notice that you don't have to provide source code for anything that contains
|
||||||
Python or is built with it. Also, the Python interpreter and accompanying
|
Python or is built with it. Also, the Python interpreter and accompanying
|
||||||
|
|
|
@ -81,7 +81,7 @@ from module import name1, name2
|
||||||
This is a "don't" which is much weaker then the previous "don't"s but is still
|
This is a "don't" which is much weaker then the previous "don't"s but is still
|
||||||
something you should not do if you don't have good reasons to do that. The
|
something you should not do if you don't have good reasons to do that. The
|
||||||
reason it is usually bad idea is because you suddenly have an object which lives
|
reason it is usually bad idea is because you suddenly have an object which lives
|
||||||
in two seperate namespaces. When the binding in one namespace changes, the
|
in two separate namespaces. When the binding in one namespace changes, the
|
||||||
binding in the other will not, so there will be a discrepancy between them. This
|
binding in the other will not, so there will be a discrepancy between them. This
|
||||||
happens when, for example, one module is reloaded, or changes the definition of
|
happens when, for example, one module is reloaded, or changes the definition of
|
||||||
a function at runtime.
|
a function at runtime.
|
||||||
|
|
|
@ -892,7 +892,7 @@ returns them in a tuple::
|
||||||
itertools.izip(['a', 'b', 'c'], (1, 2, 3)) =>
|
itertools.izip(['a', 'b', 'c'], (1, 2, 3)) =>
|
||||||
('a', 1), ('b', 2), ('c', 3)
|
('a', 1), ('b', 2), ('c', 3)
|
||||||
|
|
||||||
It's similiar to the built-in :func:`zip` function, but doesn't construct an
|
It's similar to the built-in :func:`zip` function, but doesn't construct an
|
||||||
in-memory list and exhaust all the input iterators before returning; instead
|
in-memory list and exhaust all the input iterators before returning; instead
|
||||||
tuples are constructed and returned only if they're requested. (The technical
|
tuples are constructed and returned only if they're requested. (The technical
|
||||||
term for this behaviour is `lazy evaluation
|
term for this behaviour is `lazy evaluation
|
||||||
|
|
|
@ -354,7 +354,7 @@ thing to do - give it a nice long timeout (say a minute) unless you have good
|
||||||
reason to do otherwise.
|
reason to do otherwise.
|
||||||
|
|
||||||
In return, you will get three lists. They have the sockets that are actually
|
In return, you will get three lists. They have the sockets that are actually
|
||||||
readable, writable and in error. Each of these lists is a subset (possbily
|
readable, writable and in error. Each of these lists is a subset (possibly
|
||||||
empty) of the corresponding list you passed in. And if you put a socket in more
|
empty) of the corresponding list you passed in. And if you put a socket in more
|
||||||
than one input list, it will only be (at most) in one output list.
|
than one input list, it will only be (at most) in one output list.
|
||||||
|
|
||||||
|
@ -368,7 +368,7 @@ just means outbound network buffer space is available.)
|
||||||
If you have a "server" socket, put it in the potential_readers list. If it comes
|
If you have a "server" socket, put it in the potential_readers list. If it comes
|
||||||
out in the readable list, your ``accept`` will (almost certainly) work. If you
|
out in the readable list, your ``accept`` will (almost certainly) work. If you
|
||||||
have created a new socket to ``connect`` to someone else, put it in the
|
have created a new socket to ``connect`` to someone else, put it in the
|
||||||
ptoential_writers list. If it shows up in the writable list, you have a decent
|
potential_writers list. If it shows up in the writable list, you have a decent
|
||||||
chance that it has connected.
|
chance that it has connected.
|
||||||
|
|
||||||
One very nasty problem with ``select``: if somewhere in those input lists of
|
One very nasty problem with ``select``: if somewhere in those input lists of
|
||||||
|
|
|
@ -1018,7 +1018,7 @@ particular, the following variants typically exist:
|
||||||
+-----------------+--------------------------------+--------------------------------+
|
+-----------------+--------------------------------+--------------------------------+
|
||||||
| iso8859_3 | iso-8859-3, latin3, L3 | Esperanto, Maltese |
|
| iso8859_3 | iso-8859-3, latin3, L3 | Esperanto, Maltese |
|
||||||
+-----------------+--------------------------------+--------------------------------+
|
+-----------------+--------------------------------+--------------------------------+
|
||||||
| iso8859_4 | iso-8859-4, latin4, L4 | Baltic languagues |
|
| iso8859_4 | iso-8859-4, latin4, L4 | Baltic languages |
|
||||||
+-----------------+--------------------------------+--------------------------------+
|
+-----------------+--------------------------------+--------------------------------+
|
||||||
| iso8859_5 | iso-8859-5, cyrillic | Bulgarian, Byelorussian, |
|
| iso8859_5 | iso-8859-5, cyrillic | Bulgarian, Byelorussian, |
|
||||||
| | | Macedonian, Russian, Serbian |
|
| | | Macedonian, Russian, Serbian |
|
||||||
|
|
|
@ -452,7 +452,7 @@ they add the ability to access fields by name instead of position index.
|
||||||
.. function:: namedtuple(typename, fieldnames, [verbose])
|
.. function:: namedtuple(typename, fieldnames, [verbose])
|
||||||
|
|
||||||
Returns a new tuple subclass named *typename*. The new subclass is used to
|
Returns a new tuple subclass named *typename*. The new subclass is used to
|
||||||
create tuple-like objects that have fields accessable by attribute lookup as
|
create tuple-like objects that have fields accessible by attribute lookup as
|
||||||
well as being indexable and iterable. Instances of the subclass also have a
|
well as being indexable and iterable. Instances of the subclass also have a
|
||||||
helpful docstring (with typename and fieldnames) and a helpful :meth:`__repr__`
|
helpful docstring (with typename and fieldnames) and a helpful :meth:`__repr__`
|
||||||
method which lists the tuple contents in a ``name=value`` format.
|
method which lists the tuple contents in a ``name=value`` format.
|
||||||
|
@ -516,7 +516,7 @@ Example::
|
||||||
>>> x, y = p # unpack like a regular tuple
|
>>> x, y = p # unpack like a regular tuple
|
||||||
>>> x, y
|
>>> x, y
|
||||||
(11, 22)
|
(11, 22)
|
||||||
>>> p.x + p.y # fields also accessable by name
|
>>> p.x + p.y # fields also accessible by name
|
||||||
33
|
33
|
||||||
>>> p # readable __repr__ with a name=value style
|
>>> p # readable __repr__ with a name=value style
|
||||||
Point(x=11, y=22)
|
Point(x=11, y=22)
|
||||||
|
@ -708,7 +708,7 @@ consult the sources for information about the methods which need to be provided
|
||||||
in that case.
|
in that case.
|
||||||
|
|
||||||
:class:`UserString` objects
|
:class:`UserString` objects
|
||||||
-------------------------
|
---------------------------
|
||||||
|
|
||||||
The class, :class:`UserString` acts as a wrapper around string objects.
|
The class, :class:`UserString` acts as a wrapper around string objects.
|
||||||
The need for this class has been partially supplanted by the ability to
|
The need for this class has been partially supplanted by the ability to
|
||||||
|
|
|
@ -1557,7 +1557,7 @@ of significant places in the coefficient. For example, expressing
|
||||||
original's two-place significance.
|
original's two-place significance.
|
||||||
|
|
||||||
If an application does not care about tracking significance, it is easy to
|
If an application does not care about tracking significance, it is easy to
|
||||||
remove the exponent and trailing zeroes, losing signficance, but keeping the
|
remove the exponent and trailing zeroes, losing significance, but keeping the
|
||||||
value unchanged::
|
value unchanged::
|
||||||
|
|
||||||
>>> def remove_exponent(d):
|
>>> def remove_exponent(d):
|
||||||
|
|
|
@ -41,7 +41,7 @@ can include messages from third-party modules.
|
||||||
It is, of course, possible to log messages with different verbosity levels or to
|
It is, of course, possible to log messages with different verbosity levels or to
|
||||||
different destinations. Support for writing log messages to files, HTTP
|
different destinations. Support for writing log messages to files, HTTP
|
||||||
GET/POST locations, email via SMTP, generic sockets, or OS-specific logging
|
GET/POST locations, email via SMTP, generic sockets, or OS-specific logging
|
||||||
mechnisms are all supported by the standard module. You can also create your
|
mechanisms are all supported by the standard module. You can also create your
|
||||||
own log destination class if you have special requirements not met by any of the
|
own log destination class if you have special requirements not met by any of the
|
||||||
built-in classes.
|
built-in classes.
|
||||||
|
|
||||||
|
@ -265,7 +265,7 @@ destination. Logger objects can add zero or more handler objects to themselves
|
||||||
with an :func:`addHandler` method. As an example scenario, an application may
|
with an :func:`addHandler` method. As an example scenario, an application may
|
||||||
want to send all log messages to a log file, all log messages of error or higher
|
want to send all log messages to a log file, all log messages of error or higher
|
||||||
to stdout, and all messages of critical to an email address. This scenario
|
to stdout, and all messages of critical to an email address. This scenario
|
||||||
requires three individual handlers where each hander is responsible for sending
|
requires three individual handlers where each handler is responsible for sending
|
||||||
messages of a specific severity to a specific location.
|
messages of a specific severity to a specific location.
|
||||||
|
|
||||||
The standard library includes quite a few handler types; this tutorial uses only
|
The standard library includes quite a few handler types; this tutorial uses only
|
||||||
|
|
|
@ -432,7 +432,7 @@ the original. In the interest of compatibility, :class:`mbox` implements the
|
||||||
original format, which is sometimes referred to as :dfn:`mboxo`. This means that
|
original format, which is sometimes referred to as :dfn:`mboxo`. This means that
|
||||||
the :mailheader:`Content-Length` header, if present, is ignored and that any
|
the :mailheader:`Content-Length` header, if present, is ignored and that any
|
||||||
occurrences of "From " at the beginning of a line in a message body are
|
occurrences of "From " at the beginning of a line in a message body are
|
||||||
transformed to ">From " when storing the message, although occurences of ">From
|
transformed to ">From " when storing the message, although occurrences of ">From
|
||||||
" are not transformed to "From " when reading the message.
|
" are not transformed to "From " when reading the message.
|
||||||
|
|
||||||
Some :class:`Mailbox` methods implemented by :class:`mbox` deserve special
|
Some :class:`Mailbox` methods implemented by :class:`mbox` deserve special
|
||||||
|
@ -580,7 +580,7 @@ remarks:
|
||||||
|
|
||||||
.. method:: MH.close()
|
.. method:: MH.close()
|
||||||
|
|
||||||
:class:`MH` instances do not keep any open files, so this method is equivelant
|
:class:`MH` instances do not keep any open files, so this method is equivalent
|
||||||
to :meth:`unlock`.
|
to :meth:`unlock`.
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1629,7 +1629,7 @@ arguments::
|
||||||
value.append(arg)
|
value.append(arg)
|
||||||
del rargs[0]
|
del rargs[0]
|
||||||
|
|
||||||
setattr(parser.values, option.dest, value)
|
setattr(parser.values, option.dest, value)
|
||||||
|
|
||||||
[...]
|
[...]
|
||||||
parser.add_option("-c", "--callback",
|
parser.add_option("-c", "--callback",
|
||||||
|
|
|
@ -237,7 +237,7 @@ Unix Platforms
|
||||||
version)`` which default to the given parameters in case the lookup fails.
|
version)`` which default to the given parameters in case the lookup fails.
|
||||||
|
|
||||||
Note that this function has intimate knowledge of how different libc versions
|
Note that this function has intimate knowledge of how different libc versions
|
||||||
add symbols to the executable is probably only useable for executables compiled
|
add symbols to the executable is probably only usable for executables compiled
|
||||||
using :program:`gcc`.
|
using :program:`gcc`.
|
||||||
|
|
||||||
The file is read and scanned in chunks of *chunksize* bytes.
|
The file is read and scanned in chunks of *chunksize* bytes.
|
||||||
|
|
|
@ -513,7 +513,7 @@ The :class:`Stats` Class
|
||||||
non-parenthesized number repeats the cumulative time spent in the function
|
non-parenthesized number repeats the cumulative time spent in the function
|
||||||
at the right.
|
at the right.
|
||||||
|
|
||||||
* With :mod:`cProfile`, each caller is preceeded by three numbers: the number of
|
* With :mod:`cProfile`, each caller is preceded by three numbers: the number of
|
||||||
times this specific call was made, and the total and cumulative times spent in
|
times this specific call was made, and the total and cumulative times spent in
|
||||||
the current function while it was invoked by this specific caller.
|
the current function while it was invoked by this specific caller.
|
||||||
|
|
||||||
|
|
|
@ -68,6 +68,17 @@ Bookkeeping functions:
|
||||||
the time :func:`setstate` was called.
|
the time :func:`setstate` was called.
|
||||||
|
|
||||||
|
|
||||||
|
.. function:: jumpahead(n)
|
||||||
|
|
||||||
|
Change the internal state to one different from and likely far away from the
|
||||||
|
current state. *n* is a non-negative integer which is used to scramble the
|
||||||
|
current state vector. This is most useful in multi-threaded programs, in
|
||||||
|
conjunction with multiple instances of the :class:`Random` class:
|
||||||
|
:meth:`setstate` or :meth:`seed` can be used to force all instances into the
|
||||||
|
same internal state, and then :meth:`jumpahead` can be used to force the
|
||||||
|
instances' states far apart.
|
||||||
|
|
||||||
|
|
||||||
.. function:: getrandbits(k)
|
.. function:: getrandbits(k)
|
||||||
|
|
||||||
Returns a python integer with *k* random bits. This method is supplied with
|
Returns a python integer with *k* random bits. This method is supplied with
|
||||||
|
|
|
@ -1089,7 +1089,7 @@ into a list with each nonempty line having its own entry::
|
||||||
'Heather Albrecht 548.326.4584 919 Park Place']
|
'Heather Albrecht 548.326.4584 919 Park Place']
|
||||||
|
|
||||||
Finally, split each entry into a list with first name, last name, telephone
|
Finally, split each entry into a list with first name, last name, telephone
|
||||||
number, and address. We use the ``maxsplit`` paramater of :func:`split`
|
number, and address. We use the ``maxsplit`` parameter of :func:`split`
|
||||||
because the address has spaces, our splitting pattern, in it::
|
because the address has spaces, our splitting pattern, in it::
|
||||||
|
|
||||||
>>> [re.split(":? ", entry, 3) for entry in entries]
|
>>> [re.split(":? ", entry, 3) for entry in entries]
|
||||||
|
@ -1099,7 +1099,7 @@ because the address has spaces, our splitting pattern, in it::
|
||||||
['Heather', 'Albrecht', '548.326.4584', '919 Park Place']]
|
['Heather', 'Albrecht', '548.326.4584', '919 Park Place']]
|
||||||
|
|
||||||
The ``:?`` pattern matches the colon after the last name, so that it does not
|
The ``:?`` pattern matches the colon after the last name, so that it does not
|
||||||
occur in the result list. With a ``maxsplit`` of ``4``, we could seperate the
|
occur in the result list. With a ``maxsplit`` of ``4``, we could separate the
|
||||||
house number from the street name::
|
house number from the street name::
|
||||||
|
|
||||||
>>> [re.split(":? ", entry, 4) for entry in entries]
|
>>> [re.split(":? ", entry, 4) for entry in entries]
|
||||||
|
@ -1131,7 +1131,7 @@ in each word of a sentence except for the first and last characters::
|
||||||
Finding all Adverbs
|
Finding all Adverbs
|
||||||
^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
:func:`findall` matches *all* occurences of a pattern, not just the first
|
:func:`findall` matches *all* occurrences of a pattern, not just the first
|
||||||
one as :func:`search` does. For example, if one was a writer and wanted to
|
one as :func:`search` does. For example, if one was a writer and wanted to
|
||||||
find all of the adverbs in some text, he or she might use :func:`findall` in
|
find all of the adverbs in some text, he or she might use :func:`findall` in
|
||||||
the following manner::
|
the following manner::
|
||||||
|
|
|
@ -886,5 +886,5 @@ the interface::
|
||||||
# receive a package
|
# receive a package
|
||||||
print s.recvfrom(65565)
|
print s.recvfrom(65565)
|
||||||
|
|
||||||
# disabled promiscous mode
|
# disabled promiscuous mode
|
||||||
s.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF)
|
s.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF)
|
||||||
|
|
|
@ -18,7 +18,7 @@ The primary entry point is a :term:`generator`:
|
||||||
|
|
||||||
.. function:: generate_tokens(readline)
|
.. function:: generate_tokens(readline)
|
||||||
|
|
||||||
The :func:`generate_tokens` generator requires one argment, *readline*, which
|
The :func:`generate_tokens` generator requires one argument, *readline*, which
|
||||||
must be a callable object which provides the same interface as the
|
must be a callable object which provides the same interface as the
|
||||||
:meth:`readline` method of built-in file objects (see section
|
:meth:`readline` method of built-in file objects (see section
|
||||||
:ref:`bltin-file-objects`). Each call to the function should return one line of
|
:ref:`bltin-file-objects`). Each call to the function should return one line of
|
||||||
|
|
|
@ -61,7 +61,7 @@ support weak references but can add support through subclassing::
|
||||||
class Dict(dict):
|
class Dict(dict):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
obj = Dict(red=1, green=2, blue=3) # this object is weak referencable
|
obj = Dict(red=1, green=2, blue=3) # this object is weak referenceable
|
||||||
|
|
||||||
Extension types can easily be made to support weak references; see
|
Extension types can easily be made to support weak references; see
|
||||||
:ref:`weakref-support`.
|
:ref:`weakref-support`.
|
||||||
|
|
|
@ -421,7 +421,7 @@ TreeBuilder Objects
|
||||||
|
|
||||||
.. method:: TreeBuilder.close()
|
.. method:: TreeBuilder.close()
|
||||||
|
|
||||||
Flushes the parser buffers, and returns the toplevel documen element. Returns an
|
Flushes the parser buffers, and returns the toplevel document element. Returns an
|
||||||
Element instance.
|
Element instance.
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -589,7 +589,7 @@ implementation details.
|
||||||
|
|
||||||
.. rubric:: Footnotes
|
.. rubric:: Footnotes
|
||||||
|
|
||||||
.. [#] The exception is propogated to the invocation stack only if there is no
|
.. [#] The exception is propagated to the invocation stack only if there is no
|
||||||
:keyword:`finally` clause that negates the exception.
|
:keyword:`finally` clause that negates the exception.
|
||||||
|
|
||||||
.. [#] Currently, control "flows off the end" except in the case of an exception or the
|
.. [#] Currently, control "flows off the end" except in the case of an exception or the
|
||||||
|
|
|
@ -380,7 +380,7 @@ generator function:
|
||||||
generator, or raises :exc:`StopIteration` if the generator exits without
|
generator, or raises :exc:`StopIteration` if the generator exits without
|
||||||
yielding another value. When :meth:`send` is called to start the generator,
|
yielding another value. When :meth:`send` is called to start the generator,
|
||||||
it must be called with :const:`None` as the argument, because there is no
|
it must be called with :const:`None` as the argument, because there is no
|
||||||
:keyword:`yield` expression that could receieve the value.
|
:keyword:`yield` expression that could receive the value.
|
||||||
|
|
||||||
|
|
||||||
.. method:: generator.throw(type[, value[, traceback]])
|
.. method:: generator.throw(type[, value[, traceback]])
|
||||||
|
@ -652,7 +652,7 @@ there were no excess keyword arguments.
|
||||||
|
|
||||||
If the syntax ``*expression`` appears in the function call, ``expression`` must
|
If the syntax ``*expression`` appears in the function call, ``expression`` must
|
||||||
evaluate to a sequence. Elements from this sequence are treated as if they were
|
evaluate to a sequence. Elements from this sequence are treated as if they were
|
||||||
additional positional arguments; if there are postional arguments *x1*,...,*xN*
|
additional positional arguments; if there are positional arguments *x1*,...,*xN*
|
||||||
, and ``expression`` evaluates to a sequence *y1*,...,*yM*, this is equivalent
|
, and ``expression`` evaluates to a sequence *y1*,...,*yM*, this is equivalent
|
||||||
to a call with M+N positional arguments *x1*,...,*xN*,*y1*,...,*yM*.
|
to a call with M+N positional arguments *x1*,...,*xN*,*y1*,...,*yM*.
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ write a Python extension module, and the :ref:`c-api-index` describes the
|
||||||
interfaces available to C/C++ programmers in detail.
|
interfaces available to C/C++ programmers in detail.
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 3
|
:maxdepth: 2
|
||||||
|
|
||||||
introduction.rst
|
introduction.rst
|
||||||
lexical_analysis.rst
|
lexical_analysis.rst
|
||||||
|
|
|
@ -269,7 +269,7 @@ applications include caching objects that are expensive to create::
|
||||||
0
|
0
|
||||||
>>> d['primary'] # entry was automatically removed
|
>>> d['primary'] # entry was automatically removed
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
File "<pyshell#108>", line 1, in -toplevel-
|
File "<stdin>", line 1, in <module>
|
||||||
d['primary'] # entry was automatically removed
|
d['primary'] # entry was automatically removed
|
||||||
File "C:/python30/lib/weakref.py", line 46, in __getitem__
|
File "C:/python30/lib/weakref.py", line 46, in __getitem__
|
||||||
o = self.data[key]()
|
o = self.data[key]()
|
||||||
|
|
|
@ -560,7 +560,7 @@ doing ``isinstance(obj, Number)``.
|
||||||
Numbers are further divided into :class:`Exact` and :class:`Inexact`.
|
Numbers are further divided into :class:`Exact` and :class:`Inexact`.
|
||||||
Exact numbers can represent values precisely and operations never
|
Exact numbers can represent values precisely and operations never
|
||||||
round off the results or introduce tiny errors that may break the
|
round off the results or introduce tiny errors that may break the
|
||||||
communtativity and associativity properties; inexact numbers may
|
commutativity and associativity properties; inexact numbers may
|
||||||
perform such rounding or introduce small errors. Integers, long
|
perform such rounding or introduce small errors. Integers, long
|
||||||
integers, and rational numbers are exact, while floating-point
|
integers, and rational numbers are exact, while floating-point
|
||||||
and complex numbers are inexact.
|
and complex numbers are inexact.
|
||||||
|
@ -708,7 +708,9 @@ Here are all of the changes that Python 2.6 makes to the core Python language.
|
||||||
Other functions in the :mod:`math` module, :func:`isinf` and
|
Other functions in the :mod:`math` module, :func:`isinf` and
|
||||||
:func:`isnan`, return true if their floating-point argument is
|
:func:`isnan`, return true if their floating-point argument is
|
||||||
infinite or Not A Number.
|
infinite or Not A Number.
|
||||||
|
|
||||||
.. Patch 1640
|
.. Patch 1640
|
||||||
|
|
||||||
The ``math.copysign(x, y)`` function
|
The ``math.copysign(x, y)`` function
|
||||||
copies the sign bit of an IEEE 754 number, returning the absolute
|
copies the sign bit of an IEEE 754 number, returning the absolute
|
||||||
value of *x* combined with the sign bit of *y*. For example,
|
value of *x* combined with the sign bit of *y*. For example,
|
||||||
|
@ -1078,7 +1080,7 @@ complete list of changes, or look through the CVS logs for all the details.
|
||||||
|
|
||||||
* Integrating signal handling with GUI handling event loops
|
* Integrating signal handling with GUI handling event loops
|
||||||
like those used by Tkinter or GTk+ has long been a problem; most
|
like those used by Tkinter or GTk+ has long been a problem; most
|
||||||
software ends up polling, waking up every fraction of a second. Thi
|
software ends up polling, waking up every fraction of a second.
|
||||||
The :mod:`signal` module can now make this more efficient.
|
The :mod:`signal` module can now make this more efficient.
|
||||||
Calling ``signal.set_wakeup_fd(fd)`` sets a file descriptor
|
Calling ``signal.set_wakeup_fd(fd)`` sets a file descriptor
|
||||||
to be used; when a signal is received, a byte is written to that
|
to be used; when a signal is received, a byte is written to that
|
||||||
|
@ -1293,7 +1295,8 @@ complete list of changes, or look through the CVS logs for all the details.
|
||||||
z.extractall()
|
z.extractall()
|
||||||
|
|
||||||
(Contributed by Alan McIntyre.)
|
(Contributed by Alan McIntyre.)
|
||||||
.. % Patch 467924
|
|
||||||
|
.. Patch 467924
|
||||||
|
|
||||||
.. ======================================================================
|
.. ======================================================================
|
||||||
.. whole new modules get described in subsections here
|
.. whole new modules get described in subsections here
|
||||||
|
@ -1392,7 +1395,7 @@ Changes to Python's build process and to the C API include:
|
||||||
.. Issue 1534
|
.. Issue 1534
|
||||||
|
|
||||||
* Python's C API now includes two functions for case-insensitive string
|
* Python's C API now includes two functions for case-insensitive string
|
||||||
comparisions, ``PyOS_stricmp(char*, char*)``
|
comparisons, ``PyOS_stricmp(char*, char*)``
|
||||||
and ``PyOS_strnicmp(char*, char*, Py_ssize_t)``.
|
and ``PyOS_strnicmp(char*, char*, Py_ssize_t)``.
|
||||||
(Contributed by Christian Heimes.)
|
(Contributed by Christian Heimes.)
|
||||||
|
|
||||||
|
|
|
@ -147,11 +147,11 @@ class CCompiler:
|
||||||
# discovered at run-time, since there are many different ways to do
|
# discovered at run-time, since there are many different ways to do
|
||||||
# basically the same things with Unix C compilers.
|
# basically the same things with Unix C compilers.
|
||||||
|
|
||||||
for key, value in kwargs.items():
|
for key in kwargs:
|
||||||
if key not in self.executables:
|
if key not in self.executables:
|
||||||
raise ValueError("unknown executable '%s' for class %s" % \
|
raise ValueError("unknown executable '%s' for class %s" %
|
||||||
(key, self.__class__.__name__))
|
(key, self.__class__.__name__))
|
||||||
self.set_executable(key, value)
|
self.set_executable(key, kwargs[key])
|
||||||
|
|
||||||
def set_executable(self, key, value):
|
def set_executable(self, key, value):
|
||||||
if isinstance(value, str):
|
if isinstance(value, str):
|
||||||
|
|
|
@ -357,6 +357,7 @@ class sdist (Command):
|
||||||
if line[-1] == '\n':
|
if line[-1] == '\n':
|
||||||
line = line[0:-1]
|
line = line[0:-1]
|
||||||
self.filelist.append(line)
|
self.filelist.append(line)
|
||||||
|
manifest.close()
|
||||||
|
|
||||||
def make_release_tree(self, base_dir, files):
|
def make_release_tree(self, base_dir, files):
|
||||||
"""Create the directory tree that will become the source
|
"""Create the directory tree that will become the source
|
||||||
|
|
18
Lib/runpy.py
18
Lib/runpy.py
|
@ -89,6 +89,9 @@ def _get_module_details(mod_name):
|
||||||
|
|
||||||
|
|
||||||
# XXX ncoghlan: Should this be documented and made public?
|
# XXX ncoghlan: Should this be documented and made public?
|
||||||
|
# (Current thoughts: don't repeat the mistake that lead to its
|
||||||
|
# creation when run_module() no longer met the needs of
|
||||||
|
# mainmodule.c, but couldn't be changed because it was public)
|
||||||
def _run_module_as_main(mod_name, set_argv0=True):
|
def _run_module_as_main(mod_name, set_argv0=True):
|
||||||
"""Runs the designated module in the __main__ namespace
|
"""Runs the designated module in the __main__ namespace
|
||||||
|
|
||||||
|
@ -96,7 +99,20 @@ def _run_module_as_main(mod_name, set_argv0=True):
|
||||||
__file__
|
__file__
|
||||||
__loader__
|
__loader__
|
||||||
"""
|
"""
|
||||||
loader, code, fname = _get_module_details(mod_name)
|
try:
|
||||||
|
loader, code, fname = _get_module_details(mod_name)
|
||||||
|
except ImportError as exc:
|
||||||
|
# Try to provide a good error message
|
||||||
|
# for directories, zip files and the -m switch
|
||||||
|
if set_argv0:
|
||||||
|
# For -m switch, just disply the exception
|
||||||
|
info = str(exc)
|
||||||
|
else:
|
||||||
|
# For directories/zipfiles, let the user
|
||||||
|
# know what the code was looking for
|
||||||
|
info = "can't find '__main__.py' in %r" % sys.argv[0]
|
||||||
|
msg = "%s: %s" % (sys.executable, info)
|
||||||
|
sys.exit(msg)
|
||||||
pkg_name = mod_name.rpartition('.')[0]
|
pkg_name = mod_name.rpartition('.')[0]
|
||||||
main_globals = sys.modules["__main__"].__dict__
|
main_globals = sys.modules["__main__"].__dict__
|
||||||
if set_argv0:
|
if set_argv0:
|
||||||
|
|
|
@ -5,6 +5,7 @@ from weakref import proxy
|
||||||
import sys
|
import sys
|
||||||
import operator
|
import operator
|
||||||
import random
|
import random
|
||||||
|
from functools import reduce
|
||||||
maxsize = test_support.MAX_Py_ssize_t
|
maxsize = test_support.MAX_Py_ssize_t
|
||||||
minsize = -maxsize-1
|
minsize = -maxsize-1
|
||||||
|
|
||||||
|
@ -261,6 +262,28 @@ class TestBasicOps(unittest.TestCase):
|
||||||
ids = list(map(id, list(izip_longest('abc', 'def'))))
|
ids = list(map(id, list(izip_longest('abc', 'def'))))
|
||||||
self.assertEqual(len(dict.fromkeys(ids)), len(ids))
|
self.assertEqual(len(dict.fromkeys(ids)), len(ids))
|
||||||
|
|
||||||
|
def test_product(self):
|
||||||
|
for args, result in [
|
||||||
|
([], []), # zero iterables ??? is this correct
|
||||||
|
(['ab'], [('a',), ('b',)]), # one iterable
|
||||||
|
([range(2), range(3)], [(0,0), (0,1), (0,2), (1,0), (1,1), (1,2)]), # two iterables
|
||||||
|
([range(0), range(2), range(3)], []), # first iterable with zero length
|
||||||
|
([range(2), range(0), range(3)], []), # middle iterable with zero length
|
||||||
|
([range(2), range(3), range(0)], []), # last iterable with zero length
|
||||||
|
]:
|
||||||
|
self.assertEqual(list(product(*args)), result)
|
||||||
|
self.assertEqual(len(list(product(*[range(7)]*6))), 7**6)
|
||||||
|
self.assertRaises(TypeError, product, range(6), None)
|
||||||
|
argtypes = ['', 'abc', '', range(0), range(4), dict(a=1, b=2, c=3),
|
||||||
|
set('abcdefg'), range(11), tuple(range(13))]
|
||||||
|
for i in range(100):
|
||||||
|
args = [random.choice(argtypes) for j in range(random.randrange(5))]
|
||||||
|
n = reduce(operator.mul, map(len, args), 1) if args else 0
|
||||||
|
self.assertEqual(len(list(product(*args))), n)
|
||||||
|
args = map(iter, args)
|
||||||
|
self.assertEqual(len(list(product(*args))), n)
|
||||||
|
|
||||||
|
|
||||||
def test_repeat(self):
|
def test_repeat(self):
|
||||||
self.assertEqual(lzip(range(3),repeat('a')),
|
self.assertEqual(lzip(range(3),repeat('a')),
|
||||||
[(0, 'a'), (1, 'a'), (2, 'a')])
|
[(0, 'a'), (1, 'a'), (2, 'a')])
|
||||||
|
@ -636,6 +659,12 @@ class TestVariousIteratorArgs(unittest.TestCase):
|
||||||
self.assertRaises(TypeError, chain, N(s))
|
self.assertRaises(TypeError, chain, N(s))
|
||||||
self.assertRaises(ZeroDivisionError, list, chain(E(s)))
|
self.assertRaises(ZeroDivisionError, list, chain(E(s)))
|
||||||
|
|
||||||
|
def test_product(self):
|
||||||
|
for s in ("123", "", range(1000), ('do', 1.2), range(2000,2200,5)):
|
||||||
|
self.assertRaises(TypeError, product, X(s))
|
||||||
|
self.assertRaises(TypeError, product, N(s))
|
||||||
|
self.assertRaises(ZeroDivisionError, product, E(s))
|
||||||
|
|
||||||
def test_cycle(self):
|
def test_cycle(self):
|
||||||
for s in ("123", "", range(1000), ('do', 1.2), range(2000,2200,5)):
|
for s in ("123", "", range(1000), ('do', 1.2), range(2000,2200,5)):
|
||||||
for g in (G, I, Ig, S, L, R):
|
for g in (G, I, Ig, S, L, R):
|
||||||
|
|
|
@ -89,6 +89,29 @@ class TypesTests(unittest.TestCase):
|
||||||
if float(1) == 1.0 and float(-1) == -1.0 and float(0) == 0.0: pass
|
if float(1) == 1.0 and float(-1) == -1.0 and float(0) == 0.0: pass
|
||||||
else: self.fail('float() does not work properly')
|
else: self.fail('float() does not work properly')
|
||||||
|
|
||||||
|
def test_float_to_string(self):
|
||||||
|
def test(f, result):
|
||||||
|
self.assertEqual(f.__format__('e'), result)
|
||||||
|
self.assertEqual('%e' % f, result)
|
||||||
|
|
||||||
|
# test all 2 digit exponents, both with __format__ and with
|
||||||
|
# '%' formatting
|
||||||
|
for i in range(-99, 100):
|
||||||
|
test(float('1.5e'+str(i)), '1.500000e{0:+03d}'.format(i))
|
||||||
|
|
||||||
|
# test some 3 digit exponents
|
||||||
|
self.assertEqual(1.5e100.__format__('e'), '1.500000e+100')
|
||||||
|
self.assertEqual('%e' % 1.5e100, '1.500000e+100')
|
||||||
|
|
||||||
|
self.assertEqual(1.5e101.__format__('e'), '1.500000e+101')
|
||||||
|
self.assertEqual('%e' % 1.5e101, '1.500000e+101')
|
||||||
|
|
||||||
|
self.assertEqual(1.5e-100.__format__('e'), '1.500000e-100')
|
||||||
|
self.assertEqual('%e' % 1.5e-100, '1.500000e-100')
|
||||||
|
|
||||||
|
self.assertEqual(1.5e-101.__format__('e'), '1.500000e-101')
|
||||||
|
self.assertEqual('%e' % 1.5e-101, '1.500000e-101')
|
||||||
|
|
||||||
def test_normal_integers(self):
|
def test_normal_integers(self):
|
||||||
# Ensure the first 256 integers are shared
|
# Ensure the first 256 integers are shared
|
||||||
a = 256
|
a = 256
|
||||||
|
@ -416,16 +439,17 @@ class TypesTests(unittest.TestCase):
|
||||||
test(-1.0, ' f', '-1.000000')
|
test(-1.0, ' f', '-1.000000')
|
||||||
test( 1.0, '+f', '+1.000000')
|
test( 1.0, '+f', '+1.000000')
|
||||||
test(-1.0, '+f', '-1.000000')
|
test(-1.0, '+f', '-1.000000')
|
||||||
|
test(1.1234e90, 'f', '1.1234e+90')
|
||||||
|
test(1.1234e90, 'F', '1.1234e+90')
|
||||||
test(1.1234e200, 'f', '1.1234e+200')
|
test(1.1234e200, 'f', '1.1234e+200')
|
||||||
test(1.1234e200, 'F', '1.1234e+200')
|
test(1.1234e200, 'F', '1.1234e+200')
|
||||||
|
|
||||||
# temporarily removed. see issue 1600
|
test( 1.0, 'e', '1.000000e+00')
|
||||||
# test( 1.0, 'e', '1.000000e+00')
|
test(-1.0, 'e', '-1.000000e+00')
|
||||||
# test(-1.0, 'e', '-1.000000e+00')
|
test( 1.0, 'E', '1.000000E+00')
|
||||||
# test( 1.0, 'E', '1.000000E+00')
|
test(-1.0, 'E', '-1.000000E+00')
|
||||||
# test(-1.0, 'E', '-1.000000E+00')
|
test(1.1234e20, 'e', '1.123400e+20')
|
||||||
# test(1.1234e20, 'e', '1.123400e+20')
|
test(1.1234e20, 'E', '1.123400E+20')
|
||||||
# test(1.1234e20, 'E', '1.123400E+20')
|
|
||||||
|
|
||||||
# % formatting
|
# % formatting
|
||||||
test(-1.0, '%', '-100.000000%')
|
test(-1.0, '%', '-100.000000%')
|
||||||
|
|
2139
Misc/HISTORY
2139
Misc/HISTORY
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -106,17 +106,6 @@ if test $ac_cv_sizeof_double != $ac_cv_sizeof_long_double; then
|
||||||
fi
|
fi
|
||||||
AC_SUBST(HAVE_LONG_DOUBLE)
|
AC_SUBST(HAVE_LONG_DOUBLE)
|
||||||
|
|
||||||
AC_MSG_CHECKING(for _Bool support)
|
|
||||||
have_c99_bool=no
|
|
||||||
AC_TRY_COMPILE([], [_Bool x; x = (_Bool)0;], [
|
|
||||||
AC_DEFINE(HAVE_C99_BOOL, 1, [Define this if you have the type _Bool.])
|
|
||||||
have_c99_bool=yes
|
|
||||||
])
|
|
||||||
AC_MSG_RESULT($have_c99_bool)
|
|
||||||
if test "$have_c99_bool" = yes ; then
|
|
||||||
AC_CHECK_SIZEOF(_Bool, 1)
|
|
||||||
fi
|
|
||||||
|
|
||||||
AC_C_BIGENDIAN
|
AC_C_BIGENDIAN
|
||||||
AH_VERBATIM([WORDS_BIGENDIAN],
|
AH_VERBATIM([WORDS_BIGENDIAN],
|
||||||
[
|
[
|
||||||
|
|
|
@ -28,9 +28,6 @@
|
||||||
*/
|
*/
|
||||||
#undef HAVE_AS_SPARC_UA_PCREL
|
#undef HAVE_AS_SPARC_UA_PCREL
|
||||||
|
|
||||||
/* Define this if you have the type _Bool. */
|
|
||||||
#undef HAVE_C99_BOOL
|
|
||||||
|
|
||||||
/* Define if __attribute__((visibility("hidden"))) is supported. */
|
/* Define if __attribute__((visibility("hidden"))) is supported. */
|
||||||
#undef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE
|
#undef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE
|
||||||
|
|
||||||
|
@ -100,18 +97,15 @@
|
||||||
/* Define to the version of this package. */
|
/* Define to the version of this package. */
|
||||||
#undef PACKAGE_VERSION
|
#undef PACKAGE_VERSION
|
||||||
|
|
||||||
/* The size of a `double', as computed by sizeof. */
|
/* The size of `double', as computed by sizeof. */
|
||||||
#undef SIZEOF_DOUBLE
|
#undef SIZEOF_DOUBLE
|
||||||
|
|
||||||
/* The size of a `long double', as computed by sizeof. */
|
/* The size of `long double', as computed by sizeof. */
|
||||||
#undef SIZEOF_LONG_DOUBLE
|
#undef SIZEOF_LONG_DOUBLE
|
||||||
|
|
||||||
/* The size of a `_Bool', as computed by sizeof. */
|
|
||||||
#undef SIZEOF__BOOL
|
|
||||||
|
|
||||||
/* If using the C implementation of alloca, define if you know the
|
/* If using the C implementation of alloca, define if you know the
|
||||||
direction of stack growth for your system; otherwise it will be
|
direction of stack growth for your system; otherwise it will be
|
||||||
automatically deduced at run-time.
|
automatically deduced at runtime.
|
||||||
STACK_DIRECTION > 0 => grows toward higher addresses
|
STACK_DIRECTION > 0 => grows toward higher addresses
|
||||||
STACK_DIRECTION < 0 => grows toward lower addresses
|
STACK_DIRECTION < 0 => grows toward lower addresses
|
||||||
STACK_DIRECTION = 0 => direction of growth unknown */
|
STACK_DIRECTION = 0 => direction of growth unknown */
|
||||||
|
|
|
@ -1711,6 +1711,216 @@ static PyTypeObject chain_type = {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* product object ************************************************************/
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
PyObject_HEAD
|
||||||
|
PyObject *pools; /* tuple of pool tuples */
|
||||||
|
Py_ssize_t *maxvec;
|
||||||
|
Py_ssize_t *indices;
|
||||||
|
PyObject *result;
|
||||||
|
int stopped;
|
||||||
|
} productobject;
|
||||||
|
|
||||||
|
static PyTypeObject product_type;
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
product_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
||||||
|
{
|
||||||
|
productobject *lz;
|
||||||
|
Py_ssize_t npools;
|
||||||
|
PyObject *pools = NULL;
|
||||||
|
Py_ssize_t *maxvec = NULL;
|
||||||
|
Py_ssize_t *indices = NULL;
|
||||||
|
Py_ssize_t i;
|
||||||
|
|
||||||
|
if (type == &product_type && !_PyArg_NoKeywords("product()", kwds))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
assert(PyTuple_Check(args));
|
||||||
|
npools = PyTuple_GET_SIZE(args);
|
||||||
|
|
||||||
|
maxvec = PyMem_Malloc(npools * sizeof(Py_ssize_t));
|
||||||
|
indices = PyMem_Malloc(npools * sizeof(Py_ssize_t));
|
||||||
|
if (maxvec == NULL || indices == NULL) {
|
||||||
|
PyErr_NoMemory();
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
pools = PyTuple_New(npools);
|
||||||
|
if (pools == NULL)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
for (i=0; i < npools; ++i) {
|
||||||
|
PyObject *item = PyTuple_GET_ITEM(args, i);
|
||||||
|
PyObject *pool = PySequence_Tuple(item);
|
||||||
|
if (pool == NULL)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
PyTuple_SET_ITEM(pools, i, pool);
|
||||||
|
maxvec[i] = PyTuple_GET_SIZE(pool);
|
||||||
|
indices[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* create productobject structure */
|
||||||
|
lz = (productobject *)type->tp_alloc(type, 0);
|
||||||
|
if (lz == NULL) {
|
||||||
|
Py_DECREF(pools);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
lz->pools = pools;
|
||||||
|
lz->maxvec = maxvec;
|
||||||
|
lz->indices = indices;
|
||||||
|
lz->result = NULL;
|
||||||
|
lz->stopped = 0;
|
||||||
|
|
||||||
|
return (PyObject *)lz;
|
||||||
|
|
||||||
|
error:
|
||||||
|
if (maxvec != NULL)
|
||||||
|
PyMem_Free(maxvec);
|
||||||
|
if (indices != NULL)
|
||||||
|
PyMem_Free(indices);
|
||||||
|
Py_XDECREF(pools);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
product_dealloc(productobject *lz)
|
||||||
|
{
|
||||||
|
PyObject_GC_UnTrack(lz);
|
||||||
|
Py_XDECREF(lz->pools);
|
||||||
|
Py_XDECREF(lz->result);
|
||||||
|
PyMem_Free(lz->maxvec);
|
||||||
|
PyMem_Free(lz->indices);
|
||||||
|
Py_TYPE(lz)->tp_free(lz);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
product_traverse(productobject *lz, visitproc visit, void *arg)
|
||||||
|
{
|
||||||
|
Py_VISIT(lz->pools);
|
||||||
|
Py_VISIT(lz->result);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
product_next(productobject *lz)
|
||||||
|
{
|
||||||
|
PyObject *pool;
|
||||||
|
PyObject *elem;
|
||||||
|
PyObject *tuple_result;
|
||||||
|
PyObject *pools = lz->pools;
|
||||||
|
PyObject *result = lz->result;
|
||||||
|
Py_ssize_t npools = PyTuple_GET_SIZE(pools);
|
||||||
|
Py_ssize_t i;
|
||||||
|
|
||||||
|
if (lz->stopped)
|
||||||
|
return NULL;
|
||||||
|
if (result == NULL) {
|
||||||
|
if (npools == 0)
|
||||||
|
goto empty;
|
||||||
|
result = PyList_New(npools);
|
||||||
|
if (result == NULL)
|
||||||
|
goto empty;
|
||||||
|
lz->result = result;
|
||||||
|
for (i=0; i < npools; i++) {
|
||||||
|
pool = PyTuple_GET_ITEM(pools, i);
|
||||||
|
if (PyTuple_GET_SIZE(pool) == 0)
|
||||||
|
goto empty;
|
||||||
|
elem = PyTuple_GET_ITEM(pool, 0);
|
||||||
|
Py_INCREF(elem);
|
||||||
|
PyList_SET_ITEM(result, i, elem);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Py_ssize_t *indices = lz->indices;
|
||||||
|
Py_ssize_t *maxvec = lz->maxvec;
|
||||||
|
for (i=npools-1 ; i >= 0 ; i--) {
|
||||||
|
pool = PyTuple_GET_ITEM(pools, i);
|
||||||
|
indices[i]++;
|
||||||
|
if (indices[i] == maxvec[i]) {
|
||||||
|
indices[i] = 0;
|
||||||
|
elem = PyTuple_GET_ITEM(pool, 0);
|
||||||
|
Py_INCREF(elem);
|
||||||
|
PyList_SetItem(result, i, elem);
|
||||||
|
} else {
|
||||||
|
elem = PyTuple_GET_ITEM(pool, indices[i]);
|
||||||
|
Py_INCREF(elem);
|
||||||
|
PyList_SetItem(result, i, elem);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i < 0)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
tuple_result = PySequence_Tuple(result);
|
||||||
|
if (tuple_result == NULL)
|
||||||
|
lz->stopped = 1;
|
||||||
|
return tuple_result;
|
||||||
|
|
||||||
|
empty:
|
||||||
|
lz->stopped = 1;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyDoc_STRVAR(product_doc,
|
||||||
|
"product(*iterables) --> product object\n\
|
||||||
|
\n\
|
||||||
|
Cartesian product of input interables. Equivalent to nested for-loops.\n\n\
|
||||||
|
For example, product(A, B) returns the same as: ((x,y) for x in A for y in B).\n\
|
||||||
|
The leftmost iterators are in the outermost for-loop, so the output tuples\n\
|
||||||
|
cycle in a manner similar to an odometer (with the rightmost element changing\n\
|
||||||
|
on every iteration).\n\n\
|
||||||
|
product('ab', range(3)) --> ('a',0) ('a',1) ('a',2) ('b',0) ('b',1) ('b',2)\n\
|
||||||
|
product((0,1), (0,1), (0,1)) --> (0,0,0) (0,0,1) (0,1,0) (0,1,1) (1,0,0) ...");
|
||||||
|
|
||||||
|
static PyTypeObject product_type = {
|
||||||
|
PyVarObject_HEAD_INIT(NULL, 0)
|
||||||
|
"itertools.product", /* tp_name */
|
||||||
|
sizeof(productobject), /* tp_basicsize */
|
||||||
|
0, /* tp_itemsize */
|
||||||
|
/* methods */
|
||||||
|
(destructor)product_dealloc, /* tp_dealloc */
|
||||||
|
0, /* tp_print */
|
||||||
|
0, /* tp_getattr */
|
||||||
|
0, /* tp_setattr */
|
||||||
|
0, /* tp_compare */
|
||||||
|
0, /* tp_repr */
|
||||||
|
0, /* tp_as_number */
|
||||||
|
0, /* tp_as_sequence */
|
||||||
|
0, /* tp_as_mapping */
|
||||||
|
0, /* tp_hash */
|
||||||
|
0, /* tp_call */
|
||||||
|
0, /* tp_str */
|
||||||
|
PyObject_GenericGetAttr, /* tp_getattro */
|
||||||
|
0, /* tp_setattro */
|
||||||
|
0, /* tp_as_buffer */
|
||||||
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
|
||||||
|
Py_TPFLAGS_BASETYPE, /* tp_flags */
|
||||||
|
product_doc, /* tp_doc */
|
||||||
|
(traverseproc)product_traverse, /* tp_traverse */
|
||||||
|
0, /* tp_clear */
|
||||||
|
0, /* tp_richcompare */
|
||||||
|
0, /* tp_weaklistoffset */
|
||||||
|
PyObject_SelfIter, /* tp_iter */
|
||||||
|
(iternextfunc)product_next, /* tp_iternext */
|
||||||
|
0, /* tp_methods */
|
||||||
|
0, /* tp_members */
|
||||||
|
0, /* tp_getset */
|
||||||
|
0, /* tp_base */
|
||||||
|
0, /* tp_dict */
|
||||||
|
0, /* tp_descr_get */
|
||||||
|
0, /* tp_descr_set */
|
||||||
|
0, /* tp_dictoffset */
|
||||||
|
0, /* tp_init */
|
||||||
|
0, /* tp_alloc */
|
||||||
|
product_new, /* tp_new */
|
||||||
|
PyObject_GC_Del, /* tp_free */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/* ifilter object ************************************************************/
|
/* ifilter object ************************************************************/
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -2749,6 +2959,7 @@ inititertools(void)
|
||||||
&count_type,
|
&count_type,
|
||||||
&izip_type,
|
&izip_type,
|
||||||
&iziplongest_type,
|
&iziplongest_type,
|
||||||
|
&product_type,
|
||||||
&repeat_type,
|
&repeat_type,
|
||||||
&groupby_type,
|
&groupby_type,
|
||||||
NULL
|
NULL
|
||||||
|
|
|
@ -130,16 +130,16 @@ parse_internal_render_format_spec(PyObject *format_spec,
|
||||||
}
|
}
|
||||||
else if (end-ptr >= 1 && is_alignment_token(ptr[0])) {
|
else if (end-ptr >= 1 && is_alignment_token(ptr[0])) {
|
||||||
format->align = ptr[0];
|
format->align = ptr[0];
|
||||||
ptr++;
|
++ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parse the various sign options */
|
/* Parse the various sign options */
|
||||||
if (end-ptr >= 1 && is_sign_element(ptr[0])) {
|
if (end-ptr >= 1 && is_sign_element(ptr[0])) {
|
||||||
format->sign = ptr[0];
|
format->sign = ptr[0];
|
||||||
ptr++;
|
++ptr;
|
||||||
#if ALLOW_PARENS_FOR_SIGN
|
#if ALLOW_PARENS_FOR_SIGN
|
||||||
if (end-ptr >= 1 && ptr[0] == ')') {
|
if (end-ptr >= 1 && ptr[0] == ')') {
|
||||||
ptr++;
|
++ptr;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -150,7 +150,7 @@ parse_internal_render_format_spec(PyObject *format_spec,
|
||||||
if (format->align == '\0') {
|
if (format->align == '\0') {
|
||||||
format->align = '=';
|
format->align = '=';
|
||||||
}
|
}
|
||||||
ptr++;
|
++ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* XXX add error checking */
|
/* XXX add error checking */
|
||||||
|
@ -165,7 +165,7 @@ parse_internal_render_format_spec(PyObject *format_spec,
|
||||||
|
|
||||||
/* Parse field precision */
|
/* Parse field precision */
|
||||||
if (end-ptr && ptr[0] == '.') {
|
if (end-ptr && ptr[0] == '.') {
|
||||||
ptr++;
|
++ptr;
|
||||||
|
|
||||||
/* XXX add error checking */
|
/* XXX add error checking */
|
||||||
specified_width = get_integer(&ptr, end, &format->precision);
|
specified_width = get_integer(&ptr, end, &format->precision);
|
||||||
|
@ -189,7 +189,7 @@ parse_internal_render_format_spec(PyObject *format_spec,
|
||||||
|
|
||||||
if (end-ptr == 1) {
|
if (end-ptr == 1) {
|
||||||
format->type = ptr[0];
|
format->type = ptr[0];
|
||||||
ptr++;
|
++ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -570,7 +570,7 @@ format_int_or_long_internal(PyObject *value, const InternalFormatSpec *format,
|
||||||
/* if X, convert to uppercase */
|
/* if X, convert to uppercase */
|
||||||
if (format->type == 'X') {
|
if (format->type == 'X') {
|
||||||
Py_ssize_t t;
|
Py_ssize_t t;
|
||||||
for (t = 0; t < n_digits; t++)
|
for (t = 0; t < n_digits; ++t)
|
||||||
p[t + n_leading_chars] = STRINGLIB_TOUPPER(p[t + n_leading_chars]);
|
p[t + n_leading_chars] = STRINGLIB_TOUPPER(p[t + n_leading_chars]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -596,37 +596,20 @@ strtounicode(Py_UNICODE *buffer, const char *charbuffer)
|
||||||
{
|
{
|
||||||
register Py_ssize_t i;
|
register Py_ssize_t i;
|
||||||
Py_ssize_t len = strlen(charbuffer);
|
Py_ssize_t len = strlen(charbuffer);
|
||||||
for (i = len - 1; i >= 0; i--)
|
for (i = len - 1; i >= 0; --i)
|
||||||
buffer[i] = (Py_UNICODE) charbuffer[i];
|
buffer[i] = (Py_UNICODE) charbuffer[i];
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* the callback function to call to do the actual float formatting.
|
|
||||||
it matches the definition of PyOS_ascii_formatd */
|
|
||||||
typedef char*
|
|
||||||
(*DoubleSnprintfFunction)(char *buffer, size_t buf_len,
|
|
||||||
const char *format, double d);
|
|
||||||
|
|
||||||
/* just a wrapper to make PyOS_snprintf look like DoubleSnprintfFunction */
|
|
||||||
static char*
|
|
||||||
snprintf_double(char *buffer, size_t buf_len, const char *format, double d)
|
|
||||||
{
|
|
||||||
PyOS_snprintf(buffer, buf_len, format, d);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* see FORMATBUFLEN in unicodeobject.c */
|
/* see FORMATBUFLEN in unicodeobject.c */
|
||||||
#define FLOAT_FORMATBUFLEN 120
|
#define FLOAT_FORMATBUFLEN 120
|
||||||
|
|
||||||
/* much of this is taken from unicodeobject.c */
|
/* much of this is taken from unicodeobject.c */
|
||||||
/* use type instead of format->type, so that it can be overridden by
|
|
||||||
format_number() */
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
_format_float(STRINGLIB_CHAR type, PyObject *value,
|
format_float_internal(PyObject *value,
|
||||||
const InternalFormatSpec *format,
|
const InternalFormatSpec *format)
|
||||||
DoubleSnprintfFunction snprintf)
|
|
||||||
{
|
{
|
||||||
/* fmt = '%.' + `prec` + `type` + '%%'
|
/* fmt = '%.' + `prec` + `type` + '%%'
|
||||||
worst case length = 2 + 10 (len of INT_MAX) + 1 + 2 = 15 (use 20)*/
|
worst case length = 2 + 10 (len of INT_MAX) + 1 + 2 = 15 (use 20)*/
|
||||||
|
@ -658,6 +641,7 @@ _format_float(STRINGLIB_CHAR type, PyObject *value,
|
||||||
char* trailing = "";
|
char* trailing = "";
|
||||||
STRINGLIB_CHAR *p;
|
STRINGLIB_CHAR *p;
|
||||||
NumberFieldWidths spec;
|
NumberFieldWidths spec;
|
||||||
|
STRINGLIB_CHAR type = format->type;
|
||||||
|
|
||||||
#if STRINGLIB_IS_UNICODE
|
#if STRINGLIB_IS_UNICODE
|
||||||
Py_UNICODE unicodebuf[FLOAT_FORMATBUFLEN];
|
Py_UNICODE unicodebuf[FLOAT_FORMATBUFLEN];
|
||||||
|
@ -692,8 +676,8 @@ _format_float(STRINGLIB_CHAR type, PyObject *value,
|
||||||
PyOS_snprintf(fmt, sizeof(fmt), "%%.%" PY_FORMAT_SIZE_T "d%c", precision,
|
PyOS_snprintf(fmt, sizeof(fmt), "%%.%" PY_FORMAT_SIZE_T "d%c", precision,
|
||||||
(char)type);
|
(char)type);
|
||||||
|
|
||||||
/* call the passed in function to do the actual formatting */
|
/* do the actual formatting */
|
||||||
snprintf(charbuf, sizeof(charbuf), fmt, x);
|
PyOS_ascii_formatd(charbuf, sizeof(charbuf), fmt, x);
|
||||||
|
|
||||||
/* adding trailing to fmt with PyOS_snprintf doesn't work, not
|
/* adding trailing to fmt with PyOS_snprintf doesn't work, not
|
||||||
sure why. we'll just concatentate it here, no harm done. we
|
sure why. we'll just concatentate it here, no harm done. we
|
||||||
|
@ -719,8 +703,8 @@ _format_float(STRINGLIB_CHAR type, PyObject *value,
|
||||||
and skip it */
|
and skip it */
|
||||||
sign = p[0];
|
sign = p[0];
|
||||||
if (sign == '-') {
|
if (sign == '-') {
|
||||||
p++;
|
++p;
|
||||||
n_digits--;
|
--n_digits;
|
||||||
}
|
}
|
||||||
|
|
||||||
calc_number_widths(&spec, sign, n_digits, format);
|
calc_number_widths(&spec, sign, n_digits, format);
|
||||||
|
@ -743,15 +727,6 @@ _format_float(STRINGLIB_CHAR type, PyObject *value,
|
||||||
done:
|
done:
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
format_float_internal(PyObject *value, const InternalFormatSpec *format)
|
|
||||||
{
|
|
||||||
if (format->type == 'n')
|
|
||||||
return _format_float('f', value, format, snprintf_double);
|
|
||||||
else
|
|
||||||
return _format_float(format->type, value, format, PyOS_ascii_formatd);
|
|
||||||
}
|
|
||||||
#endif /* FORMAT_FLOAT */
|
#endif /* FORMAT_FLOAT */
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
|
@ -186,6 +186,15 @@ PyOS_ascii_strtod(const char *nptr, char **endptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* From the C99 standard, section 7.19.6:
|
||||||
|
The exponent always contains at least two digits, and only as many more digits
|
||||||
|
as necessary to represent the exponent.
|
||||||
|
*/
|
||||||
|
#define MIN_EXPONENT_DIGITS 2
|
||||||
|
|
||||||
|
/* see FORMATBUFLEN in unicodeobject.c */
|
||||||
|
#define FLOAT_FORMATBUFLEN 120
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PyOS_ascii_formatd:
|
* PyOS_ascii_formatd:
|
||||||
* @buffer: A buffer to place the resulting string in
|
* @buffer: A buffer to place the resulting string in
|
||||||
|
@ -197,7 +206,9 @@ PyOS_ascii_strtod(const char *nptr, char **endptr)
|
||||||
* Converts a #gdouble to a string, using the '.' as
|
* Converts a #gdouble to a string, using the '.' as
|
||||||
* decimal point. To format the number you pass in
|
* decimal point. To format the number you pass in
|
||||||
* a printf()-style format string. Allowed conversion
|
* a printf()-style format string. Allowed conversion
|
||||||
* specifiers are 'e', 'E', 'f', 'F', 'g' and 'G'.
|
* specifiers are 'e', 'E', 'f', 'F', 'g', 'G', and 'n'.
|
||||||
|
*
|
||||||
|
* 'n' is the same as 'g', except it uses the current locale.
|
||||||
*
|
*
|
||||||
* Return value: The pointer to the buffer with the converted string.
|
* Return value: The pointer to the buffer with the converted string.
|
||||||
**/
|
**/
|
||||||
|
@ -207,17 +218,23 @@ PyOS_ascii_formatd(char *buffer,
|
||||||
const char *format,
|
const char *format,
|
||||||
double d)
|
double d)
|
||||||
{
|
{
|
||||||
struct lconv *locale_data;
|
|
||||||
const char *decimal_point;
|
|
||||||
size_t decimal_point_len, rest_len;
|
|
||||||
char *p;
|
char *p;
|
||||||
char format_char;
|
char format_char;
|
||||||
|
size_t format_len = strlen(format);
|
||||||
|
|
||||||
|
/* For type 'n', we need to make a copy of the format string, because
|
||||||
|
we're going to modify 'n' -> 'g', and format is const char*, so we
|
||||||
|
can't modify it directly. FLOAT_FORMATBUFLEN should be longer than
|
||||||
|
we ever need this to be. There's an upcoming check to ensure it's
|
||||||
|
big enough. */
|
||||||
|
char tmp_format[FLOAT_FORMATBUFLEN];
|
||||||
|
|
||||||
/* g_return_val_if_fail (buffer != NULL, NULL); */
|
/* g_return_val_if_fail (buffer != NULL, NULL); */
|
||||||
/* g_return_val_if_fail (format[0] == '%', NULL); */
|
/* g_return_val_if_fail (format[0] == '%', NULL); */
|
||||||
/* g_return_val_if_fail (strpbrk (format + 1, "'l%") == NULL, NULL); */
|
/* g_return_val_if_fail (strpbrk (format + 1, "'l%") == NULL, NULL); */
|
||||||
|
|
||||||
format_char = format[strlen(format) - 1];
|
/* The last character in the format string must be the format char */
|
||||||
|
format_char = format[format_len - 1];
|
||||||
|
|
||||||
/* g_return_val_if_fail (format_char == 'e' || format_char == 'E' || */
|
/* g_return_val_if_fail (format_char == 'e' || format_char == 'E' || */
|
||||||
/* format_char == 'f' || format_char == 'F' || */
|
/* format_char == 'f' || format_char == 'F' || */
|
||||||
|
@ -227,43 +244,126 @@ PyOS_ascii_formatd(char *buffer,
|
||||||
if (format[0] != '%')
|
if (format[0] != '%')
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
/* I'm not sure why this test is here. It's ensuring that the format
|
||||||
|
string after the first character doesn't have a single quote, a
|
||||||
|
lowercase l, or a percent. This is the reverse of the commented-out
|
||||||
|
test about 10 lines ago. */
|
||||||
if (strpbrk(format + 1, "'l%"))
|
if (strpbrk(format + 1, "'l%"))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (!(format_char == 'e' || format_char == 'E' ||
|
if (!(format_char == 'e' || format_char == 'E' ||
|
||||||
format_char == 'f' || format_char == 'F' ||
|
format_char == 'f' || format_char == 'F' ||
|
||||||
format_char == 'g' || format_char == 'G'))
|
format_char == 'g' || format_char == 'G' ||
|
||||||
|
format_char == 'n'))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
/* Map 'n' format_char to 'g', by copying the format string and
|
||||||
|
replacing the final 'n' with a 'g' */
|
||||||
|
if (format_char == 'n') {
|
||||||
|
if (format_len + 1 >= sizeof(tmp_format)) {
|
||||||
|
/* The format won't fit in our copy. Error out. In
|
||||||
|
practice, this will never happen and will be detected
|
||||||
|
by returning NULL */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
strcpy(tmp_format, format);
|
||||||
|
tmp_format[format_len - 1] = 'g';
|
||||||
|
format = tmp_format;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Have PyOS_snprintf do the hard work */
|
||||||
PyOS_snprintf(buffer, buf_len, format, d);
|
PyOS_snprintf(buffer, buf_len, format, d);
|
||||||
|
|
||||||
locale_data = localeconv();
|
/* Get the current local, and find the decimal point character (or
|
||||||
decimal_point = locale_data->decimal_point;
|
string?). Convert that string back to a dot. Do not do this if
|
||||||
decimal_point_len = strlen(decimal_point);
|
using the 'n' (number) format code. */
|
||||||
|
if (format_char != 'n') {
|
||||||
|
struct lconv *locale_data = localeconv();
|
||||||
|
const char *decimal_point = locale_data->decimal_point;
|
||||||
|
size_t decimal_point_len = strlen(decimal_point);
|
||||||
|
size_t rest_len;
|
||||||
|
|
||||||
assert(decimal_point_len != 0);
|
assert(decimal_point_len != 0);
|
||||||
|
|
||||||
if (decimal_point[0] != '.' ||
|
if (decimal_point[0] != '.' || decimal_point[1] != 0) {
|
||||||
decimal_point[1] != 0)
|
p = buffer;
|
||||||
{
|
|
||||||
p = buffer;
|
|
||||||
|
|
||||||
if (*p == '+' || *p == '-')
|
if (*p == '+' || *p == '-')
|
||||||
p++;
|
p++;
|
||||||
|
|
||||||
while (isdigit((unsigned char)*p))
|
while (isdigit(Py_CHARMASK(*p)))
|
||||||
p++;
|
p++;
|
||||||
|
|
||||||
if (strncmp(p, decimal_point, decimal_point_len) == 0)
|
if (strncmp(p, decimal_point, decimal_point_len) == 0) {
|
||||||
{
|
*p = '.';
|
||||||
*p = '.';
|
p++;
|
||||||
p++;
|
if (decimal_point_len > 1) {
|
||||||
if (decimal_point_len > 1) {
|
rest_len = strlen(p +
|
||||||
rest_len = strlen(p + (decimal_point_len - 1));
|
(decimal_point_len - 1));
|
||||||
memmove(p, p + (decimal_point_len - 1),
|
memmove(p, p + (decimal_point_len - 1),
|
||||||
rest_len);
|
rest_len);
|
||||||
p[rest_len] = 0;
|
p[rest_len] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If an exponent exists, ensure that the exponent is at least
|
||||||
|
MIN_EXPONENT_DIGITS digits, providing the buffer is large enough
|
||||||
|
for the extra zeros. Also, if there are more than
|
||||||
|
MIN_EXPONENT_DIGITS, remove as many zeros as possible until we get
|
||||||
|
back to MIN_EXPONENT_DIGITS */
|
||||||
|
p = strpbrk(buffer, "eE");
|
||||||
|
if (p && (*(p + 1) == '-' || *(p + 1) == '+')) {
|
||||||
|
char *start = p + 2;
|
||||||
|
int exponent_digit_cnt = 0;
|
||||||
|
int leading_zero_cnt = 0;
|
||||||
|
int in_leading_zeros = 1;
|
||||||
|
int significant_digit_cnt;
|
||||||
|
|
||||||
|
p += 2;
|
||||||
|
while (*p && isdigit(Py_CHARMASK(*p))) {
|
||||||
|
if (in_leading_zeros && *p == '0')
|
||||||
|
++leading_zero_cnt;
|
||||||
|
if (*p != '0')
|
||||||
|
in_leading_zeros = 0;
|
||||||
|
++p;
|
||||||
|
++exponent_digit_cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
significant_digit_cnt = exponent_digit_cnt - leading_zero_cnt;
|
||||||
|
if (exponent_digit_cnt == MIN_EXPONENT_DIGITS) {
|
||||||
|
/* If there are 2 exactly digits, we're done,
|
||||||
|
regardless of what they contain */
|
||||||
|
}
|
||||||
|
else if (exponent_digit_cnt > MIN_EXPONENT_DIGITS) {
|
||||||
|
int extra_zeros_cnt;
|
||||||
|
|
||||||
|
/* There are more than 2 digits in the exponent. See
|
||||||
|
if we can delete some of the leading zeros */
|
||||||
|
if (significant_digit_cnt < MIN_EXPONENT_DIGITS)
|
||||||
|
significant_digit_cnt = MIN_EXPONENT_DIGITS;
|
||||||
|
extra_zeros_cnt = exponent_digit_cnt - significant_digit_cnt;
|
||||||
|
|
||||||
|
/* Delete extra_zeros_cnt worth of characters from the
|
||||||
|
front of the exponent */
|
||||||
|
assert(extra_zeros_cnt >= 0);
|
||||||
|
|
||||||
|
/* Add one to significant_digit_cnt to copy the
|
||||||
|
trailing 0 byte, thus setting the length */
|
||||||
|
memmove(start,
|
||||||
|
start + extra_zeros_cnt,
|
||||||
|
significant_digit_cnt + 1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* If there are fewer than 2 digits, add zeros
|
||||||
|
until there are 2, if there's enough room */
|
||||||
|
int zeros = MIN_EXPONENT_DIGITS - exponent_digit_cnt;
|
||||||
|
if (start + zeros + exponent_digit_cnt + 1
|
||||||
|
< buffer + buf_len) {
|
||||||
|
memmove(start + zeros, start,
|
||||||
|
exponent_digit_cnt + 1);
|
||||||
|
memset(start, '0', zeros);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue