debug.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. #
  2. # This file is part of pyasn1 software.
  3. #
  4. # Copyright (c) 2005-2020, Ilya Etingof <etingof@gmail.com>
  5. # License: https://pyasn1.readthedocs.io/en/latest/license.html
  6. #
  7. import logging
  8. import sys
  9. from pyasn1 import __version__
  10. from pyasn1 import error
  11. __all__ = ['Debug', 'setLogger', 'hexdump']
  12. DEBUG_NONE = 0x0000
  13. DEBUG_ENCODER = 0x0001
  14. DEBUG_DECODER = 0x0002
  15. DEBUG_ALL = 0xffff
  16. FLAG_MAP = {
  17. 'none': DEBUG_NONE,
  18. 'encoder': DEBUG_ENCODER,
  19. 'decoder': DEBUG_DECODER,
  20. 'all': DEBUG_ALL
  21. }
  22. LOGGEE_MAP = {}
  23. class Printer(object):
  24. # noinspection PyShadowingNames
  25. def __init__(self, logger=None, handler=None, formatter=None):
  26. if logger is None:
  27. logger = logging.getLogger('pyasn1')
  28. logger.setLevel(logging.DEBUG)
  29. if handler is None:
  30. handler = logging.StreamHandler()
  31. if formatter is None:
  32. formatter = logging.Formatter('%(asctime)s %(name)s: %(message)s')
  33. handler.setFormatter(formatter)
  34. handler.setLevel(logging.DEBUG)
  35. logger.addHandler(handler)
  36. self.__logger = logger
  37. def __call__(self, msg):
  38. self.__logger.debug(msg)
  39. def __str__(self):
  40. return '<python logging>'
  41. class Debug(object):
  42. defaultPrinter = Printer()
  43. def __init__(self, *flags, **options):
  44. self._flags = DEBUG_NONE
  45. if 'loggerName' in options:
  46. # route our logs to parent logger
  47. self._printer = Printer(
  48. logger=logging.getLogger(options['loggerName']),
  49. handler=logging.NullHandler()
  50. )
  51. elif 'printer' in options:
  52. self._printer = options.get('printer')
  53. else:
  54. self._printer = self.defaultPrinter
  55. self._printer('running pyasn1 %s, debug flags %s' % (__version__, ', '.join(flags)))
  56. for flag in flags:
  57. inverse = flag and flag[0] in ('!', '~')
  58. if inverse:
  59. flag = flag[1:]
  60. try:
  61. if inverse:
  62. self._flags &= ~FLAG_MAP[flag]
  63. else:
  64. self._flags |= FLAG_MAP[flag]
  65. except KeyError:
  66. raise error.PyAsn1Error('bad debug flag %s' % flag)
  67. self._printer("debug category '%s' %s" % (flag, inverse and 'disabled' or 'enabled'))
  68. def __str__(self):
  69. return 'logger %s, flags %x' % (self._printer, self._flags)
  70. def __call__(self, msg):
  71. self._printer(msg)
  72. def __and__(self, flag):
  73. return self._flags & flag
  74. def __rand__(self, flag):
  75. return flag & self._flags
  76. _LOG = DEBUG_NONE
  77. def setLogger(userLogger):
  78. global _LOG
  79. if userLogger:
  80. _LOG = userLogger
  81. else:
  82. _LOG = DEBUG_NONE
  83. # Update registered logging clients
  84. for module, (name, flags) in LOGGEE_MAP.items():
  85. setattr(module, name, _LOG & flags and _LOG or DEBUG_NONE)
  86. def registerLoggee(module, name='LOG', flags=DEBUG_NONE):
  87. LOGGEE_MAP[sys.modules[module]] = name, flags
  88. setLogger(_LOG)
  89. return _LOG
  90. def hexdump(octets):
  91. return ' '.join(
  92. ['%s%.2X' % (n % 16 == 0 and ('\n%.5d: ' % n) or '', x)
  93. for n, x in zip(range(len(octets)), octets)]
  94. )
  95. class Scope(object):
  96. def __init__(self):
  97. self._list = []
  98. def __str__(self): return '.'.join(self._list)
  99. def push(self, token):
  100. self._list.append(token)
  101. def pop(self):
  102. return self._list.pop()
  103. scope = Scope()