diff options
| author | Richard Purdie <richard@openedhand.com> | 2008-09-30 15:08:33 +0000 | 
|---|---|---|
| committer | Richard Purdie <richard@openedhand.com> | 2008-09-30 15:08:33 +0000 | 
| commit | c30eddb243e7e65f67f656e62848a033cf6f2e5c (patch) | |
| tree | 110dd95788b76f55d31cb8d30aac2de8400b6f4a /bitbake-dev/lib/bb/utils.py | |
| parent | 5ef0510474004eeb2ae8a99b64e2febb1920e077 (diff) | |
| download | openembedded-core-c30eddb243e7e65f67f656e62848a033cf6f2e5c.tar.gz openembedded-core-c30eddb243e7e65f67f656e62848a033cf6f2e5c.tar.bz2 openembedded-core-c30eddb243e7e65f67f656e62848a033cf6f2e5c.zip | |
Add bitbake-dev to allow ease of testing and development of bitbake trunk
git-svn-id: https://svn.o-hand.com/repos/poky/trunk@5337 311d38ba-8fff-0310-9ca6-ca027cbcb966
Diffstat (limited to 'bitbake-dev/lib/bb/utils.py')
| -rw-r--r-- | bitbake-dev/lib/bb/utils.py | 270 | 
1 files changed, 270 insertions, 0 deletions
| diff --git a/bitbake-dev/lib/bb/utils.py b/bitbake-dev/lib/bb/utils.py new file mode 100644 index 0000000000..17e22e389e --- /dev/null +++ b/bitbake-dev/lib/bb/utils.py @@ -0,0 +1,270 @@ +# ex:ts=4:sw=4:sts=4:et +# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- +""" +BitBake Utility Functions +""" + +# Copyright (C) 2004 Michael Lauer +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +digits = "0123456789" +ascii_letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" + +import re, fcntl, os + +def explode_version(s): +    r = [] +    alpha_regexp = re.compile('^([a-zA-Z]+)(.*)$') +    numeric_regexp = re.compile('^(\d+)(.*)$') +    while (s != ''): +        if s[0] in digits: +            m = numeric_regexp.match(s) +            r.append(int(m.group(1))) +            s = m.group(2) +            continue +        if s[0] in ascii_letters: +            m = alpha_regexp.match(s) +            r.append(m.group(1)) +            s = m.group(2) +            continue +        s = s[1:] +    return r + +def vercmp_part(a, b): +    va = explode_version(a) +    vb = explode_version(b) +    while True: +        if va == []: +            ca = None +        else: +            ca = va.pop(0) +        if vb == []: +            cb = None +        else: +            cb = vb.pop(0) +        if ca == None and cb == None: +            return 0 +        if ca > cb: +            return 1 +        if ca < cb: +            return -1 + +def vercmp(ta, tb): +    (ea, va, ra) = ta +    (eb, vb, rb) = tb + +    r = int(ea)-int(eb) +    if (r == 0): +        r = vercmp_part(va, vb) +    if (r == 0): +        r = vercmp_part(ra, rb) +    return r + +def explode_deps(s): +    """ +    Take an RDEPENDS style string of format: +    "DEPEND1 (optional version) DEPEND2 (optional version) ..." +    and return a list of dependencies. +    Version information is ignored. +    """ +    r = [] +    l = s.split() +    flag = False +    for i in l: +        if i[0] == '(': +            flag = True +            #j = [] +        if not flag: +            r.append(i) +        #else: +        #    j.append(i) +        if flag and i.endswith(')'): +            flag = False +            # Ignore version +            #r[-1] += ' ' + ' '.join(j) +    return r + + + +def _print_trace(body, line): +    """ +    Print the Environment of a Text Body +    """ +    import bb + +    # print the environment of the method +    bb.msg.error(bb.msg.domain.Util, "Printing the environment of the function") +    min_line = max(1,line-4) +    max_line = min(line+4,len(body)-1) +    for i in range(min_line,max_line+1): +        bb.msg.error(bb.msg.domain.Util, "\t%.4d:%s" % (i, body[i-1]) ) + + +def better_compile(text, file, realfile): +    """ +    A better compile method. This method +    will print  the offending lines. +    """ +    try: +        return compile(text, file, "exec") +    except Exception, e: +        import bb,sys + +        # split the text into lines again +        body = text.split('\n') +        bb.msg.error(bb.msg.domain.Util, "Error in compiling python function in: ", realfile) +        bb.msg.error(bb.msg.domain.Util, "The lines resulting into this error were:") +        bb.msg.error(bb.msg.domain.Util, "\t%d:%s:'%s'" % (e.lineno, e.__class__.__name__, body[e.lineno-1])) + +        _print_trace(body, e.lineno) + +        # exit now +        sys.exit(1) + +def better_exec(code, context, text, realfile): +    """ +    Similiar to better_compile, better_exec will +    print the lines that are responsible for the +    error. +    """ +    import bb,sys +    try: +        exec code in context +    except: +        (t,value,tb) = sys.exc_info() + +        if t in [bb.parse.SkipPackage, bb.build.FuncFailed]: +            raise + +        # print the Header of the Error Message +        bb.msg.error(bb.msg.domain.Util, "Error in executing python function in: ", realfile) +        bb.msg.error(bb.msg.domain.Util, "Exception:%s Message:%s" % (t,value) ) + +        # let us find the line number now +        while tb.tb_next: +            tb = tb.tb_next + +        import traceback +        line = traceback.tb_lineno(tb) + +        _print_trace( text.split('\n'), line ) +         +        raise + +def Enum(*names): +   """ +   A simple class to give Enum support +   """ + +   assert names, "Empty enums are not supported" + +   class EnumClass(object): +      __slots__ = names +      def __iter__(self):        return iter(constants) +      def __len__(self):         return len(constants) +      def __getitem__(self, i):  return constants[i] +      def __repr__(self):        return 'Enum' + str(names) +      def __str__(self):         return 'enum ' + str(constants) + +   class EnumValue(object): +      __slots__ = ('__value') +      def __init__(self, value): self.__value = value +      Value = property(lambda self: self.__value) +      EnumType = property(lambda self: EnumType) +      def __hash__(self):        return hash(self.__value) +      def __cmp__(self, other): +         # C fans might want to remove the following assertion +         # to make all enums comparable by ordinal value {;)) +         assert self.EnumType is other.EnumType, "Only values from the same enum are comparable" +         return cmp(self.__value, other.__value) +      def __invert__(self):      return constants[maximum - self.__value] +      def __nonzero__(self):     return bool(self.__value) +      def __repr__(self):        return str(names[self.__value]) + +   maximum = len(names) - 1 +   constants = [None] * len(names) +   for i, each in enumerate(names): +      val = EnumValue(i) +      setattr(EnumClass, each, val) +      constants[i] = val +   constants = tuple(constants) +   EnumType = EnumClass() +   return EnumType + +def lockfile(name): +    """ +    Use the file fn as a lock file, return when the lock has been acquired. +    Returns a variable to pass to unlockfile(). +    """ +    while True: +        # If we leave the lockfiles lying around there is no problem +        # but we should clean up after ourselves. This gives potential +        # for races though. To work around this, when we acquire the lock  +        # we check the file we locked was still the lock file on disk.  +        # by comparing inode numbers. If they don't match or the lockfile  +        # no longer exists, we start again. + +        # This implementation is unfair since the last person to request the  +        # lock is the most likely to win it. + +        lf = open(name, "a+") +        fcntl.flock(lf.fileno(), fcntl.LOCK_EX) +        statinfo = os.fstat(lf.fileno()) +        if os.path.exists(lf.name): +           statinfo2 = os.stat(lf.name) +           if statinfo.st_ino == statinfo2.st_ino: +               return lf +        # File no longer exists or changed, retry +        lf.close + +def unlockfile(lf): +    """ +    Unlock a file locked using lockfile()				 +    """ +    os.unlink(lf.name) +    fcntl.flock(lf.fileno(), fcntl.LOCK_UN) +    lf.close + +def md5_file(filename): +    """ +    Return the hex string representation of the MD5 checksum of filename. +    """ +    try: +        import hashlib +        m = hashlib.md5() +    except ImportError: +        import md5 +        m = md5.new() +     +    for line in open(filename): +        m.update(line) +    return m.hexdigest() + +def sha256_file(filename): +    """ +    Return the hex string representation of the 256-bit SHA checksum of +    filename.  On Python 2.4 this will return None, so callers will need to +    handle that by either skipping SHA checks, or running a standalone sha256sum +    binary. +    """ +    try: +        import hashlib +    except ImportError: +        return None + +    s = hashlib.sha256() +    for line in open(filename): +        s.update(line) +    return s.hexdigest() | 
