Show More
@@ -111,7 +111,7 b' class ColorScheme:' | |||||
111 | """Return a full copy of the object, optionally renaming it.""" |
|
111 | """Return a full copy of the object, optionally renaming it.""" | |
112 | if name is None: |
|
112 | if name is None: | |
113 | name = self.name |
|
113 | name = self.name | |
114 |
return ColorScheme(name,self.colors. |
|
114 | return ColorScheme(name, self.colors.dict()) | |
115 |
|
115 | |||
116 | class ColorSchemeTable(dict): |
|
116 | class ColorSchemeTable(dict): | |
117 | """General class to handle tables of color schemes. |
|
117 | """General class to handle tables of color schemes. |
@@ -11,12 +11,13 b'' | |||||
11 |
|
11 | |||
12 | __all__ = ['Struct'] |
|
12 | __all__ = ['Struct'] | |
13 |
|
13 | |||
|
14 | import inspect | |||
14 | import types |
|
15 | import types | |
15 | import pprint |
|
16 | import pprint | |
16 |
|
17 | |||
17 | from IPython.utils.genutils import list2dict2 |
|
18 | from IPython.utils.genutils import list2dict2 | |
18 |
|
19 | |||
19 | class Struct: |
|
20 | class Struct(object): | |
20 | """Class to mimic C structs but also provide convenient dictionary-like |
|
21 | """Class to mimic C structs but also provide convenient dictionary-like | |
21 | functionality. |
|
22 | functionality. | |
22 |
|
23 | |||
@@ -105,222 +106,224 b' class Struct:' | |||||
105 | 'merge popitem setdefault update values ' |
|
106 | 'merge popitem setdefault update values ' | |
106 | '__make_dict __dict_invert ').split() |
|
107 | '__make_dict __dict_invert ').split() | |
107 |
|
108 | |||
108 |
def __init__(self,d |
|
109 | def __init__(self,data=None,**kw): | |
109 |
"""Initialize with a dictionary, another Struct, or |
|
110 | """Initialize with a dictionary, another Struct, or data. | |
110 | explicitly the list of attributes. |
|
|||
111 |
|
111 | |||
112 | Both can be used, but the dictionary must come first: |
|
112 | Parameters | |
113 | Struct(dict), Struct(k1=v1,k2=v2) or Struct(dict,k1=v1,k2=v2). |
|
113 | ---------- | |
|
114 | data : dict, Struct | |||
|
115 | Initialize with this data. | |||
|
116 | kw : dict | |||
|
117 | Initialize with key, value pairs. | |||
|
118 | ||||
|
119 | Examples | |||
|
120 | -------- | |||
|
121 | ||||
114 | """ |
|
122 | """ | |
115 |
self |
|
123 | object.__setattr__(self, '_allownew', True) | |
116 | if dict is None: |
|
124 | object.__setattr__(self, '_data',{}) | |
117 | dict = {} |
|
125 | if data is None: | |
118 | if isinstance(dict,Struct): |
|
126 | data = {} | |
119 | dict = dict.dict() |
|
127 | if isinstance(data, Struct): | |
120 | elif dict and type(dict) is not types.DictType: |
|
128 | data = data.dict() | |
121 | raise TypeError,\ |
|
129 | elif data and not isinstance(data, dict): | |
122 |
|
|
130 | raise TypeError('initialize with a dict, Struct or key=val pairs') | |
123 |
d |
|
131 | data.update(kw) | |
124 | # do the updating by hand to guarantee that we go through the |
|
132 | # do the updating by hand to guarantee that we go through the | |
125 | # safety-checked __setitem__ |
|
133 | # safety-checked __setitem__ | |
126 |
for k,v in d |
|
134 | for k, v in data.items(): | |
127 | self[k] = v |
|
135 | self[k] = v | |
128 |
|
||||
129 |
|
136 | |||
130 | def __setitem__(self,key,value): |
|
137 | def __setitem__(self, key, value): | |
131 | """Used when struct[key] = val calls are made.""" |
|
138 | """Used when struct[key] = val calls are made.""" | |
132 | if key in Struct.__protected: |
|
139 | if isinstance(key, str): | |
133 | raise KeyError,'Key '+`key`+' is a protected key of class Struct.' |
|
140 | # I can't simply call hasattr here because it calls getattr, which | |
134 | if not self['__allownew'] and key not in self.__dict__: |
|
141 | # calls self.__getattr__, which returns True for keys in | |
|
142 | # self._data. But I only want keys in the class and in | |||
|
143 | # self.__dict__ | |||
|
144 | if key in self.__dict__ or hasattr(Struct, key): | |||
|
145 | raise KeyError( | |||
|
146 | 'key %s is a protected key of class Struct.' % key | |||
|
147 | ) | |||
|
148 | if not self._allownew and key not in self._data: | |||
135 | raise KeyError( |
|
149 | raise KeyError( | |
136 |
" |
|
150 | "can't create unknown attribute %s. Check for typos, or use allow_new_attr" % key) | |
137 | key) |
|
151 | self._data[key] = value | |
138 |
|
||||
139 | self.__dict__[key] = value |
|
|||
140 |
|
152 | |||
141 | def __setattr__(self, key, value): |
|
153 | def __setattr__(self, key, value): | |
142 | """Used when struct.key = val calls are made.""" |
|
154 | self.__setitem__(key, value) | |
143 | self.__setitem__(key,value) |
|
155 | ||
|
156 | def __getattr__(self, key): | |||
|
157 | try: | |||
|
158 | result = self._data[key] | |||
|
159 | except KeyError: | |||
|
160 | raise AttributeError(key) | |||
|
161 | else: | |||
|
162 | return result | |||
|
163 | ||||
|
164 | def __getitem__(self, key): | |||
|
165 | return self._data[key] | |||
144 |
|
166 | |||
145 | def __str__(self): |
|
167 | def __str__(self): | |
146 | """Gets called by print.""" |
|
168 | return 'Struct('+ pprint.pformat(self._data)+')' | |
147 |
|
||||
148 | return 'Struct('+ pprint.pformat(self.__dict__)+')' |
|
|||
149 |
|
169 | |||
150 | def __repr__(self): |
|
170 | def __repr__(self): | |
151 | """Gets called by repr. |
|
|||
152 |
|
||||
153 | A Struct can be recreated with S_new=eval(repr(S_old)).""" |
|
|||
154 | return self.__str__() |
|
171 | return self.__str__() | |
155 |
|
172 | |||
156 |
def __ |
|
173 | def __contains__(self, key): | |
157 | """Allows struct[key] access.""" |
|
174 | return key in self._data | |
158 | return self.__dict__[key] |
|
|||
159 |
|
||||
160 | def __contains__(self,key): |
|
|||
161 | """Allows use of the 'in' operator. |
|
|||
162 |
|
||||
163 | Examples: |
|
|||
164 | >>> s = Struct(x=1) |
|
|||
165 | >>> 'x' in s |
|
|||
166 | True |
|
|||
167 | >>> 'y' in s |
|
|||
168 | False |
|
|||
169 | >>> s[4] = None |
|
|||
170 | >>> 4 in s |
|
|||
171 | True |
|
|||
172 | >>> s.z = None |
|
|||
173 | >>> 'z' in s |
|
|||
174 | True |
|
|||
175 | """ |
|
|||
176 | return key in self.__dict__ |
|
|||
177 |
|
175 | |||
178 | def __iadd__(self,other): |
|
176 | def __iadd__(self, other): | |
179 | """S += S2 is a shorthand for S.merge(S2).""" |
|
177 | """S += S2 is a shorthand for S.merge(S2).""" | |
180 | self.merge(other) |
|
178 | self.merge(other) | |
181 | return self |
|
179 | return self | |
182 |
|
180 | |||
183 | def __add__(self,other): |
|
181 | def __add__(self,other): | |
184 |
"""S + S2 -> New Struct made f |
|
182 | """S + S2 -> New Struct made from S.merge(S2)""" | |
185 | Sout = self.copy() |
|
183 | Sout = self.copy() | |
186 | Sout.merge(other) |
|
184 | Sout.merge(other) | |
187 | return Sout |
|
185 | return Sout | |
188 |
|
186 | |||
189 | def __sub__(self,other): |
|
187 | def __sub__(self,other): | |
190 | """Return S1-S2, where all keys in S2 have been deleted (if present) |
|
188 | """Out of place remove keys from self that are in other.""" | |
191 | from S1.""" |
|
|||
192 | Sout = self.copy() |
|
189 | Sout = self.copy() | |
193 | Sout -= other |
|
190 | Sout -= other | |
194 | return Sout |
|
191 | return Sout | |
195 |
|
192 | |||
196 | def __isub__(self,other): |
|
193 | def __isub__(self,other): | |
197 | """Do in place S = S - S2, meaning all keys in S2 have been deleted |
|
194 | """Inplace remove keys from self that are in other.""" | |
198 | (if present) from S1.""" |
|
|||
199 |
|
||||
200 | for k in other.keys(): |
|
195 | for k in other.keys(): | |
201 | if self.has_key(k): |
|
196 | if self.has_key(k): | |
202 |
del self._ |
|
197 | del self._data[k] | |
203 |
|
198 | |||
204 | def __make_dict(self,__loc_data__,**kw): |
|
199 | def __make_dict(self,__loc_data__,**kw): | |
205 |
"Helper function for update and merge. Return a dict from data. |
|
200 | """Helper function for update and merge. Return a dict from data. | |
206 |
|
201 | """ | ||
207 | if __loc_data__ == None: |
|
202 | if __loc_data__ == None: | |
208 |
d |
|
203 | data = {} | |
209 |
elif |
|
204 | elif isinstance(__loc_data__, dict): | |
210 |
d |
|
205 | data = __loc_data__ | |
211 | elif isinstance(__loc_data__,Struct): |
|
206 | elif isinstance(__loc_data__, Struct): | |
212 |
d |
|
207 | data = __loc_data__._data | |
213 | else: |
|
208 | else: | |
214 |
raise TypeError |
|
209 | raise TypeError('update with a dict, Struct or key=val pairs') | |
215 | if kw: |
|
210 | if kw: | |
216 |
d |
|
211 | data.update(kw) | |
217 |
return d |
|
212 | return data | |
218 |
|
213 | |||
219 |
def __dict_invert(self, |
|
214 | def __dict_invert(self, data): | |
220 |
"""Helper function for merge. |
|
215 | """Helper function for merge. | |
221 | lists and returns a dict. with the elements of each list as keys and |
|
216 | ||
222 | the original keys as values.""" |
|
217 | Takes a dictionary whose values are lists and returns a dict with | |
223 |
|
218 | the elements of each list as keys and the original keys as values. | ||
|
219 | """ | |||
224 | outdict = {} |
|
220 | outdict = {} | |
225 |
for k,lst in d |
|
221 | for k,lst in data.items(): | |
226 |
if |
|
222 | if isinstance(lst, str): | |
227 | lst = lst.split() |
|
223 | lst = lst.split() | |
228 | for entry in lst: |
|
224 | for entry in lst: | |
229 | outdict[entry] = k |
|
225 | outdict[entry] = k | |
230 | return outdict |
|
226 | return outdict | |
231 |
|
227 | |||
232 | def clear(self): |
|
228 | def clear(self): | |
233 | """Clear all attributes.""" |
|
229 | """Clear all attributes.""" | |
234 |
self._ |
|
230 | self._data.clear() | |
235 |
|
231 | |||
236 | def copy(self): |
|
232 | def copy(self): | |
237 | """Return a (shallow) copy of a Struct.""" |
|
233 | """Return a (shallow) copy of a Struct.""" | |
238 |
return Struct(self._ |
|
234 | return Struct(self._data.copy()) | |
239 |
|
235 | |||
240 | def dict(self): |
|
236 | def dict(self): | |
241 | """Return the Struct's dictionary.""" |
|
237 | """Return the Struct's dictionary.""" | |
242 |
return self._ |
|
238 | return self._data | |
243 |
|
239 | |||
244 | def dictcopy(self): |
|
240 | def dictcopy(self): | |
245 | """Return a (shallow) copy of the Struct's dictionary.""" |
|
241 | """Return a (shallow) copy of the Struct's dictionary.""" | |
246 |
return self._ |
|
242 | return self._data.copy() | |
247 |
|
243 | |||
248 | def popitem(self): |
|
244 | def popitem(self): | |
249 | """S.popitem() -> (k, v), remove and return some (key, value) pair as |
|
245 | """Return (key, value) tuple and remove from Struct. | |
250 | a 2-tuple; but raise KeyError if S is empty.""" |
|
246 | ||
251 | return self.__dict__.popitem() |
|
247 | If key is not present raise KeyError. | |
252 |
|
248 | """ | ||
|
249 | return self._data.popitem() | |||
|
250 | ||||
253 | def update(self,__loc_data__=None,**kw): |
|
251 | def update(self,__loc_data__=None,**kw): | |
254 |
"""Update (merge) with data from another Struct or |
|
252 | """Update (merge) with data from another Struct or dict. | |
255 | Optionally, one or more key=value pairs can be given at the end for |
|
253 | ||
256 | direct update.""" |
|
254 | Parameters | |
257 |
|
255 | ---------- | ||
|
256 | __loc_data : dict, Struct | |||
|
257 | The new data to add to self. | |||
|
258 | kw : dict | |||
|
259 | Key, value pairs to add to self. | |||
|
260 | """ | |||
258 | # The funny name __loc_data__ is to prevent a common variable name |
|
261 | # The funny name __loc_data__ is to prevent a common variable name | |
259 | # which could be a fieled of a Struct to collide with this |
|
262 | # which could be a fieled of a Struct to collide with this | |
260 | # parameter. The problem would arise if the function is called with a |
|
263 | # parameter. The problem would arise if the function is called with a | |
261 | # keyword with this same name that a user means to add as a Struct |
|
264 | # keyword with this same name that a user means to add as a Struct | |
262 | # field. |
|
265 | # field. | |
263 |
newdict = |
|
266 | newdict = self.__make_dict(__loc_data__, **kw) | |
264 | for k,v in newdict.iteritems(): |
|
267 | for k, v in newdict.iteritems(): | |
265 | self[k] = v |
|
268 | self[k] = v | |
266 |
|
269 | |||
267 | def merge(self,__loc_data__=None,__conflict_solve=None,**kw): |
|
270 | def merge(self, __loc_data__=None, __conflict_solve=None, **kw): | |
268 | """S.merge(data,conflict,k=v1,k=v2,...) -> merge data and k=v into S. |
|
271 | """S.merge(data,conflict,k=v1,k=v2,...) -> merge data and k=v into S. | |
269 |
|
272 | |||
270 | This is similar to update(), but much more flexible. First, a dict is |
|
273 | This is similar to update(), but much more flexible. First, a dict is | |
271 | made from data+key=value pairs. When merging this dict with the Struct |
|
274 | made from data+key=value pairs. When merging this dict with the Struct | |
272 | S, the optional dictionary 'conflict' is used to decide what to do. |
|
275 | S, the optional dictionary 'conflict' is used to decide what to do. | |
273 |
|
276 | |||
274 | If conflict is not given, the default behavior is to preserve any keys |
|
277 | If conflict is not given, the default behavior is to preserve any keys | |
275 | with their current value (the opposite of the update method's |
|
278 | with their current value (the opposite of the update method's | |
276 | behavior). |
|
279 | behavior). | |
277 |
|
280 | |||
278 | conflict is a dictionary of binary functions which will be used to |
|
281 | conflict is a dictionary of binary functions which will be used to | |
279 | solve key conflicts. It must have the following structure: |
|
282 | solve key conflicts. It must have the following structure: | |
280 |
|
283 | |||
281 | conflict == { fn1 : [Skey1,Skey2,...], fn2 : [Skey3], etc } |
|
284 | conflict == { fn1 : [Skey1,Skey2,...], fn2 : [Skey3], etc } | |
282 |
|
285 | |||
283 | Values must be lists or whitespace separated strings which are |
|
286 | Values must be lists or whitespace separated strings which are | |
284 | automatically converted to lists of strings by calling string.split(). |
|
287 | automatically converted to lists of strings by calling string.split(). | |
285 |
|
288 | |||
286 | Each key of conflict is a function which defines a policy for |
|
289 | Each key of conflict is a function which defines a policy for | |
287 | resolving conflicts when merging with the input data. Each fn must be |
|
290 | resolving conflicts when merging with the input data. Each fn must be | |
288 | a binary function which returns the desired outcome for a key |
|
291 | a binary function which returns the desired outcome for a key | |
289 | conflict. These functions will be called as fn(old,new). |
|
292 | conflict. These functions will be called as fn(old,new). | |
290 |
|
293 | |||
291 | An example is probably in order. Suppose you are merging the struct S |
|
294 | An example is probably in order. Suppose you are merging the struct S | |
292 | with a dict D and the following conflict policy dict: |
|
295 | with a dict D and the following conflict policy dict: | |
293 |
|
296 | |||
294 | S.merge(D,{fn1:['a','b',4], fn2:'key_c key_d'}) |
|
297 | S.merge(D,{fn1:['a','b',4], fn2:'key_c key_d'}) | |
295 |
|
298 | |||
296 | If the key 'a' is found in both S and D, the merge method will call: |
|
299 | If the key 'a' is found in both S and D, the merge method will call: | |
297 |
|
300 | |||
298 | S['a'] = fn1(S['a'],D['a']) |
|
301 | S['a'] = fn1(S['a'],D['a']) | |
299 |
|
302 | |||
300 | As a convenience, merge() provides five (the most commonly needed) |
|
303 | As a convenience, merge() provides five (the most commonly needed) | |
301 | pre-defined policies: preserve, update, add, add_flip and add_s. The |
|
304 | pre-defined policies: preserve, update, add, add_flip and add_s. The | |
302 | easiest explanation is their implementation: |
|
305 | easiest explanation is their implementation: | |
303 |
|
306 | |||
304 | preserve = lambda old,new: old |
|
307 | preserve = lambda old,new: old | |
305 | update = lambda old,new: new |
|
308 | update = lambda old,new: new | |
306 | add = lambda old,new: old + new |
|
309 | add = lambda old,new: old + new | |
307 | add_flip = lambda old,new: new + old # note change of order! |
|
310 | add_flip = lambda old,new: new + old # note change of order! | |
308 | add_s = lambda old,new: old + ' ' + new # only works for strings! |
|
311 | add_s = lambda old,new: old + ' ' + new # only works for strings! | |
309 |
|
312 | |||
310 | You can use those four words (as strings) as keys in conflict instead |
|
313 | You can use those four words (as strings) as keys in conflict instead | |
311 | of defining them as functions, and the merge method will substitute |
|
314 | of defining them as functions, and the merge method will substitute | |
312 | the appropriate functions for you. That is, the call |
|
315 | the appropriate functions for you. That is, the call | |
313 |
|
316 | |||
314 | S.merge(D,{'preserve':'a b c','add':[4,5,'d'],my_function:[6]}) |
|
317 | S.merge(D,{'preserve':'a b c','add':[4,5,'d'],my_function:[6]}) | |
315 |
|
318 | |||
316 | will automatically substitute the functions preserve and add for the |
|
319 | will automatically substitute the functions preserve and add for the | |
317 | names 'preserve' and 'add' before making any function calls. |
|
320 | names 'preserve' and 'add' before making any function calls. | |
318 |
|
321 | |||
319 | For more complicated conflict resolution policies, you still need to |
|
322 | For more complicated conflict resolution policies, you still need to | |
320 | construct your own functions. """ |
|
323 | construct your own functions. """ | |
321 |
|
324 | |||
322 |
data_dict = |
|
325 | data_dict = self.__make_dict(__loc_data__,**kw) | |
323 |
|
326 | |||
324 | # policies for conflict resolution: two argument functions which return |
|
327 | # policies for conflict resolution: two argument functions which return | |
325 | # the value that will go in the new struct |
|
328 | # the value that will go in the new struct | |
326 | preserve = lambda old,new: old |
|
329 | preserve = lambda old,new: old | |
@@ -328,10 +331,10 b' class Struct:' | |||||
328 | add = lambda old,new: old + new |
|
331 | add = lambda old,new: old + new | |
329 | add_flip = lambda old,new: new + old # note change of order! |
|
332 | add_flip = lambda old,new: new + old # note change of order! | |
330 | add_s = lambda old,new: old + ' ' + new |
|
333 | add_s = lambda old,new: old + ' ' + new | |
331 |
|
334 | |||
332 | # default policy is to keep current keys when there's a conflict |
|
335 | # default policy is to keep current keys when there's a conflict | |
333 | conflict_solve = list2dict2(self.keys(),default = preserve) |
|
336 | conflict_solve = list2dict2(self.keys(), default = preserve) | |
334 |
|
337 | |||
335 | # the conflict_solve dictionary is given by the user 'inverted': we |
|
338 | # the conflict_solve dictionary is given by the user 'inverted': we | |
336 | # need a name-function mapping, it comes as a function -> names |
|
339 | # need a name-function mapping, it comes as a function -> names | |
337 | # dict. Make a local copy (b/c we'll make changes), replace user |
|
340 | # dict. Make a local copy (b/c we'll make changes), replace user | |
@@ -344,7 +347,7 b' class Struct:' | |||||
344 | if name in inv_conflict_solve_user.keys(): |
|
347 | if name in inv_conflict_solve_user.keys(): | |
345 | inv_conflict_solve_user[func] = inv_conflict_solve_user[name] |
|
348 | inv_conflict_solve_user[func] = inv_conflict_solve_user[name] | |
346 | del inv_conflict_solve_user[name] |
|
349 | del inv_conflict_solve_user[name] | |
347 |
conflict_solve.update( |
|
350 | conflict_solve.update(self.__dict_invert(inv_conflict_solve_user)) | |
348 | #print 'merge. conflict_solve: '; pprint(conflict_solve) # dbg |
|
351 | #print 'merge. conflict_solve: '; pprint(conflict_solve) # dbg | |
349 | #print '*'*50,'in merger. conflict_solver:'; pprint(conflict_solve) |
|
352 | #print '*'*50,'in merger. conflict_solver:'; pprint(conflict_solve) | |
350 | for key in data_dict: |
|
353 | for key in data_dict: | |
@@ -352,64 +355,62 b' class Struct:' | |||||
352 | self[key] = data_dict[key] |
|
355 | self[key] = data_dict[key] | |
353 | else: |
|
356 | else: | |
354 | self[key] = conflict_solve[key](self[key],data_dict[key]) |
|
357 | self[key] = conflict_solve[key](self[key],data_dict[key]) | |
355 |
|
358 | |||
356 | def has_key(self,key): |
|
359 | def has_key(self,key): | |
357 | """Like has_key() dictionary method.""" |
|
360 | """Like has_key() dictionary method.""" | |
358 |
return self._ |
|
361 | return self._data.has_key(key) | |
359 |
|
362 | |||
360 | def hasattr(self,key): |
|
363 | def hasattr(self,key): | |
361 | """hasattr function available as a method. |
|
364 | """hasattr function available as a method. | |
362 |
|
365 | |||
363 | Implemented like has_key, to make sure that all available keys in the |
|
366 | Implemented like has_key, to make sure that all available keys in the | |
364 | internal dictionary of the Struct appear also as attributes (even |
|
367 | internal dictionary of the Struct appear also as attributes (even | |
365 | numeric keys).""" |
|
368 | numeric keys).""" | |
366 |
return self._ |
|
369 | return self._data.has_key(key) | |
367 |
|
370 | |||
368 | def items(self): |
|
371 | def items(self): | |
369 |
"""Return the items in the Struct's dictionary |
|
372 | """Return the items in the Struct's dictionary as (key, value)'s.""" | |
370 | as a call to {}.items().""" |
|
373 | return self._data.items() | |
371 | return self.__dict__.items() |
|
374 | ||
372 |
|
||||
373 | def keys(self): |
|
375 | def keys(self): | |
374 |
"""Return the keys in the Struct's dictionary |
|
376 | """Return the keys in the Struct's dictionary..""" | |
375 | as a call to {}.keys().""" |
|
377 | return self._data.keys() | |
376 | return self.__dict__.keys() |
|
378 | ||
377 |
|
379 | def values(self, keys=None): | ||
378 | def values(self,keys=None): |
|
380 | """Return the values in the Struct's dictionary. | |
379 | """Return the values in the Struct's dictionary, in the same format |
|
381 | ||
380 | as a call to {}.values(). |
|
|||
381 |
|
||||
382 | Can be called with an optional argument keys, which must be a list or |
|
382 | Can be called with an optional argument keys, which must be a list or | |
383 | tuple of keys. In this case it returns only the values corresponding |
|
383 | tuple of keys. In this case it returns only the values corresponding | |
384 |
to those keys (allowing a form of 'slicing' for Structs). |
|
384 | to those keys (allowing a form of 'slicing' for Structs). | |
|
385 | """ | |||
385 | if not keys: |
|
386 | if not keys: | |
386 |
return self._ |
|
387 | return self._data.values() | |
387 | else: |
|
388 | else: | |
388 | ret=[] |
|
389 | result=[] | |
389 | for k in keys: |
|
390 | for k in keys: | |
390 | ret.append(self[k]) |
|
391 | result.append(self[k]) | |
391 | return ret |
|
392 | return result | |
392 |
|
393 | |||
393 | def get(self,attr,val=None): |
|
394 | def get(self, attr, val=None): | |
394 | """S.get(k[,d]) -> S[k] if k in S, else d. d defaults to None.""" |
|
395 | """S.get(k[,d]) -> S[k] if k in S, else d. d defaults to None.""" | |
395 | try: |
|
396 | try: | |
396 | return self[attr] |
|
397 | return self[attr] | |
397 | except KeyError: |
|
398 | except KeyError: | |
398 | return val |
|
399 | return val | |
399 |
|
400 | |||
400 | def setdefault(self,attr,val=None): |
|
401 | def setdefault(self, attr, val=None): | |
401 | """S.setdefault(k[,d]) -> S.get(k,d), also set S[k]=d if k not in S""" |
|
402 | """S.setdefault(k[,d]) -> S.get(k,d), also set S[k]=d if k not in S""" | |
402 | if not self.has_key(attr): |
|
403 | if not self._data.has_key(attr): | |
403 | self[attr] = val |
|
404 | self[attr] = val | |
404 | return self.get(attr,val) |
|
405 | return self.get(attr, val) | |
405 |
|
406 | |||
406 | def allow_new_attr(self, allow = True): |
|
407 | def allow_new_attr(self, allow = True): | |
407 |
""" |
|
408 | """Set whether new attributes can be created in this Struct. | |
408 |
|
409 | |||
409 | This can be used to catch typos by verifying that the attribute user |
|
410 | This can be used to catch typos by verifying that the attribute user | |
410 | tries to change already exists in this Struct. |
|
411 | tries to change already exists in this Struct. | |
411 | """ |
|
412 | """ | |
412 |
self |
|
413 | object.__setattr__(self, '_allownew', allow) | |
413 |
|
414 | |||
414 |
|
415 | |||
415 | # end class Struct |
|
416 | # end class Struct |
General Comments 0
You need to be logged in to leave comments.
Login now