3 # Thomas Nagy, 2005 (ita)
5 """Environment representation
7 There is one gotcha: getitem returns [] if the contents evals to False
8 This means env['foo'] = {}; print env['foo'] will print [] not {}
12 import Logs
, Options
, Utils
13 from Constants
import *
14 re_imp
= re
.compile('^(#)*?([^#=]*?)\ =\ (.*?)$', re
.M
)
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
20 __slots__
= ("table", "parent")
21 def __init__(self
, filename
=None):
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
37 keys
.update(cur
.table
.keys())
38 cur
= getattr(cur
, 'parent', None)
41 return "\n".join(["%r %r" % (x
, self
.__getitem
__(x
)) for x
in keys
])
43 def __getitem__(self
, key
):
46 x
= self
.table
.get(key
, None)
50 except AttributeError:
53 def __setitem__(self
, key
, value
):
54 self
.table
[key
] = value
56 def __delitem__(self
, key
):
59 def pop(self
, key
, *args
):
61 return self
.table
.pop(key
, *args
)
62 return self
.table
.pop(key
)
64 def set_variant(self
, name
):
65 self
.table
[VARIANT
] = name
70 x
= self
.table
.get(VARIANT
, None)
74 except AttributeError:
78 # TODO waf 1.6 rename this method derive, #368
79 newenv
= Environment()
85 modifying the original env will not change the copy"""
86 tbl
= self
.get_merged_dict()
88 delattr(self
, 'parent')
89 except AttributeError:
94 tbl
[x
] = copy
.deepcopy(tbl
[x
])
97 def get_flat(self
, key
):
99 if isinstance(s
, str): return s
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.
108 value
= self
.table
[key
]
110 try: value
= self
.parent
[key
]
111 except AttributeError: value
= []
112 if isinstance(value
, list):
117 if not isinstance(value
, list):
119 self
.table
[key
] = value
122 def append_value(self
, var
, value
):
123 current_value
= self
._get
_list
_value
_for
_modification
(var
)
125 if isinstance(value
, list):
126 current_value
.extend(value
)
128 current_value
.append(value
)
130 def prepend_value(self
, var
, value
):
131 current_value
= self
._get
_list
_value
_for
_modification
(var
)
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
138 current_value
.insert(0, value
)
140 # prepend unique would be ambiguous
141 def append_unique(self
, var
, value
):
142 current_value
= self
._get
_list
_value
_for
_modification
(var
)
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
)
149 if value
not in current_value
:
150 current_value
.append(value
)
152 def get_merged_dict(self
):
153 """compute a merged table"""
157 table_list
.insert(0, env
.table
)
158 try: env
= env
.parent
159 except AttributeError: break
161 for table
in table_list
:
162 merged_table
.update(table
)
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())
171 for k
in keys
: file.write('%s = %r\n' % (k
, merged_table
[k
]))
174 def load(self
, filename
):
175 "Retrieve the variables from a file"
177 code
= Utils
.readf(filename
)
178 for m
in re_imp
.finditer(code
):
180 tbl
[g(2)] = eval(g(3))
181 Logs
.debug('env: %s', self
.table
)
183 def get_destdir(self
):
184 "return the destdir, useful for installing"
185 if self
.__getitem
__('NOINSTALL'): return ''
186 return Options
.options
.destdir
189 for k
, v
in d
.iteritems():
193 def __getattr__(self
, name
):
194 if name
in self
.__slots
__:
195 return object.__getattr
__(self
, name
)
199 def __setattr__(self
, name
, value
):
200 if name
in self
.__slots
__:
201 object.__setattr
__(self
, name
, value
)
205 def __delattr__(self
, name
):
206 if name
in self
.__slots
__:
207 object.__delattr
__(self
, name
)