mirror of
https://github.com/python/cpython.git
synced 2025-08-04 00:48:58 +00:00
Merged revisions 62350-62355,62358-62359,62364-62365,62370,62372-62375,62378-62379,62381 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk ........ r62350 | nick.coghlan | 2008-04-15 12:25:31 +0200 (Tue, 15 Apr 2008) | 1 line Issue 2439: add pkgutils.get_data() as a convenience wrapper for the PEP 302 get_data() API (contributed by Paul Moore) ........ r62351 | nick.coghlan | 2008-04-15 12:28:14 +0200 (Tue, 15 Apr 2008) | 1 line Add test file missing from rev 62350 ........ r62352 | benjamin.peterson | 2008-04-15 13:58:46 +0200 (Tue, 15 Apr 2008) | 2 lines Add myself to Doc/ACKS.txt ........ r62353 | andrew.kuchling | 2008-04-15 15:10:07 +0200 (Tue, 15 Apr 2008) | 6 lines Add *,**,@ to index, as suggested by http://farmdev.com/thoughts/24/what-does-the-def-star-variable-or-def-asterisk-parameter-syntax-do-in-python-/ The right entry type to use isn't clear; operator seems wrong, because *,**,@ aren't being used in expressions here. I put them as 'statement'; 'syntax' might be better. ........ r62354 | andrew.kuchling | 2008-04-15 15:10:41 +0200 (Tue, 15 Apr 2008) | 1 line Typo fix ........ r62355 | mark.dickinson | 2008-04-15 22:51:18 +0200 (Tue, 15 Apr 2008) | 3 lines Fix for possible signed overflow: the behaviour of -LONG_MIN is undefined in ANSI C. ........ r62358 | jeroen.ruigrok | 2008-04-16 14:47:01 +0200 (Wed, 16 Apr 2008) | 2 lines Reformat to 80 columns prior to adding documentation. ........ r62359 | jeroen.ruigrok | 2008-04-16 14:57:43 +0200 (Wed, 16 Apr 2008) | 2 lines Add details about the return value for mmap.flush(). ........ r62364 | raymond.hettinger | 2008-04-17 12:48:31 +0200 (Thu, 17 Apr 2008) | 1 line Issue 2648: Add leading zero to money format recipe in the docs. ........ r62365 | jeroen.ruigrok | 2008-04-17 14:39:45 +0200 (Thu, 17 Apr 2008) | 2 lines Be consistent in the use of read-only. ........ r62370 | andrew.kuchling | 2008-04-17 22:44:06 +0200 (Thu, 17 Apr 2008) | 1 line Typo fixes ........ r62372 | andrew.kuchling | 2008-04-18 04:40:47 +0200 (Fri, 18 Apr 2008) | 1 line Use correct parameter name ........ r62373 | andrew.kuchling | 2008-04-18 18:53:09 +0200 (Fri, 18 Apr 2008) | 1 line #2654: fix typo ........ r62374 | andrew.kuchling | 2008-04-18 20:28:23 +0200 (Fri, 18 Apr 2008) | 4 lines Remove personal note from Jim Roskind; it no longer applies, and the e-mail address is for a previous employer. Can we move the big long copyright statement into a sidebar or something? ........ r62375 | andrew.kuchling | 2008-04-18 20:39:55 +0200 (Fri, 18 Apr 2008) | 1 line Rewrite introductory section, and remove old section. (It was already commented-out, but why keep it?) ........ r62378 | skip.montanaro | 2008-04-18 22:35:46 +0200 (Fri, 18 Apr 2008) | 1 line resolve issue 2014 ........ r62379 | benjamin.peterson | 2008-04-18 22:45:33 +0200 (Fri, 18 Apr 2008) | 2 lines Fix indentation in sysmodule.c ........ r62381 | amaury.forgeotdarc | 2008-04-19 01:31:33 +0200 (Sat, 19 Apr 2008) | 3 lines Some tests did not pass on repeated calls (regrtest -R::) Perform additional cleanup, mostly deleting from sys.modules, or clearing the warnings registry. ........
This commit is contained in:
parent
53876d9cd8
commit
dae2a8939d
22 changed files with 412 additions and 189 deletions
|
@ -145,6 +145,7 @@ docs@python.org), and we'll be glad to correct the problem.
|
||||||
* Harri Pasanen
|
* Harri Pasanen
|
||||||
* Bo Peng
|
* Bo Peng
|
||||||
* Tim Peters
|
* Tim Peters
|
||||||
|
* Benjamin Peterson
|
||||||
* Christopher Petrilli
|
* Christopher Petrilli
|
||||||
* Justin D. Pettit
|
* Justin D. Pettit
|
||||||
* Chris Phoenix
|
* Chris Phoenix
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
:Author: Moshe Zadka
|
:Author: Moshe Zadka
|
||||||
|
|
||||||
This document is placed in the public doman.
|
This document is placed in the public domain.
|
||||||
|
|
||||||
|
|
||||||
.. topic:: Abstract
|
.. topic:: Abstract
|
||||||
|
|
|
@ -1374,7 +1374,7 @@ to work with the :class:`Decimal` class::
|
||||||
>>> moneyfmt(Decimal(123456789), sep=' ')
|
>>> moneyfmt(Decimal(123456789), sep=' ')
|
||||||
'123 456 789.00'
|
'123 456 789.00'
|
||||||
>>> moneyfmt(Decimal('-0.02'), neg='<', trailneg='>')
|
>>> moneyfmt(Decimal('-0.02'), neg='<', trailneg='>')
|
||||||
'<.02>'
|
'<0.02>'
|
||||||
|
|
||||||
"""
|
"""
|
||||||
q = Decimal(10) ** -places # 2 places --> '0.01'
|
q = Decimal(10) ** -places # 2 places --> '0.01'
|
||||||
|
@ -1387,6 +1387,8 @@ to work with the :class:`Decimal` class::
|
||||||
for i in range(places):
|
for i in range(places):
|
||||||
build(next() if digits else '0')
|
build(next() if digits else '0')
|
||||||
build(dp)
|
build(dp)
|
||||||
|
if not digits:
|
||||||
|
build('0')
|
||||||
i = 0
|
i = 0
|
||||||
while digits:
|
while digits:
|
||||||
build(next())
|
build(next())
|
||||||
|
|
|
@ -96,7 +96,7 @@ loops that truncate the stream.
|
||||||
|
|
||||||
.. function:: combinations(iterable, r)
|
.. function:: combinations(iterable, r)
|
||||||
|
|
||||||
Return successive *r* length combinations of elements in the *iterable*.
|
Return *r* length subsequences of elements from the input *iterable*.
|
||||||
|
|
||||||
Combinations are emitted in lexicographic sort order. So, if the
|
Combinations are emitted in lexicographic sort order. So, if the
|
||||||
input *iterable* is sorted, the combination tuples will be produced
|
input *iterable* is sorted, the combination tuples will be produced
|
||||||
|
@ -106,9 +106,6 @@ loops that truncate the stream.
|
||||||
value. So if the input elements are unique, there will be no repeat
|
value. So if the input elements are unique, there will be no repeat
|
||||||
values in each combination.
|
values in each combination.
|
||||||
|
|
||||||
Each result tuple is ordered to match the input order. So, every
|
|
||||||
combination is a subsequence of the input *iterable*.
|
|
||||||
|
|
||||||
Equivalent to::
|
Equivalent to::
|
||||||
|
|
||||||
def combinations(iterable, r):
|
def combinations(iterable, r):
|
||||||
|
@ -375,11 +372,10 @@ loops that truncate the stream.
|
||||||
Equivalent to nested for-loops in a generator expression. For example,
|
Equivalent to nested for-loops in a generator expression. For example,
|
||||||
``product(A, B)`` returns the same as ``((x,y) for x in A for y in B)``.
|
``product(A, B)`` returns the same as ``((x,y) for x in A for y in B)``.
|
||||||
|
|
||||||
The leftmost iterators correspond to the outermost for-loop, so the output
|
The nested loops cycle like an odometer with the rightmost element advancing
|
||||||
tuples cycle like an odometer (with the rightmost element changing on every
|
on every iteration. This pattern creates a lexicographic ordering so that if
|
||||||
iteration). This results in a lexicographic ordering so that if the
|
the input's iterables are sorted, the product tuples are emitted in sorted
|
||||||
inputs iterables are sorted, the product tuples are emitted
|
order.
|
||||||
in sorted order.
|
|
||||||
|
|
||||||
To compute the product of an iterable with itself, specify the number of
|
To compute the product of an iterable with itself, specify the number of
|
||||||
repetitions with the optional *repeat* keyword argument. For example,
|
repetitions with the optional *repeat* keyword argument. For example,
|
||||||
|
|
|
@ -8,54 +8,55 @@
|
||||||
|
|
||||||
Memory-mapped file objects behave like both strings and like file objects.
|
Memory-mapped file objects behave like both strings and like file objects.
|
||||||
Unlike normal string objects, however, these are mutable. You can use mmap
|
Unlike normal string objects, however, these are mutable. You can use mmap
|
||||||
objects in most places where strings are expected; for example, you can use the
|
objects in most places where strings are expected; for example, you can use
|
||||||
:mod:`re` module to search through a memory-mapped file. Since they're mutable,
|
the :mod:`re` module to search through a memory-mapped file. Since they're
|
||||||
you can change a single character by doing ``obj[index] = 'a'``, or change a
|
mutable, you can change a single character by doing ``obj[index] = 'a'``, or
|
||||||
substring by assigning to a slice: ``obj[i1:i2] = '...'``. You can also read
|
change a substring by assigning to a slice: ``obj[i1:i2] = '...'``. You can
|
||||||
and write data starting at the current file position, and :meth:`seek` through
|
also read and write data starting at the current file position, and
|
||||||
the file to different positions.
|
:meth:`seek` through the file to different positions.
|
||||||
|
|
||||||
A memory-mapped file is created by the :class:`mmap` constructor, which is different
|
A memory-mapped file is created by the :class:`mmap` constructor, which is
|
||||||
on Unix and on Windows. In either case you must provide a file descriptor for a
|
different on Unix and on Windows. In either case you must provide a file
|
||||||
file opened for update. If you wish to map an existing Python file object, use
|
descriptor for a file opened for update. If you wish to map an existing Python
|
||||||
its :meth:`fileno` method to obtain the correct value for the *fileno*
|
file object, use its :meth:`fileno` method to obtain the correct value for the
|
||||||
parameter. Otherwise, you can open the file using the :func:`os.open` function,
|
*fileno* parameter. Otherwise, you can open the file using the
|
||||||
which returns a file descriptor directly (the file still needs to be closed when
|
:func:`os.open` function, which returns a file descriptor directly (the file
|
||||||
done).
|
still needs to be closed when done).
|
||||||
|
|
||||||
For both the Unix and Windows versions of the constructor, *access* may be
|
For both the Unix and Windows versions of the constructor, *access* may be
|
||||||
specified as an optional keyword parameter. *access* accepts one of three
|
specified as an optional keyword parameter. *access* accepts one of three
|
||||||
values: :const:`ACCESS_READ`, :const:`ACCESS_WRITE`, or :const:`ACCESS_COPY` to
|
values: :const:`ACCESS_READ`, :const:`ACCESS_WRITE`, or :const:`ACCESS_COPY`
|
||||||
specify readonly, write-through or copy-on-write memory respectively. *access*
|
to specify read-only, write-through or copy-on-write memory respectively.
|
||||||
can be used on both Unix and Windows. If *access* is not specified, Windows
|
*access* can be used on both Unix and Windows. If *access* is not specified,
|
||||||
mmap returns a write-through mapping. The initial memory values for all three
|
Windows mmap returns a write-through mapping. The initial memory values for
|
||||||
access types are taken from the specified file. Assignment to an
|
all three access types are taken from the specified file. Assignment to an
|
||||||
:const:`ACCESS_READ` memory map raises a :exc:`TypeError` exception. Assignment
|
:const:`ACCESS_READ` memory map raises a :exc:`TypeError` exception.
|
||||||
to an :const:`ACCESS_WRITE` memory map affects both memory and the underlying
|
Assignment to an :const:`ACCESS_WRITE` memory map affects both memory and the
|
||||||
file. Assignment to an :const:`ACCESS_COPY` memory map affects memory but does
|
underlying file. Assignment to an :const:`ACCESS_COPY` memory map affects
|
||||||
not update the underlying file.
|
memory but does not update the underlying file.
|
||||||
|
|
||||||
To map anonymous memory, -1 should be passed as the fileno along with the length.
|
To map anonymous memory, -1 should be passed as the fileno along with the length.
|
||||||
|
|
||||||
.. class:: mmap(fileno, length[, tagname[, access[, offset]]])
|
.. class:: mmap(fileno, length[, tagname[, access[, offset]]])
|
||||||
|
|
||||||
**(Windows version)** Maps *length* bytes from the file specified by the file
|
**(Windows version)** Maps *length* bytes from the file specified by the
|
||||||
handle *fileno*, and creates a mmap object. If *length* is larger than the
|
file handle *fileno*, and creates a mmap object. If *length* is larger
|
||||||
current size of the file, the file is extended to contain *length* bytes. If
|
than the current size of the file, the file is extended to contain *length*
|
||||||
*length* is ``0``, the maximum length of the map is the current size of the
|
bytes. If *length* is ``0``, the maximum length of the map is the current
|
||||||
file, except that if the file is empty Windows raises an exception (you cannot
|
size of the file, except that if the file is empty Windows raises an
|
||||||
create an empty mapping on Windows).
|
exception (you cannot create an empty mapping on Windows).
|
||||||
|
|
||||||
*tagname*, if specified and not ``None``, is a string giving a tag name for the
|
*tagname*, if specified and not ``None``, is a string giving a tag name for
|
||||||
mapping. Windows allows you to have many different mappings against the same
|
the mapping. Windows allows you to have many different mappings against
|
||||||
file. If you specify the name of an existing tag, that tag is opened, otherwise
|
the same file. If you specify the name of an existing tag, that tag is
|
||||||
a new tag of this name is created. If this parameter is omitted or ``None``,
|
opened, otherwise a new tag of this name is created. If this parameter is
|
||||||
the mapping is created without a name. Avoiding the use of the tag parameter
|
omitted or ``None``, the mapping is created without a name. Avoiding the
|
||||||
will assist in keeping your code portable between Unix and Windows.
|
use of the tag parameter will assist in keeping your code portable between
|
||||||
|
Unix and Windows.
|
||||||
|
|
||||||
*offset* may be specified as a non-negative integer offset. mmap references will
|
*offset* may be specified as a non-negative integer offset. mmap references
|
||||||
be relative to the offset from the beginning of the file. *offset* defaults to 0.
|
will be relative to the offset from the beginning of the file. *offset*
|
||||||
*offset* must be a multiple of the ALLOCATIONGRANULARITY.
|
defaults to 0. *offset* must be a multiple of the ALLOCATIONGRANULARITY.
|
||||||
|
|
||||||
|
|
||||||
.. class:: mmap(fileno, length[, flags[, prot[, access[, offset]]]])
|
.. class:: mmap(fileno, length[, flags[, prot[, access[, offset]]]])
|
||||||
|
@ -63,26 +64,29 @@ To map anonymous memory, -1 should be passed as the fileno along with the length
|
||||||
|
|
||||||
**(Unix version)** Maps *length* bytes from the file specified by the file
|
**(Unix version)** Maps *length* bytes from the file specified by the file
|
||||||
descriptor *fileno*, and returns a mmap object. If *length* is ``0``, the
|
descriptor *fileno*, and returns a mmap object. If *length* is ``0``, the
|
||||||
maximum length of the map will be the current size of the file when :class:`mmap`
|
maximum length of the map will be the current size of the file when
|
||||||
is called.
|
:class:`mmap` is called.
|
||||||
|
|
||||||
*flags* specifies the nature of the mapping. :const:`MAP_PRIVATE` creates a
|
*flags* specifies the nature of the mapping. :const:`MAP_PRIVATE` creates a
|
||||||
private copy-on-write mapping, so changes to the contents of the mmap object
|
private copy-on-write mapping, so changes to the contents of the mmap
|
||||||
will be private to this process, and :const:`MAP_SHARED` creates a mapping
|
object will be private to this process, and :const:`MAP_SHARED` creates a
|
||||||
that's shared with all other processes mapping the same areas of the file. The
|
mapping that's shared with all other processes mapping the same areas of
|
||||||
default value is :const:`MAP_SHARED`.
|
the file. The default value is :const:`MAP_SHARED`.
|
||||||
|
|
||||||
*prot*, if specified, gives the desired memory protection; the two most useful
|
*prot*, if specified, gives the desired memory protection; the two most
|
||||||
values are :const:`PROT_READ` and :const:`PROT_WRITE`, to specify that the pages
|
useful values are :const:`PROT_READ` and :const:`PROT_WRITE`, to specify
|
||||||
may be read or written. *prot* defaults to :const:`PROT_READ \| PROT_WRITE`.
|
that the pages may be read or written. *prot* defaults to
|
||||||
|
:const:`PROT_READ \| PROT_WRITE`.
|
||||||
|
|
||||||
*access* may be specified in lieu of *flags* and *prot* as an optional keyword
|
*access* may be specified in lieu of *flags* and *prot* as an optional
|
||||||
parameter. It is an error to specify both *flags*, *prot* and *access*. See
|
keyword parameter. It is an error to specify both *flags*, *prot* and
|
||||||
the description of *access* above for information on how to use this parameter.
|
*access*. See the description of *access* above for information on how to
|
||||||
|
use this parameter.
|
||||||
|
|
||||||
*offset* may be specified as a non-negative integer offset. mmap references will
|
*offset* may be specified as a non-negative integer offset. mmap references
|
||||||
be relative to the offset from the beginning of the file. *offset* defaults to 0.
|
will be relative to the offset from the beginning of the file. *offset*
|
||||||
*offset* must be a multiple of the PAGESIZE or ALLOCATIONGRANULARITY.
|
defaults to 0. *offset* must be a multiple of the PAGESIZE or
|
||||||
|
ALLOCATIONGRANULARITY.
|
||||||
|
|
||||||
This example shows a simple way of using :class:`mmap`::
|
This example shows a simple way of using :class:`mmap`::
|
||||||
|
|
||||||
|
@ -132,32 +136,38 @@ Memory-mapped file objects support the following methods:
|
||||||
|
|
||||||
.. method:: mmap.close()
|
.. method:: mmap.close()
|
||||||
|
|
||||||
Close the file. Subsequent calls to other methods of the object will result in
|
Close the file. Subsequent calls to other methods of the object will
|
||||||
an exception being raised.
|
result in an exception being raised.
|
||||||
|
|
||||||
|
|
||||||
.. method:: mmap.find(string[, start[, end]])
|
.. method:: mmap.find(string[, start[, end]])
|
||||||
|
|
||||||
Returns the lowest index in the object where the substring *string* is found,
|
Returns the lowest index in the object where the substring *string* is
|
||||||
such that *string* is contained in the range [*start*, *end*]. Optional
|
found, such that *string* is contained in the range [*start*, *end*].
|
||||||
arguments *start* and *end* are interpreted as in slice notation.
|
Optional arguments *start* and *end* are interpreted as in slice notation.
|
||||||
Returns ``-1`` on failure.
|
Returns ``-1`` on failure.
|
||||||
|
|
||||||
|
|
||||||
.. method:: mmap.flush([offset, size])
|
.. method:: mmap.flush([offset, size])
|
||||||
|
|
||||||
Flushes changes made to the in-memory copy of a file back to disk. Without use
|
Flushes changes made to the in-memory copy of a file back to disk. Without
|
||||||
of this call there is no guarantee that changes are written back before the
|
use of this call there is no guarantee that changes are written back before
|
||||||
object is destroyed. If *offset* and *size* are specified, only changes to the
|
the object is destroyed. If *offset* and *size* are specified, only
|
||||||
given range of bytes will be flushed to disk; otherwise, the whole extent of the
|
changes to the given range of bytes will be flushed to disk; otherwise, the
|
||||||
mapping is flushed.
|
whole extent of the mapping is flushed.
|
||||||
|
|
||||||
|
**(Windows version)** A nonzero value returned indicates success; zero
|
||||||
|
indicates failure.
|
||||||
|
|
||||||
|
**(Unix version)** A zero value is returned to indicate success. An
|
||||||
|
exception is raised when the call failed.
|
||||||
|
|
||||||
|
|
||||||
.. method:: mmap.move(dest, src, count)
|
.. method:: mmap.move(dest, src, count)
|
||||||
|
|
||||||
Copy the *count* bytes starting at offset *src* to the destination index *dest*.
|
Copy the *count* bytes starting at offset *src* to the destination index
|
||||||
If the mmap was created with :const:`ACCESS_READ`, then calls to move will throw
|
*dest*. If the mmap was created with :const:`ACCESS_READ`, then calls to
|
||||||
a :exc:`TypeError` exception.
|
move will throw a :exc:`TypeError` exception.
|
||||||
|
|
||||||
|
|
||||||
.. method:: mmap.read(num)
|
.. method:: mmap.read(num)
|
||||||
|
@ -175,31 +185,31 @@ Memory-mapped file objects support the following methods:
|
||||||
|
|
||||||
.. method:: mmap.readline()
|
.. method:: mmap.readline()
|
||||||
|
|
||||||
Returns a single line, starting at the current file position and up to the next
|
Returns a single line, starting at the current file position and up to the
|
||||||
newline.
|
next newline.
|
||||||
|
|
||||||
|
|
||||||
.. method:: mmap.resize(newsize)
|
.. method:: mmap.resize(newsize)
|
||||||
|
|
||||||
Resizes the map and the underlying file, if any. If the mmap was created with
|
Resizes the map and the underlying file, if any. If the mmap was created
|
||||||
:const:`ACCESS_READ` or :const:`ACCESS_COPY`, resizing the map will throw a
|
with :const:`ACCESS_READ` or :const:`ACCESS_COPY`, resizing the map will
|
||||||
:exc:`TypeError` exception.
|
throw a :exc:`TypeError` exception.
|
||||||
|
|
||||||
|
|
||||||
.. method:: mmap.rfind(string[, start[, end]])
|
.. method:: mmap.rfind(string[, start[, end]])
|
||||||
|
|
||||||
Returns the highest index in the object where the substring *string* is
|
Returns the highest index in the object where the substring *string* is
|
||||||
found, such that *string* is contained in the range [*start*,
|
found, such that *string* is contained in the range [*start*, *end*].
|
||||||
*end*]. Optional arguments *start* and *end* are interpreted as in slice
|
Optional arguments *start* and *end* are interpreted as in slice notation.
|
||||||
notation. Returns ``-1`` on failure.
|
Returns ``-1`` on failure.
|
||||||
|
|
||||||
|
|
||||||
.. method:: mmap.seek(pos[, whence])
|
.. method:: mmap.seek(pos[, whence])
|
||||||
|
|
||||||
Set the file's current position. *whence* argument is optional and defaults to
|
Set the file's current position. *whence* argument is optional and
|
||||||
``os.SEEK_SET`` or ``0`` (absolute file positioning); other values are
|
defaults to ``os.SEEK_SET`` or ``0`` (absolute file positioning); other
|
||||||
``os.SEEK_CUR`` or ``1`` (seek relative to the current position) and
|
values are ``os.SEEK_CUR`` or ``1`` (seek relative to the current position)
|
||||||
``os.SEEK_END`` or ``2`` (seek relative to the file's end).
|
and ``os.SEEK_END`` or ``2`` (seek relative to the file's end).
|
||||||
|
|
||||||
|
|
||||||
.. method:: mmap.size()
|
.. method:: mmap.size()
|
||||||
|
@ -217,15 +227,15 @@ Memory-mapped file objects support the following methods:
|
||||||
|
|
||||||
Write the bytes in *string* into memory at the current position of the file
|
Write the bytes in *string* into memory at the current position of the file
|
||||||
pointer; the file position is updated to point after the bytes that were
|
pointer; the file position is updated to point after the bytes that were
|
||||||
written. If the mmap was created with :const:`ACCESS_READ`, then writing to it
|
written. If the mmap was created with :const:`ACCESS_READ`, then writing to
|
||||||
will throw a :exc:`TypeError` exception.
|
it will throw a :exc:`TypeError` exception.
|
||||||
|
|
||||||
|
|
||||||
.. method:: mmap.write_byte(byte)
|
.. method:: mmap.write_byte(byte)
|
||||||
|
|
||||||
Write the single-character string *byte* into memory at the current position of
|
Write the single-character string *byte* into memory at the current
|
||||||
the file pointer; the file position is advanced by ``1``. If the mmap was
|
position of the file pointer; the file position is advanced by ``1``. If
|
||||||
created with :const:`ACCESS_READ`, then writing to it will throw a
|
the mmap was created with :const:`ACCESS_READ`, then writing to it will
|
||||||
:exc:`TypeError` exception.
|
throw a :exc:`TypeError` exception.
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
:synopsis: Utilities to support extension of packages.
|
:synopsis: Utilities to support extension of packages.
|
||||||
|
|
||||||
|
|
||||||
This module provides a single function:
|
This module provides functions to manipulate packages:
|
||||||
|
|
||||||
|
|
||||||
.. function:: extend_path(path, name)
|
.. function:: extend_path(path, name)
|
||||||
|
@ -38,3 +38,24 @@ This module provides a single function:
|
||||||
``sys.path`` that cause errors when used as filenames may cause this function
|
``sys.path`` that cause errors when used as filenames may cause this function
|
||||||
to raise an exception (in line with :func:`os.path.isdir` behavior).
|
to raise an exception (in line with :func:`os.path.isdir` behavior).
|
||||||
|
|
||||||
|
.. function:: get_data(package, resource)
|
||||||
|
|
||||||
|
Get a resource from a package.
|
||||||
|
|
||||||
|
This is a wrapper round the PEP 302 loader :func:`get_data` API. The package
|
||||||
|
argument should be the name of a package, in standard module format
|
||||||
|
(foo.bar). The resource argument should be in the form of a relative
|
||||||
|
filename, using ``/`` as the path separator. The parent directory name
|
||||||
|
``..`` is not allowed, and nor is a rooted name (starting with a ``/``).
|
||||||
|
|
||||||
|
The function returns a binary string, which is the contents of the
|
||||||
|
specified resource.
|
||||||
|
|
||||||
|
For packages located in the filesystem, which have already been imported,
|
||||||
|
this is the rough equivalent of::
|
||||||
|
|
||||||
|
d = os.path.dirname(sys.modules[package].__file__)
|
||||||
|
data = open(os.path.join(d, resource), 'rb').read()
|
||||||
|
|
||||||
|
If the package cannot be located or loaded, or it uses a PEP 302 loader
|
||||||
|
which does not support :func:`get_data`, then None is returned.
|
||||||
|
|
|
@ -32,15 +32,6 @@ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||||
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||||
OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
The profiler was written after only programming in Python for 3 weeks. As a
|
|
||||||
result, it is probably clumsy code, but I don't know for sure yet 'cause I'm a
|
|
||||||
beginner :-). I did work hard to make the code run fast, so that profiling
|
|
||||||
would be a reasonable thing to do. I tried not to repeat code fragments, but
|
|
||||||
I'm sure I did some stuff in really awkward ways at times. Please send
|
|
||||||
suggestions for improvements to: jar@netscape.com. I won't promise *any*
|
|
||||||
support. ...but I'd appreciate the feedback.
|
|
||||||
|
|
||||||
|
|
||||||
.. _profiler-introduction:
|
.. _profiler-introduction:
|
||||||
|
|
||||||
Introduction to the profilers
|
Introduction to the profilers
|
||||||
|
@ -50,69 +41,38 @@ Introduction to the profilers
|
||||||
single: deterministic profiling
|
single: deterministic profiling
|
||||||
single: profiling, deterministic
|
single: profiling, deterministic
|
||||||
|
|
||||||
A :dfn:`profiler` is a program that describes the run time performance of a
|
A :dfn:`profiler` is a program that describes the run time performance
|
||||||
program, providing a variety of statistics. This documentation describes the
|
of a program, providing a variety of statistics. This documentation
|
||||||
profiler functionality provided in the modules :mod:`profile` and :mod:`pstats`.
|
describes the profiler functionality provided in the modules
|
||||||
This profiler provides :dfn:`deterministic profiling` of any Python programs.
|
:mod:`cProfile`, :mod:`profile` and :mod:`pstats`. This profiler
|
||||||
It also provides a series of report generation tools to allow users to rapidly
|
provides :dfn:`deterministic profiling` of Python programs. It also
|
||||||
|
provides a series of report generation tools to allow users to rapidly
|
||||||
examine the results of a profile operation.
|
examine the results of a profile operation.
|
||||||
|
|
||||||
The Python standard library provides two different profilers:
|
The Python standard library provides two different profilers:
|
||||||
|
|
||||||
#. :mod:`profile`, a pure Python module, described in the sequel. Copyright ©
|
#. :mod:`cProfile` is recommended for most users; it's a C extension
|
||||||
1994, by InfoSeek Corporation.
|
with reasonable overhead
|
||||||
|
that makes it suitable for profiling long-running programs.
|
||||||
|
Based on :mod:`lsprof`,
|
||||||
|
contributed by Brett Rosen and Ted Czotter.
|
||||||
|
|
||||||
#. :mod:`cProfile`, a module written in C, with a reasonable overhead that makes
|
#. :mod:`profile`, a pure Python module whose interface is imitated by
|
||||||
it suitable for profiling long-running programs. Based on :mod:`lsprof`,
|
:mod:`cProfile`. Adds significant overhead to profiled programs.
|
||||||
contributed by Brett Rosen and Ted Czotter.
|
If you're trying to extend
|
||||||
|
the profiler in some way, the task might be easier with this module.
|
||||||
|
Copyright © 1994, by InfoSeek Corporation.
|
||||||
|
|
||||||
The :mod:`profile` and :mod:`cProfile` modules export the same interface, so
|
The :mod:`profile` and :mod:`cProfile` modules export the same interface, so
|
||||||
they are mostly interchangeables; :mod:`cProfile` has a much lower overhead but
|
they are mostly interchangeable; :mod:`cProfile` has a much lower overhead but
|
||||||
is not so far as well-tested and might not be available on all systems.
|
is newer and might not be available on all systems.
|
||||||
:mod:`cProfile` is really a compatibility layer on top of the internal
|
:mod:`cProfile` is really a compatibility layer on top of the internal
|
||||||
|
<<<<<<< .working
|
||||||
:mod:`_lsprof` module.
|
:mod:`_lsprof` module.
|
||||||
|
=======
|
||||||
.. \section{How Is This Profiler Different From The Old Profiler?}
|
:mod:`_lsprof` module. The :mod:`hotshot` module is reserved for specialized
|
||||||
\nodename{Profiler Changes}
|
usage.
|
||||||
|
>>>>>>> .merge-right.r62379
|
||||||
(This section is of historical importance only; the old profiler
|
|
||||||
discussed here was last seen in Python 1.1.)
|
|
||||||
|
|
||||||
The big changes from old profiling module are that you get more
|
|
||||||
information, and you pay less CPU time. It's not a trade-off, it's a
|
|
||||||
trade-up.
|
|
||||||
|
|
||||||
To be specific:
|
|
||||||
|
|
||||||
\begin{description}
|
|
||||||
|
|
||||||
\item[Bugs removed:]
|
|
||||||
Local stack frame is no longer molested, execution time is now charged
|
|
||||||
to correct functions.
|
|
||||||
|
|
||||||
\item[Accuracy increased:]
|
|
||||||
Profiler execution time is no longer charged to user's code,
|
|
||||||
calibration for platform is supported, file reads are not done \emph{by}
|
|
||||||
profiler \emph{during} profiling (and charged to user's code!).
|
|
||||||
|
|
||||||
\item[Speed increased:]
|
|
||||||
Overhead CPU cost was reduced by more than a factor of two (perhaps a
|
|
||||||
factor of five), lightweight profiler module is all that must be
|
|
||||||
loaded, and the report generating module (\module{pstats}) is not needed
|
|
||||||
during profiling.
|
|
||||||
|
|
||||||
\item[Recursive functions support:]
|
|
||||||
Cumulative times in recursive functions are correctly calculated;
|
|
||||||
recursive entries are counted.
|
|
||||||
|
|
||||||
\item[Large growth in report generating UI:]
|
|
||||||
Distinct profiles runs can be added together forming a comprehensive
|
|
||||||
report; functions that import statistics take arbitrary lists of
|
|
||||||
files; sorting criteria is now based on keywords (instead of 4 integer
|
|
||||||
options); reports shows what functions were profiled as well as what
|
|
||||||
profile file was referenced; output format has been improved.
|
|
||||||
|
|
||||||
\end{description}
|
|
||||||
|
|
||||||
|
|
||||||
.. _profile-instant:
|
.. _profile-instant:
|
||||||
|
|
|
@ -543,7 +543,7 @@ end, and use :func:`wrap_socket` to create a server-side SSL context for it::
|
||||||
server_side=True,
|
server_side=True,
|
||||||
certfile="mycertfile",
|
certfile="mycertfile",
|
||||||
keyfile="mykeyfile",
|
keyfile="mykeyfile",
|
||||||
ssl_protocol=ssl.PROTOCOL_TLSv1)
|
ssl_version=ssl.PROTOCOL_TLSv1)
|
||||||
deal_with_client(connstream)
|
deal_with_client(connstream)
|
||||||
|
|
||||||
Then you'd read data from the ``connstream`` and do something with it till you are finished with the client (or the client is finished with you)::
|
Then you'd read data from the ``connstream`` and do something with it till you are finished with the client (or the client is finished with you)::
|
||||||
|
|
|
@ -446,6 +446,9 @@ when the function is called.
|
||||||
The function definition does not execute the function body; this gets executed
|
The function definition does not execute the function body; this gets executed
|
||||||
only when the function is called.
|
only when the function is called.
|
||||||
|
|
||||||
|
.. index::
|
||||||
|
statement: @
|
||||||
|
|
||||||
A function definition may be wrapped by one or more :term:`decorator` expressions.
|
A function definition may be wrapped by one or more :term:`decorator` expressions.
|
||||||
Decorator expressions are evaluated when the function is defined, in the scope
|
Decorator expressions are evaluated when the function is defined, in the scope
|
||||||
that contains the function definition. The result must be a callable, which is
|
that contains the function definition. The result must be a callable, which is
|
||||||
|
@ -486,7 +489,11 @@ as the default, and explicitly test for it in the body of the function, e.g.::
|
||||||
penguin.append("property of the zoo")
|
penguin.append("property of the zoo")
|
||||||
return penguin
|
return penguin
|
||||||
|
|
||||||
Function call semantics are described in more detail in section :ref:`calls`. A
|
.. index::
|
||||||
|
statement: *
|
||||||
|
statement: **
|
||||||
|
|
||||||
|
Function call semantics are described in more detail in section :ref:`calls`. A
|
||||||
function call always assigns values to all parameters mentioned in the parameter
|
function call always assigns values to all parameters mentioned in the parameter
|
||||||
list, either from position arguments, from keyword arguments, or from default
|
list, either from position arguments, from keyword arguments, or from default
|
||||||
values. If the form "``*identifier``" is present, it is initialized to a tuple
|
values. If the form "``*identifier``" is present, it is initialized to a tuple
|
||||||
|
|
|
@ -467,6 +467,9 @@ if this is not done, the order in which the arguments are printed is undefined.
|
||||||
Arbitrary Argument Lists
|
Arbitrary Argument Lists
|
||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
|
.. index::
|
||||||
|
statement: *
|
||||||
|
|
||||||
Finally, the least frequently used option is to specify that a function can be
|
Finally, the least frequently used option is to specify that a function can be
|
||||||
called with an arbitrary number of arguments. These arguments will be wrapped
|
called with an arbitrary number of arguments. These arguments will be wrapped
|
||||||
up in a tuple. Before the variable number of arguments, zero or more normal
|
up in a tuple. Before the variable number of arguments, zero or more normal
|
||||||
|
@ -508,6 +511,9 @@ or tuple::
|
||||||
>>> list(range(*args)) # call with arguments unpacked from a list
|
>>> list(range(*args)) # call with arguments unpacked from a list
|
||||||
[3, 4, 5]
|
[3, 4, 5]
|
||||||
|
|
||||||
|
.. index::
|
||||||
|
statement: **
|
||||||
|
|
||||||
In the same fashion, dictionaries can deliver keyword arguments with the ``**``\
|
In the same fashion, dictionaries can deliver keyword arguments with the ``**``\
|
||||||
-operator::
|
-operator::
|
||||||
|
|
||||||
|
@ -610,7 +616,7 @@ concise, *formatted*) in different styles; some are more readable than others.
|
||||||
Making it easy for others to read your code is always a good idea, and adopting
|
Making it easy for others to read your code is always a good idea, and adopting
|
||||||
a nice coding style helps tremendously for that.
|
a nice coding style helps tremendously for that.
|
||||||
|
|
||||||
For Python, :pep:`8` has emerged as the style guide that most projects adher to;
|
For Python, :pep:`8` has emerged as the style guide that most projects adhere to;
|
||||||
it promotes a very readable and eye-pleasing coding style. Every Python
|
it promotes a very readable and eye-pleasing coding style. Every Python
|
||||||
developer should read it at some point; here are the most important points
|
developer should read it at some point; here are the most important points
|
||||||
extracted for you:
|
extracted for you:
|
||||||
|
|
|
@ -542,3 +542,40 @@ def extend_path(path, name):
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
return path
|
return path
|
||||||
|
|
||||||
|
def get_data(package, resource):
|
||||||
|
"""Get a resource from a package.
|
||||||
|
|
||||||
|
This is a wrapper round the PEP 302 loader get_data API. The package
|
||||||
|
argument should be the name of a package, in standard module format
|
||||||
|
(foo.bar). The resource argument should be in the form of a relative
|
||||||
|
filename, using '/' as the path separator. The parent directory name '..'
|
||||||
|
is not allowed, and nor is a rooted name (starting with a '/').
|
||||||
|
|
||||||
|
The function returns a binary string, which is the contents of the
|
||||||
|
specified resource.
|
||||||
|
|
||||||
|
For packages located in the filesystem, which have already been imported,
|
||||||
|
this is the rough equivalent of
|
||||||
|
|
||||||
|
d = os.path.dirname(sys.modules[package].__file__)
|
||||||
|
data = open(os.path.join(d, resource), 'rb').read()
|
||||||
|
|
||||||
|
If the package cannot be located or loaded, or it uses a PEP 302 loader
|
||||||
|
which does not support get_data(), then None is returned.
|
||||||
|
"""
|
||||||
|
|
||||||
|
loader = get_loader(package)
|
||||||
|
if loader is None or not hasattr(loader, 'get_data'):
|
||||||
|
return None
|
||||||
|
mod = sys.modules.get(package) or loader.load_module(package)
|
||||||
|
if mod is None or not hasattr(mod, '__file__'):
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Modify the resource name to be compatible with the loader.get_data
|
||||||
|
# signature - an os.path format "filename" starting with the dirname of
|
||||||
|
# the package's __file__
|
||||||
|
parts = resource.split('/')
|
||||||
|
parts.insert(0, os.path.dirname(mod.__file__))
|
||||||
|
resource_name = os.path.join(*parts)
|
||||||
|
return loader.get_data(resource_name)
|
||||||
|
|
|
@ -731,6 +731,11 @@ def dash_R_cleanup(fs, ps, pic, abcs):
|
||||||
from distutils.dir_util import _path_created
|
from distutils.dir_util import _path_created
|
||||||
from weakref import WeakSet
|
from weakref import WeakSet
|
||||||
|
|
||||||
|
# Clear the warnings registry, so they can be displayed again
|
||||||
|
for mod in sys.modules.values():
|
||||||
|
if hasattr(mod, '__warningregistry__'):
|
||||||
|
del mod.__warningregistry__
|
||||||
|
|
||||||
# Restore some original values.
|
# Restore some original values.
|
||||||
warnings.filters[:] = fs
|
warnings.filters[:] = fs
|
||||||
copy_reg.dispatch_table.clear()
|
copy_reg.dispatch_table.clear()
|
||||||
|
|
|
@ -39,6 +39,18 @@ class FrozenTests(unittest.TestCase):
|
||||||
else:
|
else:
|
||||||
self.fail("import __phello__.foo should have failed")
|
self.fail("import __phello__.foo should have failed")
|
||||||
|
|
||||||
|
if sys.platform != "mac": # On the Mac this import does succeed.
|
||||||
|
try:
|
||||||
|
import __phello__.foo
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
self.fail("import __phello__.foo should have failed")
|
||||||
|
|
||||||
|
del sys.modules['__hello__']
|
||||||
|
del sys.modules['__phello__']
|
||||||
|
del sys.modules['__phello__.spam']
|
||||||
|
|
||||||
def test_main():
|
def test_main():
|
||||||
run_unittest(FrozenTests)
|
run_unittest(FrozenTests)
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,7 @@ class TestPkg(unittest.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.root = None
|
self.root = None
|
||||||
|
self.pkgname = None
|
||||||
self.syspath = list(sys.path)
|
self.syspath = list(sys.path)
|
||||||
self.sysmodules = sys.modules.copy()
|
self.sysmodules = sys.modules.copy()
|
||||||
|
|
||||||
|
@ -56,6 +57,13 @@ class TestPkg(unittest.TestCase):
|
||||||
del self.sysmodules
|
del self.sysmodules
|
||||||
cleanout(self.root)
|
cleanout(self.root)
|
||||||
|
|
||||||
|
# delete all modules concerning the tested hiearchy
|
||||||
|
if self.pkgname:
|
||||||
|
modules = [name for name in sys.modules
|
||||||
|
if self.pkgname in name.split('.')]
|
||||||
|
for name in modules:
|
||||||
|
del sys.modules[name]
|
||||||
|
|
||||||
def run_code(self, code):
|
def run_code(self, code):
|
||||||
exec(textwrap.dedent(code), globals(), {"self": self})
|
exec(textwrap.dedent(code), globals(), {"self": self})
|
||||||
|
|
||||||
|
@ -78,6 +86,8 @@ class TestPkg(unittest.TestCase):
|
||||||
f.write('\n')
|
f.write('\n')
|
||||||
f.close()
|
f.close()
|
||||||
self.root = root
|
self.root = root
|
||||||
|
# package name is the name of the first item
|
||||||
|
self.pkgname = descr[0][0]
|
||||||
|
|
||||||
def test_1(self):
|
def test_1(self):
|
||||||
hier = [("t1", None), ("t1 __init__.py", "")]
|
hier = [("t1", None), ("t1 __init__.py", "")]
|
||||||
|
|
127
Lib/test/test_pkgutil.py
Normal file
127
Lib/test/test_pkgutil.py
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
from test.test_support import run_unittest
|
||||||
|
import unittest
|
||||||
|
import sys
|
||||||
|
import imp
|
||||||
|
import pkgutil
|
||||||
|
import os
|
||||||
|
import os.path
|
||||||
|
import tempfile
|
||||||
|
import shutil
|
||||||
|
import zipfile
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class PkgutilTests(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.dirname = tempfile.mkdtemp()
|
||||||
|
sys.path.insert(0, self.dirname)
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
del sys.path[0]
|
||||||
|
shutil.rmtree(self.dirname)
|
||||||
|
|
||||||
|
def test_getdata_filesys(self):
|
||||||
|
pkg = 'test_getdata_filesys'
|
||||||
|
|
||||||
|
# Include a LF and a CRLF, to test that binary data is read back
|
||||||
|
RESOURCE_DATA = b'Hello, world!\nSecond line\r\nThird line'
|
||||||
|
|
||||||
|
# Make a package with some resources
|
||||||
|
package_dir = os.path.join(self.dirname, pkg)
|
||||||
|
os.mkdir(package_dir)
|
||||||
|
# Empty init.py
|
||||||
|
f = open(os.path.join(package_dir, '__init__.py'), "wb")
|
||||||
|
f.close()
|
||||||
|
# Resource files, res.txt, sub/res.txt
|
||||||
|
f = open(os.path.join(package_dir, 'res.txt'), "wb")
|
||||||
|
f.write(RESOURCE_DATA)
|
||||||
|
f.close()
|
||||||
|
os.mkdir(os.path.join(package_dir, 'sub'))
|
||||||
|
f = open(os.path.join(package_dir, 'sub', 'res.txt'), "wb")
|
||||||
|
f.write(RESOURCE_DATA)
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
# Check we can read the resources
|
||||||
|
res1 = pkgutil.get_data(pkg, 'res.txt')
|
||||||
|
self.assertEqual(res1, RESOURCE_DATA)
|
||||||
|
res2 = pkgutil.get_data(pkg, 'sub/res.txt')
|
||||||
|
self.assertEqual(res2, RESOURCE_DATA)
|
||||||
|
|
||||||
|
del sys.modules[pkg]
|
||||||
|
|
||||||
|
def test_getdata_zipfile(self):
|
||||||
|
zip = 'test_getdata_zipfile.zip'
|
||||||
|
pkg = 'test_getdata_zipfile'
|
||||||
|
|
||||||
|
# Include a LF and a CRLF, to test that binary data is read back
|
||||||
|
RESOURCE_DATA = b'Hello, world!\nSecond line\r\nThird line'
|
||||||
|
|
||||||
|
# Make a package with some resources
|
||||||
|
zip_file = os.path.join(self.dirname, zip)
|
||||||
|
z = zipfile.ZipFile(zip_file, 'w')
|
||||||
|
|
||||||
|
# Empty init.py
|
||||||
|
z.writestr(pkg + '/__init__.py', "")
|
||||||
|
# Resource files, res.txt, sub/res.txt
|
||||||
|
z.writestr(pkg + '/res.txt', RESOURCE_DATA)
|
||||||
|
z.writestr(pkg + '/sub/res.txt', RESOURCE_DATA)
|
||||||
|
z.close()
|
||||||
|
|
||||||
|
# Check we can read the resources
|
||||||
|
sys.path.insert(0, zip_file)
|
||||||
|
res1 = pkgutil.get_data(pkg, 'res.txt')
|
||||||
|
self.assertEqual(res1, RESOURCE_DATA)
|
||||||
|
res2 = pkgutil.get_data(pkg, 'sub/res.txt')
|
||||||
|
self.assertEqual(res2, RESOURCE_DATA)
|
||||||
|
del sys.path[0]
|
||||||
|
|
||||||
|
del sys.modules[pkg]
|
||||||
|
|
||||||
|
class PkgutilPEP302Tests(unittest.TestCase):
|
||||||
|
|
||||||
|
class MyTestLoader(object):
|
||||||
|
def load_module(self, fullname):
|
||||||
|
# Create an empty module
|
||||||
|
mod = sys.modules.setdefault(fullname, imp.new_module(fullname))
|
||||||
|
mod.__file__ = "<%s>" % self.__class__.__name__
|
||||||
|
mod.__loader__ = self
|
||||||
|
# Make it a package
|
||||||
|
mod.__path__ = []
|
||||||
|
# Count how many times the module is reloaded
|
||||||
|
mod.__dict__['loads'] = mod.__dict__.get('loads',0) + 1
|
||||||
|
return mod
|
||||||
|
|
||||||
|
def get_data(self, path):
|
||||||
|
return "Hello, world!"
|
||||||
|
|
||||||
|
class MyTestImporter(object):
|
||||||
|
def find_module(self, fullname, path=None):
|
||||||
|
return PkgutilPEP302Tests.MyTestLoader()
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
sys.meta_path.insert(0, self.MyTestImporter())
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
del sys.meta_path[0]
|
||||||
|
|
||||||
|
def test_getdata_pep302(self):
|
||||||
|
# Use a dummy importer/loader
|
||||||
|
self.assertEqual(pkgutil.get_data('foo', 'dummy'), "Hello, world!")
|
||||||
|
del sys.modules['foo']
|
||||||
|
|
||||||
|
def test_alreadyloaded(self):
|
||||||
|
# Ensure that get_data works without reloading - the "loads" module
|
||||||
|
# variable in the example loader should count how many times a reload
|
||||||
|
# occurs.
|
||||||
|
import foo
|
||||||
|
self.assertEqual(foo.loads, 1)
|
||||||
|
self.assertEqual(pkgutil.get_data('foo', 'dummy'), "Hello, world!")
|
||||||
|
self.assertEqual(foo.loads, 1)
|
||||||
|
del sys.modules['foo']
|
||||||
|
|
||||||
|
def test_main():
|
||||||
|
run_unittest(PkgutilTests, PkgutilPEP302Tests)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
test_main()
|
|
@ -22,8 +22,9 @@ class ProfileTest(unittest.TestCase):
|
||||||
def do_profiling(cls):
|
def do_profiling(cls):
|
||||||
results = []
|
results = []
|
||||||
prof = cls.profilerclass(timer, 0.001)
|
prof = cls.profilerclass(timer, 0.001)
|
||||||
|
start_timer = timer()
|
||||||
prof.runctx("testfunc()", globals(), locals())
|
prof.runctx("testfunc()", globals(), locals())
|
||||||
results.append(timer())
|
results.append(timer() - start_timer)
|
||||||
for methodname in cls.methodnames:
|
for methodname in cls.methodnames:
|
||||||
s = StringIO()
|
s = StringIO()
|
||||||
stats = pstats.Stats(prof, stream=s)
|
stats = pstats.Stats(prof, stream=s)
|
||||||
|
@ -40,7 +41,7 @@ class ProfileTest(unittest.TestCase):
|
||||||
|
|
||||||
def test_cprofile(self):
|
def test_cprofile(self):
|
||||||
results = self.do_profiling()
|
results = self.do_profiling()
|
||||||
self.assertEqual(results[0], 43000)
|
self.assertEqual(results[0], 1000)
|
||||||
for i, method in enumerate(self.methodnames):
|
for i, method in enumerate(self.methodnames):
|
||||||
if results[i+1] != self.expected_output[method]:
|
if results[i+1] != self.expected_output[method]:
|
||||||
print("Stats.%s output for %s doesn't fit expectation!" %
|
print("Stats.%s output for %s doesn't fit expectation!" %
|
||||||
|
|
|
@ -101,12 +101,6 @@ class TestWarnings(unittest.TestCase):
|
||||||
|
|
||||||
|
|
||||||
def test_main(verbose=None):
|
def test_main(verbose=None):
|
||||||
# Obscure hack so that this test passes after reloads or repeated calls
|
|
||||||
# to test_main (regrtest -R).
|
|
||||||
if '__warningregistry__' in globals():
|
|
||||||
del globals()['__warningregistry__']
|
|
||||||
if hasattr(sys, '__warningregistry__'):
|
|
||||||
del sys.__warningregistry__
|
|
||||||
test_support.run_unittest(__name__)
|
test_support.run_unittest(__name__)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
|
@ -391,6 +391,8 @@ class PyWarningsDisplayTests(BaseTest, WarningsDisplayTests):
|
||||||
|
|
||||||
|
|
||||||
def test_main():
|
def test_main():
|
||||||
|
py_warnings.onceregistry.clear()
|
||||||
|
c_warnings.onceregistry.clear()
|
||||||
test_support.run_unittest(CFilterTests,
|
test_support.run_unittest(CFilterTests,
|
||||||
PyFilterTests,
|
PyFilterTests,
|
||||||
CWarnTests,
|
CWarnTests,
|
||||||
|
|
|
@ -49,6 +49,17 @@ class XMLRPCTestCase(unittest.TestCase):
|
||||||
(newdt,), m = xmlrpclib.loads(s, use_datetime=0)
|
(newdt,), m = xmlrpclib.loads(s, use_datetime=0)
|
||||||
self.assertEquals(newdt, xmlrpclib.DateTime('20050210T11:41:23'))
|
self.assertEquals(newdt, xmlrpclib.DateTime('20050210T11:41:23'))
|
||||||
|
|
||||||
|
def test_datetime_before_1900(self):
|
||||||
|
# same as before but with an date before 1900
|
||||||
|
dt = datetime.datetime(1, 2, 10, 11, 41, 23)
|
||||||
|
s = xmlrpclib.dumps((dt,))
|
||||||
|
(newdt,), m = xmlrpclib.loads(s, use_datetime=1)
|
||||||
|
self.assertEquals(newdt, dt)
|
||||||
|
self.assertEquals(m, None)
|
||||||
|
|
||||||
|
(newdt,), m = xmlrpclib.loads(s, use_datetime=0)
|
||||||
|
self.assertEquals(newdt, xmlrpclib.DateTime('00010210T11:41:23'))
|
||||||
|
|
||||||
def test_cmp_datetime_DateTime(self):
|
def test_cmp_datetime_DateTime(self):
|
||||||
now = datetime.datetime.now()
|
now = datetime.datetime.now()
|
||||||
dt = xmlrpclib.DateTime(now.timetuple())
|
dt = xmlrpclib.DateTime(now.timetuple())
|
||||||
|
|
|
@ -287,6 +287,20 @@ boolean = Boolean = bool
|
||||||
# @param value The time, given as an ISO 8601 string, a time
|
# @param value The time, given as an ISO 8601 string, a time
|
||||||
# tuple, or a integer time value.
|
# tuple, or a integer time value.
|
||||||
|
|
||||||
|
def _strftime(value):
|
||||||
|
if datetime:
|
||||||
|
if isinstance(value, datetime.datetime):
|
||||||
|
return "%04d%02d%02dT%02d:%02d:%02d" % (
|
||||||
|
value.year, value.month, value.day,
|
||||||
|
value.hour, value.minute, value.second)
|
||||||
|
|
||||||
|
if not isinstance(value, (tuple, time.struct_time)):
|
||||||
|
if value == 0:
|
||||||
|
value = time.time()
|
||||||
|
value = time.localtime(value)
|
||||||
|
|
||||||
|
return "%04d%02d%02dT%02d:%02d:%02d" % value[:6]
|
||||||
|
|
||||||
class DateTime:
|
class DateTime:
|
||||||
"""DateTime wrapper for an ISO 8601 string or time tuple or
|
"""DateTime wrapper for an ISO 8601 string or time tuple or
|
||||||
localtime integer value to generate 'dateTime.iso8601' XML-RPC
|
localtime integer value to generate 'dateTime.iso8601' XML-RPC
|
||||||
|
@ -294,16 +308,10 @@ class DateTime:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, value=0):
|
def __init__(self, value=0):
|
||||||
if not isinstance(value, str):
|
if isinstance(value, str):
|
||||||
if datetime and isinstance(value, datetime.datetime):
|
self.value = value
|
||||||
self.value = value.strftime("%Y%m%dT%H:%M:%S")
|
else:
|
||||||
return
|
self.value = _strftime(value)
|
||||||
if not isinstance(value, (tuple, time.struct_time)):
|
|
||||||
if value == 0:
|
|
||||||
value = time.time()
|
|
||||||
value = time.localtime(value)
|
|
||||||
value = time.strftime("%Y%m%dT%H:%M:%S", value)
|
|
||||||
self.value = value
|
|
||||||
|
|
||||||
def make_comparable(self, other):
|
def make_comparable(self, other):
|
||||||
if isinstance(other, DateTime):
|
if isinstance(other, DateTime):
|
||||||
|
@ -700,7 +708,7 @@ class Marshaller:
|
||||||
if datetime:
|
if datetime:
|
||||||
def dump_datetime(self, value, write):
|
def dump_datetime(self, value, write):
|
||||||
write("<value><dateTime.iso8601>")
|
write("<value><dateTime.iso8601>")
|
||||||
write(value.strftime("%Y%m%dT%H:%M:%S"))
|
write(_strftime(value))
|
||||||
write("</dateTime.iso8601></value>\n")
|
write("</dateTime.iso8601></value>\n")
|
||||||
dispatch[datetime.datetime] = dump_datetime
|
dispatch[datetime.datetime] = dump_datetime
|
||||||
|
|
||||||
|
|
|
@ -160,6 +160,7 @@ PyObject *
|
||||||
PyLong_FromLong(long ival)
|
PyLong_FromLong(long ival)
|
||||||
{
|
{
|
||||||
PyLongObject *v;
|
PyLongObject *v;
|
||||||
|
unsigned long abs_ival;
|
||||||
unsigned long t; /* unsigned so >> doesn't propagate sign bit */
|
unsigned long t; /* unsigned so >> doesn't propagate sign bit */
|
||||||
int ndigits = 0;
|
int ndigits = 0;
|
||||||
int sign = 1;
|
int sign = 1;
|
||||||
|
@ -167,9 +168,15 @@ PyLong_FromLong(long ival)
|
||||||
CHECK_SMALL_INT(ival);
|
CHECK_SMALL_INT(ival);
|
||||||
|
|
||||||
if (ival < 0) {
|
if (ival < 0) {
|
||||||
ival = -ival;
|
/* if LONG_MIN == -LONG_MAX-1 (true on most platforms) then
|
||||||
|
ANSI C says that the result of -ival is undefined when ival
|
||||||
|
== LONG_MIN. Hence the following workaround. */
|
||||||
|
abs_ival = (unsigned long)(-1-ival) + 1;
|
||||||
sign = -1;
|
sign = -1;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
abs_ival = (unsigned long)ival;
|
||||||
|
}
|
||||||
|
|
||||||
/* Fast path for single-digits ints */
|
/* Fast path for single-digits ints */
|
||||||
if (!(ival>>PyLong_SHIFT)) {
|
if (!(ival>>PyLong_SHIFT)) {
|
||||||
|
@ -193,7 +200,7 @@ PyLong_FromLong(long ival)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Larger numbers: loop to determine number of digits */
|
/* Larger numbers: loop to determine number of digits */
|
||||||
t = (unsigned long)ival;
|
t = abs_ival;
|
||||||
while (t) {
|
while (t) {
|
||||||
++ndigits;
|
++ndigits;
|
||||||
t >>= PyLong_SHIFT;
|
t >>= PyLong_SHIFT;
|
||||||
|
@ -202,7 +209,7 @@ PyLong_FromLong(long ival)
|
||||||
if (v != NULL) {
|
if (v != NULL) {
|
||||||
digit *p = v->ob_digit;
|
digit *p = v->ob_digit;
|
||||||
Py_SIZE(v) = ndigits*sign;
|
Py_SIZE(v) = ndigits*sign;
|
||||||
t = (unsigned long)ival;
|
t = abs_ival;
|
||||||
while (t) {
|
while (t) {
|
||||||
*p++ = (digit)(t & PyLong_MASK);
|
*p++ = (digit)(t & PyLong_MASK);
|
||||||
t >>= PyLong_SHIFT;
|
t >>= PyLong_SHIFT;
|
||||||
|
@ -1033,21 +1040,27 @@ PyObject *
|
||||||
PyLong_FromLongLong(PY_LONG_LONG ival)
|
PyLong_FromLongLong(PY_LONG_LONG ival)
|
||||||
{
|
{
|
||||||
PyLongObject *v;
|
PyLongObject *v;
|
||||||
|
unsigned PY_LONG_LONG abs_ival;
|
||||||
unsigned PY_LONG_LONG t; /* unsigned so >> doesn't propagate sign bit */
|
unsigned PY_LONG_LONG t; /* unsigned so >> doesn't propagate sign bit */
|
||||||
int ndigits = 0;
|
int ndigits = 0;
|
||||||
int negative = 0;
|
int negative = 0;
|
||||||
|
|
||||||
CHECK_SMALL_INT(ival);
|
CHECK_SMALL_INT(ival);
|
||||||
if (ival < 0) {
|
if (ival < 0) {
|
||||||
ival = -ival;
|
/* avoid signed overflow on negation; see comments
|
||||||
|
in PyLong_FromLong above. */
|
||||||
|
abs_ival = (unsigned PY_LONG_LONG)(-1-ival) + 1;
|
||||||
negative = 1;
|
negative = 1;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
abs_ival = (unsigned PY_LONG_LONG)ival;
|
||||||
|
}
|
||||||
|
|
||||||
/* Count the number of Python digits.
|
/* Count the number of Python digits.
|
||||||
We used to pick 5 ("big enough for anything"), but that's a
|
We used to pick 5 ("big enough for anything"), but that's a
|
||||||
waste of time and space given that 5*15 = 75 bits are rarely
|
waste of time and space given that 5*15 = 75 bits are rarely
|
||||||
needed. */
|
needed. */
|
||||||
t = (unsigned PY_LONG_LONG)ival;
|
t = abs_ival;
|
||||||
while (t) {
|
while (t) {
|
||||||
++ndigits;
|
++ndigits;
|
||||||
t >>= PyLong_SHIFT;
|
t >>= PyLong_SHIFT;
|
||||||
|
@ -1056,7 +1069,7 @@ PyLong_FromLongLong(PY_LONG_LONG ival)
|
||||||
if (v != NULL) {
|
if (v != NULL) {
|
||||||
digit *p = v->ob_digit;
|
digit *p = v->ob_digit;
|
||||||
Py_SIZE(v) = negative ? -ndigits : ndigits;
|
Py_SIZE(v) = negative ? -ndigits : ndigits;
|
||||||
t = (unsigned PY_LONG_LONG)ival;
|
t = abs_ival;
|
||||||
while (t) {
|
while (t) {
|
||||||
*p++ = (digit)(t & PyLong_MASK);
|
*p++ = (digit)(t & PyLong_MASK);
|
||||||
t >>= PyLong_SHIFT;
|
t >>= PyLong_SHIFT;
|
||||||
|
|
|
@ -1191,9 +1191,9 @@ _PySys_Init(void)
|
||||||
/* stdin/stdout/stderr are now set by pythonrun.c */
|
/* stdin/stdout/stderr are now set by pythonrun.c */
|
||||||
|
|
||||||
PyDict_SetItemString(sysdict, "__displayhook__",
|
PyDict_SetItemString(sysdict, "__displayhook__",
|
||||||
PyDict_GetItemString(sysdict, "displayhook"));
|
PyDict_GetItemString(sysdict, "displayhook"));
|
||||||
PyDict_SetItemString(sysdict, "__excepthook__",
|
PyDict_SetItemString(sysdict, "__excepthook__",
|
||||||
PyDict_GetItemString(sysdict, "excepthook"));
|
PyDict_GetItemString(sysdict, "excepthook"));
|
||||||
SET_SYS_FROM_STRING("version",
|
SET_SYS_FROM_STRING("version",
|
||||||
PyUnicode_FromString(Py_GetVersion()));
|
PyUnicode_FromString(Py_GetVersion()));
|
||||||
SET_SYS_FROM_STRING("hexversion",
|
SET_SYS_FROM_STRING("hexversion",
|
||||||
|
@ -1203,7 +1203,7 @@ _PySys_Init(void)
|
||||||
Py_BuildValue("(UUU)", "CPython", branch,
|
Py_BuildValue("(UUU)", "CPython", branch,
|
||||||
svn_revision));
|
svn_revision));
|
||||||
SET_SYS_FROM_STRING("dont_write_bytecode",
|
SET_SYS_FROM_STRING("dont_write_bytecode",
|
||||||
PyBool_FromLong(Py_DontWriteBytecodeFlag));
|
PyBool_FromLong(Py_DontWriteBytecodeFlag));
|
||||||
/*
|
/*
|
||||||
* These release level checks are mutually exclusive and cover
|
* These release level checks are mutually exclusive and cover
|
||||||
* the field, so don't get too fancy with the pre-processor!
|
* the field, so don't get too fancy with the pre-processor!
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue