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