utils.py 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. # ex:ts=4:sw=4:sts=4:et
  2. # -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
  3. """
  4. BitBake Utility Functions
  5. """
  6. # Copyright (C) 2004 Michael Lauer
  7. #
  8. # This program is free software; you can redistribute it and/or modify
  9. # it under the terms of the GNU General Public License version 2 as
  10. # published by the Free Software Foundation.
  11. #
  12. # This program is distributed in the hope that it will be useful,
  13. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. # GNU General Public License for more details.
  16. #
  17. # You should have received a copy of the GNU General Public License along
  18. # with this program; if not, write to the Free Software Foundation, Inc.,
  19. # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  20. digits = "0123456789"
  21. ascii_letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
  22. import re
  23. def explode_version(s):
  24. r = []
  25. alpha_regexp = re.compile('^([a-zA-Z]+)(.*)$')
  26. numeric_regexp = re.compile('^(\d+)(.*)$')
  27. while (s != ''):
  28. if s[0] in digits:
  29. m = numeric_regexp.match(s)
  30. r.append(int(m.group(1)))
  31. s = m.group(2)
  32. continue
  33. if s[0] in ascii_letters:
  34. m = alpha_regexp.match(s)
  35. r.append(m.group(1))
  36. s = m.group(2)
  37. continue
  38. s = s[1:]
  39. return r
  40. def vercmp_part(a, b):
  41. va = explode_version(a)
  42. vb = explode_version(b)
  43. while True:
  44. if va == []:
  45. ca = None
  46. else:
  47. ca = va.pop(0)
  48. if vb == []:
  49. cb = None
  50. else:
  51. cb = vb.pop(0)
  52. if ca == None and cb == None:
  53. return 0
  54. if ca > cb:
  55. return 1
  56. if ca < cb:
  57. return -1
  58. def vercmp(ta, tb):
  59. (va, ra) = ta
  60. (vb, rb) = tb
  61. r = vercmp_part(va, vb)
  62. if (r == 0):
  63. r = vercmp_part(ra, rb)
  64. return r
  65. def explode_deps(s):
  66. """
  67. Take an RDEPENDS style string of format:
  68. "DEPEND1 (optional version) DEPEND2 (optional version) ..."
  69. and return a list of dependencies.
  70. Version information is ignored.
  71. """
  72. r = []
  73. l = s.split()
  74. flag = False
  75. for i in l:
  76. if i[0] == '(':
  77. flag = True
  78. j = []
  79. if flag:
  80. j.append(i)
  81. else:
  82. r.append(i)
  83. if flag and i.endswith(')'):
  84. flag = False
  85. # Ignore version
  86. #r[-1] += ' ' + ' '.join(j)
  87. return r
  88. def _print_trace(body, line):
  89. """
  90. Print the Environment of a Text Body
  91. """
  92. import bb
  93. # print the environment of the method
  94. bb.msg.error(bb.msg.domain.Util, "Printing the environment of the function")
  95. min_line = max(1,line-4)
  96. max_line = min(line+4,len(body)-1)
  97. for i in range(min_line,max_line+1):
  98. bb.msg.error(bb.msg.domain.Util, "\t%.4d:%s" % (i, body[i-1]) )
  99. def better_compile(text, file, realfile):
  100. """
  101. A better compile method. This method
  102. will print the offending lines.
  103. """
  104. try:
  105. return compile(text, file, "exec")
  106. except Exception, e:
  107. import bb,sys
  108. # split the text into lines again
  109. body = text.split('\n')
  110. bb.msg.error(bb.msg.domain.Util, "Error in compiling: ", realfile)
  111. bb.msg.error(bb.msg.domain.Util, "The lines resulting into this error were:")
  112. bb.msg.error(bb.msg.domain.Util, "\t%d:%s:'%s'" % (e.lineno, e.__class__.__name__, body[e.lineno-1]))
  113. _print_trace(body, e.lineno)
  114. # exit now
  115. sys.exit(1)
  116. def better_exec(code, context, text, realfile):
  117. """
  118. Similiar to better_compile, better_exec will
  119. print the lines that are responsible for the
  120. error.
  121. """
  122. import bb,sys
  123. try:
  124. exec code in context
  125. except:
  126. (t,value,tb) = sys.exc_info()
  127. if t in [bb.parse.SkipPackage, bb.build.FuncFailed]:
  128. raise
  129. # print the Header of the Error Message
  130. bb.msg.error(bb.msg.domain.Util, "Error in executing: ", realfile)
  131. bb.msg.error(bb.msg.domain.Util, "Exception:%s Message:%s" % (t,value) )
  132. # let us find the line number now
  133. while tb.tb_next:
  134. tb = tb.tb_next
  135. import traceback
  136. line = traceback.tb_lineno(tb)
  137. _print_trace( text.split('\n'), line )
  138. raise
  139. def Enum(*names):
  140. """
  141. A simple class to give Enum support
  142. """
  143. assert names, "Empty enums are not supported"
  144. class EnumClass(object):
  145. __slots__ = names
  146. def __iter__(self): return iter(constants)
  147. def __len__(self): return len(constants)
  148. def __getitem__(self, i): return constants[i]
  149. def __repr__(self): return 'Enum' + str(names)
  150. def __str__(self): return 'enum ' + str(constants)
  151. class EnumValue(object):
  152. __slots__ = ('__value')
  153. def __init__(self, value): self.__value = value
  154. Value = property(lambda self: self.__value)
  155. EnumType = property(lambda self: EnumType)
  156. def __hash__(self): return hash(self.__value)
  157. def __cmp__(self, other):
  158. # C fans might want to remove the following assertion
  159. # to make all enums comparable by ordinal value {;))
  160. assert self.EnumType is other.EnumType, "Only values from the same enum are comparable"
  161. return cmp(self.__value, other.__value)
  162. def __invert__(self): return constants[maximum - self.__value]
  163. def __nonzero__(self): return bool(self.__value)
  164. def __repr__(self): return str(names[self.__value])
  165. maximum = len(names) - 1
  166. constants = [None] * len(names)
  167. for i, each in enumerate(names):
  168. val = EnumValue(i)
  169. setattr(EnumClass, each, val)
  170. constants[i] = val
  171. constants = tuple(constants)
  172. EnumType = EnumClass()
  173. return EnumType