[Python-checkins] r78929 - in python/branches/py3k: Doc/library/test.rst Lib/_pyio.py Lib/test/support.py Lib/test/test_fileio.py Misc/NEWS

florent.xicluna python-checkins at python.org
Sat Mar 13 16:26:44 CET 2010


Author: florent.xicluna
Date: Sat Mar 13 16:26:44 2010
New Revision: 78929

Log:
Only the parts which are relevant for 3.x branch.

Merged revisions 78757-78758,78769,78815 via svnmerge from 
svn+ssh://pythondev@svn.python.org/python/trunk

........
  r78757 | florent.xicluna | 2010-03-07 13:14:25 +0100 (dim, 07 mar 2010) | 2 lines
  
  Fix some py3k warnings in the standard library.
........
  r78758 | florent.xicluna | 2010-03-07 13:18:33 +0100 (dim, 07 mar 2010) | 4 lines
  
  Issue #7849: Now the utility ``check_warnings`` verifies if the warnings are
  effectively raised.  A new utility ``check_py3k_warnings`` deals with py3k warnings.
........
  r78769 | florent.xicluna | 2010-03-07 20:14:12 +0100 (dim, 07 mar 2010) | 2 lines
  
  Refresh the documentation for the test.test_support module.
........
  r78815 | florent.xicluna | 2010-03-09 20:57:01 +0100 (mar, 09 mar 2010) | 2 lines
  
  #7772: Fix test_py3kwarn. Now the test suite could pass with "-3" flag.
........


Modified:
   python/branches/py3k/   (props changed)
   python/branches/py3k/Doc/library/test.rst
   python/branches/py3k/Lib/_pyio.py
   python/branches/py3k/Lib/test/support.py
   python/branches/py3k/Lib/test/test_fileio.py
   python/branches/py3k/Misc/NEWS

Modified: python/branches/py3k/Doc/library/test.rst
==============================================================================
--- python/branches/py3k/Doc/library/test.rst	(original)
+++ python/branches/py3k/Doc/library/test.rst	Sat Mar 13 16:26:44 2010
@@ -130,13 +130,13 @@
              self.func(self.arg)
 
      class AcceptLists(TestFuncAcceptsSequences):
-         arg = [1,2,3]
+         arg = [1, 2, 3]
 
      class AcceptStrings(TestFuncAcceptsSequences):
          arg = 'abc'
 
      class AcceptTuples(TestFuncAcceptsSequences):
-         arg = (1,2,3)
+         arg = (1, 2, 3)
 
 
 .. seealso::
@@ -198,16 +198,9 @@
    methods.
 
 
-.. exception:: TestSkipped
-
-   Subclass of :exc:`TestFailed`. Raised when a test is skipped. This occurs when a
-   needed resource (such as a network connection) is not available at the time of
-   testing.
-
-
 .. exception:: ResourceDenied
 
-   Subclass of :exc:`TestSkipped`. Raised when a resource (such as a network
+   Subclass of :exc:`unittest.SkipTest`. Raised when a resource (such as a network
    connection) is not available. Raised by the :func:`requires` function.
 
 The :mod:`test.support` module defines the following constants:
@@ -227,7 +220,7 @@
 
 .. data:: TESTFN
 
-   Set to the path that a temporary file may be created at. Any temporary that is
+   Set to the name that a temporary file could use. Any temporary file that is
    created should be closed and unlinked (removed).
 
 The :mod:`test.support` module defines the following functions:
@@ -235,21 +228,21 @@
 
 .. function:: forget(module_name)
 
-   Removes the module named *module_name* from ``sys.modules`` and deletes any
+   Remove the module named *module_name* from ``sys.modules`` and deletes any
    byte-compiled files of the module.
 
 
 .. function:: is_resource_enabled(resource)
 
-   Returns :const:`True` if *resource* is enabled and available. The list of
+   Return :const:`True` if *resource* is enabled and available. The list of
    available resources is only set when :mod:`test.regrtest` is executing the
    tests.
 
 
 .. function:: requires(resource, msg=None)
 
-   Raises :exc:`ResourceDenied` if *resource* is not available. *msg* is the
-   argument to :exc:`ResourceDenied` if it is raised. Always returns true if called
+   Raise :exc:`ResourceDenied` if *resource* is not available. *msg* is the
+   argument to :exc:`ResourceDenied` if it is raised. Always returns True if called
    by a function whose ``__name__`` is ``'__main__'``. Used when tests are executed
    by :mod:`test.regrtest`.
 
@@ -277,14 +270,24 @@
    This will run all tests defined in the named module.
 
 
-.. function:: check_warnings()
+.. function:: check_warnings(*filters, quiet=False)
 
    A convenience wrapper for ``warnings.catch_warnings()`` that makes
    it easier to test that a warning was correctly raised with a single
    assertion. It is approximately equivalent to calling
    ``warnings.catch_warnings(record=True)``.
 
-   The main difference is that on entry to the context manager, a
+   It accepts 2-tuples ``("message regexp", WarningCategory)`` as positional
+   arguments. When the optional keyword argument ``quiet`` is True, it does
+   not fail if a filter catches nothing. Without argument, it defaults to::
+
+      check_warnings(("", Warning), quiet=False)
+
+   The main difference is that it verifies the warnings raised. If some filter
+   did not catch any warning, the test fails. If some warnings are not caught,
+   the test fails, too. To disable these checks, use argument ``quiet=True``.
+
+   Another significant difference is that on entry to the context manager, a
    :class:`WarningRecorder` instance is returned instead of a simple list.
    The underlying warnings list is available via the recorder object's
    :attr:`warnings` attribute, while the attributes of the last raised
@@ -294,19 +297,34 @@
    A :meth:`reset` method is also provided on the recorder object. This
    method simply clears the warning list.
 
-   The context manager is used like this::
+   The context manager may be used like this::
+
+      import warnings
+
+      with check_warnings():
+          exec('assert(False, "Hey!")')
+          warnings.warn(UserWarning("Hide me!"))
 
-      with check_warnings() as w:
+      with check_warnings(("assertion is always true", SyntaxWarning),
+                          ("", UserWarning)):
+          exec('assert(False, "Hey!")')
+          warnings.warn(UserWarning("Hide me!"))
+
+      with check_warnings(quiet=True) as w:
           warnings.simplefilter("always")
           warnings.warn("foo")
-          assert str(w.message) == "foo"
+          assert str(w.args[0]) == "foo"
           warnings.warn("bar")
-          assert str(w.message) == "bar"
-          assert str(w.warnings[0].message) == "foo"
-          assert str(w.warnings[1].message) == "bar"
+          assert str(w.args[0]) == "bar"
+          assert str(w.warnings[0].args[0]) == "foo"
+          assert str(w.warnings[1].args[0]) == "bar"
           w.reset()
           assert len(w.warnings) == 0
 
+   .. versionchanged:: 2.7
+      The test fails when the context manager do not catch any warning.
+      New optional attributes ``*filters`` and ``quiet``.
+
 
 .. function:: captured_stdout()
 

Modified: python/branches/py3k/Lib/_pyio.py
==============================================================================
--- python/branches/py3k/Lib/_pyio.py	(original)
+++ python/branches/py3k/Lib/_pyio.py	Sat Mar 13 16:26:44 2010
@@ -828,7 +828,7 @@
         if self.closed:
             raise ValueError("seek on closed file")
         try:
-            pos = pos.__index__()
+            pos.__index__
         except AttributeError as err:
             raise TypeError("an integer is required") from err
         if whence == 0:
@@ -853,8 +853,13 @@
             raise ValueError("truncate on closed file")
         if pos is None:
             pos = self._pos
-        elif pos < 0:
-            raise ValueError("negative truncate position %r" % (pos,))
+        else:
+            try:
+                pos.__index__
+            except AttributeError as err:
+                raise TypeError("an integer is required") from err
+            if pos < 0:
+                raise ValueError("negative truncate position %r" % (pos,))
         del self._buffer[pos:]
         return pos
 
@@ -1803,6 +1808,10 @@
         if n is None:
             n = -1
         decoder = self._decoder or self._get_decoder()
+        try:
+            n.__index__
+        except AttributeError as err:
+            raise TypeError("an integer is required") from err
         if n < 0:
             # Read everything.
             result = (self._get_decoded_chars() +

Modified: python/branches/py3k/Lib/test/support.py
==============================================================================
--- python/branches/py3k/Lib/test/support.py	(original)
+++ python/branches/py3k/Lib/test/support.py	Sat Mar 13 16:26:44 2010
@@ -16,6 +16,7 @@
 import unittest
 import importlib
 import collections
+import re
 
 __all__ = ["Error", "TestFailed", "ResourceDenied", "import_module",
            "verbose", "use_resources", "max_memuse", "record_original_stdout",
@@ -464,22 +465,80 @@
        entry to the warnings.catch_warnings() context manager.
     """
     def __init__(self, warnings_list):
-        self.warnings = warnings_list
+        self._warnings = warnings_list
+        self._last = 0
 
     def __getattr__(self, attr):
-        if self.warnings:
-            return getattr(self.warnings[-1], attr)
+        if len(self._warnings) > self._last:
+            return getattr(self._warnings[-1], attr)
         elif attr in warnings.WarningMessage._WARNING_DETAILS:
             return None
         raise AttributeError("%r has no attribute %r" % (self, attr))
 
+    @property
+    def warnings(self):
+        return self._warnings[self._last:]
+
     def reset(self):
-        del self.warnings[:]
+        self._last = len(self._warnings)
 
- at contextlib.contextmanager
-def check_warnings():
+
+def _filterwarnings(filters, quiet=False):
+    """Catch the warnings, then check if all the expected
+    warnings have been raised and re-raise unexpected warnings.
+    If 'quiet' is True, only re-raise the unexpected warnings.
+    """
+    # Clear the warning registry of the calling module
+    # in order to re-raise the warnings.
+    frame = sys._getframe(2)
+    registry = frame.f_globals.get('__warningregistry__')
+    if registry:
+        registry.clear()
     with warnings.catch_warnings(record=True) as w:
+        # Set filter "always" to record all warnings.  Because
+        # test_warnings swap the module, we need to look up in
+        # the sys.modules dictionary.
+        sys.modules['warnings'].simplefilter("always")
         yield WarningsRecorder(w)
+    # Filter the recorded warnings
+    reraise = [warning.message for warning in w]
+    missing = []
+    for msg, cat in filters:
+        seen = False
+        for exc in reraise[:]:
+            message = str(exc)
+            # Filter out the matching messages
+            if (re.match(msg, message, re.I) and
+                issubclass(exc.__class__, cat)):
+                seen = True
+                reraise.remove(exc)
+        if not seen and not quiet:
+            # This filter caught nothing
+            missing.append((msg, cat.__name__))
+    if reraise:
+        raise AssertionError("unhandled warning %r" % reraise[0])
+    if missing:
+        raise AssertionError("filter (%r, %s) did not catch any warning" %
+                             missing[0])
+
+
+ at contextlib.contextmanager
+def check_warnings(*filters, **kwargs):
+    """Context manager to silence warnings.
+
+    Accept 2-tuples as positional arguments:
+        ("message regexp", WarningCategory)
+
+    Optional argument:
+     - if 'quiet' is True, it does not fail if a filter catches nothing
+        (default False)
+
+    Without argument, it defaults to:
+        check_warnings(("", Warning), quiet=False)
+    """
+    if not filters:
+        filters = (("", Warning),)
+    return _filterwarnings(filters, kwargs.get('quiet'))
 
 
 class CleanImport(object):
@@ -714,7 +773,6 @@
 MAX_Py_ssize_t = sys.maxsize
 
 def set_memlimit(limit):
-    import re
     global max_memuse
     global real_max_memuse
     sizes = {

Modified: python/branches/py3k/Lib/test/test_fileio.py
==============================================================================
--- python/branches/py3k/Lib/test/test_fileio.py	(original)
+++ python/branches/py3k/Lib/test/test_fileio.py	Sat Mar 13 16:26:44 2010
@@ -390,7 +390,7 @@
         self.assertRaises(TypeError, _FileIO, "1", 0, 0)
 
     def testWarnings(self):
-        with check_warnings() as w:
+        with check_warnings(quiet=True) as w:
             self.assertEqual(w.warnings, [])
             self.assertRaises(TypeError, _FileIO, [])
             self.assertEqual(w.warnings, [])

Modified: python/branches/py3k/Misc/NEWS
==============================================================================
--- python/branches/py3k/Misc/NEWS	(original)
+++ python/branches/py3k/Misc/NEWS	Sat Mar 13 16:26:44 2010
@@ -869,6 +869,9 @@
 Tests
 -----
 
+- Issue #7849: Now the utility ``check_warnings`` verifies if the warnings are
+  effectively raised.
+
 - The four path modules (genericpath, macpath, ntpath, posixpath) share a
   common TestCase for some tests: test_genericpath.CommonTest.
 


More information about the Python-checkins mailing list