aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <zecke@selfish.org>2005-05-17 18:04:46 +0000
committerHolger Hans Peter Freyther <zecke@selfish.org>2005-05-17 18:04:46 +0000
commitc7f7cfd506f504f658088bc0c7ee9f487d8a3d3f (patch)
tree4c031f0154c212f14bf3754236369324a472b260
parentf07abf6a9cd413ef71db0023288f5868a9d83ec6 (diff)
downloadbitbake-c7f7cfd506f504f658088bc0c7ee9f487d8a3d3f.tar.gz
bitbake-c7f7cfd506f504f658088bc0c7ee9f487d8a3d3f.tar.bz2
bitbake-c7f7cfd506f504f658088bc0c7ee9f487d8a3d3f.zip
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
-rw-r--r--classes/base.bbclass4
-rw-r--r--lib/bb/data.py132
-rw-r--r--lib/bb/data_dict.py173
-rw-r--r--lib/bb/parse/BBHandler.py4
-rw-r--r--lib/bb/parse/ConfHandler.py8
5 files changed, 235 insertions, 86 deletions
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<base>.*?)%s(_(?P<add>.*))?' % "_append")
-__setvar_regexp__["_prepend"] = re.compile('(?P<base>.*?)%s(_(?P<add>.*))?' % "_prepend")
-__setvar_regexp__["_delete"] = re.compile('(?P<base>.*?)%s(_(?P<add>.*))?' % "_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<base>.*?)%s(_(?P<add>.*))?' % "_append")
+__setvar_regexp__["_prepend"] = re.compile('(?P<base>.*?)%s(_(?P<add>.*))?' % "_prepend")
+__setvar_regexp__["_delete"] = re.compile('(?P<base>.*?)%s(_(?P<add>.*))?' % "_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()