diff options
Diffstat (limited to 'bitbake/lib/bb/data.py')
-rw-r--r-- | bitbake/lib/bb/data.py | 417 |
1 files changed, 46 insertions, 371 deletions
diff --git a/bitbake/lib/bb/data.py b/bitbake/lib/bb/data.py index c3bb1a1f43..636983edcc 100644 --- a/bitbake/lib/bb/data.py +++ b/bitbake/lib/bb/data.py @@ -11,7 +11,7 @@ operations. At night the cookie monster came by and suggested 'give me cookies on setting the variables and things will work out'. Taking this suggestion into account applying the skills from the not yet passed 'Entwurf und -Analyse von Algorithmen' lecture and the cookie +Analyse von Algorithmen' lecture and the cookie monster seems to be right. We will track setVar more carefully to have faster update_data and expandKeys operations. @@ -37,39 +37,40 @@ the speed is more critical here. # #Based on functions from the base bb module, Copyright 2003 Holger Schurig -import sys, os, re, types +import sys, os, re if sys.argv[0][-5:] == "pydoc": path = os.path.dirname(os.path.dirname(sys.argv[1])) else: path = os.path.dirname(os.path.dirname(sys.argv[0])) -sys.path.insert(0,path) +sys.path.insert(0, path) +from itertools import groupby from bb import data_smart import bb -class VarExpandError(Exception): - pass - _dict_type = data_smart.DataSmart def init(): + """Return a new object representing the Bitbake data""" return _dict_type() def init_db(parent = None): + """Return a new object representing the Bitbake data, + optionally based on an existing object""" if parent: return parent.createCopy() else: return _dict_type() def createCopy(source): - """Link the source set to the destination - If one does not find the value in the destination set, - search will go on to the source set to get the value. - Value from source are copy-on-write. i.e. any try to - modify one of them will end up putting the modified value - in the destination set. - """ - return source.createCopy() + """Link the source set to the destination + If one does not find the value in the destination set, + search will go on to the source set to get the value. + Value from source are copy-on-write. i.e. any try to + modify one of them will end up putting the modified value + in the destination set. + """ + return source.createCopy() def initVar(var, d): """Non-destructive var init for data structure""" @@ -77,91 +78,34 @@ def initVar(var, d): def setVar(var, value, d): - """Set a variable to a given value - - Example: - >>> d = init() - >>> setVar('TEST', 'testcontents', d) - >>> print getVar('TEST', d) - testcontents - """ - d.setVar(var,value) + """Set a variable to a given value""" + d.setVar(var, value) def getVar(var, d, exp = 0): - """Gets the value of a variable - - Example: - >>> d = init() - >>> setVar('TEST', 'testcontents', d) - >>> print getVar('TEST', d) - testcontents - """ - return d.getVar(var,exp) + """Gets the value of a variable""" + return d.getVar(var, exp) def renameVar(key, newkey, d): - """Renames a variable from key to newkey - - Example: - >>> d = init() - >>> setVar('TEST', 'testcontents', d) - >>> renameVar('TEST', 'TEST2', d) - >>> print getVar('TEST2', d) - testcontents - """ + """Renames a variable from key to newkey""" d.renameVar(key, newkey) def delVar(var, d): - """Removes a variable from the data set - - Example: - >>> d = init() - >>> setVar('TEST', 'testcontents', d) - >>> print getVar('TEST', d) - testcontents - >>> delVar('TEST', d) - >>> print getVar('TEST', d) - None - """ + """Removes a variable from the data set""" d.delVar(var) def setVarFlag(var, flag, flagvalue, d): - """Set a flag for a given variable to a given value - - Example: - >>> d = init() - >>> setVarFlag('TEST', 'python', 1, d) - >>> print getVarFlag('TEST', 'python', d) - 1 - """ - d.setVarFlag(var,flag,flagvalue) + """Set a flag for a given variable to a given value""" + d.setVarFlag(var, flag, flagvalue) def getVarFlag(var, flag, d): - """Gets given flag from given var - - Example: - >>> d = init() - >>> setVarFlag('TEST', 'python', 1, d) - >>> print getVarFlag('TEST', 'python', d) - 1 - """ - return d.getVarFlag(var,flag) + """Gets given flag from given var""" + return d.getVarFlag(var, flag) def delVarFlag(var, flag, d): - """Removes a given flag from the variable's flags - - Example: - >>> d = init() - >>> setVarFlag('TEST', 'testflag', 1, d) - >>> print getVarFlag('TEST', 'testflag', d) - 1 - >>> delVarFlag('TEST', 'testflag', d) - >>> print getVarFlag('TEST', 'testflag', d) - None - - """ - d.delVarFlag(var,flag) + """Removes a given flag from the variable's flags""" + d.delVarFlag(var, flag) def setVarFlags(var, flags, d): """Set the flags for a given variable @@ -170,115 +114,27 @@ def setVarFlags(var, flags, d): setVarFlags will not clear previous flags. Think of this method as addVarFlags - - Example: - >>> d = init() - >>> myflags = {} - >>> myflags['test'] = 'blah' - >>> setVarFlags('TEST', myflags, d) - >>> print getVarFlag('TEST', 'test', d) - blah """ - d.setVarFlags(var,flags) + d.setVarFlags(var, flags) def getVarFlags(var, d): - """Gets a variable's flags - - Example: - >>> d = init() - >>> setVarFlag('TEST', 'test', 'blah', d) - >>> print getVarFlags('TEST', d)['test'] - blah - """ + """Gets a variable's flags""" return d.getVarFlags(var) def delVarFlags(var, d): - """Removes a variable's flags - - Example: - >>> data = init() - >>> setVarFlag('TEST', 'testflag', 1, data) - >>> print getVarFlag('TEST', 'testflag', data) - 1 - >>> delVarFlags('TEST', data) - >>> print getVarFlags('TEST', data) - None - - """ + """Removes a variable's flags""" d.delVarFlags(var) def keys(d): - """Return a list of keys in d - - Example: - >>> d = init() - >>> setVar('TEST', 1, d) - >>> setVar('MOO' , 2, d) - >>> setVarFlag('TEST', 'test', 1, d) - >>> keys(d) - ['TEST', 'MOO'] - """ + """Return a list of keys in d""" return d.keys() -def getData(d): - """Returns the data object used""" - return d - -def setData(newData, d): - """Sets the data object to the supplied value""" - d = newData - - -## -## Cookie Monsters' query functions -## -def _get_override_vars(d, override): - """ - Internal!!! - - Get the Names of Variables that have a specific - override. This function returns a iterable - Set or an empty list - """ - return [] - -def _get_var_flags_triple(d): - """ - Internal!!! - - """ - return [] __expand_var_regexp__ = re.compile(r"\${[^{}]+}") __expand_python_regexp__ = re.compile(r"\${@.+?}") def expand(s, d, varname = None): - """Variable expansion using the data store. - - Example: - Standard expansion: - >>> d = init() - >>> setVar('A', 'sshd', d) - >>> print expand('/usr/bin/${A}', d) - /usr/bin/sshd - - Python expansion: - >>> d = init() - >>> print expand('result: ${@37 * 72}', d) - result: 2664 - - Shell expansion: - >>> d = init() - >>> print expand('${TARGET_MOO}', d) - ${TARGET_MOO} - >>> setVar('TARGET_MOO', 'yupp', d) - >>> print expand('${TARGET_MOO}',d) - yupp - >>> setVar('SRC_URI', 'http://somebug.${TARGET_MOO}', d) - >>> delVar('TARGET_MOO', d) - >>> print expand('${SRC_URI}', d) - http://somebug.${TARGET_MOO} - """ + """Variable expansion using the data store""" return d.expand(s, varname) def expandKeys(alterdata, readdata = None): @@ -295,38 +151,13 @@ def expandKeys(alterdata, readdata = None): continue todolist[key] = ekey - # These two for loops are split for performance to maximise the + # These two for loops are split for performance to maximise the # usefulness of the expand cache for key in todolist: ekey = todolist[key] renameVar(key, ekey, alterdata) -def expandData(alterdata, readdata = None): - """For each variable in alterdata, expand it, and update the var contents. - Replacements use data from readdata. - - Example: - >>> a=init() - >>> b=init() - >>> setVar("dlmsg", "dl_dir is ${DL_DIR}", a) - >>> setVar("DL_DIR", "/path/to/whatever", b) - >>> expandData(a, b) - >>> print getVar("dlmsg", a) - dl_dir is /path/to/whatever - """ - if readdata == None: - readdata = alterdata - - for key in keys(alterdata): - val = getVar(key, alterdata) - if type(val) is not types.StringType: - continue - expanded = expand(val, readdata) -# print "key is %s, val is %s, expanded is %s" % (key, val, expanded) - if val != expanded: - setVar(key, expanded, alterdata) - def inheritFromOS(d): """Inherit variables from the environment.""" for s in os.environ.keys(): @@ -351,21 +182,15 @@ def emit_var(var, o=sys.__stdout__, d = init(), all=False): if all: oval = getVar(var, d, 0) val = getVar(var, d, 1) - except KeyboardInterrupt: + except (KeyboardInterrupt, bb.build.FuncFailed): raise - except: - excname = str(sys.exc_info()[0]) - if excname == "bb.build.FuncFailed": - raise - o.write('# expansion of %s threw %s\n' % (var, excname)) + except Exception, exc: + o.write('# expansion of %s threw %s: %s\n' % (var, exc.__class__.__name__, str(exc))) return 0 if all: o.write('# %s=%s\n' % (var, oval)) - if type(val) is not types.StringType: - return 0 - if (var.find("-") != -1 or var.find(".") != -1 or var.find('{') != -1 or var.find('}') != -1 or var.find('+') != -1) and not all: return 0 @@ -375,10 +200,11 @@ def emit_var(var, o=sys.__stdout__, d = init(), all=False): o.write('unset %s\n' % varExpanded) return 1 - val.rstrip() if not val: return 0 + val = str(val) + if func: # NOTE: should probably check for unbalanced {} within the var o.write("%s() {\n%s\n}\n" % (varExpanded, val)) @@ -393,173 +219,22 @@ def emit_var(var, o=sys.__stdout__, d = init(), all=False): o.write('%s="%s"\n' % (varExpanded, alter)) return 1 - def emit_env(o=sys.__stdout__, d = init(), all=False): """Emits all items in the data store in a format such that it can be sourced by a shell.""" - env = keys(d) - - for e in env: - if getVarFlag(e, "func", d): - continue - emit_var(e, o, d, all) and o.write('\n') - - for e in env: - if not getVarFlag(e, "func", d): - continue - emit_var(e, o, d) and o.write('\n') + isfunc = lambda key: bool(d.getVarFlag(key, "func")) + keys = sorted((key for key in d.keys() if not key.startswith("__")), key=isfunc) + grouped = groupby(keys, isfunc) + for isfunc, keys in grouped: + for key in keys: + emit_var(key, o, d, all and not isfunc) and o.write('\n') def update_data(d): - """Modifies the environment vars according to local overrides and commands. - Examples: - Appending to a variable: - >>> d = init() - >>> setVar('TEST', 'this is a', d) - >>> setVar('TEST_append', ' test', d) - >>> setVar('TEST_append', ' of the emergency broadcast system.', d) - >>> update_data(d) - >>> print getVar('TEST', d) - this is a test of the emergency broadcast system. - - Prepending to a variable: - >>> setVar('TEST', 'virtual/libc', d) - >>> setVar('TEST_prepend', 'virtual/tmake ', d) - >>> setVar('TEST_prepend', 'virtual/patcher ', d) - >>> update_data(d) - >>> print getVar('TEST', d) - virtual/patcher virtual/tmake virtual/libc - - Overrides: - >>> setVar('TEST_arm', 'target', d) - >>> setVar('TEST_ramses', 'machine', d) - >>> setVar('TEST_local', 'local', d) - >>> setVar('OVERRIDES', 'arm', d) - - >>> setVar('TEST', 'original', d) - >>> update_data(d) - >>> print getVar('TEST', d) - target - - >>> setVar('OVERRIDES', 'arm:ramses:local', d) - >>> setVar('TEST', 'original', d) - >>> update_data(d) - >>> print getVar('TEST', d) - local - - CopyMonster: - >>> e = d.createCopy() - >>> setVar('TEST_foo', 'foo', e) - >>> update_data(e) - >>> print getVar('TEST', e) - local - - >>> setVar('OVERRIDES', 'arm:ramses:local:foo', e) - >>> update_data(e) - >>> print getVar('TEST', e) - foo - - >>> f = d.createCopy() - >>> setVar('TEST_moo', 'something', f) - >>> setVar('OVERRIDES', 'moo:arm:ramses:local:foo', e) - >>> update_data(e) - >>> print getVar('TEST', e) - foo - - - >>> h = init() - >>> setVar('SRC_URI', 'file://append.foo;patch=1 ', h) - >>> g = h.createCopy() - >>> setVar('SRC_URI_append_arm', 'file://other.foo;patch=1', g) - >>> setVar('OVERRIDES', 'arm:moo', g) - >>> update_data(g) - >>> print getVar('SRC_URI', g) - file://append.foo;patch=1 file://other.foo;patch=1 - - """ - bb.msg.debug(2, bb.msg.domain.Data, "update_data()") - - # now ask the cookie monster for help - #print "Cookie Monster" - #print "Append/Prepend %s" % d._special_values - #print "Overrides %s" % d._seen_overrides - - overrides = (getVar('OVERRIDES', d, 1) or "").split(':') or [] - - # - # Well let us see what breaks here. We used to iterate - # over each variable and apply the override and then - # do the line expanding. - # If we have bad luck - which we will have - the keys - # where in some order that is so important for this - # method which we don't have anymore. - # Anyway we will fix that and write test cases this - # time. - - # - # First we apply all overrides - # Then we will handle _append and _prepend - # - - for o in overrides: - # calculate '_'+override - l = len(o)+1 - - # see if one should even try - if not d._seen_overrides.has_key(o): - continue - - vars = d._seen_overrides[o] - for var in vars: - name = var[:-l] - try: - d[name] = d[var] - except: - bb.msg.note(1, bb.msg.domain.Data, "Untracked delVar") - - # now on to the appends and prepends - if d._special_values.has_key('_append'): - appends = d._special_values['_append'] or [] - for append in appends: - for (a, o) in getVarFlag(append, '_append', d) or []: - # maybe the OVERRIDE was not yet added so keep the append - if (o and o in overrides) or not o: - delVarFlag(append, '_append', d) - if o and not o in overrides: - continue - - sval = getVar(append,d) or "" - sval+=a - setVar(append, sval, d) - - - if d._special_values.has_key('_prepend'): - prepends = d._special_values['_prepend'] or [] - - for prepend in prepends: - for (a, o) in getVarFlag(prepend, '_prepend', d) or []: - # maybe the OVERRIDE was not yet added so keep the prepend - if (o and o in overrides) or not o: - delVarFlag(prepend, '_prepend', d) - if o and not o in overrides: - continue - - sval = a + (getVar(prepend,d) or "") - setVar(prepend, sval, d) - + """Performs final steps upon the datastore, including application of overrides""" + d.finalize() def inherits_class(klass, d): val = getVar('__inherit_cache', d) or [] if os.path.join('classes', '%s.bbclass' % klass) in val: return True return False - -def _test(): - """Start a doctest run on this module""" - import doctest - import bb - from bb import data - bb.msg.set_debug_level(0) - doctest.testmod(data) - -if __name__ == "__main__": - _test() |