blob: b96466e654c960ea4b0fef8cccf3d39796465fc5 [file] [log] [blame]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001#
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#
Brad Bishopc342db32019-05-15 21:57:59 -04009# SPDX-License-Identifier: GPL-2.0-only
Patrick Williamsc124f4f2015-09-15 14:41:29 -050010#
Patrick Williamsc124f4f2015-09-15 14:41:29 -050011
Andrew Geissler82c905d2020-04-13 13:39:40 -050012__version__ = "1.46.0"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050013
14import sys
Andrew Geissler82c905d2020-04-13 13:39:40 -050015if sys.version_info < (3, 5, 0):
16 raise RuntimeError("Sorry, python 3.5.0 or later is required for this version of bitbake")
Patrick Williamsc124f4f2015-09-15 14:41:29 -050017
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
38Logger = logging.getLoggerClass()
39class BBLogger(Logger):
40 def __init__(self, name):
41 if name.split(".")[0] == "BitBake":
42 self.debug = self.bbdebug
43 Logger.__init__(self, name)
44
45 def bbdebug(self, level, msg, *args, **kwargs):
Andrew Geissler82c905d2020-04-13 13:39:40 -050046 loglevel = logging.DEBUG - level + 1
47 if not bb.event.worker_pid:
48 if self.name in bb.msg.loggerDefaultDomains and loglevel > (bb.msg.loggerDefaultDomains[self.name]):
49 return
50 if loglevel > bb.msg.loggerDefaultLogLevel:
51 return
52 return self.log(loglevel, msg, *args, **kwargs)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050053
54 def plain(self, msg, *args, **kwargs):
55 return self.log(logging.INFO + 1, msg, *args, **kwargs)
56
57 def verbose(self, msg, *args, **kwargs):
58 return self.log(logging.INFO - 1, msg, *args, **kwargs)
59
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080060 def verbnote(self, msg, *args, **kwargs):
61 return self.log(logging.INFO + 2, msg, *args, **kwargs)
62
63
Patrick Williamsc124f4f2015-09-15 14:41:29 -050064logging.raiseExceptions = False
65logging.setLoggerClass(BBLogger)
66
67logger = logging.getLogger("BitBake")
68logger.addHandler(NullHandler())
69logger.setLevel(logging.DEBUG - 2)
70
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050071mainlogger = logging.getLogger("BitBake.Main")
72
Patrick Williamsc124f4f2015-09-15 14:41:29 -050073# This has to be imported after the setLoggerClass, as the import of bb.msg
74# can result in construction of the various loggers.
75import bb.msg
76
77from bb import fetch2 as fetch
78sys.modules['bb.fetch'] = sys.modules['bb.fetch2']
79
80# Messaging convenience functions
81def plain(*args):
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050082 mainlogger.plain(''.join(args))
Patrick Williamsc124f4f2015-09-15 14:41:29 -050083
84def debug(lvl, *args):
Patrick Williamsc0f7c042017-02-23 20:41:17 -060085 if isinstance(lvl, str):
86 mainlogger.warning("Passed invalid debug level '%s' to bb.debug", lvl)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050087 args = (lvl,) + args
88 lvl = 1
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050089 mainlogger.debug(lvl, ''.join(args))
Patrick Williamsc124f4f2015-09-15 14:41:29 -050090
91def note(*args):
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050092 mainlogger.info(''.join(args))
Patrick Williamsc124f4f2015-09-15 14:41:29 -050093
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080094#
95# A higher prioity note which will show on the console but isn't a warning
96#
97# Something is happening the user should be aware of but they probably did
98# something to make it happen
99#
100def verbnote(*args):
101 mainlogger.verbnote(''.join(args))
102
103#
104# Warnings - things the user likely needs to pay attention to and fix
105#
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500106def warn(*args):
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600107 mainlogger.warning(''.join(args))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500108
109def error(*args, **kwargs):
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500110 mainlogger.error(''.join(args), extra=kwargs)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500111
112def fatal(*args, **kwargs):
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500113 mainlogger.critical(''.join(args), extra=kwargs)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500114 raise BBHandledException()
115
116def deprecated(func, name=None, advice=""):
117 """This is a decorator which can be used to mark functions
118 as deprecated. It will result in a warning being emitted
119 when the function is used."""
120 import warnings
121
122 if advice:
123 advice = ": %s" % advice
124 if name is None:
125 name = func.__name__
126
127 def newFunc(*args, **kwargs):
128 warnings.warn("Call to deprecated function %s%s." % (name,
129 advice),
130 category=DeprecationWarning,
131 stacklevel=2)
132 return func(*args, **kwargs)
133 newFunc.__name__ = func.__name__
134 newFunc.__doc__ = func.__doc__
135 newFunc.__dict__.update(func.__dict__)
136 return newFunc
137
138# For compatibility
139def deprecate_import(current, modulename, fromlist, renames = None):
140 """Import objects from one module into another, wrapping them with a DeprecationWarning"""
141 import sys
142
143 module = __import__(modulename, fromlist = fromlist)
144 for position, objname in enumerate(fromlist):
145 obj = getattr(module, objname)
146 newobj = deprecated(obj, "{0}.{1}".format(current, objname),
147 "Please use {0}.{1} instead".format(modulename, objname))
148 if renames:
149 newname = renames[position]
150 else:
151 newname = objname
152
153 setattr(sys.modules[current], newname, newobj)
154