1 from test
import test_support
5 class FuncAttrsTest(unittest
.TestCase
):
16 def cannot_set_attr(self
, obj
, name
, value
, exceptions
):
17 # Helper method for other tests.
19 setattr(obj
, name
, value
)
23 self
.fail("shouldn't be able to set %s to %r" % (name
, value
))
29 self
.fail("shouldn't be able to del %s" % name
)
32 class FunctionPropertiesTest(FuncAttrsTest
):
33 # Include the external setUp method that is common to all tests
34 def test_module(self
):
35 self
.assertEqual(self
.b
.__module
__, __name__
)
37 def test_dir_includes_correct_attrs(self
):
39 self
.assertTrue('known_attr' in dir(self
.b
),
40 "set attributes not in dir listing of method")
41 # Test on underlying function object of method
42 self
.f
.a
.im_func
.known_attr
= 7
43 self
.assertTrue('known_attr' in dir(self
.f
.a
),
44 "set attribute on unbound method implementation in "
46 self
.assertTrue('known_attr' in dir(self
.fi
.a
),
47 "set attribute on unbound method implementations, "
48 "should show up in next dir")
50 def test_duplicate_function_equality(self
):
51 # Body of `duplicate' is the exact same as self.b
55 self
.assertNotEqual(self
.b
, duplicate
)
57 def test_copying_func_code(self
):
59 self
.assertEqual(test(), None)
60 test
.func_code
= self
.b
.func_code
61 self
.assertEqual(test(), 3) # self.b always returns 3, arbitrarily
63 def test_func_globals(self
):
64 self
.assertIs(self
.b
.func_globals
, globals())
65 self
.cannot_set_attr(self
.b
, 'func_globals', 2, TypeError)
67 def test_func_closure(self
):
71 self
.assertTrue(isinstance(c
, tuple))
72 self
.assertEqual(len(c
), 1)
73 # don't have a type object handy
74 self
.assertEqual(c
[0].__class
__.__name
__, "cell")
75 self
.cannot_set_attr(f
, "func_closure", c
, TypeError)
77 def test_empty_cell(self
):
80 f
.func_closure
[0].cell_contents
84 self
.fail("shouldn't be able to read an empty cell")
87 def test_func_name(self
):
88 self
.assertEqual(self
.b
.__name
__, 'b')
89 self
.assertEqual(self
.b
.func_name
, 'b')
91 self
.assertEqual(self
.b
.__name
__, 'c')
92 self
.assertEqual(self
.b
.func_name
, 'c')
93 self
.b
.func_name
= 'd'
94 self
.assertEqual(self
.b
.__name
__, 'd')
95 self
.assertEqual(self
.b
.func_name
, 'd')
96 # __name__ and func_name must be a string
97 self
.cannot_set_attr(self
.b
, '__name__', 7, TypeError)
98 self
.cannot_set_attr(self
.b
, 'func_name', 7, TypeError)
99 # __name__ must be available when in restricted mode. Exec will raise
100 # AttributeError if __name__ is not available on f.
101 s
= """def f(): pass\nf.__name__"""
102 exec s
in {'__builtins__': {}}
103 # Test on methods, too
104 self
.assertEqual(self
.f
.a
.__name
__, 'a')
105 self
.assertEqual(self
.fi
.a
.__name
__, 'a')
106 self
.cannot_set_attr(self
.f
.a
, "__name__", 'a', AttributeError)
107 self
.cannot_set_attr(self
.fi
.a
, "__name__", 'a', AttributeError)
109 def test_func_code(self
):
110 num_one
, num_two
= 7, 8
113 def c(): return num_one
114 def d(): return num_two
115 def e(): return num_one
, num_two
116 for func
in [a
, b
, c
, d
, e
]:
117 self
.assertEqual(type(func
.func_code
), types
.CodeType
)
118 self
.assertEqual(c(), 7)
119 self
.assertEqual(d(), 8)
120 d
.func_code
= c
.func_code
121 self
.assertEqual(c
.func_code
, d
.func_code
)
122 self
.assertEqual(c(), 7)
123 # self.assertEqual(d(), 7)
125 b
.func_code
= c
.func_code
129 self
.fail("func_code with different numbers of free vars should "
132 e
.func_code
= d
.func_code
136 self
.fail("func_code with different numbers of free vars should "
139 def test_blank_func_defaults(self
):
140 self
.assertEqual(self
.b
.func_defaults
, None)
141 del self
.b
.func_defaults
142 self
.assertEqual(self
.b
.func_defaults
, None)
144 def test_func_default_args(self
):
145 def first_func(a
, b
):
147 def second_func(a
=1, b
=2):
149 self
.assertEqual(first_func
.func_defaults
, None)
150 self
.assertEqual(second_func
.func_defaults
, (1, 2))
151 first_func
.func_defaults
= (1, 2)
152 self
.assertEqual(first_func
.func_defaults
, (1, 2))
153 self
.assertEqual(first_func(), 3)
154 self
.assertEqual(first_func(3), 5)
155 self
.assertEqual(first_func(3, 5), 8)
156 del second_func
.func_defaults
157 self
.assertEqual(second_func
.func_defaults
, None)
163 self
.fail("func_defaults does not update; deleting it does not "
164 "remove requirement")
167 class InstancemethodAttrTest(FuncAttrsTest
):
168 def test_im_class(self
):
169 self
.assertEqual(self
.f
.a
.im_class
, self
.f
)
170 self
.assertEqual(self
.fi
.a
.im_class
, self
.f
)
171 self
.cannot_set_attr(self
.f
.a
, "im_class", self
.f
, TypeError)
172 self
.cannot_set_attr(self
.fi
.a
, "im_class", self
.f
, TypeError)
174 def test_im_func(self
):
176 self
.assertEqual(self
.f
.b
.im_func
, self
.b
)
177 self
.assertEqual(self
.fi
.b
.im_func
, self
.b
)
178 self
.cannot_set_attr(self
.f
.b
, "im_func", self
.b
, TypeError)
179 self
.cannot_set_attr(self
.fi
.b
, "im_func", self
.b
, TypeError)
181 def test_im_self(self
):
182 self
.assertEqual(self
.f
.a
.im_self
, None)
183 self
.assertEqual(self
.fi
.a
.im_self
, self
.fi
)
184 self
.cannot_set_attr(self
.f
.a
, "im_self", None, TypeError)
185 self
.cannot_set_attr(self
.fi
.a
, "im_self", self
.fi
, TypeError)
187 def test_im_func_non_method(self
):
188 # Behavior should be the same when a method is added via an attr
190 self
.f
.id = types
.MethodType(id, None, self
.f
)
191 self
.assertEqual(self
.fi
.id(), id(self
.fi
))
192 self
.assertNotEqual(self
.fi
.id(), id(self
.f
))
195 self
.f
.id.unknown_attr
196 except AttributeError:
199 self
.fail("using unknown attributes should raise AttributeError")
200 # Test assignment and deletion
201 self
.cannot_set_attr(self
.f
.id, 'unknown_attr', 2, AttributeError)
202 self
.cannot_set_attr(self
.fi
.id, 'unknown_attr', 2, AttributeError)
204 def test_implicit_method_properties(self
):
205 self
.f
.a
.im_func
.known_attr
= 7
206 self
.assertEqual(self
.f
.a
.known_attr
, 7)
207 self
.assertEqual(self
.fi
.a
.known_attr
, 7)
210 class ArbitraryFunctionAttrTest(FuncAttrsTest
):
211 def test_set_attr(self
):
212 # setting attributes only works on function objects
213 self
.b
.known_attr
= 7
214 self
.assertEqual(self
.b
.known_attr
, 7)
215 for func
in [self
.f
.a
, self
.fi
.a
]:
218 except AttributeError:
221 self
.fail("setting attributes on methods should raise error")
223 def test_delete_unknown_attr(self
):
225 del self
.b
.unknown_attr
226 except AttributeError:
229 self
.fail("deleting unknown attribute should raise TypeError")
231 def test_setting_attrs_duplicates(self
):
233 self
.f
.a
.klass
= self
.f
234 except AttributeError:
237 self
.fail("setting arbitrary attribute in unbound function "
238 " should raise AttributeError")
239 self
.f
.a
.im_func
.klass
= self
.f
240 for method
in [self
.f
.a
, self
.fi
.a
, self
.fi
.a
.im_func
]:
241 self
.assertEqual(method
.klass
, self
.f
)
243 def test_unset_attr(self
):
244 for func
in [self
.b
, self
.f
.a
, self
.fi
.a
]:
246 func
.non_existent_attr
247 except AttributeError:
250 self
.fail("using unknown attributes should raise "
254 class FunctionDictsTest(FuncAttrsTest
):
255 def test_setting_dict_to_invalid(self
):
256 self
.cannot_set_attr(self
.b
, '__dict__', None, TypeError)
257 self
.cannot_set_attr(self
.b
, 'func_dict', None, TypeError)
258 from UserDict
import UserDict
259 d
= UserDict({'known_attr': 7})
260 self
.cannot_set_attr(self
.f
.a
.im_func
, '__dict__', d
, TypeError)
261 self
.cannot_set_attr(self
.fi
.a
.im_func
, '__dict__', d
, TypeError)
263 def test_setting_dict_to_valid(self
):
264 d
= {'known_attr': 7}
266 # Setting dict is only possible on the underlying function objects
267 self
.f
.a
.im_func
.__dict
__ = d
269 self
.assertIs(d
, self
.b
.__dict
__)
270 self
.assertIs(d
, self
.b
.func_dict
)
271 # ... and on all the different ways of referencing the method's func
272 self
.assertIs(d
, self
.f
.a
.im_func
.__dict
__)
273 self
.assertIs(d
, self
.f
.a
.__dict
__)
274 self
.assertIs(d
, self
.fi
.a
.im_func
.__dict
__)
275 self
.assertIs(d
, self
.fi
.a
.__dict
__)
277 self
.assertEqual(self
.b
.known_attr
, 7)
278 self
.assertEqual(self
.b
.__dict
__['known_attr'], 7)
279 self
.assertEqual(self
.b
.func_dict
['known_attr'], 7)
280 # ... and again, on all the different method's names
281 self
.assertEqual(self
.f
.a
.im_func
.known_attr
, 7)
282 self
.assertEqual(self
.f
.a
.known_attr
, 7)
283 self
.assertEqual(self
.fi
.a
.im_func
.known_attr
, 7)
284 self
.assertEqual(self
.fi
.a
.known_attr
, 7)
286 def test_delete_func_dict(self
):
292 self
.fail("deleting function dictionary should raise TypeError")
298 self
.fail("deleting function dictionary should raise TypeError")
300 def test_unassigned_dict(self
):
301 self
.assertEqual(self
.b
.__dict
__, {})
303 def test_func_as_dict_key(self
):
304 value
= "Some string"
307 self
.assertEqual(d
[self
.b
], value
)
310 class FunctionDocstringTest(FuncAttrsTest
):
311 def test_set_docstring_attr(self
):
312 self
.assertEqual(self
.b
.__doc
__, None)
313 self
.assertEqual(self
.b
.func_doc
, None)
314 docstr
= "A test method that does nothing"
315 self
.b
.__doc
__ = self
.f
.a
.im_func
.__doc
__ = docstr
316 self
.assertEqual(self
.b
.__doc
__, docstr
)
317 self
.assertEqual(self
.b
.func_doc
, docstr
)
318 self
.assertEqual(self
.f
.a
.__doc
__, docstr
)
319 self
.assertEqual(self
.fi
.a
.__doc
__, docstr
)
320 self
.cannot_set_attr(self
.f
.a
, "__doc__", docstr
, AttributeError)
321 self
.cannot_set_attr(self
.fi
.a
, "__doc__", docstr
, AttributeError)
323 def test_delete_docstring(self
):
324 self
.b
.__doc
__ = "The docstring"
326 self
.assertEqual(self
.b
.__doc
__, None)
327 self
.assertEqual(self
.b
.func_doc
, None)
328 self
.b
.func_doc
= "The docstring"
330 self
.assertEqual(self
.b
.__doc
__, None)
331 self
.assertEqual(self
.b
.func_doc
, None)
334 class StaticMethodAttrsTest(unittest
.TestCase
):
335 def test_func_attribute(self
):
340 self
.assertTrue(c
.__func
__ is f
)
343 self
.assertTrue(s
.__func
__ is f
)
347 test_support
.run_unittest(FunctionPropertiesTest
, InstancemethodAttrTest
,
348 ArbitraryFunctionAttrTest
, FunctionDictsTest
,
349 FunctionDocstringTest
,
350 StaticMethodAttrsTest
)
352 if __name__
== "__main__":