Complete conversion to use bb.msg
[bitbake.git] / lib / bb / data_smart.py
1 # ex:ts=4:sw=4:sts=4:et
2 # -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
3 """
4 BitBake Smart Dictionary Implementation
5
6 Functions for interacting with the data structure used by the
7 BitBake build tools.
8
9 Copyright (C) 2003, 2004  Chris Larson
10 Copyright (C) 2004, 2005  Seb Frankengul
11 Copyright (C) 2005, 2006  Holger Hans Peter Freyther
12 Copyright (C) 2005        Uli Luckas
13 Copyright (C) 2005        ROAD GmbH
14
15 This program is free software; you can redistribute it and/or modify it under
16 the terms of the GNU General Public License as published by the Free Software
17 Foundation; either version 2 of the License, or (at your option) any later
18 version.
19
20 This program is distributed in the hope that it will be useful, but WITHOUT
21 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
22 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
23
24 You should have received a copy of the GNU General Public License along with
25 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
26 Place, Suite 330, Boston, MA 02111-1307 USA. 
27
28 Based on functions from the base bb module, Copyright 2003 Holger Schurig
29 """
30
31 import copy, os, re, sys, time, types
32 import bb
33 from bb   import utils, methodpool
34 from COW  import COWDictBase
35 from sets import Set
36 from new  import classobj
37
38
39 __setvar_keyword__ = ["_append","_prepend"]
40 __setvar_regexp__ = re.compile('(?P<base>.*?)(?P<keyword>_append|_prepend)(_(?P<add>.*))?')
41 __expand_var_regexp__ = re.compile(r"\${[^{}]+}")
42 __expand_python_regexp__ = re.compile(r"\${@.+?}")
43
44
45 class DataSmart:
46     def __init__(self, special = COWDictBase.copy(), seen = COWDictBase.copy() ):
47         self.dict = {}
48
49         # cookie monster tribute
50         self._special_values = special
51         self._seen_overrides = seen
52
53     def expand(self,s, varname):
54         def var_sub(match):
55             key = match.group()[2:-1]
56             if varname and key:
57                 if varname == key:
58                     raise Exception("variable %s references itself!" % varname)
59             var = self.getVar(key, 1)
60             if var is not None:
61                 return var
62             else:
63                 return match.group()
64
65         def python_sub(match):
66             import bb
67             code = match.group()[3:-1]
68             locals()['d'] = self
69             s = eval(code)
70             if type(s) == types.IntType: s = str(s)
71             return s
72
73         if type(s) is not types.StringType: # sanity check
74             return s
75
76         while s.find('$') != -1:
77             olds = s
78             try:
79                 s = __expand_var_regexp__.sub(var_sub, s)
80                 s = __expand_python_regexp__.sub(python_sub, s)
81                 if s == olds: break
82                 if type(s) is not types.StringType: # sanity check
83                     bb.msg.error(bb.msg.domain.Data, 'expansion of %s returned non-string %s' % (olds, s))
84             except KeyboardInterrupt:
85                 raise
86             except:
87                 bb.msg.note(1, bb.msg.domain.Data, "%s:%s while evaluating:\n%s" % (sys.exc_info()[0], sys.exc_info()[1], s))
88                 raise
89         return s
90
91     def initVar(self, var):
92         if not var in self.dict:
93             self.dict[var] = {}
94
95     def _findVar(self,var):
96         _dest = self.dict
97
98         while (_dest and var not in _dest):
99             if not "_data" in _dest:
100                 _dest = None
101                 break
102             _dest = _dest["_data"]
103
104         if _dest and var in _dest:
105             return _dest[var]
106         return None
107
108     def _makeShadowCopy(self, var):
109         if var in self.dict:
110             return
111
112         local_var = self._findVar(var)
113
114         if local_var:
115             self.dict[var] = copy.copy(local_var)
116         else:
117             self.initVar(var)
118
119     def setVar(self,var,value):
120         match  = __setvar_regexp__.match(var)
121         if match and match.group("keyword") in __setvar_keyword__:
122             base = match.group('base')
123             keyword = match.group("keyword")
124             override = match.group('add')
125             l = self.getVarFlag(base, keyword) or []
126             l.append([value, override])
127             self.setVarFlag(base, keyword, l)
128
129             # todo make sure keyword is not __doc__ or __module__
130             # pay the cookie monster
131             try:
132                 self._special_values[keyword].add( base )
133             except:
134                 self._special_values[keyword] = Set()
135                 self._special_values[keyword].add( base )
136
137             return
138
139         if not var in self.dict:
140             self._makeShadowCopy(var)
141         if self.getVarFlag(var, 'matchesenv'):
142             self.delVarFlag(var, 'matchesenv')
143             self.setVarFlag(var, 'export', 1)
144
145         # more cookies for the cookie monster
146         if '_' in var:
147             override = var[var.rfind('_')+1:]
148             if not self._seen_overrides.has_key(override):
149                 self._seen_overrides[override] = Set()
150             self._seen_overrides[override].add( var )
151
152         # setting var
153         self.dict[var]["content"] = value
154
155     def getVar(self,var,exp):
156         value = self.getVarFlag(var,"content")
157
158         if exp and value:
159             return self.expand(value,var)
160         return value
161
162     def delVar(self,var):
163         self.dict[var] = {}
164
165     def setVarFlag(self,var,flag,flagvalue):
166         if not var in self.dict:
167             self._makeShadowCopy(var)
168         self.dict[var][flag] = flagvalue
169
170     def getVarFlag(self,var,flag):
171         local_var = self._findVar(var)
172         if local_var:
173             if flag in local_var:
174                 return copy.copy(local_var[flag])
175         return None
176
177     def delVarFlag(self,var,flag):
178         local_var = self._findVar(var)
179         if not local_var:
180             return
181         if not var in self.dict:
182             self._makeShadowCopy(var)
183
184         if var in self.dict and flag in self.dict[var]:
185             del self.dict[var][flag]
186
187     def setVarFlags(self,var,flags):
188         if not var in self.dict:
189             self._makeShadowCopy(var)
190
191         for i in flags.keys():
192             if i == "content":
193                 continue
194             self.dict[var][i] = flags[i]
195
196     def getVarFlags(self,var):
197         local_var = self._findVar(var)
198         flags = {}
199
200         if local_var:
201             for i in self.dict[var].keys():
202                 if i == "content":
203                     continue
204                 flags[i] = self.dict[var][i]
205
206         if len(flags) == 0:
207             return None
208         return flags
209
210
211     def delVarFlags(self,var):
212         if not var in self.dict:
213             self._makeShadowCopy(var)
214
215         if var in self.dict:
216             content = None
217
218             # try to save the content
219             if "content" in self.dict[var]:
220                 content  = self.dict[var]["content"]
221                 self.dict[var]            = {}
222                 self.dict[var]["content"] = content
223             else:
224                 del self.dict[var]
225
226
227     def createCopy(self):
228         """
229         Create a copy of self by setting _data to self
230         """
231         # we really want this to be a DataSmart...
232         data = DataSmart(seen=self._seen_overrides.copy(), special=self._special_values.copy())
233         data.dict["_data"] = self.dict
234
235         return data
236
237     # Dictionary Methods
238     def keys(self):
239         def _keys(d, mykey):
240             if "_data" in d:
241                 _keys(d["_data"],mykey)
242
243             for key in d.keys():
244                 if key != "_data":
245                     mykey[key] = None
246         keytab = {}
247         _keys(self.dict,keytab)
248         return keytab.keys()
249
250     def __getitem__(self,item):
251         #print "Warning deprecated"
252         return self.getVar(item, False)
253
254     def __setitem__(self,var,data):
255         #print "Warning deprecated"
256         self.setVar(var,data)
257
258