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)
|
||||
|
||||
Convert a Python integer *pylong* to a C :ctype:`void` pointer. If *pylong*
|
||||
cannot be converted, an :exc:`OverflowError` will be raised. This is only
|
||||
assured to produce a usable :ctype:`void` pointer for values created with
|
||||
:cfunc:`PyLong_FromVoidPtr`.
|
||||
Convert a Python integer *pylong* to a C :ctype:`void` pointer.
|
||||
If *pylong* cannot be converted, an :exc:`OverflowError` will be raised. This
|
||||
is only assured to produce a usable :ctype:`void` pointer for values created
|
||||
with :cfunc:`PyLong_FromVoidPtr`.
|
||||
|
|
|
@ -8,7 +8,7 @@ Buffer Protocol
|
|||
|
||||
.. 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
|
||||
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`
|
||||
|
|
|
@ -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
|
||||
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
|
||||
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::
|
||||
|
||||
static int
|
||||
|
|
|
@ -195,7 +195,7 @@ Distutils configuration files. Various options and sections in the
|
|||
| | or --- & :option:`maintainer` and |
|
||||
| | :option:`maintainer_email` |
|
||||
+------------------------------------------+----------------------------------------------+
|
||||
| Copyright | :option:`licence` |
|
||||
| Copyright | :option:`license` |
|
||||
+------------------------------------------+----------------------------------------------+
|
||||
| Url | :option:`url` |
|
||||
+------------------------------------------+----------------------------------------------+
|
||||
|
|
|
@ -53,13 +53,13 @@ the web interface.
|
|||
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]
|
||||
repository: <repository-url>
|
||||
username: <username>
|
||||
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
|
||||
:func:`setup`. For example, ::
|
||||
|
||||
setup(...
|
||||
setup(...,
|
||||
ext_package='pkg',
|
||||
ext_modules=[Extension('foo', ['foo.c']),
|
||||
Extension('subpkg.bar', ['bar.c'])],
|
||||
|
@ -214,7 +214,7 @@ extension.
|
|||
This warning notwithstanding, options to SWIG can be currently passed like
|
||||
this::
|
||||
|
||||
setup(...
|
||||
setup(...,
|
||||
ext_modules=[Extension('_foo', ['foo.i'],
|
||||
swig_opts=['-modern', '-I../include'])],
|
||||
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
|
||||
way. From the PyXML setup script::
|
||||
|
||||
setup(...
|
||||
setup(...,
|
||||
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
|
||||
following way::
|
||||
|
||||
setup(...
|
||||
setup(...,
|
||||
data_files=[('bitmaps', ['bm/b1.gif', 'bm/b2.gif']),
|
||||
('config', ['cfg/data.cfg']),
|
||||
('/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::
|
||||
|
||||
setup(...
|
||||
setup(...,
|
||||
classifiers=[
|
||||
'Development Status :: 4 - Beta',
|
||||
'Environment :: Console',
|
||||
|
|
|
@ -276,7 +276,7 @@ language, but it boils down to three conditions:
|
|||
product in any way.
|
||||
|
||||
* 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
|
||||
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
|
||||
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
|
||||
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
|
||||
happens when, for example, one module is reloaded, or changes the definition of
|
||||
a function at runtime.
|
||||
|
|
|
@ -892,7 +892,7 @@ returns them in a tuple::
|
|||
itertools.izip(['a', 'b', 'c'], (1, 2, 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
|
||||
tuples are constructed and returned only if they're requested. (The technical
|
||||
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.
|
||||
|
||||
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
|
||||
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
|
||||
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
|
||||
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.
|
||||
|
||||
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_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, |
|
||||
| | | 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])
|
||||
|
||||
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
|
||||
helpful docstring (with typename and fieldnames) and a helpful :meth:`__repr__`
|
||||
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
|
||||
(11, 22)
|
||||
>>> p.x + p.y # fields also accessable by name
|
||||
>>> p.x + p.y # fields also accessible by name
|
||||
33
|
||||
>>> p # readable __repr__ with a name=value style
|
||||
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.
|
||||
|
||||
:class:`UserString` 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
|
||||
|
|
|
@ -1557,7 +1557,7 @@ of significant places in the coefficient. For example, expressing
|
|||
original's two-place significance.
|
||||
|
||||
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::
|
||||
|
||||
>>> 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
|
||||
different destinations. Support for writing log messages to files, HTTP
|
||||
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
|
||||
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
|
||||
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
|
||||
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.
|
||||
|
||||
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
|
||||
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
|
||||
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.
|
||||
|
||||
Some :class:`Mailbox` methods implemented by :class:`mbox` deserve special
|
||||
|
@ -580,7 +580,7 @@ remarks:
|
|||
|
||||
.. 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`.
|
||||
|
||||
|
||||
|
|
|
@ -237,7 +237,7 @@ Unix Platforms
|
|||
version)`` which default to the given parameters in case the lookup fails.
|
||||
|
||||
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`.
|
||||
|
||||
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
|
||||
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
|
||||
the current function while it was invoked by this specific caller.
|
||||
|
||||
|
|
|
@ -68,6 +68,17 @@ Bookkeeping functions:
|
|||
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)
|
||||
|
||||
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']
|
||||
|
||||
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::
|
||||
|
||||
>>> [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']]
|
||||
|
||||
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::
|
||||
|
||||
>>> [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
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
: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
|
||||
find all of the adverbs in some text, he or she might use :func:`findall` in
|
||||
the following manner::
|
||||
|
|
|
@ -886,5 +886,5 @@ the interface::
|
|||
# receive a package
|
||||
print s.recvfrom(65565)
|
||||
|
||||
# disabled promiscous mode
|
||||
# disabled promiscuous mode
|
||||
s.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF)
|
||||
|
|
|
@ -18,7 +18,7 @@ The primary entry point is a :term:`generator`:
|
|||
|
||||
.. 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
|
||||
:meth:`readline` method of built-in file objects (see section
|
||||
: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):
|
||||
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
|
||||
:ref:`weakref-support`.
|
||||
|
|
|
@ -421,7 +421,7 @@ TreeBuilder Objects
|
|||
|
||||
.. 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.
|
||||
|
||||
|
||||
|
|
|
@ -589,7 +589,7 @@ implementation details.
|
|||
|
||||
.. 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.
|
||||
|
||||
.. [#] 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
|
||||
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
|
||||
:keyword:`yield` expression that could receieve the value.
|
||||
:keyword:`yield` expression that could receive the value.
|
||||
|
||||
|
||||
.. 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
|
||||
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
|
||||
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.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 3
|
||||
:maxdepth: 2
|
||||
|
||||
introduction.rst
|
||||
lexical_analysis.rst
|
||||
|
|
|
@ -269,7 +269,7 @@ applications include caching objects that are expensive to create::
|
|||
0
|
||||
>>> d['primary'] # entry was automatically removed
|
||||
Traceback (most recent call last):
|
||||
File "<pyshell#108>", line 1, in -toplevel-
|
||||
File "<stdin>", line 1, in <module>
|
||||
d['primary'] # entry was automatically removed
|
||||
File "C:/python30/lib/weakref.py", line 46, in __getitem__
|
||||
o = self.data[key]()
|
||||
|
|
|
@ -560,7 +560,7 @@ doing ``isinstance(obj, Number)``.
|
|||
Numbers are further divided into :class:`Exact` and :class:`Inexact`.
|
||||
Exact numbers can represent values precisely and operations never
|
||||
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
|
||||
integers, and rational numbers are exact, while floating-point
|
||||
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
|
||||
:func:`isnan`, return true if their floating-point argument is
|
||||
infinite or Not A Number.
|
||||
|
||||
.. Patch 1640
|
||||
|
||||
The ``math.copysign(x, y)`` function
|
||||
copies the sign bit of an IEEE 754 number, returning the absolute
|
||||
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
|
||||
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.
|
||||
Calling ``signal.set_wakeup_fd(fd)`` sets a file descriptor
|
||||
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()
|
||||
|
||||
(Contributed by Alan McIntyre.)
|
||||
.. % Patch 467924
|
||||
|
||||
.. Patch 467924
|
||||
|
||||
.. ======================================================================
|
||||
.. 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
|
||||
|
||||
* 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)``.
|
||||
(Contributed by Christian Heimes.)
|
||||
|
||||
|
|
|
@ -147,11 +147,11 @@ class CCompiler:
|
|||
# discovered at run-time, since there are many different ways to do
|
||||
# basically the same things with Unix C compilers.
|
||||
|
||||
for key, value in kwargs.items():
|
||||
for key in kwargs:
|
||||
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__))
|
||||
self.set_executable(key, value)
|
||||
self.set_executable(key, kwargs[key])
|
||||
|
||||
def set_executable(self, key, value):
|
||||
if isinstance(value, str):
|
||||
|
|
|
@ -357,6 +357,7 @@ class sdist (Command):
|
|||
if line[-1] == '\n':
|
||||
line = line[0:-1]
|
||||
self.filelist.append(line)
|
||||
manifest.close()
|
||||
|
||||
def make_release_tree(self, base_dir, files):
|
||||
"""Create the directory tree that will become the source
|
||||
|
|
16
Lib/runpy.py
16
Lib/runpy.py
|
@ -89,6 +89,9 @@ def _get_module_details(mod_name):
|
|||
|
||||
|
||||
# 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):
|
||||
"""Runs the designated module in the __main__ namespace
|
||||
|
||||
|
@ -96,7 +99,20 @@ def _run_module_as_main(mod_name, set_argv0=True):
|
|||
__file__
|
||||
__loader__
|
||||
"""
|
||||
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]
|
||||
main_globals = sys.modules["__main__"].__dict__
|
||||
if set_argv0:
|
||||
|
|
|
@ -5,6 +5,7 @@ from weakref import proxy
|
|||
import sys
|
||||
import operator
|
||||
import random
|
||||
from functools import reduce
|
||||
maxsize = test_support.MAX_Py_ssize_t
|
||||
minsize = -maxsize-1
|
||||
|
||||
|
@ -261,6 +262,28 @@ class TestBasicOps(unittest.TestCase):
|
|||
ids = list(map(id, list(izip_longest('abc', 'def'))))
|
||||
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):
|
||||
self.assertEqual(lzip(range(3),repeat('a')),
|
||||
[(0, 'a'), (1, 'a'), (2, 'a')])
|
||||
|
@ -636,6 +659,12 @@ class TestVariousIteratorArgs(unittest.TestCase):
|
|||
self.assertRaises(TypeError, chain, N(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):
|
||||
for s in ("123", "", range(1000), ('do', 1.2), range(2000,2200,5)):
|
||||
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
|
||||
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):
|
||||
# Ensure the first 256 integers are shared
|
||||
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.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')
|
||||
|
||||
# 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.1234e20, 'e', '1.123400e+20')
|
||||
# test(1.1234e20, 'E', '1.123400E+20')
|
||||
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')
|
||||
|
||||
# % formatting
|
||||
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
|
||||
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
|
||||
AH_VERBATIM([WORDS_BIGENDIAN],
|
||||
[
|
||||
|
|
|
@ -28,9 +28,6 @@
|
|||
*/
|
||||
#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. */
|
||||
#undef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE
|
||||
|
||||
|
@ -100,18 +97,15 @@
|
|||
/* Define to the version of this package. */
|
||||
#undef PACKAGE_VERSION
|
||||
|
||||
/* The size of a `double', as computed by sizeof. */
|
||||
/* The size of `double', as computed by sizeof. */
|
||||
#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
|
||||
|
||||
/* The size of a `_Bool', as computed by sizeof. */
|
||||
#undef SIZEOF__BOOL
|
||||
|
||||
/* If using the C implementation of alloca, define if you know the
|
||||
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 lower addresses
|
||||
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 ************************************************************/
|
||||
|
||||
typedef struct {
|
||||
|
@ -2749,6 +2959,7 @@ inititertools(void)
|
|||
&count_type,
|
||||
&izip_type,
|
||||
&iziplongest_type,
|
||||
&product_type,
|
||||
&repeat_type,
|
||||
&groupby_type,
|
||||
NULL
|
||||
|
|
|
@ -130,16 +130,16 @@ parse_internal_render_format_spec(PyObject *format_spec,
|
|||
}
|
||||
else if (end-ptr >= 1 && is_alignment_token(ptr[0])) {
|
||||
format->align = ptr[0];
|
||||
ptr++;
|
||||
++ptr;
|
||||
}
|
||||
|
||||
/* Parse the various sign options */
|
||||
if (end-ptr >= 1 && is_sign_element(ptr[0])) {
|
||||
format->sign = ptr[0];
|
||||
ptr++;
|
||||
++ptr;
|
||||
#if ALLOW_PARENS_FOR_SIGN
|
||||
if (end-ptr >= 1 && ptr[0] == ')') {
|
||||
ptr++;
|
||||
++ptr;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -150,7 +150,7 @@ parse_internal_render_format_spec(PyObject *format_spec,
|
|||
if (format->align == '\0') {
|
||||
format->align = '=';
|
||||
}
|
||||
ptr++;
|
||||
++ptr;
|
||||
}
|
||||
|
||||
/* XXX add error checking */
|
||||
|
@ -165,7 +165,7 @@ parse_internal_render_format_spec(PyObject *format_spec,
|
|||
|
||||
/* Parse field precision */
|
||||
if (end-ptr && ptr[0] == '.') {
|
||||
ptr++;
|
||||
++ptr;
|
||||
|
||||
/* XXX add error checking */
|
||||
specified_width = get_integer(&ptr, end, &format->precision);
|
||||
|
@ -189,7 +189,7 @@ parse_internal_render_format_spec(PyObject *format_spec,
|
|||
|
||||
if (end-ptr == 1) {
|
||||
format->type = ptr[0];
|
||||
ptr++;
|
||||
++ptr;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
@ -570,7 +570,7 @@ format_int_or_long_internal(PyObject *value, const InternalFormatSpec *format,
|
|||
/* if X, convert to uppercase */
|
||||
if (format->type == 'X') {
|
||||
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]);
|
||||
}
|
||||
|
||||
|
@ -596,37 +596,20 @@ strtounicode(Py_UNICODE *buffer, const char *charbuffer)
|
|||
{
|
||||
register Py_ssize_t i;
|
||||
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];
|
||||
|
||||
return len;
|
||||
}
|
||||
#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 */
|
||||
#define FLOAT_FORMATBUFLEN 120
|
||||
|
||||
/* 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 *
|
||||
_format_float(STRINGLIB_CHAR type, PyObject *value,
|
||||
const InternalFormatSpec *format,
|
||||
DoubleSnprintfFunction snprintf)
|
||||
format_float_internal(PyObject *value,
|
||||
const InternalFormatSpec *format)
|
||||
{
|
||||
/* fmt = '%.' + `prec` + `type` + '%%'
|
||||
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 = "";
|
||||
STRINGLIB_CHAR *p;
|
||||
NumberFieldWidths spec;
|
||||
STRINGLIB_CHAR type = format->type;
|
||||
|
||||
#if STRINGLIB_IS_UNICODE
|
||||
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,
|
||||
(char)type);
|
||||
|
||||
/* call the passed in function to do the actual formatting */
|
||||
snprintf(charbuf, sizeof(charbuf), fmt, x);
|
||||
/* do the actual formatting */
|
||||
PyOS_ascii_formatd(charbuf, sizeof(charbuf), fmt, x);
|
||||
|
||||
/* adding trailing to fmt with PyOS_snprintf doesn't work, not
|
||||
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 */
|
||||
sign = p[0];
|
||||
if (sign == '-') {
|
||||
p++;
|
||||
n_digits--;
|
||||
++p;
|
||||
--n_digits;
|
||||
}
|
||||
|
||||
calc_number_widths(&spec, sign, n_digits, format);
|
||||
|
@ -743,15 +727,6 @@ _format_float(STRINGLIB_CHAR type, PyObject *value,
|
|||
done:
|
||||
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 */
|
||||
|
||||
/************************************************************************/
|
||||
|
|
|
@ -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:
|
||||
* @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
|
||||
* decimal point. To format the number you pass in
|
||||
* 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.
|
||||
**/
|
||||
|
@ -207,17 +218,23 @@ PyOS_ascii_formatd(char *buffer,
|
|||
const char *format,
|
||||
double d)
|
||||
{
|
||||
struct lconv *locale_data;
|
||||
const char *decimal_point;
|
||||
size_t decimal_point_len, rest_len;
|
||||
char *p;
|
||||
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 (format[0] == '%', 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' || */
|
||||
/* format_char == 'f' || format_char == 'F' || */
|
||||
|
@ -227,46 +244,129 @@ PyOS_ascii_formatd(char *buffer,
|
|||
if (format[0] != '%')
|
||||
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%"))
|
||||
return NULL;
|
||||
|
||||
if (!(format_char == 'e' || format_char == 'E' ||
|
||||
format_char == 'f' || format_char == 'F' ||
|
||||
format_char == 'g' || format_char == 'G'))
|
||||
format_char == 'g' || format_char == 'G' ||
|
||||
format_char == 'n'))
|
||||
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);
|
||||
|
||||
locale_data = localeconv();
|
||||
decimal_point = locale_data->decimal_point;
|
||||
decimal_point_len = strlen(decimal_point);
|
||||
/* Get the current local, and find the decimal point character (or
|
||||
string?). Convert that string back to a dot. Do not do this if
|
||||
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);
|
||||
|
||||
if (decimal_point[0] != '.' ||
|
||||
decimal_point[1] != 0)
|
||||
{
|
||||
if (decimal_point[0] != '.' || decimal_point[1] != 0) {
|
||||
p = buffer;
|
||||
|
||||
if (*p == '+' || *p == '-')
|
||||
p++;
|
||||
|
||||
while (isdigit((unsigned char)*p))
|
||||
while (isdigit(Py_CHARMASK(*p)))
|
||||
p++;
|
||||
|
||||
if (strncmp(p, decimal_point, decimal_point_len) == 0)
|
||||
{
|
||||
if (strncmp(p, decimal_point, decimal_point_len) == 0) {
|
||||
*p = '.';
|
||||
p++;
|
||||
if (decimal_point_len > 1) {
|
||||
rest_len = strlen(p + (decimal_point_len - 1));
|
||||
rest_len = strlen(p +
|
||||
(decimal_point_len - 1));
|
||||
memmove(p, p + (decimal_point_len - 1),
|
||||
rest_len);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue