__init__.py 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. #
  2. # BitBake Build System Python Library
  3. #
  4. # Copyright (C) 2003 Holger Schurig
  5. # Copyright (C) 2003, 2004 Chris Larson
  6. #
  7. # Based on Gentoo's portage.py.
  8. #
  9. # SPDX-License-Identifier: GPL-2.0-only
  10. #
  11. __version__ = "1.47.0"
  12. import sys
  13. if sys.version_info < (3, 5, 0):
  14. raise RuntimeError("Sorry, python 3.5.0 or later is required for this version of bitbake")
  15. class BBHandledException(Exception):
  16. """
  17. The big dilemma for generic bitbake code is what information to give the user
  18. when an exception occurs. Any exception inheriting this base exception class
  19. has already provided information to the user via some 'fired' message type such as
  20. an explicitly fired event using bb.fire, or a bb.error message. If bitbake
  21. encounters an exception derived from this class, no backtrace or other information
  22. will be given to the user, its assumed the earlier event provided the relevant information.
  23. """
  24. pass
  25. import os
  26. import logging
  27. class NullHandler(logging.Handler):
  28. def emit(self, record):
  29. pass
  30. class BBLoggerMixin(object):
  31. def __init__(self, *args, **kwargs):
  32. # Does nothing to allow calling super() from derived classes
  33. pass
  34. def setup_bblogger(self, name):
  35. if name.split(".")[0] == "BitBake":
  36. self.debug = self.bbdebug
  37. def bbdebug(self, level, msg, *args, **kwargs):
  38. loglevel = logging.DEBUG - level + 1
  39. if not bb.event.worker_pid:
  40. if self.name in bb.msg.loggerDefaultDomains and loglevel > (bb.msg.loggerDefaultDomains[self.name]):
  41. return
  42. if loglevel > bb.msg.loggerDefaultLogLevel:
  43. return
  44. return self.log(loglevel, msg, *args, **kwargs)
  45. def plain(self, msg, *args, **kwargs):
  46. return self.log(logging.INFO + 1, msg, *args, **kwargs)
  47. def verbose(self, msg, *args, **kwargs):
  48. return self.log(logging.INFO - 1, msg, *args, **kwargs)
  49. def verbnote(self, msg, *args, **kwargs):
  50. return self.log(logging.INFO + 2, msg, *args, **kwargs)
  51. Logger = logging.getLoggerClass()
  52. class BBLogger(Logger, BBLoggerMixin):
  53. def __init__(self, name, *args, **kwargs):
  54. self.setup_bblogger(name)
  55. super().__init__(name, *args, **kwargs)
  56. logging.raiseExceptions = False
  57. logging.setLoggerClass(BBLogger)
  58. class BBLoggerAdapter(logging.LoggerAdapter, BBLoggerMixin):
  59. def __init__(self, logger, *args, **kwargs):
  60. self.setup_bblogger(logger.name)
  61. super().__init__(logger, *args, **kwargs)
  62. if sys.version_info < (3, 6):
  63. # These properties were added in Python 3.6. Add them in older versions
  64. # for compatibility
  65. @property
  66. def manager(self):
  67. return self.logger.manager
  68. @manager.setter
  69. def manager(self, value):
  70. self.logger.manager = value
  71. @property
  72. def name(self):
  73. return self.logger.name
  74. def __repr__(self):
  75. logger = self.logger
  76. level = logger.getLevelName(logger.getEffectiveLevel())
  77. return '<%s %s (%s)>' % (self.__class__.__name__, logger.name, level)
  78. logging.LoggerAdapter = BBLoggerAdapter
  79. logger = logging.getLogger("BitBake")
  80. logger.addHandler(NullHandler())
  81. logger.setLevel(logging.DEBUG - 2)
  82. mainlogger = logging.getLogger("BitBake.Main")
  83. class PrefixLoggerAdapter(logging.LoggerAdapter):
  84. def __init__(self, prefix, logger):
  85. super().__init__(logger, {})
  86. self.__msg_prefix = prefix
  87. def process(self, msg, kwargs):
  88. return "%s%s" %(self.__msg_prefix, msg), kwargs
  89. # This has to be imported after the setLoggerClass, as the import of bb.msg
  90. # can result in construction of the various loggers.
  91. import bb.msg
  92. from bb import fetch2 as fetch
  93. sys.modules['bb.fetch'] = sys.modules['bb.fetch2']
  94. # Messaging convenience functions
  95. def plain(*args):
  96. mainlogger.plain(''.join(args))
  97. def debug(lvl, *args):
  98. if isinstance(lvl, str):
  99. mainlogger.warning("Passed invalid debug level '%s' to bb.debug", lvl)
  100. args = (lvl,) + args
  101. lvl = 1
  102. mainlogger.debug(lvl, ''.join(args))
  103. def note(*args):
  104. mainlogger.info(''.join(args))
  105. #
  106. # A higher prioity note which will show on the console but isn't a warning
  107. #
  108. # Something is happening the user should be aware of but they probably did
  109. # something to make it happen
  110. #
  111. def verbnote(*args):
  112. mainlogger.verbnote(''.join(args))
  113. #
  114. # Warnings - things the user likely needs to pay attention to and fix
  115. #
  116. def warn(*args):
  117. mainlogger.warning(''.join(args))
  118. def error(*args, **kwargs):
  119. mainlogger.error(''.join(args), extra=kwargs)
  120. def fatal(*args, **kwargs):
  121. mainlogger.critical(''.join(args), extra=kwargs)
  122. raise BBHandledException()
  123. def deprecated(func, name=None, advice=""):
  124. """This is a decorator which can be used to mark functions
  125. as deprecated. It will result in a warning being emitted
  126. when the function is used."""
  127. import warnings
  128. if advice:
  129. advice = ": %s" % advice
  130. if name is None:
  131. name = func.__name__
  132. def newFunc(*args, **kwargs):
  133. warnings.warn("Call to deprecated function %s%s." % (name,
  134. advice),
  135. category=DeprecationWarning,
  136. stacklevel=2)
  137. return func(*args, **kwargs)
  138. newFunc.__name__ = func.__name__
  139. newFunc.__doc__ = func.__doc__
  140. newFunc.__dict__.update(func.__dict__)
  141. return newFunc
  142. # For compatibility
  143. def deprecate_import(current, modulename, fromlist, renames = None):
  144. """Import objects from one module into another, wrapping them with a DeprecationWarning"""
  145. import sys
  146. module = __import__(modulename, fromlist = fromlist)
  147. for position, objname in enumerate(fromlist):
  148. obj = getattr(module, objname)
  149. newobj = deprecated(obj, "{0}.{1}".format(current, objname),
  150. "Please use {0}.{1} instead".format(modulename, objname))
  151. if renames:
  152. newname = renames[position]
  153. else:
  154. newname = objname
  155. setattr(sys.modules[current], newname, newobj)