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