1 # ex:ts=4:sw=4:sts=4:et
2 # -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
4 BitBake 'Data-Dict' implementation
6 Functions for interacting with the data structure used by the
9 Copyright (C) 2003, 2004 Chris Larson
10 Copyright (C) 2005 Holger Hans Peter Freyther
12 This program is free software; you can redistribute it and/or modify it under
13 the terms of the GNU General Public License as published by the Free Software
14 Foundation; either version 2 of the License, or (at your option) any later
17 This program is distributed in the hope that it will be useful, but WITHOUT
18 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License along with
22 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
23 Place, Suite 330, Boston, MA 02111-1307 USA.
25 Based on functions from the base bb module, Copyright 2003 Holger Schurig
28 import os, re, sys, types, copy
29 from bb import note, debug, fatal
32 import cPickle as pickle
35 print "NOTE: Importing cPickle failed. Falling back to a very slow implementation."
39 __setvar_regexp__ = {}
40 __setvar_regexp__["_append"] = re.compile('(?P<base>.*?)%s(_(?P<add>.*))?' % "_append")
41 __setvar_regexp__["_prepend"] = re.compile('(?P<base>.*?)%s(_(?P<add>.*))?' % "_prepend")
42 __setvar_regexp__["_delete"] = re.compile('(?P<base>.*?)%s(_(?P<add>.*))?' % "_delete")
44 __expand_var_regexp__ = re.compile(r"\${[^{}]+}")
45 __expand_python_regexp__ = re.compile(r"\${@.+?}")
52 def expand(self,s, varname):
54 key = match.group()[2:-1]
57 raise Exception("variable %s references itself!" % varname)
58 var = self.getVar(key, 1)
64 def python_sub(match):
66 code = match.group()[3:-1]
69 if type(s) == types.IntType: s = str(s)
72 if type(s) is not types.StringType: # sanity check
75 while s.find('$') != -1:
78 s = __expand_var_regexp__.sub(var_sub, s)
79 s = __expand_python_regexp__.sub(python_sub, s)
81 if type(s) is not types.StringType: # sanity check
83 bb.error('expansion of %s returned non-string %s' % (olds, s))
84 except KeyboardInterrupt:
87 note("%s:%s while evaluating:\n%s" % (sys.exc_info()[0], sys.exc_info()[1], s))
91 def initVar(self, var):
92 if not var in self.dict:
95 if not "flags" in self.dict[var]:
96 self.dict[var]["flags"] = {}
98 def setVar(self,var,value):
99 for v in ["_append", "_prepend", "_delete"]:
100 match = __setvar_regexp__[v].match(var)
103 base = match.group('base')
104 override = match.group('add')
105 l = self.getVarFlag(base, v) or []
106 if override == 'delete':
107 if l.count([value, None]):
108 del l[l.index([value, None])]
109 l.append([value, override])
110 self.setVarFlag(base, v, l)
114 if self.getVarFlag(var, 'matchesenv'):
115 self.delVarFlag(var, 'matchesenv')
116 self.setVarFlag(var, 'export', 1)
117 self.dict[var]["content"] = value
119 def getVar(self,var,exp):
120 if not var in self.dict or not "content" in self.dict[var]:
124 return self.expand(self.dict[var]["content"], var)
125 return self.dict[var]["content"]
127 def delVar(self,var):
131 def setVarFlag(self,var,flag,flagvalue):
133 self.dict[var]["flags"][flag] = flagvalue
135 def getVarFlag(self,var,flag):
136 if var in self.dict and "flags" in self.dict[var] and flag in self.dict[var]["flags"]:
142 def delVarFlag(self,var,flag):
143 if var in self.dict and "flags" in self.dict[var] and flag in self.dict[var]["flags"]:
144 del self.dict[var]["flags"][flag]
146 def setVarFlags(self,var,flags):
149 debug("Setting Null Flag %s" % var)
151 self.dict[var]["flags"] = flags
153 def getVarFlags(self,var):
154 if var in self.dict and "flags" in self.dict[var]:
155 return self.dict[var]["flags"]
159 def delVarFlags(self,var):
160 if var in self.dict and "flags" in self.dict[var]:
161 del self.dict[var]["flags"]
163 def createCopy(self):
164 return copy.deepcopy(self)
168 return self.dict.keys()
171 return self.dict.iterkeys()
174 return self.dict.iteritems()
177 return self.dict.items()
179 def __getitem__(self,y):
180 return self.dict.__getitem__(y)
182 def __setitem__(self,x,y):
183 self.dict.__setitem__(x,y)
187 class DataDictPackage(DataDict):
189 Persistent Data Storage
191 def sanitize_filename(bbfile):
192 return bbfile.replace( '/', '_' )
193 sanitize_filename = staticmethod(sanitize_filename)
197 Restore the dict from memory
199 cache_bbfile = self.sanitize_filename(self.bbfile)
200 p = pickle.Unpickler( file("%s/%s"%(self.cache,cache_bbfile),"rb"))
202 funcstr = self.getVar('__functions__', 0)
204 comp = compile(funcstr, "<pickled>", "exec")
205 exec comp in __builtins__
207 def linkDataSet(self,parent):
208 from copy import deepcopy
209 if not parent == None:
210 self.dict = deepcopy(parent)
213 def __init__(self,cache,name,clean,parent):
215 Construct a persistent data instance
217 #Initialize the dictionary
218 DataDict.__init__(self)
223 # Either unpickle the data or do copy on write
225 self.linkDataSet(parent)
229 def commit(self, mtime):
231 Save the package to a permanent storage
233 cache_bbfile = self.sanitize_filename(self.bbfile)
234 p = pickle.Pickler(file("%s/%s" %(self.cache,cache_bbfile), "wb" ), -1 )
237 def mtime(cache,bbfile):
238 cache_bbfile = DataDictPackage.sanitize_filename(bbfile)
240 return os.stat( "%s/%s" % (cache,cache_bbfile) )[8]
243 mtime = staticmethod(mtime)