| Trees | Indices | Help |
|
|---|
|
|
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3 #--------------------------------------------------------------------
4 # Filname: __init__.py
5 # Author: Mazhugin Aleksey
6 # Created: 2007/11/04
7 # ID: $Id: XPyLIB.xlogging-pysrc.html 24 2008-12-01 17:51:12Z alex $
8 # URL: $URL: file:///myfiles/svn_/XPyLIB/trunc/doc/html/XPyLIB.xlogging-pysrc.html $
9 # Copyright: Copyright (c) 2007, Mazhugin Aleksey.
10 # License: BSD
11 #--------------------------------------------------------------------
12 # Package initialisation
13
14 """
15 Some extensions for Python logging package.
16
17 This module import standart Python logging namespace " from logging import * ",
18 and you may use only xlogging for most usual targets.
19
20 X{Logging config file format.}
21 ==============================
22 Logging file format like config format in python logging package, but
23 have some differents.
24
25 The file must contain I{main} sections called [loggers], [handlers],
26 [filters] and [formatters] which identify by name the entities of each
27 type which are defined in the file. For each such entity, there is
28 a separate I{entity} section which identified how that entity is configured.
29 Thus, for a logger named log01 in the [loggers] section, the relevant
30 configuration details are held in a section [logger_log01]. Similarly,
31 a handler called hand01 in the [handlers] section will have its
32 configuration held in a section called [handler_hand01], while a
33 formatter called form01 in the [formatters] section will have its
34 configuration specified in a section called [formatter_form01].
35 The root logger configuration must be specified in a I{entity} section called
36 [logger_root].
37 The manager section configure loggers manager. Available only
38 one option: "disable". (It as logging.disable() function). This
39 section and option are optional.
40
41 In I{main} sections you must use option B{keys} (it mandatory):
42
43 - B{keys} - Add new object or will change configuration of existing
44 object.
45
46 Examples of these sections in the file are given below.::
47
48 [manager]
49 disable=WARNING
50
51 [loggers]
52 keys=root, log02, log03
53
54 [handlers]
55 keys=hand01, hand02, hand03, hand04
56
57 [formatters]
58 keys=form01,form02,form03,form04,form05,form06,form07,form08,form09
59
60 [filters]
61 keys=filt01, filt02, filt03
62
63 The entity sections may contains B{actions} option. In this
64 option may be listed action's names (it is a options's names with
65 description of action). Each action entity have next format::
66
67 act01=command, objecttype, arg01, arg02, ...
68
69 where:
70 - act01 - name of action given in actions option.
71 - command - command that need to executed.
72 - objecttype - object type for which command executed.
73 - arg01, arg02, ... - additional arguments for command.
74
75 For entity's sections B{logger_???} and B{handler_???} you may execute next
76 commands: B{clear}, B{remove}, B{add}.
77 For entity's sections B{formatter_???} and B{filter_???} actions will be
78 I{ignored}.
79
80 The I{arg**} in commands is name of objects.
81
82 As I{objecttype} for sections you must use next types:
83 - for B{[logger_???]} : handler, filter.
84 - for B{[handler_???]} : filter, formatter.
85
86 For entity section you also can specify object attribute and value to set::
87
88 attributes=attr01, attr02
89 attr01=attrname, attrvalue
90 attr02=attrname, attrvalue
91
92 Where B{attributes} is a option with attribute's options
93 names I{attr01}, I{attr02}.
94 Into options I{attr01}, I{attr02} you must specify attribute name
95 B{attrname} and attribute value B{attrvalue}. The value willbe evaluated
96 using eval() in logging namespace.
97
98 The root logger I{must} specify a B{level}, list of handlers and filters.
99 For [logger_???] sections have no mandatory options. By default
100 level, handlers and other attributes are no changed.
101 An example of a root logger section is given below.::
102
103 [logger_root]
104 level=NOTSET
105 handlers=hand01
106 filters=
107 actions=act01, act02
108 act01=clear, handler
109 act02=remove, filter, filt99
110 act03=add, handler, hand55
111 disabled=0
112 attributes=attr01
113 attr01= name, A.B.C
114
115 For loggers other than the root logger, some additional information is
116 required.
117 The level and handlers entries are interpreted as for the root logger,
118 except that if a non-root logger's level is specified as NOTSET,
119 the system consults loggers higher up the hierarchy to determine the
120 effective level of the logger. The B{propagate} entry is set to B{1}
121 (is default) to indicate
122 that messages must propagate to handlers higher up the logger hierarchy
123 from this logger, or B{0} to indicate that messages are not propagated to
124 handlers up the hierarchy. The B{qualname} entry is the hierarchical channel
125 name of the logger, that is to say the name used by the application to
126 get the logger.
127 The B{disabled} set this logger disabled (I{1}) or enabled (I{0}). By
128 default disabled is I{0} for new or not changed for existing logger.
129 The mandatory options is no. If B{qualname} is not specified then
130 configuration name is used, for below example it is 'parser'.
131 The B{filters} entry, specify filters names to use.If this entry specified
132 then clear all filters then add new filters from I{filters} list.
133 If I{handlers} entry specified then clear all filters then add new
134 handlers from I{handlers} list.
135 This is illustrated by the following example.::
136
137 [logger_parser]
138 level=DEBUG
139 handlers=hand01
140 propagate=1
141 qualname=compiler.parser
142 filters=
143 actions=act01
144 act01=clear,handler
145 disabled=0
146 attributes=attr01
147 attr01= name, A.B.C
148
149 Sections which specify handler configuration are exemplified by the following.
150 The B{class} entry indicates the handler's class (as determined by eval() in
151 the logging package's namespace). The level is interpreted as for loggers,
152 and NOTSET is taken to mean "log everything".
153
154 The B{formatter} entry indicates the key name of the formatter for
155 this handler. If blank, a default formatter (C{logging._defaultFormatter})
156 is used. If a name is specified, it must appear in the [formatters]
157 section and have a corresponding section in the configuration file.
158
159 The B{args} entry, when eval() evaluated in the context of the logging
160 package's namespace, is the list of arguments to the constructor
161 for the handler class. Refer to the constructors for the relevant
162 handlers, or to the examples below, to see how typical entries are
163 constructed.
164
165 The B{filters} entry, specify filters names to use.If this entry specified
166 then clear all filters then add new filters from I{filters} list.
167
168 The mandatory options is B{class} and B{args} and only for new handlers.::
169
170 [handler_hand01]
171 class=StreamHandler
172 level=NOTSET
173 formatter=form01
174 args=(sys.stdout,)
175 filters=
176 actions=act01
177 act01=add, filter, filt01
178 attributes=attr01
179 attr01= attrname, A.B.C
180
181 Sections which specify filter configuration are typified by the following.
182 The mandatory options is B{class} and B{args} and only for new filters.::
183
184 [filter_filt01]
185 class=Filter
186 args=('App')
187 attributes=attr01
188 attr01= name, A.B.C
189
190 Sections which specify formatter configuration are typified by the following.::
191
192 [formatter_form01]
193 format=F1 %(asctime)s %(levelname)s %(message)s
194 datefmt=
195 class=logging.Formatter
196 args=()
197 attributes=attr01
198 attr01= name, A.B.C
199
200 The mandatory options is B{format} and B{datefmt}.
201
202 The B{format} entry is the overall format string, and the B{datefmt}
203 entry is the strftime()-compatible date/time format string.
204 If empty, the package substitutes ISO8601 format date/times,
205 which is almost equivalent to specifying the date format string
206 "The ISO8601 format also specifies milliseconds, which are appended to
207 the result of using the above format string, with a comma separator.
208 An example time in ISO8601 format is 2003-01-23 00:29:50,411.
209
210 The B{class} entry is optional. It indicates the name of the formatter's
211 class (as a dotted module and class name.) This option is useful for
212 instantiating a Formatter subclass. Subclasses of Formatter can present
213 exception tracebacks in an expanded or condensed format.
214
215
216
217
218 @warning: You must accurate use remove or clear options or commands,
219 becouse may be conflict with currently executed code in runtime if it
220 use removed objects.
221
222 @note: After importing xlogging L{XLogger} class set as default class for
223 new loggers.
224
225 @var TRACE: Logging level constant, used for prereliase tracing.
226 @type TRACE: int
227
228 @var DBGTRACE: Logging level constant, used for debug tracing.
229 @type DBGTRACE: int
230
231 @var _xBaseloggerClass: Base logger class (get from logging). Used as base for XLogger.
232 @type _xBaseloggerClass: Logger
233 """
234
235 # Importing
236 import logging
237 from logging import *
238 from functools import wraps
239
240 try:
241 import thread
242 import threading
243 except:
244 thread=None
245
246 # Not XPyLIB.dbg, only dbg for cross links avoid.
247 import dbg ##@
248
249 ##dbg.fwriteln('*** xlogging debug output ***') ##@
250
251 # Constants.
252
253 TRACE = 15
254 DBGTRACE = 5
255
256 # Add logging level constants.
257 addLevelName(TRACE, 'TRACE')
258 addLevelName(DBGTRACE, 'DBGTRACE')
259
260 # Store base logger class.
261 _xBaseloggerClass = logging.getLoggerClass()
262
263 # Start Implementation
264 ##@dbg.fwlevel ##@
266 """
267 Return level name by level value.
268
269 If no such level then raise error KeyError.
270 """
271 ##dbg.fwriteln('getLevelByName: level %s=%d'% (levelname,logging._levelNames[levelname])) ##@
272 return logging._levelNames[levelname]
273
274 ##@dbg.fwlevel ##@
276 """
277 Read the logging configuration from a ConfigParser-format file.
278
279 This can be called several times from an application, allowing an end user
280 the ability to select from various pre-canned configurations (if the
281 developer provides a mechanism to present the choices and load the chosen
282 configuration).
283 In versions of ConfigParser which have the readfp method [typically
284 shipped in 2.x versions of Python], you can pass in a file-like object
285 rather than a filename, in which case the file-like object will be read
286 using readfp.
287
288 Algorithm:
289 ==========
290
291 1. Read [loggers], [handlers], [filters], [formatters] keys into DICT.
292 2. FOR _logger_ IN [loggers]:
293 1. IF _logger_ EXIST get it, ELSE create new
294 2. Read _fs_=[filters].
295 3. IF _fs_ THEN:
296 1. _filters_.clear.
297 2. FOR _f_ IN _fs_:
298 1. Read filter from config.
299 2. Create new filter.
300 3. Add filter to _logger_.
301 4. FOR _f_ IN _fs_:
302 1. Read filter changes from config section.
303 2. Change filter _f_.
304 3. Read [attributes] and apply.
305 5. Read _hs_=[handlers].
306 6. IF _hs_ THEN:
307 1. _handlers_.clear.
308 2. FOR _h_ IN _hs_:
309 1. Read handler from config.
310 2. Create new handler.
311 3. Add handler to _logger_.
312 7. FOR _h_ IN _hs_:
313 1. Read handler changes from config section.
314 2. Change handler _h_.
315 3. Read [formatter] and ADD or CHANGE.
316 4. Read [filters] and ADD or CHANGE.
317 5. Read [attributes] and apply.
318 8. Read [attributes] and apply.
319
320 Logger section example::
321
322 [manager]
323 #disable=WARNING
324
325 [logger_parser]
326 level=DEBUG
327 handlers=hand01
328 propagate=1
329 qualname=compiler.parser
330 filters=
331 actions=act01
332 act01=clear,handler
333 disabled=0
334 attributes=attr01
335 attr01= name, A.B.C
336 """
337 import ConfigParser
338
339 ##dbg.fwriteln('Load config parser.') ##@
340
341 cp = ConfigParser.SafeConfigParser(defaults)
342 if hasattr(cp, 'readfp') and hasattr(fname, 'readline'):
343 cp.readfp(fname)
344 else:
345 cp.read(fname)
346
347 # Test for mandatory main sections.
348 ##dbg.fwriteln('Test for mandatory main sections.') ##@
349 if not all( \
350 [ cp.has_section(s) and cp.has_option(s, 'keys') \
351 for s in ('loggers', 'handlers', 'filters', 'formatters') ] ):
352 ##dbg.fwriteln('\tFAIL Test for mandatory main sections.') ##@
353 return # Return if not all have.
354
355 loggers=dict((n.strip(), None) for n in str(cp.get('loggers','keys')).split(',') if n.strip())
356 handlers=dict((n.strip(), None) for n in str(cp.get('handlers','keys')).split(',') if n.strip())
357 filters=dict((n.strip(), None) for n in str(cp.get('filters','keys')).split(',') if n.strip())
358 formatters=dict((n.strip(), None) for n in str(cp.get('formatters','keys')).split(',') if n.strip())
359
360 ##dbg.fwriteln('loggers=', loggers) ##@
361 ##dbg.fwriteln('handlers=', handlers) ##@
362 ##dbg.fwriteln('filters=', filters) ##@
363 ##dbg.fwriteln('formatters=', formatters) ##@
364
365 # Start critical section.
366 logging._acquireLock()
367 try:
368
369 ##dbg.fwriteln('manager configure') ##@
370 sec='manager'
371 if cp.has_section(sec):
372 if cp.has_option(sec, 'disable'):
373 try:
374 ##dbg.fwriteln('set disable=',cp.get(sec,'disable')) ##@
375 disable( getLevelByName(cp.get(sec,'disable')) )
376 except:
377 ##dbg.fwriteln('\texception') ##@
378 pass
379
380 ##dbg.fwriteln('\nSTART LOGGER LOOP\n') ##@
381 for logger in loggers:
382 sec = 'logger_' + logger
383 ##dbg.fwriteln('Read section=', sec) ##@
384 if cp.has_section(sec):
385 opts = _options(sec, cp)
386 ##dbg.fwriteln('opts=', opts) ##@
387 # Get logger name, overwork about root.
388 if logger == 'root':
389 name = logger
390 else:
391 name = opts.has_key('qualname') and opts['qualname'] or logger
392 ##dbg.fwriteln('name=', name) ##@
393 # Get logger, overwork about root logger.
394 if name == 'root':
395 loginst = root
396 else:
397 loginst = logging.getLogger(name)
398 loggers[logger] = loginst
399 # Configure logger.
400 ##dbg.fwriteln('Configure logger') ##@
401 if opts.has_key('level'):
402 try:
403 loginst.setLevel( getLevelByName(opts['level']) )
404 ##dbg.fwriteln('set level=', getLevelByName(opts['level'])) ##@
405 except:
406 ##dbg.fwriteln('\texception') ##@
407 pass
408 if opts.has_key('propagate'):
409 try:
410 loginst.propagate = int(opts['propagate'])
411 ##dbg.fwriteln('set propogate', int(opts['propagate'])) ##@
412 except:
413 ##dbg.fwriteln('\texception') ##@
414 pass
415 if opts.has_key('disabled'):
416 try:
417 loginst.disabled = int(opts['disabled'])
418 ##dbg.fwriteln('set disabled', int(opts['disabled'])) ##@
419 except:
420 ##dbg.fwriteln('\texception') ##@
421 pass
422
423 # Apply attributes.
424 ##dbg.fwriteln('Apply attributes') ##@
425 _applyAttrs(opts, loginst)
426
427 # Apply filters.
428 ##dbg.fwriteln('Apply filters') ##@
429 if opts.has_key('filters'):
430 # Clear filters.
431 ##dbg.fwriteln('\tClearfilters') ##@
432 for f in loginst.filters:
433 loginst.remove(f)
434 fs=[ n.strip() for n in opts['filters'].split(',') if n.strip() ]
435 ##dbg.fwriteln('\tfilters=', fs) ##@
436 _applyFilters(fs, loginst, cp, filters)
437
438 # Apply handlers.
439 ##dbg.fwriteln('Apply handlers') ##@
440 if opts.has_key('handlers'):
441 # Clear filters.
442 ##dbg.fwriteln('\tClear handlers') ##@
443 for h in loginst.handlers:
444 loginst.removeHandler(h)
445 hs=[ n.strip() for n in opts['handlers'].split(',') if n.strip() ]
446 ##dbg.fwriteln('handlers=', hs) ##@
447 _applyHandlers(hs, loginst, cp, handlers, formatters, filters)
448
449 # Apply actions.
450 ##dbg.fwriteln('Apply actions') ##@
451 _applyActions(opts, loginst, cp, handlers, formatters, filters)
452
453 ##end if cp.has_section(sec):
454
455 ##end for logger
456 ##dbg.fwriteln() ##@
457
458 finally:
459 # End critical section.
460 logging._releaseLock()
461
462 ##@dbg.fwlevel ##@
464 """
465 Apply attributes from dictionary "opts" to object instance "inst".
466
467 @param opts: Dictionary with item "attributes" and items listed in
468 "attributes" which will be applied.
469 @type opts: dict
470 @param inst: Object instance.
471 """
472 if opts.has_key('attributes'):
473 ##dbg.fwriteln('Find attributes') ##@
474 for a in [ opts[n.strip()] for n in opts['attributes'].split(',') \
475 if opts.has_key( n.strip() ) ]:
476 # Loop for attributes.
477 aa = [n.strip() for n in a.partition(',')]
478 ##dbg.fwriteln('apply attr "',aa[0], '" = ', aa[2]) ##@
479 if aa[0]:
480 try:
481 ##dbg.fwriteln('\tset attr') ##@
482 setattr(inst, aa[0], aa[2])
483 except:
484 ##dbg.fwriteln('\t\texception') ##@
485 pass
486 ##end for a
487
488 ##@dbg.fwlevel ##@
490 """
491 Return readed options and it's values in dictionary.
492
493 @param sec: Section name.
494 @type sec: str
495 @param cp: Config parser instance.
496 @type cp: ConfigParser
497 @param raw: Raw mode for get in ConfigParser.
498 @type raw: int = {0}
499 @return: Dictionary with options and values.
500 @rtype: dict
501 """
502 r = {}
503 if cp.has_section(sec):
504 r = dict( (n, cp.get(sec,n,raw)) for n in cp.options(sec) )
505 ##dbg.fwriteln('options=', r) ##@
506 return r
507
508 ##@dbg.fwlevel ##@
510 """
511 Aplly filters with names listed in "flts": to object "inst".
512
513 First try find named filter into "inst.filters" list (which have attribute "name"),
514 if not find then try find into "filters" dict,
515 else create new. Then apply changes
516 to filter.
517 Filter name must exist in filters list.
518 To add filter to inst used "addFilter" method.
519 To created or added filters set attribute "name" to filter name.
520
521 @param flts: List with filter's names.
522 @type flts: list
523 @param inst: Object instance to apply filters.
524 @type inst: Object instance
525 @param cp: Config parser instance.
526 @type cp: ConfigParser
527 @param filters: Permited filters name with existing or None instances.
528 @type filters: dict
529
530 Filter section example::
531
532 [filter_filt01]
533 class=Filter
534 args=('App')
535 attributes=attr01
536 attr01= name, A.B.C
537
538 """
539 if not flts or not hasattr(inst, 'filters') or not hasattr(inst, 'addFilter'):
540 return
541 import sys
542 ##_self_module=sys.modules[XLogger.__module__]
543 ##dbg.fwriteln('_self_module=', _self_module) ##@
544 ##dbg.fwriteln('Filter loop') ##@
545 for fn in flts:
546 ##dbg.fwriteln('fn=', fn) ##@
547 if not filters.has_key(fn):
548 # Exit for if no such filter name into filters.
549 ##dbg.fwriteln('EXIT: no such name into filters') ##@
550 break
551 if cp.has_section('filter_' + fn):
552 opts = _options('filter_' + fn, cp)
553 ##dbg.fwriteln('opts=', opts) ##@
554 f = None # Filter
555
556 # Try find filter in instance.
557 ##dbg.fwriteln('Try find filter in instance') ##@
558 for fi in inst.filters:
559 if hasattr(fi, 'name') and (fi.name == fn):
560 ##dbg.fwriteln('FIND filter in instance') ##@
561 f=fi
562 break
563 if not f:
564 if filters[fn] != None:
565 ##dbg.fwriteln('find filter into filters') ##@
566 f=filters[fn]
567 else:
568 # Create new filter.
569 ##dbg.fwriteln('Create new filter') ##@
570 klass = logging.Filter
571 if opts.has_key('class'):
572 c = opts['class'].strip()
573 ##dbg.fwriteln('["class"]=', c) ##@
574 if c:
575 try:
576 ##dbg.fwriteln('eval class') ##@
577 c = eval(c, vars(sys.modules[__name__]))
578 except:
579 ##dbg.fwriteln('\texception') ##@
580 c=None
581 if c:
582 ##dbg.fwriteln('Set new class', c) ##@
583 klass = c
584 a = ()
585 ##dbg.fwriteln('search args') ##@
586 if opts.has_key('args'):
587 ##dbg.fwriteln('have args') ##@
588 a = opts['args']
589 ##dbg.fwriteln('args=', a) ##@
590 try:
591 ##dbg.fwriteln('Try eval args') ##@
592 a = eval(a, vars(sys.modules[__name__]))
593 except:
594 ##dbg.fwriteln('\texception') ##@
595 a=()
596
597 ##dbg.fwriteln('CREATE filter') ##@
598 f = klass(*a)
599 ##end if filters[fn] != None
600 try:
601 ##dbg.fwriteln('Add to instance') ##@
602 inst.addFilter(f)
603 except:
604 pass
605
606 ##end if not f
607 if filters[fn] == None:
608 ##dbg.fwriteln('set to filters') ##@
609 filters[fn]=f
610
611 # Set filter name.
612 ##dbg.fwriteln('Set name to filter=',fn) ##@
613 setattr(f, 'name', fn)
614
615 ##dbg.fwriteln('Apply attrs') ##@
616 _applyAttrs(opts, f)
617
618 ##end if cp.has_section('filter_' + fn)
619 ##dbg.fwriteln() ##@
620 ##end for f
621 ##dbg.fwriteln('End filter loop') ##@
622 # Ignore actions for filters
623
624 ##@dbg.fwlevel ##@
626 """
627 Aplly formatter with name listed in "fmtr": to object "inst".
628
629 First try find named formatter into "inst.formatter" list (which have attribute "name"),
630 if not find then try find into "formatters" dict,
631 else create new. Then apply changes
632 to formatter.
633 Formatter name must exist in formatters list.
634 To add filter to inst used "setFormatter" method.
635
636 @warning: Options for formatter readed in raw mode (see ConfigParser).
637
638 @param fmtr: Formatter name.
639 @type fmtr: list
640 @param inst: Object instance to apply formatter.
641 @type inst: Object instance
642 @param cp: Config parser instance.
643 @type cp: ConfigParser
644 @param formatters: Permited formatters name with existing or None instances.
645 @type formatters: dict
646
647 Formatter section example::
648
649 [formatter_form01]
650 format=F1 %(asctime)s %(levelname)s %(message)s
651 datefmt=
652 class=logging.Formatter
653 args=()
654 attributes=attr01
655 attr01= name, A.B.C
656
657 """
658 if not fmtr or not hasattr(inst, 'formatter') or not hasattr(inst, 'setFormatter'):
659 return
660 import sys
661 ##_self_module=sys.modules[XLogger.__module__]
662 ##dbg.fwriteln('_self_module=', _self_module) ##@
663 sec = 'formatter_' + fmtr
664 ##dbg.fwriteln('sec=', sec) ##@
665 if cp.has_section(sec):
666 opts = _options(sec, cp, 1) # Raw
667 ##dbg.fwriteln('opts=', opts) ##@
668 f = None # Formatter
669 if not formatters.has_key(fmtr):
670 # Exit if no such formatter name into formatterss.
671 ##dbg.fwriteln('EXIT such formatter is not in formatters.') ##@
672 return
673 # Try find formatter in instance.
674 ##dbg.fwriteln('Try find in instance') ##@
675 fi = inst.formatter
676 if hasattr(fi, 'name') and (fi.name == fmtr):
677 ##dbg.fwriteln('FIND in instance') ##@
678 f=fi
679 if not f:
680 ##dbg.fwriteln('search in formatters') ##@
681 if formatters[fmtr] != None:
682 ##dbg.fwriteln('FIND in formatters') ##@
683 f=formatters[fmtr]
684 else:
685 # Create new formatter.
686 ##dbg.fwriteln('Create new') ##@
687 klass = logging.Formatter
688 if opts.has_key('class'):
689 c = opts['class'].strip()
690 ##dbg.fwriteln('["class"]=',c) ##@
691 if c:
692 try:
693 ##dbg.fwriteln('Eval class') ##@
694 c = eval(c, vars(sys.modules[__name__]))
695 except:
696 ##dbg.fwriteln('\texception') ##@
697 c=None
698 if c:
699 ##dbg.fwriteln('Set new class ', c) ##@
700 klass = c
701 a = ()
702 ##dbg.fwriteln('Search args') ##@
703 if opts.has_key('args'):
704 a = opts['args']
705 ##dbg.fwriteln('args=', a) ##@
706 try:
707 ##dbg.fwriteln('eval args') ##@
708 a = eval(a, vars(sys.modules[__name__]))
709 except:
710 ##dbg.fwriteln('\texception') ##@
711 a=()
712 if opts.has_key('format'):
713 fs = opts['format']
714 ##dbg.fwriteln('format=', fs) ##@
715 else:
716 ##dbg.fwriteln('no format') ##@
717 fs = None
718 if opts.has_key('datefmt'):
719 dfs = opts['datefmt']
720 ##dbg.fwriteln('datefmt=', dfs) ##@
721 else:
722 ##dbg.fwriteln('no datefmt') ##@
723 dfs = None
724 ##dbg.fwriteln('Create new formatter.') ##@
725 f = klass(fs, dfs, *a)
726 ##end if formatters[fmtr] != None
727 try:
728 ##dbg.fwriteln('Set instance formatter.') ##@
729 inst.setFormatter(f)
730 except:
731 ##dbg.fwriteln('\texception') ##@
732 pass
733 ##end if not f
734 if formatters[fmtr] == None:
735 ##dbg.fwriteln('Set formatters') ##@
736 formatters[fmtr]=f
737 ##dbg.fwriteln('Set name to formatter=', fmtr) ##@
738 setattr(f,'name',fmtr)
739
740 ##dbg.fwriteln('Apply attrs') ##@
741 _applyAttrs(opts, f)
742 ##end if cp.has_section('filter_' + fn)
743 # Ignore actions for formatter
744
745 ##@dbg.fwlevel ##@
747 """
748 Aplly handlerss with names listed in "hdls": to object "inst".
749
750 First try find named handler into "inst.handlers" list
751 (which have attribute "name"), if not then
752 try find in "handlers" dict,
753 else create new. Then apply changes
754 to handler.
755 Handler name must exist in handlers list.
756 To add handler to inst used "addHandler" method.
757
758 @param hdls: List with hamdler's names.
759 @type hdls: list
760 @param inst: Object instance to apply handlers.
761 @type inst: Object instance
762 @param cp: Config parser instance.
763 @type cp: ConfigParser
764 @param handlers: Permited handlers name with existing or None instances.
765 @type handlers: dict
766 @param formatters: Permited formatters.
767 @type formatters: dict
768 @param filters: Permited filters.
769 @type filters: dict
770
771 Handler section example::
772
773 [handler_hand01]
774 class=StreamHandler
775 level=NOTSET
776 formatter=form01
777 args=(sys.stdout,)
778 filters=
779 actions=act01
780 act01=add, filter, filt01
781 attributes=attr01
782 attr01= attrname, A.B.C
783
784 """
785 if not hdls or not hasattr(inst, 'handlers') or not hasattr(inst, 'addHandler'):
786 return
787 import sys
788 ##_self_module=sys.modules[XLogger.__module__]
789 ##dbg.fwriteln('_self_module=', _self_module) ##@
790 ##dbg.fwriteln('HANDLERS LOOP') ##@
791 for hn in hdls:
792 ##dbg.fwriteln('hn=', hn) ##@
793 if cp.has_section('handler_' + hn):
794 opts = _options('handler_' + hn, cp)
795 ##dbg.fwriteln('opts=', opts) ##@
796 h = None # Handler
797 if not handlers.has_key(hn):
798 # Exit if no such handler name into handlers.
799 ##dbg.fwriteln('EXIT such handler not find in handlers') ##@
800 return
801 # Try find handler in instance.
802 ##dbg.fwriteln('Try find in instance') ##@
803 for hi in inst.handlers:
804 if hasattr(hi, 'name') and (hi.name == hn):
805 ##dbg.fwriteln('FIND in instance') ##@
806 h=hi
807 break
808 if not h:
809 # Try find handlers dict.
810 ##dbg.fwriteln('Search in handlers') ##@
811 if handlers[hn] != None:
812 ##dbg.fwriteln('FIND in handlers') ##@
813 h=handlers[hn]
814 else:
815 # Create new handler.
816 ##dbg.fwriteln('Create new') ##@
817 klass = NullHandler
818 if opts.has_key('class'):
819 c = opts['class'].strip()
820 ##dbg.fwriteln('["class"]=', c) ##@
821 if c:
822 try:
823 ##dbg.fwriteln('Eval class') ##@
824 c = eval(c, vars(sys.modules[__name__]))
825 except Exception, e:
826 ##dbg.fwriteln('\texception=', e) ##@
827 c=None
828 if c:
829 ##dbg.fwriteln('Set new class') ##@
830 klass = c
831 a = ()
832 if opts.has_key('args'):
833 a = opts['args']
834 ##dbg.fwriteln('args=', a) ##@
835 try:
836 ##dbg.fwriteln('Eval args') ##@
837 a = eval(a, vars(sys.modules[__name__]))
838 except:
839 ##dbg.fwriteln('\texception') ##@
840 a=()
841
842 ##dbg.fwriteln('Create and set new class', klass) ##@
843 h = klass(*a)
844 ##end if handlers[hn] != None
845 ##dbg.fwriteln('Try add to instance') ##@
846 try:
847 ##dbg.fwriteln('Add handler to instance') ##@
848 inst.addHandler(h)
849 except:
850 ##dbg.fwriteln('\texception') ##@
851 pass
852
853 ##end if not h
854 if handlers[hn] == None:
855 ##dbg.fwriteln('Add to handlers') ##@
856 handlers[hn]=h
857
858 ##dbg.fwriteln('Set name to handler=',hn) ##@
859 setattr(h, 'name', hn)
860
861 # Configure handler.
862 ##dbg.fwriteln('Configure handler') ##@
863 if opts.has_key('level'):
864 try:
865 h.setLevel( getLevelByName(opts['level']) )
866 ##dbg.fwriteln('set level=', getLevelByName(opts['level'])) ##@
867 except:
868 ##dbg.fwriteln('\texception') ##@
869 pass
870
871 # Apply formatter.
872 if opts.has_key('formatter'):
873 ##dbg.fwriteln('Apply formatter') ##@
874 _applyFormatter(opts['formatter'].strip(), h, cp, formatters)
875 # Apply filters.
876 if opts.has_key('filters'):
877 ##dbg.fwriteln('ApplyFilters') ##@
878 _applyFilters([f.strip() for f in opts['filters'].split(',') if f.strip()], h, cp, filters)
879
880 ##dbg.fwriteln('apply attrs') ##@
881 _applyAttrs(opts, h)
882
883 ##dbg.fwriteln('Apply actions') ##@
884 _applyActions(opts, h, cp, handlers, formatters, filters)
885 ##end if cp.has_section('handler_' + hn)
886 ##dbg.fwriteln() ##@
887 ##end for h
888
889 ##@dbg.fwlevel ##@
891 """
892 Aplly actions with names listed in "opts['actions']": to object "inst".
893
894 First try find named filter into "filters" dict, if not find then
895 (which have attribute "name") into "inst.filters" list,
896 else create new. Then apply changes
897 to filter.
898 Filter name must exist in filters list.
899 To add filter to inst used "addFilter" method.
900
901 @param opts: Dictionary with actions describes.
902 @type opts: dict
903 @param inst: Object instance to apply actions.
904 @type inst: Object instance
905
906 Action example::
907
908 actions=act01
909 act01=add, filter, filt01
910
911 """
912
913 if opts.has_key('actions'):
914 ##dbg.fwriteln('Action LOOP') ##@
915 for a in [ opts[n.strip()] for n in opts['actions'].split(',') \
916 if opts.has_key( n.strip() ) ]:
917 # Loop for actions.
918 aa = [n.strip() for n in a.split(',')]
919 ##dbg.fwriteln('aa=', aa) ##@
920 if aa[0] == 'add':
921 ##dbg.fwriteln('add') ##@
922 if aa[1] == 'filter' and ( issubclass(inst.__class__, logging.Handler) \
923 or issubclass(inst.__class__, logging.Logger) ):
924 ##dbg.fwriteln('\tfilters') ##@
925 _applyFilters([aa[2]], inst, cp, filters)
926 elif aa[1] == 'handler' and issubclass(inst.__class__, logging.Logger):
927 ##dbg.fwriteln('\thandler') ##@
928 _applyHandlers([aa[2]], inst, cp, handlers, formatters, filters)
929 elif aa[1] == 'formatter' and issubclass(inst.__class__, logging.Handler):
930 ##dbg.fwriteln('\tformatter') ##@
931 _applyFormatter(aa[2], inst, cp, formatters)
932 ##end elif a[0] == 'add'
933 elif aa[0] == 'remove':
934 ##dbg.fwriteln('remove') ##@
935 if aa[1] == 'filter' and ( issubclass(inst.__class__, logging.Handler) \
936 or issubclass(inst.__class__, logging.Logger) ):
937 ##dbg.fwriteln('\tfilters') ##@
938 for i in inst.filters:
939 if hasattr(i, 'name') and i.name == aa[2]:
940 inst.removeFilter(i)
941 break
942 elif aa[1] == 'handler' and issubclass(inst.__class__, logging.Logger):
943 ##dbg.fwriteln('\thandlers') ##@
944 for i in inst.handlers:
945 if hasattr(i, 'name') and i.name == aa[2]:
946 inst.removeHandler(i)
947 break
948 elif aa[1] == 'formatter' and issubclass(inst.__class__, logging.Handler):
949 if hasattr(inst.formatter, 'name') and inst.formatter.name == aa[2]:
950 ##dbg.fwriteln('formatter') ##@
951 inst.setFormatter(logging.Formatter())
952 ##end elif a[0] == 'remove'
953 elif aa[0] == 'clear':
954 ##dbg.fwriteln('clear') ##@
955 if aa[1] == 'filter' and ( issubclass(inst.__class__, logging.Handler) \
956 or issubclass(inst.__class__, logging.Logger) ):
957 ##dbg.fwriteln('\tfilters') ##@
958 for i in inst.filters:
959 inst.removeFilter(i)
960 elif aa[1] == 'handler' and issubclass(inst.__class__, logging.Logger):
961 ##dbg.fwriteln('\thandlers') ##@
962 for i in inst.handlers:
963 inst.removeHandler(i)
964 elif aa[1] == 'formatter' and issubclass(inst.__class__, logging.Handler):
965 ##dbg.fwriteln('\tformatter') ##@
966 inst.setFormatter(logging.Formatter())
967 ##end elif a[0] == 'clear'
968 ##dbg.fwriteln() ##@
969 ##end for a
970
971
986
988 """
989 Filter available output only if level in specified range.
990 Return true if available.
991 """
993 """
994 @param min: Minimal available level for output.
995 @type min: int = {NOTSET}
996 @param max: Maximal available level for output.
997 @type max: int = {CRITICAL}
998 """
999 ##dbg.fwriteln('RangeFilter.__init__() ', min, ', ', max) ##@
1000 self._min=min
1001 self._max=max
1002
1009
1011 """
1012 Filter available output only if logger name equal any from 'names'.
1013 Return true if available.
1014 """
1016 """
1017 @param names: List (or string with one name) of names with which
1018 allow output.
1019 @type names: list or str = ''
1020 @param case: If true then compare names case sensitive.
1021 @type case: bool = 0
1022 """
1023 ##dbg.fwriteln('NamesFilter.__init__() names=', repr(names)) ##@
1024 if type(names) == str:
1025 names = [names]
1026 if not case:
1027 self._names=[n.lower() for n in names]
1028 else:
1029 self._names=names
1030 self._case=case
1031
1033 """
1034 Return true if message is available (in 'names').
1035 """
1036 r= self._case and record.name or record.name.lower()
1037 ##dbg.writeln('**** name=',r) ##@
1038 for n in self._names:
1039 ##dbg.writeln('******** n=',n) ##@
1040 if r.startswith(n):
1041 return 1
1042 ##dbg.writeln('**** return 0') ##@
1043 return 0
1044
1046 """
1047 Formatter with indentation level support.
1048
1049 Instance of this class exists only in one exemplar. For other requests
1050 of new instance returned already existing.
1051
1052 Level indentation is specific for each threads separately (if thread
1053 library available, otherwase used only common indentation level for all threads).
1054
1055 @cvar _level: Indentation level. Dictionary of {thread.id, level} if thread
1056 enebled, else level.
1057 @type _level: dict{int,int} or int
1058 @cvar __instance: Singular instance.
1059 @type __instance: Instance IndentFormatter
1060 """
1061
1062 __instance = None
1063 _level = thread and threading.local() or 0
1064
1066 """
1067 Allow only one exemplar of instance. For other calls return existing.
1068 """
1069 ##dbg.fwriteln('IndentFormatter.__new__') ##@
1070 logging._acquireLock()
1071 try:
1072 if not IndentFormatter.__instance:
1073 ##dbg.fwriteln('IndentFormatter.__new__ create new') ##@
1074 IndentFormatter.__instance = super(IndentFormatter, cls).__new__(cls, *args)
1075 IndentFormatter.__createLock()
1076 finally:
1077 logging._releaseLock()
1078 return IndentFormatter.__instance
1079
1081 """
1082 Initialize the formatter with specified format strings.
1083
1084 Initialize the formatter either with the specified format string, or a
1085 default as described above. Allow for specialized date formatting with
1086 the optional datefmt argument (if omitted, you get the ISO8601 format).
1087 """
1088 ##dbg.fwriteln('IndentFormatter.__init__') ##@
1089 Formatter.__init__(self, fmt, datefmt)
1090
1091 @staticmethod
1093 """
1094 Initialize level for current thread.
1095 """
1096 ##dbg.fwriteln('IndentFormatter.initlevel') ##@
1097 if thread:
1098 # Init thread dependent levels.
1099 if not hasattr(IndentFormatter._level, 'level'):
1100 ##dbg.fwriteln('IndentFormatter.initlevel initialized') ##@
1101 IndentFormatter._level.level = 0
1102
1103 @staticmethod
1105 """
1106 Get level for current thread.
1107 """
1108 ##dbg.fwriteln('IndentFormatter.getlevel') ##@
1109 IndentFormatter.__init_level()
1110 if thread:
1111 l=IndentFormatter._level.level
1112 else:
1113 l=IndentFormatter._level
1114 return l
1115
1116 @staticmethod
1118 """
1119 Set level for current thread.
1120 """
1121 ##dbg.fwriteln('IndentFormatter.setlevel') ##@
1122 IndentFormatter.__init_level()
1123 if thread:
1124 IndentFormatter._level.level=value
1125 else:
1126 IndentFormatter._level=value
1127
1128 @staticmethod
1130 """
1131 Acquire a thread lock for serializing access to the level counter.
1132 """
1133 ##dbg.fwriteln('IndentFormatter.createLock') ##@
1134 if thread:
1135 IndentFormatter.__lock = threading.RLock()
1136 else:
1137 IndentFormatter.__lock = None
1138
1139 @staticmethod
1141 """
1142 Acquire thread lock.
1143 """
1144 ##dbg.fwriteln('IndentFormatter.acquire') ##@
1145 if IndentFormatter.__lock:
1146 IndentFormatter.__lock.acquire()
1147
1148 @staticmethod
1150 """
1151 Release thread lock.
1152 """
1153 ##dbg.fwriteln('IndentFormatter.release') ##@
1154 if IndentFormatter.__lock:
1155 IndentFormatter.__lock.release()
1156
1158 """
1159 Format the specified record as text.
1160 """
1161 ##dbg.fwriteln('IndentFormatter.format') ##@
1162 c=__import__('XPyLIB')
1163 IndentFormatter.acquire()
1164 try:
1165 r=(c.log_levelbodychar * c.log_levelwidth * IndentFormatter.__get_level()) + c.log_levelendchar \
1166 + Formatter.format(self, record)
1167 finally:
1168 IndentFormatter.release()
1169 return r
1170
1171 @staticmethod
1173 """
1174 Increase indentation level.
1175 """
1176 ##dbg.fwriteln('IndentFormatter.lvlup') ##@
1177 IndentFormatter.acquire()
1178 try:
1179 IndentFormatter.__set_level(IndentFormatter.__get_level()+1)
1180 finally:
1181 IndentFormatter.release()
1182
1183 @staticmethod
1185 """
1186 Decrease indentation level.
1187 """
1188 ##dbg.fwriteln('IndentFormatter.lvldown') ##@
1189 IndentFormatter.acquire()
1190 try:
1191 IndentFormatter.__set_level(IndentFormatter.__get_level()-1)
1192 if IndentFormatter.__get_level() < 0:
1193 IndentFormatter.__set_level(0)
1194 finally:
1195 IndentFormatter.release()
1196
1197 @staticmethod
1199 """
1200 Reset indentation level to "0".
1201 """
1202 ##dbg.fwriteln('IndentFormatter.lvlreset') ##@
1203 IndentFormatter.acquire()
1204 try:
1205 IndentFormatter.__set_level(0)
1206 finally:
1207 IndentFormatter.release()
1208
1209 @staticmethod
1211 """
1212 Auto level decorator for functions.
1213
1214 Call L{lvlup}() befor function call and L{lvldown}() after
1215 wrapped function return.
1216 @param fun: Wrapped function.
1217 @type func
1218 """
1219 ##dbg.fwriteln('IndentFormatter.lvlwrap') ##@
1220 @wraps(fun)
1221 def wrapper(*args, **kwds):
1222 IndentFormatter.acquire()
1223 try:
1224 l=IndentFormatter.__get_level()
1225 IndentFormatter.lvlup()
1226 r = fun(*args, **kwds)
1227 ##IndentFormatter.lvldown()
1228 IndentFormatter.__set_level(l) # Defense from error
1229 finally:
1230 IndentFormatter.release()
1231 return r
1232 return wrapper
1233
1234 @staticmethod
1236 """
1237 Auto level decorator for functions.
1238
1239 Write first 'Call "fun.__name__"' using loginst.L{dbgtrace}().
1240 Also as L{lvlwrap}().
1241 If exception occurs then raise it.
1242 If level error tested then write '*** DBG LEVEL ERROR = different'
1243 where 'different' is level different.
1244 Write last 'Return from "fun.__name__"' using loginst.L{dbgtrace}().
1245
1246 @param fun: Wrapped function.
1247 @type func
1248 @param loginst: Logger instance to use for reporting.
1249 @type loginst
1250 """
1251 ##dbg.fwriteln('IndentFormatter.lvlwraplog') ##@
1252 @wraps(fun)
1253 def wrapper(*args, **kwds):
1254 ##dbg.fwriteln('IndentFormatter.lvlwraplog.wrapper') ##@
1255 IndentFormatter.acquire()
1256 c=__import__('XPyLIB')
1257 try:
1258 l=IndentFormatter.__get_level()
1259 loginst.dbgtrace('%s%s()' % (c.log_descfuncall,fun.__name__))
1260 IndentFormatter.lvlup()
1261 r = fun(*args, **kwds)
1262 IndentFormatter.lvldown()
1263 if IndentFormatter.__get_level()!=l:
1264 IndentFormatter.__set_level(l) # Defense from error
1265 loginst.dbgtrace('%s%d' % (c.log_levelerr, d))
1266 except Exception,e:
1267 IndentFormatter.__set_level(l)
1268 ##dbg.fwriteln('IndentFormatter.lvlwraplog.wrapper except ',e) ##@
1269 raise e
1270 finally:
1271 IndentFormatter.release()
1272 loginst.dbgtrace('%s%s()' % (c.log_descfunret,fun.__name__))
1273 return r
1274 return wrapper
1275
1276 # Initialize instance of Indent formatter.
1277 IndentFormatter()
1278
1281 """
1282 Base logging class fo xlogging.
1283
1284 After importing xlogging this class set as default class for new loggers.
1285 """
1286 _xBaseloggerClass.__init__(self, name, level)
1287
1289 """
1290 Log 'msg % args' with severity 'TRACE'.
1291
1292 To pass exception information, use the keyword argument exc_info with
1293 a true value, e.g.
1294
1295 logger.trace("Houston, we have a %s", "thorny problem", exc_info=1)
1296 """
1297 ##dbg.fwriteln('XLogger.trace') ##@
1298 _trace(self, msg, *args, **kwargs)
1299
1301 """
1302 Log 'msg % args' with severity 'DBGTRACE'.
1303
1304 To pass exception information, use the keyword argument exc_info with
1305 a true value, e.g.
1306
1307 logger.dbgtrace("Houston, we have a %s", "thorny problem", exc_info=1)
1308 """
1309 ##dbg.fwriteln('XLogger.dbgtrace') ##@
1310 _dbgtrace(self, msg, *args, **kwargs)
1311
1312
1313 # Set XLogger as base logger class.
1314 logging.setLoggerClass(XLogger)
1315
1316 # Additional module assigments.
1317 ##dbg.fwriteln('_self_module=', sys.modules[__name__]) ##@
1318
1319 # Additional fuctions for bound to logger class.
1320 ##@dbg.fwlevel ##@
1322 """
1323 Log 'msg % args' with severity 'TRACE'.
1324
1325 To pass exception information, use the keyword argument exc_info with
1326 a true value, e.g.
1327
1328 logger.trace("Houston, we have a %s", "thorny problem", exc_info=1)
1329 """
1330 ##dbg.fwriteln('_trace') ##@
1331 if self.manager.disable >= TRACE:
1332 return
1333 ##dbg.fwriteln('_trace ... %d>=%d'%(TRACE,self.getEffectiveLevel())) ##@
1334 if TRACE >= self.getEffectiveLevel():
1335 apply(self._log, (TRACE, msg, args), kwargs)
1336
1337 ##@dbg.fwlevel ##@
1339 """
1340 Log 'msg % args' with severity 'DBGTRACE'.
1341
1342 To pass exception information, use the keyword argument exc_info with
1343 a true value, e.g.
1344
1345 logger.dbgtrace("Houston, we have a %s", "thorny problem", exc_info=1)
1346 """
1347 ##dbg.fwriteln('_dbgtrace') ##@
1348 if self.manager.disable >= DBGTRACE:
1349 return
1350 ##dbg.fwriteln('_dbgtrace ... %d>=%d'%(DBGTRACE,self.getEffectiveLevel())) ##@
1351 if DBGTRACE >= self.getEffectiveLevel():
1352 apply(self._log, (DBGTRACE, msg, args), kwargs)
1353
1354 # Add if need trace and dbgtrace method to root logger.
1355 if not hasattr(root, 'tarce'):
1356 setattr(root, 'trace', XLogger.trace)
1357
1358 if not hasattr(root, 'dbgtarce'):
1359 setattr(root, 'dbgtrace', XLogger.dbgtrace)
1360
1361 ##@dbg.fwlevel ##@
1363 """
1364 Log a message with severity 'TRACE' on the root logger.
1365 """
1366 if len(root.handlers) == 0:
1367 basicConfig()
1368 apply(_trace, (root, msg,)+args, kwargs)
1369
1370 ##@dbg.fwlevel ##@
1372 """
1373 Log a message with severity 'DBGTRACE' on the root logger.
1374 """
1375 if len(root.handlers) == 0:
1376 basicConfig()
1377 apply(_dbgtrace, (root, msg,)+args, kwargs)
1378
1379
1380
1381
1382 # End Implemetation
1383
1384
1385
1386
1387 #-DEBUG-START-------------------------------------------------------------------
1388
1390 """
1391 """
1392 import XPyLIB
1393 import os
1394
1395 class _TestHandler(Handler):
1396 """
1397 Test handler that add at start message 'TestHandler emit:' and output it to
1398 sys.stderr.
1399 """
1400 def __init__(self, level=NOTSET):
1401 dbg.fwriteln('TestHandler.__init__') ##@
1402 Handler.__init__(self, level)
1403
1404 def emit(self, record):
1405 """
1406
1407 """
1408 dbg.fwriteln('TestHandler.emit') ##@
1409 import sys
1410 msg=self.format(record)
1411 sys.stderr.write('TestHandler emit: %s\n' % msg)
1412 pass
1413
1414 class _TestFilter(Filter):
1415 """
1416 Test filter that available only if msg starts with 'yes'
1417 """
1418 attr='NOT SET ATTR'
1419 def __init__(self, args='NO ARGS'):
1420 dbg.fwriteln('TestFilter.__init__() ', args) ##@
1421 Filter.__init__(self, '') # No name
1422
1423 def filter(self, record):
1424 """
1425 """
1426 dbg.fwriteln('TestFilter.filter msg="'+record.getMessage()[:5]+'..."') ##@
1427 dbg.fwriteln('TestFilter.filter attr=', self.attr) ##@
1428 return 'yes' == record.getMessage()[:3]
1429 pass
1430
1431 _debug.TestHandler=_TestHandler
1432 _debug.TestFilter=_TestFilter
1433 #root.setLevel(TRACE) do this throw .cfg.
1434 p=os.path.join(XPyLIB.dir_root,'XPyLIB','test','xlogging1.cfg')
1435 dbg.writeln('p=',p)
1436 applyConfigFile(p)
1437 A=getLogger('A')
1438 trace('test trace msg')
1439 dbgtrace('test dbgtrace msg MUST NOT print')
1440 A.trace('test A.trace msg')
1441 A.warning('test A.warning msg')
1442 AB=getLogger('A.B')
1443 AB.error('test A.B.error msg')
1444 AB.dbgtrace('!!!!!!test A.B.dbgtrace msg must NOT print')
1445 ABC=getLogger('A.B.C')
1446 ABC.dbgtrace('yes!!!!!!test A.B.C.dbgtrace msg must NOT print')
1447 ABC.trace('!!!!!!test A.B.C.trace msg must NOT print')
1448 ABC.trace('yes test A.B.C.trace msg')
1449
1450 p=os.path.join(XPyLIB.dir_root,'XPyLIB','test','xlogging2.cfg')
1451 dbg.writeln('p=',p)
1452 applyConfigFile(p)
1453 warning('test root warning msg')
1454 A.warning('test A warning msg')
1455 critical('test root critical msg')
1456 A.critical('test A critical msg')
1457
1458 B=getLogger('B')
1459 B.propagate=0
1460 B.setLevel(TRACE)
1461 hB=StreamHandler(sys.stderr)
1462 B.addHandler(hB)
1463 BF=getLogger('B.F')
1464 BG=getLogger('B.g')
1465 BH=getLogger('B.H')
1466 fFG=NamesFilter(['B.F','B.G'])
1467 #fFG=Filter('B.F')
1468 hB.addFilter(fFG)
1469 BF.trace('BF.trace')
1470 BH.trace('BH.trace MUST NOT OUT')
1471 BG.trace('BG.trace')
1472 pass
1473
1474 #-DEBUG-END---------------------------------------------------------------------
1475
1476 if __name__=='__main__':
1477 _debug()
1478
| Trees | Indices | Help |
|
|---|
| Generated by Epydoc 3.0beta1 on Mon Dec 1 23:43:16 2008 | http://epydoc.sourceforge.net |