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