2 # ex:ts=4:sw=4:sts=4:et
3 # -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
5 OpenEmbedded 'Data' implementations
7 Functions for interacting with the data structure used by the
8 OpenEmbedded (http://openembedded.org) build infrastructure.
10 Copyright: (c) 2003 Chris Larson
12 Based on functions from the base oe module, Copyright 2003 Holger Schurig
15 import sys, os, re, time, types
16 if sys.argv[0][-5:] == "pydoc":
17 path = os.path.dirname(os.path.dirname(sys.argv[1]))
19 path = os.path.dirname(os.path.dirname(sys.argv[0]))
22 from oe import note, debug
29 def initVar(var, d = _data):
30 """Non-destructive var init for data structure"""
34 if not "flags" in d[var]:
37 __setvar_regexp__ = {}
38 __setvar_regexp__["_append"] = re.compile('(?P<base>.*?)%s(_(?P<add>.*))?' % "_append")
39 __setvar_regexp__["_prepend"] = re.compile('(?P<base>.*?)%s(_(?P<add>.*))?' % "_prepend")
40 __setvar_regexp__["_delete"] = re.compile('(?P<base>.*?)%s(_(?P<add>.*))?' % "_delete")
42 def setVar(var, value, d = _data):
43 """Set a variable to a given value
46 >>> setVar('TEST', 'testcontents')
47 >>> print getVar('TEST')
50 for v in ["_append", "_prepend", "_delete"]:
51 match = __setvar_regexp__[v].match(var)
53 base = match.group('base')
54 override = match.group('add')
55 l = getVarFlag(base, v, d) or []
56 if override == 'delete':
57 if l.count([value, None]):
58 del l[l.index([value, None])]
59 l.append([value, override])
60 setVarFlag(base, v, l, d)
65 if getVarFlag(var, 'matchesenv', d):
66 delVarFlag(var, 'matchesenv', d)
67 setVarFlag(var, 'export', 1, d)
68 d[var]["content"] = value
70 def getVar(var, d = _data, exp = 0):
71 """Gets the value of a variable
74 >>> setVar('TEST', 'testcontents')
75 >>> print getVar('TEST')
78 if not var in d or not "content" in d[var]:
81 return expand(d[var]["content"], d, var)
82 return d[var]["content"]
84 def delVar(var, d = _data):
85 """Removes a variable from the data set
88 >>> setVar('TEST', 'testcontents')
89 >>> print getVar('TEST')
92 >>> print getVar('TEST')
98 def setVarFlag(var, flag, flagvalue, d = _data):
99 """Set a flag for a given variable to a given value
102 >>> setVarFlag('TEST', 'python', 1)
103 >>> print getVarFlag('TEST', 'python')
106 # print "d[%s][\"flags\"][%s] = %s" % (var, flag, flagvalue)
109 d[var]["flags"][flag] = flagvalue
111 def getVarFlag(var, flag, d = _data):
112 """Gets given flag from given var
115 >>> setVarFlag('TEST', 'python', 1)
116 >>> print getVarFlag('TEST', 'python')
119 if var in d and "flags" in d[var] and flag in d[var]["flags"]:
120 return d[var]["flags"][flag]
123 def delVarFlag(var, flag, d = _data):
124 """Removes a given flag from the variable's flags
127 >>> setVarFlag('TEST', 'testflag', 1)
128 >>> print getVarFlag('TEST', 'testflag')
130 >>> delVarFlag('TEST', 'testflag')
131 >>> print getVarFlag('TEST', 'testflag')
135 if var in d and "flags" in d[var] and flag in d[var]["flags"]:
136 del d[var]["flags"][flag]
138 def setVarFlags(var, flags, d = _data):
139 """Set the flags for a given variable
143 >>> myflags['test'] = 'blah'
144 >>> setVarFlags('TEST', myflags)
145 >>> print getVarFlag('TEST', 'test')
150 d[var]["flags"] = flags
152 def getVarFlags(var, d = _data):
153 """Gets a variable's flags
156 >>> setVarFlag('TEST', 'test', 'blah')
157 >>> print getVarFlags('TEST')['test']
160 if var in d and "flags" in d[var]:
161 return d[var]["flags"]
164 def delVarFlags(var, d = _data):
165 """Removes a variable's flags
168 >>> setVarFlag('TEST', 'testflag', 1)
169 >>> print getVarFlag('TEST', 'testflag')
171 >>> delVarFlags('TEST')
172 >>> print getVarFlags('TEST')
176 if var in d and "flags" in d[var]:
179 def getData(d = _data):
180 """Returns the data object used"""
183 def setData(newData, d = _data):
184 """Sets the data object to the supplied value"""
187 __expand_var_regexp__ = re.compile(r"\${[^{}]+}")
188 __expand_python_regexp__ = re.compile(r"\${@.+?}")
190 def expand(s, d = _data, varname = None):
191 """Variable expansion using the data store.
195 >>> setVar('A', 'sshd')
196 >>> print expand('/usr/bin/${A}')
200 >>> print expand('result: ${@37 * 72}')
204 key = match.group()[2:-1]
207 raise Exception("variable %s references itself!" % varname)
208 var = getVar(key, d, 1)
214 def python_sub(match):
216 code = match.group()[3:-1]
219 if type(s) == types.IntType: s = str(s)
222 if type(s) is not types.StringType: # sanity check
225 while s.find('$') != -1:
228 s = __expand_var_regexp__.sub(var_sub, s)
229 s = __expand_python_regexp__.sub(python_sub, s)
231 if type(s) is not types.StringType: # sanity check
233 oe.error('expansion of %s returned non-string %s' % (olds, s))
236 oe.note("%s:%s while evaluating:\n%s" % (sys.exc_info()[0], sys.exc_info()[1], s))
240 def expandKeys(alterdata = _data, readdata = None):
244 for key in alterdata.keys():
245 ekey = expand(key, readdata)
248 val = getVar(key, alterdata)
252 # setVarFlags(ekey, copy.copy(getVarFlags(key, readdata)), alterdata)
253 setVar(ekey, val, alterdata)
255 for i in ('_append', '_prepend', '_delete'):
256 dest = getVarFlag(ekey, i, alterdata) or []
257 src = getVarFlag(key, i, readdata) or []
259 setVarFlag(ekey, i, dest, alterdata)
261 delVar(key, alterdata)
263 def expandData(alterdata = _data, readdata = None):
264 """For each variable in alterdata, expand it, and update the var contents.
265 Replacements use data from readdata.
270 >>> setVar("dlmsg", "dl_dir is ${DL_DIR}", a)
271 >>> setVar("DL_DIR", "/path/to/whatever", b)
273 >>> print getVar("dlmsg", a)
274 dl_dir is /path/to/whatever
279 for key in alterdata.keys():
280 val = getVar(key, alterdata)
281 if type(val) is not types.StringType:
283 expanded = expand(val, readdata)
284 # print "key is %s, val is %s, expanded is %s" % (key, val, expanded)
286 setVar(key, expanded, alterdata)
290 def inheritFromOS(d = _data):
291 """Inherit variables from the environment."""
292 # fakeroot needs to be able to set these
293 non_inherit_vars = [ "LD_LIBRARY_PATH", "LD_PRELOAD" ]
294 for s in os.environ.keys():
295 if not s in non_inherit_vars:
297 setVar(s, os.environ[s], d)
298 setVarFlag(s, 'matchesenv', '1', d)
304 def emit_var(var, o=sys.__stdout__, d = _data, all=False):
305 """Emit a variable to be sourced by a shell."""
306 if getVarFlag(var, "python", d):
311 oval = getVar(var, d, 0)
312 val = getVar(var, d, 1)
313 except KeyboardInterrupt:
316 o.write('# expansion of %s threw %s\n' % (var, sys.exc_info()[0]))
320 o.write('# %s=%s\n' % (var, oval))
322 if type(val) is not types.StringType:
325 if getVarFlag(var, 'matchesenv', d):
328 if var.find("-") != -1 or var.find(".") != -1 or var.find('{') != -1 or var.find('}') != -1 or var.find('+') != -1:
335 if getVarFlag(var, "func", d):
336 # NOTE: should probably check for unbalanced {} within the var
337 o.write("%s() {\n%s\n}\n" % (var, val))
339 if getVarFlag(var, "export", d):
344 # if we're going to output this within doublequotes,
345 # to a shell, we need to escape the quotes in the var
346 alter = re.sub('"', '\\"', val.strip())
347 o.write('%s="%s"\n' % (var, alter))
351 def emit_env(o=sys.__stdout__, d = _data, all=False):
352 """Emits all items in the data store in a format such that it can be sourced by a shell."""
357 if getVarFlag(e, "func", d):
359 emit_var(e, o, d, all) and o.write('\n')
362 if not getVarFlag(e, "func", d):
364 emit_var(e, o, d) and o.write('\n')
366 def update_data(d = _data):
367 """Modifies the environment vars according to local overrides and commands.
369 Appending to a variable:
370 >>> setVar('TEST', 'this is a')
371 >>> setVar('TEST_append', ' test')
372 >>> setVar('TEST_append', ' of the emergency broadcast system.')
374 >>> print getVar('TEST')
375 this is a test of the emergency broadcast system.
377 Prepending to a variable:
378 >>> setVar('TEST', 'virtual/libc')
379 >>> setVar('TEST_prepend', 'virtual/tmake ')
380 >>> setVar('TEST_prepend', 'virtual/patcher ')
382 >>> print getVar('TEST')
383 virtual/patcher virtual/tmake virtual/libc
386 >>> setVar('TEST_arm', 'target')
387 >>> setVar('TEST_ramses', 'machine')
388 >>> setVar('TEST_local', 'local')
389 >>> setVar('OVERRIDES', 'arm')
391 >>> setVar('TEST', 'original')
393 >>> print getVar('TEST')
396 >>> setVar('OVERRIDES', 'arm:ramses:local')
397 >>> setVar('TEST', 'original')
399 >>> print getVar('TEST')
403 debug(2, "update_data()")
405 # can't do delete env[...] while iterating over the dictionary, so remember them
407 overrides = (getVar('OVERRIDES', d, 1) or "").split(':') or []
409 def applyOverrides(var, d = _data):
411 debug(1, "OVERRIDES not defined, nothing to do")
415 if var.endswith("_" + o):
422 sval = getVar(s, d) or ""
424 # Handle line appends:
425 for (a, o) in getVarFlag(s, '_append', d) or []:
426 # maybe the OVERRIDE was not yet added so keep the append
427 if (o and o in overrides) or not o:
428 delVarFlag(s, '_append', d)
430 if not o in overrides:
435 # Handle line prepends
436 for (a, o) in getVarFlag(s, '_prepend', d) or []:
437 # maybe the OVERRIDE was not yet added so keep the append
438 if (o and o in overrides) or not o:
439 delVarFlag(s, '_prepend', d)
441 if not o in overrides:
446 # Handle line deletions
448 nameval = getVar(name, d)
453 pattern = nameval.replace('\n','').strip()
454 for line in sval.split('\n'):
455 if line.find(pattern) == -1:
456 new = new + '\n' + line
460 # delete all environment vars no longer needed
464 def inherits_class(klass, d):
465 val = getVar('__inherit_cache', d) or ""
466 if ("classes/%s.oeclass" % klass) in val.split():
471 """Start a doctest run on this module"""
474 doctest.testmod(data)
476 if __name__ == "__main__":