merge heads
This commit is contained in:
commit
455fa0a314
|
@ -53,7 +53,7 @@ checkout:
|
|||
fi
|
||||
@if [ ! -d tools/pygments ]; then \
|
||||
echo "Checking out Pygments..."; \
|
||||
svn checkout $(SVNROOT)/external/Pygments-1.3.1/pygments tools/pygments; \
|
||||
svn checkout $(SVNROOT)/external/Pygments-1.5dev-20120930/pygments tools/pygments; \
|
||||
fi
|
||||
|
||||
update: clean checkout
|
||||
|
|
|
@ -1083,8 +1083,6 @@ These are the UTF-32 codec APIs:
|
|||
After completion, *\*byteorder* is set to the current byte order at the end
|
||||
of input data.
|
||||
|
||||
In a narrow build codepoints outside the BMP will be decoded as surrogate pairs.
|
||||
|
||||
If *byteorder* is *NULL*, the codec starts in native order mode.
|
||||
|
||||
Return *NULL* if an exception was raised by the codec.
|
||||
|
|
|
@ -660,7 +660,7 @@ Glossary
|
|||
sequence
|
||||
An :term:`iterable` which supports efficient element access using integer
|
||||
indices via the :meth:`__getitem__` special method and defines a
|
||||
:meth:`len` method that returns the length of the sequence.
|
||||
:meth:`__len__` method that returns the length of the sequence.
|
||||
Some built-in sequence types are :class:`list`, :class:`str`,
|
||||
:class:`tuple`, and :class:`bytes`. Note that :class:`dict` also
|
||||
supports :meth:`__getitem__` and :meth:`__len__`, but is considered a
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
.. _ipaddress-howto:
|
||||
|
||||
***************************************
|
||||
An Introduction to the ipaddress module
|
||||
An introduction to the ipaddress module
|
||||
***************************************
|
||||
|
||||
:author: Peter Moody
|
||||
|
@ -47,7 +47,12 @@ Addresses, often referred to as "host addresses" are the most basic unit
|
|||
when working with IP addressing. The simplest way to create addresses is
|
||||
to use the :func:`ipaddress.ip_address` factory function, which automatically
|
||||
determines whether to create an IPv4 or IPv6 address based on the passed in
|
||||
value::
|
||||
value:
|
||||
|
||||
.. testsetup::
|
||||
>>> import ipaddress
|
||||
|
||||
::
|
||||
|
||||
>>> ipaddress.ip_address('192.0.2.1')
|
||||
IPv4Address('192.0.2.1')
|
||||
|
@ -142,7 +147,7 @@ address.
|
|||
|
||||
>>> ipaddress.ip_interface('192.0.2.1/24')
|
||||
IPv4Interface('192.0.2.1/24')
|
||||
>>> ipaddress.ip_network('2001:db8::1/96')
|
||||
>>> ipaddress.ip_interface('2001:db8::1/96')
|
||||
IPv6Interface('2001:db8::1/96')
|
||||
|
||||
Integer inputs are accepted (as with networks), and use of a particular IP
|
||||
|
@ -177,22 +182,22 @@ Obtaining the network from an interface::
|
|||
Finding out how many individual addresses are in a network::
|
||||
|
||||
>>> net4 = ipaddress.ip_network('192.0.2.0/24')
|
||||
>>> net4.numhosts
|
||||
>>> net4.num_addresses
|
||||
256
|
||||
>>> net6 = ipaddress.ip_network('2001:db8::0/96')
|
||||
>>> net6.numhosts
|
||||
>>> net6.num_addresses
|
||||
4294967296
|
||||
|
||||
Iterating through the "usable" addresses on a network::
|
||||
|
||||
>>> net4 = ipaddress.ip_network('192.0.2.0/24')
|
||||
>>> for x in net4.hosts():
|
||||
print(x)
|
||||
... print(x) # doctest: +ELLIPSIS
|
||||
192.0.2.1
|
||||
192.0.2.2
|
||||
192.0.2.3
|
||||
192.0.2.4
|
||||
<snip>
|
||||
...
|
||||
192.0.2.252
|
||||
192.0.2.253
|
||||
192.0.2.254
|
||||
|
@ -216,9 +221,9 @@ the hostmask (any bits that are not part of the netmask):
|
|||
Exploding or compressing the address::
|
||||
|
||||
>>> addr6.exploded
|
||||
'2001:0db8:0000:0000:0000:0000:0000:0000'
|
||||
'2001:0db8:0000:0000:0000:0000:0000:0001'
|
||||
>>> addr6.compressed
|
||||
'2001:db8::'
|
||||
'2001:db8::1'
|
||||
>>> net6.exploded
|
||||
'2001:0db8:0000:0000:0000:0000:0000:0000/96'
|
||||
>>> net6.compressed
|
||||
|
@ -241,9 +246,9 @@ to index them like this::
|
|||
>>> net4[-1]
|
||||
IPv4Address('192.0.2.255')
|
||||
>>> net6[1]
|
||||
IPv6Address('2001::1')
|
||||
IPv6Address('2001:db8::1')
|
||||
>>> net6[-1]
|
||||
IPv6Address('2001::ffff:ffff')
|
||||
IPv6Address('2001:db8::ffff:ffff')
|
||||
|
||||
|
||||
It also means that network objects lend themselves to using the list
|
||||
|
|
|
@ -144,7 +144,7 @@ This is done as follows::
|
|||
>>> data['location'] = 'Northampton'
|
||||
>>> data['language'] = 'Python'
|
||||
>>> url_values = urllib.parse.urlencode(data)
|
||||
>>> print(url_values)
|
||||
>>> print(url_values) # The order may differ from below. #doctest: +SKIP
|
||||
name=Somebody+Here&language=Python&location=Northampton
|
||||
>>> url = 'http://www.example.com/example.cgi'
|
||||
>>> full_url = url + '?' + url_values
|
||||
|
@ -214,9 +214,9 @@ e.g. ::
|
|||
|
||||
>>> req = urllib.request.Request('http://www.pretend_server.org')
|
||||
>>> try: urllib.request.urlopen(req)
|
||||
>>> except urllib.error.URLError as e:
|
||||
>>> print(e.reason)
|
||||
>>>
|
||||
... except urllib.error.URLError as e:
|
||||
... print(e.reason) #doctest: +SKIP
|
||||
...
|
||||
(4, 'getaddrinfo failed')
|
||||
|
||||
|
||||
|
@ -322,18 +322,17 @@ geturl, and info, methods as returned by the ``urllib.response`` module::
|
|||
|
||||
>>> req = urllib.request.Request('http://www.python.org/fish.html')
|
||||
>>> try:
|
||||
>>> urllib.request.urlopen(req)
|
||||
>>> except urllib.error.HTTPError as e:
|
||||
>>> print(e.code)
|
||||
>>> print(e.read())
|
||||
>>>
|
||||
... urllib.request.urlopen(req)
|
||||
... except urllib.error.HTTPError as e:
|
||||
... print(e.code)
|
||||
... print(e.read()) #doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE
|
||||
...
|
||||
404
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
<?xml-stylesheet href="./css/ht2html.css"
|
||||
type="text/css"?>
|
||||
<html><head><title>Error 404: File Not Found</title>
|
||||
...... etc...
|
||||
b'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\n\n\n<html
|
||||
...
|
||||
<title>Page Not Found</title>\n
|
||||
...
|
||||
|
||||
Wrapping it Up
|
||||
--------------
|
||||
|
|
|
@ -159,7 +159,7 @@ contexts::
|
|||
|
||||
d['x'] # Get first key in the chain of contexts
|
||||
d['x'] = 1 # Set value in current context
|
||||
del['x'] # Delete from current context
|
||||
del d['x'] # Delete from current context
|
||||
list(d) # All nested values
|
||||
k in d # Check all nested values
|
||||
len(d) # Number of nested values
|
||||
|
|
|
@ -15,6 +15,7 @@ multitasking) Here's an overview:
|
|||
|
||||
threading.rst
|
||||
multiprocessing.rst
|
||||
concurrent.rst
|
||||
concurrent.futures.rst
|
||||
subprocess.rst
|
||||
sched.rst
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
The :mod:`concurrent` package
|
||||
=============================
|
||||
|
||||
Currently, there is only one module in this package:
|
||||
|
||||
* :mod:`concurrent.futures` -- Launching parallel tasks
|
|
@ -770,9 +770,9 @@ An example of writing to a configuration file::
|
|||
# values using the mapping protocol or ConfigParser's set() does not allow
|
||||
# such assignments to take place.
|
||||
config.add_section('Section1')
|
||||
config.set('Section1', 'int', '15')
|
||||
config.set('Section1', 'bool', 'true')
|
||||
config.set('Section1', 'float', '3.1415')
|
||||
config.set('Section1', 'an_int', '15')
|
||||
config.set('Section1', 'a_bool', 'true')
|
||||
config.set('Section1', 'a_float', '3.1415')
|
||||
config.set('Section1', 'baz', 'fun')
|
||||
config.set('Section1', 'bar', 'Python')
|
||||
config.set('Section1', 'foo', '%(bar)s is %(baz)s!')
|
||||
|
@ -790,13 +790,13 @@ An example of reading the configuration file again::
|
|||
|
||||
# getfloat() raises an exception if the value is not a float
|
||||
# getint() and getboolean() also do this for their respective types
|
||||
float = config.getfloat('Section1', 'float')
|
||||
int = config.getint('Section1', 'int')
|
||||
print(float + int)
|
||||
a_float = config.getfloat('Section1', 'a_float')
|
||||
an_int = config.getint('Section1', 'an_int')
|
||||
print(a_float + an_int)
|
||||
|
||||
# Notice that the next output does not interpolate '%(bar)s' or '%(baz)s'.
|
||||
# This is because we are using a RawConfigParser().
|
||||
if config.getboolean('Section1', 'bool'):
|
||||
if config.getboolean('Section1', 'a_bool'):
|
||||
print(config.get('Section1', 'foo'))
|
||||
|
||||
To get interpolation, use :class:`ConfigParser`::
|
||||
|
|
|
@ -650,7 +650,16 @@ above.
|
|||
An example's doctest directives modify doctest's behavior for that single
|
||||
example. Use ``+`` to enable the named behavior, or ``-`` to disable it.
|
||||
|
||||
For example, this test passes::
|
||||
.. note::
|
||||
Due to an `unfortunate limitation`_ of our current documentation
|
||||
publishing process, syntax highlighting has been disabled in the examples
|
||||
below in order to ensure the doctest directives are correctly displayed.
|
||||
|
||||
.. _unfortunate limitation: http://bugs.python.org/issue12947
|
||||
|
||||
For example, this test passes:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
>>> print(list(range(20))) #doctest: +NORMALIZE_WHITESPACE
|
||||
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
|
||||
|
@ -659,18 +668,25 @@ For example, this test passes::
|
|||
Without the directive it would fail, both because the actual output doesn't have
|
||||
two blanks before the single-digit list elements, and because the actual output
|
||||
is on a single line. This test also passes, and also requires a directive to do
|
||||
so::
|
||||
so:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
>>> print(list(range(20))) # doctest: +ELLIPSIS
|
||||
[0, 1, ..., 18, 19]
|
||||
|
||||
Multiple directives can be used on a single physical line, separated by commas::
|
||||
Multiple directives can be used on a single physical line, separated by
|
||||
commas:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
>>> print(list(range(20))) # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE
|
||||
[0, 1, ..., 18, 19]
|
||||
|
||||
If multiple directive comments are used for a single example, then they are
|
||||
combined::
|
||||
combined:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
>>> print(list(range(20))) # doctest: +ELLIPSIS
|
||||
... # doctest: +NORMALIZE_WHITESPACE
|
||||
|
@ -678,7 +694,9 @@ combined::
|
|||
|
||||
As the previous example shows, you can add ``...`` lines to your example
|
||||
containing only directives. This can be useful when an example is too long for
|
||||
a directive to comfortably fit on the same line::
|
||||
a directive to comfortably fit on the same line:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
>>> print(list(range(5)) + list(range(10, 20)) + list(range(30, 40)))
|
||||
... # doctest: +ELLIPSIS
|
||||
|
|
|
@ -17,7 +17,7 @@ Suggested usage is::
|
|||
try:
|
||||
import threading
|
||||
except ImportError:
|
||||
import dummy_threading
|
||||
import dummy_threading as threading
|
||||
|
||||
Be careful to not use this module where deadlock might occur from a thread being
|
||||
created that blocks waiting for another thread to be created. This often occurs
|
||||
|
|
|
@ -270,12 +270,12 @@ followed by ``lines`` for the text version or ``binary`` for the binary version.
|
|||
.. method:: FTP.storbinary(cmd, file, blocksize=8192, callback=None, rest=None)
|
||||
|
||||
Store a file in binary transfer mode. *cmd* should be an appropriate
|
||||
``STOR`` command: ``"STOR filename"``. *file* is an open :term:`file object`
|
||||
which is read until EOF using its :meth:`read` method in blocks of size
|
||||
*blocksize* to provide the data to be stored. The *blocksize* argument
|
||||
defaults to 8192. *callback* is an optional single parameter callable that
|
||||
is called on each block of data after it is sent. *rest* means the same thing
|
||||
as in the :meth:`transfercmd` method.
|
||||
``STOR`` command: ``"STOR filename"``. *file* is a :term:`file object`
|
||||
(opened in binary mode) which is read until EOF using its :meth:`read`
|
||||
method in blocks of size *blocksize* to provide the data to be stored.
|
||||
The *blocksize* argument defaults to 8192. *callback* is an optional single
|
||||
parameter callable that is called on each block of data after it is sent.
|
||||
*rest* means the same thing as in the :meth:`transfercmd` method.
|
||||
|
||||
.. versionchanged:: 3.2
|
||||
*rest* parameter added.
|
||||
|
@ -285,9 +285,9 @@ followed by ``lines`` for the text version or ``binary`` for the binary version.
|
|||
|
||||
Store a file in ASCII transfer mode. *cmd* should be an appropriate
|
||||
``STOR`` command (see :meth:`storbinary`). Lines are read until EOF from the
|
||||
open :term:`file object` *file* using its :meth:`readline` method to provide
|
||||
the data to be stored. *callback* is an optional single parameter callable
|
||||
that is called on each line after it is sent.
|
||||
:term:`file object` *file* (opened in binary mode) using its :meth:`readline`
|
||||
method to provide the data to be stored. *callback* is an optional single
|
||||
parameter callable that is called on each line after it is sent.
|
||||
|
||||
|
||||
.. method:: FTP.transfercmd(cmd, rest=None)
|
||||
|
|
|
@ -1203,7 +1203,8 @@ are always available. They are listed here in alphabetical order.
|
|||
|
||||
|
||||
.. _func-str:
|
||||
.. function:: str([object[, encoding[, errors]]])
|
||||
.. function:: str(object='')
|
||||
str(object[, encoding[, errors]])
|
||||
|
||||
Return a string version of an object, using one of the following modes:
|
||||
|
||||
|
|
|
@ -189,13 +189,13 @@ values but should not rebind them):
|
|||
after collection. The callbacks will be called with two arguments,
|
||||
*phase* and *info*.
|
||||
|
||||
*phase* can one of two values:
|
||||
*phase* can be one of two values:
|
||||
|
||||
"start": The garbage collection is about to start.
|
||||
|
||||
"stop": The garbage collection has finished.
|
||||
|
||||
*info* provides more information for the callback. The following
|
||||
*info* is a dict providing more information for the callback. The following
|
||||
keys are currently defined:
|
||||
|
||||
"generation": The oldest generation being collected.
|
||||
|
@ -203,7 +203,7 @@ values but should not rebind them):
|
|||
"collected": When *phase* is "stop", the number of objects
|
||||
successfully collected.
|
||||
|
||||
"uncollectable": when *phase* is "stop", the number of objects
|
||||
"uncollectable": When *phase* is "stop", the number of objects
|
||||
that could not be collected and were put in :data:`garbage`.
|
||||
|
||||
Applications can add their own callbacks to this list. The primary
|
||||
|
|
|
@ -19,3 +19,10 @@ This module defines utilities to manipulate HTML.
|
|||
attribute value delimited by quotes, as in ``<a href="...">``.
|
||||
|
||||
.. versionadded:: 3.2
|
||||
|
||||
--------------
|
||||
|
||||
Submodules in the ``html`` package are:
|
||||
|
||||
* :mod:`html.parser` -- HTML/XHTML parser with lenient parsing mode
|
||||
* :mod:`html.entities` -- HTML entity definitions
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
:mod:`http` --- HTTP modules
|
||||
============================
|
||||
|
||||
``http`` is a package that collects several modules for working with the
|
||||
HyperText Transfer Protocol:
|
||||
|
||||
* :mod:`http.client` is a low-level HTTP protocol client; for high-level URL
|
||||
opening use :mod:`urllib.request`
|
||||
* :mod:`http.server` contains basic HTTP server classes based on :mod:`socketserver`
|
||||
* :mod:`http.cookies` has utilities for implementing state management with cookies
|
||||
* :mod:`http.cookiejar` provides persistence of cookies
|
|
@ -23,10 +23,12 @@ is currently supported on most popular platforms. Here is an overview:
|
|||
cgi.rst
|
||||
cgitb.rst
|
||||
wsgiref.rst
|
||||
urllib.rst
|
||||
urllib.request.rst
|
||||
urllib.parse.rst
|
||||
urllib.error.rst
|
||||
urllib.robotparser.rst
|
||||
http.rst
|
||||
http.client.rst
|
||||
ftplib.rst
|
||||
poplib.rst
|
||||
|
@ -40,6 +42,7 @@ is currently supported on most popular platforms. Here is an overview:
|
|||
http.server.rst
|
||||
http.cookies.rst
|
||||
http.cookiejar.rst
|
||||
xmlrpc.rst
|
||||
xmlrpc.client.rst
|
||||
xmlrpc.server.rst
|
||||
ipaddress.rst
|
||||
|
|
|
@ -42,8 +42,15 @@ IP addresses, networks and interfaces:
|
|||
Return an :class:`IPv4Address` or :class:`IPv6Address` object depending on
|
||||
the IP address passed as argument. Either IPv4 or IPv6 addresses may be
|
||||
supplied; integers less than 2**32 will be considered to be IPv4 by default.
|
||||
A :exc:`ValueError` is raised if *address* does not represent a valid IPv4 or
|
||||
IPv6 address.
|
||||
A :exc:`ValueError` is raised if *address* does not represent a valid IPv4
|
||||
or IPv6 address.
|
||||
|
||||
.. testsetup::
|
||||
>>> import ipaddress
|
||||
>>> from ipaddress import (ip_network, IPv4Address, IPv4Interface,
|
||||
... IPv4Network)
|
||||
|
||||
::
|
||||
|
||||
>>> ipaddress.ip_address('192.168.0.1')
|
||||
IPv4Address('192.168.0.1')
|
||||
|
@ -111,7 +118,7 @@ write code that handles both IP versions correctly.
|
|||
|
||||
>>> ipaddress.IPv4Address('192.168.0.1')
|
||||
IPv4Address('192.168.0.1')
|
||||
>>> ipaddress.IPv4Address(3221225985)
|
||||
>>> ipaddress.IPv4Address(3232235521)
|
||||
IPv4Address('192.168.0.1')
|
||||
>>> ipaddress.IPv4Address(b'\xC0\xA8\x00\x01')
|
||||
IPv4Address('192.168.0.1')
|
||||
|
@ -437,7 +444,7 @@ so to avoid duplication they are only documented for :class:`IPv4Network`.
|
|||
hosts are all the IP addresses that belong to the network, except the
|
||||
network address itself and the network broadcast address.
|
||||
|
||||
>>> list(ip_network('192.0.2.0/29').hosts())
|
||||
>>> list(ip_network('192.0.2.0/29').hosts()) #doctest: +NORMALIZE_WHITESPACE
|
||||
[IPv4Address('192.0.2.1'), IPv4Address('192.0.2.2'),
|
||||
IPv4Address('192.0.2.3'), IPv4Address('192.0.2.4'),
|
||||
IPv4Address('192.0.2.5'), IPv4Address('192.0.2.6')]
|
||||
|
@ -456,7 +463,7 @@ so to avoid duplication they are only documented for :class:`IPv4Network`.
|
|||
|
||||
>>> n1 = ip_network('192.0.2.0/28')
|
||||
>>> n2 = ip_network('192.0.2.1/32')
|
||||
>>> list(n1.address_exclude(n2))
|
||||
>>> list(n1.address_exclude(n2)) #doctest: +NORMALIZE_WHITESPACE
|
||||
[IPv4Network('192.0.2.8/29'), IPv4Network('192.0.2.4/30'),
|
||||
IPv4Network('192.0.2.2/31'), IPv4Network('192.0.2.0/32')]
|
||||
|
||||
|
@ -471,10 +478,10 @@ so to avoid duplication they are only documented for :class:`IPv4Network`.
|
|||
|
||||
>>> list(ip_network('192.0.2.0/24').subnets())
|
||||
[IPv4Network('192.0.2.0/25'), IPv4Network('192.0.2.128/25')]
|
||||
>>> list(ip_network('192.0.2.0/24').subnets(prefixlen_diff=2))
|
||||
>>> list(ip_network('192.0.2.0/24').subnets(prefixlen_diff=2)) #doctest: +NORMALIZE_WHITESPACE
|
||||
[IPv4Network('192.0.2.0/26'), IPv4Network('192.0.2.64/26'),
|
||||
IPv4Network('192.0.2.128/26'), IPv4Network('192.0.2.192/26')]
|
||||
>>> list(ip_network('192.0.2.0/24').subnets(new_prefix=26))
|
||||
>>> list(ip_network('192.0.2.0/24').subnets(new_prefix=26)) #doctest: +NORMALIZE_WHITESPACE
|
||||
[IPv4Network('192.0.2.0/26'), IPv4Network('192.0.2.64/26'),
|
||||
IPv4Network('192.0.2.128/26'), IPv4Network('192.0.2.192/26')]
|
||||
>>> list(ip_network('192.0.2.0/24').subnets(new_prefix=23))
|
||||
|
|
|
@ -9,20 +9,13 @@ data markup. This includes modules to work with the Standard Generalized Markup
|
|||
Language (SGML) and the Hypertext Markup Language (HTML), and several interfaces
|
||||
for working with the Extensible Markup Language (XML).
|
||||
|
||||
It is important to note that modules in the :mod:`xml` package require that
|
||||
there be at least one SAX-compliant XML parser available. The Expat parser is
|
||||
included with Python, so the :mod:`xml.parsers.expat` module will always be
|
||||
available.
|
||||
|
||||
The documentation for the :mod:`xml.dom` and :mod:`xml.sax` packages are the
|
||||
definition of the Python bindings for the DOM and SAX interfaces.
|
||||
|
||||
|
||||
.. toctree::
|
||||
|
||||
html.rst
|
||||
html.parser.rst
|
||||
html.entities.rst
|
||||
xml.rst
|
||||
xml.etree.elementtree.rst
|
||||
xml.dom.rst
|
||||
xml.dom.minidom.rst
|
||||
|
|
|
@ -29,7 +29,7 @@ Windows.
|
|||
Functionality within this package requires that the ``__main__`` module be
|
||||
importable by the children. This is covered in :ref:`multiprocessing-programming`
|
||||
however it is worth pointing out here. This means that some examples, such
|
||||
as the :class:`multiprocessing.Pool` examples will not work in the
|
||||
as the :class:`multiprocessing.pool.Pool` examples will not work in the
|
||||
interactive interpreter. For example::
|
||||
|
||||
>>> from multiprocessing import Pool
|
||||
|
@ -916,7 +916,7 @@ object -- see :ref:`multiprocessing-managers`.
|
|||
|
||||
.. class:: Condition([lock])
|
||||
|
||||
A condition variable: a clone of :class:`threading.Condition`.
|
||||
A condition variable: an alias for :class:`threading.Condition`.
|
||||
|
||||
If *lock* is specified then it should be a :class:`Lock` or :class:`RLock`
|
||||
object from :mod:`multiprocessing`.
|
||||
|
@ -1638,7 +1638,7 @@ Process Pools
|
|||
One can create a pool of processes which will carry out tasks submitted to it
|
||||
with the :class:`Pool` class.
|
||||
|
||||
.. class:: multiprocessing.Pool([processes[, initializer[, initargs[, maxtasksperchild]]]])
|
||||
.. class:: Pool([processes[, initializer[, initargs[, maxtasksperchild]]]])
|
||||
|
||||
A process pool object which controls a pool of worker processes to which jobs
|
||||
can be submitted. It supports asynchronous results with timeouts and
|
||||
|
|
|
@ -1555,18 +1555,21 @@ features:
|
|||
single: UNC paths; and os.makedirs()
|
||||
|
||||
Recursive directory creation function. Like :func:`mkdir`, but makes all
|
||||
intermediate-level directories needed to contain the leaf directory. If
|
||||
the target directory with the same mode as specified already exists,
|
||||
raises an :exc:`OSError` exception if *exist_ok* is False, otherwise no
|
||||
exception is raised. If the directory cannot be created in other cases,
|
||||
raises an :exc:`OSError` exception. The default *mode* is ``0o777`` (octal).
|
||||
On some systems, *mode* is ignored. Where it is used, the current umask
|
||||
value is first masked out.
|
||||
intermediate-level directories needed to contain the leaf directory.
|
||||
|
||||
The default *mode* is ``0o777`` (octal). On some systems, *mode* is
|
||||
ignored. Where it is used, the current umask value is first masked out.
|
||||
|
||||
If *exists_ok* is ``False`` (the default), an :exc:`OSError` is raised if
|
||||
the target directory already exists. If *exists_ok* is ``True`` an
|
||||
:exc:`OSError` is still raised if the umask-masked *mode* is different from
|
||||
the existing mode, on systems where the mode is used. :exc:`OSError` will
|
||||
also be raised if the directory creation fails.
|
||||
|
||||
.. note::
|
||||
|
||||
:func:`makedirs` will become confused if the path elements to create
|
||||
include :data:`pardir`.
|
||||
include :data:`pardir` (eg. ".." on UNIX systems).
|
||||
|
||||
This function handles UNC paths correctly.
|
||||
|
||||
|
|
|
@ -153,20 +153,22 @@ Server Objects
|
|||
|
||||
.. method:: BaseServer.serve_forever(poll_interval=0.5)
|
||||
|
||||
Handle requests until an explicit :meth:`shutdown` request.
|
||||
Poll for shutdown every *poll_interval* seconds. Ignores :attr:`self.timeout`. It also calls
|
||||
:meth:`service_actions` which may be used by a subclass or Mixin to provide
|
||||
various cleanup actions. For e.g. ForkingMixin class uses
|
||||
:meth:`service_actions` to cleanup the zombie child processes.
|
||||
Handle requests until an explicit :meth:`shutdown` request. Poll for
|
||||
shutdown every *poll_interval* seconds. Ignores :attr:`self.timeout`. It
|
||||
also calls :meth:`service_actions`, which may be used by a subclass or mixin
|
||||
to provide actions specific to a given service. For example, the
|
||||
:class:`ForkingMixIn` class uses :meth:`service_actions` to clean up zombie
|
||||
child processes.
|
||||
|
||||
.. versionchanged:: 3.3
|
||||
Added service_actions call to the serve_forever method.
|
||||
Added ``service_actions`` call to the ``serve_forever`` method.
|
||||
|
||||
|
||||
.. method:: BaseServer.service_actions()
|
||||
|
||||
This is called by the serve_forever loop. This method is can be overridden
|
||||
by Mixin's to add cleanup or service specific actions.
|
||||
This is called in the :meth:`serve_forever` loop. This method is can be
|
||||
overridden by subclasses or mixin classes to perform actions specific to
|
||||
a given service, such as cleanup actions.
|
||||
|
||||
.. versionadded:: 3.3
|
||||
|
||||
|
|
|
@ -222,64 +222,64 @@ Connection Objects
|
|||
|
||||
A SQLite database connection has the following attributes and methods:
|
||||
|
||||
.. attribute:: Connection.isolation_level
|
||||
.. attribute:: isolation_level
|
||||
|
||||
Get or set the current isolation level. :const:`None` for autocommit mode or
|
||||
one of "DEFERRED", "IMMEDIATE" or "EXCLUSIVE". See section
|
||||
:ref:`sqlite3-controlling-transactions` for a more detailed explanation.
|
||||
|
||||
.. attribute:: Connection.in_transaction
|
||||
.. attribute:: in_transaction
|
||||
|
||||
:const:`True` if a transaction is active (there are uncommitted changes),
|
||||
:const:`False` otherwise. Read-only attribute.
|
||||
|
||||
.. versionadded:: 3.2
|
||||
|
||||
.. method:: Connection.cursor([cursorClass])
|
||||
.. method:: cursor([cursorClass])
|
||||
|
||||
The cursor method accepts a single optional parameter *cursorClass*. If
|
||||
supplied, this must be a custom cursor class that extends
|
||||
:class:`sqlite3.Cursor`.
|
||||
|
||||
.. method:: Connection.commit()
|
||||
.. method:: commit()
|
||||
|
||||
This method commits the current transaction. If you don't call this method,
|
||||
anything you did since the last call to ``commit()`` is not visible from
|
||||
other database connections. If you wonder why you don't see the data you've
|
||||
written to the database, please check you didn't forget to call this method.
|
||||
|
||||
.. method:: Connection.rollback()
|
||||
.. method:: rollback()
|
||||
|
||||
This method rolls back any changes to the database since the last call to
|
||||
:meth:`commit`.
|
||||
|
||||
.. method:: Connection.close()
|
||||
.. method:: close()
|
||||
|
||||
This closes the database connection. Note that this does not automatically
|
||||
call :meth:`commit`. If you just close your database connection without
|
||||
calling :meth:`commit` first, your changes will be lost!
|
||||
|
||||
.. method:: Connection.execute(sql, [parameters])
|
||||
.. method:: execute(sql, [parameters])
|
||||
|
||||
This is a nonstandard shortcut that creates an intermediate cursor object by
|
||||
calling the cursor method, then calls the cursor's :meth:`execute
|
||||
<Cursor.execute>` method with the parameters given.
|
||||
|
||||
|
||||
.. method:: Connection.executemany(sql, [parameters])
|
||||
.. method:: executemany(sql, [parameters])
|
||||
|
||||
This is a nonstandard shortcut that creates an intermediate cursor object by
|
||||
calling the cursor method, then calls the cursor's :meth:`executemany
|
||||
<Cursor.executemany>` method with the parameters given.
|
||||
|
||||
.. method:: Connection.executescript(sql_script)
|
||||
.. method:: executescript(sql_script)
|
||||
|
||||
This is a nonstandard shortcut that creates an intermediate cursor object by
|
||||
calling the cursor method, then calls the cursor's :meth:`executescript
|
||||
<Cursor.executescript>` method with the parameters given.
|
||||
|
||||
|
||||
.. method:: Connection.create_function(name, num_params, func)
|
||||
.. method:: create_function(name, num_params, func)
|
||||
|
||||
Creates a user-defined function that you can later use from within SQL
|
||||
statements under the function name *name*. *num_params* is the number of
|
||||
|
@ -294,7 +294,7 @@ Connection Objects
|
|||
.. literalinclude:: ../includes/sqlite3/md5func.py
|
||||
|
||||
|
||||
.. method:: Connection.create_aggregate(name, num_params, aggregate_class)
|
||||
.. method:: create_aggregate(name, num_params, aggregate_class)
|
||||
|
||||
Creates a user-defined aggregate function.
|
||||
|
||||
|
@ -310,7 +310,7 @@ Connection Objects
|
|||
.. literalinclude:: ../includes/sqlite3/mysumaggr.py
|
||||
|
||||
|
||||
.. method:: Connection.create_collation(name, callable)
|
||||
.. method:: create_collation(name, callable)
|
||||
|
||||
Creates a collation with the specified *name* and *callable*. The callable will
|
||||
be passed two string arguments. It should return -1 if the first is ordered
|
||||
|
@ -330,14 +330,14 @@ Connection Objects
|
|||
con.create_collation("reverse", None)
|
||||
|
||||
|
||||
.. method:: Connection.interrupt()
|
||||
.. method:: interrupt()
|
||||
|
||||
You can call this method from a different thread to abort any queries that might
|
||||
be executing on the connection. The query will then abort and the caller will
|
||||
get an exception.
|
||||
|
||||
|
||||
.. method:: Connection.set_authorizer(authorizer_callback)
|
||||
.. method:: set_authorizer(authorizer_callback)
|
||||
|
||||
This routine registers a callback. The callback is invoked for each attempt to
|
||||
access a column of a table in the database. The callback should return
|
||||
|
@ -358,7 +358,7 @@ Connection Objects
|
|||
one. All necessary constants are available in the :mod:`sqlite3` module.
|
||||
|
||||
|
||||
.. method:: Connection.set_progress_handler(handler, n)
|
||||
.. method:: set_progress_handler(handler, n)
|
||||
|
||||
This routine registers a callback. The callback is invoked for every *n*
|
||||
instructions of the SQLite virtual machine. This is useful if you want to
|
||||
|
@ -369,7 +369,7 @@ Connection Objects
|
|||
method with :const:`None` for *handler*.
|
||||
|
||||
|
||||
.. method:: Connection.set_trace_callback(trace_callback)
|
||||
.. method:: set_trace_callback(trace_callback)
|
||||
|
||||
Registers *trace_callback* to be called for each SQL statement that is
|
||||
actually executed by the SQLite backend.
|
||||
|
@ -385,7 +385,7 @@ Connection Objects
|
|||
.. versionadded:: 3.3
|
||||
|
||||
|
||||
.. method:: Connection.enable_load_extension(enabled)
|
||||
.. method:: enable_load_extension(enabled)
|
||||
|
||||
This routine allows/disallows the SQLite engine to load SQLite extensions
|
||||
from shared libraries. SQLite extensions can define new functions,
|
||||
|
@ -398,7 +398,7 @@ Connection Objects
|
|||
|
||||
.. literalinclude:: ../includes/sqlite3/load_extension.py
|
||||
|
||||
.. method:: Connection.load_extension(path)
|
||||
.. method:: load_extension(path)
|
||||
|
||||
This routine loads a SQLite extension from a shared library. You have to
|
||||
enable extension loading with :meth:`enable_load_extension` before you can
|
||||
|
@ -408,7 +408,7 @@ Connection Objects
|
|||
|
||||
.. versionadded:: 3.2
|
||||
|
||||
.. attribute:: Connection.row_factory
|
||||
.. attribute:: row_factory
|
||||
|
||||
You can change this attribute to a callable that accepts the cursor and the
|
||||
original row as a tuple and will return the real result row. This way, you can
|
||||
|
@ -429,13 +429,17 @@ Connection Objects
|
|||
.. XXX what's a db_row-based solution?
|
||||
|
||||
|
||||
.. attribute:: Connection.text_factory
|
||||
.. attribute:: text_factory
|
||||
|
||||
Using this attribute you can control what objects are returned for the ``TEXT``
|
||||
data type. By default, this attribute is set to :class:`str` and the
|
||||
:mod:`sqlite3` module will return Unicode objects for ``TEXT``. If you want to
|
||||
return bytestrings instead, you can set it to :class:`bytes`.
|
||||
|
||||
For efficiency reasons, there's also a way to return :class:`str` objects
|
||||
only for non-ASCII data, and :class:`bytes` otherwise. To activate it, set
|
||||
this attribute to :const:`sqlite3.OptimizedUnicode`.
|
||||
|
||||
You can also set it to any other callable that accepts a single bytestring
|
||||
parameter and returns the resulting object.
|
||||
|
||||
|
@ -444,13 +448,13 @@ Connection Objects
|
|||
.. literalinclude:: ../includes/sqlite3/text_factory.py
|
||||
|
||||
|
||||
.. attribute:: Connection.total_changes
|
||||
.. attribute:: total_changes
|
||||
|
||||
Returns the total number of database rows that have been modified, inserted, or
|
||||
deleted since the database connection was opened.
|
||||
|
||||
|
||||
.. attribute:: Connection.iterdump
|
||||
.. attribute:: iterdump
|
||||
|
||||
Returns an iterator to dump the database in an SQL text format. Useful when
|
||||
saving an in-memory database for later restoration. This function provides
|
||||
|
@ -477,7 +481,7 @@ Cursor Objects
|
|||
|
||||
A :class:`Cursor` instance has the following attributes and methods.
|
||||
|
||||
.. method:: Cursor.execute(sql, [parameters])
|
||||
.. method:: execute(sql, [parameters])
|
||||
|
||||
Executes an SQL statement. The SQL statement may be parametrized (i. e.
|
||||
placeholders instead of SQL literals). The :mod:`sqlite3` module supports two
|
||||
|
@ -494,7 +498,7 @@ Cursor Objects
|
|||
call.
|
||||
|
||||
|
||||
.. method:: Cursor.executemany(sql, seq_of_parameters)
|
||||
.. method:: executemany(sql, seq_of_parameters)
|
||||
|
||||
Executes an SQL command against all parameter sequences or mappings found in
|
||||
the sequence *sql*. The :mod:`sqlite3` module also allows using an
|
||||
|
@ -507,7 +511,7 @@ Cursor Objects
|
|||
.. literalinclude:: ../includes/sqlite3/executemany_2.py
|
||||
|
||||
|
||||
.. method:: Cursor.executescript(sql_script)
|
||||
.. method:: executescript(sql_script)
|
||||
|
||||
This is a nonstandard convenience method for executing multiple SQL statements
|
||||
at once. It issues a ``COMMIT`` statement first, then executes the SQL script it
|
||||
|
@ -520,13 +524,13 @@ Cursor Objects
|
|||
.. literalinclude:: ../includes/sqlite3/executescript.py
|
||||
|
||||
|
||||
.. method:: Cursor.fetchone()
|
||||
.. method:: fetchone()
|
||||
|
||||
Fetches the next row of a query result set, returning a single sequence,
|
||||
or :const:`None` when no more data is available.
|
||||
|
||||
|
||||
.. method:: Cursor.fetchmany(size=cursor.arraysize)
|
||||
.. method:: fetchmany(size=cursor.arraysize)
|
||||
|
||||
Fetches the next set of rows of a query result, returning a list. An empty
|
||||
list is returned when no more rows are available.
|
||||
|
@ -542,14 +546,14 @@ Cursor Objects
|
|||
If the *size* parameter is used, then it is best for it to retain the same
|
||||
value from one :meth:`fetchmany` call to the next.
|
||||
|
||||
.. method:: Cursor.fetchall()
|
||||
.. method:: fetchall()
|
||||
|
||||
Fetches all (remaining) rows of a query result, returning a list. Note that
|
||||
the cursor's arraysize attribute can affect the performance of this operation.
|
||||
An empty list is returned when no rows are available.
|
||||
|
||||
|
||||
.. attribute:: Cursor.rowcount
|
||||
.. attribute:: rowcount
|
||||
|
||||
Although the :class:`Cursor` class of the :mod:`sqlite3` module implements this
|
||||
attribute, the database engine's own support for the determination of "rows
|
||||
|
@ -567,14 +571,14 @@ Cursor Objects
|
|||
With SQLite versions before 3.6.5, :attr:`rowcount` is set to 0 if
|
||||
you make a ``DELETE FROM table`` without any condition.
|
||||
|
||||
.. attribute:: Cursor.lastrowid
|
||||
.. attribute:: lastrowid
|
||||
|
||||
This read-only attribute provides the rowid of the last modified row. It is
|
||||
only set if you issued a ``INSERT`` statement using the :meth:`execute`
|
||||
method. For operations other than ``INSERT`` or when :meth:`executemany` is
|
||||
called, :attr:`lastrowid` is set to :const:`None`.
|
||||
|
||||
.. attribute:: Cursor.description
|
||||
.. attribute:: description
|
||||
|
||||
This read-only attribute provides the column names of the last query. To
|
||||
remain compatible with the Python DB API, it returns a 7-tuple for each
|
||||
|
|
|
@ -358,20 +358,15 @@ functions.
|
|||
|
||||
Arguments are:
|
||||
|
||||
*args* should be a string, or a sequence of program arguments. The program
|
||||
to execute is normally the first item in the args sequence or the string if
|
||||
a string is given, but can be explicitly set by using the *executable*
|
||||
argument. When *executable* is given, the first item in the args sequence
|
||||
is still treated by most programs as the command name, which can then be
|
||||
different from the actual executable name. On Unix, it becomes the display
|
||||
name for the executing program in utilities such as :program:`ps`.
|
||||
*args* should be a sequence of program arguments or else a single string.
|
||||
By default, the program to execute is the first item in *args* if *args* is
|
||||
a sequence and the string itself if *args* is a string. However, see the
|
||||
*shell* and *executable* arguments for differences from this behavior.
|
||||
|
||||
On Unix, with *shell=False* (default): In this case, the Popen class uses
|
||||
:meth:`os.execvp` like behavior to execute the child program.
|
||||
*args* should normally be a
|
||||
sequence. If a string is specified for *args*, it will be used as the name
|
||||
or path of the program to execute; this will only work if the program is
|
||||
being given no arguments.
|
||||
On Unix, the :class:`Popen` class uses :meth:`os.execvp`-like behavior to
|
||||
execute the child program. If *args* is a string, the string is
|
||||
interpreted as the name or path of the program to execute; this only works
|
||||
if the program is being given no arguments.
|
||||
|
||||
.. note::
|
||||
|
||||
|
@ -392,13 +387,23 @@ functions.
|
|||
used in the shell (such as filenames containing spaces or the *echo* command
|
||||
shown above) are single list elements.
|
||||
|
||||
On Unix, with *shell=True*: If args is a string, it specifies the command
|
||||
string to execute through the shell. This means that the string must be
|
||||
On Windows, the :class:`Popen` class uses ``CreateProcess()`` to
|
||||
execute the child program, which operates on strings. If *args* is a
|
||||
sequence, it will be converted to a string in a manner described in
|
||||
:ref:`converting-argument-sequence`.
|
||||
|
||||
The *shell* argument (which defaults to *False*) specifies whether to use
|
||||
the shell as the program to execute. It is recommended to pass *args* as a
|
||||
sequence if *shell* is *False* and as a string if *shell* is *True*.
|
||||
|
||||
On Unix with ``shell=True``, the shell defaults to :file:`/bin/sh`. If
|
||||
*args* is a string, the string specifies the command
|
||||
to execute through the shell. This means that the string must be
|
||||
formatted exactly as it would be when typed at the shell prompt. This
|
||||
includes, for example, quoting or backslash escaping filenames with spaces in
|
||||
them. If *args* is a sequence, the first item specifies the command string, and
|
||||
any additional items will be treated as additional arguments to the shell
|
||||
itself. That is to say, *Popen* does the equivalent of::
|
||||
itself. That is to say, :class:`Popen` does the equivalent of::
|
||||
|
||||
Popen(['/bin/sh', '-c', args[0], args[1], ...])
|
||||
|
||||
|
@ -408,10 +413,11 @@ functions.
|
|||
input. See the warning under :ref:`frequently-used-arguments`
|
||||
for details.
|
||||
|
||||
On Windows: the :class:`Popen` class uses CreateProcess() to execute the
|
||||
child program, which operates on strings. If *args* is a sequence, it will
|
||||
be converted to a string in a manner described in
|
||||
:ref:`converting-argument-sequence`.
|
||||
On Windows with ``shell=True``, the :envvar:`COMSPEC` environment variable
|
||||
specifies the default shell. The only time you need to specify
|
||||
``shell=True`` on Windows is when the command you wish to execute is built
|
||||
into the shell (e.g. :command:`dir` or :command:`copy`). You do not need
|
||||
``shell=True`` to run a batch file or console-based executable.
|
||||
|
||||
*bufsize*, if given, has the same meaning as the corresponding argument to the
|
||||
built-in open() function: :const:`0` means unbuffered, :const:`1` means line
|
||||
|
@ -425,15 +431,14 @@ functions.
|
|||
enable buffering by setting *bufsize* to either -1 or a large enough
|
||||
positive value (such as 4096).
|
||||
|
||||
The *executable* argument specifies the program to execute. It is very seldom
|
||||
needed: Usually, the program to execute is defined by the *args* argument. If
|
||||
``shell=True``, the *executable* argument specifies which shell to use. On Unix,
|
||||
the default shell is :file:`/bin/sh`. On Windows, the default shell is
|
||||
specified by the :envvar:`COMSPEC` environment variable. The only reason you
|
||||
would need to specify ``shell=True`` on Windows is where the command you
|
||||
wish to execute is actually built in to the shell, eg ``dir``, ``copy``.
|
||||
You don't need ``shell=True`` to run a batch file, nor to run a console-based
|
||||
executable.
|
||||
The *executable* argument specifies a replacement program to execute. It
|
||||
is very seldom needed. When ``shell=False``, *executable* replaces the
|
||||
program to execute specified by *args*. However, the *args* program is
|
||||
still treated by most programs as the command name, which can then be
|
||||
different from the program actually executed. On Unix, the *args* name
|
||||
becomes the display name for the executable in utilities such as
|
||||
:program:`ps`. If ``shell=True``, on Unix the *executable* argument
|
||||
specifies a replacement shell for the default :file:`/bin/sh`.
|
||||
|
||||
*stdin*, *stdout* and *stderr* specify the executed program's standard input,
|
||||
standard output and standard error file handles, respectively. Valid values
|
||||
|
@ -484,10 +489,10 @@ functions.
|
|||
.. versionadded:: 3.2
|
||||
The *pass_fds* parameter was added.
|
||||
|
||||
If *cwd* is not ``None``, the child's current directory will be changed to *cwd*
|
||||
before it is executed. Note that this directory is not considered when
|
||||
searching the executable, so you can't specify the program's path relative to
|
||||
*cwd*.
|
||||
If *cwd* is not ``None``, the function changes the working directory to
|
||||
*cwd* before executing the child. In particular, the function looks for
|
||||
*executable* (or for the first item in *args*) relative to *cwd* if the
|
||||
executable path is a relative path.
|
||||
|
||||
If *restore_signals* is True (the default) all signals that Python has set to
|
||||
SIG_IGN are restored to SIG_DFL in the child process before the exec.
|
||||
|
|
|
@ -86,6 +86,9 @@ The module defines the following user-callable items:
|
|||
whether :func:`rollover` has been called. This file-like object can be
|
||||
used in a :keyword:`with` statement, just like a normal file.
|
||||
|
||||
.. versionchanged:: 3.3
|
||||
the truncate method now accepts a ``size`` argument.
|
||||
|
||||
|
||||
.. function:: TemporaryDirectory(suffix='', prefix='tmp', dir=None)
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ The :mod:`dummy_threading` module is provided for situations where
|
|||
supported by this module.
|
||||
|
||||
|
||||
This module defines the following functions and objects:
|
||||
This module defines the following functions:
|
||||
|
||||
|
||||
.. function:: active_count()
|
||||
|
@ -30,16 +30,6 @@ This module defines the following functions and objects:
|
|||
count is equal to the length of the list returned by :func:`.enumerate`.
|
||||
|
||||
|
||||
.. function:: Condition()
|
||||
:noindex:
|
||||
|
||||
A factory function that returns a new condition variable object. A condition
|
||||
variable allows one or more threads to wait until they are notified by another
|
||||
thread.
|
||||
|
||||
See :ref:`condition-objects`.
|
||||
|
||||
|
||||
.. function:: current_thread()
|
||||
|
||||
Return the current :class:`Thread` object, corresponding to the caller's thread
|
||||
|
@ -67,88 +57,6 @@ This module defines the following functions and objects:
|
|||
and threads that have not yet been started.
|
||||
|
||||
|
||||
.. function:: Event()
|
||||
:noindex:
|
||||
|
||||
A factory function that returns a new event object. An event manages a flag
|
||||
that can be set to true with the :meth:`~Event.set` method and reset to false
|
||||
with the :meth:`clear` method. The :meth:`wait` method blocks until the flag
|
||||
is true.
|
||||
|
||||
See :ref:`event-objects`.
|
||||
|
||||
|
||||
.. class:: local
|
||||
|
||||
A class that represents thread-local data. Thread-local data are data whose
|
||||
values are thread specific. To manage thread-local data, just create an
|
||||
instance of :class:`local` (or a subclass) and store attributes on it::
|
||||
|
||||
mydata = threading.local()
|
||||
mydata.x = 1
|
||||
|
||||
The instance's values will be different for separate threads.
|
||||
|
||||
For more details and extensive examples, see the documentation string of the
|
||||
:mod:`_threading_local` module.
|
||||
|
||||
|
||||
.. function:: Lock()
|
||||
|
||||
A factory function that returns a new primitive lock object. Once a thread has
|
||||
acquired it, subsequent attempts to acquire it block, until it is released; any
|
||||
thread may release it.
|
||||
|
||||
See :ref:`lock-objects`.
|
||||
|
||||
|
||||
.. function:: RLock()
|
||||
|
||||
A factory function that returns a new reentrant lock object. A reentrant lock
|
||||
must be released by the thread that acquired it. Once a thread has acquired a
|
||||
reentrant lock, the same thread may acquire it again without blocking; the
|
||||
thread must release it once for each time it has acquired it.
|
||||
|
||||
See :ref:`rlock-objects`.
|
||||
|
||||
|
||||
.. function:: Semaphore(value=1)
|
||||
:noindex:
|
||||
|
||||
A factory function that returns a new semaphore object. A semaphore manages a
|
||||
counter representing the number of :meth:`release` calls minus the number of
|
||||
:meth:`acquire` calls, plus an initial value. The :meth:`acquire` method blocks
|
||||
if necessary until it can return without making the counter negative. If not
|
||||
given, *value* defaults to 1.
|
||||
|
||||
See :ref:`semaphore-objects`.
|
||||
|
||||
|
||||
.. function:: BoundedSemaphore(value=1)
|
||||
|
||||
A factory function that returns a new bounded semaphore object. A bounded
|
||||
semaphore checks to make sure its current value doesn't exceed its initial
|
||||
value. If it does, :exc:`ValueError` is raised. In most situations semaphores
|
||||
are used to guard resources with limited capacity. If the semaphore is released
|
||||
too many times it's a sign of a bug. If not given, *value* defaults to 1.
|
||||
|
||||
|
||||
.. class:: Thread
|
||||
|
||||
A class that represents a thread of control. This class can be safely
|
||||
subclassed in a limited fashion.
|
||||
|
||||
See :ref:`thread-objects`.
|
||||
|
||||
|
||||
.. class:: Timer
|
||||
:noindex:
|
||||
|
||||
A thread that executes a function after a specified interval has passed.
|
||||
|
||||
See :ref:`timer-objects`.
|
||||
|
||||
|
||||
.. function:: settrace(func)
|
||||
|
||||
.. index:: single: trace function
|
||||
|
@ -197,7 +105,8 @@ This module also defines the following constant:
|
|||
.. versionadded:: 3.2
|
||||
|
||||
|
||||
Detailed interfaces for the objects are documented below.
|
||||
This module defines a number of classes, which are detailed in the sections
|
||||
below.
|
||||
|
||||
The design of this module is loosely based on Java's threading model. However,
|
||||
where Java makes locks and condition variables basic behavior of every object,
|
||||
|
@ -210,17 +119,38 @@ when implemented, are mapped to module-level functions.
|
|||
All of the methods described below are executed atomically.
|
||||
|
||||
|
||||
Thread-Local Data
|
||||
-----------------
|
||||
|
||||
Thread-local data is data whose values are thread specific. To manage
|
||||
thread-local data, just create an instance of :class:`local` (or a
|
||||
subclass) and store attributes on it::
|
||||
|
||||
mydata = threading.local()
|
||||
mydata.x = 1
|
||||
|
||||
The instance's values will be different for separate threads.
|
||||
|
||||
|
||||
.. class:: local()
|
||||
|
||||
A class that represents thread-local data.
|
||||
|
||||
For more details and extensive examples, see the documentation string of the
|
||||
:mod:`_threading_local` module.
|
||||
|
||||
|
||||
.. _thread-objects:
|
||||
|
||||
Thread Objects
|
||||
--------------
|
||||
|
||||
This class represents an activity that is run in a separate thread of control.
|
||||
There are two ways to specify the activity: by passing a callable object to the
|
||||
constructor, or by overriding the :meth:`~Thread.run` method in a subclass.
|
||||
No other methods (except for the constructor) should be overridden in a
|
||||
subclass. In other words, *only* override the :meth:`~Thread.__init__`
|
||||
and :meth:`~Thread.run` methods of this class.
|
||||
The :class:`Thread` class represents an activity that is run in a separate
|
||||
thread of control. There are two ways to specify the activity: by passing a
|
||||
callable object to the constructor, or by overriding the :meth:`~Thread.run`
|
||||
method in a subclass. No other methods (except for the constructor) should be
|
||||
overridden in a subclass. In other words, *only* override the
|
||||
:meth:`~Thread.__init__` and :meth:`~Thread.run` methods of this class.
|
||||
|
||||
Once a thread object is created, its activity must be started by calling the
|
||||
thread's :meth:`~Thread.start` method. This invokes the :meth:`~Thread.run`
|
||||
|
@ -419,7 +349,17 @@ is not defined, and may vary across implementations.
|
|||
All methods are executed atomically.
|
||||
|
||||
|
||||
.. method:: Lock.acquire(blocking=True, timeout=-1)
|
||||
.. class:: Lock()
|
||||
|
||||
The class implementing primitive lock objects. Once a thread has acquired a
|
||||
lock, subsequent attempts to acquire it block, until it is released; any
|
||||
thread may release it.
|
||||
|
||||
.. versionchanged:: 3.3
|
||||
Changed from a factory function to a class.
|
||||
|
||||
|
||||
.. method:: acquire(blocking=True, timeout=-1)
|
||||
|
||||
Acquire a lock, blocking or non-blocking.
|
||||
|
||||
|
@ -446,7 +386,7 @@ All methods are executed atomically.
|
|||
Lock acquires can now be interrupted by signals on POSIX.
|
||||
|
||||
|
||||
.. method:: Lock.release()
|
||||
.. method:: release()
|
||||
|
||||
Release a lock. This can be called from any thread, not only the thread
|
||||
which has acquired the lock.
|
||||
|
@ -481,7 +421,19 @@ allows another thread blocked in :meth:`~Lock.acquire` to proceed.
|
|||
Reentrant locks also support the :ref:`context manager protocol <with-locks>`.
|
||||
|
||||
|
||||
.. method:: RLock.acquire(blocking=True, timeout=-1)
|
||||
.. class:: RLock()
|
||||
|
||||
This class implements reentrant lock objects. A reentrant lock must be
|
||||
released by the thread that acquired it. Once a thread has acquired a
|
||||
reentrant lock, the same thread may acquire it again without blocking; the
|
||||
thread must release it once for each time it has acquired it.
|
||||
|
||||
Note that ``RLock`` is actually a factory function which returns an instance
|
||||
of the most efficient version of the concrete RLock class that is supported
|
||||
by the platform.
|
||||
|
||||
|
||||
.. method:: acquire(blocking=True, timeout=-1)
|
||||
|
||||
Acquire a lock, blocking or non-blocking.
|
||||
|
||||
|
@ -509,7 +461,7 @@ Reentrant locks also support the :ref:`context manager protocol <with-locks>`.
|
|||
The *timeout* parameter is new.
|
||||
|
||||
|
||||
.. method:: RLock.release()
|
||||
.. method:: release()
|
||||
|
||||
Release a lock, decrementing the recursion level. If after the decrement it is
|
||||
zero, reset the lock to unlocked (not owned by any thread), and if any other
|
||||
|
@ -556,10 +508,6 @@ not return from their :meth:`~Condition.wait` call immediately, but only when
|
|||
the thread that called :meth:`~Condition.notify` or :meth:`~Condition.notify_all`
|
||||
finally relinquishes ownership of the lock.
|
||||
|
||||
|
||||
Usage
|
||||
^^^^^
|
||||
|
||||
The typical programming style using condition variables uses the lock to
|
||||
synchronize access to some shared state; threads that are interested in a
|
||||
particular change of state call :meth:`~Condition.wait` repeatedly until they
|
||||
|
@ -598,15 +546,18 @@ waiting threads. E.g. in a typical producer-consumer situation, adding one
|
|||
item to the buffer only needs to wake up one consumer thread.
|
||||
|
||||
|
||||
Interface
|
||||
^^^^^^^^^
|
||||
|
||||
.. class:: Condition(lock=None)
|
||||
|
||||
This class implements condition variable objects. A condition variable
|
||||
allows one or more threads to wait until they are notified by another thread.
|
||||
|
||||
If the *lock* argument is given and not ``None``, it must be a :class:`Lock`
|
||||
or :class:`RLock` object, and it is used as the underlying lock. Otherwise,
|
||||
a new :class:`RLock` object is created and used as the underlying lock.
|
||||
|
||||
.. versionchanged:: 3.3
|
||||
changed from a factory function to a class.
|
||||
|
||||
.. method:: acquire(*args)
|
||||
|
||||
Acquire the underlying lock. This method calls the corresponding method on
|
||||
|
@ -716,10 +667,19 @@ Semaphores also support the :ref:`context manager protocol <with-locks>`.
|
|||
|
||||
.. class:: Semaphore(value=1)
|
||||
|
||||
This class implements semaphore objects. A semaphore manages a counter
|
||||
representing the number of :meth:`release` calls minus the number of
|
||||
:meth:`acquire` calls, plus an initial value. The :meth:`acquire` method
|
||||
blocks if necessary until it can return without making the counter negative.
|
||||
If not given, *value* defaults to 1.
|
||||
|
||||
The optional argument gives the initial *value* for the internal counter; it
|
||||
defaults to ``1``. If the *value* given is less than 0, :exc:`ValueError` is
|
||||
raised.
|
||||
|
||||
.. versionchanged:: 3.3
|
||||
changed from a factory function to a class.
|
||||
|
||||
.. method:: acquire(blocking=True, timeout=None)
|
||||
|
||||
Acquire a semaphore.
|
||||
|
@ -752,6 +712,18 @@ Semaphores also support the :ref:`context manager protocol <with-locks>`.
|
|||
than zero again, wake up that thread.
|
||||
|
||||
|
||||
.. class:: BoundedSemaphore(value=1)
|
||||
|
||||
Class implementing bounded semaphore objects. A bounded semaphore checks to
|
||||
make sure its current value doesn't exceed its initial value. If it does,
|
||||
:exc:`ValueError` is raised. In most situations semaphores are used to guard
|
||||
resources with limited capacity. If the semaphore is released too many times
|
||||
it's a sign of a bug. If not given, *value* defaults to 1.
|
||||
|
||||
.. versionchanged:: 3.3
|
||||
changed from a factory function to a class.
|
||||
|
||||
|
||||
.. _semaphore-examples:
|
||||
|
||||
:class:`Semaphore` Example
|
||||
|
@ -763,7 +735,7 @@ you should use a bounded semaphore. Before spawning any worker threads, your
|
|||
main thread would initialize the semaphore::
|
||||
|
||||
maxconnections = 5
|
||||
...
|
||||
# ...
|
||||
pool_sema = BoundedSemaphore(value=maxconnections)
|
||||
|
||||
Once spawned, worker threads call the semaphore's acquire and release methods
|
||||
|
@ -772,7 +744,7 @@ when they need to connect to the server::
|
|||
with pool_sema:
|
||||
conn = connectdb()
|
||||
try:
|
||||
... use connection ...
|
||||
# ... use connection ...
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
|
@ -795,7 +767,13 @@ method. The :meth:`~Event.wait` method blocks until the flag is true.
|
|||
|
||||
.. class:: Event()
|
||||
|
||||
The internal flag is initially false.
|
||||
Class implementing event objects. An event manages a flag that can be set to
|
||||
true with the :meth:`~Event.set` method and reset to false with the
|
||||
:meth:`clear` method. The :meth:`wait` method blocks until the flag is true.
|
||||
The flag is initially false.
|
||||
|
||||
.. versionchanged:: 3.3
|
||||
changed from a factory function to a class.
|
||||
|
||||
.. method:: is_set()
|
||||
|
||||
|
@ -860,6 +838,9 @@ For example::
|
|||
Create a timer that will run *function* with arguments *args* and keyword
|
||||
arguments *kwargs*, after *interval* seconds have passed.
|
||||
|
||||
.. versionchanged:: 3.3
|
||||
changed from a factory function to a class.
|
||||
|
||||
.. method:: cancel()
|
||||
|
||||
Stop the timer, and cancel the execution of the timer's action. This will
|
||||
|
|
|
@ -557,7 +557,7 @@ The module defines the following functions and data items:
|
|||
:exc:`TypeError` is raised.
|
||||
|
||||
.. versionchanged:: 3.3
|
||||
:attr:`tm_gmtoff` and :attr:`tm_zone` attributes are avaliable on platforms
|
||||
:attr:`tm_gmtoff` and :attr:`tm_zone` attributes are available on platforms
|
||||
with C library supporting the corresponding fields in ``struct tm``.
|
||||
|
||||
.. function:: time()
|
||||
|
|
|
@ -14,25 +14,83 @@
|
|||
--------------
|
||||
|
||||
This module provides a simple way to time small bits of Python code. It has both
|
||||
command line as well as callable interfaces. It avoids a number of common traps
|
||||
for measuring execution times. See also Tim Peters' introduction to the
|
||||
"Algorithms" chapter in the Python Cookbook, published by O'Reilly.
|
||||
a :ref:`command-line-interface` as well as a :ref:`callable <python-interface>`
|
||||
one. It avoids a number of common traps for measuring execution times.
|
||||
See also Tim Peters' introduction to the "Algorithms" chapter in the *Python
|
||||
Cookbook*, published by O'Reilly.
|
||||
|
||||
The module defines the following public class:
|
||||
|
||||
Basic Examples
|
||||
--------------
|
||||
|
||||
The following example shows how the :ref:`command-line-interface`
|
||||
can be used to compare three different expressions:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
$ python -m timeit '"-".join(str(n) for n in range(100))'
|
||||
10000 loops, best of 3: 40.3 usec per loop
|
||||
$ python -m timeit '"-".join([str(n) for n in range(100)])'
|
||||
10000 loops, best of 3: 33.4 usec per loop
|
||||
$ python -m timeit '"-".join(map(str, range(100)))'
|
||||
10000 loops, best of 3: 25.2 usec per loop
|
||||
|
||||
This can be achieved from the :ref:`python-interface` with::
|
||||
|
||||
>>> import timeit
|
||||
>>> timeit.timeit('"-".join(str(n) for n in range(100))', number=10000)
|
||||
0.8187260627746582
|
||||
>>> timeit.timeit('"-".join([str(n) for n in range(100)])', number=10000)
|
||||
0.7288308143615723
|
||||
>>> timeit.timeit('"-".join(map(str, range(100)))', number=10000)
|
||||
0.5858950614929199
|
||||
|
||||
Note however that :mod:`timeit` will automatically determine the number of
|
||||
repetitions only when the command-line interface is used. In the
|
||||
:ref:`timeit-examples` section you can find more advanced examples.
|
||||
|
||||
|
||||
.. _python-interface:
|
||||
|
||||
Python Interface
|
||||
----------------
|
||||
|
||||
The module defines three convenience functions and a public class:
|
||||
|
||||
|
||||
.. function:: timeit(stmt='pass', setup='pass', timer=<default timer>, number=1000000)
|
||||
|
||||
Create a :class:`Timer` instance with the given statement, *setup* code and
|
||||
*timer* function and run its :meth:`.timeit` method with *number* executions.
|
||||
|
||||
|
||||
.. function:: repeat(stmt='pass', setup='pass', timer=<default timer>, repeat=3, number=1000000)
|
||||
|
||||
Create a :class:`Timer` instance with the given statement, *setup* code and
|
||||
*timer* function and run its :meth:`.repeat` method with the given *repeat*
|
||||
count and *number* executions.
|
||||
|
||||
|
||||
.. function:: default_timer()
|
||||
|
||||
The default timer, which is always :func:`time.perf_counter`.
|
||||
|
||||
.. versionchanged:: 3.3
|
||||
:func:`time.perf_counter` is now the default timer.
|
||||
|
||||
|
||||
.. class:: Timer(stmt='pass', setup='pass', timer=<timer function>)
|
||||
|
||||
Class for timing execution speed of small code snippets.
|
||||
|
||||
The constructor takes a statement to be timed, an additional statement used for
|
||||
setup, and a timer function. Both statements default to ``'pass'``; the timer
|
||||
function is platform-dependent (see the module doc string). *stmt* and *setup*
|
||||
may also contain multiple statements separated by ``;`` or newlines, as long as
|
||||
they don't contain multi-line string literals.
|
||||
The constructor takes a statement to be timed, an additional statement used
|
||||
for setup, and a timer function. Both statements default to ``'pass'``;
|
||||
the timer function is platform-dependent (see the module doc string).
|
||||
*stmt* and *setup* may also contain multiple statements separated by ``;``
|
||||
or newlines, as long as they don't contain multi-line string literals.
|
||||
|
||||
To measure the execution time of the first statement, use the :meth:`Timer.timeit`
|
||||
method. The :meth:`repeat` method is a convenience to call :meth:`.timeit`
|
||||
To measure the execution time of the first statement, use the :meth:`.timeit`
|
||||
method. The :meth:`.repeat` method is a convenience to call :meth:`.timeit`
|
||||
multiple times and return a list of results.
|
||||
|
||||
The *stmt* and *setup* parameters can also take objects that are callable
|
||||
|
@ -41,6 +99,49 @@ The module defines the following public class:
|
|||
little larger in this case because of the extra function calls.
|
||||
|
||||
|
||||
.. method:: Timer.timeit(number=1000000)
|
||||
|
||||
Time *number* executions of the main statement. This executes the setup
|
||||
statement once, and then returns the time it takes to execute the main
|
||||
statement a number of times, measured in seconds as a float.
|
||||
The argument is the number of times through the loop, defaulting to one
|
||||
million. The main statement, the setup statement and the timer function
|
||||
to be used are passed to the constructor.
|
||||
|
||||
.. note::
|
||||
|
||||
By default, :meth:`.timeit` temporarily turns off :term:`garbage
|
||||
collection` during the timing. The advantage of this approach is that
|
||||
it makes independent timings more comparable. This disadvantage is
|
||||
that GC may be an important component of the performance of the
|
||||
function being measured. If so, GC can be re-enabled as the first
|
||||
statement in the *setup* string. For example::
|
||||
|
||||
timeit.Timer('for i in range(10): oct(i)', 'gc.enable()').timeit()
|
||||
|
||||
|
||||
.. method:: Timer.repeat(repeat=3, number=1000000)
|
||||
|
||||
Call :meth:`.timeit` a few times.
|
||||
|
||||
This is a convenience function that calls the :meth:`.timeit` repeatedly,
|
||||
returning a list of results. The first argument specifies how many times
|
||||
to call :meth:`.timeit`. The second argument specifies the *number*
|
||||
argument for :meth:`.timeit`.
|
||||
|
||||
.. note::
|
||||
|
||||
It's tempting to calculate mean and standard deviation from the result
|
||||
vector and report these. However, this is not very useful.
|
||||
In a typical case, the lowest value gives a lower bound for how fast
|
||||
your machine can run the given code snippet; higher values in the
|
||||
result vector are typically not caused by variability in Python's
|
||||
speed, but by other processes interfering with your timing accuracy.
|
||||
So the :func:`min` of the result is probably the only number you
|
||||
should be interested in. After that, you should look at the entire
|
||||
vector and apply common sense rather than statistics.
|
||||
|
||||
|
||||
.. method:: Timer.print_exc(file=None)
|
||||
|
||||
Helper to print a traceback from the timed code.
|
||||
|
@ -53,74 +154,14 @@ The module defines the following public class:
|
|||
except:
|
||||
t.print_exc()
|
||||
|
||||
The advantage over the standard traceback is that source lines in the compiled
|
||||
template will be displayed. The optional *file* argument directs where the
|
||||
traceback is sent; it defaults to ``sys.stderr``.
|
||||
The advantage over the standard traceback is that source lines in the
|
||||
compiled template will be displayed. The optional *file* argument directs
|
||||
where the traceback is sent; it defaults to :data:`sys.stderr`.
|
||||
|
||||
|
||||
.. method:: Timer.repeat(repeat=3, number=1000000)
|
||||
.. _command-line-interface:
|
||||
|
||||
Call :meth:`.timeit` a few times.
|
||||
|
||||
This is a convenience function that calls the :meth:`.timeit` repeatedly,
|
||||
returning a list of results. The first argument specifies how many times to
|
||||
call :meth:`.timeit`. The second argument specifies the *number* argument for
|
||||
:meth:`.timeit`.
|
||||
|
||||
.. note::
|
||||
|
||||
It's tempting to calculate mean and standard deviation from the result vector
|
||||
and report these. However, this is not very useful. In a typical case, the
|
||||
lowest value gives a lower bound for how fast your machine can run the given
|
||||
code snippet; higher values in the result vector are typically not caused by
|
||||
variability in Python's speed, but by other processes interfering with your
|
||||
timing accuracy. So the :func:`min` of the result is probably the only number
|
||||
you should be interested in. After that, you should look at the entire vector
|
||||
and apply common sense rather than statistics.
|
||||
|
||||
|
||||
.. method:: Timer.timeit(number=1000000)
|
||||
|
||||
Time *number* executions of the main statement. This executes the setup
|
||||
statement once, and then returns the time it takes to execute the main statement
|
||||
a number of times, measured in seconds as a float. The argument is the number
|
||||
of times through the loop, defaulting to one million. The main statement, the
|
||||
setup statement and the timer function to be used are passed to the constructor.
|
||||
|
||||
.. note::
|
||||
|
||||
By default, :meth:`.timeit` temporarily turns off :term:`garbage collection`
|
||||
during the timing. The advantage of this approach is that it makes
|
||||
independent timings more comparable. This disadvantage is that GC may be
|
||||
an important component of the performance of the function being measured.
|
||||
If so, GC can be re-enabled as the first statement in the *setup* string.
|
||||
For example::
|
||||
|
||||
timeit.Timer('for i in range(10): oct(i)', 'gc.enable()').timeit()
|
||||
|
||||
|
||||
The module also defines three convenience functions:
|
||||
|
||||
|
||||
.. function:: default_timer()
|
||||
|
||||
The default timer, which is always :func:`time.perf_counter`.
|
||||
|
||||
|
||||
.. function:: repeat(stmt='pass', setup='pass', timer=<default timer>, repeat=3, number=1000000)
|
||||
|
||||
Create a :class:`Timer` instance with the given statement, setup code and timer
|
||||
function and run its :meth:`repeat` method with the given repeat count and
|
||||
*number* executions.
|
||||
|
||||
|
||||
.. function:: timeit(stmt='pass', setup='pass', timer=<default timer>, number=1000000)
|
||||
|
||||
Create a :class:`Timer` instance with the given statement, setup code and timer
|
||||
function and run its :meth:`.timeit` method with *number* executions.
|
||||
|
||||
|
||||
Command Line Interface
|
||||
Command-Line Interface
|
||||
----------------------
|
||||
|
||||
When called as a program from the command line, the following form is used::
|
||||
|
@ -184,25 +225,53 @@ most cases. You can use :func:`time.process_time` to measure CPU time.
|
|||
|
||||
There is a certain baseline overhead associated with executing a pass statement.
|
||||
The code here doesn't try to hide it, but you should be aware of it. The
|
||||
baseline overhead can be measured by invoking the program without arguments.
|
||||
baseline overhead can be measured by invoking the program without arguments,
|
||||
and it might differ between Python versions.
|
||||
|
||||
The baseline overhead differs between Python versions! Also, to fairly compare
|
||||
older Python versions to Python 2.3, you may want to use Python's :option:`-O`
|
||||
option for the older versions to avoid timing ``SET_LINENO`` instructions.
|
||||
|
||||
.. _timeit-examples:
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
Here are two example sessions (one using the command line, one using the module
|
||||
interface) that compare the cost of using :func:`hasattr` vs.
|
||||
:keyword:`try`/:keyword:`except` to test for missing and present object
|
||||
attributes. ::
|
||||
It is possible to provide a setup statement that is executed only once at the beginning:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
$ python -m timeit -s 'text = "sample string"; char = "g"' 'char in text'
|
||||
10000000 loops, best of 3: 0.0877 usec per loop
|
||||
$ python -m timeit -s 'text = "sample string"; char = "g"' 'text.find(char)'
|
||||
1000000 loops, best of 3: 0.342 usec per loop
|
||||
|
||||
::
|
||||
|
||||
>>> import timeit
|
||||
>>> timeit.timeit('char in text', setup='text = "sample string"; char = "g"')
|
||||
0.41440500499993504
|
||||
>>> timeit.timeit('text.find(char)', setup='text = "sample string"; char = "g"')
|
||||
1.7246671520006203
|
||||
|
||||
The same can be done using the :class:`Timer` class and its methods::
|
||||
|
||||
>>> import timeit
|
||||
>>> t = timeit.Timer('char in text', setup='text = "sample string"; char = "g"')
|
||||
>>> t.timeit()
|
||||
0.3955516149999312
|
||||
>>> t.repeat()
|
||||
[0.40193588800002544, 0.3960157959998014, 0.39594301399984033]
|
||||
|
||||
|
||||
The following examples show how to time expressions that contain multiple lines.
|
||||
Here we compare the cost of using :func:`hasattr` vs. :keyword:`try`/:keyword:`except`
|
||||
to test for missing and present object attributes:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
$ python -m timeit 'try:' ' str.__bool__' 'except AttributeError:' ' pass'
|
||||
100000 loops, best of 3: 15.7 usec per loop
|
||||
$ python -m timeit 'if hasattr(str, "__bool__"): pass'
|
||||
100000 loops, best of 3: 4.26 usec per loop
|
||||
|
||||
$ python -m timeit 'try:' ' int.__bool__' 'except AttributeError:' ' pass'
|
||||
1000000 loops, best of 3: 1.43 usec per loop
|
||||
$ python -m timeit 'if hasattr(int, "__bool__"): pass'
|
||||
|
@ -211,36 +280,32 @@ attributes. ::
|
|||
::
|
||||
|
||||
>>> import timeit
|
||||
>>> # attribute is missing
|
||||
>>> s = """\
|
||||
... try:
|
||||
... str.__bool__
|
||||
... except AttributeError:
|
||||
... pass
|
||||
... """
|
||||
>>> t = timeit.Timer(stmt=s)
|
||||
>>> print("%.2f usec/pass" % (1000000 * t.timeit(number=100000)/100000))
|
||||
17.09 usec/pass
|
||||
>>> s = """\
|
||||
... if hasattr(str, '__bool__'): pass
|
||||
... """
|
||||
>>> t = timeit.Timer(stmt=s)
|
||||
>>> print("%.2f usec/pass" % (1000000 * t.timeit(number=100000)/100000))
|
||||
4.85 usec/pass
|
||||
>>> timeit.timeit(stmt=s, number=100000)
|
||||
0.9138244460009446
|
||||
>>> s = "if hasattr(str, '__bool__'): pass"
|
||||
>>> timeit.timeit(stmt=s, number=100000)
|
||||
0.5829014980008651
|
||||
>>>
|
||||
>>> # attribute is present
|
||||
>>> s = """\
|
||||
... try:
|
||||
... int.__bool__
|
||||
... except AttributeError:
|
||||
... pass
|
||||
... """
|
||||
>>> t = timeit.Timer(stmt=s)
|
||||
>>> print("%.2f usec/pass" % (1000000 * t.timeit(number=100000)/100000))
|
||||
1.97 usec/pass
|
||||
>>> s = """\
|
||||
... if hasattr(int, '__bool__'): pass
|
||||
... """
|
||||
>>> t = timeit.Timer(stmt=s)
|
||||
>>> print("%.2f usec/pass" % (1000000 * t.timeit(number=100000)/100000))
|
||||
3.15 usec/pass
|
||||
>>> timeit.timeit(stmt=s, number=100000)
|
||||
0.04215312199994514
|
||||
>>> s = "if hasattr(int, '__bool__'): pass"
|
||||
>>> timeit.timeit(stmt=s, number=100000)
|
||||
0.08588060699912603
|
||||
|
||||
|
||||
To give the :mod:`timeit` module access to functions you define, you can pass a
|
||||
*setup* parameter which contains an import statement::
|
||||
|
@ -250,7 +315,5 @@ To give the :mod:`timeit` module access to functions you define, you can pass a
|
|||
L = [i for i in range(100)]
|
||||
|
||||
if __name__ == '__main__':
|
||||
from timeit import Timer
|
||||
t = Timer("test()", "from __main__ import test")
|
||||
print(t.timeit())
|
||||
|
||||
import timeit
|
||||
print(timeit.timeit("test()", setup="from __main__ import test"))
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
:mod:`urllib` --- URL handling modules
|
||||
======================================
|
||||
|
||||
``urllib`` is a package that collects several modules for working with URLs:
|
||||
|
||||
* :mod:`urllib.request` for opening and reading URLs
|
||||
* :mod:`urllib.error` containing the exceptions raised by :mod:`urllib.request`
|
||||
* :mod:`urllib.parse` for parsing URLs
|
||||
* :mod:`urllib.robotparser` for parsing ``robots.txt`` files
|
|
@ -291,7 +291,9 @@ Supported XPath syntax
|
|||
| | current element. For example, ``.//egg`` selects |
|
||||
| | all ``egg`` elements in the entire tree. |
|
||||
+-----------------------+------------------------------------------------------+
|
||||
| ``..`` | Selects the parent element. |
|
||||
| ``..`` | Selects the parent element. Returns ``None`` if the |
|
||||
| | path attempts to reach the ancestors of the start |
|
||||
| | element (the element ``find`` was called on). |
|
||||
+-----------------------+------------------------------------------------------+
|
||||
| ``[@attrib]`` | Selects all elements that have the given attribute. |
|
||||
+-----------------------+------------------------------------------------------+
|
||||
|
@ -431,9 +433,9 @@ Functions
|
|||
Generates a string representation of an XML element, including all
|
||||
subelements. *element* is an :class:`Element` instance. *encoding* [1]_ is
|
||||
the output encoding (default is US-ASCII). Use ``encoding="unicode"`` to
|
||||
generate a Unicode string. *method* is either ``"xml"``,
|
||||
``"html"`` or ``"text"`` (default is ``"xml"``). Returns an (optionally)
|
||||
encoded string containing the XML data.
|
||||
generate a Unicode string (otherwise, a bytestring is generated). *method*
|
||||
is either ``"xml"``, ``"html"`` or ``"text"`` (default is ``"xml"``).
|
||||
Returns an (optionally) encoded string containing the XML data.
|
||||
|
||||
|
||||
.. function:: tostringlist(element, encoding="us-ascii", method="xml")
|
||||
|
@ -441,11 +443,11 @@ Functions
|
|||
Generates a string representation of an XML element, including all
|
||||
subelements. *element* is an :class:`Element` instance. *encoding* [1]_ is
|
||||
the output encoding (default is US-ASCII). Use ``encoding="unicode"`` to
|
||||
generate a Unicode string. *method* is either ``"xml"``,
|
||||
``"html"`` or ``"text"`` (default is ``"xml"``). Returns a list of
|
||||
(optionally) encoded strings containing the XML data. It does not guarantee
|
||||
any specific sequence, except that ``"".join(tostringlist(element)) ==
|
||||
tostring(element)``.
|
||||
generate a Unicode string (otherwise, a bytestring is generated). *method*
|
||||
is either ``"xml"``, ``"html"`` or ``"text"`` (default is ``"xml"``).
|
||||
Returns a list of (optionally) encoded strings containing the XML data.
|
||||
It does not guarantee any specific sequence, except that
|
||||
``"".join(tostringlist(element)) == tostring(element)``.
|
||||
|
||||
.. versionadded:: 3.2
|
||||
|
||||
|
@ -521,7 +523,7 @@ Element Objects
|
|||
.. method:: clear()
|
||||
|
||||
Resets an element. This function removes all subelements, clears all
|
||||
attributes, and sets the text and tail attributes to None.
|
||||
attributes, and sets the text and tail attributes to ``None``.
|
||||
|
||||
|
||||
.. method:: get(key, default=None)
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
.. _xml:
|
||||
|
||||
XML Processing Modules
|
||||
======================
|
||||
|
||||
Python's interfaces for processing XML are grouped in the ``xml`` package.
|
||||
|
||||
It is important to note that modules in the :mod:`xml` package require that
|
||||
there be at least one SAX-compliant XML parser available. The Expat parser is
|
||||
included with Python, so the :mod:`xml.parsers.expat` module will always be
|
||||
available.
|
||||
|
||||
The documentation for the :mod:`xml.dom` and :mod:`xml.sax` packages are the
|
||||
definition of the Python bindings for the DOM and SAX interfaces.
|
||||
|
||||
The XML handling submodules are:
|
||||
|
||||
* :mod:`xml.etree.ElementTree`: the ElementTree API, a simple and lightweight
|
||||
|
||||
..
|
||||
|
||||
* :mod:`xml.dom`: the DOM API definition
|
||||
* :mod:`xml.dom.minidom`: a lightweight DOM implementation
|
||||
* :mod:`xml.dom.pulldom`: support for building partial DOM trees
|
||||
|
||||
..
|
||||
|
||||
* :mod:`xml.sax`: SAX2 base classes and convenience functions
|
||||
* :mod:`xml.parsers.expat`: the Expat parser binding
|
|
@ -0,0 +1,12 @@
|
|||
:mod:`xmlrpc` --- XMLRPC server and client modules
|
||||
==================================================
|
||||
|
||||
XML-RPC is a Remote Procedure Call method that uses XML passed via HTTP as a
|
||||
transport. With it, a client can call methods with parameters on a remote
|
||||
server (the server is named by a URI) and get back structured data.
|
||||
|
||||
``xmlrpc`` is a package that collects server and client modules implementing
|
||||
XML-RPC. The modules are:
|
||||
|
||||
* :mod:`xmlrpc.client`
|
||||
* :mod:`xmlrpc.server`
|
|
@ -61,7 +61,7 @@ The module defines the following items:
|
|||
.. class:: ZipInfo(filename='NoName', date_time=(1980,1,1,0,0,0))
|
||||
|
||||
Class used to represent information about a member of an archive. Instances
|
||||
of this class are returned by the :meth:`getinfo` and :meth:`infolist`
|
||||
of this class are returned by the :meth:`.getinfo` and :meth:`.infolist`
|
||||
methods of :class:`ZipFile` objects. Most users of the :mod:`zipfile` module
|
||||
will not need to create these, but only use those created by this
|
||||
module. *filename* should be the full name of the archive member, and
|
||||
|
@ -87,20 +87,20 @@ The module defines the following items:
|
|||
.. data:: ZIP_DEFLATED
|
||||
|
||||
The numeric constant for the usual ZIP compression method. This requires the
|
||||
zlib module.
|
||||
:mod:`zlib` module.
|
||||
|
||||
|
||||
.. data:: ZIP_BZIP2
|
||||
|
||||
The numeric constant for the BZIP2 compression method. This requires the
|
||||
bz2 module.
|
||||
:mod:`bz2` module.
|
||||
|
||||
.. versionadded:: 3.3
|
||||
|
||||
.. data:: ZIP_LZMA
|
||||
|
||||
The numeric constant for the LZMA compression method. This requires the
|
||||
lzma module.
|
||||
:mod:`lzma` module.
|
||||
|
||||
.. versionadded:: 3.3
|
||||
|
||||
|
@ -155,7 +155,7 @@ ZipFile Objects
|
|||
these extensions.
|
||||
|
||||
If the file is created with mode ``'a'`` or ``'w'`` and then
|
||||
:meth:`close`\ d without adding any files to the archive, the appropriate
|
||||
:meth:`closed <close>` without adding any files to the archive, the appropriate
|
||||
ZIP structures for an empty archive will be written to the file.
|
||||
|
||||
ZipFile is also a context manager and therefore supports the
|
||||
|
@ -169,7 +169,7 @@ ZipFile Objects
|
|||
Added the ability to use :class:`ZipFile` as a context manager.
|
||||
|
||||
.. versionchanged:: 3.3
|
||||
Added support for :mod:`bzip2` and :mod:`lzma` compression.
|
||||
Added support for :mod:`bzip2 <bz2>` and :mod:`lzma` compression.
|
||||
|
||||
|
||||
.. method:: ZipFile.close()
|
||||
|
@ -207,7 +207,7 @@ ZipFile Objects
|
|||
*mode* parameter, if included, must be one of the following: ``'r'`` (the
|
||||
default), ``'U'``, or ``'rU'``. Choosing ``'U'`` or ``'rU'`` will enable
|
||||
:term:`universal newlines` support in the read-only object. *pwd* is the
|
||||
password used for encrypted files. Calling :meth:`open` on a closed
|
||||
password used for encrypted files. Calling :meth:`.open` on a closed
|
||||
ZipFile will raise a :exc:`RuntimeError`.
|
||||
|
||||
.. note::
|
||||
|
@ -229,7 +229,7 @@ ZipFile Objects
|
|||
|
||||
.. note::
|
||||
|
||||
The :meth:`open`, :meth:`read` and :meth:`extract` methods can take a filename
|
||||
The :meth:`.open`, :meth:`read` and :meth:`extract` methods can take a filename
|
||||
or a :class:`ZipInfo` object. You will appreciate this when trying to read a
|
||||
ZIP file that contains members with duplicate names.
|
||||
|
||||
|
@ -335,7 +335,7 @@ ZipFile Objects
|
|||
:class:`ZipInfo` constructor sets this member to :const:`ZIP_STORED`.
|
||||
|
||||
.. versionchanged:: 3.2
|
||||
The *compression_type* argument.
|
||||
The *compress_type* argument.
|
||||
|
||||
The following data attributes are also available:
|
||||
|
||||
|
@ -351,7 +351,7 @@ The following data attributes are also available:
|
|||
The comment text associated with the ZIP file. If assigning a comment to a
|
||||
:class:`ZipFile` instance created with mode 'a' or 'w', this should be a
|
||||
string no longer than 65535 bytes. Comments longer than this will be
|
||||
truncated in the written archive when :meth:`ZipFile.close` is called.
|
||||
truncated in the written archive when :meth:`close` is called.
|
||||
|
||||
|
||||
.. _pyzipfile-objects:
|
||||
|
@ -407,8 +407,8 @@ The :class:`PyZipFile` constructor takes the same parameters as the
|
|||
ZipInfo Objects
|
||||
---------------
|
||||
|
||||
Instances of the :class:`ZipInfo` class are returned by the :meth:`getinfo` and
|
||||
:meth:`infolist` methods of :class:`ZipFile` objects. Each object stores
|
||||
Instances of the :class:`ZipInfo` class are returned by the :meth:`.getinfo` and
|
||||
:meth:`.infolist` methods of :class:`ZipFile` objects. Each object stores
|
||||
information about a single member of the ZIP archive.
|
||||
|
||||
Instances have the following attributes:
|
||||
|
|
|
@ -37,7 +37,7 @@ goto end
|
|||
svn co %SVNROOT%/external/Sphinx-1.0.7/sphinx tools/sphinx
|
||||
svn co %SVNROOT%/external/docutils-0.6/docutils tools/docutils
|
||||
svn co %SVNROOT%/external/Jinja-2.3.1/jinja2 tools/jinja2
|
||||
svn co %SVNROOT%/external/Pygments-1.3.1/pygments tools/pygments
|
||||
svn co %SVNROOT%/external/Pygments-1.5dev-20120930/pygments tools/pygments
|
||||
goto end
|
||||
|
||||
:update
|
||||
|
|
|
@ -312,7 +312,7 @@ Sequences
|
|||
|
||||
A bytes object is an immutable array. The items are 8-bit bytes,
|
||||
represented by integers in the range 0 <= x < 256. Bytes literals
|
||||
(like ``b'abc'`` and the built-in function :func:`bytes` can be used to
|
||||
(like ``b'abc'``) and the built-in function :func:`bytes` can be used to
|
||||
construct bytes objects. Also, bytes objects can be decoded to strings
|
||||
via the :meth:`decode` method.
|
||||
|
||||
|
|
|
@ -1094,16 +1094,10 @@ Comparison of objects of the same type depends on the type:
|
|||
another one is made arbitrarily but consistently within one execution of a
|
||||
program.
|
||||
|
||||
Comparison of objects of the differing types depends on whether either
|
||||
of the types provide explicit support for the comparison. Most numeric types
|
||||
can be compared with one another, but comparisons of :class:`float` and
|
||||
:class:`Decimal` are not supported to avoid the inevitable confusion arising
|
||||
from representation issues such as ``float('1.1')`` being inexactly represented
|
||||
and therefore not exactly equal to ``Decimal('1.1')`` which is. When
|
||||
cross-type comparison is not supported, the comparison method returns
|
||||
``NotImplemented``. This can create the illusion of non-transitivity between
|
||||
supported cross-type comparisons and unsupported comparisons. For example,
|
||||
``Decimal(2) == 2`` and ``2 == float(2)`` but ``Decimal(2) != float(2)``.
|
||||
Comparison of objects of the differing types depends on whether either of the
|
||||
types provide explicit support for the comparison. Most numeric types can be
|
||||
compared with one another. When cross-type comparison is not supported, the
|
||||
comparison method returns ``NotImplemented``.
|
||||
|
||||
.. _membership-test-details:
|
||||
|
||||
|
|
|
@ -538,9 +538,7 @@ Notes:
|
|||
this escape sequence. Exactly four hex digits are required.
|
||||
|
||||
(6)
|
||||
Any Unicode character can be encoded this way, but characters outside the Basic
|
||||
Multilingual Plane (BMP) will be encoded using a surrogate pair if Python is
|
||||
compiled to use 16-bit code units (the default). Exactly eight hex digits
|
||||
Any Unicode character can be encoded this way. Exactly eight hex digits
|
||||
are required.
|
||||
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<h3>Docs for other versions</h3>
|
||||
<ul>
|
||||
<li><a href="http://docs.python.org/2.7/">Python 2.7 (stable)</a></li>
|
||||
<li><a href="http://docs.python.org/3.2/">Python 3.2 (stable)</a></li>
|
||||
<li><a href="http://docs.python.org/3.4/">Python 3.4 (in development)</a></li>
|
||||
<li><a href="http://www.python.org/doc/versions/">Old versions</a></li>
|
||||
</ul>
|
||||
|
||||
|
|
|
@ -8,6 +8,63 @@
|
|||
{% block extrahead %}
|
||||
<link rel="shortcut icon" type="image/png" href="{{ pathto('_static/py.png', 1) }}" />
|
||||
{% if not embedded %}<script type="text/javascript" src="{{ pathto('_static/copybutton.js', 1) }}"></script>{% endif %}
|
||||
{% if pagename == 'whatsnew/changelog' %}
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
// add the search form and bind the events
|
||||
$('h1').after([
|
||||
'<p>Filter entries by content:',
|
||||
'<input type="text" value="" id="searchbox" style="width: 50%">',
|
||||
'<input type="submit" id="searchbox-submit" value="Filter"></p>'
|
||||
].join('\n'));
|
||||
|
||||
function dofilter() {
|
||||
try {
|
||||
var query = new RegExp($('#searchbox').val(), 'i');
|
||||
}
|
||||
catch (e) {
|
||||
return; // not a valid regex (yet)
|
||||
}
|
||||
// find headers for the versions (What's new in Python X.Y.Z?)
|
||||
$('#changelog h2').each(function(index1, h2) {
|
||||
var h2_parent = $(h2).parent();
|
||||
var sections_found = 0;
|
||||
// find headers for the sections (Core, Library, etc.)
|
||||
h2_parent.find('h3').each(function(index2, h3) {
|
||||
var h3_parent = $(h3).parent();
|
||||
var entries_found = 0;
|
||||
// find all the entries
|
||||
h3_parent.find('li').each(function(index3, li) {
|
||||
var li = $(li);
|
||||
// check if the query matches the entry
|
||||
if (query.test(li.text())) {
|
||||
li.show();
|
||||
entries_found++;
|
||||
}
|
||||
else {
|
||||
li.hide();
|
||||
}
|
||||
});
|
||||
// if there are entries, show the section, otherwise hide it
|
||||
if (entries_found > 0) {
|
||||
h3_parent.show();
|
||||
sections_found++;
|
||||
}
|
||||
else {
|
||||
h3_parent.hide();
|
||||
}
|
||||
});
|
||||
if (sections_found > 0)
|
||||
h2_parent.show();
|
||||
else
|
||||
h2_parent.hide();
|
||||
});
|
||||
}
|
||||
$('#searchbox').keyup(dofilter);
|
||||
$('#searchbox-submit').click(dofilter);
|
||||
});
|
||||
</script>
|
||||
{% endif %}
|
||||
{{ super() }}
|
||||
{% endblock %}
|
||||
{% block footer %}
|
||||
|
|
|
@ -145,6 +145,47 @@ class DeprecatedRemoved(Directive):
|
|||
return ret
|
||||
|
||||
|
||||
# Support for including Misc/NEWS
|
||||
|
||||
import re
|
||||
import codecs
|
||||
|
||||
issue_re = re.compile('([Ii])ssue #([0-9]+)')
|
||||
whatsnew_re = re.compile(r"(?im)^what's new in (.*?)\??$")
|
||||
|
||||
class MiscNews(Directive):
|
||||
has_content = False
|
||||
required_arguments = 1
|
||||
optional_arguments = 0
|
||||
final_argument_whitespace = False
|
||||
option_spec = {}
|
||||
|
||||
def run(self):
|
||||
fname = self.arguments[0]
|
||||
source = self.state_machine.input_lines.source(
|
||||
self.lineno - self.state_machine.input_offset - 1)
|
||||
source_dir = path.dirname(path.abspath(source))
|
||||
fpath = path.join(source_dir, fname)
|
||||
self.state.document.settings.record_dependencies.add(fpath)
|
||||
try:
|
||||
fp = codecs.open(fpath, encoding='utf-8')
|
||||
try:
|
||||
content = fp.read()
|
||||
finally:
|
||||
fp.close()
|
||||
except Exception:
|
||||
text = 'The NEWS file is not available.'
|
||||
node = nodes.strong(text, text)
|
||||
return [node]
|
||||
content = issue_re.sub(r'`\1ssue #\2 <http://bugs.python.org/\2>`__',
|
||||
content)
|
||||
content = whatsnew_re.sub(r'\1', content)
|
||||
# remove first 3 lines as they are the main heading
|
||||
lines = ['.. default-role:: obj', ''] + content.splitlines()[3:]
|
||||
self.state_machine.insert_input(lines, fname)
|
||||
return []
|
||||
|
||||
|
||||
# Support for building "topic help" for pydoc
|
||||
|
||||
pydoc_topic_labels = [
|
||||
|
@ -276,3 +317,4 @@ def setup(app):
|
|||
app.add_description_unit('2to3fixer', '2to3fixer', '%s (2to3 fixer)')
|
||||
app.add_directive_to_domain('py', 'decorator', PyDecoratorFunction)
|
||||
app.add_directive_to_domain('py', 'decoratormethod', PyDecoratorMethod)
|
||||
app.add_directive('miscnews', MiscNews)
|
||||
|
|
|
@ -357,3 +357,15 @@ whatsnew/3.2,,:location,... zope9-location = ${zope9:location}
|
|||
whatsnew/3.2,,:location,zope9-location = ${zope9:location}
|
||||
whatsnew/3.2,,:prefix,... zope-conf = ${custom:prefix}/etc/zope.conf
|
||||
whatsnew/3.2,,:prefix,zope-conf = ${custom:prefix}/etc/zope.conf
|
||||
whatsnew/news,,:platform,:platform:
|
||||
whatsnew/news,,:password,: Unquote before b64encoding user:password during Basic
|
||||
whatsnew/news,,:close,Connection:close header.
|
||||
whatsnew/news,,:PythonCmd,"With Tk < 8.5 _tkinter.c:PythonCmd() raised UnicodeDecodeError, caused"
|
||||
whatsnew/news,,:close,: Connection:close header is sent by requests using URLOpener
|
||||
whatsnew/news,,::,": Fix FTP tests for IPv6, bind to ""::1"" instead of ""localhost""."
|
||||
whatsnew/news,,:test,: test_subprocess:test_leaking_fds_on_error no longer gives a
|
||||
whatsnew/news,,:test,: Fix test_posix:test_getgroups failure under Solaris. Patch
|
||||
whatsnew/news,,:Olimit,Drop -OPT:Olimit compiler option.
|
||||
whatsnew/news,,:MAXYEAR,timedelta from date or datetime falls outside of the MINYEAR:MAXYEAR range.
|
||||
whatsnew/news,,:bz2,with mode 'r' or 'r:bz2' and a fileobj argument that contained no data or
|
||||
whatsnew/news,,:db2,: Add configure option --with-dbmliborder=db1:db2:... to specify
|
||||
|
|
|
|
@ -132,6 +132,8 @@ Consult :command:`set /?` for details on this behaviour.
|
|||
Setting Environment variables, Louis J. Farrugia
|
||||
|
||||
|
||||
.. _windows-path-mod:
|
||||
|
||||
Finding the Python executable
|
||||
-----------------------------
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,6 @@
|
|||
+++++++++
|
||||
Changelog
|
||||
+++++++++
|
||||
|
||||
.. miscnews:: ../../Misc/NEWS
|
||||
|
|
@ -23,3 +23,11 @@ anyone wishing to stay up-to-date after a new release.
|
|||
2.2.rst
|
||||
2.1.rst
|
||||
2.0.rst
|
||||
|
||||
The "Changelog" is a HTML version of the file :source:`Misc/NEWS` which
|
||||
contains *all* nontrivial changes to Python for the current version.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
changelog.rst
|
||||
|
|
|
@ -1022,8 +1022,7 @@ PyAPI_FUNC(void*) _PyUnicode_AsKind(PyObject *s, unsigned int kind);
|
|||
|
||||
/* Create a Unicode Object from the given Unicode code point ordinal.
|
||||
|
||||
The ordinal must be in range(0x10000) on narrow Python builds
|
||||
(UCS2), and range(0x110000) on wide builds (UCS4). A ValueError is
|
||||
The ordinal must be in range(0x110000). A ValueError is
|
||||
raised in case it is not.
|
||||
|
||||
*/
|
||||
|
|
91
Lib/bz2.py
91
Lib/bz2.py
|
@ -79,7 +79,8 @@ class BZ2File(io.BufferedIOBase):
|
|||
mode = "rb"
|
||||
mode_code = _MODE_READ
|
||||
self._decompressor = BZ2Decompressor()
|
||||
self._buffer = None
|
||||
self._buffer = b""
|
||||
self._buffer_offset = 0
|
||||
elif mode in ("w", "wb"):
|
||||
mode = "wb"
|
||||
mode_code = _MODE_WRITE
|
||||
|
@ -124,7 +125,8 @@ class BZ2File(io.BufferedIOBase):
|
|||
self._fp = None
|
||||
self._closefp = False
|
||||
self._mode = _MODE_CLOSED
|
||||
self._buffer = None
|
||||
self._buffer = b""
|
||||
self._buffer_offset = 0
|
||||
|
||||
@property
|
||||
def closed(self):
|
||||
|
@ -157,15 +159,18 @@ class BZ2File(io.BufferedIOBase):
|
|||
raise ValueError("I/O operation on closed file")
|
||||
|
||||
def _check_can_read(self):
|
||||
if not self.readable():
|
||||
if self._mode not in (_MODE_READ, _MODE_READ_EOF):
|
||||
self._check_not_closed()
|
||||
raise io.UnsupportedOperation("File not open for reading")
|
||||
|
||||
def _check_can_write(self):
|
||||
if not self.writable():
|
||||
if self._mode != _MODE_WRITE:
|
||||
self._check_not_closed()
|
||||
raise io.UnsupportedOperation("File not open for writing")
|
||||
|
||||
def _check_can_seek(self):
|
||||
if not self.readable():
|
||||
if self._mode not in (_MODE_READ, _MODE_READ_EOF):
|
||||
self._check_not_closed()
|
||||
raise io.UnsupportedOperation("Seeking is only supported "
|
||||
"on files open for reading")
|
||||
if not self._fp.seekable():
|
||||
|
@ -174,16 +179,13 @@ class BZ2File(io.BufferedIOBase):
|
|||
|
||||
# Fill the readahead buffer if it is empty. Returns False on EOF.
|
||||
def _fill_buffer(self):
|
||||
if self._mode == _MODE_READ_EOF:
|
||||
return False
|
||||
# Depending on the input data, our call to the decompressor may not
|
||||
# return any data. In this case, try again after reading another block.
|
||||
while True:
|
||||
if self._buffer:
|
||||
return True
|
||||
|
||||
if self._decompressor.unused_data:
|
||||
rawblock = self._decompressor.unused_data
|
||||
else:
|
||||
rawblock = self._fp.read(_BUFFER_SIZE)
|
||||
while self._buffer_offset == len(self._buffer):
|
||||
rawblock = (self._decompressor.unused_data or
|
||||
self._fp.read(_BUFFER_SIZE))
|
||||
|
||||
if not rawblock:
|
||||
if self._decompressor.eof:
|
||||
|
@ -199,30 +201,48 @@ class BZ2File(io.BufferedIOBase):
|
|||
self._decompressor = BZ2Decompressor()
|
||||
|
||||
self._buffer = self._decompressor.decompress(rawblock)
|
||||
self._buffer_offset = 0
|
||||
return True
|
||||
|
||||
# Read data until EOF.
|
||||
# If return_data is false, consume the data without returning it.
|
||||
def _read_all(self, return_data=True):
|
||||
# The loop assumes that _buffer_offset is 0. Ensure that this is true.
|
||||
self._buffer = self._buffer[self._buffer_offset:]
|
||||
self._buffer_offset = 0
|
||||
|
||||
blocks = []
|
||||
while self._fill_buffer():
|
||||
if return_data:
|
||||
blocks.append(self._buffer)
|
||||
self._pos += len(self._buffer)
|
||||
self._buffer = None
|
||||
self._buffer = b""
|
||||
if return_data:
|
||||
return b"".join(blocks)
|
||||
|
||||
# Read a block of up to n bytes.
|
||||
# If return_data is false, consume the data without returning it.
|
||||
def _read_block(self, n, return_data=True):
|
||||
# If we have enough data buffered, return immediately.
|
||||
end = self._buffer_offset + n
|
||||
if end <= len(self._buffer):
|
||||
data = self._buffer[self._buffer_offset : end]
|
||||
self._buffer_offset = end
|
||||
self._pos += len(data)
|
||||
return data if return_data else None
|
||||
|
||||
# The loop assumes that _buffer_offset is 0. Ensure that this is true.
|
||||
self._buffer = self._buffer[self._buffer_offset:]
|
||||
self._buffer_offset = 0
|
||||
|
||||
blocks = []
|
||||
while n > 0 and self._fill_buffer():
|
||||
if n < len(self._buffer):
|
||||
data = self._buffer[:n]
|
||||
self._buffer = self._buffer[n:]
|
||||
self._buffer_offset = n
|
||||
else:
|
||||
data = self._buffer
|
||||
self._buffer = None
|
||||
self._buffer = b""
|
||||
if return_data:
|
||||
blocks.append(data)
|
||||
self._pos += len(data)
|
||||
|
@ -238,9 +258,9 @@ class BZ2File(io.BufferedIOBase):
|
|||
"""
|
||||
with self._lock:
|
||||
self._check_can_read()
|
||||
if self._mode == _MODE_READ_EOF or not self._fill_buffer():
|
||||
if not self._fill_buffer():
|
||||
return b""
|
||||
return self._buffer
|
||||
return self._buffer[self._buffer_offset:]
|
||||
|
||||
def read(self, size=-1):
|
||||
"""Read up to size uncompressed bytes from the file.
|
||||
|
@ -250,7 +270,7 @@ class BZ2File(io.BufferedIOBase):
|
|||
"""
|
||||
with self._lock:
|
||||
self._check_can_read()
|
||||
if self._mode == _MODE_READ_EOF or size == 0:
|
||||
if size == 0:
|
||||
return b""
|
||||
elif size < 0:
|
||||
return self._read_all()
|
||||
|
@ -268,15 +288,19 @@ class BZ2File(io.BufferedIOBase):
|
|||
# In this case we make multiple reads, to avoid returning b"".
|
||||
with self._lock:
|
||||
self._check_can_read()
|
||||
if (size == 0 or self._mode == _MODE_READ_EOF or
|
||||
not self._fill_buffer()):
|
||||
if (size == 0 or
|
||||
# Only call _fill_buffer() if the buffer is actually empty.
|
||||
# This gives a significant speedup if *size* is small.
|
||||
(self._buffer_offset == len(self._buffer) and not self._fill_buffer())):
|
||||
return b""
|
||||
if 0 < size < len(self._buffer):
|
||||
data = self._buffer[:size]
|
||||
self._buffer = self._buffer[size:]
|
||||
if size > 0:
|
||||
data = self._buffer[self._buffer_offset :
|
||||
self._buffer_offset + size]
|
||||
self._buffer_offset += len(data)
|
||||
else:
|
||||
data = self._buffer
|
||||
self._buffer = None
|
||||
data = self._buffer[self._buffer_offset:]
|
||||
self._buffer = b""
|
||||
self._buffer_offset = 0
|
||||
self._pos += len(data)
|
||||
return data
|
||||
|
||||
|
@ -295,10 +319,20 @@ class BZ2File(io.BufferedIOBase):
|
|||
non-negative, no more than size bytes will be read (in which
|
||||
case the line may be incomplete). Returns b'' if already at EOF.
|
||||
"""
|
||||
if not isinstance(size, int):
|
||||
if not hasattr(size, "__index__"):
|
||||
raise TypeError("Integer argument expected")
|
||||
size = size.__index__()
|
||||
with self._lock:
|
||||
self._check_can_read()
|
||||
# Shortcut for the common case - the whole line is in the buffer.
|
||||
if size < 0:
|
||||
end = self._buffer.find(b"\n", self._buffer_offset) + 1
|
||||
if end > 0:
|
||||
line = self._buffer[self._buffer_offset : end]
|
||||
self._buffer_offset = end
|
||||
self._pos += len(line)
|
||||
return line
|
||||
return io.BufferedIOBase.readline(self, size)
|
||||
|
||||
def readlines(self, size=-1):
|
||||
|
@ -308,6 +342,7 @@ class BZ2File(io.BufferedIOBase):
|
|||
further lines will be read once the total size of the lines read
|
||||
so far equals or exceeds size.
|
||||
"""
|
||||
if not isinstance(size, int):
|
||||
if not hasattr(size, "__index__"):
|
||||
raise TypeError("Integer argument expected")
|
||||
size = size.__index__()
|
||||
|
@ -345,7 +380,8 @@ class BZ2File(io.BufferedIOBase):
|
|||
self._mode = _MODE_READ
|
||||
self._pos = 0
|
||||
self._decompressor = BZ2Decompressor()
|
||||
self._buffer = None
|
||||
self._buffer = b""
|
||||
self._buffer_offset = 0
|
||||
|
||||
def seek(self, offset, whence=0):
|
||||
"""Change the file position.
|
||||
|
@ -385,7 +421,6 @@ class BZ2File(io.BufferedIOBase):
|
|||
offset -= self._pos
|
||||
|
||||
# Read and discard data until we reach the desired position.
|
||||
if self._mode != _MODE_READ_EOF:
|
||||
self._read_block(offset, return_data=False)
|
||||
|
||||
return self._pos
|
||||
|
|
|
@ -461,7 +461,7 @@ class StreamReader(Codec):
|
|||
|
||||
# read until we get the required number of characters (if available)
|
||||
while True:
|
||||
# can the request can be satisfied from the character buffer?
|
||||
# can the request be satisfied from the character buffer?
|
||||
if chars < 0:
|
||||
if size < 0:
|
||||
if self.charbuffer:
|
||||
|
|
|
@ -456,7 +456,7 @@ if _os.name in ("nt", "ce"):
|
|||
code = GetLastError()
|
||||
if descr is None:
|
||||
descr = FormatError(code).strip()
|
||||
return WindowsError(code, descr)
|
||||
return WindowsError(None, descr, None, code)
|
||||
|
||||
if sizeof(c_uint) == sizeof(c_void_p):
|
||||
c_size_t = c_uint
|
||||
|
|
|
@ -67,6 +67,28 @@ if sys.platform == "win32":
|
|||
self.assertEqual(ex.text, "text")
|
||||
self.assertEqual(ex.details, ("details",))
|
||||
|
||||
class TestWinError(unittest.TestCase):
|
||||
def test_winerror(self):
|
||||
# see Issue 16169
|
||||
import errno
|
||||
ERROR_INVALID_PARAMETER = 87
|
||||
msg = FormatError(ERROR_INVALID_PARAMETER).strip()
|
||||
args = (errno.EINVAL, msg, None, ERROR_INVALID_PARAMETER)
|
||||
|
||||
e = WinError(ERROR_INVALID_PARAMETER)
|
||||
self.assertEqual(e.args, args)
|
||||
self.assertEqual(e.errno, errno.EINVAL)
|
||||
self.assertEqual(e.winerror, ERROR_INVALID_PARAMETER)
|
||||
|
||||
windll.kernel32.SetLastError(ERROR_INVALID_PARAMETER)
|
||||
try:
|
||||
raise WinError()
|
||||
except OSError as exc:
|
||||
e = exc
|
||||
self.assertEqual(e.args, args)
|
||||
self.assertEqual(e.errno, errno.EINVAL)
|
||||
self.assertEqual(e.winerror, ERROR_INVALID_PARAMETER)
|
||||
|
||||
class Structures(unittest.TestCase):
|
||||
|
||||
def test_struct_by_value(self):
|
||||
|
|
|
@ -46,6 +46,8 @@ zoom-height=<Alt-Key-2>
|
|||
|
||||
[ScriptBinding]
|
||||
enable=1
|
||||
enable_shell=0
|
||||
enable_editor=1
|
||||
[ScriptBinding_cfgBindings]
|
||||
run-module=<Key-F5>
|
||||
check-module=<Alt-Key-x>
|
||||
|
|
|
@ -206,8 +206,9 @@ def summarize_address_range(first, last):
|
|||
"""Summarize a network range given the first and last IP addresses.
|
||||
|
||||
Example:
|
||||
>>> summarize_address_range(IPv4Address('192.0.2.0'),
|
||||
IPv4Address('192.0.2.130'))
|
||||
>>> list(summarize_address_range(IPv4Address('192.0.2.0'),
|
||||
... IPv4Address('192.0.2.130')))
|
||||
... #doctest: +NORMALIZE_WHITESPACE
|
||||
[IPv4Network('192.0.2.0/25'), IPv4Network('192.0.2.128/31'),
|
||||
IPv4Network('192.0.2.130/32')]
|
||||
|
||||
|
|
|
@ -794,13 +794,7 @@ class SysLogHandler(logging.Handler):
|
|||
self.formatter = None
|
||||
|
||||
def _connect_unixsocket(self, address):
|
||||
self.socket = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
|
||||
# syslog may require either DGRAM or STREAM sockets
|
||||
try:
|
||||
self.socket.connect(address)
|
||||
except socket.error:
|
||||
self.socket.close()
|
||||
self.socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
||||
self.socket = socket.socket(socket.AF_UNIX, self.socktype)
|
||||
try:
|
||||
self.socket.connect(address)
|
||||
except socket.error:
|
||||
|
|
|
@ -112,7 +112,7 @@ __copyright__ = """
|
|||
__version__ = '1.0.7'
|
||||
|
||||
import collections
|
||||
import sys, os, re
|
||||
import sys, os, re, subprocess
|
||||
|
||||
### Globals & Constants
|
||||
|
||||
|
@ -922,13 +922,15 @@ def _syscmd_file(target,default=''):
|
|||
if sys.platform in ('dos','win32','win16','os2'):
|
||||
# XXX Others too ?
|
||||
return default
|
||||
target = _follow_symlinks(target).replace('"', '\\"')
|
||||
target = _follow_symlinks(target)
|
||||
try:
|
||||
f = os.popen('file -b "%s" 2> %s' % (target, DEV_NULL))
|
||||
proc = subprocess.Popen(['file', target],
|
||||
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||
|
||||
except (AttributeError,os.error):
|
||||
return default
|
||||
output = f.read().strip()
|
||||
rc = f.close()
|
||||
output = proc.communicate()[0].decode('latin-1')
|
||||
rc = proc.wait()
|
||||
if not output or rc:
|
||||
return default
|
||||
else:
|
||||
|
|
|
@ -159,15 +159,19 @@ class Stats:
|
|||
# along with some printable description
|
||||
sort_arg_dict_default = {
|
||||
"calls" : (((1,-1), ), "call count"),
|
||||
"ncalls" : (((1,-1), ), "call count"),
|
||||
"cumtime" : (((3,-1), ), "cumulative time"),
|
||||
"cumulative": (((3,-1), ), "cumulative time"),
|
||||
"file" : (((4, 1), ), "file name"),
|
||||
"filename" : (((4, 1), ), "file name"),
|
||||
"line" : (((5, 1), ), "line number"),
|
||||
"module" : (((4, 1), ), "file name"),
|
||||
"name" : (((6, 1), ), "function name"),
|
||||
"nfl" : (((6, 1),(4, 1),(5, 1),), "name/file/line"),
|
||||
"pcalls" : (((0,-1), ), "call count"),
|
||||
"pcalls" : (((0,-1), ), "primitive call count"),
|
||||
"stdname" : (((7, 1), ), "standard name"),
|
||||
"time" : (((2,-1), ), "internal time"),
|
||||
"tottime" : (((2,-1), ), "internal time"),
|
||||
}
|
||||
|
||||
def get_sort_arg_defs(self):
|
||||
|
|
|
@ -562,7 +562,7 @@ class ForkingMixIn:
|
|||
self.collect_children()
|
||||
|
||||
def service_actions(self):
|
||||
"""Collect the zombie child processes regularly in the ForkingMixin.
|
||||
"""Collect the zombie child processes regularly in the ForkingMixIn.
|
||||
|
||||
service_actions is called in the BaseServer's serve_forver loop.
|
||||
"""
|
||||
|
|
|
@ -1445,9 +1445,16 @@ class Popen(object):
|
|||
pid, sts = _waitpid(self.pid, _WNOHANG)
|
||||
if pid == self.pid:
|
||||
self._handle_exitstatus(sts)
|
||||
except _os_error:
|
||||
except _os_error as e:
|
||||
if _deadstate is not None:
|
||||
self.returncode = _deadstate
|
||||
elif e.errno == errno.ECHILD:
|
||||
# This happens if SIGCLD is set to be ignored or
|
||||
# waiting for child processes has otherwise been
|
||||
# disabled for our process. This child is dead, we
|
||||
# can't get the status.
|
||||
# http://bugs.python.org/issue15756
|
||||
self.returncode = 0
|
||||
return self.returncode
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,15 @@
|
|||
import signal, subprocess, sys
|
||||
import signal, subprocess, sys, time
|
||||
# On Linux this causes os.waitpid to fail with OSError as the OS has already
|
||||
# reaped our child process. The wait() passing the OSError on to the caller
|
||||
# and causing us to exit with an error is what we are testing against.
|
||||
signal.signal(signal.SIGCHLD, signal.SIG_IGN)
|
||||
subprocess.Popen([sys.executable, '-c', 'print("albatross")']).wait()
|
||||
# Also ensure poll() handles an errno.ECHILD appropriately.
|
||||
p = subprocess.Popen([sys.executable, '-c', 'print("albatross")'])
|
||||
num_polls = 0
|
||||
while p.poll() is None:
|
||||
# Waiting for the process to finish.
|
||||
time.sleep(0.01) # Avoid being a CPU busy loop.
|
||||
num_polls += 1
|
||||
if num_polls > 3000:
|
||||
raise RuntimeError('poll should have returned 0 within 30 seconds')
|
||||
|
|
|
@ -316,6 +316,17 @@ class SkipitemTest(unittest.TestCase):
|
|||
c, i, when_skipped, when_not_skipped))
|
||||
self.assertIs(when_skipped, when_not_skipped, message)
|
||||
|
||||
def test_parse_tuple_and_keywords(self):
|
||||
# parse_tuple_and_keywords error handling tests
|
||||
self.assertRaises(TypeError, _testcapi.parse_tuple_and_keywords,
|
||||
(), {}, 42, [])
|
||||
self.assertRaises(ValueError, _testcapi.parse_tuple_and_keywords,
|
||||
(), {}, b'', 42)
|
||||
self.assertRaises(ValueError, _testcapi.parse_tuple_and_keywords,
|
||||
(), {}, b'', [''] * 42)
|
||||
self.assertRaises(ValueError, _testcapi.parse_tuple_and_keywords,
|
||||
(), {}, b'', [42])
|
||||
|
||||
def test_main():
|
||||
support.run_unittest(CAPITest, TestPendingCalls,
|
||||
Test6012, EmbeddingTest, SkipitemTest)
|
||||
|
|
|
@ -62,6 +62,7 @@ class BaseTestCase(unittest.TestCase):
|
|||
|
||||
def tearDown(self):
|
||||
self.thread.stop()
|
||||
self.thread = None
|
||||
os.environ.__exit__()
|
||||
support.threading_cleanup(*self._threads)
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import unittest
|
||||
from test import script_helper
|
||||
from test import support
|
||||
import subprocess
|
||||
import sys
|
||||
|
@ -191,15 +192,134 @@ class ProcessTestCase(BaseTestCase):
|
|||
p.wait()
|
||||
self.assertEqual(p.stderr, None)
|
||||
|
||||
def _assert_python(self, pre_args, **kwargs):
|
||||
# We include sys.exit() to prevent the test runner from hanging
|
||||
# whenever python is found.
|
||||
args = pre_args + ["import sys; sys.exit(47)"]
|
||||
p = subprocess.Popen(args, **kwargs)
|
||||
p.wait()
|
||||
self.assertEqual(47, p.returncode)
|
||||
|
||||
# TODO: make this test work on Linux.
|
||||
# This may be failing on Linux because of issue #7774.
|
||||
@unittest.skipIf(sys.platform not in ('win32', 'darwin'),
|
||||
"possible bug using executable argument on Linux")
|
||||
def test_executable(self):
|
||||
# Check that the executable argument works.
|
||||
self._assert_python(["doesnotexist", "-c"], executable=sys.executable)
|
||||
|
||||
def test_executable_takes_precedence(self):
|
||||
# Check that the executable argument takes precedence over args[0].
|
||||
#
|
||||
# Verify first that the call succeeds without the executable arg.
|
||||
pre_args = [sys.executable, "-c"]
|
||||
self._assert_python(pre_args)
|
||||
self.assertRaises(FileNotFoundError, self._assert_python, pre_args,
|
||||
executable="doesnotexist")
|
||||
|
||||
@unittest.skipIf(mswindows, "executable argument replaces shell")
|
||||
def test_executable_replaces_shell(self):
|
||||
# Check that the executable argument replaces the default shell
|
||||
# when shell=True.
|
||||
self._assert_python([], executable=sys.executable, shell=True)
|
||||
|
||||
# For use in the test_cwd* tests below.
|
||||
def _normalize_cwd(self, cwd):
|
||||
# Normalize an expected cwd (for Tru64 support).
|
||||
# We can't use os.path.realpath since it doesn't expand Tru64 {memb}
|
||||
# strings. See bug #1063571.
|
||||
original_cwd = os.getcwd()
|
||||
os.chdir(cwd)
|
||||
cwd = os.getcwd()
|
||||
os.chdir(original_cwd)
|
||||
return cwd
|
||||
|
||||
# For use in the test_cwd* tests below.
|
||||
def _split_python_path(self):
|
||||
# Return normalized (python_dir, python_base).
|
||||
python_path = os.path.realpath(sys.executable)
|
||||
return os.path.split(python_path)
|
||||
|
||||
# For use in the test_cwd* tests below.
|
||||
def _assert_cwd(self, expected_cwd, python_arg, **kwargs):
|
||||
# Invoke Python via Popen, and assert that (1) the call succeeds,
|
||||
# and that (2) the current working directory of the child process
|
||||
# matches *expected_cwd*.
|
||||
p = subprocess.Popen([python_arg, "-c",
|
||||
"import os, sys; "
|
||||
"sys.stdout.write(os.getcwd()); "
|
||||
"sys.exit(47)"],
|
||||
stdout=subprocess.PIPE,
|
||||
**kwargs)
|
||||
self.addCleanup(p.stdout.close)
|
||||
p.wait()
|
||||
self.assertEqual(47, p.returncode)
|
||||
normcase = os.path.normcase
|
||||
self.assertEqual(normcase(expected_cwd),
|
||||
normcase(p.stdout.read().decode("utf-8")))
|
||||
|
||||
def test_cwd(self):
|
||||
# Check that cwd changes the cwd for the child process.
|
||||
temp_dir = tempfile.gettempdir()
|
||||
temp_dir = self._normalize_cwd(temp_dir)
|
||||
self._assert_cwd(temp_dir, sys.executable, cwd=temp_dir)
|
||||
|
||||
@unittest.skipIf(mswindows, "pending resolution of issue #15533")
|
||||
def test_cwd_with_relative_arg(self):
|
||||
# Check that Popen looks for args[0] relative to cwd if args[0]
|
||||
# is relative.
|
||||
python_dir, python_base = self._split_python_path()
|
||||
rel_python = os.path.join(os.curdir, python_base)
|
||||
with support.temp_cwd() as wrong_dir:
|
||||
# Before calling with the correct cwd, confirm that the call fails
|
||||
# without cwd and with the wrong cwd.
|
||||
self.assertRaises(FileNotFoundError, subprocess.Popen,
|
||||
[rel_python])
|
||||
self.assertRaises(FileNotFoundError, subprocess.Popen,
|
||||
[rel_python], cwd=wrong_dir)
|
||||
python_dir = self._normalize_cwd(python_dir)
|
||||
self._assert_cwd(python_dir, rel_python, cwd=python_dir)
|
||||
|
||||
@unittest.skipIf(mswindows, "pending resolution of issue #15533")
|
||||
def test_cwd_with_relative_executable(self):
|
||||
# Check that Popen looks for executable relative to cwd if executable
|
||||
# is relative (and that executable takes precedence over args[0]).
|
||||
python_dir, python_base = self._split_python_path()
|
||||
rel_python = os.path.join(os.curdir, python_base)
|
||||
doesntexist = "somethingyoudonthave"
|
||||
with support.temp_cwd() as wrong_dir:
|
||||
# Before calling with the correct cwd, confirm that the call fails
|
||||
# without cwd and with the wrong cwd.
|
||||
self.assertRaises(FileNotFoundError, subprocess.Popen,
|
||||
[doesntexist], executable=rel_python)
|
||||
self.assertRaises(FileNotFoundError, subprocess.Popen,
|
||||
[doesntexist], executable=rel_python,
|
||||
cwd=wrong_dir)
|
||||
python_dir = self._normalize_cwd(python_dir)
|
||||
self._assert_cwd(python_dir, doesntexist, executable=rel_python,
|
||||
cwd=python_dir)
|
||||
|
||||
def test_cwd_with_absolute_arg(self):
|
||||
# Check that Popen can find the executable when the cwd is wrong
|
||||
# if args[0] is an absolute path.
|
||||
python_dir, python_base = self._split_python_path()
|
||||
abs_python = os.path.join(python_dir, python_base)
|
||||
rel_python = os.path.join(os.curdir, python_base)
|
||||
with script_helper.temp_dir() as wrong_dir:
|
||||
# Before calling with an absolute path, confirm that using a
|
||||
# relative path fails.
|
||||
self.assertRaises(FileNotFoundError, subprocess.Popen,
|
||||
[rel_python], cwd=wrong_dir)
|
||||
wrong_dir = self._normalize_cwd(wrong_dir)
|
||||
self._assert_cwd(wrong_dir, abs_python, cwd=wrong_dir)
|
||||
|
||||
@unittest.skipIf(sys.base_prefix != sys.prefix,
|
||||
'Test is not venv-compatible')
|
||||
def test_executable_with_cwd(self):
|
||||
python_dir = os.path.dirname(os.path.realpath(sys.executable))
|
||||
p = subprocess.Popen(["somethingyoudonthave", "-c",
|
||||
"import sys; sys.exit(47)"],
|
||||
python_dir, python_base = self._split_python_path()
|
||||
python_dir = self._normalize_cwd(python_dir)
|
||||
self._assert_cwd(python_dir, "somethingyoudonthave",
|
||||
executable=sys.executable, cwd=python_dir)
|
||||
p.wait()
|
||||
self.assertEqual(p.returncode, 47)
|
||||
|
||||
@unittest.skipIf(sys.base_prefix != sys.prefix,
|
||||
'Test is not venv-compatible')
|
||||
|
@ -208,11 +328,7 @@ class ProcessTestCase(BaseTestCase):
|
|||
def test_executable_without_cwd(self):
|
||||
# For a normal installation, it should work without 'cwd'
|
||||
# argument. For test runs in the build directory, see #7774.
|
||||
p = subprocess.Popen(["somethingyoudonthave", "-c",
|
||||
"import sys; sys.exit(47)"],
|
||||
executable=sys.executable)
|
||||
p.wait()
|
||||
self.assertEqual(p.returncode, 47)
|
||||
self._assert_cwd('', "somethingyoudonthave", executable=sys.executable)
|
||||
|
||||
def test_stdin_pipe(self):
|
||||
# stdin redirection
|
||||
|
@ -369,24 +485,6 @@ class ProcessTestCase(BaseTestCase):
|
|||
p.wait()
|
||||
self.assertEqual(p.stdin, None)
|
||||
|
||||
def test_cwd(self):
|
||||
tmpdir = tempfile.gettempdir()
|
||||
# We cannot use os.path.realpath to canonicalize the path,
|
||||
# since it doesn't expand Tru64 {memb} strings. See bug 1063571.
|
||||
cwd = os.getcwd()
|
||||
os.chdir(tmpdir)
|
||||
tmpdir = os.getcwd()
|
||||
os.chdir(cwd)
|
||||
p = subprocess.Popen([sys.executable, "-c",
|
||||
'import sys,os;'
|
||||
'sys.stdout.write(os.getcwd())'],
|
||||
stdout=subprocess.PIPE,
|
||||
cwd=tmpdir)
|
||||
self.addCleanup(p.stdout.close)
|
||||
normcase = os.path.normcase
|
||||
self.assertEqual(normcase(p.stdout.read().decode("utf-8")),
|
||||
normcase(tmpdir))
|
||||
|
||||
def test_env(self):
|
||||
newenv = os.environ.copy()
|
||||
newenv["FRUIT"] = "orange"
|
||||
|
|
|
@ -225,11 +225,9 @@ class ThreadedImportTests(unittest.TestCase):
|
|||
@reap_threads
|
||||
def test_main():
|
||||
old_switchinterval = None
|
||||
# Issue #15599: FreeBSD/KVM cannot handle gil_interval == 1.
|
||||
new_switchinterval = 0.00001 if 'freebsd' in sys.platform else 0.00000001
|
||||
try:
|
||||
old_switchinterval = sys.getswitchinterval()
|
||||
sys.setswitchinterval(new_switchinterval)
|
||||
sys.setswitchinterval(1e-5)
|
||||
except AttributeError:
|
||||
pass
|
||||
try:
|
||||
|
|
|
@ -1893,10 +1893,23 @@ class TreeBuilderTest(unittest.TestCase):
|
|||
sample1 = ('<!DOCTYPE html PUBLIC'
|
||||
' "-//W3C//DTD XHTML 1.0 Transitional//EN"'
|
||||
' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">'
|
||||
'<html>text</html>')
|
||||
'<html>text<div>subtext</div>tail</html>')
|
||||
|
||||
sample2 = '''<toplevel>sometext</toplevel>'''
|
||||
|
||||
def _check_sample1_element(self, e):
|
||||
self.assertEqual(e.tag, 'html')
|
||||
self.assertEqual(e.text, 'text')
|
||||
self.assertEqual(e.tail, None)
|
||||
self.assertEqual(e.attrib, {})
|
||||
children = list(e)
|
||||
self.assertEqual(len(children), 1)
|
||||
child = children[0]
|
||||
self.assertEqual(child.tag, 'div')
|
||||
self.assertEqual(child.text, 'subtext')
|
||||
self.assertEqual(child.tail, 'tail')
|
||||
self.assertEqual(child.attrib, {})
|
||||
|
||||
def test_dummy_builder(self):
|
||||
class BaseDummyBuilder:
|
||||
def close(self):
|
||||
|
@ -1929,7 +1942,7 @@ class TreeBuilderTest(unittest.TestCase):
|
|||
parser.feed(self.sample1)
|
||||
|
||||
e = parser.close()
|
||||
self.assertEqual(e.tag, 'html')
|
||||
self._check_sample1_element(e)
|
||||
|
||||
def test_element_factory(self):
|
||||
lst = []
|
||||
|
@ -1945,6 +1958,33 @@ class TreeBuilderTest(unittest.TestCase):
|
|||
|
||||
self.assertEqual(lst, ['toplevel'])
|
||||
|
||||
def _check_element_factory_class(self, cls):
|
||||
tb = ET.TreeBuilder(element_factory=cls)
|
||||
|
||||
parser = ET.XMLParser(target=tb)
|
||||
parser.feed(self.sample1)
|
||||
e = parser.close()
|
||||
self.assertIsInstance(e, cls)
|
||||
self._check_sample1_element(e)
|
||||
|
||||
def test_element_factory_subclass(self):
|
||||
class MyElement(ET.Element):
|
||||
pass
|
||||
self._check_element_factory_class(MyElement)
|
||||
|
||||
def test_element_factory_pure_python_subclass(self):
|
||||
# Mimick SimpleTAL's behaviour (issue #16089): both versions of
|
||||
# TreeBuilder should be able to cope with a subclass of the
|
||||
# pure Python Element class.
|
||||
base = ET._Element
|
||||
# Not from a C extension
|
||||
self.assertEqual(base.__module__, 'xml.etree.ElementTree')
|
||||
# Force some multiple inheritance with a C class to make things
|
||||
# more interesting.
|
||||
class MyElement(base, ValueError):
|
||||
pass
|
||||
self._check_element_factory_class(MyElement)
|
||||
|
||||
def test_doctype(self):
|
||||
class DoctypeParser:
|
||||
_doctype = None
|
||||
|
|
|
@ -303,7 +303,9 @@ class Element:
|
|||
self._children.insert(index, element)
|
||||
|
||||
def _assert_is_element(self, e):
|
||||
if not isinstance(e, Element):
|
||||
# Need to refer to the actual Python implementation, not the
|
||||
# shadowing C implementation.
|
||||
if not isinstance(e, _Element):
|
||||
raise TypeError('expected an Element, not %s' % type(e).__name__)
|
||||
|
||||
##
|
||||
|
|
|
@ -49,9 +49,9 @@ Jason Asbahr
|
|||
David Ascher
|
||||
Chris AtLee
|
||||
Aymeric Augustin
|
||||
Jesús Cea Avión
|
||||
John Aycock
|
||||
Donovan Baarda
|
||||
Arne Babenhauserheide
|
||||
Attila Babo
|
||||
Marcin Bachry
|
||||
Alfonso Baciero
|
||||
|
@ -94,6 +94,7 @@ Ben Bell
|
|||
Thomas Bellman
|
||||
Alexander “Саша” Belopolsky
|
||||
Eli Bendersky
|
||||
David Benjamin
|
||||
Andrew Bennetts
|
||||
Andy Bensky
|
||||
Bennett Benson
|
||||
|
@ -101,6 +102,7 @@ Ezra Berch
|
|||
Michel Van den Bergh
|
||||
Julian Berman
|
||||
Brice Berna
|
||||
Olivier Bernard
|
||||
Eric Beser
|
||||
Steven Bethard
|
||||
Stephen Bevan
|
||||
|
@ -183,6 +185,7 @@ Terry Carroll
|
|||
Lorenzo M. Catucci
|
||||
Donn Cave
|
||||
Charles Cazabon
|
||||
Jesús Cea Avión
|
||||
Per Cederqvist
|
||||
Matej Cepl
|
||||
Carl Cerecke
|
||||
|
@ -246,6 +249,7 @@ Christopher A. Craig
|
|||
Jeremy Craven
|
||||
Laura Creighton
|
||||
Simon Cross
|
||||
Felipe Cruz
|
||||
Drew Csillag
|
||||
Joaquin Cuenca Abela
|
||||
John Cugini
|
||||
|
|
5397
Misc/HISTORY
5397
Misc/HISTORY
File diff suppressed because it is too large
Load Diff
|
@ -177,12 +177,12 @@ escape_encode(PyObject *self,
|
|||
return NULL;
|
||||
|
||||
size = PyBytes_GET_SIZE(str);
|
||||
newsize = 4*size;
|
||||
if (newsize > PY_SSIZE_T_MAX || newsize / 4 != size) {
|
||||
if (size > PY_SSIZE_T_MAX / 4) {
|
||||
PyErr_SetString(PyExc_OverflowError,
|
||||
"string is too large to encode");
|
||||
return NULL;
|
||||
}
|
||||
newsize = 4*size;
|
||||
v = PyBytes_FromStringAndSize(NULL, newsize);
|
||||
|
||||
if (v == NULL) {
|
||||
|
|
|
@ -1265,14 +1265,13 @@ wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple,
|
|||
assert(ptoappend != NULL);
|
||||
assert(ntoappend > 0);
|
||||
while (usednew + ntoappend > totalnew) {
|
||||
size_t bigger = totalnew << 1;
|
||||
if ((bigger >> 1) != totalnew) { /* overflow */
|
||||
if (totalnew > (PY_SSIZE_T_MAX >> 1)) { /* overflow */
|
||||
PyErr_NoMemory();
|
||||
goto Done;
|
||||
}
|
||||
if (_PyBytes_Resize(&newfmt, bigger) < 0)
|
||||
totalnew <<= 1;
|
||||
if (_PyBytes_Resize(&newfmt, totalnew) < 0)
|
||||
goto Done;
|
||||
totalnew = bigger;
|
||||
pnew = PyBytes_AsString(newfmt) + usednew;
|
||||
}
|
||||
memcpy(pnew, ptoappend, ntoappend);
|
||||
|
|
|
@ -207,7 +207,7 @@ _mpd_mul_words(mpd_uint_t *hi, mpd_uint_t *lo, mpd_uint_t a, mpd_uint_t b)
|
|||
{
|
||||
mpd_uint_t h, l;
|
||||
|
||||
asm ( "mulq %3\n\t"
|
||||
__asm__ ( "mulq %3\n\t"
|
||||
: "=d" (h), "=a" (l)
|
||||
: "%a" (a), "rm" (b)
|
||||
: "cc"
|
||||
|
@ -223,7 +223,7 @@ _mpd_div_words(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t hi, mpd_uint_t lo,
|
|||
{
|
||||
mpd_uint_t qq, rr;
|
||||
|
||||
asm ( "divq %4\n\t"
|
||||
__asm__ ( "divq %4\n\t"
|
||||
: "=a" (qq), "=d" (rr)
|
||||
: "a" (lo), "d" (hi), "rm" (d)
|
||||
: "cc"
|
||||
|
@ -464,7 +464,7 @@ _mpd_mul_words(mpd_uint_t *hi, mpd_uint_t *lo, mpd_uint_t a, mpd_uint_t b)
|
|||
{
|
||||
mpd_uint_t h, l;
|
||||
|
||||
asm ( "mull %3\n\t"
|
||||
__asm__ ( "mull %3\n\t"
|
||||
: "=d" (h), "=a" (l)
|
||||
: "%a" (a), "rm" (b)
|
||||
: "cc"
|
||||
|
@ -480,7 +480,7 @@ _mpd_div_words(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t hi, mpd_uint_t lo,
|
|||
{
|
||||
mpd_uint_t qq, rr;
|
||||
|
||||
asm ( "divl %4\n\t"
|
||||
__asm__ ( "divl %4\n\t"
|
||||
: "=a" (qq), "=d" (rr)
|
||||
: "a" (lo), "d" (hi), "rm" (d)
|
||||
: "cc"
|
||||
|
|
|
@ -402,7 +402,7 @@ ppro_mulmod(mpd_uint_t a, mpd_uint_t b, double *dmod, uint32_t *dinvmod)
|
|||
{
|
||||
mpd_uint_t retval;
|
||||
|
||||
asm (
|
||||
__asm__ (
|
||||
"fildl %2\n\t"
|
||||
"fildl %1\n\t"
|
||||
"fmulp %%st, %%st(1)\n\t"
|
||||
|
@ -432,7 +432,7 @@ static inline void
|
|||
ppro_mulmod2c(mpd_uint_t *a0, mpd_uint_t *a1, mpd_uint_t w,
|
||||
double *dmod, uint32_t *dinvmod)
|
||||
{
|
||||
asm (
|
||||
__asm__ (
|
||||
"fildl %2\n\t"
|
||||
"fildl (%1)\n\t"
|
||||
"fmul %%st(1), %%st\n\t"
|
||||
|
@ -471,7 +471,7 @@ static inline void
|
|||
ppro_mulmod2(mpd_uint_t *a0, mpd_uint_t b0, mpd_uint_t *a1, mpd_uint_t b1,
|
||||
double *dmod, uint32_t *dinvmod)
|
||||
{
|
||||
asm (
|
||||
__asm__ (
|
||||
"fildl %3\n\t"
|
||||
"fildl (%2)\n\t"
|
||||
"fmulp %%st, %%st(1)\n\t"
|
||||
|
|
|
@ -18,8 +18,13 @@ except ImportError:
|
|||
C = import_fresh_module('decimal', fresh=['_decimal'])
|
||||
P = import_fresh_module('decimal', blocked=['_decimal'])
|
||||
|
||||
|
||||
# Pi function from the decimal.py documentation
|
||||
#
|
||||
# NOTE: This is the pi function from the decimal documentation, modified
|
||||
# for benchmarking purposes. Since floats do not have a context, the higher
|
||||
# intermediate precision from the original is NOT used, so the modified
|
||||
# algorithm only gives an approximation to the correctly rounded result.
|
||||
# For serious use, refer to the documentation or the appropriate literature.
|
||||
#
|
||||
def pi_float():
|
||||
"""native float"""
|
||||
lasts, t, s, n, na, d, da = 0, 3.0, 3, 1, 0, 0, 24
|
||||
|
|
|
@ -123,17 +123,11 @@ deepcopy(PyObject* object, PyObject* memo)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
args = PyTuple_New(2);
|
||||
args = PyTuple_Pack(2, object, memo);
|
||||
if (!args)
|
||||
return NULL;
|
||||
|
||||
Py_INCREF(object); PyTuple_SET_ITEM(args, 0, (PyObject*) object);
|
||||
Py_INCREF(memo); PyTuple_SET_ITEM(args, 1, (PyObject*) memo);
|
||||
|
||||
result = PyObject_CallObject(elementtree_deepcopy_obj, args);
|
||||
|
||||
Py_DECREF(args);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -141,48 +135,16 @@ LOCAL(PyObject*)
|
|||
list_join(PyObject* list)
|
||||
{
|
||||
/* join list elements (destroying the list in the process) */
|
||||
|
||||
PyObject* joiner;
|
||||
PyObject* function;
|
||||
PyObject* args;
|
||||
PyObject* result;
|
||||
|
||||
switch (PyList_GET_SIZE(list)) {
|
||||
case 0:
|
||||
Py_DECREF(list);
|
||||
return PyBytes_FromString("");
|
||||
case 1:
|
||||
result = PyList_GET_ITEM(list, 0);
|
||||
Py_INCREF(result);
|
||||
Py_DECREF(list);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* two or more elements: slice out a suitable separator from the
|
||||
first member, and use that to join the entire list */
|
||||
|
||||
joiner = PySequence_GetSlice(PyList_GET_ITEM(list, 0), 0, 0);
|
||||
joiner = PyUnicode_FromStringAndSize("", 0);
|
||||
if (!joiner)
|
||||
return NULL;
|
||||
|
||||
function = PyObject_GetAttrString(joiner, "join");
|
||||
if (!function) {
|
||||
result = PyUnicode_Join(joiner, list);
|
||||
Py_DECREF(joiner);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
args = PyTuple_New(1);
|
||||
if (!args)
|
||||
return NULL;
|
||||
|
||||
PyTuple_SET_ITEM(args, 0, list);
|
||||
|
||||
result = PyObject_CallObject(function, args);
|
||||
|
||||
Py_DECREF(args); /* also removes list */
|
||||
Py_DECREF(function);
|
||||
Py_DECREF(joiner);
|
||||
|
||||
if (result)
|
||||
Py_DECREF(list);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -399,6 +361,7 @@ element_init(PyObject *self, PyObject *args, PyObject *kwds)
|
|||
return -1;
|
||||
if (kwds) {
|
||||
if (PyDict_Update(attrib, kwds) < 0) {
|
||||
Py_DECREF(attrib);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -407,38 +370,34 @@ element_init(PyObject *self, PyObject *args, PyObject *kwds)
|
|||
attrib = get_attrib_from_keywords(kwds);
|
||||
if (!attrib)
|
||||
return -1;
|
||||
} else {
|
||||
/* no attrib arg, no kwds, so no attributes */
|
||||
Py_INCREF(Py_None);
|
||||
attrib = Py_None;
|
||||
}
|
||||
|
||||
self_elem = (ElementObject *)self;
|
||||
|
||||
if (attrib != Py_None && !is_empty_dict(attrib)) {
|
||||
if (attrib != NULL && !is_empty_dict(attrib)) {
|
||||
if (create_extra(self_elem, attrib) < 0) {
|
||||
PyObject_Del(self_elem);
|
||||
Py_DECREF(attrib);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* We own a reference to attrib here and it's no longer needed. */
|
||||
Py_DECREF(attrib);
|
||||
Py_XDECREF(attrib);
|
||||
|
||||
/* Replace the objects already pointed to by tag, text and tail. */
|
||||
tmp = self_elem->tag;
|
||||
self_elem->tag = tag;
|
||||
Py_INCREF(tag);
|
||||
self_elem->tag = tag;
|
||||
Py_DECREF(tmp);
|
||||
|
||||
tmp = self_elem->text;
|
||||
self_elem->text = Py_None;
|
||||
Py_INCREF(Py_None);
|
||||
self_elem->text = Py_None;
|
||||
Py_DECREF(JOIN_OBJ(tmp));
|
||||
|
||||
tmp = self_elem->tail;
|
||||
self_elem->tail = Py_None;
|
||||
Py_INCREF(Py_None);
|
||||
self_elem->tail = Py_None;
|
||||
Py_DECREF(JOIN_OBJ(tmp));
|
||||
|
||||
return 0;
|
||||
|
@ -520,11 +479,11 @@ element_get_attrib(ElementObject* self)
|
|||
PyObject* res = self->extra->attrib;
|
||||
|
||||
if (res == Py_None) {
|
||||
Py_DECREF(res);
|
||||
/* create missing dictionary */
|
||||
res = PyDict_New();
|
||||
if (!res)
|
||||
return NULL;
|
||||
Py_DECREF(Py_None);
|
||||
self->extra->attrib = res;
|
||||
}
|
||||
|
||||
|
@ -824,7 +783,7 @@ element_deepcopy(ElementObject* self, PyObject* args)
|
|||
}
|
||||
|
||||
/* add object to memo dictionary (so deepcopy won't visit it again) */
|
||||
id = PyLong_FromLong((Py_uintptr_t) self);
|
||||
id = PyLong_FromSsize_t((Py_uintptr_t) self);
|
||||
if (!id)
|
||||
goto error;
|
||||
|
||||
|
@ -2038,8 +1997,8 @@ typedef struct {
|
|||
|
||||
PyObject *root; /* root node (first created node) */
|
||||
|
||||
ElementObject *this; /* current node */
|
||||
ElementObject *last; /* most recently created node */
|
||||
PyObject *this; /* current node */
|
||||
PyObject *last; /* most recently created node */
|
||||
|
||||
PyObject *data; /* data collector (string or list), or NULL */
|
||||
|
||||
|
@ -2071,9 +2030,9 @@ treebuilder_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|||
t->root = NULL;
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
t->this = (ElementObject *)Py_None;
|
||||
t->this = Py_None;
|
||||
Py_INCREF(Py_None);
|
||||
t->last = (ElementObject *)Py_None;
|
||||
t->last = Py_None;
|
||||
|
||||
t->data = NULL;
|
||||
t->element_factory = NULL;
|
||||
|
@ -2081,6 +2040,7 @@ treebuilder_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|||
if (!t->stack) {
|
||||
Py_DECREF(t->this);
|
||||
Py_DECREF(t->last);
|
||||
Py_DECREF((PyObject *) t);
|
||||
return NULL;
|
||||
}
|
||||
t->index = 0;
|
||||
|
@ -2098,6 +2058,7 @@ treebuilder_init(PyObject *self, PyObject *args, PyObject *kwds)
|
|||
static char *kwlist[] = {"element_factory", 0};
|
||||
PyObject *element_factory = NULL;
|
||||
TreeBuilderObject *self_tb = (TreeBuilderObject *)self;
|
||||
PyObject *tmp;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:TreeBuilder", kwlist,
|
||||
&element_factory)) {
|
||||
|
@ -2106,8 +2067,9 @@ treebuilder_init(PyObject *self, PyObject *args, PyObject *kwds)
|
|||
|
||||
if (element_factory) {
|
||||
Py_INCREF(element_factory);
|
||||
Py_XDECREF(self_tb->element_factory);
|
||||
tmp = self_tb->element_factory;
|
||||
self_tb->element_factory = element_factory;
|
||||
Py_XDECREF(tmp);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -2128,17 +2090,17 @@ treebuilder_gc_traverse(TreeBuilderObject *self, visitproc visit, void *arg)
|
|||
static int
|
||||
treebuilder_gc_clear(TreeBuilderObject *self)
|
||||
{
|
||||
Py_XDECREF(self->end_ns_event_obj);
|
||||
Py_XDECREF(self->start_ns_event_obj);
|
||||
Py_XDECREF(self->end_event_obj);
|
||||
Py_XDECREF(self->start_event_obj);
|
||||
Py_XDECREF(self->events);
|
||||
Py_DECREF(self->stack);
|
||||
Py_XDECREF(self->data);
|
||||
Py_DECREF(self->last);
|
||||
Py_DECREF(self->this);
|
||||
Py_CLEAR(self->end_ns_event_obj);
|
||||
Py_CLEAR(self->start_ns_event_obj);
|
||||
Py_CLEAR(self->end_event_obj);
|
||||
Py_CLEAR(self->start_event_obj);
|
||||
Py_CLEAR(self->events);
|
||||
Py_CLEAR(self->stack);
|
||||
Py_CLEAR(self->data);
|
||||
Py_CLEAR(self->last);
|
||||
Py_CLEAR(self->this);
|
||||
Py_CLEAR(self->element_factory);
|
||||
Py_XDECREF(self->root);
|
||||
Py_CLEAR(self->root);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2150,6 +2112,64 @@ treebuilder_dealloc(TreeBuilderObject *self)
|
|||
Py_TYPE(self)->tp_free((PyObject *)self);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* helpers for handling of arbitrary element-like objects */
|
||||
|
||||
static int
|
||||
treebuilder_set_element_text_or_tail(PyObject *element, PyObject *data,
|
||||
PyObject **dest, _Py_Identifier *name)
|
||||
{
|
||||
if (Element_CheckExact(element)) {
|
||||
Py_DECREF(JOIN_OBJ(*dest));
|
||||
*dest = JOIN_SET(data, PyList_CheckExact(data));
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
PyObject *joined = list_join(data);
|
||||
int r;
|
||||
if (joined == NULL)
|
||||
return -1;
|
||||
r = _PyObject_SetAttrId(element, name, joined);
|
||||
Py_DECREF(joined);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
/* These two functions steal a reference to data */
|
||||
static int
|
||||
treebuilder_set_element_text(PyObject *element, PyObject *data)
|
||||
{
|
||||
_Py_IDENTIFIER(text);
|
||||
return treebuilder_set_element_text_or_tail(
|
||||
element, data, &((ElementObject *) element)->text, &PyId_text);
|
||||
}
|
||||
|
||||
static int
|
||||
treebuilder_set_element_tail(PyObject *element, PyObject *data)
|
||||
{
|
||||
_Py_IDENTIFIER(tail);
|
||||
return treebuilder_set_element_text_or_tail(
|
||||
element, data, &((ElementObject *) element)->tail, &PyId_tail);
|
||||
}
|
||||
|
||||
static int
|
||||
treebuilder_add_subelement(PyObject *element, PyObject *child)
|
||||
{
|
||||
_Py_IDENTIFIER(append);
|
||||
if (Element_CheckExact(element)) {
|
||||
ElementObject *elem = (ElementObject *) element;
|
||||
return element_add_subelement(elem, child);
|
||||
}
|
||||
else {
|
||||
PyObject *res;
|
||||
res = _PyObject_CallMethodId(element, &PyId_append, "O", child);
|
||||
if (res == NULL)
|
||||
return -1;
|
||||
Py_DECREF(res);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* handlers */
|
||||
|
||||
|
@ -2162,15 +2182,12 @@ treebuilder_handle_start(TreeBuilderObject* self, PyObject* tag,
|
|||
|
||||
if (self->data) {
|
||||
if (self->this == self->last) {
|
||||
Py_DECREF(JOIN_OBJ(self->last->text));
|
||||
self->last->text = JOIN_SET(
|
||||
self->data, PyList_CheckExact(self->data)
|
||||
);
|
||||
} else {
|
||||
Py_DECREF(JOIN_OBJ(self->last->tail));
|
||||
self->last->tail = JOIN_SET(
|
||||
self->data, PyList_CheckExact(self->data)
|
||||
);
|
||||
if (treebuilder_set_element_text(self->last, self->data))
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
if (treebuilder_set_element_tail(self->last, self->data))
|
||||
return NULL;
|
||||
}
|
||||
self->data = NULL;
|
||||
}
|
||||
|
@ -2184,10 +2201,10 @@ treebuilder_handle_start(TreeBuilderObject* self, PyObject* tag,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
this = (PyObject*) self->this;
|
||||
this = self->this;
|
||||
|
||||
if (this != Py_None) {
|
||||
if (element_add_subelement((ElementObject*) this, node) < 0)
|
||||
if (treebuilder_add_subelement(this, node) < 0)
|
||||
goto error;
|
||||
} else {
|
||||
if (self->root) {
|
||||
|
@ -2213,19 +2230,17 @@ treebuilder_handle_start(TreeBuilderObject* self, PyObject* tag,
|
|||
|
||||
Py_DECREF(this);
|
||||
Py_INCREF(node);
|
||||
self->this = (ElementObject*) node;
|
||||
self->this = node;
|
||||
|
||||
Py_DECREF(self->last);
|
||||
Py_INCREF(node);
|
||||
self->last = (ElementObject*) node;
|
||||
self->last = node;
|
||||
|
||||
if (self->start_event_obj) {
|
||||
PyObject* res;
|
||||
PyObject* action = self->start_event_obj;
|
||||
res = PyTuple_New(2);
|
||||
res = PyTuple_Pack(2, action, node);
|
||||
if (res) {
|
||||
Py_INCREF(action); PyTuple_SET_ITEM(res, 0, (PyObject*) action);
|
||||
Py_INCREF(node); PyTuple_SET_ITEM(res, 1, (PyObject*) node);
|
||||
PyList_Append(self->events, res);
|
||||
Py_DECREF(res);
|
||||
} else
|
||||
|
@ -2243,7 +2258,7 @@ LOCAL(PyObject*)
|
|||
treebuilder_handle_data(TreeBuilderObject* self, PyObject* data)
|
||||
{
|
||||
if (!self->data) {
|
||||
if (self->last == (ElementObject*) Py_None) {
|
||||
if (self->last == Py_None) {
|
||||
/* ignore calls to data before the first call to start */
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
@ -2253,6 +2268,7 @@ treebuilder_handle_data(TreeBuilderObject* self, PyObject* data)
|
|||
/* more than one item; use a list to collect items */
|
||||
if (PyBytes_CheckExact(self->data) && Py_REFCNT(self->data) == 1 &&
|
||||
PyBytes_CheckExact(data) && PyBytes_GET_SIZE(data) == 1) {
|
||||
/* XXX this code path unused in Python 3? */
|
||||
/* expat often generates single character data sections; handle
|
||||
the most common case by resizing the existing string... */
|
||||
Py_ssize_t size = PyBytes_GET_SIZE(self->data);
|
||||
|
@ -2282,15 +2298,11 @@ treebuilder_handle_end(TreeBuilderObject* self, PyObject* tag)
|
|||
|
||||
if (self->data) {
|
||||
if (self->this == self->last) {
|
||||
Py_DECREF(JOIN_OBJ(self->last->text));
|
||||
self->last->text = JOIN_SET(
|
||||
self->data, PyList_CheckExact(self->data)
|
||||
);
|
||||
if (treebuilder_set_element_text(self->last, self->data))
|
||||
return NULL;
|
||||
} else {
|
||||
Py_DECREF(JOIN_OBJ(self->last->tail));
|
||||
self->last->tail = JOIN_SET(
|
||||
self->data, PyList_CheckExact(self->data)
|
||||
);
|
||||
if (treebuilder_set_element_tail(self->last, self->data))
|
||||
return NULL;
|
||||
}
|
||||
self->data = NULL;
|
||||
}
|
||||
|
@ -2310,17 +2322,15 @@ treebuilder_handle_end(TreeBuilderObject* self, PyObject* tag)
|
|||
|
||||
Py_DECREF(self->last);
|
||||
|
||||
self->last = (ElementObject*) self->this;
|
||||
self->this = (ElementObject*) item;
|
||||
self->last = self->this;
|
||||
self->this = item;
|
||||
|
||||
if (self->end_event_obj) {
|
||||
PyObject* res;
|
||||
PyObject* action = self->end_event_obj;
|
||||
PyObject* node = (PyObject*) self->last;
|
||||
res = PyTuple_New(2);
|
||||
res = PyTuple_Pack(2, action, node);
|
||||
if (res) {
|
||||
Py_INCREF(action); PyTuple_SET_ITEM(res, 0, (PyObject*) action);
|
||||
Py_INCREF(node); PyTuple_SET_ITEM(res, 1, (PyObject*) node);
|
||||
PyList_Append(self->events, res);
|
||||
Py_DECREF(res);
|
||||
} else
|
||||
|
@ -2366,9 +2376,13 @@ treebuilder_handle_namespace(TreeBuilderObject* self, int start,
|
|||
PyTuple_SET_ITEM(res, 1, parcel);
|
||||
PyList_Append(self->events, res);
|
||||
Py_DECREF(res);
|
||||
} else
|
||||
}
|
||||
else {
|
||||
Py_DECREF(action);
|
||||
Py_DECREF(parcel);
|
||||
PyErr_Clear(); /* FIXME: propagate error */
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* methods (in alphabetical order) */
|
||||
|
@ -2526,7 +2540,7 @@ makeuniversal(XMLParserObject* self, const char* string)
|
|||
/* convert a UTF-8 tag/attribute name from the expat parser
|
||||
to a universal name string */
|
||||
|
||||
int size = strlen(string);
|
||||
Py_ssize_t size = (Py_ssize_t) strlen(string);
|
||||
PyObject* key;
|
||||
PyObject* value;
|
||||
|
||||
|
@ -2545,7 +2559,7 @@ makeuniversal(XMLParserObject* self, const char* string)
|
|||
|
||||
PyObject* tag;
|
||||
char* p;
|
||||
int i;
|
||||
Py_ssize_t i;
|
||||
|
||||
/* look for namespace separator */
|
||||
for (i = 0; i < size; i++)
|
||||
|
@ -2717,13 +2731,7 @@ expat_start_handler(XMLParserObject* self, const XML_Char* tag_in,
|
|||
attrib_in += 2;
|
||||
}
|
||||
} else {
|
||||
Py_INCREF(Py_None);
|
||||
attrib = Py_None;
|
||||
}
|
||||
|
||||
/* If we get None, pass an empty dictionary on */
|
||||
if (attrib == Py_None) {
|
||||
Py_DECREF(attrib);
|
||||
/* Pass an empty dictionary on */
|
||||
attrib = PyDict_New();
|
||||
if (!attrib)
|
||||
return;
|
||||
|
@ -3015,14 +3023,14 @@ xmlparser_init(PyObject *self, PyObject *args, PyObject *kwds)
|
|||
|
||||
self_xp->names = PyDict_New();
|
||||
if (!self_xp->names) {
|
||||
Py_XDECREF(self_xp->entity);
|
||||
Py_CLEAR(self_xp->entity);
|
||||
return -1;
|
||||
}
|
||||
|
||||
self_xp->parser = EXPAT(ParserCreate_MM)(encoding, &ExpatMemoryHandler, "}");
|
||||
if (!self_xp->parser) {
|
||||
Py_XDECREF(self_xp->entity);
|
||||
Py_XDECREF(self_xp->names);
|
||||
Py_CLEAR(self_xp->entity);
|
||||
Py_CLEAR(self_xp->names);
|
||||
PyErr_NoMemory();
|
||||
return -1;
|
||||
}
|
||||
|
@ -3032,8 +3040,8 @@ xmlparser_init(PyObject *self, PyObject *args, PyObject *kwds)
|
|||
} else {
|
||||
target = treebuilder_new(&TreeBuilder_Type, NULL, NULL);
|
||||
if (!target) {
|
||||
Py_XDECREF(self_xp->entity);
|
||||
Py_XDECREF(self_xp->names);
|
||||
Py_CLEAR(self_xp->entity);
|
||||
Py_CLEAR(self_xp->names);
|
||||
EXPAT(ParserFree)(self_xp->parser);
|
||||
return -1;
|
||||
}
|
||||
|
@ -3109,17 +3117,17 @@ xmlparser_gc_clear(XMLParserObject *self)
|
|||
{
|
||||
EXPAT(ParserFree)(self->parser);
|
||||
|
||||
Py_XDECREF(self->handle_close);
|
||||
Py_XDECREF(self->handle_pi);
|
||||
Py_XDECREF(self->handle_comment);
|
||||
Py_XDECREF(self->handle_end);
|
||||
Py_XDECREF(self->handle_data);
|
||||
Py_XDECREF(self->handle_start);
|
||||
Py_XDECREF(self->handle_doctype);
|
||||
Py_CLEAR(self->handle_close);
|
||||
Py_CLEAR(self->handle_pi);
|
||||
Py_CLEAR(self->handle_comment);
|
||||
Py_CLEAR(self->handle_end);
|
||||
Py_CLEAR(self->handle_data);
|
||||
Py_CLEAR(self->handle_start);
|
||||
Py_CLEAR(self->handle_doctype);
|
||||
|
||||
Py_XDECREF(self->target);
|
||||
Py_XDECREF(self->entity);
|
||||
Py_XDECREF(self->names);
|
||||
Py_CLEAR(self->target);
|
||||
Py_CLEAR(self->entity);
|
||||
Py_CLEAR(self->names);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -3227,17 +3235,12 @@ xmlparser_parse(XMLParserObject* self, PyObject* args)
|
|||
break;
|
||||
}
|
||||
temp = PyUnicode_AsEncodedString(buffer, "utf-8", "surrogatepass");
|
||||
Py_DECREF(buffer);
|
||||
if (!temp) {
|
||||
/* Propagate exception from PyUnicode_AsEncodedString */
|
||||
Py_DECREF(buffer);
|
||||
Py_DECREF(reader);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Here we no longer need the original buffer since it contains
|
||||
* unicode. Make it point to the encoded bytes object.
|
||||
*/
|
||||
Py_DECREF(buffer);
|
||||
buffer = temp;
|
||||
}
|
||||
else if (!PyBytes_CheckExact(buffer) || PyBytes_GET_SIZE(buffer) == 0) {
|
||||
|
@ -3307,10 +3310,10 @@ xmlparser_setevents(XMLParserObject *self, PyObject* args)
|
|||
target->events = events;
|
||||
|
||||
/* clear out existing events */
|
||||
Py_XDECREF(target->start_event_obj); target->start_event_obj = NULL;
|
||||
Py_XDECREF(target->end_event_obj); target->end_event_obj = NULL;
|
||||
Py_XDECREF(target->start_ns_event_obj); target->start_ns_event_obj = NULL;
|
||||
Py_XDECREF(target->end_ns_event_obj); target->end_ns_event_obj = NULL;
|
||||
Py_CLEAR(target->start_event_obj);
|
||||
Py_CLEAR(target->end_event_obj);
|
||||
Py_CLEAR(target->start_ns_event_obj);
|
||||
Py_CLEAR(target->end_ns_event_obj);
|
||||
|
||||
if (event_set == Py_None) {
|
||||
/* default is "end" only */
|
||||
|
|
|
@ -284,7 +284,8 @@ random_seed(RandomObject *self, PyObject *args)
|
|||
n = newn;
|
||||
if (keyused >= keymax) {
|
||||
unsigned long bigger = keymax << 1;
|
||||
if ((bigger >> 1) != keymax) {
|
||||
if ((bigger >> 1) != keymax ||
|
||||
bigger > PY_SSIZE_T_MAX / sizeof(*key)) {
|
||||
PyErr_NoMemory();
|
||||
goto Done;
|
||||
}
|
||||
|
|
|
@ -1238,7 +1238,7 @@ parse_tuple_and_keywords(PyObject *self, PyObject *args)
|
|||
o = PySequence_Fast_GET_ITEM(sub_keywords, i);
|
||||
if (!PyUnicode_FSConverter(o, (void *)(converted + i))) {
|
||||
PyErr_Format(PyExc_ValueError,
|
||||
"parse_tuple_and_keywords: could not convert keywords[%s] to narrow string", i);
|
||||
"parse_tuple_and_keywords: could not convert keywords[%zd] to narrow string", i);
|
||||
goto exit;
|
||||
}
|
||||
keywords[i] = PyBytes_AS_STRING(converted[i]);
|
||||
|
|
|
@ -483,11 +483,11 @@ newarrayobject(PyTypeObject *type, Py_ssize_t size, struct arraydescr *descr)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
nbytes = size * descr->itemsize;
|
||||
/* Check for overflow */
|
||||
if (nbytes / descr->itemsize != (size_t)size) {
|
||||
if (size > PY_SSIZE_T_MAX / descr->itemsize) {
|
||||
return PyErr_NoMemory();
|
||||
}
|
||||
nbytes = size * descr->itemsize;
|
||||
op = (arrayobject *) type->tp_alloc(type, 0);
|
||||
if (op == NULL) {
|
||||
return NULL;
|
||||
|
@ -1251,11 +1251,15 @@ array_fromfile(arrayobject *self, PyObject *args)
|
|||
if (!PyArg_ParseTuple(args, "On:fromfile", &f, &n))
|
||||
return NULL;
|
||||
|
||||
nbytes = n * itemsize;
|
||||
if (nbytes < 0 || nbytes/itemsize != n) {
|
||||
if (n < 0) {
|
||||
PyErr_SetString(PyExc_ValueError, "negative count");
|
||||
return NULL;
|
||||
}
|
||||
if (n > PY_SSIZE_T_MAX / itemsize) {
|
||||
PyErr_NoMemory();
|
||||
return NULL;
|
||||
}
|
||||
nbytes = n * itemsize;
|
||||
|
||||
b = _PyObject_CallMethodId(f, &PyId_read, "n", nbytes);
|
||||
if (b == NULL)
|
||||
|
|
|
@ -1108,8 +1108,7 @@ audioop_ratecv(PyObject *self, PyObject *args)
|
|||
PyErr_SetString(AudioopError, "# of channels should be >= 1");
|
||||
return NULL;
|
||||
}
|
||||
bytes_per_frame = size * nchannels;
|
||||
if (bytes_per_frame / nchannels != size) {
|
||||
if (size > INT_MAX / nchannels) {
|
||||
/* This overflow test is rigorously correct because
|
||||
both multiplicands are >= 1. Use the argument names
|
||||
from the docs for the error msg. */
|
||||
|
@ -1117,6 +1116,7 @@ audioop_ratecv(PyObject *self, PyObject *args)
|
|||
"width * nchannels too big for a C int");
|
||||
return NULL;
|
||||
}
|
||||
bytes_per_frame = size * nchannels;
|
||||
if (weightA < 1 || weightB < 0) {
|
||||
PyErr_SetString(AudioopError,
|
||||
"weightA should be >= 1, weightB should be >= 0");
|
||||
|
|
|
@ -875,7 +875,12 @@ read_directory(PyObject *archive)
|
|||
PyErr_Format(ZipImportError, "can't open Zip file: %R", archive);
|
||||
return NULL;
|
||||
}
|
||||
fseek(fp, -22, SEEK_END);
|
||||
|
||||
if (fseek(fp, -22, SEEK_END) == -1) {
|
||||
fclose(fp);
|
||||
PyErr_Format(ZipImportError, "can't read Zip file: %R", archive);
|
||||
return NULL;
|
||||
}
|
||||
header_position = ftell(fp);
|
||||
if (fread(endof_central_dir, 1, 22, fp) != 22) {
|
||||
fclose(fp);
|
||||
|
@ -904,11 +909,13 @@ read_directory(PyObject *archive)
|
|||
PyObject *t;
|
||||
int err;
|
||||
|
||||
fseek(fp, header_offset, 0); /* Start of file header */
|
||||
if (fseek(fp, header_offset, 0) == -1) /* Start of file header */
|
||||
goto fseek_error;
|
||||
l = PyMarshal_ReadLongFromFile(fp);
|
||||
if (l != 0x02014B50)
|
||||
break; /* Bad: Central Dir File Header */
|
||||
fseek(fp, header_offset + 8, 0);
|
||||
if (fseek(fp, header_offset + 8, 0) == -1)
|
||||
goto fseek_error;
|
||||
flags = (unsigned short)PyMarshal_ReadShortFromFile(fp);
|
||||
compress = PyMarshal_ReadShortFromFile(fp);
|
||||
time = PyMarshal_ReadShortFromFile(fp);
|
||||
|
@ -920,7 +927,8 @@ read_directory(PyObject *archive)
|
|||
header_size = 46 + name_size +
|
||||
PyMarshal_ReadShortFromFile(fp) +
|
||||
PyMarshal_ReadShortFromFile(fp);
|
||||
fseek(fp, header_offset + 42, 0);
|
||||
if (fseek(fp, header_offset + 42, 0) == -1)
|
||||
goto fseek_error;
|
||||
file_offset = PyMarshal_ReadLongFromFile(fp) + arc_offset;
|
||||
if (name_size > MAXPATHLEN)
|
||||
name_size = MAXPATHLEN;
|
||||
|
@ -980,6 +988,12 @@ read_directory(PyObject *archive)
|
|||
PySys_FormatStderr("# zipimport: found %ld names in %R\n",
|
||||
count, archive);
|
||||
return files;
|
||||
fseek_error:
|
||||
fclose(fp);
|
||||
Py_XDECREF(files);
|
||||
Py_XDECREF(nameobj);
|
||||
PyErr_Format(ZipImportError, "can't read Zip file: %R", archive);
|
||||
return NULL;
|
||||
error:
|
||||
fclose(fp);
|
||||
Py_XDECREF(files);
|
||||
|
@ -1050,7 +1064,12 @@ get_data(PyObject *archive, PyObject *toc_entry)
|
|||
}
|
||||
|
||||
/* Check to make sure the local file header is correct */
|
||||
fseek(fp, file_offset, 0);
|
||||
if (fseek(fp, file_offset, 0) == -1) {
|
||||
fclose(fp);
|
||||
PyErr_Format(ZipImportError, "can't read Zip file: %R", archive);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
l = PyMarshal_ReadLongFromFile(fp);
|
||||
if (l != 0x04034B50) {
|
||||
/* Bad: Local File Header */
|
||||
|
@ -1060,7 +1079,12 @@ get_data(PyObject *archive, PyObject *toc_entry)
|
|||
fclose(fp);
|
||||
return NULL;
|
||||
}
|
||||
fseek(fp, file_offset + 26, 0);
|
||||
if (fseek(fp, file_offset + 26, 0) == -1) {
|
||||
fclose(fp);
|
||||
PyErr_Format(ZipImportError, "can't read Zip file: %R", archive);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
l = 30 + PyMarshal_ReadShortFromFile(fp) +
|
||||
PyMarshal_ReadShortFromFile(fp); /* local header size */
|
||||
file_offset += l; /* Start of file data */
|
||||
|
@ -1077,8 +1101,13 @@ get_data(PyObject *archive, PyObject *toc_entry)
|
|||
buf = PyBytes_AsString(raw_data);
|
||||
|
||||
err = fseek(fp, file_offset, 0);
|
||||
if (err == 0)
|
||||
if (err == 0) {
|
||||
bytes_read = fread(buf, 1, data_size, fp);
|
||||
} else {
|
||||
fclose(fp);
|
||||
PyErr_Format(ZipImportError, "can't read Zip file: %R", archive);
|
||||
return NULL;
|
||||
}
|
||||
fclose(fp);
|
||||
if (err || bytes_read != data_size) {
|
||||
PyErr_SetString(PyExc_IOError,
|
||||
|
|
|
@ -668,10 +668,9 @@ _PyLong_NumBits(PyObject *vv)
|
|||
assert(ndigits == 0 || v->ob_digit[ndigits - 1] != 0);
|
||||
if (ndigits > 0) {
|
||||
digit msd = v->ob_digit[ndigits - 1];
|
||||
|
||||
result = (ndigits - 1) * PyLong_SHIFT;
|
||||
if (result / PyLong_SHIFT != (size_t)(ndigits - 1))
|
||||
if ((size_t)(ndigits - 1) > PY_SIZE_MAX / (size_t)PyLong_SHIFT)
|
||||
goto Overflow;
|
||||
result = (size_t)(ndigits - 1) * (size_t)PyLong_SHIFT;
|
||||
do {
|
||||
++result;
|
||||
if (result == 0)
|
||||
|
@ -4849,13 +4848,20 @@ static PyGetSetDef long_getset[] = {
|
|||
};
|
||||
|
||||
PyDoc_STRVAR(long_doc,
|
||||
"int(x[, base]) -> integer\n\
|
||||
"int(x=0) -> integer\n\
|
||||
int(x, base=10) -> integer\n\
|
||||
\n\
|
||||
Convert a string or number to an integer, if possible. A floating\n\
|
||||
point argument will be truncated towards zero (this does not include a\n\
|
||||
string representation of a floating point number!) When converting a\n\
|
||||
string, use the optional base. It is an error to supply a base when\n\
|
||||
converting a non-string.");
|
||||
Convert a number or string to an integer, or return 0 if no arguments\n\
|
||||
are given. If x is a number, return x.__int__(). For floating point\n\
|
||||
numbers, this truncates towards zero.\n\
|
||||
\n\
|
||||
If x is not a number or if base is given, then x must be a string,\n\
|
||||
bytes, or bytearray instance representing an integer literal in the\n\
|
||||
given base. The literal can be preceded by '+' or '-' and be surrounded\n\
|
||||
by whitespace. The base defaults to 10. Valid bases are 0 and 2-36.\n\
|
||||
Base 0 means to interpret the base from the string as an integer literal.\n\
|
||||
>>> int('0b100', base=0)\n\
|
||||
4");
|
||||
|
||||
static PyNumberMethods long_as_number = {
|
||||
(binaryfunc)long_add, /*nb_add*/
|
||||
|
|
|
@ -136,7 +136,8 @@ range_new(PyTypeObject *type, PyObject *args, PyObject *kw)
|
|||
}
|
||||
|
||||
PyDoc_STRVAR(range_doc,
|
||||
"range([start,] stop[, step]) -> range object\n\
|
||||
"range(stop) -> range object\n\
|
||||
range(start, stop[, step]) -> range object\n\
|
||||
\n\
|
||||
Returns a virtual sequence of numbers from start to stop by step.");
|
||||
|
||||
|
|
|
@ -269,7 +269,8 @@ slice_new(PyTypeObject *type, PyObject *args, PyObject *kw)
|
|||
}
|
||||
|
||||
PyDoc_STRVAR(slice_doc,
|
||||
"slice([start,] stop[, step])\n\
|
||||
"slice(stop)\n\
|
||||
slice(start, stop[, step])\n\
|
||||
\n\
|
||||
Create a slice object. This is used for extended slicing (e.g. a[0:10:2]).");
|
||||
|
||||
|
|
|
@ -96,15 +96,11 @@ PyTuple_New(register Py_ssize_t size)
|
|||
else
|
||||
#endif
|
||||
{
|
||||
Py_ssize_t nbytes = size * sizeof(PyObject *);
|
||||
/* Check for overflow */
|
||||
if (nbytes / sizeof(PyObject *) != (size_t)size ||
|
||||
(nbytes > PY_SSIZE_T_MAX - sizeof(PyTupleObject) - sizeof(PyObject *)))
|
||||
{
|
||||
if (size > (PY_SSIZE_T_MAX - sizeof(PyTupleObject) -
|
||||
sizeof(PyObject *)) / sizeof(PyObject *)) {
|
||||
return PyErr_NoMemory();
|
||||
}
|
||||
/* nbytes += sizeof(PyTupleObject) - sizeof(PyObject *); */
|
||||
|
||||
op = PyObject_GC_NewVar(PyTupleObject, &PyTuple_Type, size);
|
||||
if (op == NULL)
|
||||
return NULL;
|
||||
|
@ -481,9 +477,9 @@ tuplerepeat(PyTupleObject *a, Py_ssize_t n)
|
|||
if (Py_SIZE(a) == 0)
|
||||
return PyTuple_New(0);
|
||||
}
|
||||
size = Py_SIZE(a) * n;
|
||||
if (size/Py_SIZE(a) != n)
|
||||
if (n > PY_SSIZE_T_MAX / Py_SIZE(a))
|
||||
return PyErr_NoMemory();
|
||||
size = Py_SIZE(a) * n;
|
||||
np = (PyTupleObject *) PyTuple_New(size);
|
||||
if (np == NULL)
|
||||
return NULL;
|
||||
|
|
|
@ -4492,7 +4492,6 @@ _PyUnicode_EncodeUTF7(PyObject *str,
|
|||
void *data;
|
||||
Py_ssize_t len;
|
||||
PyObject *v;
|
||||
Py_ssize_t allocated;
|
||||
int inShift = 0;
|
||||
Py_ssize_t i;
|
||||
unsigned int base64bits = 0;
|
||||
|
@ -4510,11 +4509,9 @@ _PyUnicode_EncodeUTF7(PyObject *str,
|
|||
return PyBytes_FromStringAndSize(NULL, 0);
|
||||
|
||||
/* It might be possible to tighten this worst case */
|
||||
allocated = 8 * len;
|
||||
if (allocated / 8 != len)
|
||||
if (len > PY_SSIZE_T_MAX / 8)
|
||||
return PyErr_NoMemory();
|
||||
|
||||
v = PyBytes_FromStringAndSize(NULL, allocated);
|
||||
v = PyBytes_FromStringAndSize(NULL, len * 8);
|
||||
if (v == NULL)
|
||||
return NULL;
|
||||
|
||||
|
@ -5092,7 +5089,7 @@ _PyUnicode_EncodeUTF32(PyObject *str,
|
|||
Py_ssize_t len;
|
||||
PyObject *v;
|
||||
unsigned char *p;
|
||||
Py_ssize_t nsize, bytesize, i;
|
||||
Py_ssize_t nsize, i;
|
||||
/* Offsets from p for storing byte pairs in the right order. */
|
||||
#ifdef BYTEORDER_IS_LITTLE_ENDIAN
|
||||
int iorder[] = {0, 1, 2, 3};
|
||||
|
@ -5120,10 +5117,9 @@ _PyUnicode_EncodeUTF32(PyObject *str,
|
|||
len = PyUnicode_GET_LENGTH(str);
|
||||
|
||||
nsize = len + (byteorder == 0);
|
||||
bytesize = nsize * 4;
|
||||
if (bytesize / 4 != nsize)
|
||||
if (nsize > PY_SSIZE_T_MAX / 4)
|
||||
return PyErr_NoMemory();
|
||||
v = PyBytes_FromStringAndSize(NULL, bytesize);
|
||||
v = PyBytes_FromStringAndSize(NULL, nsize * 4);
|
||||
if (v == NULL)
|
||||
return NULL;
|
||||
|
||||
|
@ -5772,18 +5768,12 @@ PyUnicode_AsUnicodeEscapeString(PyObject *unicode)
|
|||
void *data;
|
||||
Py_ssize_t expandsize = 0;
|
||||
|
||||
/* Initial allocation is based on the longest-possible unichr
|
||||
/* Initial allocation is based on the longest-possible character
|
||||
escape.
|
||||
|
||||
In wide (UTF-32) builds '\U00xxxxxx' is 10 chars per source
|
||||
unichr, so in this case it's the longest unichr escape. In
|
||||
narrow (UTF-16) builds this is five chars per source unichr
|
||||
since there are two unichrs in the surrogate pair, so in narrow
|
||||
(UTF-16) builds it's not the longest unichr escape.
|
||||
|
||||
In wide or narrow builds '\uxxxx' is 6 chars per source unichr,
|
||||
so in the narrow (UTF-16) build case it's the longest unichr
|
||||
escape.
|
||||
For UCS1 strings it's '\xxx', 4 bytes per source character.
|
||||
For UCS2 strings it's '\uxxxx', 6 bytes per source character.
|
||||
For UCS4 strings it's '\U00xxxxxx', 10 bytes per source character.
|
||||
*/
|
||||
|
||||
if (!PyUnicode_Check(unicode)) {
|
||||
|
@ -10165,7 +10155,7 @@ replace(PyObject *self, PyObject *str1,
|
|||
}
|
||||
else {
|
||||
Py_ssize_t n, i, j, ires;
|
||||
Py_ssize_t product, new_size;
|
||||
Py_ssize_t new_size;
|
||||
int rkind = skind;
|
||||
char *res;
|
||||
|
||||
|
@ -10197,19 +10187,18 @@ replace(PyObject *self, PyObject *str1,
|
|||
}
|
||||
/* new_size = PyUnicode_GET_LENGTH(self) + n * (PyUnicode_GET_LENGTH(str2) -
|
||||
PyUnicode_GET_LENGTH(str1))); */
|
||||
product = n * (len2-len1);
|
||||
if ((product / (len2-len1)) != n) {
|
||||
if (len2 > len1 && len2 - len1 > (PY_SSIZE_T_MAX - slen) / n) {
|
||||
PyErr_SetString(PyExc_OverflowError,
|
||||
"replace string is too long");
|
||||
goto error;
|
||||
}
|
||||
new_size = slen + product;
|
||||
new_size = slen + n * (len2 - len1);
|
||||
if (new_size == 0) {
|
||||
Py_INCREF(unicode_empty);
|
||||
u = unicode_empty;
|
||||
goto done;
|
||||
}
|
||||
if (new_size < 0 || new_size > (PY_SSIZE_T_MAX >> (rkind-1))) {
|
||||
if (new_size > (PY_SSIZE_T_MAX >> (rkind-1))) {
|
||||
PyErr_SetString(PyExc_OverflowError,
|
||||
"replace string is too long");
|
||||
goto error;
|
||||
|
@ -13442,8 +13431,10 @@ PyUnicode_Format(PyObject *format, PyObject *args)
|
|||
uformat = PyUnicode_FromObject(format);
|
||||
if (uformat == NULL)
|
||||
return NULL;
|
||||
if (PyUnicode_READY(uformat) == -1)
|
||||
if (PyUnicode_READY(uformat) == -1) {
|
||||
Py_DECREF(uformat);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fmt = PyUnicode_DATA(uformat);
|
||||
fmtkind = PyUnicode_KIND(uformat);
|
||||
|
@ -14083,7 +14074,8 @@ onError:
|
|||
}
|
||||
|
||||
PyDoc_STRVAR(unicode_doc,
|
||||
"str(object[, encoding[, errors]]) -> str\n\
|
||||
"str(object='') -> str\n\
|
||||
str(bytes_or_buffer[, encoding[, errors]]) -> str\n\
|
||||
\n\
|
||||
Create a new string object from the given object. If encoding or\n\
|
||||
errors is specified, then the object must expose a data buffer\n\
|
||||
|
|
|
@ -1064,7 +1064,7 @@ class ObjVisitor(PickleVisitor):
|
|||
self.emit("case %s:" % t.name, 2)
|
||||
self.emit("Py_INCREF(%s_singleton);" % t.name, 3)
|
||||
self.emit("return %s_singleton;" % t.name, 3)
|
||||
self.emit("default:" % name, 2)
|
||||
self.emit("default:", 2)
|
||||
self.emit('/* should never happen, but just in case ... */', 3)
|
||||
code = "PyErr_Format(PyExc_SystemError, \"unknown %s found\");" % name
|
||||
self.emit(code, 3, reflow=False)
|
||||
|
|
Loading…
Reference in New Issue