Ignore:
Timestamp:
Mar 19, 2014, 11:31:01 PM (11 years ago)
Author:
dmik
Message:

python: Merge vendor 2.7.6 to trunk.

Location:
python/trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • python/trunk

  • python/trunk/Lib/test/test_logging.py

    r2 r391  
    11#!/usr/bin/env python
    22#
    3 # Copyright 2001-2004 by Vinay Sajip. All Rights Reserved.
     3# Copyright 2001-2013 by Vinay Sajip. All Rights Reserved.
    44#
    55# Permission to use, copy, modify, and distribute this software and its
     
    1919"""Test harness for the logging module. Run all tests.
    2020
    21 Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
     21Copyright (C) 2001-2013 Vinay Sajip. All Rights Reserved.
    2222"""
    2323
     
    2727
    2828import codecs
    29 import copy
    3029import cPickle
    3130import cStringIO
    3231import gc
     32import json
    3333import os
     34import random
    3435import re
    3536import select
    3637import socket
    3738from SocketServer import ThreadingTCPServer, StreamRequestHandler
    38 import string
    3939import struct
    4040import sys
     
    4242from test.test_support import captured_stdout, run_with_locale, run_unittest
    4343import textwrap
    44 import threading
    4544import time
    46 import types
    4745import unittest
     46import warnings
    4847import weakref
    49 
     48try:
     49    import threading
     50except ImportError:
     51    threading = None
    5052
    5153class BaseTest(unittest.TestCase):
     
    7072            logging._releaseLock()
    7173
     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
    7280        self.root_logger = logging.getLogger("")
    7381        self.original_logging_level = self.root_logger.getEffectiveLevel()
     
    8593        self.stream.close()
    8694        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()
    8799        self.root_logger.setLevel(self.original_logging_level)
    88100        logging._acquireLock()
     
    111123            # StringIO.StringIO lacks a reset() method.
    112124            actual_lines = stream.getvalue().splitlines()
    113         self.assertEquals(len(actual_lines), len(expected_values))
     125        self.assertEqual(len(actual_lines), len(expected_values))
    114126        for actual, expected in zip(actual_lines, expected_values):
    115127            match = pat.search(actual)
     
    117129                self.fail("Log line does not match expected pattern:\n" +
    118130                            actual)
    119             self.assertEquals(tuple(match.groups()), expected)
     131            self.assertEqual(tuple(match.groups()), expected)
    120132        s = stream.read()
    121133        if s:
     
    263275        ])
    264276
     277    def test_invalid_name(self):
     278        self.assertRaises(TypeError, logging.getLogger, any)
    265279
    266280class BasicFilterTest(BaseTest):
     
    553567    """
    554568
    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 = """
    563571    [loggers]
    564     keys=root
     572    keys=root,parser
    565573
    566574    [handlers]
     
    571579
    572580    [logger_root]
    573     level=NOTSET
     581    level=WARNING
    574582    handlers=hand1
     583
     584    [logger_parser]
     585    level=DEBUG
     586    handlers=
     587    propagate=1
     588    qualname=compiler.parser
    575589
    576590    [handler_hand1]
     
    581595
    582596    [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]
    583629    class=""" + __name__ + """.ExceptionFormatter
    584630    format=%(levelname)s:%(name)s:%(message)s
     
    631677    """
    632678
    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)
    642741
    643742    def test_config0_ok(self):
     
    689788                logging.exception("just testing")
    690789            sys.stdout.seek(0)
    691             self.assertEquals(output.getvalue(),
     790            self.assertEqual(output.getvalue(),
    692791                "ERROR:root:just testing\nGot a [RuntimeError]\n")
    693792            # Original logger output is empty
     
    699798    def test_config6_ok(self):
    700799        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)
    701852
    702853class LogRecordStreamHandler(StreamRequestHandler):
     
    763914
    764915
     916@unittest.skipUnless(threading, 'Threading required for this test.')
    765917class SocketHandlerTest(BaseTest):
    766918
     
    807959        logger.error("spam")
    808960        logger.debug("eggs")
    809         self.assertEquals(self.get_output(), "spam\neggs\n")
     961        self.assertEqual(self.get_output(), "spam\neggs\n")
    810962
    811963
     
    826978            self._survivors[key] = weakref.ref(obj)
    827979
    828     def _assert_survival(self):
     980    def _assertTruesurvival(self):
    829981        """Assert that all objects watched for survival have survived."""
    830982        # Trigger cycle breaking.
     
    8521004        del foo
    8531005        # foo has survived.
    854         self._assert_survival()
     1006        self._assertTruesurvival()
    8551007        # foo has retained its settings.
    8561008        bar = logging.getLogger("foo")
     
    8811033            f = open(fn)
    8821034            try:
    883                 self.failUnlessEqual(f.read().rstrip(), data)
     1035                self.assertEqual(f.read().rstrip(), data)
    8841036            finally:
    8851037                f.close()
     
    9091061        self.assertEqual(s, '\xe4\xee \xf1\xe2\xe8\xe4\xe0\xed\xe8\xff\n')
    9101062
     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
     1082class 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
     1111def formatFunc(format, datefmt=None):
     1112    return logging.Formatter(format, datefmt)
     1113
     1114def handlerFunc():
     1115    return logging.StreamHandler()
     1116
     1117class CustomHandler(logging.StreamHandler):
     1118    pass
     1119
     1120class 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
     1925class 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
     1943class 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
     1960class 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
    9112000
    9122001# Set the locale to the platform-dependent default.  I have no idea
     
    9162005def test_main():
    9172006    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)
    9212011
    9222012if __name__ == "__main__":
Note: See TracChangeset for help on using the changeset viewer.