1# ex:ts=4:sw=4:sts=4:et 2# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- 3# 4# BitBake Build System Python Library 5# 6# Copyright (C) 2003 Holger Schurig 7# Copyright (C) 2003, 2004 Chris Larson 8# 9# Based on Gentoo's portage.py. 10# 11# This program is free software; you can redistribute it and/or modify 12# it under the terms of the GNU General Public License version 2 as 13# published by the Free Software Foundation. 14# 15# This program is distributed in the hope that it will be useful, 16# but WITHOUT ANY WARRANTY; without even the implied warranty of 17# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18# GNU General Public License for more details. 19# 20# You should have received a copy of the GNU General Public License along 21# with this program; if not, write to the Free Software Foundation, Inc., 22# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 23 24__version__ = "1.40.0" 25 26import sys 27if sys.version_info < (3, 4, 0): 28 raise RuntimeError("Sorry, python 3.4.0 or later is required for this version of bitbake") 29 30 31class BBHandledException(Exception): 32 """ 33 The big dilemma for generic bitbake code is what information to give the user 34 when an exception occurs. Any exception inheriting this base exception class 35 has already provided information to the user via some 'fired' message type such as 36 an explicitly fired event using bb.fire, or a bb.error message. If bitbake 37 encounters an exception derived from this class, no backtrace or other information 38 will be given to the user, its assumed the earlier event provided the relevant information. 39 """ 40 pass 41 42import os 43import logging 44 45 46class NullHandler(logging.Handler): 47 def emit(self, record): 48 pass 49 50Logger = logging.getLoggerClass() 51class BBLogger(Logger): 52 def __init__(self, name): 53 if name.split(".")[0] == "BitBake": 54 self.debug = self.bbdebug 55 Logger.__init__(self, name) 56 57 def bbdebug(self, level, msg, *args, **kwargs): 58 return self.log(logging.DEBUG - level + 1, msg, *args, **kwargs) 59 60 def plain(self, msg, *args, **kwargs): 61 return self.log(logging.INFO + 1, msg, *args, **kwargs) 62 63 def verbose(self, msg, *args, **kwargs): 64 return self.log(logging.INFO - 1, msg, *args, **kwargs) 65 66 def verbnote(self, msg, *args, **kwargs): 67 return self.log(logging.INFO + 2, msg, *args, **kwargs) 68 69 70logging.raiseExceptions = False 71logging.setLoggerClass(BBLogger) 72 73logger = logging.getLogger("BitBake") 74logger.addHandler(NullHandler()) 75logger.setLevel(logging.DEBUG - 2) 76 77mainlogger = logging.getLogger("BitBake.Main") 78 79# This has to be imported after the setLoggerClass, as the import of bb.msg 80# can result in construction of the various loggers. 81import bb.msg 82 83from bb import fetch2 as fetch 84sys.modules['bb.fetch'] = sys.modules['bb.fetch2'] 85 86# Messaging convenience functions 87def plain(*args): 88 mainlogger.plain(''.join(args)) 89 90def debug(lvl, *args): 91 if isinstance(lvl, str): 92 mainlogger.warning("Passed invalid debug level '%s' to bb.debug", lvl) 93 args = (lvl,) + args 94 lvl = 1 95 mainlogger.debug(lvl, ''.join(args)) 96 97def note(*args): 98 mainlogger.info(''.join(args)) 99 100# 101# A higher prioity note which will show on the console but isn't a warning 102# 103# Something is happening the user should be aware of but they probably did 104# something to make it happen 105# 106def verbnote(*args): 107 mainlogger.verbnote(''.join(args)) 108 109# 110# Warnings - things the user likely needs to pay attention to and fix 111# 112def warn(*args): 113 mainlogger.warning(''.join(args)) 114 115def error(*args, **kwargs): 116 mainlogger.error(''.join(args), extra=kwargs) 117 118def fatal(*args, **kwargs): 119 mainlogger.critical(''.join(args), extra=kwargs) 120 raise BBHandledException() 121 122def deprecated(func, name=None, advice=""): 123 """This is a decorator which can be used to mark functions 124 as deprecated. It will result in a warning being emitted 125 when the function is used.""" 126 import warnings 127 128 if advice: 129 advice = ": %s" % advice 130 if name is None: 131 name = func.__name__ 132 133 def newFunc(*args, **kwargs): 134 warnings.warn("Call to deprecated function %s%s." % (name, 135 advice), 136 category=DeprecationWarning, 137 stacklevel=2) 138 return func(*args, **kwargs) 139 newFunc.__name__ = func.__name__ 140 newFunc.__doc__ = func.__doc__ 141 newFunc.__dict__.update(func.__dict__) 142 return newFunc 143 144# For compatibility 145def deprecate_import(current, modulename, fromlist, renames = None): 146 """Import objects from one module into another, wrapping them with a DeprecationWarning""" 147 import sys 148 149 module = __import__(modulename, fromlist = fromlist) 150 for position, objname in enumerate(fromlist): 151 obj = getattr(module, objname) 152 newobj = deprecated(obj, "{0}.{1}".format(current, objname), 153 "Please use {0}.{1} instead".format(modulename, objname)) 154 if renames: 155 newname = renames[position] 156 else: 157 newname = objname 158 159 setattr(sys.modules[current], newname, newobj) 160 161