59
59
def lookup_by_name (name , nsdicts ):
60
60
"""
61
61
Look up an object by name from a sequence of namespace dictionaries.
62
- Returns a tuple of (nsdict, object, attributes ); nsdict is the
63
- dictionary the name was found in, object is the name of the base object
64
- the name is bound to, and the attributes list is the chain of attributes
65
- of the object that complete the name.
62
+ Returns a tuple of (nsdict, obj_name, attrs ); nsdict is the namespace
63
+ dictionary the name was found in, obj_name is the name of the base object
64
+ the name is bound to, and the attrs list is the chain of attributes
65
+ of the object that completes the name.
66
66
67
67
>>> import os
68
- >>> nsdict, name, attributes = lookup_by_name("os.path.isdir",
68
+ >>> nsdict, obj_name, attrs = lookup_by_name("os.path.isdir",
69
69
... (locals(),))
70
- >>> name, attributes
70
+ >>> obj_name, attrs
71
71
('os', ['path', 'isdir'])
72
- >>> nsdict, name, attributes = lookup_by_name("os.monkey", (locals(),))
72
+ >>> getattr(getattr(nsdict[obj_name], attrs[0]), attrs[1])
73
+ <function isdir at ...>
74
+ >>> lookup_by_name("os.monkey", (locals(),))
73
75
Traceback (most recent call last):
74
76
...
75
77
NameError: name 'os.monkey' is not defined
76
-
78
+
77
79
"""
78
80
for nsdict in nsdicts :
79
81
attrs = name .split ("." )
@@ -165,6 +167,22 @@ def mock(name, nsdicts=None, mock_obj=None, **kw):
165
167
>>> Test.sm()
166
168
'sm'
167
169
170
+ Test mocking a proxy object::
171
+
172
+ >>> class Proxy(object):
173
+ ... def __init__(self, obj):
174
+ ... self._obj = obj
175
+ ... def __getattr__(self, name):
176
+ ... return getattr(self._obj, name)
177
+ >>> import os
178
+ >>> os = Proxy(os)
179
+ >>> os.path.isfile
180
+ <function isfile at ...>
181
+ >>> mock('os.path.isfile')
182
+ >>> os.path.isfile
183
+ <Mock ... os.path.isfile>
184
+ >>> restore()
185
+
168
186
"""
169
187
if nsdicts is None :
170
188
stack = inspect .stack ()
@@ -196,8 +214,14 @@ def mock(name, nsdicts=None, mock_obj=None, **kw):
196
214
nsdict [obj_name ] = mock_obj
197
215
else :
198
216
for attr in attrs [:- 1 ]:
199
- tmp = tmp .__dict__ [attr ]
200
- original = tmp .__dict__ [attrs [- 1 ]]
217
+ try :
218
+ tmp = tmp .__dict__ [attr ]
219
+ except KeyError :
220
+ tmp = getattr (tmp , attr )
221
+ try :
222
+ original = tmp .__dict__ [attrs [- 1 ]]
223
+ except KeyError :
224
+ original = getattr (tmp , attrs [- 1 ])
201
225
setattr (tmp , attrs [- 1 ], mock_obj )
202
226
203
227
mocked .append ((original , nsdict , obj_name , attrs ))
@@ -217,7 +241,10 @@ def restore():
217
241
else :
218
242
tmp = nsdict [name ]
219
243
for attr in attrs [:- 1 ]:
220
- tmp = tmp .__dict__ [attr ]
244
+ try :
245
+ tmp = tmp .__dict__ [attr ]
246
+ except KeyError :
247
+ tmp = getattr (tmp , attr )
221
248
setattr (tmp , attrs [- 1 ], original )
222
249
223
250
def assert_same_trace (tracker , want ):
@@ -504,7 +531,7 @@ def __setattr__(self, attr, value):
504
531
'mock_returns_func' ,
505
532
'mock_returns_iter' ,
506
533
'mock_tracker' ,
507
- 'show_attrs ' ,
534
+ 'mock_show_attrs ' ,
508
535
)):
509
536
if attr == 'mock_returns_iter' and value is not None :
510
537
value = iter (value )
@@ -541,6 +568,10 @@ def __setattr__(self, attr, value):
541
568
... pass
542
569
... else:
543
570
... raise AssertionError('m() should have raised ValueError')
571
+ >>> m.mock_tracker = Printer(sys.stdout)
572
+ >>> m.mock_show_attrs = True
573
+ >>> m.a = 2
574
+ Set mock_obj.a = 2
544
575
""" ,
545
576
546
577
"mock" :
0 commit comments