From 18c66898b0a14761786161c07d89d65c8f088601 Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Sun, 17 Feb 2008 13:31:39 +0000 Subject: Merged revisions 60481,60485,60489-60492,60494-60496,60498-60499,60501-60503,60505-60506,60508-60509,60523-60524,60532,60543,60545,60547-60548,60552,60554,60556-60559,60561-60562,60569,60571-60572,60574,60576-60583,60585-60586,60589,60591,60594-60595,60597-60598,60600-60601,60606-60612,60615,60617,60619-60621,60623-60625,60627-60629,60631,60633,60635,60647,60650,60652,60654,60656,60658-60659,60664-60666,60668-60670,60672,60676,60678,60680-60683,60685-60686,60688,60690,60692-60694,60697-60700,60705-60706,60708,60711,60714,60720,60724-60730,60732,60736,60742,60744,60746,60748,60750-60751,60753,60756-60757,60759-60761,60763-60764,60766,60769-60770,60774-60784,60787-60789,60793,60796,60799-60809,60812-60813,60815-60821,60823-60826,60828-60829,60831-60834,60836,60838-60839,60846-60873 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r60850 | amaury.forgeotdarc | 2008-02-16 01:16:50 +0100 (Sat, 16 Feb 2008) | 3 lines mmap.PROT_READ does not exists on win32; Skip this test created by r60830. ........ r60851 | raymond.hettinger | 2008-02-16 02:22:54 +0100 (Sat, 16 Feb 2008) | 1 line Add __all__ to logging module. ........ r60855 | georg.brandl | 2008-02-16 10:37:32 +0100 (Sat, 16 Feb 2008) | 2 lines #2120: broken links in advocacy document. ........ r60860 | amaury.forgeotdarc | 2008-02-16 15:34:57 +0100 (Sat, 16 Feb 2008) | 23 lines Crashers of the day: Py_CLEAR must be used when there is a chance that the function can be called recursively. This was discussed in issue1020188. In python codebase, all occurrences of Py_[X]DECREF(xxx->yyy) are suspect, except when they appear in tp_new or tp_dealloc functions, or when the member cannot be of a user-defined class. Note that tp_init is not safe. I do have a (crashing) example for every changed line. Is it worth adding them to the test suite? Example: class SpecialStr(str): def __del__(self): s.close() import cStringIO s = cStringIO.StringIO(SpecialStr("text")) s.close() # Segfault ........ r60871 | amaury.forgeotdarc | 2008-02-16 21:55:24 +0100 (Sat, 16 Feb 2008) | 3 lines Prevent a crash with nested scopes, again caused by calling Py_DECREF when the pointer is still present in the containing structure. ........ r60872 | brett.cannon | 2008-02-17 02:59:18 +0100 (Sun, 17 Feb 2008) | 4 lines Move test_logging over to doctest. Thanks to Christopher White from GHOP. ........ r60873 | georg.brandl | 2008-02-17 12:33:38 +0100 (Sun, 17 Feb 2008) | 2 lines #2131: note that codecs.open() always opens files in binary mode. ........ --- Doc/howto/advocacy.rst | 10 +- Doc/library/codecs.rst | 10 +- Lib/logging/__init__.py | 4 + Lib/test/output/test_logging | 525 --------- Lib/test/test_logging.py | 2456 ++++++++++++++++++++++++++++++++++-------- Lib/test/test_mmap.py | 2 + Lib/test/test_scope.py | 7 + Misc/ACKS | 1 + Modules/_struct.c | 2 +- Modules/cStringIO.c | 3 +- Objects/cellobject.c | 4 +- 11 files changed, 2041 insertions(+), 983 deletions(-) delete mode 100644 Lib/test/output/test_logging diff --git a/Doc/howto/advocacy.rst b/Doc/howto/advocacy.rst index 669ce72..407bf9f 100644 --- a/Doc/howto/advocacy.rst +++ b/Doc/howto/advocacy.rst @@ -160,7 +160,7 @@ for "compact": don't merge cleanly into the overall design scheme (thus, some fans of Classic C maintain that ANSI C is no longer compact). - (From http://www.catb.org/ esr/jargon/html/C/compact.html) + (From http://www.catb.org/~esr/jargon/html/C/compact.html) In this sense of the word, Python is quite compact, because the language has just a few ideas, which are used in lots of places. Take namespaces, for @@ -174,14 +174,14 @@ standard dictionary data type: .keys() returns all the keys, and so forth. This simplicity arises from Python's development history. The language syntax derives from different sources; ABC, a relatively obscure teaching language, is one primary influence, and Modula-3 is another. (For more information about ABC -and Modula-3, consult their respective Web sites at http://www.cwi.nl/ -steven/abc/ and http://www.m3.org.) Other features have come from C, Icon, +and Modula-3, consult their respective Web sites at http://www.cwi.nl/~steven/abc/ +and http://www.m3.org.) Other features have come from C, Icon, Algol-68, and even Perl. Python hasn't really innovated very much, but instead has tried to keep the language small and easy to learn, building on ideas that have been tried in other languages and found useful. Simplicity is a virtue that should not be underestimated. It lets you learn the -language more quickly, and then rapidly write code, code that often works the +language more quickly, and then rapidly write code -- code that often works the first time you run it. @@ -266,7 +266,7 @@ the organizations that use Python. They're practically nonexistent. Consult the :file:`Misc/COPYRIGHT` file in the source distribution, or the section :ref:`history-and-license` for the full -language, but it boils down to three conditions. +language, but it boils down to three conditions: * You have to leave the copyright notice on the software; if you don't include the source code in a product, you have to put the copyright notice in the diff --git a/Doc/library/codecs.rst b/Doc/library/codecs.rst index ae79049..1491213 100644 --- a/Doc/library/codecs.rst +++ b/Doc/library/codecs.rst @@ -202,7 +202,8 @@ utility functions: .. function:: open(filename, mode[, encoding[, errors[, buffering]]]) Open an encoded file using the given *mode* and return a wrapped version - providing transparent encoding/decoding. + providing transparent encoding/decoding. The default file mode is ``'r'`` + meaning to open the file in read mode. .. note:: @@ -210,6 +211,13 @@ utility functions: i.e. Unicode objects for most built-in codecs. Output is also codec-dependent and will usually be Unicode as well. + .. note:: + + Files are always opened in binary mode, even if no binary mode was + specified. This is done to avoid data loss due to encodings using 8-bit + values. This means that no automatic conversion of ``'\n'`` is done + on reading and writing. + *encoding* specifies the encoding which is to be used for the file. *errors* may be given to define the error handling. It defaults to ``'strict'`` diff --git a/Lib/logging/__init__.py b/Lib/logging/__init__.py index 762ea43..92ab502 100644 --- a/Lib/logging/__init__.py +++ b/Lib/logging/__init__.py @@ -24,6 +24,10 @@ To use, simply 'import logging' and log away! """ import sys, os, time, io, traceback +__all__ = ['BASIC_FORMAT', 'BufferingFormatter', 'CRITICAL', 'DEBUG', 'ERROR', + 'FATAL', 'FileHandler', 'Filter', 'Filterer', 'Formatter', 'Handler', + 'INFO', 'LogRecord', 'Logger', 'Manager', 'NOTSET', 'PlaceHolder', + 'RootLogger', 'StreamHandler', 'WARN', 'WARNING'] try: import codecs diff --git a/Lib/test/output/test_logging b/Lib/test/output/test_logging deleted file mode 100644 index ebf40c5..0000000 --- a/Lib/test/output/test_logging +++ /dev/null @@ -1,525 +0,0 @@ -test_logging --- log_test0 begin --------------------------------------------------- -CRITICAL:ERR:Message 0 -ERROR:ERR:Message 1 -CRITICAL:INF:Message 2 -ERROR:INF:Message 3 -WARNING:INF:Message 4 -INFO:INF:Message 5 -CRITICAL:INF.UNDEF:Message 6 -ERROR:INF.UNDEF:Message 7 -WARNING:INF.UNDEF:Message 8 -INFO:INF.UNDEF:Message 9 -CRITICAL:INF.ERR:Message 10 -ERROR:INF.ERR:Message 11 -CRITICAL:INF.ERR.UNDEF:Message 12 -ERROR:INF.ERR.UNDEF:Message 13 -CRITICAL:DEB:Message 14 -ERROR:DEB:Message 15 -WARNING:DEB:Message 16 -INFO:DEB:Message 17 -DEBUG:DEB:Message 18 -CRITICAL:UNDEF:Message 19 -ERROR:UNDEF:Message 20 -WARNING:UNDEF:Message 21 -INFO:UNDEF:Message 22 -CRITICAL:INF.BADPARENT.UNDEF:Message 23 -CRITICAL:INF.BADPARENT:Message 24 -INFO:INF:Finish up, it's closing time. Messages should bear numbers 0 through 24. --- log_test0 end --------------------------------------------------- --- log_test1 begin --------------------------------------------------- --- setting logging level to 'Boring' ----- -Boring:root:This should only be seen at the 'Boring' logging level (or lower) -Chatterbox:root:This should only be seen at the 'Chatterbox' logging level (or lower) -Garrulous:root:This should only be seen at the 'Garrulous' logging level (or lower) -Talkative:root:This should only be seen at the 'Talkative' logging level (or lower) -Verbose:root:This should only be seen at the 'Verbose' logging level (or lower) -Sociable:root:This should only be seen at the 'Sociable' logging level (or lower) -Effusive:root:This should only be seen at the 'Effusive' logging level (or lower) -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Chatterbox' ----- -Chatterbox:root:This should only be seen at the 'Chatterbox' logging level (or lower) -Garrulous:root:This should only be seen at the 'Garrulous' logging level (or lower) -Talkative:root:This should only be seen at the 'Talkative' logging level (or lower) -Verbose:root:This should only be seen at the 'Verbose' logging level (or lower) -Sociable:root:This should only be seen at the 'Sociable' logging level (or lower) -Effusive:root:This should only be seen at the 'Effusive' logging level (or lower) -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Garrulous' ----- -Garrulous:root:This should only be seen at the 'Garrulous' logging level (or lower) -Talkative:root:This should only be seen at the 'Talkative' logging level (or lower) -Verbose:root:This should only be seen at the 'Verbose' logging level (or lower) -Sociable:root:This should only be seen at the 'Sociable' logging level (or lower) -Effusive:root:This should only be seen at the 'Effusive' logging level (or lower) -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Talkative' ----- -Talkative:root:This should only be seen at the 'Talkative' logging level (or lower) -Verbose:root:This should only be seen at the 'Verbose' logging level (or lower) -Sociable:root:This should only be seen at the 'Sociable' logging level (or lower) -Effusive:root:This should only be seen at the 'Effusive' logging level (or lower) -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Verbose' ----- -Verbose:root:This should only be seen at the 'Verbose' logging level (or lower) -Sociable:root:This should only be seen at the 'Sociable' logging level (or lower) -Effusive:root:This should only be seen at the 'Effusive' logging level (or lower) -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Sociable' ----- -Sociable:root:This should only be seen at the 'Sociable' logging level (or lower) -Effusive:root:This should only be seen at the 'Effusive' logging level (or lower) -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Effusive' ----- -Effusive:root:This should only be seen at the 'Effusive' logging level (or lower) -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Terse' ----- -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Taciturn' ----- -Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Silent' ----- -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- Filtering at handler level to SOCIABLE -- --- setting logging level to 'Boring' ----- -Sociable:root:This should only be seen at the 'Sociable' logging level (or lower) -Effusive:root:This should only be seen at the 'Effusive' logging level (or lower) -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Chatterbox' ----- -Sociable:root:This should only be seen at the 'Sociable' logging level (or lower) -Effusive:root:This should only be seen at the 'Effusive' logging level (or lower) -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Garrulous' ----- -Sociable:root:This should only be seen at the 'Sociable' logging level (or lower) -Effusive:root:This should only be seen at the 'Effusive' logging level (or lower) -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Talkative' ----- -Sociable:root:This should only be seen at the 'Sociable' logging level (or lower) -Effusive:root:This should only be seen at the 'Effusive' logging level (or lower) -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Verbose' ----- -Sociable:root:This should only be seen at the 'Sociable' logging level (or lower) -Effusive:root:This should only be seen at the 'Effusive' logging level (or lower) -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Sociable' ----- -Sociable:root:This should only be seen at the 'Sociable' logging level (or lower) -Effusive:root:This should only be seen at the 'Effusive' logging level (or lower) -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Effusive' ----- -Effusive:root:This should only be seen at the 'Effusive' logging level (or lower) -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Terse' ----- -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Taciturn' ----- -Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Silent' ----- -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- Filtering using GARRULOUS filter -- --- setting logging level to 'Boring' ----- -Boring:root:This should only be seen at the 'Boring' logging level (or lower) -Chatterbox:root:This should only be seen at the 'Chatterbox' logging level (or lower) -Talkative:root:This should only be seen at the 'Talkative' logging level (or lower) -Verbose:root:This should only be seen at the 'Verbose' logging level (or lower) -Sociable:root:This should only be seen at the 'Sociable' logging level (or lower) -Effusive:root:This should only be seen at the 'Effusive' logging level (or lower) -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Chatterbox' ----- -Chatterbox:root:This should only be seen at the 'Chatterbox' logging level (or lower) -Talkative:root:This should only be seen at the 'Talkative' logging level (or lower) -Verbose:root:This should only be seen at the 'Verbose' logging level (or lower) -Sociable:root:This should only be seen at the 'Sociable' logging level (or lower) -Effusive:root:This should only be seen at the 'Effusive' logging level (or lower) -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Garrulous' ----- -Talkative:root:This should only be seen at the 'Talkative' logging level (or lower) -Verbose:root:This should only be seen at the 'Verbose' logging level (or lower) -Sociable:root:This should only be seen at the 'Sociable' logging level (or lower) -Effusive:root:This should only be seen at the 'Effusive' logging level (or lower) -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Talkative' ----- -Talkative:root:This should only be seen at the 'Talkative' logging level (or lower) -Verbose:root:This should only be seen at the 'Verbose' logging level (or lower) -Sociable:root:This should only be seen at the 'Sociable' logging level (or lower) -Effusive:root:This should only be seen at the 'Effusive' logging level (or lower) -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Verbose' ----- -Verbose:root:This should only be seen at the 'Verbose' logging level (or lower) -Sociable:root:This should only be seen at the 'Sociable' logging level (or lower) -Effusive:root:This should only be seen at the 'Effusive' logging level (or lower) -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Sociable' ----- -Sociable:root:This should only be seen at the 'Sociable' logging level (or lower) -Effusive:root:This should only be seen at the 'Effusive' logging level (or lower) -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Effusive' ----- -Effusive:root:This should only be seen at the 'Effusive' logging level (or lower) -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Terse' ----- -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Taciturn' ----- -Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Silent' ----- -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- Filtering using specific filter for SOCIABLE, TACITURN -- --- setting logging level to 'Boring' ----- -Boring:root:This should only be seen at the 'Boring' logging level (or lower) -Chatterbox:root:This should only be seen at the 'Chatterbox' logging level (or lower) -Talkative:root:This should only be seen at the 'Talkative' logging level (or lower) -Verbose:root:This should only be seen at the 'Verbose' logging level (or lower) -Effusive:root:This should only be seen at the 'Effusive' logging level (or lower) -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Chatterbox' ----- -Chatterbox:root:This should only be seen at the 'Chatterbox' logging level (or lower) -Talkative:root:This should only be seen at the 'Talkative' logging level (or lower) -Verbose:root:This should only be seen at the 'Verbose' logging level (or lower) -Effusive:root:This should only be seen at the 'Effusive' logging level (or lower) -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Garrulous' ----- -Talkative:root:This should only be seen at the 'Talkative' logging level (or lower) -Verbose:root:This should only be seen at the 'Verbose' logging level (or lower) -Effusive:root:This should only be seen at the 'Effusive' logging level (or lower) -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Talkative' ----- -Talkative:root:This should only be seen at the 'Talkative' logging level (or lower) -Verbose:root:This should only be seen at the 'Verbose' logging level (or lower) -Effusive:root:This should only be seen at the 'Effusive' logging level (or lower) -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Verbose' ----- -Verbose:root:This should only be seen at the 'Verbose' logging level (or lower) -Effusive:root:This should only be seen at the 'Effusive' logging level (or lower) -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Sociable' ----- -Effusive:root:This should only be seen at the 'Effusive' logging level (or lower) -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Effusive' ----- -Effusive:root:This should only be seen at the 'Effusive' logging level (or lower) -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Terse' ----- -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Taciturn' ----- -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Silent' ----- -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- log_test1 end --------------------------------------------------- --- log_test2 begin --------------------------------------------------- --- logging at DEBUG, nothing should be seen yet -- --- logging at INFO, nothing should be seen yet -- --- logging at WARNING, 3 messages should be seen -- -DEBUG:root:Debug message -INFO:root:Info message -WARNING:root:Warn message --- logging 0 at INFO, messages should be seen every 10 events -- --- logging 1 at INFO, messages should be seen every 10 events -- --- logging 2 at INFO, messages should be seen every 10 events -- --- logging 3 at INFO, messages should be seen every 10 events -- --- logging 4 at INFO, messages should be seen every 10 events -- --- logging 5 at INFO, messages should be seen every 10 events -- --- logging 6 at INFO, messages should be seen every 10 events -- --- logging 7 at INFO, messages should be seen every 10 events -- --- logging 8 at INFO, messages should be seen every 10 events -- --- logging 9 at INFO, messages should be seen every 10 events -- -INFO:root:Info index = 0 -INFO:root:Info index = 1 -INFO:root:Info index = 2 -INFO:root:Info index = 3 -INFO:root:Info index = 4 -INFO:root:Info index = 5 -INFO:root:Info index = 6 -INFO:root:Info index = 7 -INFO:root:Info index = 8 -INFO:root:Info index = 9 --- logging 10 at INFO, messages should be seen every 10 events -- --- logging 11 at INFO, messages should be seen every 10 events -- --- logging 12 at INFO, messages should be seen every 10 events -- --- logging 13 at INFO, messages should be seen every 10 events -- --- logging 14 at INFO, messages should be seen every 10 events -- --- logging 15 at INFO, messages should be seen every 10 events -- --- logging 16 at INFO, messages should be seen every 10 events -- --- logging 17 at INFO, messages should be seen every 10 events -- --- logging 18 at INFO, messages should be seen every 10 events -- --- logging 19 at INFO, messages should be seen every 10 events -- -INFO:root:Info index = 10 -INFO:root:Info index = 11 -INFO:root:Info index = 12 -INFO:root:Info index = 13 -INFO:root:Info index = 14 -INFO:root:Info index = 15 -INFO:root:Info index = 16 -INFO:root:Info index = 17 -INFO:root:Info index = 18 -INFO:root:Info index = 19 --- logging 20 at INFO, messages should be seen every 10 events -- --- logging 21 at INFO, messages should be seen every 10 events -- --- logging 22 at INFO, messages should be seen every 10 events -- --- logging 23 at INFO, messages should be seen every 10 events -- --- logging 24 at INFO, messages should be seen every 10 events -- --- logging 25 at INFO, messages should be seen every 10 events -- --- logging 26 at INFO, messages should be seen every 10 events -- --- logging 27 at INFO, messages should be seen every 10 events -- --- logging 28 at INFO, messages should be seen every 10 events -- --- logging 29 at INFO, messages should be seen every 10 events -- -INFO:root:Info index = 20 -INFO:root:Info index = 21 -INFO:root:Info index = 22 -INFO:root:Info index = 23 -INFO:root:Info index = 24 -INFO:root:Info index = 25 -INFO:root:Info index = 26 -INFO:root:Info index = 27 -INFO:root:Info index = 28 -INFO:root:Info index = 29 --- logging 30 at INFO, messages should be seen every 10 events -- --- logging 31 at INFO, messages should be seen every 10 events -- --- logging 32 at INFO, messages should be seen every 10 events -- --- logging 33 at INFO, messages should be seen every 10 events -- --- logging 34 at INFO, messages should be seen every 10 events -- --- logging 35 at INFO, messages should be seen every 10 events -- --- logging 36 at INFO, messages should be seen every 10 events -- --- logging 37 at INFO, messages should be seen every 10 events -- --- logging 38 at INFO, messages should be seen every 10 events -- --- logging 39 at INFO, messages should be seen every 10 events -- -INFO:root:Info index = 30 -INFO:root:Info index = 31 -INFO:root:Info index = 32 -INFO:root:Info index = 33 -INFO:root:Info index = 34 -INFO:root:Info index = 35 -INFO:root:Info index = 36 -INFO:root:Info index = 37 -INFO:root:Info index = 38 -INFO:root:Info index = 39 --- logging 40 at INFO, messages should be seen every 10 events -- --- logging 41 at INFO, messages should be seen every 10 events -- --- logging 42 at INFO, messages should be seen every 10 events -- --- logging 43 at INFO, messages should be seen every 10 events -- --- logging 44 at INFO, messages should be seen every 10 events -- --- logging 45 at INFO, messages should be seen every 10 events -- --- logging 46 at INFO, messages should be seen every 10 events -- --- logging 47 at INFO, messages should be seen every 10 events -- --- logging 48 at INFO, messages should be seen every 10 events -- --- logging 49 at INFO, messages should be seen every 10 events -- -INFO:root:Info index = 40 -INFO:root:Info index = 41 -INFO:root:Info index = 42 -INFO:root:Info index = 43 -INFO:root:Info index = 44 -INFO:root:Info index = 45 -INFO:root:Info index = 46 -INFO:root:Info index = 47 -INFO:root:Info index = 48 -INFO:root:Info index = 49 --- logging 50 at INFO, messages should be seen every 10 events -- --- logging 51 at INFO, messages should be seen every 10 events -- --- logging 52 at INFO, messages should be seen every 10 events -- --- logging 53 at INFO, messages should be seen every 10 events -- --- logging 54 at INFO, messages should be seen every 10 events -- --- logging 55 at INFO, messages should be seen every 10 events -- --- logging 56 at INFO, messages should be seen every 10 events -- --- logging 57 at INFO, messages should be seen every 10 events -- --- logging 58 at INFO, messages should be seen every 10 events -- --- logging 59 at INFO, messages should be seen every 10 events -- -INFO:root:Info index = 50 -INFO:root:Info index = 51 -INFO:root:Info index = 52 -INFO:root:Info index = 53 -INFO:root:Info index = 54 -INFO:root:Info index = 55 -INFO:root:Info index = 56 -INFO:root:Info index = 57 -INFO:root:Info index = 58 -INFO:root:Info index = 59 --- logging 60 at INFO, messages should be seen every 10 events -- --- logging 61 at INFO, messages should be seen every 10 events -- --- logging 62 at INFO, messages should be seen every 10 events -- --- logging 63 at INFO, messages should be seen every 10 events -- --- logging 64 at INFO, messages should be seen every 10 events -- --- logging 65 at INFO, messages should be seen every 10 events -- --- logging 66 at INFO, messages should be seen every 10 events -- --- logging 67 at INFO, messages should be seen every 10 events -- --- logging 68 at INFO, messages should be seen every 10 events -- --- logging 69 at INFO, messages should be seen every 10 events -- -INFO:root:Info index = 60 -INFO:root:Info index = 61 -INFO:root:Info index = 62 -INFO:root:Info index = 63 -INFO:root:Info index = 64 -INFO:root:Info index = 65 -INFO:root:Info index = 66 -INFO:root:Info index = 67 -INFO:root:Info index = 68 -INFO:root:Info index = 69 --- logging 70 at INFO, messages should be seen every 10 events -- --- logging 71 at INFO, messages should be seen every 10 events -- --- logging 72 at INFO, messages should be seen every 10 events -- --- logging 73 at INFO, messages should be seen every 10 events -- --- logging 74 at INFO, messages should be seen every 10 events -- --- logging 75 at INFO, messages should be seen every 10 events -- --- logging 76 at INFO, messages should be seen every 10 events -- --- logging 77 at INFO, messages should be seen every 10 events -- --- logging 78 at INFO, messages should be seen every 10 events -- --- logging 79 at INFO, messages should be seen every 10 events -- -INFO:root:Info index = 70 -INFO:root:Info index = 71 -INFO:root:Info index = 72 -INFO:root:Info index = 73 -INFO:root:Info index = 74 -INFO:root:Info index = 75 -INFO:root:Info index = 76 -INFO:root:Info index = 77 -INFO:root:Info index = 78 -INFO:root:Info index = 79 --- logging 80 at INFO, messages should be seen every 10 events -- --- logging 81 at INFO, messages should be seen every 10 events -- --- logging 82 at INFO, messages should be seen every 10 events -- --- logging 83 at INFO, messages should be seen every 10 events -- --- logging 84 at INFO, messages should be seen every 10 events -- --- logging 85 at INFO, messages should be seen every 10 events -- --- logging 86 at INFO, messages should be seen every 10 events -- --- logging 87 at INFO, messages should be seen every 10 events -- --- logging 88 at INFO, messages should be seen every 10 events -- --- logging 89 at INFO, messages should be seen every 10 events -- -INFO:root:Info index = 80 -INFO:root:Info index = 81 -INFO:root:Info index = 82 -INFO:root:Info index = 83 -INFO:root:Info index = 84 -INFO:root:Info index = 85 -INFO:root:Info index = 86 -INFO:root:Info index = 87 -INFO:root:Info index = 88 -INFO:root:Info index = 89 --- logging 90 at INFO, messages should be seen every 10 events -- --- logging 91 at INFO, messages should be seen every 10 events -- --- logging 92 at INFO, messages should be seen every 10 events -- --- logging 93 at INFO, messages should be seen every 10 events -- --- logging 94 at INFO, messages should be seen every 10 events -- --- logging 95 at INFO, messages should be seen every 10 events -- --- logging 96 at INFO, messages should be seen every 10 events -- --- logging 97 at INFO, messages should be seen every 10 events -- --- logging 98 at INFO, messages should be seen every 10 events -- --- logging 99 at INFO, messages should be seen every 10 events -- -INFO:root:Info index = 90 -INFO:root:Info index = 91 -INFO:root:Info index = 92 -INFO:root:Info index = 93 -INFO:root:Info index = 94 -INFO:root:Info index = 95 -INFO:root:Info index = 96 -INFO:root:Info index = 97 -INFO:root:Info index = 98 -INFO:root:Info index = 99 --- logging 100 at INFO, messages should be seen every 10 events -- --- logging 101 at INFO, messages should be seen every 10 events -- -INFO:root:Info index = 100 -INFO:root:Info index = 101 --- log_test2 end --------------------------------------------------- --- log_test3 begin --------------------------------------------------- -Unfiltered... -INFO:a:Info 1 -INFO:a.b:Info 2 -INFO:a.c:Info 3 -INFO:a.b.c:Info 4 -INFO:a.b.c.d:Info 5 -INFO:a.bb.c:Info 6 -INFO:b:Info 7 -INFO:b.a:Info 8 -INFO:c.a.b:Info 9 -INFO:a.bb:Info 10 -Filtered with 'a.b'... -INFO:a.b:Info 2 -INFO:a.b.c:Info 4 -INFO:a.b.c.d:Info 5 --- log_test3 end --------------------------------------------------- --- log_test4 begin --------------------------------------------------- -config0: ok. -config1: ok. -config2: -config3: --- log_test4 end --------------------------------------------------- --- log_test5 begin --------------------------------------------------- -ERROR:root:just testing -... Don't panic! --- log_test5 end --------------------------------------------------- --- logrecv output begin --------------------------------------------------- -ERR -> CRITICAL: Message 0 (via logrecv.tcp.ERR) -ERR -> ERROR: Message 1 (via logrecv.tcp.ERR) -INF -> CRITICAL: Message 2 (via logrecv.tcp.INF) -INF -> ERROR: Message 3 (via logrecv.tcp.INF) -INF -> WARNING: Message 4 (via logrecv.tcp.INF) -INF -> INFO: Message 5 (via logrecv.tcp.INF) -INF.UNDEF -> CRITICAL: Message 6 (via logrecv.tcp.INF.UNDEF) -INF.UNDEF -> ERROR: Message 7 (via logrecv.tcp.INF.UNDEF) -INF.UNDEF -> WARNING: Message 8 (via logrecv.tcp.INF.UNDEF) -INF.UNDEF -> INFO: Message 9 (via logrecv.tcp.INF.UNDEF) -INF.ERR -> CRITICAL: Message 10 (via logrecv.tcp.INF.ERR) -INF.ERR -> ERROR: Message 11 (via logrecv.tcp.INF.ERR) -INF.ERR.UNDEF -> CRITICAL: Message 12 (via logrecv.tcp.INF.ERR.UNDEF) -INF.ERR.UNDEF -> ERROR: Message 13 (via logrecv.tcp.INF.ERR.UNDEF) -DEB -> CRITICAL: Message 14 (via logrecv.tcp.DEB) -DEB -> ERROR: Message 15 (via logrecv.tcp.DEB) -DEB -> WARNING: Message 16 (via logrecv.tcp.DEB) -DEB -> INFO: Message 17 (via logrecv.tcp.DEB) -DEB -> DEBUG: Message 18 (via logrecv.tcp.DEB) -UNDEF -> CRITICAL: Message 19 (via logrecv.tcp.UNDEF) -UNDEF -> ERROR: Message 20 (via logrecv.tcp.UNDEF) -UNDEF -> WARNING: Message 21 (via logrecv.tcp.UNDEF) -UNDEF -> INFO: Message 22 (via logrecv.tcp.UNDEF) -INF.BADPARENT.UNDEF -> CRITICAL: Message 23 (via logrecv.tcp.INF.BADPARENT.UNDEF) -INF.BADPARENT -> CRITICAL: Message 24 (via logrecv.tcp.INF.BADPARENT) -INF -> INFO: Finish up, it's closing time. Messages should bear numbers 0 through 24. (via logrecv.tcp.INF) --- logrecv output end --------------------------------------------------- diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py index 127cf84..a31ad37 100644 --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -1,38 +1,1883 @@ #!/usr/bin/env python -# -# Copyright 2001-2004 by Vinay Sajip. All Rights Reserved. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose and without fee is hereby granted, -# provided that the above copyright notice appear in all copies and that -# both that copyright notice and this permission notice appear in -# supporting documentation, and that the name of Vinay Sajip -# not be used in advertising or publicity pertaining to distribution -# of the software without specific, written prior permission. -# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL -# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# -# This file is part of the Python logging distribution. See -# http://www.red-dove.com/python_logging.html -# -"""Test harness for the logging module. Run all tests. - -Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved. """ +Test 0 +====== +Some preliminaries: +>>> import sys +>>> import logging +>>> def nextmessage(): +... global msgcount +... rv = "Message %d" % msgcount +... msgcount = msgcount + 1 +... return rv + +Set a few variables, then go through the logger autoconfig and set the default threshold. +>>> msgcount = 0 +>>> FINISH_UP = "Finish up, it's closing time. Messages should bear numbers 0 through 24." +>>> logging.basicConfig(stream=sys.stdout) +>>> rootLogger = logging.getLogger("") +>>> rootLogger.setLevel(logging.DEBUG) + +Now, create a bunch of loggers, and set their thresholds. +>>> ERR = logging.getLogger("ERR0") +>>> ERR.setLevel(logging.ERROR) +>>> INF = logging.getLogger("INFO0") +>>> INF.setLevel(logging.INFO) +>>> INF_ERR = logging.getLogger("INFO0.ERR") +>>> INF_ERR.setLevel(logging.ERROR) +>>> DEB = logging.getLogger("DEB0") +>>> DEB.setLevel(logging.DEBUG) +>>> INF_UNDEF = logging.getLogger("INFO0.UNDEF") +>>> INF_ERR_UNDEF = logging.getLogger("INFO0.ERR.UNDEF") +>>> UNDEF = logging.getLogger("UNDEF0") +>>> GRANDCHILD = logging.getLogger("INFO0.BADPARENT.UNDEF") +>>> CHILD = logging.getLogger("INFO0.BADPARENT") + + +And finally, run all the tests. + +>>> ERR.log(logging.FATAL, nextmessage()) +CRITICAL:ERR0:Message 0 + +>>> ERR.error(nextmessage()) +ERROR:ERR0:Message 1 + +>>> INF.log(logging.FATAL, nextmessage()) +CRITICAL:INFO0:Message 2 + +>>> INF.error(nextmessage()) +ERROR:INFO0:Message 3 + +>>> INF.warn(nextmessage()) +WARNING:INFO0:Message 4 + +>>> INF.info(nextmessage()) +INFO:INFO0:Message 5 + +>>> INF_UNDEF.log(logging.FATAL, nextmessage()) +CRITICAL:INFO0.UNDEF:Message 6 + +>>> INF_UNDEF.error(nextmessage()) +ERROR:INFO0.UNDEF:Message 7 + +>>> INF_UNDEF.warn (nextmessage()) +WARNING:INFO0.UNDEF:Message 8 + +>>> INF_UNDEF.info (nextmessage()) +INFO:INFO0.UNDEF:Message 9 + +>>> INF_ERR.log(logging.FATAL, nextmessage()) +CRITICAL:INFO0.ERR:Message 10 + +>>> INF_ERR.error(nextmessage()) +ERROR:INFO0.ERR:Message 11 + +>>> INF_ERR_UNDEF.log(logging.FATAL, nextmessage()) +CRITICAL:INFO0.ERR.UNDEF:Message 12 + +>>> INF_ERR_UNDEF.error(nextmessage()) +ERROR:INFO0.ERR.UNDEF:Message 13 + +>>> DEB.log(logging.FATAL, nextmessage()) +CRITICAL:DEB0:Message 14 + +>>> DEB.error(nextmessage()) +ERROR:DEB0:Message 15 + +>>> DEB.warn (nextmessage()) +WARNING:DEB0:Message 16 + +>>> DEB.info (nextmessage()) +INFO:DEB0:Message 17 + +>>> DEB.debug(nextmessage()) +DEBUG:DEB0:Message 18 + +>>> UNDEF.log(logging.FATAL, nextmessage()) +CRITICAL:UNDEF0:Message 19 + +>>> UNDEF.error(nextmessage()) +ERROR:UNDEF0:Message 20 + +>>> UNDEF.warn (nextmessage()) +WARNING:UNDEF0:Message 21 + +>>> UNDEF.info (nextmessage()) +INFO:UNDEF0:Message 22 + +>>> GRANDCHILD.log(logging.FATAL, nextmessage()) +CRITICAL:INFO0.BADPARENT.UNDEF:Message 23 + +>>> CHILD.log(logging.FATAL, nextmessage()) +CRITICAL:INFO0.BADPARENT:Message 24 + +These should not log: + +>>> ERR.warn(nextmessage()) + +>>> ERR.info(nextmessage()) + +>>> ERR.debug(nextmessage()) + +>>> INF.debug(nextmessage()) + +>>> INF_UNDEF.debug(nextmessage()) + +>>> INF_ERR.warn(nextmessage()) + +>>> INF_ERR.info(nextmessage()) + +>>> INF_ERR.debug(nextmessage()) + +>>> INF_ERR_UNDEF.warn(nextmessage()) + +>>> INF_ERR_UNDEF.info(nextmessage()) + +>>> INF_ERR_UNDEF.debug(nextmessage()) + +>>> INF.info(FINISH_UP) +INFO:INFO0:Finish up, it's closing time. Messages should bear numbers 0 through 24. + +Test 1 +====== + +>>> import sys, logging +>>> logging.basicConfig(stream=sys.stdout) + +First, we define our levels. There can be as many as you want - the only +limitations are that they should be integers, the lowest should be > 0 and +larger values mean less information being logged. If you need specific +level values which do not fit into these limitations, you can use a +mapping dictionary to convert between your application levels and the +logging system. + +>>> SILENT = 10 +>>> TACITURN = 9 +>>> TERSE = 8 +>>> EFFUSIVE = 7 +>>> SOCIABLE = 6 +>>> VERBOSE = 5 +>>> TALKATIVE = 4 +>>> GARRULOUS = 3 +>>> CHATTERBOX = 2 +>>> BORING = 1 +>>> LEVEL_RANGE = range(BORING, SILENT + 1) + + +Next, we define names for our levels. You don't need to do this - in which + case the system will use "Level n" to denote the text for the level. +' + + +>>> my_logging_levels = { +... SILENT : 'SILENT', +... TACITURN : 'TACITURN', +... TERSE : 'TERSE', +... EFFUSIVE : 'EFFUSIVE', +... SOCIABLE : 'SOCIABLE', +... VERBOSE : 'VERBOSE', +... TALKATIVE : 'TALKATIVE', +... GARRULOUS : 'GARRULOUS', +... CHATTERBOX : 'CHATTERBOX', +... BORING : 'BORING', +... } + + +Now, to demonstrate filtering: suppose for some perverse reason we only +want to print out all except GARRULOUS messages. We create a filter for +this purpose... + +>>> class SpecificLevelFilter(logging.Filter): +... def __init__(self, lvl): +... self.level = lvl +... +... def filter(self, record): +... return self.level != record.levelno + +>>> class GarrulousFilter(SpecificLevelFilter): +... def __init__(self): +... SpecificLevelFilter.__init__(self, GARRULOUS) + + +Now, demonstrate filtering at the logger. This time, use a filter +which excludes SOCIABLE and TACITURN messages. Note that GARRULOUS events +are still excluded. + + +>>> class VerySpecificFilter(logging.Filter): +... def filter(self, record): +... return record.levelno not in [SOCIABLE, TACITURN] + +>>> SHOULD1 = "This should only be seen at the '%s' logging level (or lower)" + +Configure the logger, and tell the logging system to associate names with our levels. +>>> logging.basicConfig(stream=sys.stdout) +>>> rootLogger = logging.getLogger("") +>>> rootLogger.setLevel(logging.DEBUG) +>>> for lvl in my_logging_levels.keys(): +... logging.addLevelName(lvl, my_logging_levels[lvl]) +>>> log = logging.getLogger("") +>>> hdlr = log.handlers[0] +>>> from test.test_logging import message + +Set the logging level to each different value and call the utility +function to log events. In the output, you should see that each time +round the loop, the number of logging events which are actually output +decreases. + +>>> log.setLevel(1) + +>>> log.log(1, "This should only be seen at the '%s' logging level (or lower)", BORING) +BORING:root:This should only be seen at the '1' logging level (or lower) + +>>> log.log(2, "This should only be seen at the '%s' logging level (or lower)", CHATTERBOX) +CHATTERBOX:root:This should only be seen at the '2' logging level (or lower) + +>>> log.log(3, "This should only be seen at the '%s' logging level (or lower)", GARRULOUS) +GARRULOUS:root:This should only be seen at the '3' logging level (or lower) + +>>> log.log(4, "This should only be seen at the '%s' logging level (or lower)", TALKATIVE) +TALKATIVE:root:This should only be seen at the '4' logging level (or lower) + +>>> log.log(5, "This should only be seen at the '%s' logging level (or lower)", VERBOSE) +VERBOSE:root:This should only be seen at the '5' logging level (or lower) + +>>> log.log(6, "This should only be seen at the '%s' logging level (or lower)", SOCIABLE) +SOCIABLE:root:This should only be seen at the '6' logging level (or lower) + +>>> log.log(7, "This should only be seen at the '%s' logging level (or lower)", EFFUSIVE) +EFFUSIVE:root:This should only be seen at the '7' logging level (or lower) + +>>> log.log(8, "This should only be seen at the '%s' logging level (or lower)", TERSE) +TERSE:root:This should only be seen at the '8' logging level (or lower) + +>>> log.log(9, "This should only be seen at the '%s' logging level (or lower)", TACITURN) +TACITURN:root:This should only be seen at the '9' logging level (or lower) + +>>> log.log(10, "This should only be seen at the '%s' logging level (or lower)", SILENT) +SILENT:root:This should only be seen at the '10' logging level (or lower) + +>>> log.setLevel(0) + +>>> log.setLevel(2) + +>>> log.log(1, "This should only be seen at the '%s' logging level (or lower)", BORING) + +>>> log.log(2, "This should only be seen at the '%s' logging level (or lower)", CHATTERBOX) +CHATTERBOX:root:This should only be seen at the '2' logging level (or lower) + +>>> log.log(3, "This should only be seen at the '%s' logging level (or lower)", GARRULOUS) +GARRULOUS:root:This should only be seen at the '3' logging level (or lower) + +>>> log.log(4, "This should only be seen at the '%s' logging level (or lower)", TALKATIVE) +TALKATIVE:root:This should only be seen at the '4' logging level (or lower) + +>>> log.log(5, "This should only be seen at the '%s' logging level (or lower)", VERBOSE) +VERBOSE:root:This should only be seen at the '5' logging level (or lower) + +>>> log.log(6, "This should only be seen at the '%s' logging level (or lower)", SOCIABLE) +SOCIABLE:root:This should only be seen at the '6' logging level (or lower) + +>>> log.log(7, "This should only be seen at the '%s' logging level (or lower)", EFFUSIVE) +EFFUSIVE:root:This should only be seen at the '7' logging level (or lower) + +>>> log.log(8, "This should only be seen at the '%s' logging level (or lower)", TERSE) +TERSE:root:This should only be seen at the '8' logging level (or lower) + +>>> log.log(9, "This should only be seen at the '%s' logging level (or lower)", TACITURN) +TACITURN:root:This should only be seen at the '9' logging level (or lower) + +>>> log.log(10, "This should only be seen at the '%s' logging level (or lower)", SILENT) +SILENT:root:This should only be seen at the '10' logging level (or lower) + +>>> log.setLevel(3) + +>>> log.log(1, "This should only be seen at the '%s' logging level (or lower)", BORING) + +>>> log.log(2, "This should only be seen at the '%s' logging level (or lower)", CHATTERBOX) + +>>> log.log(3, "This should only be seen at the '%s' logging level (or lower)", GARRULOUS) +GARRULOUS:root:This should only be seen at the '3' logging level (or lower) + +>>> log.log(4, "This should only be seen at the '%s' logging level (or lower)", TALKATIVE) +TALKATIVE:root:This should only be seen at the '4' logging level (or lower) + +>>> log.log(5, "This should only be seen at the '%s' logging level (or lower)", VERBOSE) +VERBOSE:root:This should only be seen at the '5' logging level (or lower) + +>>> log.log(6, "This should only be seen at the '%s' logging level (or lower)", SOCIABLE) +SOCIABLE:root:This should only be seen at the '6' logging level (or lower) + +>>> log.log(7, "This should only be seen at the '%s' logging level (or lower)", EFFUSIVE) +EFFUSIVE:root:This should only be seen at the '7' logging level (or lower) + +>>> log.log(8, "This should only be seen at the '%s' logging level (or lower)", TERSE) +TERSE:root:This should only be seen at the '8' logging level (or lower) + +>>> log.log(9, "This should only be seen at the '%s' logging level (or lower)", TACITURN) +TACITURN:root:This should only be seen at the '9' logging level (or lower) + +>>> log.log(10, "This should only be seen at the '%s' logging level (or lower)", SILENT) +SILENT:root:This should only be seen at the '10' logging level (or lower) + +>>> log.setLevel(4) + +>>> log.log(1, "This should only be seen at the '%s' logging level (or lower)", BORING) + +>>> log.log(2, "This should only be seen at the '%s' logging level (or lower)", CHATTERBOX) + +>>> log.log(3, "This should only be seen at the '%s' logging level (or lower)", GARRULOUS) + +>>> log.log(4, "This should only be seen at the '%s' logging level (or lower)", TALKATIVE) +TALKATIVE:root:This should only be seen at the '4' logging level (or lower) + +>>> log.log(5, "This should only be seen at the '%s' logging level (or lower)", VERBOSE) +VERBOSE:root:This should only be seen at the '5' logging level (or lower) + +>>> log.log(6, "This should only be seen at the '%s' logging level (or lower)", SOCIABLE) +SOCIABLE:root:This should only be seen at the '6' logging level (or lower) + +>>> log.log(7, "This should only be seen at the '%s' logging level (or lower)", EFFUSIVE) +EFFUSIVE:root:This should only be seen at the '7' logging level (or lower) + +>>> log.log(8, "This should only be seen at the '%s' logging level (or lower)", TERSE) +TERSE:root:This should only be seen at the '8' logging level (or lower) + +>>> log.log(9, "This should only be seen at the '%s' logging level (or lower)", TACITURN) +TACITURN:root:This should only be seen at the '9' logging level (or lower) + +>>> log.log(10, "This should only be seen at the '%s' logging level (or lower)", SILENT) +SILENT:root:This should only be seen at the '10' logging level (or lower) + +>>> log.setLevel(5) + +>>> log.log(1, "This should only be seen at the '%s' logging level (or lower)", BORING) + +>>> log.log(2, "This should only be seen at the '%s' logging level (or lower)", CHATTERBOX) + +>>> log.log(3, "This should only be seen at the '%s' logging level (or lower)", GARRULOUS) + +>>> log.log(4, "This should only be seen at the '%s' logging level (or lower)", TALKATIVE) + +>>> log.log(5, "This should only be seen at the '%s' logging level (or lower)", VERBOSE) +VERBOSE:root:This should only be seen at the '5' logging level (or lower) + +>>> log.log(6, "This should only be seen at the '%s' logging level (or lower)", SOCIABLE) +SOCIABLE:root:This should only be seen at the '6' logging level (or lower) + +>>> log.log(7, "This should only be seen at the '%s' logging level (or lower)", EFFUSIVE) +EFFUSIVE:root:This should only be seen at the '7' logging level (or lower) + +>>> log.log(8, "This should only be seen at the '%s' logging level (or lower)", TERSE) +TERSE:root:This should only be seen at the '8' logging level (or lower) + +>>> log.log(9, "This should only be seen at the '%s' logging level (or lower)", TACITURN) +TACITURN:root:This should only be seen at the '9' logging level (or lower) + +>>> log.log(10, "This should only be seen at the '%s' logging level (or lower)", SILENT) +SILENT:root:This should only be seen at the '10' logging level (or lower) + + +>>> log.setLevel(6) + +>>> log.log(1, "This should only be seen at the '%s' logging level (or lower)", BORING) + +>>> log.log(2, "This should only be seen at the '%s' logging level (or lower)", CHATTERBOX) + +>>> log.log(3, "This should only be seen at the '%s' logging level (or lower)", GARRULOUS) + +>>> log.log(4, "This should only be seen at the '%s' logging level (or lower)", TALKATIVE) + +>>> log.log(5, "This should only be seen at the '%s' logging level (or lower)", VERBOSE) + +>>> log.log(6, "This should only be seen at the '%s' logging level (or lower)", SOCIABLE) +SOCIABLE:root:This should only be seen at the '6' logging level (or lower) + +>>> log.log(7, "This should only be seen at the '%s' logging level (or lower)", EFFUSIVE) +EFFUSIVE:root:This should only be seen at the '7' logging level (or lower) + +>>> log.log(8, "This should only be seen at the '%s' logging level (or lower)", TERSE) +TERSE:root:This should only be seen at the '8' logging level (or lower) + +>>> log.log(9, "This should only be seen at the '%s' logging level (or lower)", TACITURN) +TACITURN:root:This should only be seen at the '9' logging level (or lower) + +>>> log.log(10, "This should only be seen at the '%s' logging level (or lower)", SILENT) +SILENT:root:This should only be seen at the '10' logging level (or lower) + +>>> log.setLevel(7) + +>>> log.log(1, "This should only be seen at the '%s' logging level (or lower)", BORING) + +>>> log.log(2, "This should only be seen at the '%s' logging level (or lower)", CHATTERBOX) + +>>> log.log(3, "This should only be seen at the '%s' logging level (or lower)", GARRULOUS) + +>>> log.log(4, "This should only be seen at the '%s' logging level (or lower)", TALKATIVE) + +>>> log.log(5, "This should only be seen at the '%s' logging level (or lower)", VERBOSE) + +>>> log.log(6, "This should only be seen at the '%s' logging level (or lower)", SOCIABLE) + +>>> log.log(7, "This should only be seen at the '%s' logging level (or lower)", EFFUSIVE) +EFFUSIVE:root:This should only be seen at the '7' logging level (or lower) + +>>> log.log(8, "This should only be seen at the '%s' logging level (or lower)", TERSE) +TERSE:root:This should only be seen at the '8' logging level (or lower) + +>>> log.log(9, "This should only be seen at the '%s' logging level (or lower)", TACITURN) +TACITURN:root:This should only be seen at the '9' logging level (or lower) + +>>> log.log(10, "This should only be seen at the '%s' logging level (or lower)", SILENT) +SILENT:root:This should only be seen at the '10' logging level (or lower) + +>>> log.setLevel(8) + +>>> log.log(1, "This should only be seen at the '%s' logging level (or lower)", BORING) + +>>> log.log(2, "This should only be seen at the '%s' logging level (or lower)", CHATTERBOX) + +>>> log.log(3, "This should only be seen at the '%s' logging level (or lower)", GARRULOUS) + +>>> log.log(4, "This should only be seen at the '%s' logging level (or lower)", TALKATIVE) + +>>> log.log(5, "This should only be seen at the '%s' logging level (or lower)", VERBOSE) + +>>> log.log(6, "This should only be seen at the '%s' logging level (or lower)", SOCIABLE) + +>>> log.log(7, "This should only be seen at the '%s' logging level (or lower)", EFFUSIVE) + +>>> log.log(8, "This should only be seen at the '%s' logging level (or lower)", TERSE) +TERSE:root:This should only be seen at the '8' logging level (or lower) + +>>> log.log(9, "This should only be seen at the '%s' logging level (or lower)", TACITURN) +TACITURN:root:This should only be seen at the '9' logging level (or lower) + +>>> log.log(10, "This should only be seen at the '%s' logging level (or lower)", SILENT) +SILENT:root:This should only be seen at the '10' logging level (or lower) + +>>> log.setLevel(0) + +>>> log.setLevel(9) + +>>> log.log(1, "This should only be seen at the '%s' logging level (or lower)", BORING) + +>>> log.log(2, "This should only be seen at the '%s' logging level (or lower)", CHATTERBOX) + +>>> log.log(3, "This should only be seen at the '%s' logging level (or lower)", GARRULOUS) + +>>> log.log(4, "This should only be seen at the '%s' logging level (or lower)", TALKATIVE) + +>>> log.log(5, "This should only be seen at the '%s' logging level (or lower)", VERBOSE) + +>>> log.log(6, "This should only be seen at the '%s' logging level (or lower)", SOCIABLE) + +>>> log.log(7, "This should only be seen at the '%s' logging level (or lower)", EFFUSIVE) + +>>> log.log(8, "This should only be seen at the '%s' logging level (or lower)", TERSE) + +>>> log.log(9, "This should only be seen at the '%s' logging level (or lower)", TACITURN) +TACITURN:root:This should only be seen at the '9' logging level (or lower) + +>>> log.log(10, "This should only be seen at the '%s' logging level (or lower)", SILENT) +SILENT:root:This should only be seen at the '10' logging level (or lower) + +>>> log.setLevel(0) + +>>> log.setLevel(10) + +>>> log.log(1, "This should only be seen at the '%s' logging level (or lower)", BORING) + +>>> log.log(2, "This should only be seen at the '%s' logging level (or lower)", CHATTERBOX) + +>>> log.log(3, "This should only be seen at the '%s' logging level (or lower)", GARRULOUS) + +>>> log.log(4, "This should only be seen at the '%s' logging level (or lower)", TALKATIVE) + +>>> log.log(5, "This should only be seen at the '%s' logging level (or lower)", VERBOSE) + +>>> log.log(6, "This should only be seen at the '%s' logging level (or lower)", SOCIABLE) + +>>> log.log(7, "This should only be seen at the '%s' logging level (or lower)", EFFUSIVE) + +>>> log.log(8, "This should only be seen at the '%s' logging level (or lower)", TERSE) + +>>> log.log(9, "This should only be seen at the '%s' logging level (or lower)", TACITURN) + +>>> log.log(10, "This should only be seen at the '%s' logging level (or lower)", SILENT) +SILENT:root:This should only be seen at the '10' logging level (or lower) + +>>> hdlr.setLevel(SOCIABLE) + +>>> log.setLevel(1) + +>>> log.log(1, "This should only be seen at the '%s' logging level (or lower)", BORING) + +>>> log.log(2, "This should only be seen at the '%s' logging level (or lower)", CHATTERBOX) + +>>> log.log(3, "This should only be seen at the '%s' logging level (or lower)", GARRULOUS) + +>>> log.log(4, "This should only be seen at the '%s' logging level (or lower)", TALKATIVE) + +>>> log.log(5, "This should only be seen at the '%s' logging level (or lower)", VERBOSE) + +>>> log.log(6, "This should only be seen at the '%s' logging level (or lower)", SOCIABLE) +SOCIABLE:root:This should only be seen at the '6' logging level (or lower) + +>>> log.log(7, "This should only be seen at the '%s' logging level (or lower)", EFFUSIVE) +EFFUSIVE:root:This should only be seen at the '7' logging level (or lower) + +>>> log.log(8, "This should only be seen at the '%s' logging level (or lower)", TERSE) +TERSE:root:This should only be seen at the '8' logging level (or lower) + +>>> log.log(9, "This should only be seen at the '%s' logging level (or lower)", TACITURN) +TACITURN:root:This should only be seen at the '9' logging level (or lower) + +>>> log.log(10, "This should only be seen at the '%s' logging level (or lower)", SILENT) +SILENT:root:This should only be seen at the '10' logging level (or lower) + +>>> log.setLevel(2) + +>>> log.log(1, "This should only be seen at the '%s' logging level (or lower)", BORING) + +>>> log.log(2, "This should only be seen at the '%s' logging level (or lower)", CHATTERBOX) + +>>> log.log(3, "This should only be seen at the '%s' logging level (or lower)", GARRULOUS) + +>>> log.log(4, "This should only be seen at the '%s' logging level (or lower)", TALKATIVE) + +>>> log.log(5, "This should only be seen at the '%s' logging level (or lower)", VERBOSE) + +>>> log.log(6, "This should only be seen at the '%s' logging level (or lower)", SOCIABLE) +SOCIABLE:root:This should only be seen at the '6' logging level (or lower) + +>>> log.log(7, "This should only be seen at the '%s' logging level (or lower)", EFFUSIVE) +EFFUSIVE:root:This should only be seen at the '7' logging level (or lower) + +>>> log.log(8, "This should only be seen at the '%s' logging level (or lower)", TERSE) +TERSE:root:This should only be seen at the '8' logging level (or lower) + +>>> log.log(9, "This should only be seen at the '%s' logging level (or lower)", TACITURN) +TACITURN:root:This should only be seen at the '9' logging level (or lower) + +>>> log.log(10, "This should only be seen at the '%s' logging level (or lower)", SILENT) +SILENT:root:This should only be seen at the '10' logging level (or lower) + +>>> log.setLevel(3) + +>>> log.log(1, "This should only be seen at the '%s' logging level (or lower)", BORING) + +>>> log.log(2, "This should only be seen at the '%s' logging level (or lower)", CHATTERBOX) + +>>> log.log(3, "This should only be seen at the '%s' logging level (or lower)", GARRULOUS) + +>>> log.log(4, "This should only be seen at the '%s' logging level (or lower)", TALKATIVE) + +>>> log.log(5, "This should only be seen at the '%s' logging level (or lower)", VERBOSE) + +>>> log.log(6, "This should only be seen at the '%s' logging level (or lower)", SOCIABLE) +SOCIABLE:root:This should only be seen at the '6' logging level (or lower) + +>>> log.log(7, "This should only be seen at the '%s' logging level (or lower)", EFFUSIVE) +EFFUSIVE:root:This should only be seen at the '7' logging level (or lower) + +>>> log.log(8, "This should only be seen at the '%s' logging level (or lower)", TERSE) +TERSE:root:This should only be seen at the '8' logging level (or lower) + +>>> log.log(9, "This should only be seen at the '%s' logging level (or lower)", TACITURN) +TACITURN:root:This should only be seen at the '9' logging level (or lower) + +>>> log.log(10, "This should only be seen at the '%s' logging level (or lower)", SILENT) +SILENT:root:This should only be seen at the '10' logging level (or lower) + +>>> log.setLevel(0) + +>>> log.setLevel(4) + +>>> log.log(1, "This should only be seen at the '%s' logging level (or lower)", BORING) + +>>> log.log(2, "This should only be seen at the '%s' logging level (or lower)", CHATTERBOX) + +>>> log.log(3, "This should only be seen at the '%s' logging level (or lower)", GARRULOUS) + +>>> log.log(4, "This should only be seen at the '%s' logging level (or lower)", TALKATIVE) + +>>> log.log(5, "This should only be seen at the '%s' logging level (or lower)", VERBOSE) + +>>> log.log(6, "This should only be seen at the '%s' logging level (or lower)", SOCIABLE) +SOCIABLE:root:This should only be seen at the '6' logging level (or lower) + +>>> log.log(7, "This should only be seen at the '%s' logging level (or lower)", EFFUSIVE) +EFFUSIVE:root:This should only be seen at the '7' logging level (or lower) + +>>> log.log(8, "This should only be seen at the '%s' logging level (or lower)", TERSE) +TERSE:root:This should only be seen at the '8' logging level (or lower) + +>>> log.log(9, "This should only be seen at the '%s' logging level (or lower)", TACITURN) +TACITURN:root:This should only be seen at the '9' logging level (or lower) + +>>> log.log(10, "This should only be seen at the '%s' logging level (or lower)", SILENT) +SILENT:root:This should only be seen at the '10' logging level (or lower) + +>>> log.setLevel(0) + +>>> log.setLevel(5) + +>>> log.log(1, "This should only be seen at the '%s' logging level (or lower)", BORING) + +>>> log.log(2, "This should only be seen at the '%s' logging level (or lower)", CHATTERBOX) + +>>> log.log(3, "This should only be seen at the '%s' logging level (or lower)", GARRULOUS) + +>>> log.log(4, "This should only be seen at the '%s' logging level (or lower)", TALKATIVE) + +>>> log.log(5, "This should only be seen at the '%s' logging level (or lower)", VERBOSE) + +>>> log.log(6, "This should only be seen at the '%s' logging level (or lower)", SOCIABLE) +SOCIABLE:root:This should only be seen at the '6' logging level (or lower) + +>>> log.log(7, "This should only be seen at the '%s' logging level (or lower)", EFFUSIVE) +EFFUSIVE:root:This should only be seen at the '7' logging level (or lower) + +>>> log.log(8, "This should only be seen at the '%s' logging level (or lower)", TERSE) +TERSE:root:This should only be seen at the '8' logging level (or lower) + +>>> log.log(9, "This should only be seen at the '%s' logging level (or lower)", TACITURN) +TACITURN:root:This should only be seen at the '9' logging level (or lower) + +>>> log.log(10, "This should only be seen at the '%s' logging level (or lower)", SILENT) +SILENT:root:This should only be seen at the '10' logging level (or lower) + +>>> log.setLevel(0) + +>>> log.setLevel(6) + +>>> log.log(1, "This should only be seen at the '%s' logging level (or lower)", BORING) + +>>> log.log(2, "This should only be seen at the '%s' logging level (or lower)", CHATTERBOX) + +>>> log.log(3, "This should only be seen at the '%s' logging level (or lower)", GARRULOUS) + +>>> log.log(4, "This should only be seen at the '%s' logging level (or lower)", TALKATIVE) + +>>> log.log(5, "This should only be seen at the '%s' logging level (or lower)", VERBOSE) + +>>> log.log(6, "This should only be seen at the '%s' logging level (or lower)", SOCIABLE) +SOCIABLE:root:This should only be seen at the '6' logging level (or lower) + +>>> log.log(7, "This should only be seen at the '%s' logging level (or lower)", EFFUSIVE) +EFFUSIVE:root:This should only be seen at the '7' logging level (or lower) + +>>> log.log(8, "This should only be seen at the '%s' logging level (or lower)", TERSE) +TERSE:root:This should only be seen at the '8' logging level (or lower) + +>>> log.log(9, "This should only be seen at the '%s' logging level (or lower)", TACITURN) +TACITURN:root:This should only be seen at the '9' logging level (or lower) + +>>> log.log(10, "This should only be seen at the '%s' logging level (or lower)", SILENT) +SILENT:root:This should only be seen at the '10' logging level (or lower) + +>>> log.setLevel(0) + +>>> log.setLevel(7) + +>>> log.log(1, "This should only be seen at the '%s' logging level (or lower)", BORING) + +>>> log.log(2, "This should only be seen at the '%s' logging level (or lower)", CHATTERBOX) + +>>> log.log(3, "This should only be seen at the '%s' logging level (or lower)", GARRULOUS) + +>>> log.log(4, "This should only be seen at the '%s' logging level (or lower)", TALKATIVE) + +>>> log.log(5, "This should only be seen at the '%s' logging level (or lower)", VERBOSE) + +>>> log.log(6, "This should only be seen at the '%s' logging level (or lower)", SOCIABLE) + +>>> log.log(7, "This should only be seen at the '%s' logging level (or lower)", EFFUSIVE) +EFFUSIVE:root:This should only be seen at the '7' logging level (or lower) + +>>> log.log(8, "This should only be seen at the '%s' logging level (or lower)", TERSE) +TERSE:root:This should only be seen at the '8' logging level (or lower) + +>>> log.log(9, "This should only be seen at the '%s' logging level (or lower)", TACITURN) +TACITURN:root:This should only be seen at the '9' logging level (or lower) + +>>> log.log(10, "This should only be seen at the '%s' logging level (or lower)", SILENT) +SILENT:root:This should only be seen at the '10' logging level (or lower) + +>>> log.setLevel(0) + +>>> log.setLevel(8) + +>>> log.log(1, "This should only be seen at the '%s' logging level (or lower)", BORING) + +>>> log.log(2, "This should only be seen at the '%s' logging level (or lower)", CHATTERBOX) + +>>> log.log(3, "This should only be seen at the '%s' logging level (or lower)", GARRULOUS) + +>>> log.log(4, "This should only be seen at the '%s' logging level (or lower)", TALKATIVE) + +>>> log.log(5, "This should only be seen at the '%s' logging level (or lower)", VERBOSE) + +>>> log.log(6, "This should only be seen at the '%s' logging level (or lower)", SOCIABLE) + +>>> log.log(7, "This should only be seen at the '%s' logging level (or lower)", EFFUSIVE) + +>>> log.log(8, "This should only be seen at the '%s' logging level (or lower)", TERSE) +TERSE:root:This should only be seen at the '8' logging level (or lower) + +>>> log.log(9, "This should only be seen at the '%s' logging level (or lower)", TACITURN) +TACITURN:root:This should only be seen at the '9' logging level (or lower) + +>>> log.log(10, "This should only be seen at the '%s' logging level (or lower)", SILENT) +SILENT:root:This should only be seen at the '10' logging level (or lower) + +>>> log.setLevel(0) + +>>> log.setLevel(9) + +>>> log.log(1, "This should only be seen at the '%s' logging level (or lower)", BORING) + +>>> log.log(2, "This should only be seen at the '%s' logging level (or lower)", CHATTERBOX) + +>>> log.log(3, "This should only be seen at the '%s' logging level (or lower)", GARRULOUS) + +>>> log.log(4, "This should only be seen at the '%s' logging level (or lower)", TALKATIVE) + +>>> log.log(5, "This should only be seen at the '%s' logging level (or lower)", VERBOSE) + +>>> log.log(6, "This should only be seen at the '%s' logging level (or lower)", SOCIABLE) + +>>> log.log(7, "This should only be seen at the '%s' logging level (or lower)", EFFUSIVE) + +>>> log.log(8, "This should only be seen at the '%s' logging level (or lower)", TERSE) + +>>> log.log(9, "This should only be seen at the '%s' logging level (or lower)", TACITURN) +TACITURN:root:This should only be seen at the '9' logging level (or lower) + +>>> log.log(10, "This should only be seen at the '%s' logging level (or lower)", SILENT) +SILENT:root:This should only be seen at the '10' logging level (or lower) + +>>> log.setLevel(0) + +>>> log.setLevel(10) + +>>> log.log(1, "This should only be seen at the '%s' logging level (or lower)", BORING) + +>>> log.log(2, "This should only be seen at the '%s' logging level (or lower)", CHATTERBOX) + +>>> log.log(3, "This should only be seen at the '%s' logging level (or lower)", GARRULOUS) + +>>> log.log(4, "This should only be seen at the '%s' logging level (or lower)", TALKATIVE) + +>>> log.log(5, "This should only be seen at the '%s' logging level (or lower)", VERBOSE) + +>>> log.log(6, "This should only be seen at the '%s' logging level (or lower)", SOCIABLE) + +>>> log.log(7, "This should only be seen at the '%s' logging level (or lower)", EFFUSIVE) + +>>> log.log(8, "This should only be seen at the '%s' logging level (or lower)", TERSE) + +>>> log.log(9, "This should only be seen at the '%s' logging level (or lower)", TACITURN) + +>>> log.log(10, "This should only be seen at the '%s' logging level (or lower)", SILENT) +SILENT:root:This should only be seen at the '10' logging level (or lower) + +>>> log.setLevel(0) + +>>> + +>>> hdlr.setLevel(0) + +>>> garr = GarrulousFilter() + +>>> hdlr.addFilter(garr) + +>>> log.setLevel(1) + +>>> log.log(1, "This should only be seen at the '%s' logging level (or lower)", BORING) +BORING:root:This should only be seen at the '1' logging level (or lower) + +>>> log.log(2, "This should only be seen at the '%s' logging level (or lower)", CHATTERBOX) +CHATTERBOX:root:This should only be seen at the '2' logging level (or lower) + +>>> log.log(3, "This should only be seen at the '%s' logging level (or lower)", GARRULOUS) + +>>> log.log(4, "This should only be seen at the '%s' logging level (or lower)", TALKATIVE) +TALKATIVE:root:This should only be seen at the '4' logging level (or lower) + +>>> log.log(5, "This should only be seen at the '%s' logging level (or lower)", VERBOSE) +VERBOSE:root:This should only be seen at the '5' logging level (or lower) + +>>> log.log(6, "This should only be seen at the '%s' logging level (or lower)", SOCIABLE) +SOCIABLE:root:This should only be seen at the '6' logging level (or lower) + +>>> log.log(7, "This should only be seen at the '%s' logging level (or lower)", EFFUSIVE) +EFFUSIVE:root:This should only be seen at the '7' logging level (or lower) + +>>> log.log(8, "This should only be seen at the '%s' logging level (or lower)", TERSE) +TERSE:root:This should only be seen at the '8' logging level (or lower) + +>>> log.log(9, "This should only be seen at the '%s' logging level (or lower)", TACITURN) +TACITURN:root:This should only be seen at the '9' logging level (or lower) + +>>> log.log(10, "This should only be seen at the '%s' logging level (or lower)", SILENT) +SILENT:root:This should only be seen at the '10' logging level (or lower) + +>>> log.setLevel(2) + +>>> log.log(1, "This should only be seen at the '%s' logging level (or lower)", BORING) + +>>> log.log(2, "This should only be seen at the '%s' logging level (or lower)", CHATTERBOX) +CHATTERBOX:root:This should only be seen at the '2' logging level (or lower) + +>>> log.log(3, "This should only be seen at the '%s' logging level (or lower)", GARRULOUS) + +>>> log.log(4, "This should only be seen at the '%s' logging level (or lower)", TALKATIVE) +TALKATIVE:root:This should only be seen at the '4' logging level (or lower) + +>>> log.log(5, "This should only be seen at the '%s' logging level (or lower)", VERBOSE) +VERBOSE:root:This should only be seen at the '5' logging level (or lower) + +>>> log.log(6, "This should only be seen at the '%s' logging level (or lower)", SOCIABLE) +SOCIABLE:root:This should only be seen at the '6' logging level (or lower) + +>>> log.log(7, "This should only be seen at the '%s' logging level (or lower)", EFFUSIVE) +EFFUSIVE:root:This should only be seen at the '7' logging level (or lower) + +>>> log.log(8, "This should only be seen at the '%s' logging level (or lower)", TERSE) +TERSE:root:This should only be seen at the '8' logging level (or lower) + +>>> log.log(9, "This should only be seen at the '%s' logging level (or lower)", TACITURN) +TACITURN:root:This should only be seen at the '9' logging level (or lower) + +>>> log.log(10, "This should only be seen at the '%s' logging level (or lower)", SILENT) +SILENT:root:This should only be seen at the '10' logging level (or lower) + +>>> log.setLevel(3) + +>>> log.log(1, "This should only be seen at the '%s' logging level (or lower)", BORING) + +>>> log.log(2, "This should only be seen at the '%s' logging level (or lower)", CHATTERBOX) + +>>> log.log(3, "This should only be seen at the '%s' logging level (or lower)", GARRULOUS) + +>>> log.log(4, "This should only be seen at the '%s' logging level (or lower)", TALKATIVE) +TALKATIVE:root:This should only be seen at the '4' logging level (or lower) + +>>> log.log(5, "This should only be seen at the '%s' logging level (or lower)", VERBOSE) +VERBOSE:root:This should only be seen at the '5' logging level (or lower) + +>>> log.log(6, "This should only be seen at the '%s' logging level (or lower)", SOCIABLE) +SOCIABLE:root:This should only be seen at the '6' logging level (or lower) + +>>> log.log(7, "This should only be seen at the '%s' logging level (or lower)", EFFUSIVE) +EFFUSIVE:root:This should only be seen at the '7' logging level (or lower) + +>>> log.log(8, "This should only be seen at the '%s' logging level (or lower)", TERSE) +TERSE:root:This should only be seen at the '8' logging level (or lower) + +>>> log.log(9, "This should only be seen at the '%s' logging level (or lower)", TACITURN) +TACITURN:root:This should only be seen at the '9' logging level (or lower) + +>>> log.log(10, "This should only be seen at the '%s' logging level (or lower)", SILENT) +SILENT:root:This should only be seen at the '10' logging level (or lower) + +>>> log.setLevel(4) + +>>> log.log(1, "This should only be seen at the '%s' logging level (or lower)", BORING) + +>>> log.log(2, "This should only be seen at the '%s' logging level (or lower)", CHATTERBOX) + +>>> log.log(3, "This should only be seen at the '%s' logging level (or lower)", GARRULOUS) + +>>> log.log(4, "This should only be seen at the '%s' logging level (or lower)", TALKATIVE) +TALKATIVE:root:This should only be seen at the '4' logging level (or lower) + +>>> log.log(5, "This should only be seen at the '%s' logging level (or lower)", VERBOSE) +VERBOSE:root:This should only be seen at the '5' logging level (or lower) + +>>> log.log(6, "This should only be seen at the '%s' logging level (or lower)", SOCIABLE) +SOCIABLE:root:This should only be seen at the '6' logging level (or lower) + +>>> log.log(7, "This should only be seen at the '%s' logging level (or lower)", EFFUSIVE) +EFFUSIVE:root:This should only be seen at the '7' logging level (or lower) + +>>> log.log(8, "This should only be seen at the '%s' logging level (or lower)", TERSE) +TERSE:root:This should only be seen at the '8' logging level (or lower) + +>>> log.log(9, "This should only be seen at the '%s' logging level (or lower)", TACITURN) +TACITURN:root:This should only be seen at the '9' logging level (or lower) + +>>> log.log(10, "This should only be seen at the '%s' logging level (or lower)", SILENT) +SILENT:root:This should only be seen at the '10' logging level (or lower) + +>>> log.setLevel(5) + +>>> log.log(1, "This should only be seen at the '%s' logging level (or lower)", BORING) + +>>> log.log(2, "This should only be seen at the '%s' logging level (or lower)", CHATTERBOX) + +>>> log.log(3, "This should only be seen at the '%s' logging level (or lower)", GARRULOUS) + +>>> log.log(4, "This should only be seen at the '%s' logging level (or lower)", TALKATIVE) + +>>> log.log(5, "This should only be seen at the '%s' logging level (or lower)", VERBOSE) +VERBOSE:root:This should only be seen at the '5' logging level (or lower) + +>>> log.log(6, "This should only be seen at the '%s' logging level (or lower)", SOCIABLE) +SOCIABLE:root:This should only be seen at the '6' logging level (or lower) + +>>> log.log(7, "This should only be seen at the '%s' logging level (or lower)", EFFUSIVE) +EFFUSIVE:root:This should only be seen at the '7' logging level (or lower) + +>>> log.log(8, "This should only be seen at the '%s' logging level (or lower)", TERSE) +TERSE:root:This should only be seen at the '8' logging level (or lower) + +>>> log.log(9, "This should only be seen at the '%s' logging level (or lower)", TACITURN) +TACITURN:root:This should only be seen at the '9' logging level (or lower) + +>>> log.log(10, "This should only be seen at the '%s' logging level (or lower)", SILENT) +SILENT:root:This should only be seen at the '10' logging level (or lower) + +>>> log.setLevel(0) + +>>> log.setLevel(6) + +>>> log.log(1, "This should only be seen at the '%s' logging level (or lower)", BORING) + +>>> log.log(2, "This should only be seen at the '%s' logging level (or lower)", CHATTERBOX) + +>>> log.log(3, "This should only be seen at the '%s' logging level (or lower)", GARRULOUS) + +>>> log.log(4, "This should only be seen at the '%s' logging level (or lower)", TALKATIVE) + +>>> log.log(5, "This should only be seen at the '%s' logging level (or lower)", VERBOSE) + +>>> log.log(6, "This should only be seen at the '%s' logging level (or lower)", SOCIABLE) +SOCIABLE:root:This should only be seen at the '6' logging level (or lower) + +>>> log.log(7, "This should only be seen at the '%s' logging level (or lower)", EFFUSIVE) +EFFUSIVE:root:This should only be seen at the '7' logging level (or lower) + +>>> log.log(8, "This should only be seen at the '%s' logging level (or lower)", TERSE) +TERSE:root:This should only be seen at the '8' logging level (or lower) + +>>> log.log(9, "This should only be seen at the '%s' logging level (or lower)", TACITURN) +TACITURN:root:This should only be seen at the '9' logging level (or lower) + +>>> log.log(10, "This should only be seen at the '%s' logging level (or lower)", SILENT) +SILENT:root:This should only be seen at the '10' logging level (or lower) + +>>> log.setLevel(7) + +>>> log.log(1, "This should only be seen at the '%s' logging level (or lower)", BORING) + +>>> log.log(2, "This should only be seen at the '%s' logging level (or lower)", CHATTERBOX) + +>>> log.log(3, "This should only be seen at the '%s' logging level (or lower)", GARRULOUS) + +>>> log.log(4, "This should only be seen at the '%s' logging level (or lower)", TALKATIVE) + +>>> log.log(5, "This should only be seen at the '%s' logging level (or lower)", VERBOSE) + +>>> log.log(6, "This should only be seen at the '%s' logging level (or lower)", SOCIABLE) + +>>> log.log(7, "This should only be seen at the '%s' logging level (or lower)", EFFUSIVE) +EFFUSIVE:root:This should only be seen at the '7' logging level (or lower) + +>>> log.log(8, "This should only be seen at the '%s' logging level (or lower)", TERSE) +TERSE:root:This should only be seen at the '8' logging level (or lower) + +>>> log.log(9, "This should only be seen at the '%s' logging level (or lower)", TACITURN) +TACITURN:root:This should only be seen at the '9' logging level (or lower) + +>>> log.log(10, "This should only be seen at the '%s' logging level (or lower)", SILENT) +SILENT:root:This should only be seen at the '10' logging level (or lower) + +>>> log.setLevel(8) + +>>> log.log(1, "This should only be seen at the '%s' logging level (or lower)", BORING) + +>>> log.log(2, "This should only be seen at the '%s' logging level (or lower)", CHATTERBOX) + +>>> log.log(3, "This should only be seen at the '%s' logging level (or lower)", GARRULOUS) + +>>> log.log(4, "This should only be seen at the '%s' logging level (or lower)", TALKATIVE) + +>>> log.log(5, "This should only be seen at the '%s' logging level (or lower)", VERBOSE) + +>>> log.log(6, "This should only be seen at the '%s' logging level (or lower)", SOCIABLE) + +>>> log.log(7, "This should only be seen at the '%s' logging level (or lower)", EFFUSIVE) + +>>> log.log(8, "This should only be seen at the '%s' logging level (or lower)", TERSE) +TERSE:root:This should only be seen at the '8' logging level (or lower) + +>>> log.log(9, "This should only be seen at the '%s' logging level (or lower)", TACITURN) +TACITURN:root:This should only be seen at the '9' logging level (or lower) + +>>> log.log(10, "This should only be seen at the '%s' logging level (or lower)", SILENT) +SILENT:root:This should only be seen at the '10' logging level (or lower) + +>>> log.setLevel(9) + +>>> log.log(1, "This should only be seen at the '%s' logging level (or lower)", BORING) + +>>> log.log(2, "This should only be seen at the '%s' logging level (or lower)", CHATTERBOX) + +>>> log.log(3, "This should only be seen at the '%s' logging level (or lower)", GARRULOUS) + +>>> log.log(4, "This should only be seen at the '%s' logging level (or lower)", TALKATIVE) + +>>> log.log(5, "This should only be seen at the '%s' logging level (or lower)", VERBOSE) + +>>> log.log(6, "This should only be seen at the '%s' logging level (or lower)", SOCIABLE) + +>>> log.log(7, "This should only be seen at the '%s' logging level (or lower)", EFFUSIVE) + +>>> log.log(8, "This should only be seen at the '%s' logging level (or lower)", TERSE) + +>>> log.log(9, "This should only be seen at the '%s' logging level (or lower)", TACITURN) +TACITURN:root:This should only be seen at the '9' logging level (or lower) + +>>> log.log(10, "This should only be seen at the '%s' logging level (or lower)", SILENT) +SILENT:root:This should only be seen at the '10' logging level (or lower) + +>>> log.setLevel(10) + +>>> log.log(1, "This should only be seen at the '%s' logging level (or lower)", BORING) + +>>> log.log(2, "This should only be seen at the '%s' logging level (or lower)", CHATTERBOX) + +>>> log.log(3, "This should only be seen at the '%s' logging level (or lower)", GARRULOUS) + +>>> log.log(4, "This should only be seen at the '%s' logging level (or lower)", TALKATIVE) + +>>> log.log(5, "This should only be seen at the '%s' logging level (or lower)", VERBOSE) + +>>> log.log(6, "This should only be seen at the '%s' logging level (or lower)", SOCIABLE) + +>>> log.log(7, "This should only be seen at the '%s' logging level (or lower)", EFFUSIVE) + +>>> log.log(8, "This should only be seen at the '%s' logging level (or lower)", TERSE) + +>>> log.log(9, "This should only be seen at the '%s' logging level (or lower)", TACITURN) + +>>> log.log(10, "This should only be seen at the '%s' logging level (or lower)", SILENT) +SILENT:root:This should only be seen at the '10' logging level (or lower) + +>>> spec = VerySpecificFilter() + +>>> log.addFilter(spec) + +>>> log.setLevel(1) + +>>> log.log(1, "This should only be seen at the '%s' logging level (or lower)", BORING) +BORING:root:This should only be seen at the '1' logging level (or lower) + +>>> log.log(2, "This should only be seen at the '%s' logging level (or lower)", CHATTERBOX) +CHATTERBOX:root:This should only be seen at the '2' logging level (or lower) + +>>> log.log(3, "This should only be seen at the '%s' logging level (or lower)", GARRULOUS) + +>>> log.log(4, "This should only be seen at the '%s' logging level (or lower)", TALKATIVE) +TALKATIVE:root:This should only be seen at the '4' logging level (or lower) + +>>> log.log(5, "This should only be seen at the '%s' logging level (or lower)", VERBOSE) +VERBOSE:root:This should only be seen at the '5' logging level (or lower) + +>>> log.log(6, "This should only be seen at the '%s' logging level (or lower)", SOCIABLE) + +>>> log.log(7, "This should only be seen at the '%s' logging level (or lower)", EFFUSIVE) +EFFUSIVE:root:This should only be seen at the '7' logging level (or lower) + +>>> log.log(8, "This should only be seen at the '%s' logging level (or lower)", TERSE) +TERSE:root:This should only be seen at the '8' logging level (or lower) + +>>> log.log(9, "This should only be seen at the '%s' logging level (or lower)", TACITURN) + +>>> log.log(10, "This should only be seen at the '%s' logging level (or lower)", SILENT) +SILENT:root:This should only be seen at the '10' logging level (or lower) + +>>> log.setLevel(2) + +>>> log.log(1, "This should only be seen at the '%s' logging level (or lower)", BORING) + +>>> log.log(2, "This should only be seen at the '%s' logging level (or lower)", CHATTERBOX) +CHATTERBOX:root:This should only be seen at the '2' logging level (or lower) + +>>> log.log(3, "This should only be seen at the '%s' logging level (or lower)", GARRULOUS) + +>>> log.log(4, "This should only be seen at the '%s' logging level (or lower)", TALKATIVE) +TALKATIVE:root:This should only be seen at the '4' logging level (or lower) + +>>> log.log(5, "This should only be seen at the '%s' logging level (or lower)", VERBOSE) +VERBOSE:root:This should only be seen at the '5' logging level (or lower) + +>>> log.log(6, "This should only be seen at the '%s' logging level (or lower)", SOCIABLE) + +>>> log.log(7, "This should only be seen at the '%s' logging level (or lower)", EFFUSIVE) +EFFUSIVE:root:This should only be seen at the '7' logging level (or lower) + +>>> log.log(8, "This should only be seen at the '%s' logging level (or lower)", TERSE) +TERSE:root:This should only be seen at the '8' logging level (or lower) + +>>> log.log(9, "This should only be seen at the '%s' logging level (or lower)", TACITURN) + +>>> log.log(10, "This should only be seen at the '%s' logging level (or lower)", SILENT) +SILENT:root:This should only be seen at the '10' logging level (or lower) + +>>> log.setLevel(3) + +>>> log.log(1, "This should only be seen at the '%s' logging level (or lower)", BORING) + +>>> log.log(2, "This should only be seen at the '%s' logging level (or lower)", CHATTERBOX) + +>>> log.log(3, "This should only be seen at the '%s' logging level (or lower)", GARRULOUS) + +>>> log.log(4, "This should only be seen at the '%s' logging level (or lower)", TALKATIVE) +TALKATIVE:root:This should only be seen at the '4' logging level (or lower) + +>>> log.log(5, "This should only be seen at the '%s' logging level (or lower)", VERBOSE) +VERBOSE:root:This should only be seen at the '5' logging level (or lower) + +>>> log.log(6, "This should only be seen at the '%s' logging level (or lower)", SOCIABLE) + +>>> log.log(7, "This should only be seen at the '%s' logging level (or lower)", EFFUSIVE) +EFFUSIVE:root:This should only be seen at the '7' logging level (or lower) + +>>> log.log(8, "This should only be seen at the '%s' logging level (or lower)", TERSE) +TERSE:root:This should only be seen at the '8' logging level (or lower) + +>>> log.log(9, "This should only be seen at the '%s' logging level (or lower)", TACITURN) + +>>> log.log(10, "This should only be seen at the '%s' logging level (or lower)", SILENT) +SILENT:root:This should only be seen at the '10' logging level (or lower) + +>>> log.setLevel(4) + +>>> log.log(1, "This should only be seen at the '%s' logging level (or lower)", BORING) + +>>> log.log(2, "This should only be seen at the '%s' logging level (or lower)", CHATTERBOX) + +>>> log.log(3, "This should only be seen at the '%s' logging level (or lower)", GARRULOUS) + +>>> log.log(4, "This should only be seen at the '%s' logging level (or lower)", TALKATIVE) +TALKATIVE:root:This should only be seen at the '4' logging level (or lower) + +>>> log.log(5, "This should only be seen at the '%s' logging level (or lower)", VERBOSE) +VERBOSE:root:This should only be seen at the '5' logging level (or lower) + +>>> log.log(6, "This should only be seen at the '%s' logging level (or lower)", SOCIABLE) + +>>> log.log(7, "This should only be seen at the '%s' logging level (or lower)", EFFUSIVE) +EFFUSIVE:root:This should only be seen at the '7' logging level (or lower) + +>>> log.log(8, "This should only be seen at the '%s' logging level (or lower)", TERSE) +TERSE:root:This should only be seen at the '8' logging level (or lower) + +>>> log.log(9, "This should only be seen at the '%s' logging level (or lower)", TACITURN) + +>>> log.log(10, "This should only be seen at the '%s' logging level (or lower)", SILENT) +SILENT:root:This should only be seen at the '10' logging level (or lower) + +>>> log.setLevel(5) + +>>> log.log(1, "This should only be seen at the '%s' logging level (or lower)", BORING) + +>>> log.log(2, "This should only be seen at the '%s' logging level (or lower)", CHATTERBOX) + +>>> log.log(3, "This should only be seen at the '%s' logging level (or lower)", GARRULOUS) + +>>> log.log(4, "This should only be seen at the '%s' logging level (or lower)", TALKATIVE) + +>>> log.log(5, "This should only be seen at the '%s' logging level (or lower)", VERBOSE) +VERBOSE:root:This should only be seen at the '5' logging level (or lower) + +>>> log.log(6, "This should only be seen at the '%s' logging level (or lower)", SOCIABLE) + +>>> log.log(7, "This should only be seen at the '%s' logging level (or lower)", EFFUSIVE) +EFFUSIVE:root:This should only be seen at the '7' logging level (or lower) + +>>> log.log(8, "This should only be seen at the '%s' logging level (or lower)", TERSE) +TERSE:root:This should only be seen at the '8' logging level (or lower) + +>>> log.log(9, "This should only be seen at the '%s' logging level (or lower)", TACITURN) + +>>> log.log(10, "This should only be seen at the '%s' logging level (or lower)", SILENT) +SILENT:root:This should only be seen at the '10' logging level (or lower) + +>>> log.setLevel(6) + +>>> log.log(1, "This should only be seen at the '%s' logging level (or lower)", BORING) + +>>> log.log(2, "This should only be seen at the '%s' logging level (or lower)", CHATTERBOX) + +>>> log.log(3, "This should only be seen at the '%s' logging level (or lower)", GARRULOUS) + +>>> log.log(4, "This should only be seen at the '%s' logging level (or lower)", TALKATIVE) + +>>> log.log(5, "This should only be seen at the '%s' logging level (or lower)", VERBOSE) + +>>> log.log(6, "This should only be seen at the '%s' logging level (or lower)", SOCIABLE) + +>>> log.log(7, "This should only be seen at the '%s' logging level (or lower)", EFFUSIVE) +EFFUSIVE:root:This should only be seen at the '7' logging level (or lower) + +>>> log.log(8, "This should only be seen at the '%s' logging level (or lower)", TERSE) +TERSE:root:This should only be seen at the '8' logging level (or lower) + +>>> log.log(9, "This should only be seen at the '%s' logging level (or lower)", TACITURN) + +>>> log.log(10, "This should only be seen at the '%s' logging level (or lower)", SILENT) +SILENT:root:This should only be seen at the '10' logging level (or lower) + +>>> log.setLevel(7) + +>>> log.log(1, "This should only be seen at the '%s' logging level (or lower)", BORING) + +>>> log.log(2, "This should only be seen at the '%s' logging level (or lower)", CHATTERBOX) + +>>> log.log(3, "This should only be seen at the '%s' logging level (or lower)", GARRULOUS) + +>>> log.log(4, "This should only be seen at the '%s' logging level (or lower)", TALKATIVE) + +>>> log.log(5, "This should only be seen at the '%s' logging level (or lower)", VERBOSE) + +>>> log.log(6, "This should only be seen at the '%s' logging level (or lower)", SOCIABLE) + +>>> log.log(7, "This should only be seen at the '%s' logging level (or lower)", EFFUSIVE) +EFFUSIVE:root:This should only be seen at the '7' logging level (or lower) + +>>> log.log(8, "This should only be seen at the '%s' logging level (or lower)", TERSE) +TERSE:root:This should only be seen at the '8' logging level (or lower) + +>>> log.log(9, "This should only be seen at the '%s' logging level (or lower)", TACITURN) + +>>> log.log(10, "This should only be seen at the '%s' logging level (or lower)", SILENT) +SILENT:root:This should only be seen at the '10' logging level (or lower) + +>>> log.setLevel(8) + +>>> log.log(1, "This should only be seen at the '%s' logging level (or lower)", BORING) + +>>> log.log(2, "This should only be seen at the '%s' logging level (or lower)", CHATTERBOX) + +>>> log.log(3, "This should only be seen at the '%s' logging level (or lower)", GARRULOUS) + +>>> log.log(4, "This should only be seen at the '%s' logging level (or lower)", TALKATIVE) + +>>> log.log(5, "This should only be seen at the '%s' logging level (or lower)", VERBOSE) + +>>> log.log(6, "This should only be seen at the '%s' logging level (or lower)", SOCIABLE) + +>>> log.log(7, "This should only be seen at the '%s' logging level (or lower)", EFFUSIVE) + +>>> log.log(8, "This should only be seen at the '%s' logging level (or lower)", TERSE) +TERSE:root:This should only be seen at the '8' logging level (or lower) + +>>> log.log(9, "This should only be seen at the '%s' logging level (or lower)", TACITURN) + +>>> log.log(10, "This should only be seen at the '%s' logging level (or lower)", SILENT) +SILENT:root:This should only be seen at the '10' logging level (or lower) + +>>> log.setLevel(9) + +>>> log.log(1, "This should only be seen at the '%s' logging level (or lower)", BORING) + +>>> log.log(2, "This should only be seen at the '%s' logging level (or lower)", CHATTERBOX) + +>>> log.log(3, "This should only be seen at the '%s' logging level (or lower)", GARRULOUS) + +>>> log.log(4, "This should only be seen at the '%s' logging level (or lower)", TALKATIVE) + +>>> log.log(5, "This should only be seen at the '%s' logging level (or lower)", VERBOSE) + +>>> log.log(6, "This should only be seen at the '%s' logging level (or lower)", SOCIABLE) + +>>> log.log(7, "This should only be seen at the '%s' logging level (or lower)", EFFUSIVE) + +>>> log.log(8, "This should only be seen at the '%s' logging level (or lower)", TERSE) + +>>> log.log(9, "This should only be seen at the '%s' logging level (or lower)", TACITURN) + +>>> log.log(10, "This should only be seen at the '%s' logging level (or lower)", SILENT) +SILENT:root:This should only be seen at the '10' logging level (or lower) + +>>> log.setLevel(10) + +>>> log.log(1, "This should only be seen at the '%s' logging level (or lower)", BORING) + +>>> log.log(2, "This should only be seen at the '%s' logging level (or lower)", CHATTERBOX) + +>>> log.log(3, "This should only be seen at the '%s' logging level (or lower)", GARRULOUS) + +>>> log.log(4, "This should only be seen at the '%s' logging level (or lower)", TALKATIVE) + +>>> log.log(5, "This should only be seen at the '%s' logging level (or lower)", VERBOSE) + +>>> log.log(6, "This should only be seen at the '%s' logging level (or lower)", SOCIABLE) + +>>> log.log(7, "This should only be seen at the '%s' logging level (or lower)", EFFUSIVE) + +>>> log.log(8, "This should only be seen at the '%s' logging level (or lower)", TERSE) + +>>> log.log(9, "This should only be seen at the '%s' logging level (or lower)", TACITURN) + +>>> log.log(10, "This should only be seen at the '%s' logging level (or lower)", SILENT) +SILENT:root:This should only be seen at the '10' logging level (or lower) + +>>> log.setLevel(0) + +>>> log.removeFilter(spec) + +>>> hdlr.removeFilter(garr) + +>>> logging.addLevelName(logging.DEBUG, "DEBUG") + + +Test 2 +====== +Test memory handlers. These are basically buffers for log messages: they take so many messages, and then print them all. + +>>> import logging.handlers + +>>> sys.stderr = sys.stdout +>>> logger = logging.getLogger("") +>>> sh = logger.handlers[0] +>>> sh.close() +>>> logger.removeHandler(sh) +>>> mh = logging.handlers.MemoryHandler(10,logging.WARNING, sh) +>>> logger.setLevel(logging.DEBUG) +>>> logger.addHandler(mh) + +>>> logger.debug("Debug message") + +-- logging at INFO, nothing should be seen yet -- + +>>> logger.info("Info message") + +-- logging at WARNING, 3 messages should be seen -- + +>>> logger.warn("Warn message") +DEBUG:root:Debug message +INFO:root:Info message +WARNING:root:Warn message + +>>> logger.info("Info index = 0") + +>>> logger.info("Info index = 1") + +>>> logger.info("Info index = 2") + +>>> logger.info("Info index = 3") + +>>> logger.info("Info index = 4") + +>>> logger.info("Info index = 5") + +>>> logger.info("Info index = 6") + +>>> logger.info("Info index = 7") + +>>> logger.info("Info index = 8") + +>>> logger.info("Info index = 9") +INFO:root:Info index = 0 +INFO:root:Info index = 1 +INFO:root:Info index = 2 +INFO:root:Info index = 3 +INFO:root:Info index = 4 +INFO:root:Info index = 5 +INFO:root:Info index = 6 +INFO:root:Info index = 7 +INFO:root:Info index = 8 +INFO:root:Info index = 9 + +>>> logger.info("Info index = 10") + +>>> logger.info("Info index = 11") + +>>> logger.info("Info index = 12") + +>>> logger.info("Info index = 13") + +>>> logger.info("Info index = 14") + +>>> logger.info("Info index = 15") + +>>> logger.info("Info index = 16") + +>>> logger.info("Info index = 17") + +>>> logger.info("Info index = 18") + +>>> logger.info("Info index = 19") +INFO:root:Info index = 10 +INFO:root:Info index = 11 +INFO:root:Info index = 12 +INFO:root:Info index = 13 +INFO:root:Info index = 14 +INFO:root:Info index = 15 +INFO:root:Info index = 16 +INFO:root:Info index = 17 +INFO:root:Info index = 18 +INFO:root:Info index = 19 + +>>> logger.info("Info index = 20") + +>>> logger.info("Info index = 21") + +>>> logger.info("Info index = 22") + +>>> logger.info("Info index = 23") + +>>> logger.info("Info index = 24") + +>>> logger.info("Info index = 25") + +>>> logger.info("Info index = 26") + +>>> logger.info("Info index = 27") + +>>> logger.info("Info index = 28") + +>>> logger.info("Info index = 29") +INFO:root:Info index = 20 +INFO:root:Info index = 21 +INFO:root:Info index = 22 +INFO:root:Info index = 23 +INFO:root:Info index = 24 +INFO:root:Info index = 25 +INFO:root:Info index = 26 +INFO:root:Info index = 27 +INFO:root:Info index = 28 +INFO:root:Info index = 29 + +>>> logger.info("Info index = 30") + +>>> logger.info("Info index = 31") + +>>> logger.info("Info index = 32") + +>>> logger.info("Info index = 33") + +>>> logger.info("Info index = 34") + +>>> logger.info("Info index = 35") + +>>> logger.info("Info index = 36") + +>>> logger.info("Info index = 37") + +>>> logger.info("Info index = 38") + +>>> logger.info("Info index = 39") +INFO:root:Info index = 30 +INFO:root:Info index = 31 +INFO:root:Info index = 32 +INFO:root:Info index = 33 +INFO:root:Info index = 34 +INFO:root:Info index = 35 +INFO:root:Info index = 36 +INFO:root:Info index = 37 +INFO:root:Info index = 38 +INFO:root:Info index = 39 + +>>> logger.info("Info index = 40") + +>>> logger.info("Info index = 41") + +>>> logger.info("Info index = 42") + +>>> logger.info("Info index = 43") + +>>> logger.info("Info index = 44") + +>>> logger.info("Info index = 45") + +>>> logger.info("Info index = 46") + +>>> logger.info("Info index = 47") + +>>> logger.info("Info index = 48") + +>>> logger.info("Info index = 49") +INFO:root:Info index = 40 +INFO:root:Info index = 41 +INFO:root:Info index = 42 +INFO:root:Info index = 43 +INFO:root:Info index = 44 +INFO:root:Info index = 45 +INFO:root:Info index = 46 +INFO:root:Info index = 47 +INFO:root:Info index = 48 +INFO:root:Info index = 49 + +>>> logger.info("Info index = 50") + +>>> logger.info("Info index = 51") + +>>> logger.info("Info index = 52") + +>>> logger.info("Info index = 53") + +>>> logger.info("Info index = 54") + +>>> logger.info("Info index = 55") + +>>> logger.info("Info index = 56") + +>>> logger.info("Info index = 57") + +>>> logger.info("Info index = 58") + +>>> logger.info("Info index = 59") +INFO:root:Info index = 50 +INFO:root:Info index = 51 +INFO:root:Info index = 52 +INFO:root:Info index = 53 +INFO:root:Info index = 54 +INFO:root:Info index = 55 +INFO:root:Info index = 56 +INFO:root:Info index = 57 +INFO:root:Info index = 58 +INFO:root:Info index = 59 + +>>> logger.info("Info index = 60") + +>>> logger.info("Info index = 61") + +>>> logger.info("Info index = 62") + +>>> logger.info("Info index = 63") + +>>> logger.info("Info index = 64") + +>>> logger.info("Info index = 65") + +>>> logger.info("Info index = 66") + +>>> logger.info("Info index = 67") + +>>> logger.info("Info index = 68") + +>>> logger.info("Info index = 69") +INFO:root:Info index = 60 +INFO:root:Info index = 61 +INFO:root:Info index = 62 +INFO:root:Info index = 63 +INFO:root:Info index = 64 +INFO:root:Info index = 65 +INFO:root:Info index = 66 +INFO:root:Info index = 67 +INFO:root:Info index = 68 +INFO:root:Info index = 69 + +>>> logger.info("Info index = 70") + +>>> logger.info("Info index = 71") + +>>> logger.info("Info index = 72") + +>>> logger.info("Info index = 73") + +>>> logger.info("Info index = 74") + +>>> logger.info("Info index = 75") + +>>> logger.info("Info index = 76") + +>>> logger.info("Info index = 77") + +>>> logger.info("Info index = 78") + +>>> logger.info("Info index = 79") +INFO:root:Info index = 70 +INFO:root:Info index = 71 +INFO:root:Info index = 72 +INFO:root:Info index = 73 +INFO:root:Info index = 74 +INFO:root:Info index = 75 +INFO:root:Info index = 76 +INFO:root:Info index = 77 +INFO:root:Info index = 78 +INFO:root:Info index = 79 + +>>> logger.info("Info index = 80") + +>>> logger.info("Info index = 81") + +>>> logger.info("Info index = 82") + +>>> logger.info("Info index = 83") + +>>> logger.info("Info index = 84") + +>>> logger.info("Info index = 85") + +>>> logger.info("Info index = 86") + +>>> logger.info("Info index = 87") + +>>> logger.info("Info index = 88") + +>>> logger.info("Info index = 89") +INFO:root:Info index = 80 +INFO:root:Info index = 81 +INFO:root:Info index = 82 +INFO:root:Info index = 83 +INFO:root:Info index = 84 +INFO:root:Info index = 85 +INFO:root:Info index = 86 +INFO:root:Info index = 87 +INFO:root:Info index = 88 +INFO:root:Info index = 89 + +>>> logger.info("Info index = 90") + +>>> logger.info("Info index = 91") + +>>> logger.info("Info index = 92") + +>>> logger.info("Info index = 93") + +>>> logger.info("Info index = 94") + +>>> logger.info("Info index = 95") + +>>> logger.info("Info index = 96") + +>>> logger.info("Info index = 97") + +>>> logger.info("Info index = 98") + +>>> logger.info("Info index = 99") +INFO:root:Info index = 90 +INFO:root:Info index = 91 +INFO:root:Info index = 92 +INFO:root:Info index = 93 +INFO:root:Info index = 94 +INFO:root:Info index = 95 +INFO:root:Info index = 96 +INFO:root:Info index = 97 +INFO:root:Info index = 98 +INFO:root:Info index = 99 + +>>> logger.info("Info index = 100") + +>>> logger.info("Info index = 101") + +>>> mh.close() +INFO:root:Info index = 100 +INFO:root:Info index = 101 + +>>> logger.removeHandler(mh) +>>> logger.addHandler(sh) + + + +Test 3 +====== + +>>> import sys, logging +>>> sys.stderr = sys +>>> logging.basicConfig() +>>> FILTER = "a.b" +>>> root = logging.getLogger() +>>> root.setLevel(logging.DEBUG) +>>> hand = root.handlers[0] + +>>> logging.getLogger("a").info("Info 1") +INFO:a:Info 1 + +>>> logging.getLogger("a.b").info("Info 2") +INFO:a.b:Info 2 + +>>> logging.getLogger("a.c").info("Info 3") +INFO:a.c:Info 3 + +>>> logging.getLogger("a.b.c").info("Info 4") +INFO:a.b.c:Info 4 + +>>> logging.getLogger("a.b.c.d").info("Info 5") +INFO:a.b.c.d:Info 5 + +>>> logging.getLogger("a.bb.c").info("Info 6") +INFO:a.bb.c:Info 6 + +>>> logging.getLogger("b").info("Info 7") +INFO:b:Info 7 + +>>> logging.getLogger("b.a").info("Info 8") +INFO:b.a:Info 8 + +>>> logging.getLogger("c.a.b").info("Info 9") +INFO:c.a.b:Info 9 + +>>> logging.getLogger("a.bb").info("Info 10") +INFO:a.bb:Info 10 + +Filtered with 'a.b'... + +>>> filt = logging.Filter(FILTER) + +>>> hand.addFilter(filt) + +>>> logging.getLogger("a").info("Info 1") + +>>> logging.getLogger("a.b").info("Info 2") +INFO:a.b:Info 2 + +>>> logging.getLogger("a.c").info("Info 3") + +>>> logging.getLogger("a.b.c").info("Info 4") +INFO:a.b.c:Info 4 + +>>> logging.getLogger("a.b.c.d").info("Info 5") +INFO:a.b.c.d:Info 5 + +>>> logging.getLogger("a.bb.c").info("Info 6") + +>>> logging.getLogger("b").info("Info 7") + +>>> logging.getLogger("b.a").info("Info 8") + +>>> logging.getLogger("c.a.b").info("Info 9") + +>>> logging.getLogger("a.bb").info("Info 10") + +>>> hand.removeFilter(filt) + + +Test 4 +====== +>>> import sys, logging, logging.handlers, string +>>> import tempfile, logging.config, os, test.test_support +>>> sys.stderr = sys.stdout + +>>> from test.test_logging import config0, config1 + +config2 has a subtle configuration error that should be reported +>>> config2 = config1.replace("sys.stdout", "sys.stbout") + +config3 has a less subtle configuration error +>>> config3 = config1.replace("formatter=form1", "formatter=misspelled_name") + +>>> def test4(conf): +... loggerDict = logging.getLogger().manager.loggerDict +... logging._acquireLock() +... try: +... saved_handlers = logging._handlers.copy() +... saved_handler_list = logging._handlerList[:] +... saved_loggers = loggerDict.copy() +... finally: +... logging._releaseLock() +... try: +... fn = test.test_support.TESTFN +... f = open(fn, "w") +... f.write(conf) +... f.close() +... try: +... logging.config.fileConfig(fn) +... #call again to make sure cleanup is correct +... logging.config.fileConfig(fn) +... except: +... t = sys.exc_info()[0] +... message(str(t)) +... else: +... message('ok.') +... os.remove(fn) +... finally: +... logging._acquireLock() +... try: +... logging._handlers.clear() +... logging._handlers.update(saved_handlers) +... logging._handlerList[:] = saved_handler_list +... loggerDict = logging.getLogger().manager.loggerDict +... loggerDict.clear() +... loggerDict.update(saved_loggers) +... finally: +... logging._releaseLock() + +>>> test4(config0) +ok. + +>>> test4(config1) +ok. + +>>> test4(config2) + + +>>> test4(config3) + + +>>> from test import test_logging +>>> test_logging.test5() +ERROR:root:just testing +... Don't panic! + + +Test Main +========= +>>> import select +>>> import os, sys, string, struct, types, pickle, io +>>> import socket, tempfile, threading, time +>>> import logging, logging.handlers, logging.config +>>> from test import test_logging + +XXX: The test is unstable! +#>>> test_logging.test_main_inner() +ERR -> CRITICAL: Message 0 (via logrecv.tcp.ERR) +ERR -> ERROR: Message 1 (via logrecv.tcp.ERR) +INF -> CRITICAL: Message 2 (via logrecv.tcp.INF) +INF -> ERROR: Message 3 (via logrecv.tcp.INF) +INF -> WARNING: Message 4 (via logrecv.tcp.INF) +INF -> INFO: Message 5 (via logrecv.tcp.INF) +INF.UNDEF -> CRITICAL: Message 6 (via logrecv.tcp.INF.UNDEF) +INF.UNDEF -> ERROR: Message 7 (via logrecv.tcp.INF.UNDEF) +INF.UNDEF -> WARNING: Message 8 (via logrecv.tcp.INF.UNDEF) +INF.UNDEF -> INFO: Message 9 (via logrecv.tcp.INF.UNDEF) +INF.ERR -> CRITICAL: Message 10 (via logrecv.tcp.INF.ERR) +INF.ERR -> ERROR: Message 11 (via logrecv.tcp.INF.ERR) +INF.ERR.UNDEF -> CRITICAL: Message 12 (via logrecv.tcp.INF.ERR.UNDEF) +INF.ERR.UNDEF -> ERROR: Message 13 (via logrecv.tcp.INF.ERR.UNDEF) +DEB -> CRITICAL: Message 14 (via logrecv.tcp.DEB) +DEB -> ERROR: Message 15 (via logrecv.tcp.DEB) +DEB -> WARNING: Message 16 (via logrecv.tcp.DEB) +DEB -> INFO: Message 17 (via logrecv.tcp.DEB) +DEB -> DEBUG: Message 18 (via logrecv.tcp.DEB) +UNDEF -> CRITICAL: Message 19 (via logrecv.tcp.UNDEF) +UNDEF -> ERROR: Message 20 (via logrecv.tcp.UNDEF) +UNDEF -> WARNING: Message 21 (via logrecv.tcp.UNDEF) +UNDEF -> INFO: Message 22 (via logrecv.tcp.UNDEF) +INF.BADPARENT.UNDEF -> CRITICAL: Message 23 (via logrecv.tcp.INF.BADPARENT.UNDEF) +INF.BADPARENT -> CRITICAL: Message 24 (via logrecv.tcp.INF.BADPARENT) +INF -> INFO: Finish up, it's closing time. Messages should bear numbers 0 through 24. (via logrecv.tcp.INF) + +""" import select import os, sys, struct, pickle, io import socket, tempfile, threading, time -import logging, logging.handlers, logging.config -from test.test_support import run_with_locale +import logging, logging.handlers, logging.config, test.test_support + BANNER = "-- %-10s %-6s ---------------------------------------------------\n" FINISH_UP = "Finish up, it's closing time. Messages should bear numbers 0 through 24." +#---------------------------------------------------------------------------- +# Test 0 +#---------------------------------------------------------------------------- + +msgcount = 0 + +def nextmessage(): + global msgcount + rv = "Message %d" % msgcount + msgcount = msgcount + 1 + return rv #---------------------------------------------------------------------------- # Log receiver @@ -78,11 +1923,80 @@ class LogRecordStreamHandler(StreamRequestHandler): if record.msg == FINISH_UP: self.server.abort = 1 record.msg = record.msg + " (via " + logname + ")" - logger = logging.getLogger(logname) + logger = logging.getLogger("logrecv") logger.handle(record) -# The server sets socketDataProcessed when it's done. -socketDataProcessed = threading.Event() +# The server sets socketDataProcessed when it's done. +socketDataProcessed = threading.Event() +#---------------------------------------------------------------------------- +# Test 5 +#---------------------------------------------------------------------------- + +test5_config = """ +[loggers] +keys=root + +[handlers] +keys=hand1 + +[formatters] +keys=form1 + +[logger_root] +level=NOTSET +handlers=hand1 + +[handler_hand1] +class=StreamHandler +level=NOTSET +formatter=form1 +args=(sys.stdout,) + +[formatter_form1] +class=test.test_logging.FriendlyFormatter +format=%(levelname)s:%(name)s:%(message)s +datefmt= +""" + +class FriendlyFormatter (logging.Formatter): + def formatException(self, ei): + return "%s... Don't panic!" % str(ei[0]) + + +def test5(): + loggerDict = logging.getLogger().manager.loggerDict + logging._acquireLock() + try: + saved_handlers = logging._handlers.copy() + saved_handler_list = logging._handlerList[:] + saved_loggers = loggerDict.copy() + finally: + logging._releaseLock() + try: + fn = test.test_support.TESTFN + f = open(fn, "w") + f.write(test5_config) + f.close() + logging.config.fileConfig(fn) + try: + raise KeyError + except KeyError: + logging.exception("just testing") + os.remove(fn) + hdlr = logging.getLogger().handlers[0] + logging.getLogger().handlers.remove(hdlr) + finally: + logging._acquireLock() + try: + logging._handlers.clear() + logging._handlers.update(saved_handlers) + logging._handlerList[:] = saved_handler_list + loggerDict = logging.getLogger().manager.loggerDict + loggerDict.clear() + loggerDict.update(saved_loggers) + finally: + logging._releaseLock() + class LogRecordSocketReceiver(ThreadingTCPServer): """ @@ -105,8 +2019,6 @@ class LogRecordSocketReceiver(ThreadingTCPServer): self.timeout) if rd: self.handle_request() - #notify the main thread that we're about to exit - socketDataProcessed.set() # close the listen socket self.server_close() @@ -119,17 +2031,10 @@ class LogRecordSocketReceiver(ThreadingTCPServer): def runTCP(tcpserver): tcpserver.serve_until_stopped() -#---------------------------------------------------------------------------- -# Test 0 -#---------------------------------------------------------------------------- - -msgcount = 0 - -def nextmessage(): - global msgcount - rv = "Message %d" % msgcount - msgcount = msgcount + 1 - return rv +def banner(nm, typ): + sep = BANNER % (nm, typ) + sys.stdout.write(sep) + sys.stdout.flush() def test0(): ERR = logging.getLogger("ERR") @@ -199,202 +2104,70 @@ def test0(): INF.info(FINISH_UP) -#---------------------------------------------------------------------------- -# Test 1 -#---------------------------------------------------------------------------- +def test_main_inner(): + rootLogger = logging.getLogger("") + rootLogger.setLevel(logging.DEBUG) -# -# First, we define our levels. There can be as many as you want - the only -# limitations are that they should be integers, the lowest should be > 0 and -# larger values mean less information being logged. If you need specific -# level values which do not fit into these limitations, you can use a -# mapping dictionary to convert between your application levels and the -# logging system. -# -SILENT = 10 -TACITURN = 9 -TERSE = 8 -EFFUSIVE = 7 -SOCIABLE = 6 -VERBOSE = 5 -TALKATIVE = 4 -GARRULOUS = 3 -CHATTERBOX = 2 -BORING = 1 - -LEVEL_RANGE = range(BORING, SILENT + 1) - -# -# Next, we define names for our levels. You don't need to do this - in which -# case the system will use "Level n" to denote the text for the level. -# -my_logging_levels = { - SILENT : 'Silent', - TACITURN : 'Taciturn', - TERSE : 'Terse', - EFFUSIVE : 'Effusive', - SOCIABLE : 'Sociable', - VERBOSE : 'Verbose', - TALKATIVE : 'Talkative', - GARRULOUS : 'Garrulous', - CHATTERBOX : 'Chatterbox', - BORING : 'Boring', -} - -# -# Now, to demonstrate filtering: suppose for some perverse reason we only -# want to print out all except GARRULOUS messages. Let's create a filter for -# this purpose... -# -class SpecificLevelFilter(logging.Filter): - def __init__(self, lvl): - self.level = lvl - - def filter(self, record): - return self.level != record.levelno - -class GarrulousFilter(SpecificLevelFilter): - def __init__(self): - SpecificLevelFilter.__init__(self, GARRULOUS) - -# -# Now, let's demonstrate filtering at the logger. This time, use a filter -# which excludes SOCIABLE and TACITURN messages. Note that GARRULOUS events -# are still excluded. -# -class VerySpecificFilter(logging.Filter): - def filter(self, record): - return record.levelno not in [SOCIABLE, TACITURN] + # Find an unused port number + port = logging.handlers.DEFAULT_TCP_LOGGING_PORT + while port < logging.handlers.DEFAULT_TCP_LOGGING_PORT+100: + try: + tcpserver = LogRecordSocketReceiver(port=port) + except socket.error: + port += 1 + else: + break + else: + raise ImportError("Could not find unused port") -def message(s): - sys.stdout.write("%s\n" % s) -SHOULD1 = "This should only be seen at the '%s' logging level (or lower)" - -def test1(): -# -# Now, tell the logging system to associate names with our levels. -# - for lvl in my_logging_levels.keys(): - logging.addLevelName(lvl, my_logging_levels[lvl]) - -# -# Now, define a test function which logs an event at each of our levels. -# - - def doLog(log): - for lvl in LEVEL_RANGE: - log.log(lvl, SHOULD1, logging.getLevelName(lvl)) - - log = logging.getLogger("") - hdlr = log.handlers[0] -# -# Set the logging level to each different value and call the utility -# function to log events. -# In the output, you should see that each time round the loop, the number of -# logging events which are actually output decreases. -# - for lvl in LEVEL_RANGE: - message("-- setting logging level to '%s' -----" % - logging.getLevelName(lvl)) - log.setLevel(lvl) - doLog(log) - # - # Now, we demonstrate level filtering at the handler level. Tell the - # handler defined above to filter at level 'SOCIABLE', and repeat the - # above loop. Compare the output from the two runs. - # - hdlr.setLevel(SOCIABLE) - message("-- Filtering at handler level to SOCIABLE --") - for lvl in LEVEL_RANGE: - message("-- setting logging level to '%s' -----" % - logging.getLevelName(lvl)) - log.setLevel(lvl) - doLog(log) - - hdlr.setLevel(0) #turn off level filtering at the handler - - garr = GarrulousFilter() - hdlr.addFilter(garr) - message("-- Filtering using GARRULOUS filter --") - for lvl in LEVEL_RANGE: - message("-- setting logging level to '%s' -----" % - logging.getLevelName(lvl)) - log.setLevel(lvl) - doLog(log) - spec = VerySpecificFilter() - log.addFilter(spec) - message("-- Filtering using specific filter for SOCIABLE, TACITURN --") - for lvl in LEVEL_RANGE: - message("-- setting logging level to '%s' -----" % - logging.getLevelName(lvl)) - log.setLevel(lvl) - doLog(log) - - log.removeFilter(spec) - hdlr.removeFilter(garr) - #Undo the one level which clashes...for regression tests - logging.addLevelName(logging.DEBUG, "DEBUG") + #Set up a handler such that all events are sent via a socket to the log + #receiver (logrecv). + #The handler will only be added to the rootLogger for some of the tests + shdlr = logging.handlers.SocketHandler('localhost', port) + rootLogger.addHandler(shdlr) -#---------------------------------------------------------------------------- -# Test 2 -#---------------------------------------------------------------------------- + #Configure the logger for logrecv so events do not propagate beyond it. + #The sockLogger output is buffered in memory until the end of the test, + #and printed at the end. + sockOut = io.StringIO() + sockLogger = logging.getLogger("logrecv") + sockLogger.setLevel(logging.DEBUG) + sockhdlr = logging.StreamHandler(sockOut) + sockhdlr.setFormatter(logging.Formatter( + "%(name)s -> %(levelname)s: %(message)s")) + sockLogger.addHandler(sockhdlr) + sockLogger.propagate = 0 -MSG = "-- logging %d at INFO, messages should be seen every 10 events --" -def test2(): - logger = logging.getLogger("") - sh = logger.handlers[0] - sh.close() - logger.removeHandler(sh) - mh = logging.handlers.MemoryHandler(10,logging.WARNING, sh) - logger.setLevel(logging.DEBUG) - logger.addHandler(mh) - message("-- logging at DEBUG, nothing should be seen yet --") - logger.debug("Debug message") - message("-- logging at INFO, nothing should be seen yet --") - logger.info("Info message") - message("-- logging at WARNING, 3 messages should be seen --") - logger.warn("Warn message") - for i in range(102): - message(MSG % i) - logger.info("Info index = %d", i) - mh.close() - logger.removeHandler(mh) - logger.addHandler(sh) + #Set up servers + threads = [] + #sys.stdout.write("About to start TCP server...\n") + threads.append(threading.Thread(target=runTCP, args=(tcpserver,))) -#---------------------------------------------------------------------------- -# Test 3 -#---------------------------------------------------------------------------- + for thread in threads: + thread.start() + try: + test0() -FILTER = "a.b" - -def doLog3(): - logging.getLogger("a").info("Info 1") - logging.getLogger("a.b").info("Info 2") - logging.getLogger("a.c").info("Info 3") - logging.getLogger("a.b.c").info("Info 4") - logging.getLogger("a.b.c.d").info("Info 5") - logging.getLogger("a.bb.c").info("Info 6") - logging.getLogger("b").info("Info 7") - logging.getLogger("b.a").info("Info 8") - logging.getLogger("c.a.b").info("Info 9") - logging.getLogger("a.bb").info("Info 10") - -def test3(): - root = logging.getLogger() - root.setLevel(logging.DEBUG) - hand = root.handlers[0] - message("Unfiltered...") - doLog3() - message("Filtered with '%s'..." % FILTER) - filt = logging.Filter(FILTER) - hand.addFilter(filt) - doLog3() - hand.removeFilter(filt) + # XXX(nnorwitz): Try to fix timing related test failures. + # This sleep gives us some extra time to read messages. + # The test generally only fails on Solaris without this sleep. + #time.sleep(2.0) + shdlr.close() + rootLogger.removeHandler(shdlr) -#---------------------------------------------------------------------------- -# Test 4 -#---------------------------------------------------------------------------- + finally: + #wait for TCP receiver to terminate +# socketDataProcessed.wait() + # ensure the server dies + tcpserver.abort = 1 + for thread in threads: + thread.join(2.0) + print(sockOut.getvalue()) + sockOut.close() + sockLogger.removeHandler(sockhdlr) + sockhdlr.close() + sys.stdout.flush() # config0 is a standard configuration. config0 = """ @@ -454,231 +2227,18 @@ format=%(levelname)s:%(name)s:%(message)s datefmt= """ +def message(s): + sys.stdout.write("%s\n" % s) + # config2 has a subtle configuration error that should be reported config2 = config1.replace("sys.stdout", "sys.stbout") # config3 has a less subtle configuration error config3 = config1.replace("formatter=form1", "formatter=misspelled_name") -def test4(): - for i in range(4): - conf = globals()['config%d' % i] - sys.stdout.write('config%d: ' % i) - loggerDict = logging.getLogger().manager.loggerDict - logging._acquireLock() - try: - saved_handlers = logging._handlers.copy() - saved_handler_list = logging._handlerList[:] - saved_loggers = loggerDict.copy() - finally: - logging._releaseLock() - try: - fn = tempfile.mktemp(".ini") - f = open(fn, "w") - f.write(conf) - f.close() - try: - logging.config.fileConfig(fn) - #call again to make sure cleanup is correct - logging.config.fileConfig(fn) - except: - t = sys.exc_info()[0] - message(str(t)) - else: - message('ok.') - os.remove(fn) - finally: - logging._acquireLock() - try: - logging._handlers.clear() - logging._handlers.update(saved_handlers) - logging._handlerList[:] = saved_handler_list - loggerDict = logging.getLogger().manager.loggerDict - loggerDict.clear() - loggerDict.update(saved_loggers) - finally: - logging._releaseLock() - -#---------------------------------------------------------------------------- -# Test 5 -#---------------------------------------------------------------------------- - -test5_config = """ -[loggers] -keys=root - -[handlers] -keys=hand1 - -[formatters] -keys=form1 - -[logger_root] -level=NOTSET -handlers=hand1 - -[handler_hand1] -class=StreamHandler -level=NOTSET -formatter=form1 -args=(sys.stdout,) - -[formatter_form1] -class=test.test_logging.FriendlyFormatter -format=%(levelname)s:%(name)s:%(message)s -datefmt= -""" - -class FriendlyFormatter (logging.Formatter): - def formatException(self, ei): - return "%s... Don't panic!" % str(ei[0]) - - -def test5(): - loggerDict = logging.getLogger().manager.loggerDict - logging._acquireLock() - try: - saved_handlers = logging._handlers.copy() - saved_handler_list = logging._handlerList[:] - saved_loggers = loggerDict.copy() - finally: - logging._releaseLock() - try: - fn = tempfile.mktemp(".ini") - f = open(fn, "w") - f.write(test5_config) - f.close() - logging.config.fileConfig(fn) - try: - raise KeyError - except KeyError: - logging.exception("just testing") - os.remove(fn) - hdlr = logging.getLogger().handlers[0] - logging.getLogger().handlers.remove(hdlr) - finally: - logging._acquireLock() - try: - logging._handlers.clear() - logging._handlers.update(saved_handlers) - logging._handlerList[:] = saved_handler_list - loggerDict = logging.getLogger().manager.loggerDict - loggerDict.clear() - loggerDict.update(saved_loggers) - finally: - logging._releaseLock() - - -#---------------------------------------------------------------------------- -# Test Harness -#---------------------------------------------------------------------------- -def banner(nm, typ): - sep = BANNER % (nm, typ) - sys.stdout.write(sep) - sys.stdout.flush() - -def test_main_inner(): - rootLogger = logging.getLogger("") - rootLogger.setLevel(logging.DEBUG) - hdlr = logging.StreamHandler(sys.stdout) - fmt = logging.Formatter(logging.BASIC_FORMAT) - hdlr.setFormatter(fmt) - rootLogger.addHandler(hdlr) - - # Find an unused port number - port = logging.handlers.DEFAULT_TCP_LOGGING_PORT - while port < logging.handlers.DEFAULT_TCP_LOGGING_PORT+100: - try: - tcpserver = LogRecordSocketReceiver(port=port) - except socket.error: - port += 1 - else: - break - else: - raise ImportError("Could not find unused port") - - - #Set up a handler such that all events are sent via a socket to the log - #receiver (logrecv). - #The handler will only be added to the rootLogger for some of the tests - shdlr = logging.handlers.SocketHandler('localhost', port) - - #Configure the logger for logrecv so events do not propagate beyond it. - #The sockLogger output is buffered in memory until the end of the test, - #and printed at the end. - sockOut = io.StringIO() - sockLogger = logging.getLogger("logrecv") - sockLogger.setLevel(logging.DEBUG) - sockhdlr = logging.StreamHandler(sockOut) - sockhdlr.setFormatter(logging.Formatter( - "%(name)s -> %(levelname)s: %(message)s")) - sockLogger.addHandler(sockhdlr) - sockLogger.propagate = 0 - - #Set up servers - threads = [] - #sys.stdout.write("About to start TCP server...\n") - threads.append(threading.Thread(target=runTCP, args=(tcpserver,))) - - for thread in threads: - thread.start() - try: - banner("log_test0", "begin") - - rootLogger.addHandler(shdlr) - test0() - # XXX(nnorwitz): Try to fix timing related test failures. - # This sleep gives us some extra time to read messages. - # The test generally only fails on Solaris without this sleep. - time.sleep(2.0) - shdlr.close() - rootLogger.removeHandler(shdlr) - - banner("log_test0", "end") - - for t in range(1,6): - banner("log_test%d" % t, "begin") - globals()['test%d' % t]() - banner("log_test%d" % t, "end") - - finally: - #wait for TCP receiver to terminate - socketDataProcessed.wait() - # ensure the server dies - tcpserver.abort = 1 - for thread in threads: - thread.join(2.0) - banner("logrecv output", "begin") - sys.stdout.write(sockOut.getvalue()) - sockOut.close() - sockLogger.removeHandler(sockhdlr) - sockhdlr.close() - banner("logrecv output", "end") - sys.stdout.flush() - try: - hdlr.close() - except: - pass - rootLogger.removeHandler(hdlr) - -# Set the locale to the platform-dependent default. I have no idea -# why the test does this, but in any case we save the current locale -# first and restore it at the end. -@run_with_locale('LC_ALL', '') def test_main(): - # Save and restore the original root logger level across the tests. - # Otherwise, e.g., if any test using cookielib runs after test_logging, - # cookielib's debug-level logger tries to log messages, leading to - # confusing: - # No handlers could be found for logger "cookielib" - # output while the tests are running. - root_logger = logging.getLogger("") - original_logging_level = root_logger.getEffectiveLevel() - try: - test_main_inner() - finally: - root_logger.setLevel(original_logging_level) + from test import test_support, test_logging + test_support.run_doctest(test_logging) -if __name__ == "__main__": - sys.stdout.write("test_logging\n") +if __name__=="__main__": test_main() diff --git a/Lib/test/test_mmap.py b/Lib/test/test_mmap.py index c3f7dbb..08f60f8 100644 --- a/Lib/test/test_mmap.py +++ b/Lib/test/test_mmap.py @@ -426,6 +426,8 @@ class MmapTests(unittest.TestCase): anon_mmap(PAGESIZE) def test_prot_readonly(self): + if not hasattr(mmap, 'PROT_READ'): + return mapsize = 10 open(TESTFN, "wb").write(b"a"*mapsize) f = open(TESTFN, "rb") diff --git a/Lib/test/test_scope.py b/Lib/test/test_scope.py index ccb9016..c18445d 100644 --- a/Lib/test/test_scope.py +++ b/Lib/test/test_scope.py @@ -573,6 +573,13 @@ self.assert_(X.passed) f(4)() + def testFreeingCell(self): + # Test what happens when a finalizer accesses + # the cell where the object was stored. + class Special: + def __del__(self): + nestedcell_get() + def testNonLocalFunction(self): def f(x): diff --git a/Misc/ACKS b/Misc/ACKS index fae67a1..fa4175c 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -709,6 +709,7 @@ Edward Welbourne Cliff Wells Rickard Westman Jeff Wheeler +Christopher White Mats Wichmann Truida Wiedijk Felix Wiemann diff --git a/Modules/_struct.c b/Modules/_struct.c index dcf315e..28f67e9 100644 --- a/Modules/_struct.c +++ b/Modules/_struct.c @@ -1486,7 +1486,7 @@ s_init(PyObject *self, PyObject *args, PyObject *kwds) return -1; } - Py_XDECREF(soself->s_format); + Py_CLEAR(soself->s_format); soself->s_format = o_format; ret = prepare_s(soself); diff --git a/Modules/cStringIO.c b/Modules/cStringIO.c index 1251c1d..64e2146 100644 --- a/Modules/cStringIO.c +++ b/Modules/cStringIO.c @@ -566,8 +566,7 @@ newOobject(int size) { static PyObject * I_close(Iobject *self, PyObject *unused) { - Py_XDECREF(self->pbuf); - self->pbuf = NULL; + Py_CLEAR(self->pbuf); self->buf = NULL; self->pos = self->string_size = 0; diff --git a/Objects/cellobject.c b/Objects/cellobject.c index 4984366..490afe0 100644 --- a/Objects/cellobject.c +++ b/Objects/cellobject.c @@ -31,13 +31,15 @@ PyCell_Get(PyObject *op) int PyCell_Set(PyObject *op, PyObject *obj) { + PyObject* oldobj; if (!PyCell_Check(op)) { PyErr_BadInternalCall(); return -1; } - Py_XDECREF(((PyCellObject*)op)->ob_ref); + oldobj = PyCell_GET(op); Py_XINCREF(obj); PyCell_SET(op, obj); + Py_XDECREF(oldobj); return 0; } -- cgit v0.12