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):
215 code = match.group()[3:-1]
221 oe.note("%s:%s while evaluating:\n%s" % (sys.exc_info()[0], sys.exc_info()[1], code))
223 if type(s) == types.IntType: s = str(s)
226 if type(s) is not types.StringType: # sanity check
229 while s.find('$') != -1:
231 s = __expand_var_regexp__.sub(var_sub, s)
232 s = __expand_python_regexp__.sub(python_sub, s)
236 def expandKeys(alterdata = _data, readdata = None):
240 for key in alterdata.keys():
241 ekey = expand(key, readdata)
244 val = getVar(key, alterdata)
247 setVar(ekey, val, alterdata)
249 def expandData(alterdata = _data, readdata = None):
250 """For each variable in alterdata, expand it, and update the var contents.
251 Replacements use data from readdata.
256 >>> setVar("dlmsg", "dl_dir is ${DL_DIR}", a)
257 >>> setVar("DL_DIR", "/path/to/whatever", b)
259 >>> print getVar("dlmsg", a)
260 dl_dir is /path/to/whatever
265 for key in alterdata.keys():
266 val = getVar(key, alterdata)
267 if type(val) is not types.StringType:
269 expanded = expand(val, readdata)
270 # print "key is %s, val is %s, expanded is %s" % (key, val, expanded)
272 setVar(key, expanded, alterdata)
276 def inheritFromOS(d = _data):
277 """Inherit variables from the environment."""
278 # fakeroot needs to be able to set these
279 non_inherit_vars = [ "LD_LIBRARY_PATH", "LD_PRELOAD" ]
280 for s in os.environ.keys():
281 if not s in non_inherit_vars:
283 setVar(s, os.environ[s], d)
284 setVarFlag(s, 'matchesenv', '1', d)
290 def emit_var(var, o=sys.__stdout__, d = _data, all=False):
291 """Emit a variable to be sourced by a shell."""
292 if getVarFlag(var, "python", d):
297 oval = getVar(var, d, 0)
298 val = getVar(var, d, 1)
299 except KeyboardInterrupt:
302 o.write('# expansion of %s threw %s\n' % (var, sys.exc_info()[0]))
306 o.write('# %s=%s\n' % (var, oval))
308 if type(val) is not types.StringType:
311 if getVarFlag(var, 'matchesenv', d):
314 if var.find("-") != -1 or var.find(".") != -1 or var.find('{') != -1 or var.find('}') != -1 or var.find('+') != -1:
321 if getVarFlag(var, "func", d):
322 # NOTE: should probably check for unbalanced {} within the var
323 o.write("%s() {\n%s\n}\n" % (var, val))
325 if getVarFlag(var, "export", d):
330 # if we're going to output this within doublequotes,
331 # to a shell, we need to escape the quotes in the var
332 alter = re.sub('"', '\\"', val.strip())
333 o.write('%s="%s"\n' % (var, alter))
337 def emit_env(o=sys.__stdout__, d = _data, all=False):
338 """Emits all items in the data store in a format such that it can be sourced by a shell."""
343 if getVarFlag(e, "func", d):
345 emit_var(e, o, d, all) and o.write('\n')
348 if not getVarFlag(e, "func", d):
350 emit_var(e, o, d) and o.write('\n')
352 def update_data(d = _data):
353 """Modifies the environment vars according to local overrides and commands.
355 Appending to a variable:
356 >>> setVar('TEST', 'this is a')
357 >>> setVar('TEST_append', ' test')
358 >>> setVar('TEST_append', ' of the emergency broadcast system.')
360 >>> print getVar('TEST')
361 this is a test of the emergency broadcast system.
363 Prepending to a variable:
364 >>> setVar('TEST', 'virtual/libc')
365 >>> setVar('TEST_prepend', 'virtual/tmake ')
366 >>> setVar('TEST_prepend', 'virtual/patcher ')
368 >>> print getVar('TEST')
369 virtual/patcher virtual/tmake virtual/libc
372 >>> setVar('TEST_arm', 'target')
373 >>> setVar('TEST_ramses', 'machine')
374 >>> setVar('TEST_local', 'local')
375 >>> setVar('OVERRIDES', 'arm')
377 >>> setVar('TEST', 'original')
379 >>> print getVar('TEST')
382 >>> setVar('OVERRIDES', 'arm:ramses:local')
383 >>> setVar('TEST', 'original')
385 >>> print getVar('TEST')
389 debug(2, "update_data()")
391 # can't do delete env[...] while iterating over the dictionary, so remember them
393 overrides = (getVar('OVERRIDES', d, 1) or "").split(':') or []
395 def applyOverrides(var, d = _data):
397 debug(1, "OVERRIDES not defined, nothing to do")
401 if var.endswith("_" + o):
408 sval = getVar(s, d) or ""
410 # Handle line appends:
411 for (a, o) in getVarFlag(s, '_append', d) or []:
412 # maybe the OVERRIDE was not yet added so keep the append
413 if (o and o in overrides) or not o:
414 delVarFlag(s, '_append', d)
416 if not o in overrides:
421 # Handle line prepends
422 for (a, o) in getVarFlag(s, '_prepend', d) or []:
423 # maybe the OVERRIDE was not yet added so keep the append
424 if (o and o in overrides) or not o:
425 delVarFlag(s, '_prepend', d)
427 if not o in overrides:
432 # Handle line deletions
434 nameval = getVar(name, d)
439 pattern = nameval.replace('\n','').strip()
440 for line in sval.split('\n'):
441 if line.find(pattern) == -1:
442 new = new + '\n' + line
446 # delete all environment vars no longer needed
450 def inherits_class(klass, d):
451 val = getVar('__inherit_cache', d) or ""
452 if ("classes/%s.oeclass" % klass) in val.split():
457 """Start a doctest run on this module"""
460 doctest.testmod(data)
462 if __name__ == "__main__":