From c7f7cfd506f504f658088bc0c7ee9f487d8a3d3f Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Tue, 17 May 2005 18:04:46 +0000 Subject: bitbake data module abstraction: -bb.data is now a delegate to hookable Data implementation. -bb.data.init() is the 'factory' method to create a instance of a concrete implementation. -Kill assumptions that bb.data.init() returns a {} (python dict) -Add the old Dictionary Based Implementation as data_dict.py --- classes/base.bbclass | 4 +- lib/bb/data.py | 132 ++++++++++++++------------------- lib/bb/data_dict.py | 173 ++++++++++++++++++++++++++++++++++++++++++++ lib/bb/parse/BBHandler.py | 4 +- lib/bb/parse/ConfHandler.py | 8 +- 5 files changed, 235 insertions(+), 86 deletions(-) create mode 100644 lib/bb/data_dict.py diff --git a/classes/base.bbclass b/classes/base.bbclass index f319676d7..1d75964f5 100644 --- a/classes/base.bbclass +++ b/classes/base.bbclass @@ -54,7 +54,7 @@ python do_showdata() { # emit variables and shell functions bb.data.emit_env(sys.__stdout__, d, True) # emit the metadata which isnt valid shell - for e in d.keys(): + for e in bb.data.keys(d): if bb.data.getVarFlag(e, 'python', d): sys.__stdout__.write("\npython %s () {\n%s}\n" % (e, bb.data.getVar(e, d, 1))) } @@ -63,7 +63,7 @@ addtask listtasks do_listtasks[nostamp] = "1" python do_listtasks() { import sys - for e in d.keys(): + for e in bb.data.keys(d): if bb.data.getVarFlag(e, 'task', d): sys.__stdout__.write("%s\n" % e) } diff --git a/lib/bb/data.py b/lib/bb/data.py index 8f0f5dd6e..b7c28b26b 100644 --- a/lib/bb/data.py +++ b/lib/bb/data.py @@ -8,6 +8,7 @@ Functions for interacting with the data structure used by the BitBake build tools. Copyright (C) 2003, 2004 Chris Larson +Copyright (C) 2005 Holger Hans Peter Freyther This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -32,27 +33,22 @@ else: path = os.path.dirname(os.path.dirname(sys.argv[0])) sys.path.append(path) -from bb import note, debug +from bb import note, debug, data_dict + +_dict_type = data_dict.DataDict + def init(): - return {} + return _dict_type() -_data = init() +_data_dict = init() -def initVar(var, d = _data): +def initVar(var, d = _data_dict): """Non-destructive var init for data structure""" - if not var in d: - d[var] = {} - - if not "flags" in d[var]: - d[var]["flags"] = {} + d.initVar(var) -__setvar_regexp__ = {} -__setvar_regexp__["_append"] = re.compile('(?P.*?)%s(_(?P.*))?' % "_append") -__setvar_regexp__["_prepend"] = re.compile('(?P.*?)%s(_(?P.*))?' % "_prepend") -__setvar_regexp__["_delete"] = re.compile('(?P.*?)%s(_(?P.*))?' % "_delete") -def setVar(var, value, d = _data): +def setVar(var, value, d = _data_dict): """Set a variable to a given value Example: @@ -60,27 +56,10 @@ def setVar(var, value, d = _data): >>> print getVar('TEST') testcontents """ - for v in ["_append", "_prepend", "_delete"]: - match = __setvar_regexp__[v].match(var) - if match: - base = match.group('base') - override = match.group('add') - l = getVarFlag(base, v, d) or [] - if override == 'delete': - if l.count([value, None]): - del l[l.index([value, None])] - l.append([value, override]) - setVarFlag(base, v, l, d) - return + d.setVar(var,value) - if not var in d: - initVar(var, d) - if getVarFlag(var, 'matchesenv', d): - delVarFlag(var, 'matchesenv', d) - setVarFlag(var, 'export', 1, d) - d[var]["content"] = value -def getVar(var, d = _data, exp = 0): +def getVar(var, d = _data_dict, exp = 0): """Gets the value of a variable Example: @@ -88,13 +67,9 @@ def getVar(var, d = _data, exp = 0): >>> print getVar('TEST') testcontents """ - if not var in d or not "content" in d[var]: - return None - if exp: - return expand(d[var]["content"], d, var) - return d[var]["content"] + return d.getVar(var,exp) -def delVar(var, d = _data): +def delVar(var, d = _data_dict): """Removes a variable from the data set Example: @@ -105,10 +80,9 @@ def delVar(var, d = _data): >>> print getVar('TEST') None """ - if var in d: - del d[var] + d.delVar(var) -def setVarFlag(var, flag, flagvalue, d = _data): +def setVarFlag(var, flag, flagvalue, d = _data_dict): """Set a flag for a given variable to a given value Example: @@ -116,12 +90,9 @@ def setVarFlag(var, flag, flagvalue, d = _data): >>> print getVarFlag('TEST', 'python') 1 """ -# print "d[%s][\"flags\"][%s] = %s" % (var, flag, flagvalue) - if not var in d: - initVar(var, d) - d[var]["flags"][flag] = flagvalue + d.setVarFlag(var,flag,flagvalue) -def getVarFlag(var, flag, d = _data): +def getVarFlag(var, flag, d = _data_dict): """Gets given flag from given var Example: @@ -129,11 +100,9 @@ def getVarFlag(var, flag, d = _data): >>> print getVarFlag('TEST', 'python') 1 """ - if var in d and "flags" in d[var] and flag in d[var]["flags"]: - return d[var]["flags"][flag] - return None + return d.getVarFlag(var,flag) -def delVarFlag(var, flag, d = _data): +def delVarFlag(var, flag, d = _data_dict): """Removes a given flag from the variable's flags Example: @@ -145,10 +114,9 @@ def delVarFlag(var, flag, d = _data): None """ - if var in d and "flags" in d[var] and flag in d[var]["flags"]: - del d[var]["flags"][flag] + d.delVarFlag(var,flag) -def setVarFlags(var, flags, d = _data): +def setVarFlags(var, flags, d = _data_dict): """Set the flags for a given variable Example: @@ -158,11 +126,9 @@ def setVarFlags(var, flags, d = _data): >>> print getVarFlag('TEST', 'test') blah """ - if not var in d: - initVar(var, d) - d[var]["flags"] = flags + d.setVarFlags(var,flags) -def getVarFlags(var, d = _data): +def getVarFlags(var, d = _data_dict): """Gets a variable's flags Example: @@ -170,11 +136,9 @@ def getVarFlags(var, d = _data): >>> print getVarFlags('TEST')['test'] blah """ - if var in d and "flags" in d[var]: - return d[var]["flags"] - return None + return d.getVarFlags(var) -def delVarFlags(var, d = _data): +def delVarFlags(var, d = _data_dict): """Removes a variable's flags Example: @@ -186,21 +150,33 @@ def delVarFlags(var, d = _data): None """ - if var in d and "flags" in d[var]: - del d[var]["flags"] + d.delVarFlags(var) + +def keys(d = _data_dict): + """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 d.keys() -def getData(d = _data): +def getData(d = _data_dict): """Returns the data object used""" return d -def setData(newData, d = _data): +def setData(newData, d = _data_dict): """Sets the data object to the supplied value""" d = newData __expand_var_regexp__ = re.compile(r"\${[^{}]+}") __expand_python_regexp__ = re.compile(r"\${@.+?}") -def expand(s, d = _data, varname = None): +def expand(s, d = _data_dict, varname = None): """Variable expansion using the data store. Example: @@ -251,11 +227,11 @@ def expand(s, d = _data, varname = None): raise return s -def expandKeys(alterdata = _data, readdata = None): +def expandKeys(alterdata = _data_dict, readdata = None): if readdata == None: readdata = alterdata - for key in alterdata.keys(): + for key in keys(alterdata): ekey = expand(key, readdata) if key == ekey: continue @@ -274,7 +250,7 @@ def expandKeys(alterdata = _data, readdata = None): delVar(key, alterdata) -def expandData(alterdata = _data, readdata = None): +def expandData(alterdata = _data_dict, readdata = None): """For each variable in alterdata, expand it, and update the var contents. Replacements use data from readdata. @@ -290,7 +266,7 @@ def expandData(alterdata = _data, readdata = None): if readdata == None: readdata = alterdata - for key in alterdata.keys(): + for key in keys(alterdata): val = getVar(key, alterdata) if type(val) is not types.StringType: continue @@ -301,7 +277,7 @@ def expandData(alterdata = _data, readdata = None): import os -def inheritFromOS(d = _data): +def inheritFromOS(d = _data_dict): """Inherit variables from the environment.""" # fakeroot needs to be able to set these non_inherit_vars = [ "LD_LIBRARY_PATH", "LD_PRELOAD" ] @@ -315,7 +291,7 @@ def inheritFromOS(d = _data): import sys -def emit_var(var, o=sys.__stdout__, d = _data, all=False): +def emit_var(var, o=sys.__stdout__, d = _data_dict, all=False): """Emit a variable to be sourced by a shell.""" if getVarFlag(var, "python", d): return 0 @@ -365,10 +341,10 @@ def emit_var(var, o=sys.__stdout__, d = _data, all=False): return 1 -def emit_env(o=sys.__stdout__, d = _data, all=False): +def emit_env(o=sys.__stdout__, d = _data_dict, all=False): """Emits all items in the data store in a format such that it can be sourced by a shell.""" - env = d.keys() + env = keys(d) for e in env: if getVarFlag(e, "func", d): @@ -380,7 +356,7 @@ def emit_env(o=sys.__stdout__, d = _data, all=False): continue emit_var(e, o, d) and o.write('\n') -def update_data(d = _data): +def update_data(d = _data_dict): """Modifies the environment vars according to local overrides and commands. Examples: Appending to a variable: @@ -423,7 +399,7 @@ def update_data(d = _data): dodel = [] overrides = (getVar('OVERRIDES', d, 1) or "").split(':') or [] - def applyOverrides(var, d = _data): + def applyOverrides(var, d = _data_dict): if not overrides: debug(1, "OVERRIDES not defined, nothing to do") return @@ -434,7 +410,7 @@ def update_data(d = _data): name = var[:-l] d[name] = d[var] - for s in d.keys(): + for s in keys(d): applyOverrides(s, d) sval = getVar(s, d) or "" diff --git a/lib/bb/data_dict.py b/lib/bb/data_dict.py new file mode 100644 index 000000000..8c6f3d836 --- /dev/null +++ b/lib/bb/data_dict.py @@ -0,0 +1,173 @@ +# ex:ts=4:sw=4:sts=4:et +# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- +""" +BitBake 'Data-Dict' implementation + +Functions for interacting with the data structure used by the +BitBake build tools. + +Copyright (C) 2003, 2004 Chris Larson +Copyright (C) 2005 Holger Hans Peter Freyther + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307 USA. + +Based on functions from the base bb module, Copyright 2003 Holger Schurig +""" + +import os, re, sys, types +from bb import note, debug, fatal + +__setvar_regexp__ = {} +__setvar_regexp__["_append"] = re.compile('(?P.*?)%s(_(?P.*))?' % "_append") +__setvar_regexp__["_prepend"] = re.compile('(?P.*?)%s(_(?P.*))?' % "_prepend") +__setvar_regexp__["_delete"] = re.compile('(?P.*?)%s(_(?P.*))?' % "_delete") + +__expand_var_regexp__ = re.compile(r"\${[^{}]+}") +__expand_python_regexp__ = re.compile(r"\${@.+?}") + + +class DataDict: + def __init__(self): + self.dict = {} + + def expand(self,s, varname): + def var_sub(match): + key = match.group()[2:-1] + if varname and key: + if varname == key: + raise Exception("variable %s references itself!" % varname) + var = self.getVar(key, 1) + if var is not None: + return var + else: + return match.group() + + def python_sub(match): + import bb + code = match.group()[3:-1] + locals()['d'] = self + s = eval(code) + if type(s) == types.IntType: s = str(s) + return s + + if type(s) is not types.StringType: # sanity check + return s + + while s.find('$') != -1: + olds = s + try: + s = __expand_var_regexp__.sub(var_sub, s) + s = __expand_python_regexp__.sub(python_sub, s) + if s == olds: break + if type(s) is not types.StringType: # sanity check + import bb + bb.error('expansion of %s returned non-string %s' % (olds, s)) + except KeyboardInterrupt: + raise + except: + note("%s:%s while evaluating:\n%s" % (sys.exc_info()[0], sys.exc_info()[1], s)) + raise + return s + + def initVar(self, var): + if not var in self.dict: + self.dict[var] = {} + + if not "flags" in self.dict[var]: + self.dict[var]["flags"] = {} + + def setVar(self,var,value): + for v in ["_append", "_prepend", "_delete"]: + match = __setvar_regexp__[v].match(var) + + if match: + base = match.group('base') + override = match.group('add') + l = self.getVarFlag(base, v) or [] + if override == 'delete': + if l.count([value, None]): + del l[l.index([value, None])] + l.append([value, override]) + self.setVarFlag(base, v, l) + return + + self.initVar(var) + if self.getVarFlag(var, 'matchesenv'): + self.delVarFlag(var, 'matchesenv') + self.setVarFlag(var, 'export', 1) + self.dict[var]["content"] = value + + def getVar(self,var,exp): + if not var in self.dict or not "content" in self.dict[var]: + return None + + if exp: + return self.expand(self.dict[var]["content"], var) + return self.dict[var]["content"] + + def delVar(self,var): + if var in self.dict: + del self.dict[var] + + def setVarFlag(self,var,flag,flagvalue): + self.initVar(var) + self.dict[var]["flags"][flag] = flagvalue + + def getVarFlag(self,var,flag): + if var in self.dict and "flags" in self.dict[var] and flag in self.dict[var]["flags"]: + di = self.dict[var] + di = di["flags"] + return di[flag] + return None + + def delVarFlag(self,var,flag): + if var in self.dict and "flags" in self.dict[var] and flag in self.dict[var]["flags"]: + del self.dict[var]["flags"][flag] + + def setVarFlags(self,var,flags): + self.initVar(var) + if flags == None: + debug("Setting Null Flag %s" % var) + + self.dict[var]["flags"] = flags + + def getVarFlags(self,var): + if var in self.dict and "flags" in self.dict[var]: + return self.dict[var]["flags"] + + return None + + def delVarFlags(self,var): + if var in self.dict and "flags" in self.dict[var]: + del self.dict[var]["flags"] + + # Dictionary Methods + def keys(self): + return self.dict.keys() + + def iterkeys(self): + return self.dict.iterkeys() + + def iteritems(self): + return self.dict.iteritems() + + def items(self): + return self.dict.items() + + def __getitem__(self,y): + return self.dict.__getitem__(y) + + def __setitem__(self,x,y): + self.dict.__setitem__(x,y) + diff --git a/lib/bb/parse/BBHandler.py b/lib/bb/parse/BBHandler.py index 70d84cb06..7ff3909ad 100644 --- a/lib/bb/parse/BBHandler.py +++ b/lib/bb/parse/BBHandler.py @@ -64,7 +64,7 @@ def inherit(files, d): data.setVar('__inherit_cache', __inherit_cache, d) -def handle(fn, d = {}, include = 0): +def handle(fn, d = data.init(), include = 0): global __func_start_regexp__, __inherit_regexp__, __export_func_regexp__, __addtask_regexp__, __addhandler_regexp__, __infunc__, __body__, __bbpath_found__, __residue__ __body__ = [] __bbpath_found__ = 0 @@ -156,7 +156,7 @@ def handle(fn, d = {}, include = 0): set_additional_vars(fn, d, include) data.update_data(d) - for var in d.keys(): + for var in data.keys(d): if data.getVarFlag(var, 'handler', d): bb.event.register(data.getVar(var, d)) continue diff --git a/lib/bb/parse/ConfHandler.py b/lib/bb/parse/ConfHandler.py index 43cdec665..c001044b8 100644 --- a/lib/bb/parse/ConfHandler.py +++ b/lib/bb/parse/ConfHandler.py @@ -51,7 +51,7 @@ def localpath(fn, d): localfn = fn return localfn -def obtain(fn, data = {}): +def obtain(fn, data = bb.data.init()): import sys, bb fn = bb.data.expand(fn, data) localfn = bb.data.expand(localpath(fn, data), data) @@ -82,7 +82,7 @@ def obtain(fn, data = {}): return localfn -def include(oldfn, fn, data = {}): +def include(oldfn, fn, data = bb.data.init()): if oldfn == fn: # prevent infinate recursion return None @@ -96,7 +96,7 @@ def include(oldfn, fn, data = {}): except IOError: debug(2, "CONF file '%s' not found" % fn) -def handle(fn, data = {}, include = 0): +def handle(fn, data = bb.data.init(), include = 0): if include: inc_string = "including" else: @@ -153,7 +153,7 @@ def handle(fn, data = {}, include = 0): bb.data.setVar('FILE', oldfile, data) return data -def feeder(lineno, s, fn, data = {}): +def feeder(lineno, s, fn, data = bb.data.init()): m = __config_regexp__.match(s) if m: groupd = m.groupdict() -- cgit 1.2.3-korg