bea4146516568e51ce2e91bb934141ae558f6935
[obnox/samba/samba-obnox.git] / third_party / waf / wafadmin / Environment.py
1 #!/usr/bin/env python
2 # encoding: utf-8
3 # Thomas Nagy, 2005 (ita)
4
5 """Environment representation
6
7 There is one gotcha: getitem returns [] if the contents evals to False
8 This means env['foo'] = {}; print env['foo'] will print [] not {}
9 """
10
11 import os, copy, re
12 import Logs, Options, Utils
13 from Constants import *
14 re_imp = re.compile('^(#)*?([^#=]*?)\ =\ (.*?)$', re.M)
15
16 class Environment(object):
17         """A safe-to-use dictionary, but do not attach functions to it please (break cPickle)
18         An environment instance can be stored into a file and loaded easily
19         """
20         __slots__ = ("table", "parent")
21         def __init__(self, filename=None):
22                 self.table = {}
23                 #self.parent = None
24
25                 if filename:
26                         self.load(filename)
27
28         def __contains__(self, key):
29                 if key in self.table: return True
30                 try: return self.parent.__contains__(key)
31                 except AttributeError: return False # parent may not exist
32
33         def __str__(self):
34                 keys = set()
35                 cur = self
36                 while cur:
37                         keys.update(cur.table.keys())
38                         cur = getattr(cur, 'parent', None)
39                 keys = list(keys)
40                 keys.sort()
41                 return "\n".join(["%r %r" % (x, self.__getitem__(x)) for x in keys])
42
43         def __getitem__(self, key):
44                 try:
45                         while 1:
46                                 x = self.table.get(key, None)
47                                 if not x is None:
48                                         return x
49                                 self = self.parent
50                 except AttributeError:
51                         return []
52
53         def __setitem__(self, key, value):
54                 self.table[key] = value
55
56         def __delitem__(self, key):
57                 del self.table[key]
58
59         def pop(self, key, *args):
60                 if len(args):
61                         return self.table.pop(key, *args)
62                 return self.table.pop(key)
63
64         def set_variant(self, name):
65                 self.table[VARIANT] = name
66
67         def variant(self):
68                 try:
69                         while 1:
70                                 x = self.table.get(VARIANT, None)
71                                 if not x is None:
72                                         return x
73                                 self = self.parent
74                 except AttributeError:
75                         return DEFAULT
76
77         def copy(self):
78                 # TODO waf 1.6 rename this method derive, #368
79                 newenv = Environment()
80                 newenv.parent = self
81                 return newenv
82
83         def detach(self):
84                 """TODO try it
85                 modifying the original env will not change the copy"""
86                 tbl = self.get_merged_dict()
87                 try:
88                         delattr(self, 'parent')
89                 except AttributeError:
90                         pass
91                 else:
92                         keys = tbl.keys()
93                         for x in keys:
94                                 tbl[x] = copy.deepcopy(tbl[x])
95                         self.table = tbl
96
97         def get_flat(self, key):
98                 s = self[key]
99                 if isinstance(s, str): return s
100                 return ' '.join(s)
101
102         def _get_list_value_for_modification(self, key):
103                 """Gets a value that must be a list for further modification.  The
104                 list may be modified inplace and there is no need to
105                 "self.table[var] = value" afterwards.
106                 """
107                 try:
108                         value = self.table[key]
109                 except KeyError:
110                         try: value = self.parent[key]
111                         except AttributeError: value = []
112                         if isinstance(value, list):
113                                 value = value[:]
114                         else:
115                                 value = [value]
116                 else:
117                         if not isinstance(value, list):
118                                 value = [value]
119                 self.table[key] = value
120                 return value
121
122         def append_value(self, var, value):
123                 current_value = self._get_list_value_for_modification(var)
124
125                 if isinstance(value, list):
126                         current_value.extend(value)
127                 else:
128                         current_value.append(value)
129
130         def prepend_value(self, var, value):
131                 current_value = self._get_list_value_for_modification(var)
132
133                 if isinstance(value, list):
134                         current_value = value + current_value
135                         # a new list: update the dictionary entry
136                         self.table[var] = current_value
137                 else:
138                         current_value.insert(0, value)
139
140         # prepend unique would be ambiguous
141         def append_unique(self, var, value):
142                 current_value = self._get_list_value_for_modification(var)
143
144                 if isinstance(value, list):
145                         for value_item in value:
146                                 if value_item not in current_value:
147                                         current_value.append(value_item)
148                 else:
149                         if value not in current_value:
150                                 current_value.append(value)
151
152         def get_merged_dict(self):
153                 """compute a merged table"""
154                 table_list = []
155                 env = self
156                 while 1:
157                         table_list.insert(0, env.table)
158                         try: env = env.parent
159                         except AttributeError: break
160                 merged_table = {}
161                 for table in table_list:
162                         merged_table.update(table)
163                 return merged_table
164
165         def store(self, filename):
166                 "Write the variables into a file"
167                 file = open(filename, 'w')
168                 merged_table = self.get_merged_dict()
169                 keys = list(merged_table.keys())
170                 keys.sort()
171                 for k in keys: file.write('%s = %r\n' % (k, merged_table[k]))
172                 file.close()
173
174         def load(self, filename):
175                 "Retrieve the variables from a file"
176                 tbl = self.table
177                 code = Utils.readf(filename)
178                 for m in re_imp.finditer(code):
179                         g = m.group
180                         tbl[g(2)] = eval(g(3))
181                 Logs.debug('env: %s', self.table)
182
183         def get_destdir(self):
184                 "return the destdir, useful for installing"
185                 if self.__getitem__('NOINSTALL'): return ''
186                 return Options.options.destdir
187
188         def update(self, d):
189                 for k, v in d.iteritems():
190                         self[k] = v
191
192
193         def __getattr__(self, name):
194                 if name in self.__slots__:
195                         return object.__getattr__(self, name)
196                 else:
197                         return self[name]
198
199         def __setattr__(self, name, value):
200                 if name in self.__slots__:
201                         object.__setattr__(self, name, value)
202                 else:
203                         self[name] = value
204
205         def __delattr__(self, name):
206                 if name in self.__slots__:
207                         object.__delattr__(self, name)
208                 else:
209                         del self[name]