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