Merged revisions 62260-62261,62266,62271,62277-62279,62289-62290,62293-62298,62302-62306,62308,62311,62313-62315,62319-62321 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk ........ r62260 | gregory.p.smith | 2008-04-10 01:11:56 +0200 (Thu, 10 Apr 2008) | 2 lines better diagnostics ........ r62261 | gregory.p.smith | 2008-04-10 01:16:37 +0200 (Thu, 10 Apr 2008) | 3 lines Raise SystemError when size < 0 is passed into PyString_FromStringAndSize, PyBytes_FromStringAndSize or PyUnicode_FromStringAndSize. [issue2587] ........ r62266 | neal.norwitz | 2008-04-10 07:46:39 +0200 (Thu, 10 Apr 2008) | 5 lines Remove the test file before writing it in case there is no write permission. This might help fix some of the failures on Windows box(es). It doesn't hurt either way and ensure the tests are a little more self contained (ie have less assumptions). ........ r62271 | gregory.p.smith | 2008-04-10 21:50:36 +0200 (Thu, 10 Apr 2008) | 2 lines get rid of assert (size >= 0) now that an explicit if (size < 0) is in the code. ........ r62277 | andrew.kuchling | 2008-04-10 23:27:10 +0200 (Thu, 10 Apr 2008) | 1 line Remove forward-looking statement ........ r62278 | andrew.kuchling | 2008-04-10 23:28:51 +0200 (Thu, 10 Apr 2008) | 1 line Add punctuation ........ r62279 | andrew.kuchling | 2008-04-10 23:29:01 +0200 (Thu, 10 Apr 2008) | 1 line Use issue directive ........ r62289 | thomas.heller | 2008-04-11 15:05:38 +0200 (Fri, 11 Apr 2008) | 3 lines Move backwards compatibility macro to the correct place; PyIndex_Check() was introduced in Python 2.5. ........ r62290 | thomas.heller | 2008-04-11 16:20:26 +0200 (Fri, 11 Apr 2008) | 2 lines Performance improvements. ........ r62293 | christian.heimes | 2008-04-12 15:03:03 +0200 (Sat, 12 Apr 2008) | 2 lines Applied patch #2617 from Frank Wierzbicki wit some extras from me -J and -X are now reserved for Jython and non-standard arguments (e.g. IronPython). I've added some extra comments to make sure the reservation don't get missed in the future. ........ r62294 | georg.brandl | 2008-04-12 20:11:18 +0200 (Sat, 12 Apr 2008) | 2 lines Use absolute path in sys.path. ........ r62295 | georg.brandl | 2008-04-12 20:36:09 +0200 (Sat, 12 Apr 2008) | 2 lines #2615: small consistency update by Jeroen Ruigrok van der Werven. ........ r62296 | georg.brandl | 2008-04-12 21:00:20 +0200 (Sat, 12 Apr 2008) | 2 lines Add Jeroen. ........ r62297 | georg.brandl | 2008-04-12 21:05:37 +0200 (Sat, 12 Apr 2008) | 2 lines Don't offend snake lovers. ........ r62298 | gregory.p.smith | 2008-04-12 22:37:48 +0200 (Sat, 12 Apr 2008) | 2 lines fix compiler warnings ........ r62302 | gregory.p.smith | 2008-04-13 00:24:04 +0200 (Sun, 13 Apr 2008) | 3 lines socket.error inherits from IOError, it no longer needs listing in the all_errors tuple. ........ r62303 | brett.cannon | 2008-04-13 01:44:07 +0200 (Sun, 13 Apr 2008) | 8 lines Re-implement the 'warnings' module in C. This allows for usage of the 'warnings' code in places where it was previously not possible (e.g., the parser). It could also potentially lead to a speed-up in interpreter start-up if the C version of the code (_warnings) is imported over the use of the Python version in key places. Closes issue #1631171. ........ r62304 | gregory.p.smith | 2008-04-13 02:03:25 +0200 (Sun, 13 Apr 2008) | 3 lines Adds a profile-opt target for easy compilation of a python binary using gcc's profile guided optimization. ........ r62305 | brett.cannon | 2008-04-13 02:18:44 +0200 (Sun, 13 Apr 2008) | 3 lines Fix a bug in PySys_HasWarnOption() where it was not properly checking the length of the list storing the warning options. ........ r62306 | brett.cannon | 2008-04-13 02:25:15 +0200 (Sun, 13 Apr 2008) | 2 lines Fix an accidental bug of an non-existent init function. ........ r62308 | andrew.kuchling | 2008-04-13 03:05:59 +0200 (Sun, 13 Apr 2008) | 1 line Mention -J, -X ........ r62311 | benjamin.peterson | 2008-04-13 04:20:05 +0200 (Sun, 13 Apr 2008) | 2 lines Give the "Interactive Interpreter Changes" section in 2.6 whatsnew a unique link name ........ r62313 | brett.cannon | 2008-04-13 04:42:36 +0200 (Sun, 13 Apr 2008) | 3 lines Fix test_warnings by making the state of things more consistent for each test when it is run. ........ r62314 | skip.montanaro | 2008-04-13 05:17:30 +0200 (Sun, 13 Apr 2008) | 2 lines spelling ........ r62315 | georg.brandl | 2008-04-13 09:07:44 +0200 (Sun, 13 Apr 2008) | 2 lines Fix markup. ........ r62319 | christian.heimes | 2008-04-13 11:30:17 +0200 (Sun, 13 Apr 2008) | 1 line Fix compiler warning Include/warnings.h:19:28: warning: no newline at end of file ........ r62320 | christian.heimes | 2008-04-13 11:33:24 +0200 (Sun, 13 Apr 2008) | 1 line Use PyString_InternFromString instead of PyString_FromString for static vars ........ r62321 | christian.heimes | 2008-04-13 11:37:05 +0200 (Sun, 13 Apr 2008) | 1 line Added new files to the pcbuild files ........
This commit is contained in:
parent
659d32df78
commit
33fe8093df
|
@ -8,7 +8,7 @@
|
||||||
# that aren't pickleable (module imports are okay, they're removed automatically).
|
# that aren't pickleable (module imports are okay, they're removed automatically).
|
||||||
|
|
||||||
import sys, os, time
|
import sys, os, time
|
||||||
sys.path.append('tools/sphinxext')
|
sys.path.append(os.path.abspath('tools/sphinxext'))
|
||||||
|
|
||||||
# General configuration
|
# General configuration
|
||||||
# ---------------------
|
# ---------------------
|
||||||
|
|
|
@ -202,16 +202,16 @@ Available Functions
|
||||||
sources).
|
sources).
|
||||||
|
|
||||||
|
|
||||||
.. function:: showwarning(message, category, filename, lineno[, file])
|
.. function:: showwarning(message, category, filename, lineno[, file[, line]])
|
||||||
|
|
||||||
Write a warning to a file. The default implementation calls
|
Write a warning to a file. The default implementation calls
|
||||||
``formatwarning(message, category, filename, lineno)`` and writes the resulting
|
``formatwarning(message, category, filename, lineno, line)`` and writes the
|
||||||
string to *file*, which defaults to ``sys.stderr``. You may replace this
|
resulting string to *file*, which defaults to ``sys.stderr``. You may replace
|
||||||
function with an alternative implementation by assigning to
|
this function with an alternative implementation by assigning to
|
||||||
``warnings.showwarning``.
|
``warnings.showwarning``.
|
||||||
|
|
||||||
|
|
||||||
.. function:: formatwarning(message, category, filename, lineno)
|
.. function:: formatwarning(message, category, filename, lineno[, line])
|
||||||
|
|
||||||
Format a warning the standard way. This returns a string which may contain
|
Format a warning the standard way. This returns a string which may contain
|
||||||
embedded newlines and ends in a newline.
|
embedded newlines and ends in a newline.
|
||||||
|
|
|
@ -126,7 +126,7 @@ module documentation. This section lists the differences between the API and
|
||||||
to discard children of that node.
|
to discard children of that node.
|
||||||
|
|
||||||
|
|
||||||
.. method:: Node.writexml(writer[,indent=""[,addindent=""[,newl=""]]])
|
.. method:: Node.writexml(writer[, indent=""[, addindent=""[, newl=""[, encoding=""]]]])
|
||||||
|
|
||||||
Write XML to the writer object. The writer should have a :meth:`write` method
|
Write XML to the writer object. The writer should have a :meth:`write` method
|
||||||
which matches that of the file object interface. The *indent* parameter is the
|
which matches that of the file object interface. The *indent* parameter is the
|
||||||
|
@ -153,7 +153,7 @@ module documentation. This section lists the differences between the API and
|
||||||
encoding argument should be specified as "utf-8".
|
encoding argument should be specified as "utf-8".
|
||||||
|
|
||||||
|
|
||||||
.. method:: Node.toprettyxml([indent[, newl[, encoding]]])
|
.. method:: Node.toprettyxml([indent=""[, newl=""[, encoding=""]]])
|
||||||
|
|
||||||
Return a pretty-printed version of the document. *indent* specifies the
|
Return a pretty-printed version of the document. *indent* specifies the
|
||||||
indentation string and defaults to a tabulator; *newl* specifies the string
|
indentation string and defaults to a tabulator; *newl* specifies the string
|
||||||
|
|
|
@ -438,7 +438,36 @@ The :keyword:`yield` statement is only used when defining a generator function,
|
||||||
and is only used in the body of the generator function. Using a :keyword:`yield`
|
and is only used in the body of the generator function. Using a :keyword:`yield`
|
||||||
statement in a function definition is sufficient to cause that definition to
|
statement in a function definition is sufficient to cause that definition to
|
||||||
create a generator function instead of a normal function.
|
create a generator function instead of a normal function.
|
||||||
>>>>>>> .merge-right.r59773
|
When a generator function is called, it returns an iterator known as a generator
|
||||||
|
iterator, or more commonly, a generator. The body of the generator function is
|
||||||
|
executed by calling the generator's :meth:`next` method repeatedly until it
|
||||||
|
raises an exception.
|
||||||
|
|
||||||
|
When a :keyword:`yield` statement is executed, the state of the generator is
|
||||||
|
frozen and the value of :token:`expression_list` is returned to :meth:`next`'s
|
||||||
|
caller. By "frozen" we mean that all local state is retained, including the
|
||||||
|
current bindings of local variables, the instruction pointer, and the internal
|
||||||
|
evaluation stack: enough information is saved so that the next time :meth:`next`
|
||||||
|
is invoked, the function can proceed exactly as if the :keyword:`yield`
|
||||||
|
statement were just another external call.
|
||||||
|
|
||||||
|
As of Python version 2.5, the :keyword:`yield` statement is now allowed in the
|
||||||
|
:keyword:`try` clause of a :keyword:`try` ... :keyword:`finally` construct. If
|
||||||
|
the generator is not resumed before it is finalized (by reaching a zero
|
||||||
|
reference count or by being garbage collected), the generator-iterator's
|
||||||
|
:meth:`close` method will be called, allowing any pending :keyword:`finally`
|
||||||
|
clauses to execute.
|
||||||
|
|
||||||
|
|
||||||
|
.. seealso::
|
||||||
|
|
||||||
|
:pep:`0255` - Simple Generators
|
||||||
|
The proposal for adding generators and the :keyword:`yield` statement to Python.
|
||||||
|
|
||||||
|
:pep:`0342` - Coroutines via Enhanced Generators
|
||||||
|
The proposal that, among other generator enhancements, proposed allowing
|
||||||
|
:keyword:`yield` to appear inside a :keyword:`try` ... :keyword:`finally` block.
|
||||||
|
|
||||||
|
|
||||||
.. _raise:
|
.. _raise:
|
||||||
|
|
||||||
|
|
|
@ -68,7 +68,7 @@ application written in C and use it as an extension or command language for that
|
||||||
application.
|
application.
|
||||||
|
|
||||||
By the way, the language is named after the BBC show "Monty Python's Flying
|
By the way, the language is named after the BBC show "Monty Python's Flying
|
||||||
Circus" and has nothing to do with nasty reptiles. Making references to Monty
|
Circus" and has nothing to do with reptiles. Making references to Monty
|
||||||
Python skits in documentation is not only allowed, it is encouraged!
|
Python skits in documentation is not only allowed, it is encouraged!
|
||||||
|
|
||||||
Now that you are all excited about Python, you'll want to examine it in some
|
Now that you are all excited about Python, you'll want to examine it in some
|
||||||
|
|
|
@ -40,12 +40,11 @@
|
||||||
* Credit the author of a patch or bugfix. Just the name is
|
* Credit the author of a patch or bugfix. Just the name is
|
||||||
sufficient; the e-mail address isn't necessary.
|
sufficient; the e-mail address isn't necessary.
|
||||||
|
|
||||||
* It's helpful to add the bug/patch number as a comment:
|
* It's helpful to add the bug/patch number in an parenthetical
|
||||||
|
|
||||||
.. Patch 12345
|
|
||||||
XXX Describe the transmogrify() function added to the socket
|
XXX Describe the transmogrify() function added to the socket
|
||||||
module.
|
module.
|
||||||
(Contributed by P.Y. Developer.)
|
(Contributed by P.Y. Developer; :issue:`12345`.)
|
||||||
|
|
||||||
This saves the maintainer the effort of going through the SVN logs
|
This saves the maintainer the effort of going through the SVN logs
|
||||||
when researching a change.
|
when researching a change.
|
||||||
|
@ -53,11 +52,13 @@
|
||||||
This article explains the new features in Python 2.6. No release date for
|
This article explains the new features in Python 2.6. No release date for
|
||||||
Python 2.6 has been set; it will probably be released in mid 2008.
|
Python 2.6 has been set; it will probably be released in mid 2008.
|
||||||
|
|
||||||
This article doesn't attempt to provide a complete specification of the new
|
This article doesn't attempt to provide a complete specification of
|
||||||
features, but instead provides a convenient overview. For full details, you
|
the new features, but instead provides a convenient overview. For
|
||||||
should refer to the documentation for Python 2.6. If you want to understand the
|
full details, you should refer to the documentation for Python 2.6. If
|
||||||
complete implementation and design rationale, refer to the PEP for a particular
|
you want to understand the complete implementation and design
|
||||||
new feature.
|
rationale, refer to the PEP for a particular new feature. For smaller
|
||||||
|
changes, this edition of "What's New in Python" links to the bug/patch
|
||||||
|
item for each change whenever possible.
|
||||||
|
|
||||||
.. Compare with previous release in 2 - 3 sentences here.
|
.. Compare with previous release in 2 - 3 sentences here.
|
||||||
add hyperlink when the documentation becomes available online.
|
add hyperlink when the documentation becomes available online.
|
||||||
|
@ -147,9 +148,13 @@ After posting a call for volunteers, a new Roundup installation was
|
||||||
set up at http://bugs.python.org. One installation of Roundup can
|
set up at http://bugs.python.org. One installation of Roundup can
|
||||||
host multiple trackers, and this server now also hosts issue trackers
|
host multiple trackers, and this server now also hosts issue trackers
|
||||||
for Jython and for the Python web site. It will surely find
|
for Jython and for the Python web site. It will surely find
|
||||||
other uses in the future.
|
other uses in the future. Where possible,
|
||||||
|
this edition of "What's New in Python" links to the bug/patch
|
||||||
|
item for each change.
|
||||||
|
|
||||||
Hosting is kindly provided by `Upfront Systems <http://www.upfrontsystems.co.za/>`__ of Stellenbosch, South Africa. Martin von Loewis put a
|
Hosting is kindly provided by
|
||||||
|
`Upfront Systems <http://www.upfrontsystems.co.za/>`__
|
||||||
|
of Stellenbosch, South Africa. Martin von Loewis put a
|
||||||
lot of effort into importing existing bugs and patches from
|
lot of effort into importing existing bugs and patches from
|
||||||
SourceForge; his scripts for this import operation are at
|
SourceForge; his scripts for this import operation are at
|
||||||
http://svn.python.org/view/tracker/importer/.
|
http://svn.python.org/view/tracker/importer/.
|
||||||
|
@ -187,16 +192,15 @@ Occasionally people would suggest converting the documentation into
|
||||||
SGML or, later, XML, but performing a good conversion is a major task
|
SGML or, later, XML, but performing a good conversion is a major task
|
||||||
and no one pursued the task to completion.
|
and no one pursued the task to completion.
|
||||||
|
|
||||||
During the 2.6 development cycle, Georg Brandl put a substantial
|
During the 2.6 development cycle, Georg Brandl put a substantial
|
||||||
effort into building a new toolchain called Sphinx
|
effort into building a new toolchain for processing the documentation.
|
||||||
for processing the documentation.
|
The resulting package is called Sphinx, and is available from
|
||||||
The input format is reStructured Text,
|
http://sphinx.pocoo.org/. The input format is reStructured Text, a
|
||||||
a markup commonly used in the Python community that supports
|
markup commonly used in the Python community that supports custom
|
||||||
custom extensions and directives. Sphinx concentrates
|
extensions and directives. Sphinx concentrates on HTML output,
|
||||||
on HTML output, producing attractively styled
|
producing attractively styled and modern HTML, though printed output
|
||||||
and modern HTML, though printed output is still supported through
|
is still supported through conversion to LaTeX. Sphinx is a
|
||||||
conversion to LaTeX. Sphinx is a standalone package that
|
standalone package that can be used in documenting other projects.
|
||||||
can be used in documenting other projects.
|
|
||||||
|
|
||||||
.. seealso::
|
.. seealso::
|
||||||
|
|
||||||
|
@ -1266,30 +1270,22 @@ Here are all of the changes that Python 2.6 makes to the core Python language.
|
||||||
have a :meth:`__complex__` method. In particular, the functions in the
|
have a :meth:`__complex__` method. In particular, the functions in the
|
||||||
:mod:`cmath` module will now accept objects with this method.
|
:mod:`cmath` module will now accept objects with this method.
|
||||||
This is a backport of a Python 3.0 change.
|
This is a backport of a Python 3.0 change.
|
||||||
(Contributed by Mark Dickinson.)
|
(Contributed by Mark Dickinson; :issue:`1675423`.)
|
||||||
|
|
||||||
.. Patch #1675423
|
|
||||||
|
|
||||||
A numerical nicety: when creating a complex number from two floats
|
A numerical nicety: when creating a complex number from two floats
|
||||||
on systems that support signed zeros (-0 and +0), the
|
on systems that support signed zeros (-0 and +0), the
|
||||||
:func:`complex` constructor will now preserve the sign
|
:func:`complex` constructor will now preserve the sign
|
||||||
of the zero.
|
of the zero. (:issue:`1507`)
|
||||||
|
|
||||||
.. Patch 1507
|
|
||||||
|
|
||||||
* More floating-point features were also added. The :func:`float` function
|
* More floating-point features were also added. The :func:`float` function
|
||||||
will now turn the strings ``+nan`` and ``-nan`` into the corresponding
|
will now turn the strings ``+nan`` and ``-nan`` into the corresponding
|
||||||
IEEE 754 Not A Number values, and ``+inf`` and ``-inf`` into
|
IEEE 754 Not A Number values, and ``+inf`` and ``-inf`` into
|
||||||
positive or negative infinity. This works on any platform with
|
positive or negative infinity. This works on any platform with
|
||||||
IEEE 754 semantics. (Contributed by Christian Heimes.)
|
IEEE 754 semantics. (Contributed by Christian Heimes; :issue:`1635`.)
|
||||||
|
|
||||||
.. Patch 1635
|
|
||||||
|
|
||||||
Other functions in the :mod:`math` module, :func:`isinf` and
|
Other functions in the :mod:`math` module, :func:`isinf` and
|
||||||
:func:`isnan`, return true if their floating-point argument is
|
:func:`isnan`, return true if their floating-point argument is
|
||||||
infinite or Not A Number.
|
infinite or Not A Number. (:issue:`1640`)
|
||||||
|
|
||||||
.. Patch 1640
|
|
||||||
|
|
||||||
The ``math.copysign(x, y)`` function
|
The ``math.copysign(x, y)`` function
|
||||||
copies the sign bit of an IEEE 754 number, returning the absolute
|
copies the sign bit of an IEEE 754 number, returning the absolute
|
||||||
|
@ -1306,34 +1302,26 @@ Here are all of the changes that Python 2.6 makes to the core Python language.
|
||||||
:exc:`BaseException` instead of :exc:`Exception`. This means
|
:exc:`BaseException` instead of :exc:`Exception`. This means
|
||||||
that an exception handler that does ``except Exception:``
|
that an exception handler that does ``except Exception:``
|
||||||
will not inadvertently catch :exc:`GeneratorExit`.
|
will not inadvertently catch :exc:`GeneratorExit`.
|
||||||
(Contributed by Chad Austin.)
|
(Contributed by Chad Austin; :issue:`1537`.)
|
||||||
|
|
||||||
.. Patch #1537
|
|
||||||
|
|
||||||
* Generator objects now have a :attr:`gi_code` attribute that refers to
|
* Generator objects now have a :attr:`gi_code` attribute that refers to
|
||||||
the original code object backing the generator.
|
the original code object backing the generator.
|
||||||
(Contributed by Collin Winter.)
|
(Contributed by Collin Winter; :issue:`1473257`.)
|
||||||
|
|
||||||
.. Patch #1473257
|
|
||||||
|
|
||||||
* The :func:`compile` built-in function now accepts keyword arguments
|
* The :func:`compile` built-in function now accepts keyword arguments
|
||||||
as well as positional parameters. (Contributed by Thomas Wouters.)
|
as well as positional parameters. (Contributed by Thomas Wouters;
|
||||||
|
:issue:`1444529`.)
|
||||||
.. Patch 1444529
|
|
||||||
|
|
||||||
* The :func:`complex` constructor now accepts strings containing
|
* The :func:`complex` constructor now accepts strings containing
|
||||||
parenthesized complex numbers, letting ``complex(repr(cmplx))``
|
parenthesized complex numbers, letting ``complex(repr(cmplx))``
|
||||||
will now round-trip values. For example, ``complex('(3+4j)')``
|
will now round-trip values. For example, ``complex('(3+4j)')``
|
||||||
now returns the value (3+4j).
|
now returns the value (3+4j). (:issue:`1491866`)
|
||||||
|
|
||||||
.. Patch 1491866
|
|
||||||
|
|
||||||
* The string :meth:`translate` method now accepts ``None`` as the
|
* The string :meth:`translate` method now accepts ``None`` as the
|
||||||
translation table parameter, which is treated as the identity
|
translation table parameter, which is treated as the identity
|
||||||
transformation. This makes it easier to carry out operations
|
transformation. This makes it easier to carry out operations
|
||||||
that only delete characters. (Contributed by Bengt Richter.)
|
that only delete characters. (Contributed by Bengt Richter;
|
||||||
|
:issue:`1193128`.)
|
||||||
.. Patch 1193128
|
|
||||||
|
|
||||||
* The built-in :func:`dir` function now checks for a :meth:`__dir__`
|
* The built-in :func:`dir` function now checks for a :meth:`__dir__`
|
||||||
method on the objects it receives. This method must return a list
|
method on the objects it receives. This method must return a list
|
||||||
|
@ -1341,8 +1329,7 @@ Here are all of the changes that Python 2.6 makes to the core Python language.
|
||||||
and lets the object control the value that :func:`dir` produces.
|
and lets the object control the value that :func:`dir` produces.
|
||||||
Objects that have :meth:`__getattr__` or :meth:`__getattribute__`
|
Objects that have :meth:`__getattr__` or :meth:`__getattribute__`
|
||||||
methods can use this to advertise pseudo-attributes they will honor.
|
methods can use this to advertise pseudo-attributes they will honor.
|
||||||
|
(:issue:`1591665`)
|
||||||
.. Patch 1591665
|
|
||||||
|
|
||||||
* Instance method objects have new attributes for the object and function
|
* Instance method objects have new attributes for the object and function
|
||||||
comprising the method; the new synonym for :attr:`im_self` is
|
comprising the method; the new synonym for :attr:`im_self` is
|
||||||
|
@ -1368,9 +1355,7 @@ Optimizations
|
||||||
so the cache should remain correct even in the face of Python's dynamic
|
so the cache should remain correct even in the face of Python's dynamic
|
||||||
nature.
|
nature.
|
||||||
(Original optimization implemented by Armin Rigo, updated for
|
(Original optimization implemented by Armin Rigo, updated for
|
||||||
Python 2.6 by Kevin Jacobs.)
|
Python 2.6 by Kevin Jacobs; :issue:`1700288`.)
|
||||||
|
|
||||||
.. Patch 1700288
|
|
||||||
|
|
||||||
* All of the functions in the :mod:`struct` module have been rewritten in
|
* All of the functions in the :mod:`struct` module have been rewritten in
|
||||||
C, thanks to work at the Need For Speed sprint.
|
C, thanks to work at the Need For Speed sprint.
|
||||||
|
@ -1398,6 +1383,20 @@ benchmark around XX% faster than Python 2.5.
|
||||||
|
|
||||||
.. ======================================================================
|
.. ======================================================================
|
||||||
|
|
||||||
|
.. _new-26-interactive:
|
||||||
|
|
||||||
|
Interactive Interpreter Changes
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
Two command-line options have been reserved for use by other Python
|
||||||
|
implementations. The :option:`-J` switch has been reserved for use by
|
||||||
|
Jython for Jython-specific options, such as ones that are passed to
|
||||||
|
the underlying JVM. :option:`-X` has been reserved for options
|
||||||
|
specific to a particular implementation of Python such as CPython,
|
||||||
|
Jython, or IronPython. If either option is used with Python 2.6, the
|
||||||
|
interpreter will report that the option isn't currently used.
|
||||||
|
|
||||||
|
.. ======================================================================
|
||||||
|
|
||||||
New, Improved, and Deprecated Modules
|
New, Improved, and Deprecated Modules
|
||||||
=====================================
|
=====================================
|
||||||
|
@ -1409,9 +1408,7 @@ complete list of changes, or look through the CVS logs for all the details.
|
||||||
|
|
||||||
* The :mod:`bsddb.dbshelve` module now uses the highest pickling protocol
|
* The :mod:`bsddb.dbshelve` module now uses the highest pickling protocol
|
||||||
available, instead of restricting itself to protocol 1.
|
available, instead of restricting itself to protocol 1.
|
||||||
(Contributed by W. Barnes.)
|
(Contributed by W. Barnes; :issue:`1551443`.)
|
||||||
|
|
||||||
.. Patch 1551443
|
|
||||||
|
|
||||||
* A new data type in the :mod:`collections` module: :class:`namedtuple(typename,
|
* A new data type in the :mod:`collections` module: :class:`namedtuple(typename,
|
||||||
fieldnames)` is a factory function that creates subclasses of the standard tuple
|
fieldnames)` is a factory function that creates subclasses of the standard tuple
|
||||||
|
@ -1464,9 +1461,8 @@ complete list of changes, or look through the CVS logs for all the details.
|
||||||
(Contributed by Raymond Hettinger.)
|
(Contributed by Raymond Hettinger.)
|
||||||
|
|
||||||
* The :mod:`ctypes` module now supports a :class:`c_bool` datatype
|
* The :mod:`ctypes` module now supports a :class:`c_bool` datatype
|
||||||
that represents the C99 ``bool`` type. (Contributed by David Remahl.)
|
that represents the C99 ``bool`` type. (Contributed by David Remahl;
|
||||||
|
:issue:`1649190`.)
|
||||||
.. Patch 1649190
|
|
||||||
|
|
||||||
The :mod:`ctypes` string, buffer and array types also have improved
|
The :mod:`ctypes` string, buffer and array types also have improved
|
||||||
support for extended slicing syntax,
|
support for extended slicing syntax,
|
||||||
|
@ -1492,9 +1488,7 @@ complete list of changes, or look through the CVS logs for all the details.
|
||||||
* The :mod:`datetime` module's :meth:`strftime` methods now support a
|
* The :mod:`datetime` module's :meth:`strftime` methods now support a
|
||||||
``%f`` format code that expands to the number of microseconds in the
|
``%f`` format code that expands to the number of microseconds in the
|
||||||
object, zero-padded on
|
object, zero-padded on
|
||||||
the left to six places. (Contributed by Skip Montanaro.)
|
the left to six places. (Contributed by Skip Montanaro; :issue:`1158`.)
|
||||||
|
|
||||||
.. Patch 1158
|
|
||||||
|
|
||||||
* The :mod:`decimal` module was updated to version 1.66 of
|
* The :mod:`decimal` module was updated to version 1.66 of
|
||||||
`the General Decimal Specification <http://www2.hursley.ibm.com/decimal/decarith.html>`__. New features
|
`the General Decimal Specification <http://www2.hursley.ibm.com/decimal/decarith.html>`__. New features
|
||||||
|
@ -1527,22 +1521,17 @@ complete list of changes, or look through the CVS logs for all the details.
|
||||||
:meth:`storbinary` and :meth:`storlines`
|
:meth:`storbinary` and :meth:`storlines`
|
||||||
now take an optional *callback* parameter that will be called with
|
now take an optional *callback* parameter that will be called with
|
||||||
each block of data after the data has been sent.
|
each block of data after the data has been sent.
|
||||||
(Contributed by Phil Schwartz.)
|
(Contributed by Phil Schwartz; :issue:`1221598`.)
|
||||||
|
|
||||||
.. Patch 1221598
|
|
||||||
|
|
||||||
* The :func:`reduce` built-in function is also available in the
|
* The :func:`reduce` built-in function is also available in the
|
||||||
:mod:`functools` module. In Python 3.0, the built-in is dropped and it's
|
:mod:`functools` module. In Python 3.0, the built-in is dropped and it's
|
||||||
only available from :mod:`functools`; currently there are no plans
|
only available from :mod:`functools`; currently there are no plans
|
||||||
to drop the built-in in the 2.x series. (Patched by
|
to drop the built-in in the 2.x series. (Patched by
|
||||||
Christian Heimes.)
|
Christian Heimes; :issue:`1739906`.)
|
||||||
|
|
||||||
.. Patch 1739906
|
|
||||||
|
|
||||||
* The :func:`glob.glob` function can now return Unicode filenames if
|
* The :func:`glob.glob` function can now return Unicode filenames if
|
||||||
a Unicode path was used and Unicode filenames are matched within the directory.
|
a Unicode path was used and Unicode filenames are matched within the
|
||||||
|
directory. (:issue:`1001604`)
|
||||||
.. Patch #1001604
|
|
||||||
|
|
||||||
* The :mod:`gopherlib` module has been removed.
|
* The :mod:`gopherlib` module has been removed.
|
||||||
|
|
||||||
|
@ -1655,9 +1644,7 @@ complete list of changes, or look through the CVS logs for all the details.
|
||||||
|
|
||||||
* The :mod:`macfs` module has been removed. This in turn required the
|
* The :mod:`macfs` module has been removed. This in turn required the
|
||||||
:func:`macostools.touched` function to be removed because it depended on the
|
:func:`macostools.touched` function to be removed because it depended on the
|
||||||
:mod:`macfs` module.
|
:mod:`macfs` module. (:issue:`1490190`)
|
||||||
|
|
||||||
.. Patch #1490190
|
|
||||||
|
|
||||||
* :class:`mmap` objects now have a :meth:`rfind` method that finds
|
* :class:`mmap` objects now have a :meth:`rfind` method that finds
|
||||||
a substring, beginning at the end of the string and searching
|
a substring, beginning at the end of the string and searching
|
||||||
|
@ -1706,49 +1693,38 @@ complete list of changes, or look through the CVS logs for all the details.
|
||||||
visit the directory's contents. For backward compatibility, the
|
visit the directory's contents. For backward compatibility, the
|
||||||
parameter's default value is false. Note that the function can fall
|
parameter's default value is false. Note that the function can fall
|
||||||
into an infinite recursion if there's a symlink that points to a
|
into an infinite recursion if there's a symlink that points to a
|
||||||
parent directory.
|
parent directory. (:issue:`1273829`)
|
||||||
|
|
||||||
.. Patch 1273829
|
|
||||||
|
|
||||||
* The ``os.environ`` object's :meth:`clear` method will now unset the
|
* The ``os.environ`` object's :meth:`clear` method will now unset the
|
||||||
environment variables using :func:`os.unsetenv` in addition to clearing
|
environment variables using :func:`os.unsetenv` in addition to clearing
|
||||||
the object's keys. (Contributed by Martin Horcicka.)
|
the object's keys. (Contributed by Martin Horcicka; :issue:`1181`.)
|
||||||
|
|
||||||
.. Patch #1181
|
|
||||||
|
|
||||||
* In the :mod:`os.path` module, the :func:`splitext` function
|
* In the :mod:`os.path` module, the :func:`splitext` function
|
||||||
has been changed to not split on leading period characters.
|
has been changed to not split on leading period characters.
|
||||||
This produces better results when operating on Unix's dot-files.
|
This produces better results when operating on Unix's dot-files.
|
||||||
For example, ``os.path.splitext('.ipython')``
|
For example, ``os.path.splitext('.ipython')``
|
||||||
now returns ``('.ipython', '')`` instead of ``('', '.ipython')``.
|
now returns ``('.ipython', '')`` instead of ``('', '.ipython')``.
|
||||||
|
(:issue:`115886`)
|
||||||
.. Bug #115886
|
|
||||||
|
|
||||||
A new function, :func:`relpath(path, start)` returns a relative path
|
A new function, :func:`relpath(path, start)` returns a relative path
|
||||||
from the ``start`` path, if it's supplied, or from the current
|
from the ``start`` path, if it's supplied, or from the current
|
||||||
working directory to the destination ``path``. (Contributed by
|
working directory to the destination ``path``. (Contributed by
|
||||||
Richard Barran.)
|
Richard Barran; :issue:`1339796`.)
|
||||||
|
|
||||||
.. Patch 1339796
|
|
||||||
|
|
||||||
On Windows, :func:`os.path.expandvars` will now expand environment variables
|
On Windows, :func:`os.path.expandvars` will now expand environment variables
|
||||||
in the form "%var%", and "~user" will be expanded into the
|
in the form "%var%", and "~user" will be expanded into the
|
||||||
user's home directory path. (Contributed by Josiah Carlson.)
|
user's home directory path. (Contributed by Josiah Carlson;
|
||||||
|
:issue:`957650`.)
|
||||||
.. Patch 957650
|
|
||||||
|
|
||||||
* The Python debugger provided by the :mod:`pdb` module
|
* The Python debugger provided by the :mod:`pdb` module
|
||||||
gained a new command: "run" restarts the Python program being debugged,
|
gained a new command: "run" restarts the Python program being debugged,
|
||||||
and can optionally take new command-line arguments for the program.
|
and can optionally take new command-line arguments for the program.
|
||||||
(Contributed by Rocky Bernstein.)
|
(Contributed by Rocky Bernstein; :issue:`1393667`.)
|
||||||
|
|
||||||
.. Patch #1393667
|
|
||||||
|
|
||||||
The :func:`post_mortem` function, used to enter debugging of a
|
The :func:`post_mortem` function, used to enter debugging of a
|
||||||
traceback, will now use the traceback returned by :func:`sys.exc_info`
|
traceback, will now use the traceback returned by :func:`sys.exc_info`
|
||||||
if no traceback is supplied. (Contributed by Facundo Batista.)
|
if no traceback is supplied. (Contributed by Facundo Batista;
|
||||||
|
:issue:`1106316`.)
|
||||||
.. Patch #1106316
|
|
||||||
|
|
||||||
* The :mod:`pickletools` module now has an :func:`optimize` function
|
* The :mod:`pickletools` module now has an :func:`optimize` function
|
||||||
that takes a string containing a pickle and removes some unused
|
that takes a string containing a pickle and removes some unused
|
||||||
|
@ -1765,16 +1741,12 @@ complete list of changes, or look through the CVS logs for all the details.
|
||||||
``os.closerange(*low*, *high*)`` efficiently closes all file descriptors
|
``os.closerange(*low*, *high*)`` efficiently closes all file descriptors
|
||||||
from *low* to *high*, ignoring any errors and not including *high* itself.
|
from *low* to *high*, ignoring any errors and not including *high* itself.
|
||||||
This function is now used by the :mod:`subprocess` module to make starting
|
This function is now used by the :mod:`subprocess` module to make starting
|
||||||
processes faster. (Contributed by Georg Brandl.)
|
processes faster. (Contributed by Georg Brandl; :issue:`1663329`.)
|
||||||
|
|
||||||
.. Patch #1663329
|
|
||||||
|
|
||||||
* The :mod:`pyexpat` module's :class:`Parser` objects now allow setting
|
* The :mod:`pyexpat` module's :class:`Parser` objects now allow setting
|
||||||
their :attr:`buffer_size` attribute to change the size of the buffer
|
their :attr:`buffer_size` attribute to change the size of the buffer
|
||||||
used to hold character data.
|
used to hold character data.
|
||||||
(Contributed by Achim Gaedke.)
|
(Contributed by Achim Gaedke; :issue:`1137`.)
|
||||||
|
|
||||||
.. Patch 1137
|
|
||||||
|
|
||||||
* The :mod:`Queue` module now provides queue classes that retrieve entries
|
* The :mod:`Queue` module now provides queue classes that retrieve entries
|
||||||
in different orders. The :class:`PriorityQueue` class stores
|
in different orders. The :class:`PriorityQueue` class stores
|
||||||
|
@ -1788,25 +1760,19 @@ complete list of changes, or look through the CVS logs for all the details.
|
||||||
system, and vice versa. Unfortunately, this change also means
|
system, and vice versa. Unfortunately, this change also means
|
||||||
that Python 2.6's :class:`Random` objects can't be unpickled correctly
|
that Python 2.6's :class:`Random` objects can't be unpickled correctly
|
||||||
on earlier versions of Python.
|
on earlier versions of Python.
|
||||||
(Contributed by Shawn Ligocki.)
|
(Contributed by Shawn Ligocki; :issue:`1727780`.)
|
||||||
|
|
||||||
.. Issue 1727780
|
|
||||||
|
|
||||||
The new ``triangular(low, high, mode)`` function returns random
|
The new ``triangular(low, high, mode)`` function returns random
|
||||||
numbers following a triangular distribution. The returned values
|
numbers following a triangular distribution. The returned values
|
||||||
are between *low* and *high*, not including *high* itself, and
|
are between *low* and *high*, not including *high* itself, and
|
||||||
with *mode* as the mode, the most frequently occurring value
|
with *mode* as the mode, the most frequently occurring value
|
||||||
in the distribution. (Contributed by Wladmir van der Laan and
|
in the distribution. (Contributed by Wladmir van der Laan and
|
||||||
Raymond Hettinger.)
|
Raymond Hettinger; :issue:`1681432`.)
|
||||||
|
|
||||||
.. Patch 1681432
|
|
||||||
|
|
||||||
* Long regular expression searches carried out by the :mod:`re`
|
* Long regular expression searches carried out by the :mod:`re`
|
||||||
module will now check for signals being delivered, so especially
|
module will now check for signals being delivered, so especially
|
||||||
long searches can now be interrupted.
|
long searches can now be interrupted.
|
||||||
(Contributed by Josh Hoyt and Ralf Schmitt.)
|
(Contributed by Josh Hoyt and Ralf Schmitt; :issue:`846388`.)
|
||||||
|
|
||||||
.. Patch 846388
|
|
||||||
|
|
||||||
* The :mod:`rgbimg` module has been removed.
|
* The :mod:`rgbimg` module has been removed.
|
||||||
|
|
||||||
|
@ -1814,9 +1780,7 @@ complete list of changes, or look through the CVS logs for all the details.
|
||||||
have a read-only :attr:`queue` attribute that returns the
|
have a read-only :attr:`queue` attribute that returns the
|
||||||
contents of the scheduler's queue, represented as a list of
|
contents of the scheduler's queue, represented as a list of
|
||||||
named tuples with the fields ``(time, priority, action, argument)``.
|
named tuples with the fields ``(time, priority, action, argument)``.
|
||||||
(Contributed by Raymond Hettinger.)
|
(Contributed by Raymond Hettinger; :issue:`1861`.)
|
||||||
|
|
||||||
.. Patch 1861
|
|
||||||
|
|
||||||
* The :mod:`select` module now has wrapper functions
|
* The :mod:`select` module now has wrapper functions
|
||||||
for the Linux :cfunc:`epoll` and BSD :cfunc:`kqueue` system calls.
|
for the Linux :cfunc:`epoll` and BSD :cfunc:`kqueue` system calls.
|
||||||
|
@ -1824,11 +1788,7 @@ complete list of changes, or look through the CVS logs for all the details.
|
||||||
objects; ``pollobj.modify(fd, eventmask)`` takes a file descriptor
|
objects; ``pollobj.modify(fd, eventmask)`` takes a file descriptor
|
||||||
or file object and an event mask,
|
or file object and an event mask,
|
||||||
|
|
||||||
(Contributed by Christian Heimes.)
|
(Contributed by Christian Heimes; :issue:`1657`.)
|
||||||
|
|
||||||
.. Patch 1657
|
|
||||||
|
|
||||||
.. XXX
|
|
||||||
|
|
||||||
* The :mod:`sets` module has been deprecated; it's better to
|
* The :mod:`sets` module has been deprecated; it's better to
|
||||||
use the built-in :class:`set` and :class:`frozenset` types.
|
use the built-in :class:`set` and :class:`frozenset` types.
|
||||||
|
@ -1850,9 +1810,7 @@ complete list of changes, or look through the CVS logs for all the details.
|
||||||
On receiving a signal, a byte will be written and the main event loop
|
On receiving a signal, a byte will be written and the main event loop
|
||||||
will be woken up, without the need to poll.
|
will be woken up, without the need to poll.
|
||||||
|
|
||||||
(Contributed by Adam Olsen.)
|
(Contributed by Adam Olsen; :issue:`1583`.)
|
||||||
|
|
||||||
.. Patch 1583
|
|
||||||
|
|
||||||
The :func:`siginterrupt` function is now available from Python code,
|
The :func:`siginterrupt` function is now available from Python code,
|
||||||
and allows changing whether signals can interrupt system calls or not.
|
and allows changing whether signals can interrupt system calls or not.
|
||||||
|
@ -1863,10 +1821,7 @@ complete list of changes, or look through the CVS logs for all the details.
|
||||||
allows setting interval timers that will cause a signal to be
|
allows setting interval timers that will cause a signal to be
|
||||||
delivered to the process after a specified time, measured in
|
delivered to the process after a specified time, measured in
|
||||||
wall-clock time, consumed process time, or combined process+system
|
wall-clock time, consumed process time, or combined process+system
|
||||||
time. (Contributed by Guilherme Polo.)
|
time. (Contributed by Guilherme Polo; :issue:`2240`.)
|
||||||
|
|
||||||
.. Patch 2240
|
|
||||||
|
|
||||||
|
|
||||||
* The :mod:`smtplib` module now supports SMTP over SSL thanks to the
|
* The :mod:`smtplib` module now supports SMTP over SSL thanks to the
|
||||||
addition of the :class:`SMTP_SSL` class. This class supports an
|
addition of the :class:`SMTP_SSL` class. This class supports an
|
||||||
|
@ -1881,22 +1836,17 @@ complete list of changes, or look through the CVS logs for all the details.
|
||||||
|
|
||||||
(SMTP over SSL contributed by Monty Taylor; timeout parameter
|
(SMTP over SSL contributed by Monty Taylor; timeout parameter
|
||||||
added by Facundo Batista; LMTP implemented by Leif
|
added by Facundo Batista; LMTP implemented by Leif
|
||||||
Hedstrom.)
|
Hedstrom; :issue:`957003`.)
|
||||||
|
|
||||||
.. Patch #957003
|
|
||||||
|
|
||||||
* In the :mod:`smtplib` module, SMTP.starttls() now complies with :rfc:`3207`
|
* In the :mod:`smtplib` module, SMTP.starttls() now complies with :rfc:`3207`
|
||||||
and forgets any knowledge obtained from the server not obtained from
|
and forgets any knowledge obtained from the server not obtained from
|
||||||
the TLS negotiation itself. (Patch contributed by Bill Fenner.)
|
the TLS negotiation itself. (Patch contributed by Bill Fenner;
|
||||||
|
:issue:`829951`.)
|
||||||
.. Issue 829951
|
|
||||||
|
|
||||||
* The :mod:`socket` module now supports TIPC (http://tipc.sf.net),
|
* The :mod:`socket` module now supports TIPC (http://tipc.sf.net),
|
||||||
a high-performance non-IP-based protocol designed for use in clustered
|
a high-performance non-IP-based protocol designed for use in clustered
|
||||||
environments. TIPC addresses are 4- or 5-tuples.
|
environments. TIPC addresses are 4- or 5-tuples.
|
||||||
(Contributed by Alberto Bertogli.)
|
(Contributed by Alberto Bertogli; :issue:`1646`.)
|
||||||
|
|
||||||
.. Patch #1646
|
|
||||||
|
|
||||||
* The base classes in the :mod:`SocketServer` module now support
|
* The base classes in the :mod:`SocketServer` module now support
|
||||||
calling a :meth:`handle_timeout` method after a span of inactivity
|
calling a :meth:`handle_timeout` method after a span of inactivity
|
||||||
|
@ -1904,9 +1854,8 @@ complete list of changes, or look through the CVS logs for all the details.
|
||||||
by Michael Pomraning.) The :meth:`serve_forever` method
|
by Michael Pomraning.) The :meth:`serve_forever` method
|
||||||
now takes an optional poll interval measured in seconds,
|
now takes an optional poll interval measured in seconds,
|
||||||
controlling how often the server will check for a shutdown request.
|
controlling how often the server will check for a shutdown request.
|
||||||
(Contributed by Pedro Werneck and Jeffrey Yasskin.)
|
(Contributed by Pedro Werneck and Jeffrey Yasskin;
|
||||||
|
:issue:`742598`, :issue:`1193577`.)
|
||||||
.. Patch #742598, #1193577
|
|
||||||
|
|
||||||
* The :mod:`struct` module now supports the C99 :ctype:`_Bool` type,
|
* The :mod:`struct` module now supports the C99 :ctype:`_Bool` type,
|
||||||
using the format character ``'?'``.
|
using the format character ``'?'``.
|
||||||
|
@ -1919,9 +1868,8 @@ complete list of changes, or look through the CVS logs for all the details.
|
||||||
include
|
include
|
||||||
:attr:`mant_dig` (number of digits in the mantissa), :attr:`epsilon`
|
:attr:`mant_dig` (number of digits in the mantissa), :attr:`epsilon`
|
||||||
(smallest difference between 1.0 and the next largest value
|
(smallest difference between 1.0 and the next largest value
|
||||||
representable), and several others. (Contributed by Christian Heimes.)
|
representable), and several others. (Contributed by Christian Heimes;
|
||||||
|
:issue:`1534`.)
|
||||||
.. Patch 1534
|
|
||||||
|
|
||||||
Another new variable, :attr:`dont_write_bytecode`, controls whether Python
|
Another new variable, :attr:`dont_write_bytecode`, controls whether Python
|
||||||
writes any :file:`.pyc` or :file:`.pyo` files on importing a module.
|
writes any :file:`.pyc` or :file:`.pyo` files on importing a module.
|
||||||
|
@ -1943,9 +1891,7 @@ complete list of changes, or look through the CVS logs for all the details.
|
||||||
|
|
||||||
It's now possible to determine the current profiler and tracer functions
|
It's now possible to determine the current profiler and tracer functions
|
||||||
by calling :func:`sys.getprofile` and :func:`sys.gettrace`.
|
by calling :func:`sys.getprofile` and :func:`sys.gettrace`.
|
||||||
(Contributed by Georg Brandl.)
|
(Contributed by Georg Brandl; :issue:`1648`.)
|
||||||
|
|
||||||
.. Patch #1648
|
|
||||||
|
|
||||||
* The :mod:`tarfile` module now supports POSIX.1-2001 (pax) and
|
* The :mod:`tarfile` module now supports POSIX.1-2001 (pax) and
|
||||||
POSIX.1-1988 (ustar) format tarfiles, in addition to the GNU tar
|
POSIX.1-1988 (ustar) format tarfiles, in addition to the GNU tar
|
||||||
|
@ -1979,9 +1925,7 @@ complete list of changes, or look through the CVS logs for all the details.
|
||||||
* The :class:`tempfile.NamedTemporaryFile` class usually deletes
|
* The :class:`tempfile.NamedTemporaryFile` class usually deletes
|
||||||
the temporary file it created when the file is closed. This
|
the temporary file it created when the file is closed. This
|
||||||
behaviour can now be changed by passing ``delete=False`` to the
|
behaviour can now be changed by passing ``delete=False`` to the
|
||||||
constructor. (Contributed by Damien Miller.)
|
constructor. (Contributed by Damien Miller; :issue:`1537850`.)
|
||||||
|
|
||||||
.. Patch #1537850
|
|
||||||
|
|
||||||
A new class, :class:`SpooledTemporaryFile`, behaves like
|
A new class, :class:`SpooledTemporaryFile`, behaves like
|
||||||
a temporary file but stores its data in memory until a maximum size is
|
a temporary file but stores its data in memory until a maximum size is
|
||||||
|
@ -1991,9 +1935,7 @@ complete list of changes, or look through the CVS logs for all the details.
|
||||||
The :class:`NamedTemporaryFile` and :class:`SpooledTemporaryFile` classes
|
The :class:`NamedTemporaryFile` and :class:`SpooledTemporaryFile` classes
|
||||||
both work as context managers, so you can write
|
both work as context managers, so you can write
|
||||||
``with tempfile.NamedTemporaryFile() as tmp: ...``.
|
``with tempfile.NamedTemporaryFile() as tmp: ...``.
|
||||||
(Contributed by Alexander Belopolsky.)
|
(Contributed by Alexander Belopolsky; :issue:`2021`.)
|
||||||
|
|
||||||
.. Issue #2021
|
|
||||||
|
|
||||||
* The :mod:`test.test_support` module now contains a
|
* The :mod:`test.test_support` module now contains a
|
||||||
:func:`EnvironmentVarGuard`
|
:func:`EnvironmentVarGuard`
|
||||||
|
@ -2030,9 +1972,7 @@ complete list of changes, or look through the CVS logs for all the details.
|
||||||
whitespace.
|
whitespace.
|
||||||
>>>
|
>>>
|
||||||
|
|
||||||
(Contributed by Dwayne Bailey.)
|
(Contributed by Dwayne Bailey; :issue:`1581073`.)
|
||||||
|
|
||||||
.. Patch #1581073
|
|
||||||
|
|
||||||
* The :mod:`timeit` module now accepts callables as well as strings
|
* The :mod:`timeit` module now accepts callables as well as strings
|
||||||
for the statement being timed and for the setup code.
|
for the statement being timed and for the setup code.
|
||||||
|
@ -2040,9 +1980,8 @@ complete list of changes, or look through the CVS logs for all the details.
|
||||||
:class:`Timer` instances:
|
:class:`Timer` instances:
|
||||||
``repeat(stmt, setup, time, repeat, number)`` and
|
``repeat(stmt, setup, time, repeat, number)`` and
|
||||||
``timeit(stmt, setup, time, number)`` create an instance and call
|
``timeit(stmt, setup, time, number)`` create an instance and call
|
||||||
the corresponding method. (Contributed by Erik Demaine.)
|
the corresponding method. (Contributed by Erik Demaine;
|
||||||
|
:issue:`1533909`.)
|
||||||
.. Patch #1533909
|
|
||||||
|
|
||||||
* An optional ``timeout`` parameter was added to the
|
* An optional ``timeout`` parameter was added to the
|
||||||
:func:`urllib.urlopen` function and the
|
:func:`urllib.urlopen` function and the
|
||||||
|
@ -2065,9 +2004,7 @@ complete list of changes, or look through the CVS logs for all the details.
|
||||||
:attr:`allow_reuse_address` attribute before calling the
|
:attr:`allow_reuse_address` attribute before calling the
|
||||||
:meth:`server_bind` and :meth:`server_activate` methods to
|
:meth:`server_bind` and :meth:`server_activate` methods to
|
||||||
open the socket and begin listening for connections.
|
open the socket and begin listening for connections.
|
||||||
(Contributed by Peter Parente.)
|
(Contributed by Peter Parente; :issue:`1599845`.)
|
||||||
|
|
||||||
.. Patch 1599845
|
|
||||||
|
|
||||||
:class:`SimpleXMLRPCServer` also has a :attr:`_send_traceback_header`
|
:class:`SimpleXMLRPCServer` also has a :attr:`_send_traceback_header`
|
||||||
attribute; if true, the exception and formatted traceback are returned
|
attribute; if true, the exception and formatted traceback are returned
|
||||||
|
@ -2090,9 +2027,7 @@ complete list of changes, or look through the CVS logs for all the details.
|
||||||
# Unpack all the files in the archive.
|
# Unpack all the files in the archive.
|
||||||
z.extractall()
|
z.extractall()
|
||||||
|
|
||||||
(Contributed by Alan McIntyre.)
|
(Contributed by Alan McIntyre; :issue:`467924`.)
|
||||||
|
|
||||||
.. Patch 467924
|
|
||||||
|
|
||||||
.. ======================================================================
|
.. ======================================================================
|
||||||
.. whole new modules get described in subsections here
|
.. whole new modules get described in subsections here
|
||||||
|
@ -2178,9 +2113,12 @@ Changes to Python's build process and to the C API include:
|
||||||
* The BerkeleyDB module now has a C API object, available as
|
* The BerkeleyDB module now has a C API object, available as
|
||||||
``bsddb.db.api``. This object can be used by other C extensions
|
``bsddb.db.api``. This object can be used by other C extensions
|
||||||
that wish to use the :mod:`bsddb` module for their own purposes.
|
that wish to use the :mod:`bsddb` module for their own purposes.
|
||||||
(Contributed by Duncan Grisby.)
|
(Contributed by Duncan Grisby; :issue:`1551895`.)
|
||||||
|
|
||||||
.. Patch 1551895
|
* The new buffer interface, previously described in
|
||||||
|
`the PEP 3118 section <#pep-3118-revised-buffer-protocol>`__,
|
||||||
|
adds :cfunc:`PyObject_GetBuffer` and :cfunc:`PyObject_ReleaseBuffer`,
|
||||||
|
as well as a few other functions.
|
||||||
|
|
||||||
* Python's use of the C stdio library is now thread-safe, or at least
|
* Python's use of the C stdio library is now thread-safe, or at least
|
||||||
as thread-safe as the underlying library is. A long-standing potential
|
as thread-safe as the underlying library is. A long-standing potential
|
||||||
|
@ -2195,6 +2133,14 @@ Changes to Python's build process and to the C API include:
|
||||||
immediately after the GIL is re-acquired.
|
immediately after the GIL is re-acquired.
|
||||||
(Contributed by Antoine Pitrou and Gregory P. Smith.)
|
(Contributed by Antoine Pitrou and Gregory P. Smith.)
|
||||||
|
|
||||||
|
* Importing modules simultaneously in two different threads no longer
|
||||||
|
deadlocks; it will now raise an :exc:`ImportError`. A new API
|
||||||
|
function, :cfunc:`PyImport_ImportModuleNoBlock`, will look for a
|
||||||
|
module in ``sys.modules`` first, then try to import it after
|
||||||
|
acquiring an import lock. If the import lock is held by another
|
||||||
|
thread, the :exc:`ImportError` is raised.
|
||||||
|
(Contributed by Christian Heimes.)
|
||||||
|
|
||||||
* Several functions return information about the platform's
|
* Several functions return information about the platform's
|
||||||
floating-point support. :cfunc:`PyFloat_GetMax` returns
|
floating-point support. :cfunc:`PyFloat_GetMax` returns
|
||||||
the maximum representable floating point value,
|
the maximum representable floating point value,
|
||||||
|
@ -2204,16 +2150,12 @@ Changes to Python's build process and to the C API include:
|
||||||
``"mant_dig"`` (number of digits in the mantissa), ``"epsilon"``
|
``"mant_dig"`` (number of digits in the mantissa), ``"epsilon"``
|
||||||
(smallest difference between 1.0 and the next largest value
|
(smallest difference between 1.0 and the next largest value
|
||||||
representable), and several others.
|
representable), and several others.
|
||||||
(Contributed by Christian Heimes.)
|
(Contributed by Christian Heimes; :issue:`1534`.)
|
||||||
|
|
||||||
.. Issue 1534
|
|
||||||
|
|
||||||
* Python's C API now includes two functions for case-insensitive string
|
* Python's C API now includes two functions for case-insensitive string
|
||||||
comparisons, ``PyOS_stricmp(char*, char*)``
|
comparisons, ``PyOS_stricmp(char*, char*)``
|
||||||
and ``PyOS_strnicmp(char*, char*, Py_ssize_t)``.
|
and ``PyOS_strnicmp(char*, char*, Py_ssize_t)``.
|
||||||
(Contributed by Christian Heimes.)
|
(Contributed by Christian Heimes; :issue:`1635`.)
|
||||||
|
|
||||||
.. Issue 1635
|
|
||||||
|
|
||||||
* Many C extensions define their own little macro for adding
|
* Many C extensions define their own little macro for adding
|
||||||
integers and strings to the module's dictionary in the
|
integers and strings to the module's dictionary in the
|
||||||
|
@ -2229,14 +2171,11 @@ Changes to Python's build process and to the C API include:
|
||||||
:cmacro:`Py_Refcnt()` became :cmacro:`Py_REFCNT()`.
|
:cmacro:`Py_Refcnt()` became :cmacro:`Py_REFCNT()`.
|
||||||
The mixed-case macros are still available
|
The mixed-case macros are still available
|
||||||
in Python 2.6 for backward compatibility.
|
in Python 2.6 for backward compatibility.
|
||||||
|
(:issue:`1629`)
|
||||||
.. Issue 1629
|
|
||||||
|
|
||||||
* Distutils now places C extensions it builds in a
|
* Distutils now places C extensions it builds in a
|
||||||
different directory when running on a debug version of Python.
|
different directory when running on a debug version of Python.
|
||||||
(Contributed by Collin Winter.)
|
(Contributed by Collin Winter; :issue:`1530959`.)
|
||||||
|
|
||||||
.. Patch 1530959
|
|
||||||
|
|
||||||
* Several basic data types, such as integers and strings, maintain
|
* Several basic data types, such as integers and strings, maintain
|
||||||
internal free lists of objects that can be re-used. The data
|
internal free lists of objects that can be re-used. The data
|
||||||
|
@ -2284,8 +2223,7 @@ Port-Specific Changes: Windows
|
||||||
exposing the :func:`DisableReflectionKey`, :func:`EnableReflectionKey`,
|
exposing the :func:`DisableReflectionKey`, :func:`EnableReflectionKey`,
|
||||||
and :func:`QueryReflectionKey` functions, which enable and disable
|
and :func:`QueryReflectionKey` functions, which enable and disable
|
||||||
registry reflection for 32-bit processes running on 64-bit systems.
|
registry reflection for 32-bit processes running on 64-bit systems.
|
||||||
|
(:issue:`1753245`)
|
||||||
.. Patch 1753245
|
|
||||||
|
|
||||||
* The new default compiler on Windows is Visual Studio 2008 (VS 9.0). The
|
* The new default compiler on Windows is Visual Studio 2008 (VS 9.0). The
|
||||||
build directories for Visual Studio 2003 (VS7.1) and 2005 (VS8.0)
|
build directories for Visual Studio 2003 (VS7.1) and 2005 (VS8.0)
|
||||||
|
@ -2346,21 +2284,21 @@ that may require changes to your code:
|
||||||
the implementation now explicitly checks for this case and raises
|
the implementation now explicitly checks for this case and raises
|
||||||
an :exc:`ImportError`.
|
an :exc:`ImportError`.
|
||||||
|
|
||||||
|
* C API: the :cfunc:`PyImport_Import` and :cfunc:`PyImport_ImportModule`
|
||||||
|
functions now default to absolute imports, not relative imports.
|
||||||
|
This will affect C extensions that import other modules.
|
||||||
|
|
||||||
* The :mod:`socket` module exception :exc:`socket.error` now inherits
|
* The :mod:`socket` module exception :exc:`socket.error` now inherits
|
||||||
from :exc:`IOError`. Previously it wasn't a subclass of
|
from :exc:`IOError`. Previously it wasn't a subclass of
|
||||||
:exc:`StandardError` but now it is, through :exc:`IOError`.
|
:exc:`StandardError` but now it is, through :exc:`IOError`.
|
||||||
(Implemented by Gregory P. Smith.)
|
(Implemented by Gregory P. Smith; :issue:`1706815`.)
|
||||||
|
|
||||||
.. Issue 1706815
|
|
||||||
|
|
||||||
* The :mod:`xmlrpclib` module no longer automatically converts
|
* The :mod:`xmlrpclib` module no longer automatically converts
|
||||||
:class:`datetime.date` and :class:`datetime.time` to the
|
:class:`datetime.date` and :class:`datetime.time` to the
|
||||||
:class:`xmlrpclib.DateTime` type; the conversion semantics were
|
:class:`xmlrpclib.DateTime` type; the conversion semantics were
|
||||||
not necessarily correct for all applications. Code using
|
not necessarily correct for all applications. Code using
|
||||||
:mod:`xmlrpclib` should convert :class:`date` and :class:`time`
|
:mod:`xmlrpclib` should convert :class:`date` and :class:`time`
|
||||||
instances.
|
instances. (:issue:`1330538`)
|
||||||
|
|
||||||
.. Issue 1330538
|
|
||||||
|
|
||||||
* (3.0-warning mode) The :class:`Exception` class now warns
|
* (3.0-warning mode) The :class:`Exception` class now warns
|
||||||
when accessed using slicing or index access; having
|
when accessed using slicing or index access; having
|
||||||
|
@ -2384,5 +2322,6 @@ Acknowledgements
|
||||||
================
|
================
|
||||||
|
|
||||||
The author would like to thank the following people for offering suggestions,
|
The author would like to thank the following people for offering suggestions,
|
||||||
corrections and assistance with various drafts of this article: Jim Jewett.
|
corrections and assistance with various drafts of this article:
|
||||||
|
Georg Brandl, Jim Jewett.
|
||||||
|
|
||||||
|
|
|
@ -93,6 +93,7 @@
|
||||||
#include "iterobject.h"
|
#include "iterobject.h"
|
||||||
#include "genobject.h"
|
#include "genobject.h"
|
||||||
#include "descrobject.h"
|
#include "descrobject.h"
|
||||||
|
#include "warnings.h"
|
||||||
#include "weakrefobject.h"
|
#include "weakrefobject.h"
|
||||||
|
|
||||||
#include "codecs.h"
|
#include "codecs.h"
|
||||||
|
|
|
@ -218,13 +218,6 @@ PyAPI_FUNC(PyObject *) PyErr_NewException(const char *name, PyObject *base,
|
||||||
PyObject *dict);
|
PyObject *dict);
|
||||||
PyAPI_FUNC(void) PyErr_WriteUnraisable(PyObject *);
|
PyAPI_FUNC(void) PyErr_WriteUnraisable(PyObject *);
|
||||||
|
|
||||||
/* Issue a warning or exception */
|
|
||||||
PyAPI_FUNC(int) PyErr_WarnEx(PyObject *category, const char *msg,
|
|
||||||
Py_ssize_t stack_level);
|
|
||||||
PyAPI_FUNC(int) PyErr_WarnExplicit(PyObject *, const char *,
|
|
||||||
const char *, int,
|
|
||||||
const char *, PyObject *);
|
|
||||||
|
|
||||||
/* In sigcheck.c or signalmodule.c */
|
/* In sigcheck.c or signalmodule.c */
|
||||||
PyAPI_FUNC(int) PyErr_CheckSignals(void);
|
PyAPI_FUNC(int) PyErr_CheckSignals(void);
|
||||||
PyAPI_FUNC(void) PyErr_SetInterrupt(void);
|
PyAPI_FUNC(void) PyErr_SetInterrupt(void);
|
||||||
|
|
|
@ -22,6 +22,7 @@ PyAPI_DATA(int) _PySys_CheckInterval;
|
||||||
|
|
||||||
PyAPI_FUNC(void) PySys_ResetWarnOptions(void);
|
PyAPI_FUNC(void) PySys_ResetWarnOptions(void);
|
||||||
PyAPI_FUNC(void) PySys_AddWarnOption(const wchar_t *);
|
PyAPI_FUNC(void) PySys_AddWarnOption(const wchar_t *);
|
||||||
|
PyAPI_FUNC(int) PySys_HasWarnOptions(void);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ typedef struct _traceback {
|
||||||
|
|
||||||
PyAPI_FUNC(int) PyTraceBack_Here(struct _frame *);
|
PyAPI_FUNC(int) PyTraceBack_Here(struct _frame *);
|
||||||
PyAPI_FUNC(int) PyTraceBack_Print(PyObject *, PyObject *);
|
PyAPI_FUNC(int) PyTraceBack_Print(PyObject *, PyObject *);
|
||||||
|
PyAPI_FUNC(int) Py_DisplaySourceLine(PyObject *, const char *, int);
|
||||||
|
|
||||||
/* Reveal traceback type so we can typecheck traceback objects */
|
/* Reveal traceback type so we can typecheck traceback objects */
|
||||||
PyAPI_DATA(PyTypeObject) PyTraceBack_Type;
|
PyAPI_DATA(PyTypeObject) PyTraceBack_Type;
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
#ifndef Py_WARNINGS_H
|
||||||
|
#define Py_WARNINGS_H
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
PyAPI_FUNC(void) _PyWarnings_Init(void);
|
||||||
|
|
||||||
|
PyAPI_FUNC(int) PyErr_WarnEx(PyObject *, const char *, Py_ssize_t);
|
||||||
|
PyAPI_FUNC(int) PyErr_WarnExplicit(PyObject *, const char *, const char *, int,
|
||||||
|
const char *, PyObject *);
|
||||||
|
|
||||||
|
/* DEPRECATED: Use PyErr_WarnEx() instead. */
|
||||||
|
#define PyErr_Warn(category, msg) PyErr_WarnEx(category, msg, 1)
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif /* !Py_WARNINGS_H */
|
||||||
|
|
|
@ -65,7 +65,7 @@ class error_proto(Error): pass # response does not begin with [1-5]
|
||||||
|
|
||||||
# All exceptions (hopefully) that may be raised here and that aren't
|
# All exceptions (hopefully) that may be raised here and that aren't
|
||||||
# (always) programming errors on our side
|
# (always) programming errors on our side
|
||||||
all_errors = (Error, socket.error, IOError, EOFError)
|
all_errors = (Error, IOError, EOFError)
|
||||||
|
|
||||||
|
|
||||||
# Line terminators (we always output CRLF, but accept any of CRLF, CR, LF)
|
# Line terminators (we always output CRLF, but accept any of CRLF, CR, LF)
|
||||||
|
|
|
@ -162,6 +162,7 @@ class BaseTest(unittest.TestCase):
|
||||||
def test_tofromfile(self):
|
def test_tofromfile(self):
|
||||||
a = array.array(self.typecode, 2*self.example)
|
a = array.array(self.typecode, 2*self.example)
|
||||||
self.assertRaises(TypeError, a.tofile)
|
self.assertRaises(TypeError, a.tofile)
|
||||||
|
test_support.unlink(test_support.TESTFN)
|
||||||
f = open(test_support.TESTFN, 'wb')
|
f = open(test_support.TESTFN, 'wb')
|
||||||
try:
|
try:
|
||||||
a.tofile(f)
|
a.tofile(f)
|
||||||
|
|
|
@ -64,6 +64,7 @@ class TestBasic(unittest.TestCase):
|
||||||
self.assertEqual(list(d), [7, 8, 9])
|
self.assertEqual(list(d), [7, 8, 9])
|
||||||
d = deque(range(200), maxlen=10)
|
d = deque(range(200), maxlen=10)
|
||||||
d.append(d)
|
d.append(d)
|
||||||
|
test_support.unlink(test_support.TESTFN)
|
||||||
fo = open(test_support.TESTFN, "w")
|
fo = open(test_support.TESTFN, "w")
|
||||||
try:
|
try:
|
||||||
fo.write(str(d))
|
fo.write(str(d))
|
||||||
|
@ -283,6 +284,7 @@ class TestBasic(unittest.TestCase):
|
||||||
d = deque(range(200))
|
d = deque(range(200))
|
||||||
d.append(d)
|
d.append(d)
|
||||||
try:
|
try:
|
||||||
|
test_support.unlink(test_support.TESTFN)
|
||||||
fo = open(test_support.TESTFN, "w")
|
fo = open(test_support.TESTFN, "w")
|
||||||
print(d, file=fo, end='')
|
print(d, file=fo, end='')
|
||||||
fo.close()
|
fo.close()
|
||||||
|
|
|
@ -354,14 +354,26 @@ class WarningMessage(object):
|
||||||
self.filename = None
|
self.filename = None
|
||||||
self.lineno = None
|
self.lineno = None
|
||||||
|
|
||||||
def _showwarning(self, message, category, filename, lineno, file=None):
|
def _showwarning(self, message, category, filename, lineno, file=None,
|
||||||
|
line=None):
|
||||||
self.message = message
|
self.message = message
|
||||||
self.category = category
|
self.category = category
|
||||||
self.filename = filename
|
self.filename = filename
|
||||||
self.lineno = lineno
|
self.lineno = lineno
|
||||||
|
self.line = line
|
||||||
|
|
||||||
|
def reset(self):
|
||||||
|
self._showwarning(*((None,)*6))
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return ("{message : %r, category : %r, filename : %r, lineno : %s, "
|
||||||
|
"line : %r}" % (self.message,
|
||||||
|
self.category.__name__ if self.category else None,
|
||||||
|
self.filename, self.lineno, self.line))
|
||||||
|
|
||||||
|
|
||||||
@contextlib.contextmanager
|
@contextlib.contextmanager
|
||||||
def catch_warning():
|
def catch_warning(module=warnings):
|
||||||
"""
|
"""
|
||||||
Guard the warnings filter from being permanently changed and record the
|
Guard the warnings filter from being permanently changed and record the
|
||||||
data of the last warning that has been issued.
|
data of the last warning that has been issued.
|
||||||
|
@ -372,15 +384,15 @@ def catch_warning():
|
||||||
warnings.warn("foo")
|
warnings.warn("foo")
|
||||||
assert str(w.message) == "foo"
|
assert str(w.message) == "foo"
|
||||||
"""
|
"""
|
||||||
warning = WarningMessage()
|
warning_obj = WarningMessage()
|
||||||
original_filters = warnings.filters[:]
|
original_filters = module.filters[:]
|
||||||
original_showwarning = warnings.showwarning
|
original_showwarning = module.showwarning
|
||||||
warnings.showwarning = warning._showwarning
|
module.showwarning = warning_obj._showwarning
|
||||||
try:
|
try:
|
||||||
yield warning
|
yield warning_obj
|
||||||
finally:
|
finally:
|
||||||
warnings.showwarning = original_showwarning
|
module.showwarning = original_showwarning
|
||||||
warnings.filters = original_filters
|
module.filters = original_filters
|
||||||
|
|
||||||
class EnvironmentVarGuard(object):
|
class EnvironmentVarGuard(object):
|
||||||
|
|
||||||
|
@ -542,7 +554,7 @@ def bigmemtest(minsize, memuse, overhead=5*_1M):
|
||||||
'minsize' is the minimum useful size for the test (in arbitrary,
|
'minsize' is the minimum useful size for the test (in arbitrary,
|
||||||
test-interpreted units.) 'memuse' is the number of 'bytes per size' for
|
test-interpreted units.) 'memuse' is the number of 'bytes per size' for
|
||||||
the test, or a good estimate of it. 'overhead' specifies fixed overhead,
|
the test, or a good estimate of it. 'overhead' specifies fixed overhead,
|
||||||
independant of the testsize, and defaults to 5Mb.
|
independent of the testsize, and defaults to 5Mb.
|
||||||
|
|
||||||
The decorator tries to guess a good value for 'size' and passes it to
|
The decorator tries to guess a good value for 'size' and passes it to
|
||||||
the decorated test function. If minsize * memuse is more than the
|
the decorated test function. If minsize * memuse is more than the
|
||||||
|
|
|
@ -121,6 +121,7 @@ class UUFileTest(unittest.TestCase):
|
||||||
def test_encode(self):
|
def test_encode(self):
|
||||||
fin = fout = None
|
fin = fout = None
|
||||||
try:
|
try:
|
||||||
|
test_support.unlink(self.tmpin)
|
||||||
fin = open(self.tmpin, 'wb')
|
fin = open(self.tmpin, 'wb')
|
||||||
fin.write(plaintext)
|
fin.write(plaintext)
|
||||||
fin.close()
|
fin.close()
|
||||||
|
@ -150,6 +151,7 @@ class UUFileTest(unittest.TestCase):
|
||||||
def test_decode(self):
|
def test_decode(self):
|
||||||
f = None
|
f = None
|
||||||
try:
|
try:
|
||||||
|
test_support.unlink(self.tmpin)
|
||||||
f = open(self.tmpin, 'wb')
|
f = open(self.tmpin, 'wb')
|
||||||
f.write(encodedtextwrapped(0o644, self.tmpout))
|
f.write(encodedtextwrapped(0o644, self.tmpout))
|
||||||
f.close()
|
f.close()
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import warnings
|
from contextlib import contextmanager
|
||||||
import linecache
|
import linecache
|
||||||
import os
|
import os
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
|
@ -8,112 +8,358 @@ from test import test_support
|
||||||
|
|
||||||
from test import warning_tests
|
from test import warning_tests
|
||||||
|
|
||||||
class TestModule(unittest.TestCase):
|
import warnings as original_warnings
|
||||||
def setUp(self):
|
|
||||||
self.ignored = [w[2].__name__ for w in warnings.filters
|
|
||||||
if w[0]=='ignore' and w[1] is None and w[3] is None]
|
|
||||||
|
|
||||||
def test_warn_default_category(self):
|
sys.modules['_warnings'] = 0
|
||||||
with test_support.catch_warning() as w:
|
del sys.modules['warnings']
|
||||||
|
|
||||||
|
import warnings as py_warnings
|
||||||
|
|
||||||
|
del sys.modules['_warnings']
|
||||||
|
del sys.modules['warnings']
|
||||||
|
|
||||||
|
import warnings as c_warnings
|
||||||
|
|
||||||
|
sys.modules['warnings'] = original_warnings
|
||||||
|
|
||||||
|
|
||||||
|
@contextmanager
|
||||||
|
def warnings_state(module):
|
||||||
|
"""Use a specific warnings implementation in warning_tests."""
|
||||||
|
global __warningregistry__
|
||||||
|
for to_clear in (sys, warning_tests):
|
||||||
|
try:
|
||||||
|
to_clear.__warningregistry__.clear()
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
__warningregistry__.clear()
|
||||||
|
except NameError:
|
||||||
|
pass
|
||||||
|
original_warnings = warning_tests.warnings
|
||||||
|
try:
|
||||||
|
warning_tests.warnings = module
|
||||||
|
yield
|
||||||
|
finally:
|
||||||
|
warning_tests.warnings = original_warnings
|
||||||
|
|
||||||
|
|
||||||
|
class BaseTest(unittest.TestCase):
|
||||||
|
|
||||||
|
"""Basic bookkeeping required for testing."""
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
# The __warningregistry__ needs to be in a pristine state for tests
|
||||||
|
# to work properly.
|
||||||
|
if '__warningregistry__' in globals():
|
||||||
|
del globals()['__warningregistry__']
|
||||||
|
if hasattr(warning_tests, '__warningregistry__'):
|
||||||
|
del warning_tests.__warningregistry__
|
||||||
|
if hasattr(sys, '__warningregistry__'):
|
||||||
|
del sys.__warningregistry__
|
||||||
|
# The 'warnings' module must be explicitly set so that the proper
|
||||||
|
# interaction between _warnings and 'warnings' can be controlled.
|
||||||
|
sys.modules['warnings'] = self.module
|
||||||
|
super(BaseTest, self).setUp()
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
sys.modules['warnings'] = original_warnings
|
||||||
|
super(BaseTest, self).tearDown()
|
||||||
|
|
||||||
|
|
||||||
|
class FilterTests(object):
|
||||||
|
|
||||||
|
"""Testing the filtering functionality."""
|
||||||
|
|
||||||
|
def test_error(self):
|
||||||
|
with test_support.catch_warning(self.module) as w:
|
||||||
|
self.module.resetwarnings()
|
||||||
|
self.module.filterwarnings("error", category=UserWarning)
|
||||||
|
self.assertRaises(UserWarning, self.module.warn,
|
||||||
|
"FilterTests.test_error")
|
||||||
|
|
||||||
|
def test_ignore(self):
|
||||||
|
with test_support.catch_warning(self.module) as w:
|
||||||
|
self.module.resetwarnings()
|
||||||
|
self.module.filterwarnings("ignore", category=UserWarning)
|
||||||
|
self.module.warn("FilterTests.test_ignore", UserWarning)
|
||||||
|
self.assert_(not w.message)
|
||||||
|
|
||||||
|
def test_always(self):
|
||||||
|
with test_support.catch_warning(self.module) as w:
|
||||||
|
self.module.resetwarnings()
|
||||||
|
self.module.filterwarnings("always", category=UserWarning)
|
||||||
|
message = "FilterTests.test_always"
|
||||||
|
self.module.warn(message, UserWarning)
|
||||||
|
self.assert_(message, w.message)
|
||||||
|
w.message = None # Reset.
|
||||||
|
self.module.warn(message, UserWarning)
|
||||||
|
self.assert_(w.message, message)
|
||||||
|
|
||||||
|
def test_default(self):
|
||||||
|
with test_support.catch_warning(self.module) as w:
|
||||||
|
self.module.resetwarnings()
|
||||||
|
self.module.filterwarnings("default", category=UserWarning)
|
||||||
|
message = UserWarning("FilterTests.test_default")
|
||||||
|
for x in range(2):
|
||||||
|
self.module.warn(message, UserWarning)
|
||||||
|
if x == 0:
|
||||||
|
self.assertEquals(w.message, message)
|
||||||
|
w.reset()
|
||||||
|
elif x == 1:
|
||||||
|
self.assert_(not w.message, "unexpected warning: " + str(w))
|
||||||
|
else:
|
||||||
|
raise ValueError("loop variant unhandled")
|
||||||
|
|
||||||
|
def test_module(self):
|
||||||
|
with test_support.catch_warning(self.module) as w:
|
||||||
|
self.module.resetwarnings()
|
||||||
|
self.module.filterwarnings("module", category=UserWarning)
|
||||||
|
message = UserWarning("FilterTests.test_module")
|
||||||
|
self.module.warn(message, UserWarning)
|
||||||
|
self.assertEquals(w.message, message)
|
||||||
|
w.reset()
|
||||||
|
self.module.warn(message, UserWarning)
|
||||||
|
self.assert_(not w.message, "unexpected message: " + str(w))
|
||||||
|
|
||||||
|
def test_once(self):
|
||||||
|
with test_support.catch_warning(self.module) as w:
|
||||||
|
self.module.resetwarnings()
|
||||||
|
self.module.filterwarnings("once", category=UserWarning)
|
||||||
|
message = UserWarning("FilterTests.test_once")
|
||||||
|
self.module.warn_explicit(message, UserWarning, "test_warnings.py",
|
||||||
|
42)
|
||||||
|
self.assertEquals(w.message, message)
|
||||||
|
w.reset()
|
||||||
|
self.module.warn_explicit(message, UserWarning, "test_warnings.py",
|
||||||
|
13)
|
||||||
|
self.assert_(not w.message)
|
||||||
|
self.module.warn_explicit(message, UserWarning, "test_warnings2.py",
|
||||||
|
42)
|
||||||
|
self.assert_(not w.message)
|
||||||
|
|
||||||
|
def test_inheritance(self):
|
||||||
|
with test_support.catch_warning(self.module) as w:
|
||||||
|
self.module.resetwarnings()
|
||||||
|
self.module.filterwarnings("error", category=Warning)
|
||||||
|
self.assertRaises(UserWarning, self.module.warn,
|
||||||
|
"FilterTests.test_inheritance", UserWarning)
|
||||||
|
|
||||||
|
def test_ordering(self):
|
||||||
|
with test_support.catch_warning(self.module) as w:
|
||||||
|
self.module.resetwarnings()
|
||||||
|
self.module.filterwarnings("ignore", category=UserWarning)
|
||||||
|
self.module.filterwarnings("error", category=UserWarning,
|
||||||
|
append=True)
|
||||||
|
w.reset()
|
||||||
|
try:
|
||||||
|
self.module.warn("FilterTests.test_ordering", UserWarning)
|
||||||
|
except UserWarning:
|
||||||
|
self.fail("order handling for actions failed")
|
||||||
|
self.assert_(not w.message)
|
||||||
|
|
||||||
|
def test_filterwarnings(self):
|
||||||
|
# Test filterwarnings().
|
||||||
|
# Implicitly also tests resetwarnings().
|
||||||
|
with test_support.catch_warning(self.module) as w:
|
||||||
|
self.module.filterwarnings("error", "", Warning, "", 0)
|
||||||
|
self.assertRaises(UserWarning, self.module.warn, 'convert to error')
|
||||||
|
|
||||||
|
self.module.resetwarnings()
|
||||||
|
text = 'handle normally'
|
||||||
|
self.module.warn(text)
|
||||||
|
self.assertEqual(str(w.message), text)
|
||||||
|
self.assert_(w.category is UserWarning)
|
||||||
|
|
||||||
|
self.module.filterwarnings("ignore", "", Warning, "", 0)
|
||||||
|
text = 'filtered out'
|
||||||
|
self.module.warn(text)
|
||||||
|
self.assertNotEqual(str(w.message), text)
|
||||||
|
|
||||||
|
self.module.resetwarnings()
|
||||||
|
self.module.filterwarnings("error", "hex*", Warning, "", 0)
|
||||||
|
self.assertRaises(UserWarning, self.module.warn, 'hex/oct')
|
||||||
|
text = 'nonmatching text'
|
||||||
|
self.module.warn(text)
|
||||||
|
self.assertEqual(str(w.message), text)
|
||||||
|
self.assert_(w.category is UserWarning)
|
||||||
|
|
||||||
|
class CFilterTests(BaseTest, FilterTests):
|
||||||
|
module = c_warnings
|
||||||
|
|
||||||
|
class PyFilterTests(BaseTest, FilterTests):
|
||||||
|
module = py_warnings
|
||||||
|
|
||||||
|
|
||||||
|
class WarnTests(unittest.TestCase):
|
||||||
|
|
||||||
|
"""Test warnings.warn() and warnings.warn_explicit()."""
|
||||||
|
|
||||||
|
def test_message(self):
|
||||||
|
with test_support.catch_warning(self.module) as w:
|
||||||
for i in range(4):
|
for i in range(4):
|
||||||
text = 'multi %d' %i # Different text on each call
|
text = 'multi %d' %i # Different text on each call.
|
||||||
warnings.warn(text)
|
self.module.warn(text)
|
||||||
self.assertEqual(str(w.message), text)
|
self.assertEqual(str(w.message), text)
|
||||||
self.assert_(w.category is UserWarning)
|
self.assert_(w.category is UserWarning)
|
||||||
|
|
||||||
def test_warn_specific_category(self):
|
|
||||||
with test_support.catch_warning() as w:
|
|
||||||
text = 'None'
|
|
||||||
for category in [DeprecationWarning, FutureWarning,
|
|
||||||
PendingDeprecationWarning, RuntimeWarning,
|
|
||||||
SyntaxWarning, UserWarning, Warning]:
|
|
||||||
if category.__name__ in self.ignored:
|
|
||||||
text = 'filtered out' + category.__name__
|
|
||||||
warnings.warn(text, category)
|
|
||||||
self.assertNotEqual(w.message, text)
|
|
||||||
else:
|
|
||||||
text = 'unfiltered %s' % category.__name__
|
|
||||||
warnings.warn(text, category)
|
|
||||||
self.assertEqual(str(w.message), text)
|
|
||||||
self.assert_(w.category is category)
|
|
||||||
|
|
||||||
def test_filtering(self):
|
|
||||||
# Test filterwarnings().
|
|
||||||
# Implicitly also tests resetwarnings().
|
|
||||||
with test_support.catch_warning() as w:
|
|
||||||
warnings.filterwarnings("error", "", Warning, "", 0)
|
|
||||||
self.assertRaises(UserWarning, warnings.warn, 'convert to error')
|
|
||||||
|
|
||||||
warnings.resetwarnings()
|
|
||||||
text = 'handle normally'
|
|
||||||
warnings.warn(text)
|
|
||||||
self.assertEqual(str(w.message), text)
|
|
||||||
self.assert_(w.category is UserWarning)
|
|
||||||
|
|
||||||
warnings.filterwarnings("ignore", "", Warning, "", 0)
|
|
||||||
text = 'filtered out'
|
|
||||||
warnings.warn(text)
|
|
||||||
self.assertNotEqual(str(w.message), text)
|
|
||||||
|
|
||||||
warnings.resetwarnings()
|
|
||||||
warnings.filterwarnings("error", "hex*", Warning, "", 0)
|
|
||||||
self.assertRaises(UserWarning, warnings.warn, 'hex/oct')
|
|
||||||
text = 'nonmatching text'
|
|
||||||
warnings.warn(text)
|
|
||||||
self.assertEqual(str(w.message), text)
|
|
||||||
self.assert_(w.category is UserWarning)
|
|
||||||
|
|
||||||
def test_options(self):
|
|
||||||
# Uses the private _setoption() function to test the parsing
|
|
||||||
# of command-line warning arguments
|
|
||||||
with test_support.catch_warning():
|
|
||||||
self.assertRaises(warnings._OptionError,
|
|
||||||
warnings._setoption, '1:2:3:4:5:6')
|
|
||||||
self.assertRaises(warnings._OptionError,
|
|
||||||
warnings._setoption, 'bogus::Warning')
|
|
||||||
self.assertRaises(warnings._OptionError,
|
|
||||||
warnings._setoption, 'ignore:2::4:-5')
|
|
||||||
warnings._setoption('error::Warning::0')
|
|
||||||
self.assertRaises(UserWarning, warnings.warn, 'convert to error')
|
|
||||||
|
|
||||||
def test_filename(self):
|
def test_filename(self):
|
||||||
with test_support.catch_warning() as w:
|
with warnings_state(self.module):
|
||||||
warning_tests.inner("spam1")
|
with test_support.catch_warning(self.module) as w:
|
||||||
self.assertEqual(os.path.basename(w.filename), "warning_tests.py")
|
warning_tests.inner("spam1")
|
||||||
warning_tests.outer("spam2")
|
self.assertEqual(os.path.basename(w.filename), "warning_tests.py")
|
||||||
self.assertEqual(os.path.basename(w.filename), "warning_tests.py")
|
warning_tests.outer("spam2")
|
||||||
|
self.assertEqual(os.path.basename(w.filename), "warning_tests.py")
|
||||||
|
|
||||||
def test_stacklevel(self):
|
def test_stacklevel(self):
|
||||||
# Test stacklevel argument
|
# Test stacklevel argument
|
||||||
# make sure all messages are different, so the warning won't be skipped
|
# make sure all messages are different, so the warning won't be skipped
|
||||||
with test_support.catch_warning() as w:
|
with warnings_state(self.module):
|
||||||
warning_tests.inner("spam3", stacklevel=1)
|
with test_support.catch_warning(self.module) as w:
|
||||||
self.assertEqual(os.path.basename(w.filename), "warning_tests.py")
|
warning_tests.inner("spam3", stacklevel=1)
|
||||||
warning_tests.outer("spam4", stacklevel=1)
|
self.assertEqual(os.path.basename(w.filename), "warning_tests.py")
|
||||||
self.assertEqual(os.path.basename(w.filename), "warning_tests.py")
|
warning_tests.outer("spam4", stacklevel=1)
|
||||||
|
self.assertEqual(os.path.basename(w.filename), "warning_tests.py")
|
||||||
|
|
||||||
warning_tests.inner("spam5", stacklevel=2)
|
warning_tests.inner("spam5", stacklevel=2)
|
||||||
self.assertEqual(os.path.basename(w.filename), "test_warnings.py")
|
self.assertEqual(os.path.basename(w.filename), "test_warnings.py")
|
||||||
warning_tests.outer("spam6", stacklevel=2)
|
warning_tests.outer("spam6", stacklevel=2)
|
||||||
self.assertEqual(os.path.basename(w.filename), "warning_tests.py")
|
self.assertEqual(os.path.basename(w.filename), "warning_tests.py")
|
||||||
|
|
||||||
warning_tests.inner("spam7", stacklevel=9999)
|
warning_tests.inner("spam7", stacklevel=9999)
|
||||||
self.assertEqual(os.path.basename(w.filename), "sys")
|
self.assertEqual(os.path.basename(w.filename), "sys")
|
||||||
|
|
||||||
|
|
||||||
|
class CWarnTests(BaseTest, WarnTests):
|
||||||
|
module = c_warnings
|
||||||
|
|
||||||
|
class PyWarnTests(BaseTest, WarnTests):
|
||||||
|
module = py_warnings
|
||||||
|
|
||||||
|
|
||||||
|
class WCmdLineTests(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_improper_input(self):
|
||||||
|
# Uses the private _setoption() function to test the parsing
|
||||||
|
# of command-line warning arguments
|
||||||
|
with test_support.catch_warning(self.module):
|
||||||
|
self.assertRaises(self.module._OptionError,
|
||||||
|
self.module._setoption, '1:2:3:4:5:6')
|
||||||
|
self.assertRaises(self.module._OptionError,
|
||||||
|
self.module._setoption, 'bogus::Warning')
|
||||||
|
self.assertRaises(self.module._OptionError,
|
||||||
|
self.module._setoption, 'ignore:2::4:-5')
|
||||||
|
self.module._setoption('error::Warning::0')
|
||||||
|
self.assertRaises(UserWarning, self.module.warn, 'convert to error')
|
||||||
|
|
||||||
|
class CWCmdLineTests(BaseTest, WCmdLineTests):
|
||||||
|
module = c_warnings
|
||||||
|
|
||||||
|
class PyWCmdLineTests(BaseTest, WCmdLineTests):
|
||||||
|
module = py_warnings
|
||||||
|
|
||||||
|
|
||||||
|
class _WarningsTests(BaseTest):
|
||||||
|
|
||||||
|
"""Tests specific to the _warnings module."""
|
||||||
|
|
||||||
|
module = c_warnings
|
||||||
|
|
||||||
|
def test_filter(self):
|
||||||
|
# Everything should function even if 'filters' is not in warnings.
|
||||||
|
with test_support.catch_warning(self.module) as w:
|
||||||
|
self.module.filterwarnings("error", "", Warning, "", 0)
|
||||||
|
self.assertRaises(UserWarning, self.module.warn,
|
||||||
|
'convert to error')
|
||||||
|
del self.module.filters
|
||||||
|
self.assertRaises(UserWarning, self.module.warn,
|
||||||
|
'convert to error')
|
||||||
|
|
||||||
|
def test_onceregistry(self):
|
||||||
|
# Replacing or removing the onceregistry should be okay.
|
||||||
|
global __warningregistry__
|
||||||
|
message = UserWarning('onceregistry test')
|
||||||
|
try:
|
||||||
|
original_registry = self.module.onceregistry
|
||||||
|
__warningregistry__ = {}
|
||||||
|
with test_support.catch_warning(self.module) as w:
|
||||||
|
self.module.resetwarnings()
|
||||||
|
self.module.filterwarnings("once", category=UserWarning)
|
||||||
|
self.module.warn_explicit(message, UserWarning, "file", 42)
|
||||||
|
self.failUnlessEqual(w.message, message)
|
||||||
|
w.reset()
|
||||||
|
self.module.warn_explicit(message, UserWarning, "file", 42)
|
||||||
|
self.assert_(not w.message)
|
||||||
|
# Test the resetting of onceregistry.
|
||||||
|
self.module.onceregistry = {}
|
||||||
|
__warningregistry__ = {}
|
||||||
|
self.module.warn('onceregistry test')
|
||||||
|
self.failUnlessEqual(w.message.args, message.args)
|
||||||
|
# Removal of onceregistry is okay.
|
||||||
|
w.reset()
|
||||||
|
del self.module.onceregistry
|
||||||
|
__warningregistry__ = {}
|
||||||
|
self.module.warn_explicit(message, UserWarning, "file", 42)
|
||||||
|
self.failUnless(not w.message)
|
||||||
|
finally:
|
||||||
|
self.module.onceregistry = original_registry
|
||||||
|
|
||||||
|
def test_showwarning_missing(self):
|
||||||
|
# Test that showwarning() missing is okay.
|
||||||
|
text = 'del showwarning test'
|
||||||
|
with test_support.catch_warning(self.module):
|
||||||
|
self.module.filterwarnings("always", category=UserWarning)
|
||||||
|
del self.module.showwarning
|
||||||
|
with test_support.captured_output('stderr') as stream:
|
||||||
|
self.module.warn(text)
|
||||||
|
result = stream.getvalue()
|
||||||
|
self.failUnless(text in result)
|
||||||
|
|
||||||
|
def test_show_warning_output(self):
|
||||||
|
# With showarning() missing, make sure that output is okay.
|
||||||
|
text = 'test show_warning'
|
||||||
|
with test_support.catch_warning(self.module):
|
||||||
|
self.module.filterwarnings("always", category=UserWarning)
|
||||||
|
del self.module.showwarning
|
||||||
|
with test_support.captured_output('stderr') as stream:
|
||||||
|
warning_tests.inner(text)
|
||||||
|
result = stream.getvalue()
|
||||||
|
self.failUnlessEqual(result.count('\n'), 2,
|
||||||
|
"Too many newlines in %r" % result)
|
||||||
|
first_line, second_line = result.split('\n', 1)
|
||||||
|
expected_file = os.path.splitext(warning_tests.__file__)[0] + '.py'
|
||||||
|
path, line, warning_class, message = first_line.split(':')
|
||||||
|
line = int(line)
|
||||||
|
self.failUnlessEqual(expected_file, path)
|
||||||
|
self.failUnlessEqual(warning_class, ' ' + UserWarning.__name__)
|
||||||
|
self.failUnlessEqual(message, ' ' + text)
|
||||||
|
expected_line = ' ' + linecache.getline(path, line).strip() + '\n'
|
||||||
|
assert expected_line
|
||||||
|
self.failUnlessEqual(second_line, expected_line)
|
||||||
|
|
||||||
|
|
||||||
class WarningsDisplayTests(unittest.TestCase):
|
class WarningsDisplayTests(unittest.TestCase):
|
||||||
|
|
||||||
|
"""Test the displaying of warnings and the ability to overload functions
|
||||||
|
related to displaying warnings."""
|
||||||
|
|
||||||
def test_formatwarning(self):
|
def test_formatwarning(self):
|
||||||
message = "msg"
|
message = "msg"
|
||||||
category = Warning
|
category = Warning
|
||||||
file_name = os.path.splitext(warning_tests.__file__)[0] + '.py'
|
file_name = os.path.splitext(warning_tests.__file__)[0] + '.py'
|
||||||
line_num = 3
|
line_num = 3
|
||||||
file_line = linecache.getline(file_name, line_num).strip()
|
file_line = linecache.getline(file_name, line_num).strip()
|
||||||
expect = "%s:%s: %s: %s\n %s\n" % (file_name, line_num, category.__name__,
|
format = "%s:%s: %s: %s\n %s\n"
|
||||||
message, file_line)
|
expect = format % (file_name, line_num, category.__name__, message,
|
||||||
self.failUnlessEqual(warnings.formatwarning(message, category,
|
file_line)
|
||||||
file_name, line_num),
|
self.failUnlessEqual(expect, self.module.formatwarning(message,
|
||||||
expect)
|
category, file_name, line_num))
|
||||||
|
# Test the 'line' argument.
|
||||||
|
file_line += " for the win!"
|
||||||
|
expect = format % (file_name, line_num, category.__name__, message,
|
||||||
|
file_line)
|
||||||
|
self.failUnlessEqual(expect, self.module.formatwarning(message,
|
||||||
|
category, file_name, line_num, file_line))
|
||||||
|
|
||||||
def test_showwarning(self):
|
def test_showwarning(self):
|
||||||
file_name = os.path.splitext(warning_tests.__file__)[0] + '.py'
|
file_name = os.path.splitext(warning_tests.__file__)[0] + '.py'
|
||||||
|
@ -122,22 +368,37 @@ class WarningsDisplayTests(unittest.TestCase):
|
||||||
message = 'msg'
|
message = 'msg'
|
||||||
category = Warning
|
category = Warning
|
||||||
file_object = StringIO()
|
file_object = StringIO()
|
||||||
expect = warnings.formatwarning(message, category, file_name, line_num)
|
expect = self.module.formatwarning(message, category, file_name,
|
||||||
warnings.showwarning(message, category, file_name, line_num,
|
line_num)
|
||||||
|
self.module.showwarning(message, category, file_name, line_num,
|
||||||
file_object)
|
file_object)
|
||||||
self.failUnlessEqual(file_object.getvalue(), expect)
|
self.failUnlessEqual(file_object.getvalue(), expect)
|
||||||
|
# Test 'line' argument.
|
||||||
|
expected_file_line += "for the win!"
|
||||||
|
expect = self.module.formatwarning(message, category, file_name,
|
||||||
|
line_num, expected_file_line)
|
||||||
|
file_object = StringIO()
|
||||||
|
self.module.showwarning(message, category, file_name, line_num,
|
||||||
|
file_object, expected_file_line)
|
||||||
|
self.failUnlessEqual(expect, file_object.getvalue())
|
||||||
|
|
||||||
|
class CWarningsDisplayTests(BaseTest, WarningsDisplayTests):
|
||||||
|
module = c_warnings
|
||||||
|
|
||||||
|
class PyWarningsDisplayTests(BaseTest, WarningsDisplayTests):
|
||||||
|
module = py_warnings
|
||||||
|
|
||||||
|
|
||||||
def test_main(verbose=None):
|
def test_main():
|
||||||
# Obscure hack so that this test passes after reloads or repeated calls
|
test_support.run_unittest(CFilterTests,
|
||||||
# to test_main (regrtest -R).
|
PyFilterTests,
|
||||||
if '__warningregistry__' in globals():
|
CWarnTests,
|
||||||
del globals()['__warningregistry__']
|
PyWarnTests,
|
||||||
if hasattr(warning_tests, '__warningregistry__'):
|
CWCmdLineTests, PyWCmdLineTests,
|
||||||
del warning_tests.__warningregistry__
|
_WarningsTests,
|
||||||
if hasattr(sys, '__warningregistry__'):
|
CWarningsDisplayTests, PyWarningsDisplayTests,
|
||||||
del sys.__warningregistry__
|
)
|
||||||
test_support.run_unittest(TestModule, WarningsDisplayTests)
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
test_main(verbose=True)
|
test_main()
|
||||||
|
|
271
Lib/warnings.py
271
Lib/warnings.py
|
@ -3,143 +3,30 @@
|
||||||
# Note: function level imports should *not* be used
|
# Note: function level imports should *not* be used
|
||||||
# in this module as it may cause import lock deadlock.
|
# in this module as it may cause import lock deadlock.
|
||||||
# See bug 683658.
|
# See bug 683658.
|
||||||
import sys
|
|
||||||
import linecache
|
import linecache
|
||||||
|
import sys
|
||||||
|
import types
|
||||||
|
|
||||||
__all__ = ["warn", "showwarning", "formatwarning", "filterwarnings",
|
__all__ = ["warn", "showwarning", "formatwarning", "filterwarnings",
|
||||||
"resetwarnings"]
|
"resetwarnings"]
|
||||||
|
|
||||||
# filters contains a sequence of filter 5-tuples
|
|
||||||
# The components of the 5-tuple are:
|
|
||||||
# - an action: error, ignore, always, default, module, or once
|
|
||||||
# - a compiled regex that must match the warning message
|
|
||||||
# - a class representing the warning category
|
|
||||||
# - a compiled regex that must match the module that is being warned
|
|
||||||
# - a line number for the line being warning, or 0 to mean any line
|
|
||||||
# If either if the compiled regexs are None, match anything.
|
|
||||||
filters = []
|
|
||||||
defaultaction = "default"
|
|
||||||
onceregistry = {}
|
|
||||||
|
|
||||||
def warn(message, category=None, stacklevel=1):
|
def showwarning(message, category, filename, lineno, file=None, line=None):
|
||||||
"""Issue a warning, or maybe ignore it or raise an exception."""
|
|
||||||
# Check if message is already a Warning object
|
|
||||||
if isinstance(message, Warning):
|
|
||||||
category = message.__class__
|
|
||||||
# Check category argument
|
|
||||||
if category is None:
|
|
||||||
category = UserWarning
|
|
||||||
assert issubclass(category, Warning)
|
|
||||||
# Get context information
|
|
||||||
try:
|
|
||||||
caller = sys._getframe(stacklevel)
|
|
||||||
except ValueError:
|
|
||||||
globals = sys.__dict__
|
|
||||||
lineno = 1
|
|
||||||
else:
|
|
||||||
globals = caller.f_globals
|
|
||||||
lineno = caller.f_lineno
|
|
||||||
if '__name__' in globals:
|
|
||||||
module = globals['__name__']
|
|
||||||
else:
|
|
||||||
module = "<string>"
|
|
||||||
filename = globals.get('__file__')
|
|
||||||
if filename:
|
|
||||||
fnl = filename.lower()
|
|
||||||
if fnl.endswith((".pyc", ".pyo")):
|
|
||||||
filename = filename[:-1]
|
|
||||||
else:
|
|
||||||
if module == "__main__":
|
|
||||||
try:
|
|
||||||
filename = sys.argv[0]
|
|
||||||
except AttributeError:
|
|
||||||
# embedded interpreters don't have sys.argv, see bug #839151
|
|
||||||
filename = '__main__'
|
|
||||||
if not filename:
|
|
||||||
filename = module
|
|
||||||
registry = globals.setdefault("__warningregistry__", {})
|
|
||||||
warn_explicit(message, category, filename, lineno, module, registry,
|
|
||||||
globals)
|
|
||||||
|
|
||||||
def warn_explicit(message, category, filename, lineno,
|
|
||||||
module=None, registry=None, module_globals=None):
|
|
||||||
if module is None:
|
|
||||||
module = filename or "<unknown>"
|
|
||||||
if module[-3:].lower() == ".py":
|
|
||||||
module = module[:-3] # XXX What about leading pathname?
|
|
||||||
if registry is None:
|
|
||||||
registry = {}
|
|
||||||
if isinstance(message, Warning):
|
|
||||||
text = str(message)
|
|
||||||
category = message.__class__
|
|
||||||
else:
|
|
||||||
text = message
|
|
||||||
message = category(message)
|
|
||||||
key = (text, category, lineno)
|
|
||||||
# Quick test for common case
|
|
||||||
if registry.get(key):
|
|
||||||
return
|
|
||||||
# Search the filters
|
|
||||||
for item in filters:
|
|
||||||
action, msg, cat, mod, ln = item
|
|
||||||
if ((msg is None or msg.match(text)) and
|
|
||||||
issubclass(category, cat) and
|
|
||||||
(mod is None or mod.match(module)) and
|
|
||||||
(ln == 0 or lineno == ln)):
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
action = defaultaction
|
|
||||||
# Early exit actions
|
|
||||||
if action == "ignore":
|
|
||||||
registry[key] = 1
|
|
||||||
return
|
|
||||||
|
|
||||||
# Prime the linecache for formatting, in case the
|
|
||||||
# "file" is actually in a zipfile or something.
|
|
||||||
linecache.getlines(filename, module_globals)
|
|
||||||
|
|
||||||
if action == "error":
|
|
||||||
raise message
|
|
||||||
# Other actions
|
|
||||||
if action == "once":
|
|
||||||
registry[key] = 1
|
|
||||||
oncekey = (text, category)
|
|
||||||
if onceregistry.get(oncekey):
|
|
||||||
return
|
|
||||||
onceregistry[oncekey] = 1
|
|
||||||
elif action == "always":
|
|
||||||
pass
|
|
||||||
elif action == "module":
|
|
||||||
registry[key] = 1
|
|
||||||
altkey = (text, category, 0)
|
|
||||||
if registry.get(altkey):
|
|
||||||
return
|
|
||||||
registry[altkey] = 1
|
|
||||||
elif action == "default":
|
|
||||||
registry[key] = 1
|
|
||||||
else:
|
|
||||||
# Unrecognized actions are errors
|
|
||||||
raise RuntimeError(
|
|
||||||
"Unrecognized action (%r) in warnings.filters:\n %s" %
|
|
||||||
(action, item))
|
|
||||||
# Print message and context
|
|
||||||
showwarning(message, category, filename, lineno)
|
|
||||||
|
|
||||||
def showwarning(message, category, filename, lineno, file=None):
|
|
||||||
"""Hook to write a warning to a file; replace if you like."""
|
"""Hook to write a warning to a file; replace if you like."""
|
||||||
if file is None:
|
if file is None:
|
||||||
file = sys.stderr
|
file = sys.stderr
|
||||||
try:
|
try:
|
||||||
file.write(formatwarning(message, category, filename, lineno))
|
file.write(formatwarning(message, category, filename, lineno, line))
|
||||||
except IOError:
|
except IOError:
|
||||||
pass # the file (probably stderr) is invalid - this warning gets lost.
|
pass # the file (probably stderr) is invalid - this warning gets lost.
|
||||||
|
|
||||||
def formatwarning(message, category, filename, lineno):
|
def formatwarning(message, category, filename, lineno, line=None):
|
||||||
"""Function to format a warning the standard way."""
|
"""Function to format a warning the standard way."""
|
||||||
s = "%s:%s: %s: %s\n" % (filename, lineno, category.__name__, message)
|
s = "%s:%s: %s: %s\n" % (filename, lineno, category.__name__, message)
|
||||||
line = linecache.getline(filename, lineno).strip()
|
line = linecache.getline(filename, lineno) if line is None else line
|
||||||
if line:
|
if line:
|
||||||
s = s + " " + line + "\n"
|
line = line.strip()
|
||||||
|
s += " %s\n" % line
|
||||||
return s
|
return s
|
||||||
|
|
||||||
def filterwarnings(action, message="", category=Warning, module="", lineno=0,
|
def filterwarnings(action, message="", category=Warning, module="", lineno=0,
|
||||||
|
@ -257,7 +144,145 @@ def _getcategory(category):
|
||||||
raise _OptionError("invalid warning category: %r" % (category,))
|
raise _OptionError("invalid warning category: %r" % (category,))
|
||||||
return cat
|
return cat
|
||||||
|
|
||||||
|
|
||||||
|
# Code typically replaced by _warnings
|
||||||
|
def warn(message, category=None, stacklevel=1):
|
||||||
|
"""Issue a warning, or maybe ignore it or raise an exception."""
|
||||||
|
# Check if message is already a Warning object
|
||||||
|
if isinstance(message, Warning):
|
||||||
|
category = message.__class__
|
||||||
|
# Check category argument
|
||||||
|
if category is None:
|
||||||
|
category = UserWarning
|
||||||
|
assert issubclass(category, Warning)
|
||||||
|
# Get context information
|
||||||
|
try:
|
||||||
|
caller = sys._getframe(stacklevel)
|
||||||
|
except ValueError:
|
||||||
|
globals = sys.__dict__
|
||||||
|
lineno = 1
|
||||||
|
else:
|
||||||
|
globals = caller.f_globals
|
||||||
|
lineno = caller.f_lineno
|
||||||
|
if '__name__' in globals:
|
||||||
|
module = globals['__name__']
|
||||||
|
else:
|
||||||
|
module = "<string>"
|
||||||
|
filename = globals.get('__file__')
|
||||||
|
if filename:
|
||||||
|
fnl = filename.lower()
|
||||||
|
if fnl.endswith((".pyc", ".pyo")):
|
||||||
|
filename = filename[:-1]
|
||||||
|
else:
|
||||||
|
if module == "__main__":
|
||||||
|
try:
|
||||||
|
filename = sys.argv[0]
|
||||||
|
except AttributeError:
|
||||||
|
# embedded interpreters don't have sys.argv, see bug #839151
|
||||||
|
filename = '__main__'
|
||||||
|
if not filename:
|
||||||
|
filename = module
|
||||||
|
registry = globals.setdefault("__warningregistry__", {})
|
||||||
|
warn_explicit(message, category, filename, lineno, module, registry,
|
||||||
|
globals)
|
||||||
|
|
||||||
|
def warn_explicit(message, category, filename, lineno,
|
||||||
|
module=None, registry=None, module_globals=None):
|
||||||
|
if module is None:
|
||||||
|
module = filename or "<unknown>"
|
||||||
|
if module[-3:].lower() == ".py":
|
||||||
|
module = module[:-3] # XXX What about leading pathname?
|
||||||
|
if registry is None:
|
||||||
|
registry = {}
|
||||||
|
if isinstance(message, Warning):
|
||||||
|
text = str(message)
|
||||||
|
category = message.__class__
|
||||||
|
else:
|
||||||
|
text = message
|
||||||
|
message = category(message)
|
||||||
|
key = (text, category, lineno)
|
||||||
|
# Quick test for common case
|
||||||
|
if registry.get(key):
|
||||||
|
return
|
||||||
|
# Search the filters
|
||||||
|
for item in filters:
|
||||||
|
action, msg, cat, mod, ln = item
|
||||||
|
if ((msg is None or msg.match(text)) and
|
||||||
|
issubclass(category, cat) and
|
||||||
|
(mod is None or mod.match(module)) and
|
||||||
|
(ln == 0 or lineno == ln)):
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
action = defaultaction
|
||||||
|
# Early exit actions
|
||||||
|
if action == "ignore":
|
||||||
|
registry[key] = 1
|
||||||
|
return
|
||||||
|
|
||||||
|
# Prime the linecache for formatting, in case the
|
||||||
|
# "file" is actually in a zipfile or something.
|
||||||
|
linecache.getlines(filename, module_globals)
|
||||||
|
|
||||||
|
if action == "error":
|
||||||
|
raise message
|
||||||
|
# Other actions
|
||||||
|
if action == "once":
|
||||||
|
registry[key] = 1
|
||||||
|
oncekey = (text, category)
|
||||||
|
if onceregistry.get(oncekey):
|
||||||
|
return
|
||||||
|
onceregistry[oncekey] = 1
|
||||||
|
elif action == "always":
|
||||||
|
pass
|
||||||
|
elif action == "module":
|
||||||
|
registry[key] = 1
|
||||||
|
altkey = (text, category, 0)
|
||||||
|
if registry.get(altkey):
|
||||||
|
return
|
||||||
|
registry[altkey] = 1
|
||||||
|
elif action == "default":
|
||||||
|
registry[key] = 1
|
||||||
|
else:
|
||||||
|
# Unrecognized actions are errors
|
||||||
|
raise RuntimeError(
|
||||||
|
"Unrecognized action (%r) in warnings.filters:\n %s" %
|
||||||
|
(action, item))
|
||||||
|
# Print message and context
|
||||||
|
showwarning(message, category, filename, lineno)
|
||||||
|
|
||||||
|
|
||||||
|
# filters contains a sequence of filter 5-tuples
|
||||||
|
# The components of the 5-tuple are:
|
||||||
|
# - an action: error, ignore, always, default, module, or once
|
||||||
|
# - a compiled regex that must match the warning message
|
||||||
|
# - a class representing the warning category
|
||||||
|
# - a compiled regex that must match the module that is being warned
|
||||||
|
# - a line number for the line being warning, or 0 to mean any line
|
||||||
|
# If either if the compiled regexs are None, match anything.
|
||||||
|
_warnings_defaults = False
|
||||||
|
try:
|
||||||
|
from _warnings import (filters, default_action, once_registry,
|
||||||
|
warn, warn_explicit)
|
||||||
|
defaultaction = default_action
|
||||||
|
onceregistry = once_registry
|
||||||
|
_warnings_defaults = True
|
||||||
|
except ImportError:
|
||||||
|
filters = []
|
||||||
|
defaultaction = "default"
|
||||||
|
onceregistry = {}
|
||||||
|
|
||||||
|
|
||||||
# Module initialization
|
# Module initialization
|
||||||
_processoptions(sys.warnoptions)
|
_processoptions(sys.warnoptions)
|
||||||
simplefilter("ignore", category=PendingDeprecationWarning, append=1)
|
if not _warnings_defaults:
|
||||||
simplefilter("ignore", category=ImportWarning, append=1)
|
simplefilter("ignore", category=PendingDeprecationWarning, append=1)
|
||||||
|
simplefilter("ignore", category=ImportWarning, append=1)
|
||||||
|
bytes_warning = sys.flags.bytes_warning
|
||||||
|
if bytes_warning > 1:
|
||||||
|
bytes_action = "error"
|
||||||
|
elif bytes_warning:
|
||||||
|
bytes_action = "default"
|
||||||
|
else:
|
||||||
|
bytes_action = "ignore"
|
||||||
|
simplefilter(bytes_action, category=BytesWarning, append=1)
|
||||||
|
del _warnings_defaults
|
||||||
|
|
|
@ -175,6 +175,10 @@ LIBOBJS= @LIBOBJS@
|
||||||
PYTHON= python$(EXE)
|
PYTHON= python$(EXE)
|
||||||
BUILDPYTHON= python$(BUILDEXE)
|
BUILDPYTHON= python$(BUILDEXE)
|
||||||
|
|
||||||
|
# The task to run while instrument when building the profile-opt target
|
||||||
|
PROFILE_TASK= Tools/pybench/pybench.py -n 2 --with-gc --with-syscheck
|
||||||
|
#PROFILE_TASK= Lib/test/regrtest.py
|
||||||
|
|
||||||
# === Definitions added by makesetup ===
|
# === Definitions added by makesetup ===
|
||||||
|
|
||||||
|
|
||||||
|
@ -244,6 +248,7 @@ ASDLGEN= $(srcdir)/Parser/asdl_c.py
|
||||||
##########################################################################
|
##########################################################################
|
||||||
# Python
|
# Python
|
||||||
PYTHON_OBJS= \
|
PYTHON_OBJS= \
|
||||||
|
Python/_warnings.o \
|
||||||
Python/Python-ast.o \
|
Python/Python-ast.o \
|
||||||
Python/asdl.o \
|
Python/asdl.o \
|
||||||
Python/ast.o \
|
Python/ast.o \
|
||||||
|
@ -346,6 +351,27 @@ LIBRARY_OBJS= \
|
||||||
all: build_all
|
all: build_all
|
||||||
build_all: $(BUILDPYTHON) oldsharedmods sharedmods
|
build_all: $(BUILDPYTHON) oldsharedmods sharedmods
|
||||||
|
|
||||||
|
# Compile a binary with gcc profile guided optimization.
|
||||||
|
profile-opt:
|
||||||
|
@echo "Building with support for profile generation:"
|
||||||
|
$(MAKE) clean
|
||||||
|
$(MAKE) build_all_generate_profile
|
||||||
|
@echo "Running benchmark to generate profile data:"
|
||||||
|
$(MAKE) profile-removal
|
||||||
|
$(MAKE) run_profile_task
|
||||||
|
@echo "Rebuilding with profile guided optimizations:"
|
||||||
|
$(MAKE) clean
|
||||||
|
$(MAKE) build_all_use_profile
|
||||||
|
|
||||||
|
build_all_generate_profile:
|
||||||
|
$(MAKE) all CFLAGS="$(CFLAGS) -fprofile-generate" LIBS="$(LIBS) -lgcov"
|
||||||
|
|
||||||
|
run_profile_task:
|
||||||
|
./$(BUILDPYTHON) $(PROFILE_TASK)
|
||||||
|
|
||||||
|
build_all_use_profile:
|
||||||
|
$(MAKE) all CFLAGS="$(CFLAGS) -fprofile-use"
|
||||||
|
|
||||||
# Build the interpreter
|
# Build the interpreter
|
||||||
$(BUILDPYTHON): Modules/python.o $(LIBRARY) $(LDLIBRARY)
|
$(BUILDPYTHON): Modules/python.o $(LIBRARY) $(LDLIBRARY)
|
||||||
$(LINKCC) $(LDFLAGS) $(LINKFORSHARED) -o $@ \
|
$(LINKCC) $(LDFLAGS) $(LINKFORSHARED) -o $@ \
|
||||||
|
@ -616,6 +642,7 @@ PYTHON_HEADERS= \
|
||||||
Include/tupleobject.h \
|
Include/tupleobject.h \
|
||||||
Include/ucnhash.h \
|
Include/ucnhash.h \
|
||||||
Include/unicodeobject.h \
|
Include/unicodeobject.h \
|
||||||
|
Include/warnings.h \
|
||||||
Include/weakrefobject.h \
|
Include/weakrefobject.h \
|
||||||
pyconfig.h \
|
pyconfig.h \
|
||||||
$(PARSER_HEADERS)
|
$(PARSER_HEADERS)
|
||||||
|
@ -1100,7 +1127,10 @@ clean: pycremoval
|
||||||
find $(srcdir)/build -name 'fficonfig.h' -exec rm -f {} ';' || true
|
find $(srcdir)/build -name 'fficonfig.h' -exec rm -f {} ';' || true
|
||||||
find $(srcdir)/build -name 'fficonfig.py' -exec rm -f {} ';' || true
|
find $(srcdir)/build -name 'fficonfig.py' -exec rm -f {} ';' || true
|
||||||
|
|
||||||
clobber: clean rmtestturds docclean
|
profile-removal:
|
||||||
|
find . -name '*.gc??' -exec rm -f {} ';'
|
||||||
|
|
||||||
|
clobber: clean profile-removal
|
||||||
-rm -f $(BUILDPYTHON) $(PGEN) $(LIBRARY) $(LDLIBRARY) $(DLLLIBRARY) \
|
-rm -f $(BUILDPYTHON) $(PGEN) $(LIBRARY) $(LDLIBRARY) $(DLLLIBRARY) \
|
||||||
tags TAGS \
|
tags TAGS \
|
||||||
config.cache config.log pyconfig.h Modules/config.c
|
config.cache config.log pyconfig.h Modules/config.c
|
||||||
|
|
|
@ -17,6 +17,9 @@ the format to accommodate documentation needs as they arise.
|
||||||
Permissions History
|
Permissions History
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
|
- Jeroen Ruigrok van der Werven was given SVN access on 12 April 2008
|
||||||
|
by Georg Brandl, for documentation work.
|
||||||
|
|
||||||
- Josiah Carlson was given SVN access on 26 March 2008 by Georg Brandl,
|
- Josiah Carlson was given SVN access on 26 March 2008 by Georg Brandl,
|
||||||
for work on asyncore/asynchat.
|
for work on asyncore/asynchat.
|
||||||
|
|
||||||
|
|
|
@ -2171,7 +2171,7 @@ KeepRef(CDataObject *target, Py_ssize_t index, PyObject *keep)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
ob = CData_GetContainer(target);
|
ob = CData_GetContainer(target);
|
||||||
if (ob->b_objects == NULL || !PyDict_Check(ob->b_objects)) {
|
if (ob->b_objects == NULL || !PyDict_CheckExact(ob->b_objects)) {
|
||||||
Py_XDECREF(ob->b_objects);
|
Py_XDECREF(ob->b_objects);
|
||||||
ob->b_objects = keep; /* refcount consumed */
|
ob->b_objects = keep; /* refcount consumed */
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -4544,7 +4544,7 @@ Pointer_init(CDataObject *self, PyObject *args, PyObject *kw)
|
||||||
{
|
{
|
||||||
PyObject *value = NULL;
|
PyObject *value = NULL;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "|O:POINTER", &value))
|
if (!PyArg_UnpackTuple(args, "POINTER", 0, 1, &value))
|
||||||
return -1;
|
return -1;
|
||||||
if (value == NULL)
|
if (value == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -4946,7 +4946,7 @@ cast(void *ptr, PyObject *src, PyObject *ctype)
|
||||||
}
|
}
|
||||||
Py_XINCREF(obj->b_objects);
|
Py_XINCREF(obj->b_objects);
|
||||||
result->b_objects = obj->b_objects;
|
result->b_objects = obj->b_objects;
|
||||||
if (result->b_objects && PyDict_Check(result->b_objects)) {
|
if (result->b_objects && PyDict_CheckExact(result->b_objects)) {
|
||||||
PyObject *index;
|
PyObject *index;
|
||||||
int rc;
|
int rc;
|
||||||
index = PyLong_FromVoidPtr((void *)src);
|
index = PyLong_FromVoidPtr((void *)src);
|
||||||
|
|
|
@ -28,6 +28,7 @@ extern void PyMarshal_Init(void);
|
||||||
extern void initimp(void);
|
extern void initimp(void);
|
||||||
extern void initgc(void);
|
extern void initgc(void);
|
||||||
extern void init_ast(void);
|
extern void init_ast(void);
|
||||||
|
extern void _PyWarnings_Init(void);
|
||||||
|
|
||||||
struct _inittab _PyImport_Inittab[] = {
|
struct _inittab _PyImport_Inittab[] = {
|
||||||
|
|
||||||
|
@ -50,6 +51,9 @@ struct _inittab _PyImport_Inittab[] = {
|
||||||
/* This lives in gcmodule.c */
|
/* This lives in gcmodule.c */
|
||||||
{"gc", initgc},
|
{"gc", initgc},
|
||||||
|
|
||||||
|
/* This lives in _warnings.c */
|
||||||
|
{"_warnings", _PyWarnings_Init},
|
||||||
|
|
||||||
/* Sentinel */
|
/* Sentinel */
|
||||||
{0, 0}
|
{0, 0}
|
||||||
};
|
};
|
||||||
|
|
|
@ -45,7 +45,7 @@ static wchar_t **orig_argv;
|
||||||
static int orig_argc;
|
static int orig_argc;
|
||||||
|
|
||||||
/* command line options */
|
/* command line options */
|
||||||
#define BASE_OPTS L"bBc:dEhim:OStuvVW:xX?"
|
#define BASE_OPTS L"bBc:dEhiJm:OStuvVW:xX?"
|
||||||
|
|
||||||
#define PROGRAM_OPTS BASE_OPTS
|
#define PROGRAM_OPTS BASE_OPTS
|
||||||
|
|
||||||
|
@ -345,6 +345,8 @@ Py_Main(int argc, wchar_t **argv)
|
||||||
Py_InteractiveFlag++;
|
Py_InteractiveFlag++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
/* case 'J': reserved for Jython */
|
||||||
|
|
||||||
case 'O':
|
case 'O':
|
||||||
Py_OptimizeFlag++;
|
Py_OptimizeFlag++;
|
||||||
break;
|
break;
|
||||||
|
@ -378,6 +380,8 @@ Py_Main(int argc, wchar_t **argv)
|
||||||
skipfirstline = 1;
|
skipfirstline = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
/* case 'X': reserved for non-standard arguments */
|
||||||
|
|
||||||
case 'h':
|
case 'h':
|
||||||
case '?':
|
case '?':
|
||||||
help++;
|
help++;
|
||||||
|
|
|
@ -108,7 +108,11 @@ PyBytes_FromStringAndSize(const char *bytes, Py_ssize_t size)
|
||||||
PyBytesObject *new;
|
PyBytesObject *new;
|
||||||
Py_ssize_t alloc;
|
Py_ssize_t alloc;
|
||||||
|
|
||||||
assert(size >= 0);
|
if (size < 0) {
|
||||||
|
PyErr_SetString(PyExc_SystemError,
|
||||||
|
"Negative size passed to PyBytes_FromStringAndSize");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
new = PyObject_New(PyBytesObject, &PyBytes_Type);
|
new = PyObject_New(PyBytesObject, &PyBytes_Type);
|
||||||
if (new == NULL)
|
if (new == NULL)
|
||||||
|
|
|
@ -64,7 +64,11 @@ PyObject *
|
||||||
PyString_FromStringAndSize(const char *str, Py_ssize_t size)
|
PyString_FromStringAndSize(const char *str, Py_ssize_t size)
|
||||||
{
|
{
|
||||||
register PyStringObject *op;
|
register PyStringObject *op;
|
||||||
assert(size >= 0);
|
if (size < 0) {
|
||||||
|
PyErr_SetString(PyExc_SystemError,
|
||||||
|
"Negative size passed to PyString_FromStringAndSize");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
if (size == 0 && (op = nullstring) != NULL) {
|
if (size == 0 && (op = nullstring) != NULL) {
|
||||||
#ifdef COUNT_ALLOCS
|
#ifdef COUNT_ALLOCS
|
||||||
null_strings++;
|
null_strings++;
|
||||||
|
|
|
@ -497,6 +497,13 @@ PyObject *PyUnicode_FromUnicode(const Py_UNICODE *u,
|
||||||
PyObject *PyUnicode_FromStringAndSize(const char *u, Py_ssize_t size)
|
PyObject *PyUnicode_FromStringAndSize(const char *u, Py_ssize_t size)
|
||||||
{
|
{
|
||||||
PyUnicodeObject *unicode;
|
PyUnicodeObject *unicode;
|
||||||
|
|
||||||
|
if (size < 0) {
|
||||||
|
PyErr_SetString(PyExc_SystemError,
|
||||||
|
"Negative size passed to PyUnicode_FromStringAndSize");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* If the Unicode data is known at construction time, we can apply
|
/* If the Unicode data is known at construction time, we can apply
|
||||||
some optimizations which share commonly used objects.
|
some optimizations which share commonly used objects.
|
||||||
Also, this means the input must be UTF-8, so fall back to the
|
Also, this means the input must be UTF-8, so fall back to the
|
||||||
|
|
|
@ -60,6 +60,7 @@ extern void init_lsprof(void);
|
||||||
extern void init_ast(void);
|
extern void init_ast(void);
|
||||||
extern void init_fileio(void);
|
extern void init_fileio(void);
|
||||||
extern void initatexit(void);
|
extern void initatexit(void);
|
||||||
|
extern void _PyWarnings_Init(void);
|
||||||
|
|
||||||
/* tools/freeze/makeconfig.py marker for additional "extern" */
|
/* tools/freeze/makeconfig.py marker for additional "extern" */
|
||||||
/* -- ADDMODULE MARKER 1 -- */
|
/* -- ADDMODULE MARKER 1 -- */
|
||||||
|
@ -144,7 +145,8 @@ struct _inittab _PyImport_Inittab[] = {
|
||||||
{"__main__", NULL},
|
{"__main__", NULL},
|
||||||
{"builtins", NULL},
|
{"builtins", NULL},
|
||||||
{"sys", NULL},
|
{"sys", NULL},
|
||||||
|
{"_warnings", _PyWarnings_Init},
|
||||||
|
|
||||||
{"_fileio", init_fileio},
|
{"_fileio", init_fileio},
|
||||||
{"atexit", initatexit},
|
{"atexit", initatexit},
|
||||||
|
|
||||||
|
|
|
@ -1746,6 +1746,10 @@
|
||||||
RelativePath="..\Python\traceback.c"
|
RelativePath="..\Python\traceback.c"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\Python\_warnings.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
</Filter>
|
</Filter>
|
||||||
<Filter
|
<Filter
|
||||||
Name="Resource Files"
|
Name="Resource Files"
|
||||||
|
|
|
@ -0,0 +1,856 @@
|
||||||
|
#include "Python.h"
|
||||||
|
#include "frameobject.h"
|
||||||
|
|
||||||
|
#define MODULE_NAME "_warnings"
|
||||||
|
#define DEFAULT_ACTION_NAME "default_action"
|
||||||
|
|
||||||
|
PyDoc_STRVAR(warnings__doc__,
|
||||||
|
MODULE_NAME " provides basic warning filtering support.\n"
|
||||||
|
"It is a helper module to speed up interpreter start-up.");
|
||||||
|
|
||||||
|
/* Both 'filters' and 'onceregistry' can be set in warnings.py;
|
||||||
|
get_warnings_attr() will reset these variables accordingly. */
|
||||||
|
static PyObject *_filters; /* List */
|
||||||
|
static PyObject *_once_registry; /* Dict */
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
check_matched(PyObject *obj, PyObject *arg)
|
||||||
|
{
|
||||||
|
PyObject *result;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (obj == Py_None)
|
||||||
|
return 1;
|
||||||
|
result = PyObject_CallMethod(obj, "match", "O", arg);
|
||||||
|
if (result == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
rc = PyObject_IsTrue(result);
|
||||||
|
Py_DECREF(result);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Returns a new reference.
|
||||||
|
A NULL return value can mean false or an error.
|
||||||
|
*/
|
||||||
|
static PyObject *
|
||||||
|
get_warnings_attr(const char *attr)
|
||||||
|
{
|
||||||
|
static PyObject *warnings_str = NULL;
|
||||||
|
PyObject *all_modules;
|
||||||
|
PyObject *warnings_module;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
if (warnings_str == NULL) {
|
||||||
|
warnings_str = PyUnicode_InternFromString("warnings");
|
||||||
|
if (warnings_str == NULL)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
all_modules = PyImport_GetModuleDict();
|
||||||
|
result = PyDict_Contains(all_modules, warnings_str);
|
||||||
|
if (result == -1 || result == 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
warnings_module = PyDict_GetItem(all_modules, warnings_str);
|
||||||
|
if (!PyObject_HasAttrString(warnings_module, attr))
|
||||||
|
return NULL;
|
||||||
|
return PyObject_GetAttrString(warnings_module, attr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PyObject *
|
||||||
|
get_once_registry(void)
|
||||||
|
{
|
||||||
|
PyObject *registry;
|
||||||
|
|
||||||
|
registry = get_warnings_attr("onceregistry");
|
||||||
|
if (registry == NULL) {
|
||||||
|
if (PyErr_Occurred())
|
||||||
|
return NULL;
|
||||||
|
return _once_registry;
|
||||||
|
}
|
||||||
|
Py_DECREF(_once_registry);
|
||||||
|
_once_registry = registry;
|
||||||
|
return registry;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* The item is a borrowed reference. */
|
||||||
|
static const char *
|
||||||
|
get_filter(PyObject *category, PyObject *text, Py_ssize_t lineno,
|
||||||
|
PyObject *module, PyObject **item)
|
||||||
|
{
|
||||||
|
PyObject *action, *m, *d;
|
||||||
|
Py_ssize_t i;
|
||||||
|
PyObject *warnings_filters;
|
||||||
|
|
||||||
|
warnings_filters = get_warnings_attr("filters");
|
||||||
|
if (warnings_filters == NULL) {
|
||||||
|
if (PyErr_Occurred())
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Py_DECREF(_filters);
|
||||||
|
_filters = warnings_filters;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!PyList_Check(_filters)) {
|
||||||
|
PyErr_SetString(PyExc_ValueError,
|
||||||
|
MODULE_NAME ".filters must be a list");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* _filters could change while we are iterating over it. */
|
||||||
|
for (i = 0; i < PyList_GET_SIZE(_filters); i++) {
|
||||||
|
PyObject *tmp_item, *action, *msg, *cat, *mod, *ln_obj;
|
||||||
|
Py_ssize_t ln;
|
||||||
|
int is_subclass, good_msg, good_mod;
|
||||||
|
|
||||||
|
tmp_item = *item = PyList_GET_ITEM(_filters, i);
|
||||||
|
if (PyTuple_Size(tmp_item) != 5) {
|
||||||
|
PyErr_Format(PyExc_ValueError,
|
||||||
|
MODULE_NAME ".filters item %zd isn't a 5-tuple", i);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Python code: action, msg, cat, mod, ln = item */
|
||||||
|
action = PyTuple_GET_ITEM(tmp_item, 0);
|
||||||
|
msg = PyTuple_GET_ITEM(tmp_item, 1);
|
||||||
|
cat = PyTuple_GET_ITEM(tmp_item, 2);
|
||||||
|
mod = PyTuple_GET_ITEM(tmp_item, 3);
|
||||||
|
ln_obj = PyTuple_GET_ITEM(tmp_item, 4);
|
||||||
|
|
||||||
|
good_msg = check_matched(msg, text);
|
||||||
|
good_mod = check_matched(mod, module);
|
||||||
|
is_subclass = PyObject_IsSubclass(category, cat);
|
||||||
|
ln = PyLong_AsSsize_t(ln_obj);
|
||||||
|
if (good_msg == -1 || good_mod == -1 || is_subclass == -1 ||
|
||||||
|
(ln == -1 && PyErr_Occurred()))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (good_msg && is_subclass && good_mod && (ln == 0 || lineno == ln))
|
||||||
|
return PyUnicode_AsString(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
m = PyImport_ImportModule(MODULE_NAME);
|
||||||
|
if (m == NULL)
|
||||||
|
return NULL;
|
||||||
|
d = PyModule_GetDict(m);
|
||||||
|
Py_DECREF(m);
|
||||||
|
if (d == NULL)
|
||||||
|
return NULL;
|
||||||
|
action = PyDict_GetItemString(d, DEFAULT_ACTION_NAME);
|
||||||
|
if (action != NULL)
|
||||||
|
return PyUnicode_AsString(action);
|
||||||
|
|
||||||
|
PyErr_SetString(PyExc_ValueError,
|
||||||
|
MODULE_NAME "." DEFAULT_ACTION_NAME " not found");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
already_warned(PyObject *registry, PyObject *key, int should_set)
|
||||||
|
{
|
||||||
|
PyObject *already_warned;
|
||||||
|
|
||||||
|
if (key == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
already_warned = PyDict_GetItem(registry, key);
|
||||||
|
if (already_warned != NULL) {
|
||||||
|
int rc = PyObject_IsTrue(already_warned);
|
||||||
|
if (rc != 0)
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This warning wasn't found in the registry, set it. */
|
||||||
|
if (should_set)
|
||||||
|
return PyDict_SetItem(registry, key, Py_True);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* New reference. */
|
||||||
|
static PyObject *
|
||||||
|
normalize_module(PyObject *filename)
|
||||||
|
{
|
||||||
|
PyObject *module;
|
||||||
|
const char *mod_str;
|
||||||
|
Py_ssize_t len;
|
||||||
|
|
||||||
|
int rc = PyObject_IsTrue(filename);
|
||||||
|
if (rc == -1)
|
||||||
|
return NULL;
|
||||||
|
else if (rc == 0)
|
||||||
|
return PyUnicode_FromString("<unknown>");
|
||||||
|
|
||||||
|
mod_str = PyUnicode_AsString(filename);
|
||||||
|
if (mod_str == NULL)
|
||||||
|
return NULL;
|
||||||
|
len = PyUnicode_GetSize(filename);
|
||||||
|
if (len < 0)
|
||||||
|
return NULL;
|
||||||
|
if (len >= 3 &&
|
||||||
|
strncmp(mod_str + (len - 3), ".py", 3) == 0) {
|
||||||
|
module = PyUnicode_FromStringAndSize(mod_str, len-3);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
module = filename;
|
||||||
|
Py_INCREF(module);
|
||||||
|
}
|
||||||
|
return module;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
update_registry(PyObject *registry, PyObject *text, PyObject *category,
|
||||||
|
int add_zero)
|
||||||
|
{
|
||||||
|
PyObject *altkey, *zero = NULL;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (add_zero) {
|
||||||
|
zero = PyLong_FromLong(0);
|
||||||
|
if (zero == NULL)
|
||||||
|
return -1;
|
||||||
|
altkey = PyTuple_Pack(3, text, category, zero);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
altkey = PyTuple_Pack(2, text, category);
|
||||||
|
|
||||||
|
rc = already_warned(registry, altkey, 1);
|
||||||
|
Py_XDECREF(zero);
|
||||||
|
Py_XDECREF(altkey);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
show_warning(PyObject *filename, int lineno, PyObject *text, PyObject
|
||||||
|
*category, PyObject *sourceline)
|
||||||
|
{
|
||||||
|
PyObject *f_stderr;
|
||||||
|
PyObject *name;
|
||||||
|
char lineno_str[128];
|
||||||
|
|
||||||
|
PyOS_snprintf(lineno_str, sizeof(lineno_str), ":%d: ", lineno);
|
||||||
|
|
||||||
|
name = PyObject_GetAttrString(category, "__name__");
|
||||||
|
if (name == NULL) /* XXX Can an object lack a '__name__' attribute? */
|
||||||
|
return;
|
||||||
|
|
||||||
|
f_stderr = PySys_GetObject("stderr");
|
||||||
|
if (f_stderr == NULL) {
|
||||||
|
fprintf(stderr, "lost sys.stderr\n");
|
||||||
|
Py_DECREF(name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Print "filename:lineno: category: text\n" */
|
||||||
|
PyFile_WriteObject(filename, f_stderr, Py_PRINT_RAW);
|
||||||
|
PyFile_WriteString(lineno_str, f_stderr);
|
||||||
|
PyFile_WriteObject(name, f_stderr, Py_PRINT_RAW);
|
||||||
|
PyFile_WriteString(": ", f_stderr);
|
||||||
|
PyFile_WriteObject(text, f_stderr, Py_PRINT_RAW);
|
||||||
|
PyFile_WriteString("\n", f_stderr);
|
||||||
|
Py_XDECREF(name);
|
||||||
|
|
||||||
|
/* Print " source_line\n" */
|
||||||
|
PyFile_WriteString(" ", f_stderr);
|
||||||
|
if (sourceline) {
|
||||||
|
char *source_line_str = PyUnicode_AsString(sourceline);
|
||||||
|
while (*source_line_str == ' ' || *source_line_str == '\t' ||
|
||||||
|
*source_line_str == '\014')
|
||||||
|
source_line_str++;
|
||||||
|
|
||||||
|
PyFile_WriteString(source_line_str, f_stderr);
|
||||||
|
PyFile_WriteString("\n", f_stderr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Py_DisplaySourceLine(f_stderr, PyUnicode_AsString(filename), lineno);
|
||||||
|
PyErr_Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
warn_explicit(PyObject *category, PyObject *message,
|
||||||
|
PyObject *filename, int lineno,
|
||||||
|
PyObject *module, PyObject *registry, PyObject *sourceline)
|
||||||
|
{
|
||||||
|
PyObject *key = NULL, *text = NULL, *result = NULL, *lineno_obj = NULL;
|
||||||
|
PyObject *item = Py_None;
|
||||||
|
const char *action;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/* Normalize module. */
|
||||||
|
if (module == NULL) {
|
||||||
|
module = normalize_module(filename);
|
||||||
|
if (module == NULL)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Py_INCREF(module);
|
||||||
|
|
||||||
|
/* Normalize message. */
|
||||||
|
Py_INCREF(message); /* DECREF'ed in cleanup. */
|
||||||
|
rc = PyObject_IsInstance(message, PyExc_Warning);
|
||||||
|
if (rc == -1) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
if (rc == 1) {
|
||||||
|
text = PyObject_Str(message);
|
||||||
|
category = (PyObject*)message->ob_type;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
text = message;
|
||||||
|
message = PyObject_CallFunction(category, "O", message);
|
||||||
|
}
|
||||||
|
|
||||||
|
lineno_obj = PyLong_FromLong(lineno);
|
||||||
|
if (lineno_obj == NULL)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
/* Create key. */
|
||||||
|
key = PyTuple_Pack(3, text, category, lineno_obj);
|
||||||
|
if (key == NULL)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (registry != NULL) {
|
||||||
|
rc = already_warned(registry, key, 0);
|
||||||
|
if (rc == -1)
|
||||||
|
goto cleanup;
|
||||||
|
else if (rc == 1)
|
||||||
|
goto return_none;
|
||||||
|
/* Else this warning hasn't been generated before. */
|
||||||
|
}
|
||||||
|
|
||||||
|
action = get_filter(category, text, lineno, module, &item);
|
||||||
|
if (action == NULL)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (strcmp(action, "error") == 0) {
|
||||||
|
PyErr_SetObject(category, message);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Store in the registry that we've been here, *except* when the action
|
||||||
|
is "always". */
|
||||||
|
rc = 0;
|
||||||
|
if (strcmp(action, "always") != 0) {
|
||||||
|
if (registry != NULL && PyDict_SetItem(registry, key, Py_True) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
else if (strcmp(action, "ignore") == 0)
|
||||||
|
goto return_none;
|
||||||
|
else if (strcmp(action, "once") == 0) {
|
||||||
|
if (registry == NULL) {
|
||||||
|
registry = get_once_registry();
|
||||||
|
if (registry == NULL)
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
/* _once_registry[(text, category)] = 1 */
|
||||||
|
rc = update_registry(registry, text, category, 0);
|
||||||
|
}
|
||||||
|
else if (strcmp(action, "module") == 0) {
|
||||||
|
/* registry[(text, category, 0)] = 1 */
|
||||||
|
if (registry != NULL)
|
||||||
|
rc = update_registry(registry, text, category, 0);
|
||||||
|
}
|
||||||
|
else if (strcmp(action, "default") != 0) {
|
||||||
|
PyObject *to_str = PyObject_Str(item);
|
||||||
|
const char *err_str = "???";
|
||||||
|
|
||||||
|
if (to_str != NULL)
|
||||||
|
err_str = PyUnicode_AsString(to_str);
|
||||||
|
PyErr_Format(PyExc_RuntimeError,
|
||||||
|
"Unrecognized action (%s) in warnings.filters:\n %s",
|
||||||
|
action, err_str);
|
||||||
|
Py_XDECREF(to_str);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rc == 1) // Already warned for this module. */
|
||||||
|
goto return_none;
|
||||||
|
if (rc == 0) {
|
||||||
|
PyObject *show_fxn = get_warnings_attr("showwarning");
|
||||||
|
if (show_fxn == NULL) {
|
||||||
|
if (PyErr_Occurred())
|
||||||
|
goto cleanup;
|
||||||
|
show_warning(filename, lineno, text, category, sourceline);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
PyObject *result;
|
||||||
|
|
||||||
|
result = PyObject_CallFunctionObjArgs(show_fxn, message, category,
|
||||||
|
filename, lineno_obj,
|
||||||
|
Py_None,
|
||||||
|
sourceline ?
|
||||||
|
sourceline: Py_None,
|
||||||
|
NULL);
|
||||||
|
Py_XDECREF(result);
|
||||||
|
if (result == NULL)
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else /* if (rc == -1) */
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
return_none:
|
||||||
|
result = Py_None;
|
||||||
|
Py_INCREF(result);
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
Py_XDECREF(key);
|
||||||
|
Py_XDECREF(text);
|
||||||
|
Py_XDECREF(lineno_obj);
|
||||||
|
Py_DECREF(module);
|
||||||
|
Py_DECREF(message);
|
||||||
|
return result; /* Py_None or NULL. */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* filename, module, and registry are new refs, globals is borrowed */
|
||||||
|
/* Returns 0 on error (no new refs), 1 on success */
|
||||||
|
static int
|
||||||
|
setup_context(Py_ssize_t stack_level, PyObject **filename, int *lineno,
|
||||||
|
PyObject **module, PyObject **registry)
|
||||||
|
{
|
||||||
|
PyObject *globals;
|
||||||
|
|
||||||
|
/* Setup globals and lineno. */
|
||||||
|
PyFrameObject *f = PyThreadState_GET()->frame;
|
||||||
|
while (--stack_level > 0 && f != NULL) {
|
||||||
|
f = f->f_back;
|
||||||
|
--stack_level;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (f == NULL) {
|
||||||
|
globals = PyThreadState_Get()->interp->sysdict;
|
||||||
|
*lineno = 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
globals = f->f_globals;
|
||||||
|
*lineno = PyCode_Addr2Line(f->f_code, f->f_lasti);
|
||||||
|
}
|
||||||
|
|
||||||
|
*module = NULL;
|
||||||
|
|
||||||
|
/* Setup registry. */
|
||||||
|
assert(globals != NULL);
|
||||||
|
assert(PyDict_Check(globals));
|
||||||
|
*registry = PyDict_GetItemString(globals, "__warningregistry__");
|
||||||
|
if (*registry == NULL) {
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
*registry = PyDict_New();
|
||||||
|
if (*registry == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
rc = PyDict_SetItemString(globals, "__warningregistry__", *registry);
|
||||||
|
if (rc < 0)
|
||||||
|
goto handle_error;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Py_INCREF(*registry);
|
||||||
|
|
||||||
|
/* Setup module. */
|
||||||
|
*module = PyDict_GetItemString(globals, "__name__");
|
||||||
|
if (*module == NULL) {
|
||||||
|
*module = PyUnicode_FromString("<string>");
|
||||||
|
if (*module == NULL)
|
||||||
|
goto handle_error;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Py_INCREF(*module);
|
||||||
|
|
||||||
|
/* Setup filename. */
|
||||||
|
*filename = PyDict_GetItemString(globals, "__file__");
|
||||||
|
if (*filename != NULL) {
|
||||||
|
Py_ssize_t len = PyUnicode_GetSize(*filename);
|
||||||
|
const char *file_str = PyUnicode_AsString(*filename);
|
||||||
|
if (file_str == NULL || (len < 0 && PyErr_Occurred()))
|
||||||
|
goto handle_error;
|
||||||
|
|
||||||
|
/* if filename.lower().endswith((".pyc", ".pyo")): */
|
||||||
|
if (len >= 4 &&
|
||||||
|
file_str[len-4] == '.' &&
|
||||||
|
tolower(file_str[len-3]) == 'p' &&
|
||||||
|
tolower(file_str[len-2]) == 'y' &&
|
||||||
|
(tolower(file_str[len-1]) == 'c' ||
|
||||||
|
tolower(file_str[len-1]) == 'o')) {
|
||||||
|
*filename = PyUnicode_FromStringAndSize(file_str, len-1);
|
||||||
|
if (*filename == NULL)
|
||||||
|
goto handle_error;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Py_INCREF(*filename);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const char *module_str = PyUnicode_AsString(*module);
|
||||||
|
if (module_str && strcmp(module_str, "__main__") == 0) {
|
||||||
|
PyObject *argv = PySys_GetObject("argv");
|
||||||
|
if (argv != NULL && PyList_Size(argv) > 0) {
|
||||||
|
*filename = PyList_GetItem(argv, 0);
|
||||||
|
Py_INCREF(*filename);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* embedded interpreters don't have sys.argv, see bug #839151 */
|
||||||
|
*filename = PyUnicode_FromString("__main__");
|
||||||
|
if (*filename == NULL)
|
||||||
|
goto handle_error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (*filename == NULL) {
|
||||||
|
*filename = *module;
|
||||||
|
Py_INCREF(*filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
handle_error:
|
||||||
|
/* filename not XDECREF'ed here as there is no way to jump here with a
|
||||||
|
dangling reference. */
|
||||||
|
Py_XDECREF(*registry);
|
||||||
|
Py_XDECREF(*module);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
get_category(PyObject *message, PyObject *category)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/* Get category. */
|
||||||
|
rc = PyObject_IsInstance(message, PyExc_Warning);
|
||||||
|
if (rc == -1)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (rc == 1)
|
||||||
|
category = (PyObject*)message->ob_type;
|
||||||
|
else if (category == NULL)
|
||||||
|
category = PyExc_UserWarning;
|
||||||
|
|
||||||
|
/* Validate category. */
|
||||||
|
rc = PyObject_IsSubclass(category, PyExc_Warning);
|
||||||
|
if (rc == -1)
|
||||||
|
return NULL;
|
||||||
|
if (rc == 0) {
|
||||||
|
PyErr_SetString(PyExc_ValueError,
|
||||||
|
"category is not a subclass of Warning");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return category;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
do_warn(PyObject *message, PyObject *category, Py_ssize_t stack_level)
|
||||||
|
{
|
||||||
|
PyObject *filename, *module, *registry, *res;
|
||||||
|
int lineno;
|
||||||
|
|
||||||
|
if (!setup_context(stack_level, &filename, &lineno, &module, ®istry))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
res = warn_explicit(category, message, filename, lineno, module, registry,
|
||||||
|
NULL);
|
||||||
|
Py_DECREF(filename);
|
||||||
|
Py_DECREF(registry);
|
||||||
|
Py_DECREF(module);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
warnings_warn(PyObject *self, PyObject *args, PyObject *kwds)
|
||||||
|
{
|
||||||
|
static char *kw_list[] = { "message", "category", "stacklevel", 0 };
|
||||||
|
PyObject *message, *category = NULL;
|
||||||
|
Py_ssize_t stack_level = 1;
|
||||||
|
|
||||||
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|On:warn", kw_list,
|
||||||
|
&message, &category, &stack_level))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
category = get_category(message, category);
|
||||||
|
if (category == NULL)
|
||||||
|
return NULL;
|
||||||
|
return do_warn(message, category, stack_level);
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
warnings_warn_explicit(PyObject *self, PyObject *args, PyObject *kwds)
|
||||||
|
{
|
||||||
|
static char *kwd_list[] = {"message", "category", "filename", "lineno",
|
||||||
|
"module", "registry", "module_globals", 0};
|
||||||
|
PyObject *message;
|
||||||
|
PyObject *category;
|
||||||
|
PyObject *filename;
|
||||||
|
int lineno;
|
||||||
|
PyObject *module = NULL;
|
||||||
|
PyObject *registry = NULL;
|
||||||
|
PyObject *module_globals = NULL;
|
||||||
|
|
||||||
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOOi|OOO:warn_explicit",
|
||||||
|
kwd_list, &message, &category, &filename, &lineno, &module,
|
||||||
|
®istry, &module_globals))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (module_globals) {
|
||||||
|
static PyObject *get_source_name = NULL;
|
||||||
|
static PyObject *splitlines_name = NULL;
|
||||||
|
PyObject *loader;
|
||||||
|
PyObject *module_name;
|
||||||
|
PyObject *source;
|
||||||
|
PyObject *source_list;
|
||||||
|
PyObject *source_line;
|
||||||
|
PyObject *returned;
|
||||||
|
|
||||||
|
if (get_source_name == NULL) {
|
||||||
|
get_source_name = PyUnicode_InternFromString("get_source");
|
||||||
|
if (!get_source_name)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (splitlines_name == NULL) {
|
||||||
|
splitlines_name = PyUnicode_InternFromString("splitlines");
|
||||||
|
if (!splitlines_name)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check/get the requisite pieces needed for the loader. */
|
||||||
|
loader = PyDict_GetItemString(module_globals, "__loader__");
|
||||||
|
module_name = PyDict_GetItemString(module_globals, "__name__");
|
||||||
|
|
||||||
|
if (loader == NULL || module_name == NULL)
|
||||||
|
goto standard_call;
|
||||||
|
|
||||||
|
/* Make sure the loader implements the optional get_source() method. */
|
||||||
|
if (!PyObject_HasAttrString(loader, "get_source"))
|
||||||
|
goto standard_call;
|
||||||
|
/* Call get_source() to get the source code. */
|
||||||
|
source = PyObject_CallMethodObjArgs(loader, get_source_name,
|
||||||
|
module_name, NULL);
|
||||||
|
if (!source)
|
||||||
|
return NULL;
|
||||||
|
else if (source == Py_None) {
|
||||||
|
Py_DECREF(Py_None);
|
||||||
|
goto standard_call;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Split the source into lines. */
|
||||||
|
source_list = PyObject_CallMethodObjArgs(source, splitlines_name,
|
||||||
|
NULL);
|
||||||
|
Py_DECREF(source);
|
||||||
|
if (!source_list)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* Get the source line. */
|
||||||
|
source_line = PyList_GetItem(source_list, lineno-1);
|
||||||
|
if (!source_line) {
|
||||||
|
Py_DECREF(source_list);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Handle the warning. */
|
||||||
|
returned = warn_explicit(category, message, filename, lineno, module,
|
||||||
|
registry, source_line);
|
||||||
|
Py_DECREF(source_list);
|
||||||
|
return returned;
|
||||||
|
}
|
||||||
|
|
||||||
|
standard_call:
|
||||||
|
return warn_explicit(category, message, filename, lineno, module,
|
||||||
|
registry, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Function to issue a warning message; may raise an exception. */
|
||||||
|
int
|
||||||
|
PyErr_WarnEx(PyObject *category, const char *text, Py_ssize_t stack_level)
|
||||||
|
{
|
||||||
|
PyObject *res;
|
||||||
|
PyObject *message = PyUnicode_FromString(text);
|
||||||
|
if (message == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (category == NULL)
|
||||||
|
category = PyExc_RuntimeWarning;
|
||||||
|
|
||||||
|
res = do_warn(message, category, stack_level);
|
||||||
|
Py_DECREF(message);
|
||||||
|
if (res == NULL)
|
||||||
|
return -1;
|
||||||
|
Py_DECREF(res);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* PyErr_Warn is only for backwards compatability and will be removed.
|
||||||
|
Use PyErr_WarnEx instead. */
|
||||||
|
|
||||||
|
#undef PyErr_Warn
|
||||||
|
|
||||||
|
PyAPI_FUNC(int)
|
||||||
|
PyErr_Warn(PyObject *category, char *text)
|
||||||
|
{
|
||||||
|
return PyErr_WarnEx(category, text, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Warning with explicit origin */
|
||||||
|
int
|
||||||
|
PyErr_WarnExplicit(PyObject *category, const char *text,
|
||||||
|
const char *filename_str, int lineno,
|
||||||
|
const char *module_str, PyObject *registry)
|
||||||
|
{
|
||||||
|
PyObject *res;
|
||||||
|
PyObject *message = PyUnicode_FromString(text);
|
||||||
|
PyObject *filename = PyUnicode_FromString(filename_str);
|
||||||
|
PyObject *module = NULL;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
if (message == NULL || filename == NULL)
|
||||||
|
goto exit;
|
||||||
|
if (module_str != NULL) {
|
||||||
|
module = PyUnicode_FromString(module_str);
|
||||||
|
if (module == NULL)
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (category == NULL)
|
||||||
|
category = PyExc_RuntimeWarning;
|
||||||
|
res = warn_explicit(category, message, filename, lineno, module, registry,
|
||||||
|
NULL);
|
||||||
|
if (res == NULL)
|
||||||
|
goto exit;
|
||||||
|
Py_DECREF(res);
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
Py_XDECREF(message);
|
||||||
|
Py_XDECREF(module);
|
||||||
|
Py_XDECREF(filename);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PyDoc_STRVAR(warn_doc,
|
||||||
|
"Issue a warning, or maybe ignore it or raise an exception.");
|
||||||
|
|
||||||
|
PyDoc_STRVAR(warn_explicit_doc,
|
||||||
|
"Low-level inferface to warnings functionality.");
|
||||||
|
|
||||||
|
static PyMethodDef warnings_functions[] = {
|
||||||
|
{"warn", (PyCFunction)warnings_warn, METH_VARARGS | METH_KEYWORDS,
|
||||||
|
warn_doc},
|
||||||
|
{"warn_explicit", (PyCFunction)warnings_warn_explicit,
|
||||||
|
METH_VARARGS | METH_KEYWORDS, warn_explicit_doc},
|
||||||
|
// XXX(brett.cannon): add showwarning?
|
||||||
|
// XXX(brett.cannon): Reasonable to add formatwarning?
|
||||||
|
{NULL, NULL} /* sentinel */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
create_filter(PyObject *category, const char *action)
|
||||||
|
{
|
||||||
|
static PyObject *ignore_str = NULL;
|
||||||
|
static PyObject *error_str = NULL;
|
||||||
|
static PyObject *default_str = NULL;
|
||||||
|
PyObject *action_obj = NULL;
|
||||||
|
PyObject *lineno, *result;
|
||||||
|
|
||||||
|
if (!strcmp(action, "ignore")) {
|
||||||
|
if (ignore_str == NULL) {
|
||||||
|
ignore_str = PyUnicode_InternFromString("ignore");
|
||||||
|
if (ignore_str == NULL)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
action_obj = ignore_str;
|
||||||
|
}
|
||||||
|
else if (!strcmp(action, "error")) {
|
||||||
|
if (error_str == NULL) {
|
||||||
|
error_str = PyUnicode_InternFromString("error");
|
||||||
|
if (error_str == NULL)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
action_obj = error_str;
|
||||||
|
}
|
||||||
|
else if (!strcmp(action, "default")) {
|
||||||
|
if (default_str == NULL) {
|
||||||
|
default_str = PyUnicode_InternFromString("default");
|
||||||
|
if (default_str == NULL)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
action_obj = default_str;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Py_FatalError("unknown action");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This assumes the line number is zero for now. */
|
||||||
|
lineno = PyLong_FromLong(0);
|
||||||
|
if (lineno == NULL)
|
||||||
|
return NULL;
|
||||||
|
result = PyTuple_Pack(5, action_obj, Py_None, category, Py_None, lineno);
|
||||||
|
Py_DECREF(lineno);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
init_filters(void)
|
||||||
|
{
|
||||||
|
PyObject *filters = PyList_New(3);
|
||||||
|
const char *bytes_action;
|
||||||
|
if (filters == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
PyList_SET_ITEM(filters, 0,
|
||||||
|
create_filter(PyExc_PendingDeprecationWarning, "ignore"));
|
||||||
|
PyList_SET_ITEM(filters, 1, create_filter(PyExc_ImportWarning, "ignore"));
|
||||||
|
if (Py_BytesWarningFlag > 1)
|
||||||
|
bytes_action = "error";
|
||||||
|
else if (Py_BytesWarningFlag)
|
||||||
|
bytes_action = "default";
|
||||||
|
else
|
||||||
|
bytes_action = "ignore";
|
||||||
|
PyList_SET_ITEM(filters, 2, create_filter(PyExc_BytesWarning,
|
||||||
|
bytes_action));
|
||||||
|
|
||||||
|
if (PyList_GET_ITEM(filters, 0) == NULL ||
|
||||||
|
PyList_GET_ITEM(filters, 1) == NULL ||
|
||||||
|
PyList_GET_ITEM(filters, 2) == NULL) {
|
||||||
|
Py_DECREF(filters);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return filters;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PyMODINIT_FUNC
|
||||||
|
_PyWarnings_Init(void)
|
||||||
|
{
|
||||||
|
PyObject *m, *default_action;
|
||||||
|
|
||||||
|
m = Py_InitModule3(MODULE_NAME, warnings_functions, warnings__doc__);
|
||||||
|
if (m == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_filters = init_filters();
|
||||||
|
if (_filters == NULL)
|
||||||
|
return;
|
||||||
|
Py_INCREF(_filters);
|
||||||
|
if (PyModule_AddObject(m, "filters", _filters) < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_once_registry = PyDict_New();
|
||||||
|
if (_once_registry == NULL)
|
||||||
|
return;
|
||||||
|
Py_INCREF(_once_registry);
|
||||||
|
if (PyModule_AddObject(m, "once_registry", _once_registry) < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
default_action = PyUnicode_InternFromString("default");
|
||||||
|
if (default_action == NULL)
|
||||||
|
return;
|
||||||
|
if (PyModule_AddObject(m, DEFAULT_ACTION_NAME, default_action) < 0)
|
||||||
|
return;
|
||||||
|
}
|
|
@ -673,70 +673,6 @@ PyErr_WriteUnraisable(PyObject *obj)
|
||||||
|
|
||||||
extern PyObject *PyModule_GetWarningsModule(void);
|
extern PyObject *PyModule_GetWarningsModule(void);
|
||||||
|
|
||||||
/* Function to issue a warning message; may raise an exception. */
|
|
||||||
int
|
|
||||||
PyErr_WarnEx(PyObject *category, const char *message, Py_ssize_t stack_level)
|
|
||||||
{
|
|
||||||
PyObject *dict, *func = NULL;
|
|
||||||
PyObject *warnings_module = PyModule_GetWarningsModule();
|
|
||||||
|
|
||||||
if (warnings_module != NULL) {
|
|
||||||
dict = PyModule_GetDict(warnings_module);
|
|
||||||
if (dict != NULL)
|
|
||||||
func = PyDict_GetItemString(dict, "warn");
|
|
||||||
}
|
|
||||||
if (func == NULL) {
|
|
||||||
PySys_WriteStderr("warning: %s\n", message);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
PyObject *res;
|
|
||||||
|
|
||||||
if (category == NULL)
|
|
||||||
category = PyExc_RuntimeWarning;
|
|
||||||
res = PyObject_CallFunction(func, "sOn",
|
|
||||||
message, category, stack_level);
|
|
||||||
if (res == NULL)
|
|
||||||
return -1;
|
|
||||||
Py_DECREF(res);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Warning with explicit origin */
|
|
||||||
int
|
|
||||||
PyErr_WarnExplicit(PyObject *category, const char *message,
|
|
||||||
const char *filename, int lineno,
|
|
||||||
const char *module, PyObject *registry)
|
|
||||||
{
|
|
||||||
PyObject *mod, *dict, *func = NULL;
|
|
||||||
|
|
||||||
mod = PyImport_ImportModuleNoBlock("warnings");
|
|
||||||
if (mod != NULL) {
|
|
||||||
dict = PyModule_GetDict(mod);
|
|
||||||
func = PyDict_GetItemString(dict, "warn_explicit");
|
|
||||||
Py_DECREF(mod);
|
|
||||||
}
|
|
||||||
if (func == NULL) {
|
|
||||||
PySys_WriteStderr("warning: %s\n", message);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
PyObject *res;
|
|
||||||
|
|
||||||
if (category == NULL)
|
|
||||||
category = PyExc_RuntimeWarning;
|
|
||||||
if (registry == NULL)
|
|
||||||
registry = Py_None;
|
|
||||||
res = PyObject_CallFunction(func, "sOsizO", message, category,
|
|
||||||
filename, lineno, module, registry);
|
|
||||||
if (res == NULL)
|
|
||||||
return -1;
|
|
||||||
Py_DECREF(res);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Set file and line information for the current exception.
|
/* Set file and line information for the current exception.
|
||||||
If the exception is not a SyntaxError, also sets additional attributes
|
If the exception is not a SyntaxError, also sets additional attributes
|
||||||
|
|
|
@ -83,7 +83,18 @@ int _PyOS_GetOpt(int argc, wchar_t **argv, wchar_t *optstring)
|
||||||
|
|
||||||
if ( (option = *opt_ptr++) == L'\0')
|
if ( (option = *opt_ptr++) == L'\0')
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
if (option == 'J') {
|
||||||
|
fprintf(stderr, "-J is reserved for Jython\n");
|
||||||
|
return '_';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (option == 'X') {
|
||||||
|
fprintf(stderr,
|
||||||
|
"-X is reserved for non-standard arguments\n");
|
||||||
|
return '_';
|
||||||
|
}
|
||||||
|
|
||||||
if ((ptr = wcschr(optstring, option)) == NULL) {
|
if ((ptr = wcschr(optstring, option)) == NULL) {
|
||||||
if (_PyOS_opterr)
|
if (_PyOS_opterr)
|
||||||
fprintf(stderr, "Unknown option: -%c\n", (char)option);
|
fprintf(stderr, "Unknown option: -%c\n", (char)option);
|
||||||
|
|
|
@ -84,38 +84,12 @@ int Py_UseClassExceptionsFlag = 1; /* Needed by bltinmodule.c: deprecated */
|
||||||
int Py_FrozenFlag; /* Needed by getpath.c */
|
int Py_FrozenFlag; /* Needed by getpath.c */
|
||||||
int Py_IgnoreEnvironmentFlag; /* e.g. PYTHONPATH, PYTHONHOME */
|
int Py_IgnoreEnvironmentFlag; /* e.g. PYTHONPATH, PYTHONHOME */
|
||||||
|
|
||||||
/* Reference to 'warnings' module, to avoid importing it
|
/* PyModule_GetWarningsModule is no longer necessary as of 2.6
|
||||||
on the fly when the import lock may be held. See 683658/771097
|
since _warnings is builtin. This API should not be used. */
|
||||||
*/
|
PyObject *
|
||||||
static PyObject *warnings_module = NULL;
|
PyModule_GetWarningsModule(void)
|
||||||
|
|
||||||
/* Returns a borrowed reference to the 'warnings' module, or NULL.
|
|
||||||
If the module is returned, it is guaranteed to have been obtained
|
|
||||||
without acquiring the import lock
|
|
||||||
*/
|
|
||||||
PyObject *PyModule_GetWarningsModule(void)
|
|
||||||
{
|
{
|
||||||
PyObject *typ, *val, *tb;
|
return PyImport_ImportModule("warnings");
|
||||||
PyObject *all_modules;
|
|
||||||
/* If we managed to get the module at init time, just use it */
|
|
||||||
if (warnings_module)
|
|
||||||
return warnings_module;
|
|
||||||
/* If it wasn't available at init time, it may be available
|
|
||||||
now in sys.modules (common scenario is frozen apps: import
|
|
||||||
at init time fails, but the frozen init code sets up sys.path
|
|
||||||
correctly, then does an implicit import of warnings for us
|
|
||||||
*/
|
|
||||||
/* Save and restore any exceptions */
|
|
||||||
PyErr_Fetch(&typ, &val, &tb);
|
|
||||||
|
|
||||||
all_modules = PySys_GetObject("modules");
|
|
||||||
if (all_modules) {
|
|
||||||
warnings_module = PyDict_GetItemString(all_modules, "warnings");
|
|
||||||
/* We keep a ref in the global */
|
|
||||||
Py_XINCREF(warnings_module);
|
|
||||||
}
|
|
||||||
PyErr_Restore(typ, val, tb);
|
|
||||||
return warnings_module;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int initialized = 0;
|
static int initialized = 0;
|
||||||
|
@ -255,6 +229,15 @@ Py_InitializeEx(int install_sigs)
|
||||||
|
|
||||||
if (install_sigs)
|
if (install_sigs)
|
||||||
initsigs(); /* Signal handling stuff, including initintr() */
|
initsigs(); /* Signal handling stuff, including initintr() */
|
||||||
|
|
||||||
|
/* Initialize warnings. */
|
||||||
|
_PyWarnings_Init();
|
||||||
|
if (PySys_HasWarnOptions()) {
|
||||||
|
PyObject *warnings_module = PyImport_ImportModule("warnings");
|
||||||
|
if (!warnings_module)
|
||||||
|
PyErr_Clear();
|
||||||
|
Py_XDECREF(warnings_module);
|
||||||
|
}
|
||||||
|
|
||||||
initmain(); /* Module __main__ */
|
initmain(); /* Module __main__ */
|
||||||
if (initstdio() < 0)
|
if (initstdio() < 0)
|
||||||
|
@ -268,30 +251,6 @@ Py_InitializeEx(int install_sigs)
|
||||||
_PyGILState_Init(interp, tstate);
|
_PyGILState_Init(interp, tstate);
|
||||||
#endif /* WITH_THREAD */
|
#endif /* WITH_THREAD */
|
||||||
|
|
||||||
warnings_module = PyImport_ImportModule("warnings");
|
|
||||||
if (!warnings_module) {
|
|
||||||
PyErr_Clear();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
PyObject *o;
|
|
||||||
char *action[8];
|
|
||||||
|
|
||||||
if (Py_BytesWarningFlag > 1)
|
|
||||||
*action = "error";
|
|
||||||
else if (Py_BytesWarningFlag)
|
|
||||||
*action = "default";
|
|
||||||
else
|
|
||||||
*action = "ignore";
|
|
||||||
|
|
||||||
o = PyObject_CallMethod(warnings_module,
|
|
||||||
"simplefilter", "sO",
|
|
||||||
*action, PyExc_BytesWarning);
|
|
||||||
if (o == NULL)
|
|
||||||
Py_FatalError("Py_Initialize: can't initialize"
|
|
||||||
"warning filter for BytesWarning.");
|
|
||||||
Py_DECREF(o);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(HAVE_LANGINFO_H) && defined(CODESET)
|
#if defined(HAVE_LANGINFO_H) && defined(CODESET)
|
||||||
/* On Unix, set the file system encoding according to the
|
/* On Unix, set the file system encoding according to the
|
||||||
user's preference, if the CODESET names a well-known
|
user's preference, if the CODESET names a well-known
|
||||||
|
@ -403,10 +362,6 @@ Py_Finalize(void)
|
||||||
/* Disable signal handling */
|
/* Disable signal handling */
|
||||||
PyOS_FiniInterrupts();
|
PyOS_FiniInterrupts();
|
||||||
|
|
||||||
/* drop module references we saved */
|
|
||||||
Py_XDECREF(warnings_module);
|
|
||||||
warnings_module = NULL;
|
|
||||||
|
|
||||||
/* Clear type lookup cache */
|
/* Clear type lookup cache */
|
||||||
PyType_ClearCache();
|
PyType_ClearCache();
|
||||||
|
|
||||||
|
|
|
@ -899,6 +899,12 @@ PySys_AddWarnOption(const wchar_t *s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
PySys_HasWarnOptions(void)
|
||||||
|
{
|
||||||
|
return (warnoptions != NULL && (PyList_Size(warnoptions) > 0)) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* XXX This doc string is too long to be a single string literal in VC++ 5.0.
|
/* XXX This doc string is too long to be a single string literal in VC++ 5.0.
|
||||||
Two literals concatenated works just fine. If you have a K&R compiler
|
Two literals concatenated works just fine. If you have a K&R compiler
|
||||||
or other abomination that however *does* understand longer strings,
|
or other abomination that however *does* understand longer strings,
|
||||||
|
@ -1101,6 +1107,7 @@ static PyStructSequence_Field flags_fields[] = {
|
||||||
#endif
|
#endif
|
||||||
/* {"unbuffered", "-u"}, */
|
/* {"unbuffered", "-u"}, */
|
||||||
/* {"skip_first", "-x"}, */
|
/* {"skip_first", "-x"}, */
|
||||||
|
{"bytes_warning", "-b"},
|
||||||
{0}
|
{0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1144,6 +1151,7 @@ make_flags(void)
|
||||||
#endif
|
#endif
|
||||||
/* SetFlag(saw_unbuffered_flag); */
|
/* SetFlag(saw_unbuffered_flag); */
|
||||||
/* SetFlag(skipfirstline); */
|
/* SetFlag(skipfirstline); */
|
||||||
|
SetFlag(Py_BytesWarningFlag);
|
||||||
#undef SetFlag
|
#undef SetFlag
|
||||||
|
|
||||||
if (PyErr_Occurred()) {
|
if (PyErr_Occurred()) {
|
||||||
|
|
|
@ -128,16 +128,16 @@ PyTraceBack_Here(PyFrameObject *frame)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
int
|
||||||
tb_displayline(PyObject *f, char *filename, int lineno, char *name)
|
Py_DisplaySourceLine(PyObject *f, const char *filename, int lineno)
|
||||||
{
|
{
|
||||||
int err = 0;
|
int err = 0;
|
||||||
FILE *xfp;
|
FILE *xfp = NULL;
|
||||||
char linebuf[2000];
|
char linebuf[2000];
|
||||||
int i;
|
int i;
|
||||||
char namebuf[MAXPATHLEN+1];
|
char namebuf[MAXPATHLEN+1];
|
||||||
|
|
||||||
if (filename == NULL || name == NULL)
|
if (filename == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
/* This is needed by Emacs' compile command */
|
/* This is needed by Emacs' compile command */
|
||||||
#define FMT " File \"%.500s\", line %d, in %.500s\n"
|
#define FMT " File \"%.500s\", line %d, in %.500s\n"
|
||||||
|
@ -145,7 +145,7 @@ tb_displayline(PyObject *f, char *filename, int lineno, char *name)
|
||||||
if (xfp == NULL) {
|
if (xfp == NULL) {
|
||||||
/* Search tail of filename in sys.path before giving up */
|
/* Search tail of filename in sys.path before giving up */
|
||||||
PyObject *path;
|
PyObject *path;
|
||||||
char *tail = strrchr(filename, SEP);
|
const char *tail = strrchr(filename, SEP);
|
||||||
if (tail == NULL)
|
if (tail == NULL)
|
||||||
tail = filename;
|
tail = filename;
|
||||||
else
|
else
|
||||||
|
@ -181,14 +181,14 @@ tb_displayline(PyObject *f, char *filename, int lineno, char *name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PyOS_snprintf(linebuf, sizeof(linebuf), FMT, filename, lineno, name);
|
|
||||||
err = PyFile_WriteString(linebuf, f);
|
if (xfp == NULL)
|
||||||
if (xfp == NULL)
|
return err;
|
||||||
return err;
|
if (err != 0) {
|
||||||
else if (err != 0) {
|
fclose(xfp);
|
||||||
fclose(xfp);
|
return err;
|
||||||
return err;
|
}
|
||||||
}
|
|
||||||
for (i = 0; i < lineno; i++) {
|
for (i = 0; i < lineno; i++) {
|
||||||
char* pLastChar = &linebuf[sizeof(linebuf)-2];
|
char* pLastChar = &linebuf[sizeof(linebuf)-2];
|
||||||
do {
|
do {
|
||||||
|
@ -206,22 +206,38 @@ tb_displayline(PyObject *f, char *filename, int lineno, char *name)
|
||||||
char *p = linebuf;
|
char *p = linebuf;
|
||||||
while (*p == ' ' || *p == '\t' || *p == '\014')
|
while (*p == ' ' || *p == '\t' || *p == '\014')
|
||||||
p++;
|
p++;
|
||||||
err = PyFile_WriteString(" ", f);
|
err = PyFile_WriteString(p, f);
|
||||||
if (err == 0) {
|
if (err == 0 && strchr(p, '\n') == NULL)
|
||||||
err = PyFile_WriteString(p, f);
|
err = PyFile_WriteString("\n", f);
|
||||||
if (err == 0 && strchr(p, '\n') == NULL)
|
|
||||||
err = PyFile_WriteString("\n", f);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
fclose(xfp);
|
fclose(xfp);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
tb_printinternal(PyTracebackObject *tb, PyObject *f, int limit)
|
tb_displayline(PyObject *f, const char *filename, int lineno, const char *name)
|
||||||
{
|
{
|
||||||
int err = 0;
|
int err = 0;
|
||||||
int depth = 0;
|
char linebuf[2000];
|
||||||
|
|
||||||
|
if (filename == NULL || name == NULL)
|
||||||
|
return -1;
|
||||||
|
/* This is needed by Emacs' compile command */
|
||||||
|
#define FMT " File \"%.500s\", line %d, in %.500s\n"
|
||||||
|
PyOS_snprintf(linebuf, sizeof(linebuf), FMT, filename, lineno, name);
|
||||||
|
err = PyFile_WriteString(linebuf, f);
|
||||||
|
if (err != 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
err = PyFile_WriteString(" ", f);
|
||||||
|
return Py_DisplaySourceLine(f, filename, lineno);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
tb_printinternal(PyTracebackObject *tb, PyObject *f, long limit)
|
||||||
|
{
|
||||||
|
int err = 0;
|
||||||
|
long depth = 0;
|
||||||
PyTracebackObject *tb1 = tb;
|
PyTracebackObject *tb1 = tb;
|
||||||
while (tb1 != NULL) {
|
while (tb1 != NULL) {
|
||||||
depth++;
|
depth++;
|
||||||
|
@ -250,7 +266,7 @@ PyTraceBack_Print(PyObject *v, PyObject *f)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
PyObject *limitv;
|
PyObject *limitv;
|
||||||
int limit = PyTraceBack_LIMIT;
|
long limit = PyTraceBack_LIMIT;
|
||||||
|
|
||||||
if (v == NULL)
|
if (v == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Reference in New Issue