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