1#
2# This file is part of pysmi software.
3#
4# Copyright (c) 2015-2019, Ilya Etingof <etingof@gmail.com>
5# License: http://snmplabs.com/pysmi/license.html
6#
7import logging
8from pysmi import error
9from pysmi import __version__
10
11flagNone = 0x0000
12flagSearcher = 0x0001
13flagReader = 0x0002
14flagLexer = 0x0004
15flagParser = 0x0008
16flagGrammar = 0x0010
17flagCodegen = 0x0020
18flagWriter = 0x0040
19flagCompiler = 0x0080
20flagBorrower = 0x0100
21flagAll = 0xffff
22
23flagMap = {
24    'searcher': flagSearcher,
25    'reader': flagReader,
26    'lexer': flagLexer,
27    'parser': flagParser,
28    'grammar': flagGrammar,
29    'codegen': flagCodegen,
30    'writer': flagWriter,
31    'compiler': flagCompiler,
32    'borrower': flagBorrower,
33    'all': flagAll
34}
35
36
37class Printer(object):
38    def __init__(self, logger=None, handler=None, formatter=None):
39        if logger is None:
40            logger = logging.getLogger('pysmi')
41
42        logger.setLevel(logging.DEBUG)
43
44        if handler is None:
45            handler = logging.StreamHandler()
46
47        if formatter is None:
48            formatter = logging.Formatter('%(asctime)s %(name)s: %(message)s')
49
50        handler.setFormatter(formatter)
51        handler.setLevel(logging.DEBUG)
52
53        logger.addHandler(handler)
54
55        self.__logger = logger
56
57    def __call__(self, msg):
58        self.__logger.debug(msg)
59
60    def __str__(self):
61        return '<python built-in logging>'
62
63    def getCurrentLogger(self):
64        return self.__logger
65
66
67if hasattr(logging, 'NullHandler'):
68    NullHandler = logging.NullHandler
69else:
70    # Python 2.6 and older
71    class NullHandler(logging.Handler):
72        def emit(self, record):
73            pass
74
75
76class Debug(object):
77    defaultPrinter = None
78
79    def __init__(self, *flags, **options):
80        self._flags = flagNone
81        if options.get('printer') is not None:
82            self._printer = options.get('printer')
83
84        elif self.defaultPrinter is not None:
85            self._printer = self.defaultPrinter
86
87        else:
88            if 'loggerName' in options:
89                # route our logs to parent logger
90                self._printer = Printer(
91                    logger=logging.getLogger(options['loggerName']),
92                    handler=NullHandler()
93                )
94            else:
95                self._printer = Printer()
96
97        self('running pysmi version %s' % __version__)
98
99        for flag in flags:
100            inverse = flag and flag[0] in ('!', '~')
101
102            if inverse:
103                flag = flag[1:]
104
105            try:
106                if inverse:
107                    self._flags &= ~flagMap[flag]
108                else:
109                    self._flags |= flagMap[flag]
110
111            except KeyError:
112                raise error.PySmiError('bad debug flag %s' % flag)
113
114            self('debug category \'%s\' %s' % (flag, inverse and 'disabled' or 'enabled'))
115
116    def __str__(self):
117        return 'logger %s, flags %x' % (self._printer, self._flags)
118
119    def __call__(self, msg):
120        self._printer(msg)
121
122    def __and__(self, flag):
123        return self._flags & flag
124
125    def __rand__(self, flag):
126        return flag & self._flags
127
128    def getCurrentPrinter(self):
129        return self._printer
130
131    def getCurrentLogger(self):
132        return self._printer and self._printer.getCurrentLogger() or None
133
134
135# This will yield false from bitwise and with a flag, and save
136# on unnecessary calls
137logger = 0
138
139
140def setLogger(l):
141    global logger
142    logger = l
143