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,75 +106,72 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 | ||
|
112 | Parameters | |||
|
113 | ---------- | |||
|
114 | data : dict, Struct | |||
|
115 | Initialize with this data. | |||
|
116 | kw : dict | |||
|
117 | Initialize with key, value pairs. | |||
|
118 | ||||
|
119 | Examples | |||
|
120 | -------- | |||
111 |
|
121 | |||
112 | Both can be used, but the dictionary must come first: |
|
|||
113 | Struct(dict), Struct(k1=v1,k2=v2) or Struct(dict,k1=v1,k2=v2). |
|
|||
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 |
|
136 | |||
129 |
|
||||
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): | |||
135 | raise KeyError( |
|
145 | raise KeyError( | |
136 | "Can't create unknown attribute %s - Check for typos, or use allow_new_attr to create new attributes!" % |
|
146 | 'key %s is a protected key of class Struct.' % key | |
137 |
|
|
147 | ) | |
138 |
|
148 | if not self._allownew and key not in self._data: | ||
139 | self.__dict__[key] = value |
|
149 | raise KeyError( | |
|
150 | "can't create unknown attribute %s. Check for typos, or use allow_new_attr" % key) | |||
|
151 | self._data[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.""" |
|
|||
143 | self.__setitem__(key,value) |
|
154 | self.__setitem__(key, value) | |
144 |
|
155 | |||
145 |
def __ |
|
156 | def __getattr__(self, key): | |
146 | """Gets called by print.""" |
|
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] | |||
147 |
|
166 | |||
148 | return 'Struct('+ pprint.pformat(self.__dict__)+')' |
|
167 | def __str__(self): | |
|
168 | return 'Struct('+ pprint.pformat(self._data)+')' | |||
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 __getitem__(self,key): |
|
|||
157 | """Allows struct[key] access.""" |
|
|||
158 | return self.__dict__[key] |
|
|||
159 |
|
||||
160 | def __contains__(self,key): |
|
173 | def __contains__(self, key): | |
161 | """Allows use of the 'in' operator. |
|
174 | return key in self._data | |
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).""" | |
@@ -181,49 +179,47 b' class Struct:' | |||||
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 |
|
|||
222 | the original keys as values.""" |
|
|||
223 |
|
216 | |||
|
217 | Takes a dictionary whose values are lists and returns a dict with | |||
|
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 | |
@@ -231,36 +227,43 b' class Struct:' | |||||
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.""" |
|
|||
251 | return self.__dict__.popitem() |
|
|||
252 |
|
246 | |||
253 | def update(self,__loc_data__=None,**kw): |
|
247 | If key is not present raise KeyError. | |
254 | """Update (merge) with data from another Struct or from a dictionary. |
|
248 | """ | |
255 | Optionally, one or more key=value pairs can be given at the end for |
|
249 | return self._data.popitem() | |
256 | direct update.""" |
|
|||
257 |
|
250 | |||
|
251 | def update(self,__loc_data__=None,**kw): | |||
|
252 | """Update (merge) with data from another Struct or dict. | |||
|
253 | ||||
|
254 | Parameters | |||
|
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 | |||
@@ -319,7 +322,7 b' class Struct:' | |||||
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 | |
@@ -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: | |
@@ -355,7 +358,7 b' class Struct:' | |||||
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. | |
@@ -363,32 +366,30 b' class Struct:' | |||||
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() |
|
|||
372 |
|
374 | |||
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() |
|
|||
377 |
|
378 | |||
378 | def values(self,keys=None): |
|
379 | def values(self, keys=None): | |
379 |
"""Return the values in the Struct's dictionary |
|
380 | """Return the values in the Struct's dictionary. | |
380 | as a call to {}.values(). |
|
|||
381 |
|
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.""" | |
@@ -399,17 +400,17 b' class Struct:' | |||||
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