Home | History | Annotate | Download | only in test_warnings
      1 from contextlib import contextmanager
      2 import linecache
      3 import os
      4 from io import StringIO
      5 import re
      6 import sys
      7 import textwrap
      8 import unittest
      9 from test import support
     10 from test.support.script_helper import assert_python_ok, assert_python_failure
     11 
     12 from test.test_warnings.data import stacklevel as warning_tests
     13 
     14 import warnings as original_warnings
     15 
     16 py_warnings = support.import_fresh_module('warnings', blocked=['_warnings'])
     17 c_warnings = support.import_fresh_module('warnings', fresh=['_warnings'])
     18 
     19 @contextmanager
     20 def warnings_state(module):
     21     """Use a specific warnings implementation in warning_tests."""
     22     global __warningregistry__
     23     for to_clear in (sys, warning_tests):
     24         try:
     25             to_clear.__warningregistry__.clear()
     26         except AttributeError:
     27             pass
     28     try:
     29         __warningregistry__.clear()
     30     except NameError:
     31         pass
     32     original_warnings = warning_tests.warnings
     33     original_filters = module.filters
     34     try:
     35         module.filters = original_filters[:]
     36         module.simplefilter("once")
     37         warning_tests.warnings = module
     38         yield
     39     finally:
     40         warning_tests.warnings = original_warnings
     41         module.filters = original_filters
     42 
     43 
     44 class BaseTest:
     45 
     46     """Basic bookkeeping required for testing."""
     47 
     48     def setUp(self):
     49         self.old_unittest_module = unittest.case.warnings
     50         # The __warningregistry__ needs to be in a pristine state for tests
     51         # to work properly.
     52         if '__warningregistry__' in globals():
     53             del globals()['__warningregistry__']
     54         if hasattr(warning_tests, '__warningregistry__'):
     55             del warning_tests.__warningregistry__
     56         if hasattr(sys, '__warningregistry__'):
     57             del sys.__warningregistry__
     58         # The 'warnings' module must be explicitly set so that the proper
     59         # interaction between _warnings and 'warnings' can be controlled.
     60         sys.modules['warnings'] = self.module
     61         # Ensure that unittest.TestCase.assertWarns() uses the same warnings
     62         # module than warnings.catch_warnings(). Otherwise,
     63         # warnings.catch_warnings() will be unable to remove the added filter.
     64         unittest.case.warnings = self.module
     65         super(BaseTest, self).setUp()
     66 
     67     def tearDown(self):
     68         sys.modules['warnings'] = original_warnings
     69         unittest.case.warnings = self.old_unittest_module
     70         super(BaseTest, self).tearDown()
     71 
     72 class PublicAPITests(BaseTest):
     73 
     74     """Ensures that the correct values are exposed in the
     75     public API.
     76     """
     77 
     78     def test_module_all_attribute(self):
     79         self.assertTrue(hasattr(self.module, '__all__'))
     80         target_api = ["warn", "warn_explicit", "showwarning",
     81                       "formatwarning", "filterwarnings", "simplefilter",
     82                       "resetwarnings", "catch_warnings"]
     83         self.assertSetEqual(set(self.module.__all__),
     84                             set(target_api))
     85 
     86 class CPublicAPITests(PublicAPITests, unittest.TestCase):
     87     module = c_warnings
     88 
     89 class PyPublicAPITests(PublicAPITests, unittest.TestCase):
     90     module = py_warnings
     91 
     92 class FilterTests(BaseTest):
     93 
     94     """Testing the filtering functionality."""
     95 
     96     def test_error(self):
     97         with original_warnings.catch_warnings(module=self.module) as w:
     98             self.module.resetwarnings()
     99             self.module.filterwarnings("error", category=UserWarning)
    100             self.assertRaises(UserWarning, self.module.warn,
    101                                 "FilterTests.test_error")
    102 
    103     def test_error_after_default(self):
    104         with original_warnings.catch_warnings(module=self.module) as w:
    105             self.module.resetwarnings()
    106             message = "FilterTests.test_ignore_after_default"
    107             def f():
    108                 self.module.warn(message, UserWarning)
    109 
    110             with support.captured_stderr() as stderr:
    111                 f()
    112             stderr = stderr.getvalue()
    113             self.assertIn("UserWarning: FilterTests.test_ignore_after_default",
    114                           stderr)
    115             self.assertIn("self.module.warn(message, UserWarning)",
    116                           stderr)
    117 
    118             self.module.filterwarnings("error", category=UserWarning)
    119             self.assertRaises(UserWarning, f)
    120 
    121     def test_ignore(self):
    122         with original_warnings.catch_warnings(record=True,
    123                 module=self.module) as w:
    124             self.module.resetwarnings()
    125             self.module.filterwarnings("ignore", category=UserWarning)
    126             self.module.warn("FilterTests.test_ignore", UserWarning)
    127             self.assertEqual(len(w), 0)
    128 
    129     def test_ignore_after_default(self):
    130         with original_warnings.catch_warnings(record=True,
    131                 module=self.module) as w:
    132             self.module.resetwarnings()
    133             message = "FilterTests.test_ignore_after_default"
    134             def f():
    135                 self.module.warn(message, UserWarning)
    136             f()
    137             self.module.filterwarnings("ignore", category=UserWarning)
    138             f()
    139             f()
    140             self.assertEqual(len(w), 1)
    141 
    142     def test_always(self):
    143         with original_warnings.catch_warnings(record=True,
    144                 module=self.module) as w:
    145             self.module.resetwarnings()
    146             self.module.filterwarnings("always", category=UserWarning)
    147             message = "FilterTests.test_always"
    148             self.module.warn(message, UserWarning)
    149             self.assertTrue(message, w[-1].message)
    150             self.module.warn(message, UserWarning)
    151             self.assertTrue(w[-1].message, message)
    152 
    153     def test_always_after_default(self):
    154         with original_warnings.catch_warnings(record=True,
    155                 module=self.module) as w:
    156             self.module.resetwarnings()
    157             message = "FilterTests.test_always_after_ignore"
    158             def f():
    159                 self.module.warn(message, UserWarning)
    160             f()
    161             self.assertEqual(len(w), 1)
    162             self.assertEqual(w[-1].message.args[0], message)
    163             f()
    164             self.assertEqual(len(w), 1)
    165             self.module.filterwarnings("always", category=UserWarning)
    166             f()
    167             self.assertEqual(len(w), 2)
    168             self.assertEqual(w[-1].message.args[0], message)
    169             f()
    170             self.assertEqual(len(w), 3)
    171             self.assertEqual(w[-1].message.args[0], message)
    172 
    173     def test_default(self):
    174         with original_warnings.catch_warnings(record=True,
    175                 module=self.module) as w:
    176             self.module.resetwarnings()
    177             self.module.filterwarnings("default", category=UserWarning)
    178             message = UserWarning("FilterTests.test_default")
    179             for x in range(2):
    180                 self.module.warn(message, UserWarning)
    181                 if x == 0:
    182                     self.assertEqual(w[-1].message, message)
    183                     del w[:]
    184                 elif x == 1:
    185                     self.assertEqual(len(w), 0)
    186                 else:
    187                     raise ValueError("loop variant unhandled")
    188 
    189     def test_module(self):
    190         with original_warnings.catch_warnings(record=True,
    191                 module=self.module) as w:
    192             self.module.resetwarnings()
    193             self.module.filterwarnings("module", category=UserWarning)
    194             message = UserWarning("FilterTests.test_module")
    195             self.module.warn(message, UserWarning)
    196             self.assertEqual(w[-1].message, message)
    197             del w[:]
    198             self.module.warn(message, UserWarning)
    199             self.assertEqual(len(w), 0)
    200 
    201     def test_once(self):
    202         with original_warnings.catch_warnings(record=True,
    203                 module=self.module) as w:
    204             self.module.resetwarnings()
    205             self.module.filterwarnings("once", category=UserWarning)
    206             message = UserWarning("FilterTests.test_once")
    207             self.module.warn_explicit(message, UserWarning, "__init__.py",
    208                                     42)
    209             self.assertEqual(w[-1].message, message)
    210             del w[:]
    211             self.module.warn_explicit(message, UserWarning, "__init__.py",
    212                                     13)
    213             self.assertEqual(len(w), 0)
    214             self.module.warn_explicit(message, UserWarning, "test_warnings2.py",
    215                                     42)
    216             self.assertEqual(len(w), 0)
    217 
    218     def test_inheritance(self):
    219         with original_warnings.catch_warnings(module=self.module) as w:
    220             self.module.resetwarnings()
    221             self.module.filterwarnings("error", category=Warning)
    222             self.assertRaises(UserWarning, self.module.warn,
    223                                 "FilterTests.test_inheritance", UserWarning)
    224 
    225     def test_ordering(self):
    226         with original_warnings.catch_warnings(record=True,
    227                 module=self.module) as w:
    228             self.module.resetwarnings()
    229             self.module.filterwarnings("ignore", category=UserWarning)
    230             self.module.filterwarnings("error", category=UserWarning,
    231                                         append=True)
    232             del w[:]
    233             try:
    234                 self.module.warn("FilterTests.test_ordering", UserWarning)
    235             except UserWarning:
    236                 self.fail("order handling for actions failed")
    237             self.assertEqual(len(w), 0)
    238 
    239     def test_filterwarnings(self):
    240         # Test filterwarnings().
    241         # Implicitly also tests resetwarnings().
    242         with original_warnings.catch_warnings(record=True,
    243                 module=self.module) as w:
    244             self.module.filterwarnings("error", "", Warning, "", 0)
    245             self.assertRaises(UserWarning, self.module.warn, 'convert to error')
    246 
    247             self.module.resetwarnings()
    248             text = 'handle normally'
    249             self.module.warn(text)
    250             self.assertEqual(str(w[-1].message), text)
    251             self.assertTrue(w[-1].category is UserWarning)
    252 
    253             self.module.filterwarnings("ignore", "", Warning, "", 0)
    254             text = 'filtered out'
    255             self.module.warn(text)
    256             self.assertNotEqual(str(w[-1].message), text)
    257 
    258             self.module.resetwarnings()
    259             self.module.filterwarnings("error", "hex*", Warning, "", 0)
    260             self.assertRaises(UserWarning, self.module.warn, 'hex/oct')
    261             text = 'nonmatching text'
    262             self.module.warn(text)
    263             self.assertEqual(str(w[-1].message), text)
    264             self.assertTrue(w[-1].category is UserWarning)
    265 
    266     def test_message_matching(self):
    267         with original_warnings.catch_warnings(record=True,
    268                 module=self.module) as w:
    269             self.module.simplefilter("ignore", UserWarning)
    270             self.module.filterwarnings("error", "match", UserWarning)
    271             self.assertRaises(UserWarning, self.module.warn, "match")
    272             self.assertRaises(UserWarning, self.module.warn, "match prefix")
    273             self.module.warn("suffix match")
    274             self.assertEqual(w, [])
    275             self.module.warn("something completely different")
    276             self.assertEqual(w, [])
    277 
    278     def test_mutate_filter_list(self):
    279         class X:
    280             def match(self, a):
    281                 L[:] = []
    282 
    283         L = [("default",X(),UserWarning,X(),0) for i in range(2)]
    284         with original_warnings.catch_warnings(record=True,
    285                 module=self.module) as w:
    286             self.module.filters = L
    287             self.module.warn_explicit(UserWarning("b"), None, "f.py", 42)
    288             self.assertEqual(str(w[-1].message), "b")
    289 
    290     def test_filterwarnings_duplicate_filters(self):
    291         with original_warnings.catch_warnings(module=self.module):
    292             self.module.resetwarnings()
    293             self.module.filterwarnings("error", category=UserWarning)
    294             self.assertEqual(len(self.module.filters), 1)
    295             self.module.filterwarnings("ignore", category=UserWarning)
    296             self.module.filterwarnings("error", category=UserWarning)
    297             self.assertEqual(
    298                 len(self.module.filters), 2,
    299                 "filterwarnings inserted duplicate filter"
    300             )
    301             self.assertEqual(
    302                 self.module.filters[0][0], "error",
    303                 "filterwarnings did not promote filter to "
    304                 "the beginning of list"
    305             )
    306 
    307     def test_simplefilter_duplicate_filters(self):
    308         with original_warnings.catch_warnings(module=self.module):
    309             self.module.resetwarnings()
    310             self.module.simplefilter("error", category=UserWarning)
    311             self.assertEqual(len(self.module.filters), 1)
    312             self.module.simplefilter("ignore", category=UserWarning)
    313             self.module.simplefilter("error", category=UserWarning)
    314             self.assertEqual(
    315                 len(self.module.filters), 2,
    316                 "simplefilter inserted duplicate filter"
    317             )
    318             self.assertEqual(
    319                 self.module.filters[0][0], "error",
    320                 "simplefilter did not promote filter to the beginning of list"
    321             )
    322     def test_append_duplicate(self):
    323         with original_warnings.catch_warnings(module=self.module,
    324                 record=True) as w:
    325             self.module.resetwarnings()
    326             self.module.simplefilter("ignore")
    327             self.module.simplefilter("error", append=True)
    328             self.module.simplefilter("ignore", append=True)
    329             self.module.warn("test_append_duplicate", category=UserWarning)
    330             self.assertEqual(len(self.module.filters), 2,
    331                 "simplefilter inserted duplicate filter"
    332             )
    333             self.assertEqual(len(w), 0,
    334                 "appended duplicate changed order of filters"
    335             )
    336 
    337 class CFilterTests(FilterTests, unittest.TestCase):
    338     module = c_warnings
    339 
    340 class PyFilterTests(FilterTests, unittest.TestCase):
    341     module = py_warnings
    342 
    343 
    344 class WarnTests(BaseTest):
    345 
    346     """Test warnings.warn() and warnings.warn_explicit()."""
    347 
    348     def test_message(self):
    349         with original_warnings.catch_warnings(record=True,
    350                 module=self.module) as w:
    351             self.module.simplefilter("once")
    352             for i in range(4):
    353                 text = 'multi %d' %i  # Different text on each call.
    354                 self.module.warn(text)
    355                 self.assertEqual(str(w[-1].message), text)
    356                 self.assertTrue(w[-1].category is UserWarning)
    357 
    358     # Issue 3639
    359     def test_warn_nonstandard_types(self):
    360         # warn() should handle non-standard types without issue.
    361         for ob in (Warning, None, 42):
    362             with original_warnings.catch_warnings(record=True,
    363                     module=self.module) as w:
    364                 self.module.simplefilter("once")
    365                 self.module.warn(ob)
    366                 # Don't directly compare objects since
    367                 # ``Warning() != Warning()``.
    368                 self.assertEqual(str(w[-1].message), str(UserWarning(ob)))
    369 
    370     def test_filename(self):
    371         with warnings_state(self.module):
    372             with original_warnings.catch_warnings(record=True,
    373                     module=self.module) as w:
    374                 warning_tests.inner("spam1")
    375                 self.assertEqual(os.path.basename(w[-1].filename),
    376                                     "stacklevel.py")
    377                 warning_tests.outer("spam2")
    378                 self.assertEqual(os.path.basename(w[-1].filename),
    379                                     "stacklevel.py")
    380 
    381     def test_stacklevel(self):
    382         # Test stacklevel argument
    383         # make sure all messages are different, so the warning won't be skipped
    384         with warnings_state(self.module):
    385             with original_warnings.catch_warnings(record=True,
    386                     module=self.module) as w:
    387                 warning_tests.inner("spam3", stacklevel=1)
    388                 self.assertEqual(os.path.basename(w[-1].filename),
    389                                     "stacklevel.py")
    390                 warning_tests.outer("spam4", stacklevel=1)
    391                 self.assertEqual(os.path.basename(w[-1].filename),
    392                                     "stacklevel.py")
    393 
    394                 warning_tests.inner("spam5", stacklevel=2)
    395                 self.assertEqual(os.path.basename(w[-1].filename),
    396                                     "__init__.py")
    397                 warning_tests.outer("spam6", stacklevel=2)
    398                 self.assertEqual(os.path.basename(w[-1].filename),
    399                                     "stacklevel.py")
    400                 warning_tests.outer("spam6.5", stacklevel=3)
    401                 self.assertEqual(os.path.basename(w[-1].filename),
    402                                     "__init__.py")
    403 
    404                 warning_tests.inner("spam7", stacklevel=9999)
    405                 self.assertEqual(os.path.basename(w[-1].filename),
    406                                     "sys")
    407 
    408     def test_stacklevel_import(self):
    409         # Issue #24305: With stacklevel=2, module-level warnings should work.
    410         support.unload('test.test_warnings.data.import_warning')
    411         with warnings_state(self.module):
    412             with original_warnings.catch_warnings(record=True,
    413                     module=self.module) as w:
    414                 self.module.simplefilter('always')
    415                 import test.test_warnings.data.import_warning
    416                 self.assertEqual(len(w), 1)
    417                 self.assertEqual(w[0].filename, __file__)
    418 
    419     def test_missing_filename_not_main(self):
    420         # If __file__ is not specified and __main__ is not the module name,
    421         # then __file__ should be set to the module name.
    422         filename = warning_tests.__file__
    423         try:
    424             del warning_tests.__file__
    425             with warnings_state(self.module):
    426                 with original_warnings.catch_warnings(record=True,
    427                         module=self.module) as w:
    428                     warning_tests.inner("spam8", stacklevel=1)
    429                     self.assertEqual(w[-1].filename, warning_tests.__name__)
    430         finally:
    431             warning_tests.__file__ = filename
    432 
    433     @unittest.skipUnless(hasattr(sys, 'argv'), 'test needs sys.argv')
    434     def test_missing_filename_main_with_argv(self):
    435         # If __file__ is not specified and the caller is __main__ and sys.argv
    436         # exists, then use sys.argv[0] as the file.
    437         filename = warning_tests.__file__
    438         module_name = warning_tests.__name__
    439         try:
    440             del warning_tests.__file__
    441             warning_tests.__name__ = '__main__'
    442             with warnings_state(self.module):
    443                 with original_warnings.catch_warnings(record=True,
    444                         module=self.module) as w:
    445                     warning_tests.inner('spam9', stacklevel=1)
    446                     self.assertEqual(w[-1].filename, sys.argv[0])
    447         finally:
    448             warning_tests.__file__ = filename
    449             warning_tests.__name__ = module_name
    450 
    451     def test_missing_filename_main_without_argv(self):
    452         # If __file__ is not specified, the caller is __main__, and sys.argv
    453         # is not set, then '__main__' is the file name.
    454         filename = warning_tests.__file__
    455         module_name = warning_tests.__name__
    456         argv = sys.argv
    457         try:
    458             del warning_tests.__file__
    459             warning_tests.__name__ = '__main__'
    460             del sys.argv
    461             with warnings_state(self.module):
    462                 with original_warnings.catch_warnings(record=True,
    463                         module=self.module) as w:
    464                     warning_tests.inner('spam10', stacklevel=1)
    465                     self.assertEqual(w[-1].filename, '__main__')
    466         finally:
    467             warning_tests.__file__ = filename
    468             warning_tests.__name__ = module_name
    469             sys.argv = argv
    470 
    471     def test_missing_filename_main_with_argv_empty_string(self):
    472         # If __file__ is not specified, the caller is __main__, and sys.argv[0]
    473         # is the empty string, then '__main__ is the file name.
    474         # Tests issue 2743.
    475         file_name = warning_tests.__file__
    476         module_name = warning_tests.__name__
    477         argv = sys.argv
    478         try:
    479             del warning_tests.__file__
    480             warning_tests.__name__ = '__main__'
    481             sys.argv = ['']
    482             with warnings_state(self.module):
    483                 with original_warnings.catch_warnings(record=True,
    484                         module=self.module) as w:
    485                     warning_tests.inner('spam11', stacklevel=1)
    486                     self.assertEqual(w[-1].filename, '__main__')
    487         finally:
    488             warning_tests.__file__ = file_name
    489             warning_tests.__name__ = module_name
    490             sys.argv = argv
    491 
    492     def test_warn_explicit_non_ascii_filename(self):
    493         with original_warnings.catch_warnings(record=True,
    494                 module=self.module) as w:
    495             self.module.resetwarnings()
    496             self.module.filterwarnings("always", category=UserWarning)
    497             for filename in ("nonascii\xe9\u20ac", "surrogate\udc80"):
    498                 try:
    499                     os.fsencode(filename)
    500                 except UnicodeEncodeError:
    501                     continue
    502                 self.module.warn_explicit("text", UserWarning, filename, 1)
    503                 self.assertEqual(w[-1].filename, filename)
    504 
    505     def test_warn_explicit_type_errors(self):
    506         # warn_explicit() should error out gracefully if it is given objects
    507         # of the wrong types.
    508         # lineno is expected to be an integer.
    509         self.assertRaises(TypeError, self.module.warn_explicit,
    510                             None, UserWarning, None, None)
    511         # Either 'message' needs to be an instance of Warning or 'category'
    512         # needs to be a subclass.
    513         self.assertRaises(TypeError, self.module.warn_explicit,
    514                             None, None, None, 1)
    515         # 'registry' must be a dict or None.
    516         self.assertRaises((TypeError, AttributeError),
    517                             self.module.warn_explicit,
    518                             None, Warning, None, 1, registry=42)
    519 
    520     def test_bad_str(self):
    521         # issue 6415
    522         # Warnings instance with a bad format string for __str__ should not
    523         # trigger a bus error.
    524         class BadStrWarning(Warning):
    525             """Warning with a bad format string for __str__."""
    526             def __str__(self):
    527                 return ("A bad formatted string %(err)" %
    528                         {"err" : "there is no %(err)s"})
    529 
    530         with self.assertRaises(ValueError):
    531             self.module.warn(BadStrWarning())
    532 
    533     def test_warning_classes(self):
    534         class MyWarningClass(Warning):
    535             pass
    536 
    537         class NonWarningSubclass:
    538             pass
    539 
    540         # passing a non-subclass of Warning should raise a TypeError
    541         with self.assertRaises(TypeError) as cm:
    542             self.module.warn('bad warning category', '')
    543         self.assertIn('category must be a Warning subclass, not ',
    544                       str(cm.exception))
    545 
    546         with self.assertRaises(TypeError) as cm:
    547             self.module.warn('bad warning category', NonWarningSubclass)
    548         self.assertIn('category must be a Warning subclass, not ',
    549                       str(cm.exception))
    550 
    551         # check that warning instances also raise a TypeError
    552         with self.assertRaises(TypeError) as cm:
    553             self.module.warn('bad warning category', MyWarningClass())
    554         self.assertIn('category must be a Warning subclass, not ',
    555                       str(cm.exception))
    556 
    557         with original_warnings.catch_warnings(module=self.module):
    558             self.module.resetwarnings()
    559             self.module.filterwarnings('default')
    560             with self.assertWarns(MyWarningClass) as cm:
    561                 self.module.warn('good warning category', MyWarningClass)
    562             self.assertEqual('good warning category', str(cm.warning))
    563 
    564             with self.assertWarns(UserWarning) as cm:
    565                 self.module.warn('good warning category', None)
    566             self.assertEqual('good warning category', str(cm.warning))
    567 
    568             with self.assertWarns(MyWarningClass) as cm:
    569                 self.module.warn('good warning category', MyWarningClass)
    570             self.assertIsInstance(cm.warning, Warning)
    571 
    572 class CWarnTests(WarnTests, unittest.TestCase):
    573     module = c_warnings
    574 
    575     # As an early adopter, we sanity check the
    576     # test.support.import_fresh_module utility function
    577     def test_accelerated(self):
    578         self.assertFalse(original_warnings is self.module)
    579         self.assertFalse(hasattr(self.module.warn, '__code__'))
    580 
    581 class PyWarnTests(WarnTests, unittest.TestCase):
    582     module = py_warnings
    583 
    584     # As an early adopter, we sanity check the
    585     # test.support.import_fresh_module utility function
    586     def test_pure_python(self):
    587         self.assertFalse(original_warnings is self.module)
    588         self.assertTrue(hasattr(self.module.warn, '__code__'))
    589 
    590 
    591 class WCmdLineTests(BaseTest):
    592 
    593     def test_improper_input(self):
    594         # Uses the private _setoption() function to test the parsing
    595         # of command-line warning arguments
    596         with original_warnings.catch_warnings(module=self.module):
    597             self.assertRaises(self.module._OptionError,
    598                               self.module._setoption, '1:2:3:4:5:6')
    599             self.assertRaises(self.module._OptionError,
    600                               self.module._setoption, 'bogus::Warning')
    601             self.assertRaises(self.module._OptionError,
    602                               self.module._setoption, 'ignore:2::4:-5')
    603             self.module._setoption('error::Warning::0')
    604             self.assertRaises(UserWarning, self.module.warn, 'convert to error')
    605 
    606 
    607 class CWCmdLineTests(WCmdLineTests, unittest.TestCase):
    608     module = c_warnings
    609 
    610 
    611 class PyWCmdLineTests(WCmdLineTests, unittest.TestCase):
    612     module = py_warnings
    613 
    614     def test_improper_option(self):
    615         # Same as above, but check that the message is printed out when
    616         # the interpreter is executed. This also checks that options are
    617         # actually parsed at all.
    618         rc, out, err = assert_python_ok("-Wxxx", "-c", "pass")
    619         self.assertIn(b"Invalid -W option ignored: invalid action: 'xxx'", err)
    620 
    621     def test_warnings_bootstrap(self):
    622         # Check that the warnings module does get loaded when -W<some option>
    623         # is used (see issue #10372 for an example of silent bootstrap failure).
    624         rc, out, err = assert_python_ok("-Wi", "-c",
    625             "import sys; sys.modules['warnings'].warn('foo', RuntimeWarning)")
    626         # '-Wi' was observed
    627         self.assertFalse(out.strip())
    628         self.assertNotIn(b'RuntimeWarning', err)
    629 
    630 
    631 class _WarningsTests(BaseTest, unittest.TestCase):
    632 
    633     """Tests specific to the _warnings module."""
    634 
    635     module = c_warnings
    636 
    637     def test_filter(self):
    638         # Everything should function even if 'filters' is not in warnings.
    639         with original_warnings.catch_warnings(module=self.module) as w:
    640             self.module.filterwarnings("error", "", Warning, "", 0)
    641             self.assertRaises(UserWarning, self.module.warn,
    642                                 'convert to error')
    643             del self.module.filters
    644             self.assertRaises(UserWarning, self.module.warn,
    645                                 'convert to error')
    646 
    647     def test_onceregistry(self):
    648         # Replacing or removing the onceregistry should be okay.
    649         global __warningregistry__
    650         message = UserWarning('onceregistry test')
    651         try:
    652             original_registry = self.module.onceregistry
    653             __warningregistry__ = {}
    654             with original_warnings.catch_warnings(record=True,
    655                     module=self.module) as w:
    656                 self.module.resetwarnings()
    657                 self.module.filterwarnings("once", category=UserWarning)
    658                 self.module.warn_explicit(message, UserWarning, "file", 42)
    659                 self.assertEqual(w[-1].message, message)
    660                 del w[:]
    661                 self.module.warn_explicit(message, UserWarning, "file", 42)
    662                 self.assertEqual(len(w), 0)
    663                 # Test the resetting of onceregistry.
    664                 self.module.onceregistry = {}
    665                 __warningregistry__ = {}
    666                 self.module.warn('onceregistry test')
    667                 self.assertEqual(w[-1].message.args, message.args)
    668                 # Removal of onceregistry is okay.
    669                 del w[:]
    670                 del self.module.onceregistry
    671                 __warningregistry__ = {}
    672                 self.module.warn_explicit(message, UserWarning, "file", 42)
    673                 self.assertEqual(len(w), 0)
    674         finally:
    675             self.module.onceregistry = original_registry
    676 
    677     def test_default_action(self):
    678         # Replacing or removing defaultaction should be okay.
    679         message = UserWarning("defaultaction test")
    680         original = self.module.defaultaction
    681         try:
    682             with original_warnings.catch_warnings(record=True,
    683                     module=self.module) as w:
    684                 self.module.resetwarnings()
    685                 registry = {}
    686                 self.module.warn_explicit(message, UserWarning, "<test>", 42,
    687                                             registry=registry)
    688                 self.assertEqual(w[-1].message, message)
    689                 self.assertEqual(len(w), 1)
    690                 # One actual registry key plus the "version" key
    691                 self.assertEqual(len(registry), 2)
    692                 self.assertIn("version", registry)
    693                 del w[:]
    694                 # Test removal.
    695                 del self.module.defaultaction
    696                 __warningregistry__ = {}
    697                 registry = {}
    698                 self.module.warn_explicit(message, UserWarning, "<test>", 43,
    699                                             registry=registry)
    700                 self.assertEqual(w[-1].message, message)
    701                 self.assertEqual(len(w), 1)
    702                 self.assertEqual(len(registry), 2)
    703                 del w[:]
    704                 # Test setting.
    705                 self.module.defaultaction = "ignore"
    706                 __warningregistry__ = {}
    707                 registry = {}
    708                 self.module.warn_explicit(message, UserWarning, "<test>", 44,
    709                                             registry=registry)
    710                 self.assertEqual(len(w), 0)
    711         finally:
    712             self.module.defaultaction = original
    713 
    714     def test_showwarning_missing(self):
    715         # Test that showwarning() missing is okay.
    716         text = 'del showwarning test'
    717         with original_warnings.catch_warnings(module=self.module):
    718             self.module.filterwarnings("always", category=UserWarning)
    719             del self.module.showwarning
    720             with support.captured_output('stderr') as stream:
    721                 self.module.warn(text)
    722                 result = stream.getvalue()
    723         self.assertIn(text, result)
    724 
    725     def test_showwarnmsg_missing(self):
    726         # Test that _showwarnmsg() missing is okay.
    727         text = 'del _showwarnmsg test'
    728         with original_warnings.catch_warnings(module=self.module):
    729             self.module.filterwarnings("always", category=UserWarning)
    730             del self.module._showwarnmsg
    731             with support.captured_output('stderr') as stream:
    732                 self.module.warn(text)
    733                 result = stream.getvalue()
    734         self.assertIn(text, result)
    735 
    736     def test_showwarning_not_callable(self):
    737         with original_warnings.catch_warnings(module=self.module):
    738             self.module.filterwarnings("always", category=UserWarning)
    739             self.module.showwarning = print
    740             with support.captured_output('stdout'):
    741                 self.module.warn('Warning!')
    742             self.module.showwarning = 23
    743             self.assertRaises(TypeError, self.module.warn, "Warning!")
    744 
    745     def test_show_warning_output(self):
    746         # With showarning() missing, make sure that output is okay.
    747         text = 'test show_warning'
    748         with original_warnings.catch_warnings(module=self.module):
    749             self.module.filterwarnings("always", category=UserWarning)
    750             del self.module.showwarning
    751             with support.captured_output('stderr') as stream:
    752                 warning_tests.inner(text)
    753                 result = stream.getvalue()
    754         self.assertEqual(result.count('\n'), 2,
    755                              "Too many newlines in %r" % result)
    756         first_line, second_line = result.split('\n', 1)
    757         expected_file = os.path.splitext(warning_tests.__file__)[0] + '.py'
    758         first_line_parts = first_line.rsplit(':', 3)
    759         path, line, warning_class, message = first_line_parts
    760         line = int(line)
    761         self.assertEqual(expected_file, path)
    762         self.assertEqual(warning_class, ' ' + UserWarning.__name__)
    763         self.assertEqual(message, ' ' + text)
    764         expected_line = '  ' + linecache.getline(path, line).strip() + '\n'
    765         assert expected_line
    766         self.assertEqual(second_line, expected_line)
    767 
    768     def test_filename_none(self):
    769         # issue #12467: race condition if a warning is emitted at shutdown
    770         globals_dict = globals()
    771         oldfile = globals_dict['__file__']
    772         try:
    773             catch = original_warnings.catch_warnings(record=True,
    774                                                      module=self.module)
    775             with catch as w:
    776                 self.module.filterwarnings("always", category=UserWarning)
    777                 globals_dict['__file__'] = None
    778                 original_warnings.warn('test', UserWarning)
    779                 self.assertTrue(len(w))
    780         finally:
    781             globals_dict['__file__'] = oldfile
    782 
    783     def test_stderr_none(self):
    784         rc, stdout, stderr = assert_python_ok("-c",
    785             "import sys; sys.stderr = None; "
    786             "import warnings; warnings.simplefilter('always'); "
    787             "warnings.warn('Warning!')")
    788         self.assertEqual(stdout, b'')
    789         self.assertNotIn(b'Warning!', stderr)
    790         self.assertNotIn(b'Error', stderr)
    791 
    792 
    793 class WarningsDisplayTests(BaseTest):
    794 
    795     """Test the displaying of warnings and the ability to overload functions
    796     related to displaying warnings."""
    797 
    798     def test_formatwarning(self):
    799         message = "msg"
    800         category = Warning
    801         file_name = os.path.splitext(warning_tests.__file__)[0] + '.py'
    802         line_num = 3
    803         file_line = linecache.getline(file_name, line_num).strip()
    804         format = "%s:%s: %s: %s\n  %s\n"
    805         expect = format % (file_name, line_num, category.__name__, message,
    806                             file_line)
    807         self.assertEqual(expect, self.module.formatwarning(message,
    808                                                 category, file_name, line_num))
    809         # Test the 'line' argument.
    810         file_line += " for the win!"
    811         expect = format % (file_name, line_num, category.__name__, message,
    812                             file_line)
    813         self.assertEqual(expect, self.module.formatwarning(message,
    814                                     category, file_name, line_num, file_line))
    815 
    816     def test_showwarning(self):
    817         file_name = os.path.splitext(warning_tests.__file__)[0] + '.py'
    818         line_num = 3
    819         expected_file_line = linecache.getline(file_name, line_num).strip()
    820         message = 'msg'
    821         category = Warning
    822         file_object = StringIO()
    823         expect = self.module.formatwarning(message, category, file_name,
    824                                             line_num)
    825         self.module.showwarning(message, category, file_name, line_num,
    826                                 file_object)
    827         self.assertEqual(file_object.getvalue(), expect)
    828         # Test 'line' argument.
    829         expected_file_line += "for the win!"
    830         expect = self.module.formatwarning(message, category, file_name,
    831                                             line_num, expected_file_line)
    832         file_object = StringIO()
    833         self.module.showwarning(message, category, file_name, line_num,
    834                                 file_object, expected_file_line)
    835         self.assertEqual(expect, file_object.getvalue())
    836 
    837 
    838 class CWarningsDisplayTests(WarningsDisplayTests, unittest.TestCase):
    839     module = c_warnings
    840 
    841 class PyWarningsDisplayTests(WarningsDisplayTests, unittest.TestCase):
    842     module = py_warnings
    843 
    844     def test_tracemalloc(self):
    845         self.addCleanup(support.unlink, support.TESTFN)
    846 
    847         with open(support.TESTFN, 'w') as fp:
    848             fp.write(textwrap.dedent("""
    849                 def func():
    850                     f = open(__file__)
    851                     # Emit ResourceWarning
    852                     f = None
    853 
    854                 func()
    855             """))
    856 
    857         res = assert_python_ok('-Wd', '-X', 'tracemalloc=2', support.TESTFN)
    858 
    859         stderr = res.err.decode('ascii', 'replace')
    860         # normalize newlines
    861         stderr = '\n'.join(stderr.splitlines())
    862         stderr = re.sub('<.*>', '<...>', stderr)
    863         expected = textwrap.dedent('''
    864             {fname}:5: ResourceWarning: unclosed file <...>
    865               f = None
    866             Object allocated at (most recent call first):
    867               File "{fname}", lineno 3
    868                 f = open(__file__)
    869               File "{fname}", lineno 7
    870                 func()
    871         ''')
    872         expected = expected.format(fname=support.TESTFN).strip()
    873         self.assertEqual(stderr, expected)
    874 
    875 
    876 class CatchWarningTests(BaseTest):
    877 
    878     """Test catch_warnings()."""
    879 
    880     def test_catch_warnings_restore(self):
    881         wmod = self.module
    882         orig_filters = wmod.filters
    883         orig_showwarning = wmod.showwarning
    884         # Ensure both showwarning and filters are restored when recording
    885         with wmod.catch_warnings(module=wmod, record=True):
    886             wmod.filters = wmod.showwarning = object()
    887         self.assertTrue(wmod.filters is orig_filters)
    888         self.assertTrue(wmod.showwarning is orig_showwarning)
    889         # Same test, but with recording disabled
    890         with wmod.catch_warnings(module=wmod, record=False):
    891             wmod.filters = wmod.showwarning = object()
    892         self.assertTrue(wmod.filters is orig_filters)
    893         self.assertTrue(wmod.showwarning is orig_showwarning)
    894 
    895     def test_catch_warnings_recording(self):
    896         wmod = self.module
    897         # Ensure warnings are recorded when requested
    898         with wmod.catch_warnings(module=wmod, record=True) as w:
    899             self.assertEqual(w, [])
    900             self.assertTrue(type(w) is list)
    901             wmod.simplefilter("always")
    902             wmod.warn("foo")
    903             self.assertEqual(str(w[-1].message), "foo")
    904             wmod.warn("bar")
    905             self.assertEqual(str(w[-1].message), "bar")
    906             self.assertEqual(str(w[0].message), "foo")
    907             self.assertEqual(str(w[1].message), "bar")
    908             del w[:]
    909             self.assertEqual(w, [])
    910         # Ensure warnings are not recorded when not requested
    911         orig_showwarning = wmod.showwarning
    912         with wmod.catch_warnings(module=wmod, record=False) as w:
    913             self.assertTrue(w is None)
    914             self.assertTrue(wmod.showwarning is orig_showwarning)
    915 
    916     def test_catch_warnings_reentry_guard(self):
    917         wmod = self.module
    918         # Ensure catch_warnings is protected against incorrect usage
    919         x = wmod.catch_warnings(module=wmod, record=True)
    920         self.assertRaises(RuntimeError, x.__exit__)
    921         with x:
    922             self.assertRaises(RuntimeError, x.__enter__)
    923         # Same test, but with recording disabled
    924         x = wmod.catch_warnings(module=wmod, record=False)
    925         self.assertRaises(RuntimeError, x.__exit__)
    926         with x:
    927             self.assertRaises(RuntimeError, x.__enter__)
    928 
    929     def test_catch_warnings_defaults(self):
    930         wmod = self.module
    931         orig_filters = wmod.filters
    932         orig_showwarning = wmod.showwarning
    933         # Ensure default behaviour is not to record warnings
    934         with wmod.catch_warnings(module=wmod) as w:
    935             self.assertTrue(w is None)
    936             self.assertTrue(wmod.showwarning is orig_showwarning)
    937             self.assertTrue(wmod.filters is not orig_filters)
    938         self.assertTrue(wmod.filters is orig_filters)
    939         if wmod is sys.modules['warnings']:
    940             # Ensure the default module is this one
    941             with wmod.catch_warnings() as w:
    942                 self.assertTrue(w is None)
    943                 self.assertTrue(wmod.showwarning is orig_showwarning)
    944                 self.assertTrue(wmod.filters is not orig_filters)
    945             self.assertTrue(wmod.filters is orig_filters)
    946 
    947     def test_record_override_showwarning_before(self):
    948         # Issue #28835: If warnings.showwarning() was overriden, make sure
    949         # that catch_warnings(record=True) overrides it again.
    950         text = "This is a warning"
    951         wmod = self.module
    952         my_log = []
    953 
    954         def my_logger(message, category, filename, lineno, file=None, line=None):
    955             nonlocal my_log
    956             my_log.append(message)
    957 
    958         # Override warnings.showwarning() before calling catch_warnings()
    959         with support.swap_attr(wmod, 'showwarning', my_logger):
    960             with wmod.catch_warnings(module=wmod, record=True) as log:
    961                 self.assertIsNot(wmod.showwarning, my_logger)
    962 
    963                 wmod.simplefilter("always")
    964                 wmod.warn(text)
    965 
    966             self.assertIs(wmod.showwarning, my_logger)
    967 
    968         self.assertEqual(len(log), 1, log)
    969         self.assertEqual(log[0].message.args[0], text)
    970         self.assertEqual(my_log, [])
    971 
    972     def test_record_override_showwarning_inside(self):
    973         # Issue #28835: It is possible to override warnings.showwarning()
    974         # in the catch_warnings(record=True) context manager.
    975         text = "This is a warning"
    976         wmod = self.module
    977         my_log = []
    978 
    979         def my_logger(message, category, filename, lineno, file=None, line=None):
    980             nonlocal my_log
    981             my_log.append(message)
    982 
    983         with wmod.catch_warnings(module=wmod, record=True) as log:
    984             wmod.simplefilter("always")
    985             wmod.showwarning = my_logger
    986             wmod.warn(text)
    987 
    988         self.assertEqual(len(my_log), 1, my_log)
    989         self.assertEqual(my_log[0].args[0], text)
    990         self.assertEqual(log, [])
    991 
    992     def test_check_warnings(self):
    993         # Explicit tests for the test.support convenience wrapper
    994         wmod = self.module
    995         if wmod is not sys.modules['warnings']:
    996             self.skipTest('module to test is not loaded warnings module')
    997         with support.check_warnings(quiet=False) as w:
    998             self.assertEqual(w.warnings, [])
    999             wmod.simplefilter("always")
   1000             wmod.warn("foo")
   1001             self.assertEqual(str(w.message), "foo")
   1002             wmod.warn("bar")
   1003             self.assertEqual(str(w.message), "bar")
   1004             self.assertEqual(str(w.warnings[0].message), "foo")
   1005             self.assertEqual(str(w.warnings[1].message), "bar")
   1006             w.reset()
   1007             self.assertEqual(w.warnings, [])
   1008 
   1009         with support.check_warnings():
   1010             # defaults to quiet=True without argument
   1011             pass
   1012         with support.check_warnings(('foo', UserWarning)):
   1013             wmod.warn("foo")
   1014 
   1015         with self.assertRaises(AssertionError):
   1016             with support.check_warnings(('', RuntimeWarning)):
   1017                 # defaults to quiet=False with argument
   1018                 pass
   1019         with self.assertRaises(AssertionError):
   1020             with support.check_warnings(('foo', RuntimeWarning)):
   1021                 wmod.warn("foo")
   1022 
   1023 class CCatchWarningTests(CatchWarningTests, unittest.TestCase):
   1024     module = c_warnings
   1025 
   1026 class PyCatchWarningTests(CatchWarningTests, unittest.TestCase):
   1027     module = py_warnings
   1028 
   1029 
   1030 class EnvironmentVariableTests(BaseTest):
   1031 
   1032     def test_single_warning(self):
   1033         rc, stdout, stderr = assert_python_ok("-c",
   1034             "import sys; sys.stdout.write(str(sys.warnoptions))",
   1035             PYTHONWARNINGS="ignore::DeprecationWarning")
   1036         self.assertEqual(stdout, b"['ignore::DeprecationWarning']")
   1037 
   1038     def test_comma_separated_warnings(self):
   1039         rc, stdout, stderr = assert_python_ok("-c",
   1040             "import sys; sys.stdout.write(str(sys.warnoptions))",
   1041             PYTHONWARNINGS="ignore::DeprecationWarning,ignore::UnicodeWarning")
   1042         self.assertEqual(stdout,
   1043             b"['ignore::DeprecationWarning', 'ignore::UnicodeWarning']")
   1044 
   1045     def test_envvar_and_command_line(self):
   1046         rc, stdout, stderr = assert_python_ok("-Wignore::UnicodeWarning", "-c",
   1047             "import sys; sys.stdout.write(str(sys.warnoptions))",
   1048             PYTHONWARNINGS="ignore::DeprecationWarning")
   1049         self.assertEqual(stdout,
   1050             b"['ignore::DeprecationWarning', 'ignore::UnicodeWarning']")
   1051 
   1052     def test_conflicting_envvar_and_command_line(self):
   1053         rc, stdout, stderr = assert_python_failure("-Werror::DeprecationWarning", "-c",
   1054             "import sys, warnings; sys.stdout.write(str(sys.warnoptions)); "
   1055             "warnings.warn('Message', DeprecationWarning)",
   1056             PYTHONWARNINGS="default::DeprecationWarning")
   1057         self.assertEqual(stdout,
   1058             b"['default::DeprecationWarning', 'error::DeprecationWarning']")
   1059         self.assertEqual(stderr.splitlines(),
   1060             [b"Traceback (most recent call last):",
   1061              b"  File \"<string>\", line 1, in <module>",
   1062              b"DeprecationWarning: Message"])
   1063 
   1064     @unittest.skipUnless(sys.getfilesystemencoding() != 'ascii',
   1065                          'requires non-ascii filesystemencoding')
   1066     def test_nonascii(self):
   1067         rc, stdout, stderr = assert_python_ok("-c",
   1068             "import sys; sys.stdout.write(str(sys.warnoptions))",
   1069             PYTHONIOENCODING="utf-8",
   1070             PYTHONWARNINGS="ignore:DeprecacinWarning")
   1071         self.assertEqual(stdout,
   1072             "['ignore:DeprecacinWarning']".encode('utf-8'))
   1073 
   1074 class CEnvironmentVariableTests(EnvironmentVariableTests, unittest.TestCase):
   1075     module = c_warnings
   1076 
   1077 class PyEnvironmentVariableTests(EnvironmentVariableTests, unittest.TestCase):
   1078     module = py_warnings
   1079 
   1080 
   1081 class BootstrapTest(unittest.TestCase):
   1082     def test_issue_8766(self):
   1083         # "import encodings" emits a warning whereas the warnings is not loaded
   1084         # or not completely loaded (warnings imports indirectly encodings by
   1085         # importing linecache) yet
   1086         with support.temp_cwd() as cwd, support.temp_cwd('encodings'):
   1087             # encodings loaded by initfsencoding()
   1088             assert_python_ok('-c', 'pass', PYTHONPATH=cwd)
   1089 
   1090             # Use -W to load warnings module at startup
   1091             assert_python_ok('-c', 'pass', '-W', 'always', PYTHONPATH=cwd)
   1092 
   1093 
   1094 class FinalizationTest(unittest.TestCase):
   1095     @support.requires_type_collecting
   1096     def test_finalization(self):
   1097         # Issue #19421: warnings.warn() should not crash
   1098         # during Python finalization
   1099         code = """
   1100 import warnings
   1101 warn = warnings.warn
   1102 
   1103 class A:
   1104     def __del__(self):
   1105         warn("test")
   1106 
   1107 a=A()
   1108         """
   1109         rc, out, err = assert_python_ok("-c", code)
   1110         # note: "__main__" filename is not correct, it should be the name
   1111         # of the script
   1112         self.assertEqual(err, b'__main__:7: UserWarning: test')
   1113 
   1114     def test_late_resource_warning(self):
   1115         # Issue #21925: Emitting a ResourceWarning late during the Python
   1116         # shutdown must be logged.
   1117 
   1118         expected = b"sys:1: ResourceWarning: unclosed file "
   1119 
   1120         # don't import the warnings module
   1121         # (_warnings will try to import it)
   1122         code = "f = open(%a)" % __file__
   1123         rc, out, err = assert_python_ok("-Wd", "-c", code)
   1124         self.assertTrue(err.startswith(expected), ascii(err))
   1125 
   1126         # import the warnings module
   1127         code = "import warnings; f = open(%a)" % __file__
   1128         rc, out, err = assert_python_ok("-Wd", "-c", code)
   1129         self.assertTrue(err.startswith(expected), ascii(err))
   1130 
   1131 
   1132 def setUpModule():
   1133     py_warnings.onceregistry.clear()
   1134     c_warnings.onceregistry.clear()
   1135 
   1136 tearDownModule = setUpModule
   1137 
   1138 if __name__ == "__main__":
   1139     unittest.main()
   1140