root/branches/add_stat_caching/ftpsync-0.1/loggingclass.py

Revision 545, 3.3 kB (checked in by schwa, 2 years ago)
Code contributed by Martin Wilck. (Thank you!) I might use some of
this code to add caching of stat results to ftputil.
  • Property svn:eol-style set to native
Line 
1 from logging import *
2 import sys
3
4 NOTICE = (INFO+WARNING)/2
5 _default_level = NOTICE
6 _default_format = "%(filename)s:%(name)s[%(lineno)d]: %(message)s"
7
8 def set_default_level(level):
9     """
10     Set the default log level for classes for which set_class_level()
11     or instance.set_log_level() was never called.
12     Default: NOTICE.
13     Call early - only affects class loggers created after the call.
14     """
15     global _default_level
16     _default_level = level
17
18 def _class_logger(cls):
19     nm ="_" + cls.__name__ + "__logger"
20     try:
21         lg = getattr(cls, nm)
22     except AttributeError:
23         lg = getLogger(cls.__name__)
24         lg.setLevel(_default_level)
25         setattr(cls, nm, lg)
26     return lg
27
28 def set_class_level(cls, level):
29     """
30     Set the log level for this class.
31     level: one of the levels defined in the logging module.
32     Side effects: Sets the log level for _any object_ of this class.
33     """
34     lg = _class_logger(cls)
35     lg.setLevel(level)
36
37 class LoggingClass:
38
39     """
40     A base class for classes using for easy use of the "logging" module.
41
42     Instances of derived classes have a "logger" attribute
43     that represents a class-specific logging.Logger object.
44
45     The "name" of the class-specific logger will be the class name.
46     Log levels etc. can be set on a class-specific basis.
47
48     CAUTION: The "logger" attribute is resolved through __getattr__().
49     The "__logger" attribute should work independently of __getattr__().
50
51     Usage (doctest):
52
53 >>> class LogTest(LoggingClass):
54 ...     def info(self):
55 ...         self.logger.info("This is an info.")
56 ...     def error(self):
57 ...         self.logger.error("This is an error!")
58 ...
59 >>> init_logging(level=INFO,
60 ...              format="%(name)s[%(lineno)d]: %(message)s", stream=sys.stdout)
61 >>> logtest = LogTest()
62 >>> logtest.info()
63 >>> logtest.error()
64 LogTest[5]: This is an error!
65 >>> LogTest().set_log_level(INFO)
66 >>> logtest.info()
67 LogTest[3]: This is an info.
68
69     """
70
71     # We can't simply define a "logger" attribute because we
72     # want class-specific loggers.
73
74     # The attribute name is constructed such that self.__logger
75     # will work in derived classes.
76
77     def __getattr__(self, attr):
78         """
79         Resolves the "logger" attribute.
80         Call this when redefining __getattr__() in derived classes!
81         """
82         if attr == "logger":
83             return _class_logger(self.__class__)
84         raise AttributeError, ("'LoggingClass' object has no attribute '%s'"
85                                % attr)
86
87     def set_log_level(self, level):
88         """
89         Set the log level for this class.
90         level: one of the levels defined in the logging module.
91         Sets the log level for _any object_ of this class.
92         """
93         return set_class_level(self.__class__, level)
94
95
96 def init_logging(level=NOTICE, format=_default_format, stream=sys.stderr):
97     """Initialize a basic logging setup."""
98    
99     handler = StreamHandler(stream)
100     handler.setFormatter(Formatter(format))
101     handler.setLevel(level)
102
103     getLogger().addHandler(handler)
104
105 def init_logfile(file, level=INFO, format=_default_format):
106
107     handler = FileHandler(file)
108     handler.setFormatter(Formatter(format))
109     handler.setLevel(level)
110    
111     getLogger().addHandler(handler)
112
113 def _test():
114     import doctest, loggingclass
115     doctest.testmod(loggingclass)
116
117 if __name__ == "__main__":
118     _test()
Note: See TracBrowser for help on using the browser.