Changeset 391 for python/trunk/Lib/test/test_logging.py
- Timestamp:
- Mar 19, 2014, 11:31:01 PM (11 years ago)
- Location:
- python/trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
python/trunk
-
Property svn:mergeinfo
set to
/python/vendor/Python-2.7.6 merged eligible /python/vendor/current merged eligible
-
Property svn:mergeinfo
set to
-
python/trunk/Lib/test/test_logging.py
r2 r391 1 1 #!/usr/bin/env python 2 2 # 3 # Copyright 2001-20 04by Vinay Sajip. All Rights Reserved.3 # Copyright 2001-2013 by Vinay Sajip. All Rights Reserved. 4 4 # 5 5 # Permission to use, copy, modify, and distribute this software and its … … 19 19 """Test harness for the logging module. Run all tests. 20 20 21 Copyright (C) 2001-20 02Vinay Sajip. All Rights Reserved.21 Copyright (C) 2001-2013 Vinay Sajip. All Rights Reserved. 22 22 """ 23 23 … … 27 27 28 28 import codecs 29 import copy30 29 import cPickle 31 30 import cStringIO 32 31 import gc 32 import json 33 33 import os 34 import random 34 35 import re 35 36 import select 36 37 import socket 37 38 from SocketServer import ThreadingTCPServer, StreamRequestHandler 38 import string39 39 import struct 40 40 import sys … … 42 42 from test.test_support import captured_stdout, run_with_locale, run_unittest 43 43 import textwrap 44 import threading45 44 import time 46 import types47 45 import unittest 46 import warnings 48 47 import weakref 49 48 try: 49 import threading 50 except ImportError: 51 threading = None 50 52 51 53 class BaseTest(unittest.TestCase): … … 70 72 logging._releaseLock() 71 73 74 # Set two unused loggers: one non-ASCII and one Unicode. 75 # This is to test correct operation when sorting existing 76 # loggers in the configuration code. See issue 8201. 77 logging.getLogger("\xab\xd7\xbb") 78 logging.getLogger(u"\u013f\u00d6\u0047") 79 72 80 self.root_logger = logging.getLogger("") 73 81 self.original_logging_level = self.root_logger.getEffectiveLevel() … … 85 93 self.stream.close() 86 94 self.root_logger.removeHandler(self.root_hdlr) 95 while self.root_logger.handlers: 96 h = self.root_logger.handlers[0] 97 self.root_logger.removeHandler(h) 98 h.close() 87 99 self.root_logger.setLevel(self.original_logging_level) 88 100 logging._acquireLock() … … 111 123 # StringIO.StringIO lacks a reset() method. 112 124 actual_lines = stream.getvalue().splitlines() 113 self.assertEqual s(len(actual_lines), len(expected_values))125 self.assertEqual(len(actual_lines), len(expected_values)) 114 126 for actual, expected in zip(actual_lines, expected_values): 115 127 match = pat.search(actual) … … 117 129 self.fail("Log line does not match expected pattern:\n" + 118 130 actual) 119 self.assertEqual s(tuple(match.groups()), expected)131 self.assertEqual(tuple(match.groups()), expected) 120 132 s = stream.read() 121 133 if s: … … 263 275 ]) 264 276 277 def test_invalid_name(self): 278 self.assertRaises(TypeError, logging.getLogger, any) 265 279 266 280 class BasicFilterTest(BaseTest): … … 553 567 """ 554 568 555 # config2 has a subtle configuration error that should be reported 556 config2 = config1.replace("sys.stdout", "sys.stbout") 557 558 # config3 has a less subtle configuration error 559 config3 = config1.replace("formatter=form1", "formatter=misspelled_name") 560 561 # config4 specifies a custom formatter class to be loaded 562 config4 = """ 569 # config1a moves the handler to the root. 570 config1a = """ 563 571 [loggers] 564 keys=root 572 keys=root,parser 565 573 566 574 [handlers] … … 571 579 572 580 [logger_root] 573 level= NOTSET581 level=WARNING 574 582 handlers=hand1 583 584 [logger_parser] 585 level=DEBUG 586 handlers= 587 propagate=1 588 qualname=compiler.parser 575 589 576 590 [handler_hand1] … … 581 595 582 596 [formatter_form1] 597 format=%(levelname)s ++ %(message)s 598 datefmt= 599 """ 600 601 # config2 has a subtle configuration error that should be reported 602 config2 = config1.replace("sys.stdout", "sys.stbout") 603 604 # config3 has a less subtle configuration error 605 config3 = config1.replace("formatter=form1", "formatter=misspelled_name") 606 607 # config4 specifies a custom formatter class to be loaded 608 config4 = """ 609 [loggers] 610 keys=root 611 612 [handlers] 613 keys=hand1 614 615 [formatters] 616 keys=form1 617 618 [logger_root] 619 level=NOTSET 620 handlers=hand1 621 622 [handler_hand1] 623 class=StreamHandler 624 level=NOTSET 625 formatter=form1 626 args=(sys.stdout,) 627 628 [formatter_form1] 583 629 class=""" + __name__ + """.ExceptionFormatter 584 630 format=%(levelname)s:%(name)s:%(message)s … … 631 677 """ 632 678 633 def apply_config(self, conf): 634 try: 635 fn = tempfile.mktemp(".ini") 636 f = open(fn, "w") 637 f.write(textwrap.dedent(conf)) 638 f.close() 639 logging.config.fileConfig(fn) 640 finally: 641 os.remove(fn) 679 # config7 adds a compiler logger. 680 config7 = """ 681 [loggers] 682 keys=root,parser,compiler 683 684 [handlers] 685 keys=hand1 686 687 [formatters] 688 keys=form1 689 690 [logger_root] 691 level=WARNING 692 handlers=hand1 693 694 [logger_compiler] 695 level=DEBUG 696 handlers= 697 propagate=1 698 qualname=compiler 699 700 [logger_parser] 701 level=DEBUG 702 handlers= 703 propagate=1 704 qualname=compiler.parser 705 706 [handler_hand1] 707 class=StreamHandler 708 level=NOTSET 709 formatter=form1 710 args=(sys.stdout,) 711 712 [formatter_form1] 713 format=%(levelname)s ++ %(message)s 714 datefmt= 715 """ 716 717 disable_test = """ 718 [loggers] 719 keys=root 720 721 [handlers] 722 keys=screen 723 724 [formatters] 725 keys= 726 727 [logger_root] 728 level=DEBUG 729 handlers=screen 730 731 [handler_screen] 732 level=DEBUG 733 class=StreamHandler 734 args=(sys.stdout,) 735 formatter= 736 """ 737 738 def apply_config(self, conf, **kwargs): 739 file = cStringIO.StringIO(textwrap.dedent(conf)) 740 logging.config.fileConfig(file, **kwargs) 642 741 643 742 def test_config0_ok(self): … … 689 788 logging.exception("just testing") 690 789 sys.stdout.seek(0) 691 self.assertEqual s(output.getvalue(),790 self.assertEqual(output.getvalue(), 692 791 "ERROR:root:just testing\nGot a [RuntimeError]\n") 693 792 # Original logger output is empty … … 699 798 def test_config6_ok(self): 700 799 self.test_config1_ok(config=self.config6) 800 801 def test_config7_ok(self): 802 with captured_stdout() as output: 803 self.apply_config(self.config1a) 804 logger = logging.getLogger("compiler.parser") 805 # See issue #11424. compiler-hyphenated sorts 806 # between compiler and compiler.xyz and this 807 # was preventing compiler.xyz from being included 808 # in the child loggers of compiler because of an 809 # overzealous loop termination condition. 810 hyphenated = logging.getLogger('compiler-hyphenated') 811 # All will output a message 812 logger.info(self.next_message()) 813 logger.error(self.next_message()) 814 hyphenated.critical(self.next_message()) 815 self.assert_log_lines([ 816 ('INFO', '1'), 817 ('ERROR', '2'), 818 ('CRITICAL', '3'), 819 ], stream=output) 820 # Original logger output is empty. 821 self.assert_log_lines([]) 822 with captured_stdout() as output: 823 self.apply_config(self.config7) 824 logger = logging.getLogger("compiler.parser") 825 self.assertFalse(logger.disabled) 826 # Both will output a message 827 logger.info(self.next_message()) 828 logger.error(self.next_message()) 829 logger = logging.getLogger("compiler.lexer") 830 # Both will output a message 831 logger.info(self.next_message()) 832 logger.error(self.next_message()) 833 # Will not appear 834 hyphenated.critical(self.next_message()) 835 self.assert_log_lines([ 836 ('INFO', '4'), 837 ('ERROR', '5'), 838 ('INFO', '6'), 839 ('ERROR', '7'), 840 ], stream=output) 841 # Original logger output is empty. 842 self.assert_log_lines([]) 843 844 def test_logger_disabling(self): 845 self.apply_config(self.disable_test) 846 logger = logging.getLogger('foo') 847 self.assertFalse(logger.disabled) 848 self.apply_config(self.disable_test) 849 self.assertTrue(logger.disabled) 850 self.apply_config(self.disable_test, disable_existing_loggers=False) 851 self.assertFalse(logger.disabled) 701 852 702 853 class LogRecordStreamHandler(StreamRequestHandler): … … 763 914 764 915 916 @unittest.skipUnless(threading, 'Threading required for this test.') 765 917 class SocketHandlerTest(BaseTest): 766 918 … … 807 959 logger.error("spam") 808 960 logger.debug("eggs") 809 self.assertEqual s(self.get_output(), "spam\neggs\n")961 self.assertEqual(self.get_output(), "spam\neggs\n") 810 962 811 963 … … 826 978 self._survivors[key] = weakref.ref(obj) 827 979 828 def _assert _survival(self):980 def _assertTruesurvival(self): 829 981 """Assert that all objects watched for survival have survived.""" 830 982 # Trigger cycle breaking. … … 852 1004 del foo 853 1005 # foo has survived. 854 self._assert _survival()1006 self._assertTruesurvival() 855 1007 # foo has retained its settings. 856 1008 bar = logging.getLogger("foo") … … 881 1033 f = open(fn) 882 1034 try: 883 self. failUnlessEqual(f.read().rstrip(), data)1035 self.assertEqual(f.read().rstrip(), data) 884 1036 finally: 885 1037 f.close() … … 909 1061 self.assertEqual(s, '\xe4\xee \xf1\xe2\xe8\xe4\xe0\xed\xe8\xff\n') 910 1062 1063 def test_encoding_utf16_unicode(self): 1064 # Issue #19267 1065 log = logging.getLogger("test") 1066 message = u'b\u0142\u0105d' 1067 writer_class = codecs.getwriter('utf-16-le') 1068 writer_class.encoding = 'utf-16-le' 1069 stream = cStringIO.StringIO() 1070 writer = writer_class(stream, 'strict') 1071 handler = logging.StreamHandler(writer) 1072 log.addHandler(handler) 1073 try: 1074 log.warning(message) 1075 finally: 1076 log.removeHandler(handler) 1077 handler.close() 1078 s = stream.getvalue() 1079 self.assertEqual(s, 'b\x00B\x01\x05\x01d\x00\n\x00') 1080 1081 1082 class WarningsTest(BaseTest): 1083 1084 def test_warnings(self): 1085 with warnings.catch_warnings(): 1086 logging.captureWarnings(True) 1087 try: 1088 warnings.filterwarnings("always", category=UserWarning) 1089 file = cStringIO.StringIO() 1090 h = logging.StreamHandler(file) 1091 logger = logging.getLogger("py.warnings") 1092 logger.addHandler(h) 1093 warnings.warn("I'm warning you...") 1094 logger.removeHandler(h) 1095 s = file.getvalue() 1096 h.close() 1097 self.assertTrue(s.find("UserWarning: I'm warning you...\n") > 0) 1098 1099 #See if an explicit file uses the original implementation 1100 file = cStringIO.StringIO() 1101 warnings.showwarning("Explicit", UserWarning, "dummy.py", 42, 1102 file, "Dummy line") 1103 s = file.getvalue() 1104 file.close() 1105 self.assertEqual(s, 1106 "dummy.py:42: UserWarning: Explicit\n Dummy line\n") 1107 finally: 1108 logging.captureWarnings(False) 1109 1110 1111 def formatFunc(format, datefmt=None): 1112 return logging.Formatter(format, datefmt) 1113 1114 def handlerFunc(): 1115 return logging.StreamHandler() 1116 1117 class CustomHandler(logging.StreamHandler): 1118 pass 1119 1120 class ConfigDictTest(BaseTest): 1121 1122 """Reading logging config from a dictionary.""" 1123 1124 expected_log_pat = r"^([\w]+) \+\+ ([\w]+)$" 1125 1126 # config0 is a standard configuration. 1127 config0 = { 1128 'version': 1, 1129 'formatters': { 1130 'form1' : { 1131 'format' : '%(levelname)s ++ %(message)s', 1132 }, 1133 }, 1134 'handlers' : { 1135 'hand1' : { 1136 'class' : 'logging.StreamHandler', 1137 'formatter' : 'form1', 1138 'level' : 'NOTSET', 1139 'stream' : 'ext://sys.stdout', 1140 }, 1141 }, 1142 'root' : { 1143 'level' : 'WARNING', 1144 'handlers' : ['hand1'], 1145 }, 1146 } 1147 1148 # config1 adds a little to the standard configuration. 1149 config1 = { 1150 'version': 1, 1151 'formatters': { 1152 'form1' : { 1153 'format' : '%(levelname)s ++ %(message)s', 1154 }, 1155 }, 1156 'handlers' : { 1157 'hand1' : { 1158 'class' : 'logging.StreamHandler', 1159 'formatter' : 'form1', 1160 'level' : 'NOTSET', 1161 'stream' : 'ext://sys.stdout', 1162 }, 1163 }, 1164 'loggers' : { 1165 'compiler.parser' : { 1166 'level' : 'DEBUG', 1167 'handlers' : ['hand1'], 1168 }, 1169 }, 1170 'root' : { 1171 'level' : 'WARNING', 1172 }, 1173 } 1174 1175 # config2 has a subtle configuration error that should be reported 1176 config2 = { 1177 'version': 1, 1178 'formatters': { 1179 'form1' : { 1180 'format' : '%(levelname)s ++ %(message)s', 1181 }, 1182 }, 1183 'handlers' : { 1184 'hand1' : { 1185 'class' : 'logging.StreamHandler', 1186 'formatter' : 'form1', 1187 'level' : 'NOTSET', 1188 'stream' : 'ext://sys.stdbout', 1189 }, 1190 }, 1191 'loggers' : { 1192 'compiler.parser' : { 1193 'level' : 'DEBUG', 1194 'handlers' : ['hand1'], 1195 }, 1196 }, 1197 'root' : { 1198 'level' : 'WARNING', 1199 }, 1200 } 1201 1202 #As config1 but with a misspelt level on a handler 1203 config2a = { 1204 'version': 1, 1205 'formatters': { 1206 'form1' : { 1207 'format' : '%(levelname)s ++ %(message)s', 1208 }, 1209 }, 1210 'handlers' : { 1211 'hand1' : { 1212 'class' : 'logging.StreamHandler', 1213 'formatter' : 'form1', 1214 'level' : 'NTOSET', 1215 'stream' : 'ext://sys.stdout', 1216 }, 1217 }, 1218 'loggers' : { 1219 'compiler.parser' : { 1220 'level' : 'DEBUG', 1221 'handlers' : ['hand1'], 1222 }, 1223 }, 1224 'root' : { 1225 'level' : 'WARNING', 1226 }, 1227 } 1228 1229 1230 #As config1 but with a misspelt level on a logger 1231 config2b = { 1232 'version': 1, 1233 'formatters': { 1234 'form1' : { 1235 'format' : '%(levelname)s ++ %(message)s', 1236 }, 1237 }, 1238 'handlers' : { 1239 'hand1' : { 1240 'class' : 'logging.StreamHandler', 1241 'formatter' : 'form1', 1242 'level' : 'NOTSET', 1243 'stream' : 'ext://sys.stdout', 1244 }, 1245 }, 1246 'loggers' : { 1247 'compiler.parser' : { 1248 'level' : 'DEBUG', 1249 'handlers' : ['hand1'], 1250 }, 1251 }, 1252 'root' : { 1253 'level' : 'WRANING', 1254 }, 1255 } 1256 1257 # config3 has a less subtle configuration error 1258 config3 = { 1259 'version': 1, 1260 'formatters': { 1261 'form1' : { 1262 'format' : '%(levelname)s ++ %(message)s', 1263 }, 1264 }, 1265 'handlers' : { 1266 'hand1' : { 1267 'class' : 'logging.StreamHandler', 1268 'formatter' : 'misspelled_name', 1269 'level' : 'NOTSET', 1270 'stream' : 'ext://sys.stdout', 1271 }, 1272 }, 1273 'loggers' : { 1274 'compiler.parser' : { 1275 'level' : 'DEBUG', 1276 'handlers' : ['hand1'], 1277 }, 1278 }, 1279 'root' : { 1280 'level' : 'WARNING', 1281 }, 1282 } 1283 1284 # config4 specifies a custom formatter class to be loaded 1285 config4 = { 1286 'version': 1, 1287 'formatters': { 1288 'form1' : { 1289 '()' : __name__ + '.ExceptionFormatter', 1290 'format' : '%(levelname)s:%(name)s:%(message)s', 1291 }, 1292 }, 1293 'handlers' : { 1294 'hand1' : { 1295 'class' : 'logging.StreamHandler', 1296 'formatter' : 'form1', 1297 'level' : 'NOTSET', 1298 'stream' : 'ext://sys.stdout', 1299 }, 1300 }, 1301 'root' : { 1302 'level' : 'NOTSET', 1303 'handlers' : ['hand1'], 1304 }, 1305 } 1306 1307 # As config4 but using an actual callable rather than a string 1308 config4a = { 1309 'version': 1, 1310 'formatters': { 1311 'form1' : { 1312 '()' : ExceptionFormatter, 1313 'format' : '%(levelname)s:%(name)s:%(message)s', 1314 }, 1315 'form2' : { 1316 '()' : __name__ + '.formatFunc', 1317 'format' : '%(levelname)s:%(name)s:%(message)s', 1318 }, 1319 'form3' : { 1320 '()' : formatFunc, 1321 'format' : '%(levelname)s:%(name)s:%(message)s', 1322 }, 1323 }, 1324 'handlers' : { 1325 'hand1' : { 1326 'class' : 'logging.StreamHandler', 1327 'formatter' : 'form1', 1328 'level' : 'NOTSET', 1329 'stream' : 'ext://sys.stdout', 1330 }, 1331 'hand2' : { 1332 '()' : handlerFunc, 1333 }, 1334 }, 1335 'root' : { 1336 'level' : 'NOTSET', 1337 'handlers' : ['hand1'], 1338 }, 1339 } 1340 1341 # config5 specifies a custom handler class to be loaded 1342 config5 = { 1343 'version': 1, 1344 'formatters': { 1345 'form1' : { 1346 'format' : '%(levelname)s ++ %(message)s', 1347 }, 1348 }, 1349 'handlers' : { 1350 'hand1' : { 1351 'class' : __name__ + '.CustomHandler', 1352 'formatter' : 'form1', 1353 'level' : 'NOTSET', 1354 'stream' : 'ext://sys.stdout', 1355 }, 1356 }, 1357 'loggers' : { 1358 'compiler.parser' : { 1359 'level' : 'DEBUG', 1360 'handlers' : ['hand1'], 1361 }, 1362 }, 1363 'root' : { 1364 'level' : 'WARNING', 1365 }, 1366 } 1367 1368 # config6 specifies a custom handler class to be loaded 1369 # but has bad arguments 1370 config6 = { 1371 'version': 1, 1372 'formatters': { 1373 'form1' : { 1374 'format' : '%(levelname)s ++ %(message)s', 1375 }, 1376 }, 1377 'handlers' : { 1378 'hand1' : { 1379 'class' : __name__ + '.CustomHandler', 1380 'formatter' : 'form1', 1381 'level' : 'NOTSET', 1382 'stream' : 'ext://sys.stdout', 1383 '9' : 'invalid parameter name', 1384 }, 1385 }, 1386 'loggers' : { 1387 'compiler.parser' : { 1388 'level' : 'DEBUG', 1389 'handlers' : ['hand1'], 1390 }, 1391 }, 1392 'root' : { 1393 'level' : 'WARNING', 1394 }, 1395 } 1396 1397 #config 7 does not define compiler.parser but defines compiler.lexer 1398 #so compiler.parser should be disabled after applying it 1399 config7 = { 1400 'version': 1, 1401 'formatters': { 1402 'form1' : { 1403 'format' : '%(levelname)s ++ %(message)s', 1404 }, 1405 }, 1406 'handlers' : { 1407 'hand1' : { 1408 'class' : 'logging.StreamHandler', 1409 'formatter' : 'form1', 1410 'level' : 'NOTSET', 1411 'stream' : 'ext://sys.stdout', 1412 }, 1413 }, 1414 'loggers' : { 1415 'compiler.lexer' : { 1416 'level' : 'DEBUG', 1417 'handlers' : ['hand1'], 1418 }, 1419 }, 1420 'root' : { 1421 'level' : 'WARNING', 1422 }, 1423 } 1424 1425 config8 = { 1426 'version': 1, 1427 'disable_existing_loggers' : False, 1428 'formatters': { 1429 'form1' : { 1430 'format' : '%(levelname)s ++ %(message)s', 1431 }, 1432 }, 1433 'handlers' : { 1434 'hand1' : { 1435 'class' : 'logging.StreamHandler', 1436 'formatter' : 'form1', 1437 'level' : 'NOTSET', 1438 'stream' : 'ext://sys.stdout', 1439 }, 1440 }, 1441 'loggers' : { 1442 'compiler' : { 1443 'level' : 'DEBUG', 1444 'handlers' : ['hand1'], 1445 }, 1446 'compiler.lexer' : { 1447 }, 1448 }, 1449 'root' : { 1450 'level' : 'WARNING', 1451 }, 1452 } 1453 1454 config9 = { 1455 'version': 1, 1456 'formatters': { 1457 'form1' : { 1458 'format' : '%(levelname)s ++ %(message)s', 1459 }, 1460 }, 1461 'handlers' : { 1462 'hand1' : { 1463 'class' : 'logging.StreamHandler', 1464 'formatter' : 'form1', 1465 'level' : 'WARNING', 1466 'stream' : 'ext://sys.stdout', 1467 }, 1468 }, 1469 'loggers' : { 1470 'compiler.parser' : { 1471 'level' : 'WARNING', 1472 'handlers' : ['hand1'], 1473 }, 1474 }, 1475 'root' : { 1476 'level' : 'NOTSET', 1477 }, 1478 } 1479 1480 config9a = { 1481 'version': 1, 1482 'incremental' : True, 1483 'handlers' : { 1484 'hand1' : { 1485 'level' : 'WARNING', 1486 }, 1487 }, 1488 'loggers' : { 1489 'compiler.parser' : { 1490 'level' : 'INFO', 1491 }, 1492 }, 1493 } 1494 1495 config9b = { 1496 'version': 1, 1497 'incremental' : True, 1498 'handlers' : { 1499 'hand1' : { 1500 'level' : 'INFO', 1501 }, 1502 }, 1503 'loggers' : { 1504 'compiler.parser' : { 1505 'level' : 'INFO', 1506 }, 1507 }, 1508 } 1509 1510 #As config1 but with a filter added 1511 config10 = { 1512 'version': 1, 1513 'formatters': { 1514 'form1' : { 1515 'format' : '%(levelname)s ++ %(message)s', 1516 }, 1517 }, 1518 'filters' : { 1519 'filt1' : { 1520 'name' : 'compiler.parser', 1521 }, 1522 }, 1523 'handlers' : { 1524 'hand1' : { 1525 'class' : 'logging.StreamHandler', 1526 'formatter' : 'form1', 1527 'level' : 'NOTSET', 1528 'stream' : 'ext://sys.stdout', 1529 'filters' : ['filt1'], 1530 }, 1531 }, 1532 'loggers' : { 1533 'compiler.parser' : { 1534 'level' : 'DEBUG', 1535 'filters' : ['filt1'], 1536 }, 1537 }, 1538 'root' : { 1539 'level' : 'WARNING', 1540 'handlers' : ['hand1'], 1541 }, 1542 } 1543 1544 #As config1 but using cfg:// references 1545 config11 = { 1546 'version': 1, 1547 'true_formatters': { 1548 'form1' : { 1549 'format' : '%(levelname)s ++ %(message)s', 1550 }, 1551 }, 1552 'handler_configs': { 1553 'hand1' : { 1554 'class' : 'logging.StreamHandler', 1555 'formatter' : 'form1', 1556 'level' : 'NOTSET', 1557 'stream' : 'ext://sys.stdout', 1558 }, 1559 }, 1560 'formatters' : 'cfg://true_formatters', 1561 'handlers' : { 1562 'hand1' : 'cfg://handler_configs[hand1]', 1563 }, 1564 'loggers' : { 1565 'compiler.parser' : { 1566 'level' : 'DEBUG', 1567 'handlers' : ['hand1'], 1568 }, 1569 }, 1570 'root' : { 1571 'level' : 'WARNING', 1572 }, 1573 } 1574 1575 #As config11 but missing the version key 1576 config12 = { 1577 'true_formatters': { 1578 'form1' : { 1579 'format' : '%(levelname)s ++ %(message)s', 1580 }, 1581 }, 1582 'handler_configs': { 1583 'hand1' : { 1584 'class' : 'logging.StreamHandler', 1585 'formatter' : 'form1', 1586 'level' : 'NOTSET', 1587 'stream' : 'ext://sys.stdout', 1588 }, 1589 }, 1590 'formatters' : 'cfg://true_formatters', 1591 'handlers' : { 1592 'hand1' : 'cfg://handler_configs[hand1]', 1593 }, 1594 'loggers' : { 1595 'compiler.parser' : { 1596 'level' : 'DEBUG', 1597 'handlers' : ['hand1'], 1598 }, 1599 }, 1600 'root' : { 1601 'level' : 'WARNING', 1602 }, 1603 } 1604 1605 #As config11 but using an unsupported version 1606 config13 = { 1607 'version': 2, 1608 'true_formatters': { 1609 'form1' : { 1610 'format' : '%(levelname)s ++ %(message)s', 1611 }, 1612 }, 1613 'handler_configs': { 1614 'hand1' : { 1615 'class' : 'logging.StreamHandler', 1616 'formatter' : 'form1', 1617 'level' : 'NOTSET', 1618 'stream' : 'ext://sys.stdout', 1619 }, 1620 }, 1621 'formatters' : 'cfg://true_formatters', 1622 'handlers' : { 1623 'hand1' : 'cfg://handler_configs[hand1]', 1624 }, 1625 'loggers' : { 1626 'compiler.parser' : { 1627 'level' : 'DEBUG', 1628 'handlers' : ['hand1'], 1629 }, 1630 }, 1631 'root' : { 1632 'level' : 'WARNING', 1633 }, 1634 } 1635 1636 out_of_order = { 1637 "version": 1, 1638 "formatters": { 1639 "mySimpleFormatter": { 1640 "format": "%(asctime)s (%(name)s) %(levelname)s: %(message)s" 1641 } 1642 }, 1643 "handlers": { 1644 "fileGlobal": { 1645 "class": "logging.StreamHandler", 1646 "level": "DEBUG", 1647 "formatter": "mySimpleFormatter" 1648 }, 1649 "bufferGlobal": { 1650 "class": "logging.handlers.MemoryHandler", 1651 "capacity": 5, 1652 "formatter": "mySimpleFormatter", 1653 "target": "fileGlobal", 1654 "level": "DEBUG" 1655 } 1656 }, 1657 "loggers": { 1658 "mymodule": { 1659 "level": "DEBUG", 1660 "handlers": ["bufferGlobal"], 1661 "propagate": "true" 1662 } 1663 } 1664 } 1665 1666 def apply_config(self, conf): 1667 logging.config.dictConfig(conf) 1668 1669 def test_config0_ok(self): 1670 # A simple config which overrides the default settings. 1671 with captured_stdout() as output: 1672 self.apply_config(self.config0) 1673 logger = logging.getLogger() 1674 # Won't output anything 1675 logger.info(self.next_message()) 1676 # Outputs a message 1677 logger.error(self.next_message()) 1678 self.assert_log_lines([ 1679 ('ERROR', '2'), 1680 ], stream=output) 1681 # Original logger output is empty. 1682 self.assert_log_lines([]) 1683 1684 def test_config1_ok(self, config=config1): 1685 # A config defining a sub-parser as well. 1686 with captured_stdout() as output: 1687 self.apply_config(config) 1688 logger = logging.getLogger("compiler.parser") 1689 # Both will output a message 1690 logger.info(self.next_message()) 1691 logger.error(self.next_message()) 1692 self.assert_log_lines([ 1693 ('INFO', '1'), 1694 ('ERROR', '2'), 1695 ], stream=output) 1696 # Original logger output is empty. 1697 self.assert_log_lines([]) 1698 1699 def test_config2_failure(self): 1700 # A simple config which overrides the default settings. 1701 self.assertRaises(StandardError, self.apply_config, self.config2) 1702 1703 def test_config2a_failure(self): 1704 # A simple config which overrides the default settings. 1705 self.assertRaises(StandardError, self.apply_config, self.config2a) 1706 1707 def test_config2b_failure(self): 1708 # A simple config which overrides the default settings. 1709 self.assertRaises(StandardError, self.apply_config, self.config2b) 1710 1711 def test_config3_failure(self): 1712 # A simple config which overrides the default settings. 1713 self.assertRaises(StandardError, self.apply_config, self.config3) 1714 1715 def test_config4_ok(self): 1716 # A config specifying a custom formatter class. 1717 with captured_stdout() as output: 1718 self.apply_config(self.config4) 1719 #logger = logging.getLogger() 1720 try: 1721 raise RuntimeError() 1722 except RuntimeError: 1723 logging.exception("just testing") 1724 sys.stdout.seek(0) 1725 self.assertEqual(output.getvalue(), 1726 "ERROR:root:just testing\nGot a [RuntimeError]\n") 1727 # Original logger output is empty 1728 self.assert_log_lines([]) 1729 1730 def test_config4a_ok(self): 1731 # A config specifying a custom formatter class. 1732 with captured_stdout() as output: 1733 self.apply_config(self.config4a) 1734 #logger = logging.getLogger() 1735 try: 1736 raise RuntimeError() 1737 except RuntimeError: 1738 logging.exception("just testing") 1739 sys.stdout.seek(0) 1740 self.assertEqual(output.getvalue(), 1741 "ERROR:root:just testing\nGot a [RuntimeError]\n") 1742 # Original logger output is empty 1743 self.assert_log_lines([]) 1744 1745 def test_config5_ok(self): 1746 self.test_config1_ok(config=self.config5) 1747 1748 def test_config6_failure(self): 1749 self.assertRaises(StandardError, self.apply_config, self.config6) 1750 1751 def test_config7_ok(self): 1752 with captured_stdout() as output: 1753 self.apply_config(self.config1) 1754 logger = logging.getLogger("compiler.parser") 1755 # Both will output a message 1756 logger.info(self.next_message()) 1757 logger.error(self.next_message()) 1758 self.assert_log_lines([ 1759 ('INFO', '1'), 1760 ('ERROR', '2'), 1761 ], stream=output) 1762 # Original logger output is empty. 1763 self.assert_log_lines([]) 1764 with captured_stdout() as output: 1765 self.apply_config(self.config7) 1766 logger = logging.getLogger("compiler.parser") 1767 self.assertTrue(logger.disabled) 1768 logger = logging.getLogger("compiler.lexer") 1769 # Both will output a message 1770 logger.info(self.next_message()) 1771 logger.error(self.next_message()) 1772 self.assert_log_lines([ 1773 ('INFO', '3'), 1774 ('ERROR', '4'), 1775 ], stream=output) 1776 # Original logger output is empty. 1777 self.assert_log_lines([]) 1778 1779 #Same as test_config_7_ok but don't disable old loggers. 1780 def test_config_8_ok(self): 1781 with captured_stdout() as output: 1782 self.apply_config(self.config1) 1783 logger = logging.getLogger("compiler.parser") 1784 # Both will output a message 1785 logger.info(self.next_message()) 1786 logger.error(self.next_message()) 1787 self.assert_log_lines([ 1788 ('INFO', '1'), 1789 ('ERROR', '2'), 1790 ], stream=output) 1791 # Original logger output is empty. 1792 self.assert_log_lines([]) 1793 with captured_stdout() as output: 1794 self.apply_config(self.config8) 1795 logger = logging.getLogger("compiler.parser") 1796 self.assertFalse(logger.disabled) 1797 # Both will output a message 1798 logger.info(self.next_message()) 1799 logger.error(self.next_message()) 1800 logger = logging.getLogger("compiler.lexer") 1801 # Both will output a message 1802 logger.info(self.next_message()) 1803 logger.error(self.next_message()) 1804 self.assert_log_lines([ 1805 ('INFO', '3'), 1806 ('ERROR', '4'), 1807 ('INFO', '5'), 1808 ('ERROR', '6'), 1809 ], stream=output) 1810 # Original logger output is empty. 1811 self.assert_log_lines([]) 1812 1813 def test_config_9_ok(self): 1814 with captured_stdout() as output: 1815 self.apply_config(self.config9) 1816 logger = logging.getLogger("compiler.parser") 1817 #Nothing will be output since both handler and logger are set to WARNING 1818 logger.info(self.next_message()) 1819 self.assert_log_lines([], stream=output) 1820 self.apply_config(self.config9a) 1821 #Nothing will be output since both handler is still set to WARNING 1822 logger.info(self.next_message()) 1823 self.assert_log_lines([], stream=output) 1824 self.apply_config(self.config9b) 1825 #Message should now be output 1826 logger.info(self.next_message()) 1827 self.assert_log_lines([ 1828 ('INFO', '3'), 1829 ], stream=output) 1830 1831 def test_config_10_ok(self): 1832 with captured_stdout() as output: 1833 self.apply_config(self.config10) 1834 logger = logging.getLogger("compiler.parser") 1835 logger.warning(self.next_message()) 1836 logger = logging.getLogger('compiler') 1837 #Not output, because filtered 1838 logger.warning(self.next_message()) 1839 logger = logging.getLogger('compiler.lexer') 1840 #Not output, because filtered 1841 logger.warning(self.next_message()) 1842 logger = logging.getLogger("compiler.parser.codegen") 1843 #Output, as not filtered 1844 logger.error(self.next_message()) 1845 self.assert_log_lines([ 1846 ('WARNING', '1'), 1847 ('ERROR', '4'), 1848 ], stream=output) 1849 1850 def test_config11_ok(self): 1851 self.test_config1_ok(self.config11) 1852 1853 def test_config12_failure(self): 1854 self.assertRaises(StandardError, self.apply_config, self.config12) 1855 1856 def test_config13_failure(self): 1857 self.assertRaises(StandardError, self.apply_config, self.config13) 1858 1859 @unittest.skipUnless(threading, 'listen() needs threading to work') 1860 def setup_via_listener(self, text): 1861 # Ask for a randomly assigned port (by using port 0) 1862 t = logging.config.listen(0) 1863 t.start() 1864 t.ready.wait() 1865 # Now get the port allocated 1866 port = t.port 1867 t.ready.clear() 1868 try: 1869 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 1870 sock.settimeout(2.0) 1871 sock.connect(('localhost', port)) 1872 1873 slen = struct.pack('>L', len(text)) 1874 s = slen + text 1875 sentsofar = 0 1876 left = len(s) 1877 while left > 0: 1878 sent = sock.send(s[sentsofar:]) 1879 sentsofar += sent 1880 left -= sent 1881 sock.close() 1882 finally: 1883 t.ready.wait(2.0) 1884 logging.config.stopListening() 1885 t.join(2.0) 1886 1887 def test_listen_config_10_ok(self): 1888 with captured_stdout() as output: 1889 self.setup_via_listener(json.dumps(self.config10)) 1890 logger = logging.getLogger("compiler.parser") 1891 logger.warning(self.next_message()) 1892 logger = logging.getLogger('compiler') 1893 #Not output, because filtered 1894 logger.warning(self.next_message()) 1895 logger = logging.getLogger('compiler.lexer') 1896 #Not output, because filtered 1897 logger.warning(self.next_message()) 1898 logger = logging.getLogger("compiler.parser.codegen") 1899 #Output, as not filtered 1900 logger.error(self.next_message()) 1901 self.assert_log_lines([ 1902 ('WARNING', '1'), 1903 ('ERROR', '4'), 1904 ], stream=output) 1905 1906 def test_listen_config_1_ok(self): 1907 with captured_stdout() as output: 1908 self.setup_via_listener(textwrap.dedent(ConfigFileTest.config1)) 1909 logger = logging.getLogger("compiler.parser") 1910 # Both will output a message 1911 logger.info(self.next_message()) 1912 logger.error(self.next_message()) 1913 self.assert_log_lines([ 1914 ('INFO', '1'), 1915 ('ERROR', '2'), 1916 ], stream=output) 1917 # Original logger output is empty. 1918 self.assert_log_lines([]) 1919 1920 def test_out_of_order(self): 1921 self.apply_config(self.out_of_order) 1922 handler = logging.getLogger('mymodule').handlers[0] 1923 self.assertIsInstance(handler.target, logging.Handler) 1924 1925 class ManagerTest(BaseTest): 1926 def test_manager_loggerclass(self): 1927 logged = [] 1928 1929 class MyLogger(logging.Logger): 1930 def _log(self, level, msg, args, exc_info=None, extra=None): 1931 logged.append(msg) 1932 1933 man = logging.Manager(None) 1934 self.assertRaises(TypeError, man.setLoggerClass, int) 1935 man.setLoggerClass(MyLogger) 1936 logger = man.getLogger('test') 1937 logger.warning('should appear in logged') 1938 logging.warning('should not appear in logged') 1939 1940 self.assertEqual(logged, ['should appear in logged']) 1941 1942 1943 class ChildLoggerTest(BaseTest): 1944 def test_child_loggers(self): 1945 r = logging.getLogger() 1946 l1 = logging.getLogger('abc') 1947 l2 = logging.getLogger('def.ghi') 1948 c1 = r.getChild('xyz') 1949 c2 = r.getChild('uvw.xyz') 1950 self.assertTrue(c1 is logging.getLogger('xyz')) 1951 self.assertTrue(c2 is logging.getLogger('uvw.xyz')) 1952 c1 = l1.getChild('def') 1953 c2 = c1.getChild('ghi') 1954 c3 = l1.getChild('def.ghi') 1955 self.assertTrue(c1 is logging.getLogger('abc.def')) 1956 self.assertTrue(c2 is logging.getLogger('abc.def.ghi')) 1957 self.assertTrue(c2 is c3) 1958 1959 1960 class HandlerTest(BaseTest): 1961 1962 @unittest.skipIf(os.name == 'nt', 'WatchedFileHandler not appropriate for Windows.') 1963 @unittest.skipUnless(threading, 'Threading required for this test.') 1964 def test_race(self): 1965 # Issue #14632 refers. 1966 def remove_loop(fname, tries): 1967 for _ in range(tries): 1968 try: 1969 os.unlink(fname) 1970 except OSError: 1971 pass 1972 time.sleep(0.004 * random.randint(0, 4)) 1973 1974 del_count = 500 1975 log_count = 500 1976 1977 for delay in (False, True): 1978 fd, fn = tempfile.mkstemp('.log', 'test_logging-3-') 1979 os.close(fd) 1980 remover = threading.Thread(target=remove_loop, args=(fn, del_count)) 1981 remover.daemon = True 1982 remover.start() 1983 h = logging.handlers.WatchedFileHandler(fn, delay=delay) 1984 f = logging.Formatter('%(asctime)s: %(levelname)s: %(message)s') 1985 h.setFormatter(f) 1986 try: 1987 for _ in range(log_count): 1988 time.sleep(0.005) 1989 r = logging.makeLogRecord({'msg': 'testing' }) 1990 h.handle(r) 1991 finally: 1992 remover.join() 1993 try: 1994 h.close() 1995 except ValueError: 1996 pass 1997 if os.path.exists(fn): 1998 os.unlink(fn) 1999 911 2000 912 2001 # Set the locale to the platform-dependent default. I have no idea … … 916 2005 def test_main(): 917 2006 run_unittest(BuiltinLevelsTest, BasicFilterTest, 918 CustomLevelsAndFiltersTest, MemoryHandlerTest, 919 ConfigFileTest, SocketHandlerTest, MemoryTest, 920 EncodingTest) 2007 CustomLevelsAndFiltersTest, MemoryHandlerTest, 2008 ConfigFileTest, SocketHandlerTest, MemoryTest, 2009 EncodingTest, WarningsTest, ConfigDictTest, ManagerTest, 2010 ChildLoggerTest, HandlerTest) 921 2011 922 2012 if __name__ == "__main__":
Note:
See TracChangeset
for help on using the changeset viewer.