2 # ex:ts=4:sw=4:sts=4:et
3 # -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
5 BitBake 'Data' implementations
7 Functions for interacting with the data structure used by the
10 Copyright (C) 2003, 2004 Chris Larson
11 Copyright (C) 2005 Holger Hans Peter Freyther
13 This program is free software; you can redistribute it and/or modify it under
14 the terms of the GNU General Public License as published by the Free Software
15 Foundation; either version 2 of the License, or (at your option) any later
18 This program is distributed in the hope that it will be useful, but WITHOUT
19 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
20 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License along with
23 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
24 Place, Suite 330, Boston, MA 02111-1307 USA.
26 Based on functions from the base bb module, Copyright 2003 Holger Schurig
29 import sys, os, re, time, types
30 if sys.argv[0][-5:] == "pydoc":
31 path = os.path.dirname(os.path.dirname(sys.argv[1]))
33 path = os.path.dirname(os.path.dirname(sys.argv[0]))
36 from bb import note, debug, data_smart
38 _dict_type = data_smart.DataSmart
39 _dict_p_type = data_smart.DataSmartPackage
43 Databacked Dictionary implementation
45 def __init__(self, cache_dir):
46 self.cache_dir = cache_dir
49 def has_key(self,key):
50 return key in self.files
55 def __setitem__(self, key, data):
57 Add the key to the list of known files and
58 place the data in the cache?
63 self.files.append(key)
65 def __getitem__(self, key):
66 if not key in self.files:
70 return _dict_p_type(self.cache_dir, key,False,None)
77 def init_db(cache,name,clean,parent = None):
78 return _dict_p_type(cache,name,clean,parent)
80 def init_db_mtime(cache,cache_bbfile):
81 return _dict_p_type.mtime(cache,cache_bbfile)
83 def pkgdata(use_cache, cache):
85 Return some sort of dictionary to lookup parsed dictionaires
88 return DataDictCache(cache)
91 def createCopy(source):
92 """Link the source set to the destination
93 If one does not find the value in the destination set,
94 search will go on to the source set to get the value.
95 Value from source are copy-on-write. i.e. any try to
96 modify one of them will end up putting the modified value
97 in the destination set.
99 return source.createCopy()
102 """Non-destructive var init for data structure"""
106 def setVar(var, value, d):
107 """Set a variable to a given value
111 >>> setVar('TEST', 'testcontents', d)
112 >>> print getVar('TEST', d)
118 def getVar(var, d, exp = 0):
119 """Gets the value of a variable
123 >>> setVar('TEST', 'testcontents', d)
124 >>> print getVar('TEST', d)
127 return d.getVar(var,exp)
130 """Removes a variable from the data set
134 >>> setVar('TEST', 'testcontents', d)
135 >>> print getVar('TEST', d)
137 >>> delVar('TEST', d)
138 >>> print getVar('TEST', d)
143 def setVarFlag(var, flag, flagvalue, d):
144 """Set a flag for a given variable to a given value
148 >>> setVarFlag('TEST', 'python', 1, d)
149 >>> print getVarFlag('TEST', 'python', d)
152 d.setVarFlag(var,flag,flagvalue)
154 def getVarFlag(var, flag, d):
155 """Gets given flag from given var
159 >>> setVarFlag('TEST', 'python', 1, d)
160 >>> print getVarFlag('TEST', 'python', d)
163 return d.getVarFlag(var,flag)
165 def delVarFlag(var, flag, d):
166 """Removes a given flag from the variable's flags
170 >>> setVarFlag('TEST', 'testflag', 1, d)
171 >>> print getVarFlag('TEST', 'testflag', d)
173 >>> delVarFlag('TEST', 'testflag', d)
174 >>> print getVarFlag('TEST', 'testflag', d)
178 d.delVarFlag(var,flag)
180 def setVarFlags(var, flags, d):
181 """Set the flags for a given variable
186 >>> myflags['test'] = 'blah'
187 >>> setVarFlags('TEST', myflags, d)
188 >>> print getVarFlag('TEST', 'test', d)
191 d.setVarFlags(var,flags)
193 def getVarFlags(var, d):
194 """Gets a variable's flags
198 >>> setVarFlag('TEST', 'test', 'blah', d)
199 >>> print getVarFlags('TEST', d)['test']
202 return d.getVarFlags(var)
204 def delVarFlags(var, d):
205 """Removes a variable's flags
209 >>> setVarFlag('TEST', 'testflag', 1, data)
210 >>> print getVarFlag('TEST', 'testflag', data)
212 >>> delVarFlags('TEST', data)
213 >>> print getVarFlags('TEST', data)
220 """Return a list of keys in d
224 >>> setVar('TEST', 1, d)
225 >>> setVar('MOO' , 2, d)
226 >>> setVarFlag('TEST', 'test', 1, d)
233 """Returns the data object used"""
236 def setData(newData, d):
237 """Sets the data object to the supplied value"""
240 __expand_var_regexp__ = re.compile(r"\${[^{}]+}")
241 __expand_python_regexp__ = re.compile(r"\${@.+?}")
243 def expand(s, d, varname = None):
244 """Variable expansion using the data store.
249 >>> setVar('A', 'sshd', d)
250 >>> print expand('/usr/bin/${A}', d)
255 >>> print expand('result: ${@37 * 72}', d)
260 >>> print expand('${TARGET_MOO}', d)
262 >>> setVar('TARGET_MOO', 'yupp', d)
263 >>> print expand('${TARGET_MOO}',d)
265 >>> setVar('SRC_URI', 'http://somebug.${TARGET_MOO}', d)
266 >>> delVar('TARGET_MOO', d)
267 >>> print expand('${SRC_URI}', d)
268 http://somebug.${TARGET_MOO}
271 key = match.group()[2:-1]
274 raise Exception("variable %s references itself!" % varname)
275 var = getVar(key, d, 1)
281 def python_sub(match):
283 code = match.group()[3:-1]
286 if type(s) == types.IntType: s = str(s)
289 if type(s) is not types.StringType: # sanity check
292 while s.find('$') != -1:
295 s = __expand_var_regexp__.sub(var_sub, s)
296 s = __expand_python_regexp__.sub(python_sub, s)
298 if type(s) is not types.StringType: # sanity check
300 bb.error('expansion of %s returned non-string %s' % (olds, s))
301 except KeyboardInterrupt:
304 note("%s:%s while evaluating:\n%s" % (sys.exc_info()[0], sys.exc_info()[1], s))
308 def expandKeys(alterdata, readdata = None):
312 for key in keys(alterdata):
313 ekey = expand(key, readdata)
316 val = getVar(key, alterdata)
320 # setVarFlags(ekey, copy.copy(getVarFlags(key, readdata)), alterdata)
321 setVar(ekey, val, alterdata)
323 for i in ('_append', '_prepend', '_delete'):
324 dest = getVarFlag(ekey, i, alterdata) or []
325 src = getVarFlag(key, i, readdata) or []
327 setVarFlag(ekey, i, dest, alterdata)
329 delVar(key, alterdata)
331 def expandData(alterdata, readdata = None):
332 """For each variable in alterdata, expand it, and update the var contents.
333 Replacements use data from readdata.
338 >>> setVar("dlmsg", "dl_dir is ${DL_DIR}", a)
339 >>> setVar("DL_DIR", "/path/to/whatever", b)
341 >>> print getVar("dlmsg", a)
342 dl_dir is /path/to/whatever
347 for key in keys(alterdata):
348 val = getVar(key, alterdata)
349 if type(val) is not types.StringType:
351 expanded = expand(val, readdata)
352 # print "key is %s, val is %s, expanded is %s" % (key, val, expanded)
354 setVar(key, expanded, alterdata)
358 def inheritFromOS(d):
359 """Inherit variables from the environment."""
360 # fakeroot needs to be able to set these
361 non_inherit_vars = [ "LD_LIBRARY_PATH", "LD_PRELOAD" ]
362 for s in os.environ.keys():
363 if not s in non_inherit_vars:
365 setVar(s, os.environ[s], d)
366 setVarFlag(s, 'matchesenv', '1', d)
372 def emit_var(var, o=sys.__stdout__, d = init(), all=False):
373 """Emit a variable to be sourced by a shell."""
374 if getVarFlag(var, "python", d):
379 oval = getVar(var, d, 0)
380 val = getVar(var, d, 1)
381 except KeyboardInterrupt:
384 excname = str(sys.exc_info()[0])
385 if excname == "bb.build.FuncFailed":
387 o.write('# expansion of %s threw %s\n' % (var, excname))
391 o.write('# %s=%s\n' % (var, oval))
393 if type(val) is not types.StringType:
396 if getVarFlag(var, 'matchesenv', d):
399 if (var.find("-") != -1 or var.find(".") != -1 or var.find('{') != -1 or var.find('}') != -1 or var.find('+') != -1) and not all:
406 if getVarFlag(var, "func", d):
407 # NOTE: should probably check for unbalanced {} within the var
408 o.write("%s() {\n%s\n}\n" % (var, val))
410 if getVarFlag(var, "export", d):
415 # if we're going to output this within doublequotes,
416 # to a shell, we need to escape the quotes in the var
417 alter = re.sub('"', '\\"', val.strip())
418 o.write('%s="%s"\n' % (var, alter))
422 def emit_env(o=sys.__stdout__, d = init(), all=False):
423 """Emits all items in the data store in a format such that it can be sourced by a shell."""
428 if getVarFlag(e, "func", d):
430 emit_var(e, o, d, all) and o.write('\n')
433 if not getVarFlag(e, "func", d):
435 emit_var(e, o, d) and o.write('\n')
438 """Modifies the environment vars according to local overrides and commands.
440 Appending to a variable:
442 >>> setVar('TEST', 'this is a', d)
443 >>> setVar('TEST_append', ' test', d)
444 >>> setVar('TEST_append', ' of the emergency broadcast system.', d)
446 >>> print getVar('TEST', d)
447 this is a test of the emergency broadcast system.
449 Prepending to a variable:
450 >>> setVar('TEST', 'virtual/libc', d)
451 >>> setVar('TEST_prepend', 'virtual/tmake ', d)
452 >>> setVar('TEST_prepend', 'virtual/patcher ', d)
454 >>> print getVar('TEST', d)
455 virtual/patcher virtual/tmake virtual/libc
458 >>> setVar('TEST_arm', 'target', d)
459 >>> setVar('TEST_ramses', 'machine', d)
460 >>> setVar('TEST_local', 'local', d)
461 >>> setVar('OVERRIDES', 'arm', d)
463 >>> setVar('TEST', 'original', d)
465 >>> print getVar('TEST', d)
468 >>> setVar('OVERRIDES', 'arm:ramses:local', d)
469 >>> setVar('TEST', 'original', d)
471 >>> print getVar('TEST', d)
475 debug(2, "update_data()")
477 # can't do delete env[...] while iterating over the dictionary, so remember them
479 overrides = (getVar('OVERRIDES', d, 1) or "").split(':') or []
481 def applyOverrides(var, d):
483 debug(1, "OVERRIDES not defined, nothing to do")
487 if var.endswith("_" + o):
494 sval = getVar(s, d) or ""
496 # Handle line appends:
497 for (a, o) in getVarFlag(s, '_append', d) or []:
498 # maybe the OVERRIDE was not yet added so keep the append
499 if (o and o in overrides) or not o:
500 delVarFlag(s, '_append', d)
502 if not o in overrides:
507 # Handle line prepends
508 for (a, o) in getVarFlag(s, '_prepend', d) or []:
509 # maybe the OVERRIDE was not yet added so keep the append
510 if (o and o in overrides) or not o:
511 delVarFlag(s, '_prepend', d)
513 if not o in overrides:
518 # Handle line deletions
520 nameval = getVar(name, d)
525 pattern = nameval.replace('\n','').strip()
526 for line in sval.split('\n'):
527 if line.find(pattern) == -1:
528 new = new + '\n' + line
532 # delete all environment vars no longer needed
536 def inherits_class(klass, d):
537 val = getVar('__inherit_cache', d) or ""
538 if os.path.join('classes', '%s.bbclass' % klass) in val.split():
543 """Start a doctest run on this module"""
546 doctest.testmod(data)
548 if __name__ == "__main__":