##// END OF EJS Templates
Fix tests in IPython.utils
Thomas Kluyver -
Show More
@@ -1,167 +1,167 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 Older utilities that are not being used.
3 Older utilities that are not being used.
4
4
5 WARNING: IF YOU NEED TO USE ONE OF THESE FUNCTIONS, PLEASE FIRST MOVE IT
5 WARNING: IF YOU NEED TO USE ONE OF THESE FUNCTIONS, PLEASE FIRST MOVE IT
6 TO ANOTHER APPROPRIATE MODULE IN IPython.utils.
6 TO ANOTHER APPROPRIATE MODULE IN IPython.utils.
7 """
7 """
8
8
9 #-----------------------------------------------------------------------------
9 #-----------------------------------------------------------------------------
10 # Copyright (C) 2008-2011 The IPython Development Team
10 # Copyright (C) 2008-2011 The IPython Development Team
11 #
11 #
12 # Distributed under the terms of the BSD License. The full license is in
12 # Distributed under the terms of the BSD License. The full license is in
13 # the file COPYING, distributed as part of this software.
13 # the file COPYING, distributed as part of this software.
14 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
15
15
16 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
17 # Imports
17 # Imports
18 #-----------------------------------------------------------------------------
18 #-----------------------------------------------------------------------------
19
19
20 import sys
20 import sys
21 import warnings
21 import warnings
22
22
23 from IPython.utils.warn import warn
23 from IPython.utils.warn import warn
24
24
25 #-----------------------------------------------------------------------------
25 #-----------------------------------------------------------------------------
26 # Code
26 # Code
27 #-----------------------------------------------------------------------------
27 #-----------------------------------------------------------------------------
28
28
29
29
30 def mutex_opts(dict,ex_op):
30 def mutex_opts(dict,ex_op):
31 """Check for presence of mutually exclusive keys in a dict.
31 """Check for presence of mutually exclusive keys in a dict.
32
32
33 Call: mutex_opts(dict,[[op1a,op1b],[op2a,op2b]...]"""
33 Call: mutex_opts(dict,[[op1a,op1b],[op2a,op2b]...]"""
34 for op1,op2 in ex_op:
34 for op1,op2 in ex_op:
35 if op1 in dict and op2 in dict:
35 if op1 in dict and op2 in dict:
36 raise ValueError('\n*** ERROR in Arguments *** '\
36 raise ValueError('\n*** ERROR in Arguments *** '\
37 'Options '+op1+' and '+op2+' are mutually exclusive.')
37 'Options '+op1+' and '+op2+' are mutually exclusive.')
38
38
39
39
40 class EvalDict:
40 class EvalDict:
41 """
41 """
42 Emulate a dict which evaluates its contents in the caller's frame.
42 Emulate a dict which evaluates its contents in the caller's frame.
43
43
44 Usage:
44 Usage:
45 >>> number = 19
45 >>> number = 19
46
46
47 >>> text = "python"
47 >>> text = "python"
48
48
49 >>> print "%(text.capitalize())s %(number/9.0).1f rules!" % EvalDict()
49 >>> print("%(text.capitalize())s %(number/9.0).1f rules!" % EvalDict())
50 Python 2.1 rules!
50 Python 2.1 rules!
51 """
51 """
52
52
53 # This version is due to sismex01@hebmex.com on c.l.py, and is basically a
53 # This version is due to sismex01@hebmex.com on c.l.py, and is basically a
54 # modified (shorter) version of:
54 # modified (shorter) version of:
55 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66018 by
55 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66018 by
56 # Skip Montanaro (skip@pobox.com).
56 # Skip Montanaro (skip@pobox.com).
57
57
58 def __getitem__(self, name):
58 def __getitem__(self, name):
59 frame = sys._getframe(1)
59 frame = sys._getframe(1)
60 return eval(name, frame.f_globals, frame.f_locals)
60 return eval(name, frame.f_globals, frame.f_locals)
61
61
62 EvalString = EvalDict # for backwards compatibility
62 EvalString = EvalDict # for backwards compatibility
63
63
64
64
65 def all_belong(candidates,checklist):
65 def all_belong(candidates,checklist):
66 """Check whether a list of items ALL appear in a given list of options.
66 """Check whether a list of items ALL appear in a given list of options.
67
67
68 Returns a single 1 or 0 value."""
68 Returns a single 1 or 0 value."""
69
69
70 return 1-(0 in [x in checklist for x in candidates])
70 return 1-(0 in [x in checklist for x in candidates])
71
71
72
72
73 def belong(candidates,checklist):
73 def belong(candidates,checklist):
74 """Check whether a list of items appear in a given list of options.
74 """Check whether a list of items appear in a given list of options.
75
75
76 Returns a list of 1 and 0, one for each candidate given."""
76 Returns a list of 1 and 0, one for each candidate given."""
77
77
78 return [x in checklist for x in candidates]
78 return [x in checklist for x in candidates]
79
79
80
80
81 def with_obj(object, **args):
81 def with_obj(object, **args):
82 """Set multiple attributes for an object, similar to Pascal's with.
82 """Set multiple attributes for an object, similar to Pascal's with.
83
83
84 Example:
84 Example:
85 with_obj(jim,
85 with_obj(jim,
86 born = 1960,
86 born = 1960,
87 haircolour = 'Brown',
87 haircolour = 'Brown',
88 eyecolour = 'Green')
88 eyecolour = 'Green')
89
89
90 Credit: Greg Ewing, in
90 Credit: Greg Ewing, in
91 http://mail.python.org/pipermail/python-list/2001-May/040703.html.
91 http://mail.python.org/pipermail/python-list/2001-May/040703.html.
92
92
93 NOTE: up until IPython 0.7.2, this was called simply 'with', but 'with'
93 NOTE: up until IPython 0.7.2, this was called simply 'with', but 'with'
94 has become a keyword for Python 2.5, so we had to rename it."""
94 has become a keyword for Python 2.5, so we had to rename it."""
95
95
96 object.__dict__.update(args)
96 object.__dict__.update(args)
97
97
98
98
99 def map_method(method,object_list,*argseq,**kw):
99 def map_method(method,object_list,*argseq,**kw):
100 """map_method(method,object_list,*args,**kw) -> list
100 """map_method(method,object_list,*args,**kw) -> list
101
101
102 Return a list of the results of applying the methods to the items of the
102 Return a list of the results of applying the methods to the items of the
103 argument sequence(s). If more than one sequence is given, the method is
103 argument sequence(s). If more than one sequence is given, the method is
104 called with an argument list consisting of the corresponding item of each
104 called with an argument list consisting of the corresponding item of each
105 sequence. All sequences must be of the same length.
105 sequence. All sequences must be of the same length.
106
106
107 Keyword arguments are passed verbatim to all objects called.
107 Keyword arguments are passed verbatim to all objects called.
108
108
109 This is Python code, so it's not nearly as fast as the builtin map()."""
109 This is Python code, so it's not nearly as fast as the builtin map()."""
110
110
111 out_list = []
111 out_list = []
112 idx = 0
112 idx = 0
113 for object in object_list:
113 for object in object_list:
114 try:
114 try:
115 handler = getattr(object, method)
115 handler = getattr(object, method)
116 except AttributeError:
116 except AttributeError:
117 out_list.append(None)
117 out_list.append(None)
118 else:
118 else:
119 if argseq:
119 if argseq:
120 args = map(lambda lst:lst[idx],argseq)
120 args = map(lambda lst:lst[idx],argseq)
121 #print 'ob',object,'hand',handler,'ar',args # dbg
121 #print 'ob',object,'hand',handler,'ar',args # dbg
122 out_list.append(handler(args,**kw))
122 out_list.append(handler(args,**kw))
123 else:
123 else:
124 out_list.append(handler(**kw))
124 out_list.append(handler(**kw))
125 idx += 1
125 idx += 1
126 return out_list
126 return out_list
127
127
128
128
129 def import_fail_info(mod_name,fns=None):
129 def import_fail_info(mod_name,fns=None):
130 """Inform load failure for a module."""
130 """Inform load failure for a module."""
131
131
132 if fns == None:
132 if fns == None:
133 warn("Loading of %s failed." % (mod_name,))
133 warn("Loading of %s failed." % (mod_name,))
134 else:
134 else:
135 warn("Loading of %s from %s failed." % (fns,mod_name))
135 warn("Loading of %s from %s failed." % (fns,mod_name))
136
136
137
137
138 class NotGiven: pass
138 class NotGiven: pass
139
139
140 def popkey(dct,key,default=NotGiven):
140 def popkey(dct,key,default=NotGiven):
141 """Return dct[key] and delete dct[key].
141 """Return dct[key] and delete dct[key].
142
142
143 If default is given, return it if dct[key] doesn't exist, otherwise raise
143 If default is given, return it if dct[key] doesn't exist, otherwise raise
144 KeyError. """
144 KeyError. """
145
145
146 try:
146 try:
147 val = dct[key]
147 val = dct[key]
148 except KeyError:
148 except KeyError:
149 if default is NotGiven:
149 if default is NotGiven:
150 raise
150 raise
151 else:
151 else:
152 return default
152 return default
153 else:
153 else:
154 del dct[key]
154 del dct[key]
155 return val
155 return val
156
156
157
157
158 def wrap_deprecated(func, suggest = '<nothing>'):
158 def wrap_deprecated(func, suggest = '<nothing>'):
159 def newFunc(*args, **kwargs):
159 def newFunc(*args, **kwargs):
160 warnings.warn("Call to deprecated function %s, use %s instead" %
160 warnings.warn("Call to deprecated function %s, use %s instead" %
161 ( func.__name__, suggest),
161 ( func.__name__, suggest),
162 category=DeprecationWarning,
162 category=DeprecationWarning,
163 stacklevel = 2)
163 stacklevel = 2)
164 return func(*args, **kwargs)
164 return func(*args, **kwargs)
165 return newFunc
165 return newFunc
166
166
167
167
@@ -1,391 +1,391 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """A dict subclass that supports attribute style access.
2 """A dict subclass that supports attribute style access.
3
3
4 Authors:
4 Authors:
5
5
6 * Fernando Perez (original)
6 * Fernando Perez (original)
7 * Brian Granger (refactoring to a dict subclass)
7 * Brian Granger (refactoring to a dict subclass)
8 """
8 """
9
9
10 #-----------------------------------------------------------------------------
10 #-----------------------------------------------------------------------------
11 # Copyright (C) 2008-2011 The IPython Development Team
11 # Copyright (C) 2008-2011 The IPython Development Team
12 #
12 #
13 # Distributed under the terms of the BSD License. The full license is in
13 # Distributed under the terms of the BSD License. The full license is in
14 # the file COPYING, distributed as part of this software.
14 # the file COPYING, distributed as part of this software.
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16
16
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18 # Imports
18 # Imports
19 #-----------------------------------------------------------------------------
19 #-----------------------------------------------------------------------------
20
20
21 __all__ = ['Struct']
21 __all__ = ['Struct']
22
22
23 #-----------------------------------------------------------------------------
23 #-----------------------------------------------------------------------------
24 # Code
24 # Code
25 #-----------------------------------------------------------------------------
25 #-----------------------------------------------------------------------------
26
26
27
27
28 class Struct(dict):
28 class Struct(dict):
29 """A dict subclass with attribute style access.
29 """A dict subclass with attribute style access.
30
30
31 This dict subclass has a a few extra features:
31 This dict subclass has a a few extra features:
32
32
33 * Attribute style access.
33 * Attribute style access.
34 * Protection of class members (like keys, items) when using attribute
34 * Protection of class members (like keys, items) when using attribute
35 style access.
35 style access.
36 * The ability to restrict assignment to only existing keys.
36 * The ability to restrict assignment to only existing keys.
37 * Intelligent merging.
37 * Intelligent merging.
38 * Overloaded operators.
38 * Overloaded operators.
39 """
39 """
40 _allownew = True
40 _allownew = True
41 def __init__(self, *args, **kw):
41 def __init__(self, *args, **kw):
42 """Initialize with a dictionary, another Struct, or data.
42 """Initialize with a dictionary, another Struct, or data.
43
43
44 Parameters
44 Parameters
45 ----------
45 ----------
46 args : dict, Struct
46 args : dict, Struct
47 Initialize with one dict or Struct
47 Initialize with one dict or Struct
48 kw : dict
48 kw : dict
49 Initialize with key, value pairs.
49 Initialize with key, value pairs.
50
50
51 Examples
51 Examples
52 --------
52 --------
53
53
54 >>> s = Struct(a=10,b=30)
54 >>> s = Struct(a=10,b=30)
55 >>> s.a
55 >>> s.a
56 10
56 10
57 >>> s.b
57 >>> s.b
58 30
58 30
59 >>> s2 = Struct(s,c=30)
59 >>> s2 = Struct(s,c=30)
60 >>> sorted(s2.keys())
60 >>> sorted(s2.keys())
61 ['a', 'b', 'c']
61 ['a', 'b', 'c']
62 """
62 """
63 object.__setattr__(self, '_allownew', True)
63 object.__setattr__(self, '_allownew', True)
64 dict.__init__(self, *args, **kw)
64 dict.__init__(self, *args, **kw)
65
65
66 def __setitem__(self, key, value):
66 def __setitem__(self, key, value):
67 """Set an item with check for allownew.
67 """Set an item with check for allownew.
68
68
69 Examples
69 Examples
70 --------
70 --------
71
71
72 >>> s = Struct()
72 >>> s = Struct()
73 >>> s['a'] = 10
73 >>> s['a'] = 10
74 >>> s.allow_new_attr(False)
74 >>> s.allow_new_attr(False)
75 >>> s['a'] = 10
75 >>> s['a'] = 10
76 >>> s['a']
76 >>> s['a']
77 10
77 10
78 >>> try:
78 >>> try:
79 ... s['b'] = 20
79 ... s['b'] = 20
80 ... except KeyError:
80 ... except KeyError:
81 ... print 'this is not allowed'
81 ... print('this is not allowed')
82 ...
82 ...
83 this is not allowed
83 this is not allowed
84 """
84 """
85 if not self._allownew and key not in self:
85 if not self._allownew and key not in self:
86 raise KeyError(
86 raise KeyError(
87 "can't create new attribute %s when allow_new_attr(False)" % key)
87 "can't create new attribute %s when allow_new_attr(False)" % key)
88 dict.__setitem__(self, key, value)
88 dict.__setitem__(self, key, value)
89
89
90 def __setattr__(self, key, value):
90 def __setattr__(self, key, value):
91 """Set an attr with protection of class members.
91 """Set an attr with protection of class members.
92
92
93 This calls :meth:`self.__setitem__` but convert :exc:`KeyError` to
93 This calls :meth:`self.__setitem__` but convert :exc:`KeyError` to
94 :exc:`AttributeError`.
94 :exc:`AttributeError`.
95
95
96 Examples
96 Examples
97 --------
97 --------
98
98
99 >>> s = Struct()
99 >>> s = Struct()
100 >>> s.a = 10
100 >>> s.a = 10
101 >>> s.a
101 >>> s.a
102 10
102 10
103 >>> try:
103 >>> try:
104 ... s.get = 10
104 ... s.get = 10
105 ... except AttributeError:
105 ... except AttributeError:
106 ... print "you can't set a class member"
106 ... print("you can't set a class member")
107 ...
107 ...
108 you can't set a class member
108 you can't set a class member
109 """
109 """
110 # If key is an str it might be a class member or instance var
110 # If key is an str it might be a class member or instance var
111 if isinstance(key, str):
111 if isinstance(key, str):
112 # I can't simply call hasattr here because it calls getattr, which
112 # I can't simply call hasattr here because it calls getattr, which
113 # calls self.__getattr__, which returns True for keys in
113 # calls self.__getattr__, which returns True for keys in
114 # self._data. But I only want keys in the class and in
114 # self._data. But I only want keys in the class and in
115 # self.__dict__
115 # self.__dict__
116 if key in self.__dict__ or hasattr(Struct, key):
116 if key in self.__dict__ or hasattr(Struct, key):
117 raise AttributeError(
117 raise AttributeError(
118 'attr %s is a protected member of class Struct.' % key
118 'attr %s is a protected member of class Struct.' % key
119 )
119 )
120 try:
120 try:
121 self.__setitem__(key, value)
121 self.__setitem__(key, value)
122 except KeyError as e:
122 except KeyError as e:
123 raise AttributeError(e)
123 raise AttributeError(e)
124
124
125 def __getattr__(self, key):
125 def __getattr__(self, key):
126 """Get an attr by calling :meth:`dict.__getitem__`.
126 """Get an attr by calling :meth:`dict.__getitem__`.
127
127
128 Like :meth:`__setattr__`, this method converts :exc:`KeyError` to
128 Like :meth:`__setattr__`, this method converts :exc:`KeyError` to
129 :exc:`AttributeError`.
129 :exc:`AttributeError`.
130
130
131 Examples
131 Examples
132 --------
132 --------
133
133
134 >>> s = Struct(a=10)
134 >>> s = Struct(a=10)
135 >>> s.a
135 >>> s.a
136 10
136 10
137 >>> type(s.get)
137 >>> type(s.get)
138 <... 'builtin_function_or_method'>
138 <... 'builtin_function_or_method'>
139 >>> try:
139 >>> try:
140 ... s.b
140 ... s.b
141 ... except AttributeError:
141 ... except AttributeError:
142 ... print "I don't have that key"
142 ... print("I don't have that key")
143 ...
143 ...
144 I don't have that key
144 I don't have that key
145 """
145 """
146 try:
146 try:
147 result = self[key]
147 result = self[key]
148 except KeyError:
148 except KeyError:
149 raise AttributeError(key)
149 raise AttributeError(key)
150 else:
150 else:
151 return result
151 return result
152
152
153 def __iadd__(self, other):
153 def __iadd__(self, other):
154 """s += s2 is a shorthand for s.merge(s2).
154 """s += s2 is a shorthand for s.merge(s2).
155
155
156 Examples
156 Examples
157 --------
157 --------
158
158
159 >>> s = Struct(a=10,b=30)
159 >>> s = Struct(a=10,b=30)
160 >>> s2 = Struct(a=20,c=40)
160 >>> s2 = Struct(a=20,c=40)
161 >>> s += s2
161 >>> s += s2
162 >>> sorted(s.keys())
162 >>> sorted(s.keys())
163 ['a', 'b', 'c']
163 ['a', 'b', 'c']
164 """
164 """
165 self.merge(other)
165 self.merge(other)
166 return self
166 return self
167
167
168 def __add__(self,other):
168 def __add__(self,other):
169 """s + s2 -> New Struct made from s.merge(s2).
169 """s + s2 -> New Struct made from s.merge(s2).
170
170
171 Examples
171 Examples
172 --------
172 --------
173
173
174 >>> s1 = Struct(a=10,b=30)
174 >>> s1 = Struct(a=10,b=30)
175 >>> s2 = Struct(a=20,c=40)
175 >>> s2 = Struct(a=20,c=40)
176 >>> s = s1 + s2
176 >>> s = s1 + s2
177 >>> sorted(s.keys())
177 >>> sorted(s.keys())
178 ['a', 'b', 'c']
178 ['a', 'b', 'c']
179 """
179 """
180 sout = self.copy()
180 sout = self.copy()
181 sout.merge(other)
181 sout.merge(other)
182 return sout
182 return sout
183
183
184 def __sub__(self,other):
184 def __sub__(self,other):
185 """s1 - s2 -> remove keys in s2 from s1.
185 """s1 - s2 -> remove keys in s2 from s1.
186
186
187 Examples
187 Examples
188 --------
188 --------
189
189
190 >>> s1 = Struct(a=10,b=30)
190 >>> s1 = Struct(a=10,b=30)
191 >>> s2 = Struct(a=40)
191 >>> s2 = Struct(a=40)
192 >>> s = s1 - s2
192 >>> s = s1 - s2
193 >>> s
193 >>> s
194 {'b': 30}
194 {'b': 30}
195 """
195 """
196 sout = self.copy()
196 sout = self.copy()
197 sout -= other
197 sout -= other
198 return sout
198 return sout
199
199
200 def __isub__(self,other):
200 def __isub__(self,other):
201 """Inplace remove keys from self that are in other.
201 """Inplace remove keys from self that are in other.
202
202
203 Examples
203 Examples
204 --------
204 --------
205
205
206 >>> s1 = Struct(a=10,b=30)
206 >>> s1 = Struct(a=10,b=30)
207 >>> s2 = Struct(a=40)
207 >>> s2 = Struct(a=40)
208 >>> s1 -= s2
208 >>> s1 -= s2
209 >>> s1
209 >>> s1
210 {'b': 30}
210 {'b': 30}
211 """
211 """
212 for k in other.keys():
212 for k in other.keys():
213 if k in self:
213 if k in self:
214 del self[k]
214 del self[k]
215 return self
215 return self
216
216
217 def __dict_invert(self, data):
217 def __dict_invert(self, data):
218 """Helper function for merge.
218 """Helper function for merge.
219
219
220 Takes a dictionary whose values are lists and returns a dict with
220 Takes a dictionary whose values are lists and returns a dict with
221 the elements of each list as keys and the original keys as values.
221 the elements of each list as keys and the original keys as values.
222 """
222 """
223 outdict = {}
223 outdict = {}
224 for k,lst in data.items():
224 for k,lst in data.items():
225 if isinstance(lst, str):
225 if isinstance(lst, str):
226 lst = lst.split()
226 lst = lst.split()
227 for entry in lst:
227 for entry in lst:
228 outdict[entry] = k
228 outdict[entry] = k
229 return outdict
229 return outdict
230
230
231 def dict(self):
231 def dict(self):
232 return self
232 return self
233
233
234 def copy(self):
234 def copy(self):
235 """Return a copy as a Struct.
235 """Return a copy as a Struct.
236
236
237 Examples
237 Examples
238 --------
238 --------
239
239
240 >>> s = Struct(a=10,b=30)
240 >>> s = Struct(a=10,b=30)
241 >>> s2 = s.copy()
241 >>> s2 = s.copy()
242 >>> type(s2) is Struct
242 >>> type(s2) is Struct
243 True
243 True
244 """
244 """
245 return Struct(dict.copy(self))
245 return Struct(dict.copy(self))
246
246
247 def hasattr(self, key):
247 def hasattr(self, key):
248 """hasattr function available as a method.
248 """hasattr function available as a method.
249
249
250 Implemented like has_key.
250 Implemented like has_key.
251
251
252 Examples
252 Examples
253 --------
253 --------
254
254
255 >>> s = Struct(a=10)
255 >>> s = Struct(a=10)
256 >>> s.hasattr('a')
256 >>> s.hasattr('a')
257 True
257 True
258 >>> s.hasattr('b')
258 >>> s.hasattr('b')
259 False
259 False
260 >>> s.hasattr('get')
260 >>> s.hasattr('get')
261 False
261 False
262 """
262 """
263 return key in self
263 return key in self
264
264
265 def allow_new_attr(self, allow = True):
265 def allow_new_attr(self, allow = True):
266 """Set whether new attributes can be created in this Struct.
266 """Set whether new attributes can be created in this Struct.
267
267
268 This can be used to catch typos by verifying that the attribute user
268 This can be used to catch typos by verifying that the attribute user
269 tries to change already exists in this Struct.
269 tries to change already exists in this Struct.
270 """
270 """
271 object.__setattr__(self, '_allownew', allow)
271 object.__setattr__(self, '_allownew', allow)
272
272
273 def merge(self, __loc_data__=None, __conflict_solve=None, **kw):
273 def merge(self, __loc_data__=None, __conflict_solve=None, **kw):
274 """Merge two Structs with customizable conflict resolution.
274 """Merge two Structs with customizable conflict resolution.
275
275
276 This is similar to :meth:`update`, but much more flexible. First, a
276 This is similar to :meth:`update`, but much more flexible. First, a
277 dict is made from data+key=value pairs. When merging this dict with
277 dict is made from data+key=value pairs. When merging this dict with
278 the Struct S, the optional dictionary 'conflict' is used to decide
278 the Struct S, the optional dictionary 'conflict' is used to decide
279 what to do.
279 what to do.
280
280
281 If conflict is not given, the default behavior is to preserve any keys
281 If conflict is not given, the default behavior is to preserve any keys
282 with their current value (the opposite of the :meth:`update` method's
282 with their current value (the opposite of the :meth:`update` method's
283 behavior).
283 behavior).
284
284
285 Parameters
285 Parameters
286 ----------
286 ----------
287 __loc_data : dict, Struct
287 __loc_data : dict, Struct
288 The data to merge into self
288 The data to merge into self
289 __conflict_solve : dict
289 __conflict_solve : dict
290 The conflict policy dict. The keys are binary functions used to
290 The conflict policy dict. The keys are binary functions used to
291 resolve the conflict and the values are lists of strings naming
291 resolve the conflict and the values are lists of strings naming
292 the keys the conflict resolution function applies to. Instead of
292 the keys the conflict resolution function applies to. Instead of
293 a list of strings a space separated string can be used, like
293 a list of strings a space separated string can be used, like
294 'a b c'.
294 'a b c'.
295 kw : dict
295 kw : dict
296 Additional key, value pairs to merge in
296 Additional key, value pairs to merge in
297
297
298 Notes
298 Notes
299 -----
299 -----
300
300
301 The `__conflict_solve` dict is a dictionary of binary functions which will be used to
301 The `__conflict_solve` dict is a dictionary of binary functions which will be used to
302 solve key conflicts. Here is an example::
302 solve key conflicts. Here is an example::
303
303
304 __conflict_solve = dict(
304 __conflict_solve = dict(
305 func1=['a','b','c'],
305 func1=['a','b','c'],
306 func2=['d','e']
306 func2=['d','e']
307 )
307 )
308
308
309 In this case, the function :func:`func1` will be used to resolve
309 In this case, the function :func:`func1` will be used to resolve
310 keys 'a', 'b' and 'c' and the function :func:`func2` will be used for
310 keys 'a', 'b' and 'c' and the function :func:`func2` will be used for
311 keys 'd' and 'e'. This could also be written as::
311 keys 'd' and 'e'. This could also be written as::
312
312
313 __conflict_solve = dict(func1='a b c',func2='d e')
313 __conflict_solve = dict(func1='a b c',func2='d e')
314
314
315 These functions will be called for each key they apply to with the
315 These functions will be called for each key they apply to with the
316 form::
316 form::
317
317
318 func1(self['a'], other['a'])
318 func1(self['a'], other['a'])
319
319
320 The return value is used as the final merged value.
320 The return value is used as the final merged value.
321
321
322 As a convenience, merge() provides five (the most commonly needed)
322 As a convenience, merge() provides five (the most commonly needed)
323 pre-defined policies: preserve, update, add, add_flip and add_s. The
323 pre-defined policies: preserve, update, add, add_flip and add_s. The
324 easiest explanation is their implementation::
324 easiest explanation is their implementation::
325
325
326 preserve = lambda old,new: old
326 preserve = lambda old,new: old
327 update = lambda old,new: new
327 update = lambda old,new: new
328 add = lambda old,new: old + new
328 add = lambda old,new: old + new
329 add_flip = lambda old,new: new + old # note change of order!
329 add_flip = lambda old,new: new + old # note change of order!
330 add_s = lambda old,new: old + ' ' + new # only for str!
330 add_s = lambda old,new: old + ' ' + new # only for str!
331
331
332 You can use those four words (as strings) as keys instead
332 You can use those four words (as strings) as keys instead
333 of defining them as functions, and the merge method will substitute
333 of defining them as functions, and the merge method will substitute
334 the appropriate functions for you.
334 the appropriate functions for you.
335
335
336 For more complicated conflict resolution policies, you still need to
336 For more complicated conflict resolution policies, you still need to
337 construct your own functions.
337 construct your own functions.
338
338
339 Examples
339 Examples
340 --------
340 --------
341
341
342 This show the default policy:
342 This show the default policy:
343
343
344 >>> s = Struct(a=10,b=30)
344 >>> s = Struct(a=10,b=30)
345 >>> s2 = Struct(a=20,c=40)
345 >>> s2 = Struct(a=20,c=40)
346 >>> s.merge(s2)
346 >>> s.merge(s2)
347 >>> sorted(s.items())
347 >>> sorted(s.items())
348 [('a', 10), ('b', 30), ('c', 40)]
348 [('a', 10), ('b', 30), ('c', 40)]
349
349
350 Now, show how to specify a conflict dict:
350 Now, show how to specify a conflict dict:
351
351
352 >>> s = Struct(a=10,b=30)
352 >>> s = Struct(a=10,b=30)
353 >>> s2 = Struct(a=20,b=40)
353 >>> s2 = Struct(a=20,b=40)
354 >>> conflict = {'update':'a','add':'b'}
354 >>> conflict = {'update':'a','add':'b'}
355 >>> s.merge(s2,conflict)
355 >>> s.merge(s2,conflict)
356 >>> sorted(s.items())
356 >>> sorted(s.items())
357 [('a', 20), ('b', 70)]
357 [('a', 20), ('b', 70)]
358 """
358 """
359
359
360 data_dict = dict(__loc_data__,**kw)
360 data_dict = dict(__loc_data__,**kw)
361
361
362 # policies for conflict resolution: two argument functions which return
362 # policies for conflict resolution: two argument functions which return
363 # the value that will go in the new struct
363 # the value that will go in the new struct
364 preserve = lambda old,new: old
364 preserve = lambda old,new: old
365 update = lambda old,new: new
365 update = lambda old,new: new
366 add = lambda old,new: old + new
366 add = lambda old,new: old + new
367 add_flip = lambda old,new: new + old # note change of order!
367 add_flip = lambda old,new: new + old # note change of order!
368 add_s = lambda old,new: old + ' ' + new
368 add_s = lambda old,new: old + ' ' + new
369
369
370 # default policy is to keep current keys when there's a conflict
370 # default policy is to keep current keys when there's a conflict
371 conflict_solve = dict.fromkeys(self, preserve)
371 conflict_solve = dict.fromkeys(self, preserve)
372
372
373 # the conflict_solve dictionary is given by the user 'inverted': we
373 # the conflict_solve dictionary is given by the user 'inverted': we
374 # need a name-function mapping, it comes as a function -> names
374 # need a name-function mapping, it comes as a function -> names
375 # dict. Make a local copy (b/c we'll make changes), replace user
375 # dict. Make a local copy (b/c we'll make changes), replace user
376 # strings for the three builtin policies and invert it.
376 # strings for the three builtin policies and invert it.
377 if __conflict_solve:
377 if __conflict_solve:
378 inv_conflict_solve_user = __conflict_solve.copy()
378 inv_conflict_solve_user = __conflict_solve.copy()
379 for name, func in [('preserve',preserve), ('update',update),
379 for name, func in [('preserve',preserve), ('update',update),
380 ('add',add), ('add_flip',add_flip),
380 ('add',add), ('add_flip',add_flip),
381 ('add_s',add_s)]:
381 ('add_s',add_s)]:
382 if name in inv_conflict_solve_user.keys():
382 if name in inv_conflict_solve_user.keys():
383 inv_conflict_solve_user[func] = inv_conflict_solve_user[name]
383 inv_conflict_solve_user[func] = inv_conflict_solve_user[name]
384 del inv_conflict_solve_user[name]
384 del inv_conflict_solve_user[name]
385 conflict_solve.update(self.__dict_invert(inv_conflict_solve_user))
385 conflict_solve.update(self.__dict_invert(inv_conflict_solve_user))
386 for key in data_dict:
386 for key in data_dict:
387 if key not in self:
387 if key not in self:
388 self[key] = data_dict[key]
388 self[key] = data_dict[key]
389 else:
389 else:
390 self[key] = conflict_solve[key](self[key],data_dict[key])
390 self[key] = conflict_solve[key](self[key],data_dict[key])
391
391
@@ -1,68 +1,68 b''
1 """String dispatch class to match regexps and dispatch commands.
1 """String dispatch class to match regexps and dispatch commands.
2 """
2 """
3
3
4 # Stdlib imports
4 # Stdlib imports
5 import re
5 import re
6
6
7 # Our own modules
7 # Our own modules
8 from IPython.core.hooks import CommandChainDispatcher
8 from IPython.core.hooks import CommandChainDispatcher
9
9
10 # Code begins
10 # Code begins
11 class StrDispatch(object):
11 class StrDispatch(object):
12 """Dispatch (lookup) a set of strings / regexps for match.
12 """Dispatch (lookup) a set of strings / regexps for match.
13
13
14 Example:
14 Example:
15
15
16 >>> dis = StrDispatch()
16 >>> dis = StrDispatch()
17 >>> dis.add_s('hei',34, priority = 4)
17 >>> dis.add_s('hei',34, priority = 4)
18 >>> dis.add_s('hei',123, priority = 2)
18 >>> dis.add_s('hei',123, priority = 2)
19 >>> dis.add_re('h.i', 686)
19 >>> dis.add_re('h.i', 686)
20 >>> print list(dis.flat_matches('hei'))
20 >>> print(list(dis.flat_matches('hei')))
21 [123, 34, 686]
21 [123, 34, 686]
22 """
22 """
23
23
24 def __init__(self):
24 def __init__(self):
25 self.strs = {}
25 self.strs = {}
26 self.regexs = {}
26 self.regexs = {}
27
27
28 def add_s(self, s, obj, priority= 0 ):
28 def add_s(self, s, obj, priority= 0 ):
29 """ Adds a target 'string' for dispatching """
29 """ Adds a target 'string' for dispatching """
30
30
31 chain = self.strs.get(s, CommandChainDispatcher())
31 chain = self.strs.get(s, CommandChainDispatcher())
32 chain.add(obj,priority)
32 chain.add(obj,priority)
33 self.strs[s] = chain
33 self.strs[s] = chain
34
34
35 def add_re(self, regex, obj, priority= 0 ):
35 def add_re(self, regex, obj, priority= 0 ):
36 """ Adds a target regexp for dispatching """
36 """ Adds a target regexp for dispatching """
37
37
38 chain = self.regexs.get(regex, CommandChainDispatcher())
38 chain = self.regexs.get(regex, CommandChainDispatcher())
39 chain.add(obj,priority)
39 chain.add(obj,priority)
40 self.regexs[regex] = chain
40 self.regexs[regex] = chain
41
41
42 def dispatch(self, key):
42 def dispatch(self, key):
43 """ Get a seq of Commandchain objects that match key """
43 """ Get a seq of Commandchain objects that match key """
44 if key in self.strs:
44 if key in self.strs:
45 yield self.strs[key]
45 yield self.strs[key]
46
46
47 for r, obj in self.regexs.items():
47 for r, obj in self.regexs.items():
48 if re.match(r, key):
48 if re.match(r, key):
49 yield obj
49 yield obj
50 else:
50 else:
51 #print "nomatch",key # dbg
51 #print "nomatch",key # dbg
52 pass
52 pass
53
53
54 def __repr__(self):
54 def __repr__(self):
55 return "<Strdispatch %s, %s>" % (self.strs, self.regexs)
55 return "<Strdispatch %s, %s>" % (self.strs, self.regexs)
56
56
57 def s_matches(self, key):
57 def s_matches(self, key):
58 if key not in self.strs:
58 if key not in self.strs:
59 return
59 return
60 for el in self.strs[key]:
60 for el in self.strs[key]:
61 yield el[1]
61 yield el[1]
62
62
63 def flat_matches(self, key):
63 def flat_matches(self, key):
64 """ Yield all 'value' targets, without priority """
64 """ Yield all 'value' targets, without priority """
65 for val in self.dispatch(key):
65 for val in self.dispatch(key):
66 for el in val:
66 for el in val:
67 yield el[1] # only value, no priority
67 yield el[1] # only value, no priority
68 return
68 return
@@ -1,147 +1,143 b''
1 """Some tests for the wildcard utilities."""
1 """Some tests for the wildcard utilities."""
2
2
3 #-----------------------------------------------------------------------------
3 #-----------------------------------------------------------------------------
4 # Library imports
4 # Library imports
5 #-----------------------------------------------------------------------------
5 #-----------------------------------------------------------------------------
6 # Stdlib
6 # Stdlib
7 import unittest
7 import unittest
8
8
9 # Our own
9 # Our own
10 from IPython.utils import wildcard
10 from IPython.utils import wildcard
11
11
12 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
13 # Globals for test
13 # Globals for test
14 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
15
15
16 class obj_t(object):
16 class obj_t(object):
17 pass
17 pass
18
18
19 root = obj_t()
19 root = obj_t()
20 l = ["arna","abel","ABEL","active","bob","bark","abbot"]
20 l = ["arna","abel","ABEL","active","bob","bark","abbot"]
21 q = ["kate","loop","arne","vito","lucifer","koppel"]
21 q = ["kate","loop","arne","vito","lucifer","koppel"]
22 for x in l:
22 for x in l:
23 o = obj_t()
23 o = obj_t()
24 setattr(root,x,o)
24 setattr(root,x,o)
25 for y in q:
25 for y in q:
26 p = obj_t()
26 p = obj_t()
27 setattr(o,y,p)
27 setattr(o,y,p)
28 root._apan = obj_t()
28 root._apan = obj_t()
29 root._apan.a = 10
29 root._apan.a = 10
30 root._apan._a = 20
30 root._apan._a = 20
31 root._apan.__a = 20
31 root._apan.__a = 20
32 root.__anka = obj_t()
32 root.__anka = obj_t()
33 root.__anka.a = 10
33 root.__anka.a = 10
34 root.__anka._a = 20
34 root.__anka._a = 20
35 root.__anka.__a = 20
35 root.__anka.__a = 20
36
36
37 root._APAN = obj_t()
37 root._APAN = obj_t()
38 root._APAN.a = 10
38 root._APAN.a = 10
39 root._APAN._a = 20
39 root._APAN._a = 20
40 root._APAN.__a = 20
40 root._APAN.__a = 20
41 root.__ANKA = obj_t()
41 root.__ANKA = obj_t()
42 root.__ANKA.a = 10
42 root.__ANKA.a = 10
43 root.__ANKA._a = 20
43 root.__ANKA._a = 20
44 root.__ANKA.__a = 20
44 root.__ANKA.__a = 20
45
45
46 #-----------------------------------------------------------------------------
46 #-----------------------------------------------------------------------------
47 # Test cases
47 # Test cases
48 #-----------------------------------------------------------------------------
48 #-----------------------------------------------------------------------------
49
49
50 class Tests (unittest.TestCase):
50 class Tests (unittest.TestCase):
51 def test_case(self):
51 def test_case(self):
52 ns=root.__dict__
52 ns=root.__dict__
53 tests=[
53 tests=[
54 ("a*", ["abbot","abel","active","arna",]),
54 ("a*", ["abbot","abel","active","arna",]),
55 ("?b*.?o*",["abbot.koppel","abbot.loop","abel.koppel","abel.loop",]),
55 ("?b*.?o*",["abbot.koppel","abbot.loop","abel.koppel","abel.loop",]),
56 ("_a*", []),
56 ("_a*", []),
57 ("_*anka", ["__anka",]),
57 ("_*anka", ["__anka",]),
58 ("_*a*", ["__anka",]),
58 ("_*a*", ["__anka",]),
59 ]
59 ]
60 for pat,res in tests:
60 for pat,res in tests:
61 res.sort()
61 res.sort()
62 a=wildcard.list_namespace(ns,"all",pat,ignore_case=False,
62 a=sorted(wildcard.list_namespace(ns,"all",pat,ignore_case=False,
63 show_all=False).keys()
63 show_all=False).keys())
64 a.sort()
65 self.assertEqual(a,res)
64 self.assertEqual(a,res)
66
65
67 def test_case_showall(self):
66 def test_case_showall(self):
68 ns=root.__dict__
67 ns=root.__dict__
69 tests=[
68 tests=[
70 ("a*", ["abbot","abel","active","arna",]),
69 ("a*", ["abbot","abel","active","arna",]),
71 ("?b*.?o*",["abbot.koppel","abbot.loop","abel.koppel","abel.loop",]),
70 ("?b*.?o*",["abbot.koppel","abbot.loop","abel.koppel","abel.loop",]),
72 ("_a*", ["_apan"]),
71 ("_a*", ["_apan"]),
73 ("_*anka", ["__anka",]),
72 ("_*anka", ["__anka",]),
74 ("_*a*", ["__anka","_apan",]),
73 ("_*a*", ["__anka","_apan",]),
75 ]
74 ]
76 for pat,res in tests:
75 for pat,res in tests:
77 res.sort()
76 res.sort()
78 a=wildcard.list_namespace(ns,"all",pat,ignore_case=False,
77 a=sorted(wildcard.list_namespace(ns,"all",pat,ignore_case=False,
79 show_all=True).keys()
78 show_all=True).keys())
80 a.sort()
81 self.assertEqual(a,res)
79 self.assertEqual(a,res)
82
80
83
81
84 def test_nocase(self):
82 def test_nocase(self):
85 ns=root.__dict__
83 ns=root.__dict__
86 tests=[
84 tests=[
87 ("a*", ["abbot","abel","ABEL","active","arna",]),
85 ("a*", ["abbot","abel","ABEL","active","arna",]),
88 ("?b*.?o*",["abbot.koppel","abbot.loop","abel.koppel","abel.loop",
86 ("?b*.?o*",["abbot.koppel","abbot.loop","abel.koppel","abel.loop",
89 "ABEL.koppel","ABEL.loop",]),
87 "ABEL.koppel","ABEL.loop",]),
90 ("_a*", []),
88 ("_a*", []),
91 ("_*anka", ["__anka","__ANKA",]),
89 ("_*anka", ["__anka","__ANKA",]),
92 ("_*a*", ["__anka","__ANKA",]),
90 ("_*a*", ["__anka","__ANKA",]),
93 ]
91 ]
94 for pat,res in tests:
92 for pat,res in tests:
95 res.sort()
93 res.sort()
96 a=wildcard.list_namespace(ns,"all",pat,ignore_case=True,
94 a=sorted(wildcard.list_namespace(ns,"all",pat,ignore_case=True,
97 show_all=False).keys()
95 show_all=False).keys())
98 a.sort()
99 self.assertEqual(a,res)
96 self.assertEqual(a,res)
100
97
101 def test_nocase_showall(self):
98 def test_nocase_showall(self):
102 ns=root.__dict__
99 ns=root.__dict__
103 tests=[
100 tests=[
104 ("a*", ["abbot","abel","ABEL","active","arna",]),
101 ("a*", ["abbot","abel","ABEL","active","arna",]),
105 ("?b*.?o*",["abbot.koppel","abbot.loop","abel.koppel","abel.loop",
102 ("?b*.?o*",["abbot.koppel","abbot.loop","abel.koppel","abel.loop",
106 "ABEL.koppel","ABEL.loop",]),
103 "ABEL.koppel","ABEL.loop",]),
107 ("_a*", ["_apan","_APAN"]),
104 ("_a*", ["_apan","_APAN"]),
108 ("_*anka", ["__anka","__ANKA",]),
105 ("_*anka", ["__anka","__ANKA",]),
109 ("_*a*", ["__anka","__ANKA","_apan","_APAN"]),
106 ("_*a*", ["__anka","__ANKA","_apan","_APAN"]),
110 ]
107 ]
111 for pat,res in tests:
108 for pat,res in tests:
112 res.sort()
109 res.sort()
113 a=wildcard.list_namespace(ns,"all",pat,ignore_case=True,
110 a=sorted(wildcard.list_namespace(ns,"all",pat,ignore_case=True,
114 show_all=True).keys()
111 show_all=True).keys())
115 a.sort()
112 a.sort()
116 self.assertEqual(a,res)
113 self.assertEqual(a,res)
117
114
118 def test_dict_attributes(self):
115 def test_dict_attributes(self):
119 """Dictionaries should be indexed by attributes, not by keys. This was
116 """Dictionaries should be indexed by attributes, not by keys. This was
120 causing Github issue 129."""
117 causing Github issue 129."""
121 ns = {"az":{"king":55}, "pq":{1:0}}
118 ns = {"az":{"king":55}, "pq":{1:0}}
122 tests = [
119 tests = [
123 ("a*", ["az"]),
120 ("a*", ["az"]),
124 ("az.k*", ["az.keys"]),
121 ("az.k*", ["az.keys"]),
125 ("pq.k*", ["pq.keys"])
122 ("pq.k*", ["pq.keys"])
126 ]
123 ]
127 for pat, res in tests:
124 for pat, res in tests:
128 res.sort()
125 res.sort()
129 a = wildcard.list_namespace(ns, "all", pat, ignore_case=False,
126 a = sorted(wildcard.list_namespace(ns, "all", pat, ignore_case=False,
130 show_all=True).keys()
127 show_all=True).keys())
131 a.sort()
132 self.assertEqual(a, res)
128 self.assertEqual(a, res)
133
129
134 def test_dict_dir(self):
130 def test_dict_dir(self):
135 class A(object):
131 class A(object):
136 def __init__(self):
132 def __init__(self):
137 self.a = 1
133 self.a = 1
138 self.b = 2
134 self.b = 2
139 def __getattribute__(self, name):
135 def __getattribute__(self, name):
140 if name=="a":
136 if name=="a":
141 raise AttributeError
137 raise AttributeError
142 return object.__getattribute__(self, name)
138 return object.__getattribute__(self, name)
143
139
144 a = A()
140 a = A()
145 adict = wildcard.dict_dir(a)
141 adict = wildcard.dict_dir(a)
146 assert "a" not in adict # change to assertNotIn method in >= 2.7
142 assert "a" not in adict # change to assertNotIn method in >= 2.7
147 self.assertEqual(adict["b"], 2)
143 self.assertEqual(adict["b"], 2)
General Comments 0
You need to be logged in to leave comments. Login now