xref: /openbmc/openbmc/poky/bitbake/lib/bb/__init__.py (revision 1a4b7ee2)
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