blob: b639ca20425f1fdf0648fafacb220cc2bcf24433 [file] [log] [blame]
Georg Brandlc8088df2008-02-02 10:18:15 +00001from test import test_support
Guido van Rossumd9d1d4a2001-09-17 23:46:56 +00002import types
Georg Brandlc8088df2008-02-02 10:18:15 +00003import unittest
Barry Warsaw4a420a02001-01-15 20:30:15 +00004
Georg Brandlc8088df2008-02-02 10:18:15 +00005class FuncAttrsTest(unittest.TestCase):
6 def setUp(self):
7 class F:
8 def a(self):
9 pass
10 def b():
11 return 3
12 self.f = F
13 self.fi = F()
14 self.b = b
Barry Warsaw4a420a02001-01-15 20:30:15 +000015
Georg Brandled4ca822009-09-04 11:19:34 +000016 def cannot_set_attr(self, obj, name, value, exceptions):
17 # Helper method for other tests.
18 try:
19 setattr(obj, name, value)
20 except exceptions:
21 pass
22 else:
23 self.fail("shouldn't be able to set %s to %r" % (name, value))
24 try:
25 delattr(obj, name)
26 except exceptions:
27 pass
28 else:
29 self.fail("shouldn't be able to del %s" % name)
Georg Brandl8ada1772008-02-05 18:32:47 +000030
31
Georg Brandlc8088df2008-02-02 10:18:15 +000032class 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__)
Jeremy Hylton4f0dcc92003-01-31 18:33:18 +000036
Georg Brandlc8088df2008-02-02 10:18:15 +000037 def test_dir_includes_correct_attrs(self):
38 self.b.known_attr = 7
Ezio Melottiaa980582010-01-23 23:04:36 +000039 self.assertIn('known_attr', dir(self.b),
Georg Brandled4ca822009-09-04 11:19:34 +000040 "set attributes not in dir listing of method")
Georg Brandlc8088df2008-02-02 10:18:15 +000041 # Test on underlying function object of method
42 self.f.a.im_func.known_attr = 7
Ezio Melottiaa980582010-01-23 23:04:36 +000043 self.assertIn('known_attr', dir(self.f.a),
Georg Brandled4ca822009-09-04 11:19:34 +000044 "set attribute on unbound method implementation in "
45 "class not in dir")
Ezio Melottiaa980582010-01-23 23:04:36 +000046 self.assertIn('known_attr', dir(self.fi.a),
Georg Brandled4ca822009-09-04 11:19:34 +000047 "set attribute on unbound method implementations, "
48 "should show up in next dir")
Barry Warsaw4a420a02001-01-15 20:30:15 +000049
Georg Brandlc8088df2008-02-02 10:18:15 +000050 def test_duplicate_function_equality(self):
51 # Body of `duplicate' is the exact same as self.b
52 def duplicate():
53 'my docstring'
54 return 3
55 self.assertNotEqual(self.b, duplicate)
Barry Warsawc1e100f2001-02-26 18:07:26 +000056
Georg Brandlc8088df2008-02-02 10:18:15 +000057 def test_copying_func_code(self):
58 def test(): pass
59 self.assertEqual(test(), None)
60 test.func_code = self.b.func_code
61 self.assertEqual(test(), 3) # self.b always returns 3, arbitrarily
Barry Warsaw4a420a02001-01-15 20:30:15 +000062
Georg Brandlc8088df2008-02-02 10:18:15 +000063 def test_func_globals(self):
Georg Brandled4ca822009-09-04 11:19:34 +000064 self.assertIs(self.b.func_globals, globals())
Georg Brandl8ada1772008-02-05 18:32:47 +000065 self.cannot_set_attr(self.b, 'func_globals', 2, TypeError)
Barry Warsaw4a420a02001-01-15 20:30:15 +000066
Georg Brandled4ca822009-09-04 11:19:34 +000067 def test_func_closure(self):
68 a = 12
69 def f(): print a
70 c = f.func_closure
Ezio Melottib0f5adc2010-01-24 16:58:36 +000071 self.assertIsInstance(c, tuple)
Georg Brandled4ca822009-09-04 11:19:34 +000072 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)
76
77 def test_empty_cell(self):
78 def f(): print a
79 try:
80 f.func_closure[0].cell_contents
81 except ValueError:
82 pass
83 else:
84 self.fail("shouldn't be able to read an empty cell")
85 a = 12
86
Georg Brandlc8088df2008-02-02 10:18:15 +000087 def test_func_name(self):
88 self.assertEqual(self.b.__name__, 'b')
89 self.assertEqual(self.b.func_name, 'b')
90 self.b.__name__ = 'c'
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
Georg Brandl8ada1772008-02-05 18:32:47 +000097 self.cannot_set_attr(self.b, '__name__', 7, TypeError)
98 self.cannot_set_attr(self.b, 'func_name', 7, TypeError)
Georg Brandlc8088df2008-02-02 10:18:15 +000099 # __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')
Georg Brandl8ada1772008-02-05 18:32:47 +0000106 self.cannot_set_attr(self.f.a, "__name__", 'a', AttributeError)
107 self.cannot_set_attr(self.fi.a, "__name__", 'a', AttributeError)
Barry Warsaw4a420a02001-01-15 20:30:15 +0000108
Georg Brandlc8088df2008-02-02 10:18:15 +0000109 def test_func_code(self):
110 num_one, num_two = 7, 8
111 def a(): pass
112 def b(): return 12
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)
Georg Brandled4ca822009-09-04 11:19:34 +0000124 try:
125 b.func_code = c.func_code
126 except ValueError:
127 pass
128 else:
129 self.fail("func_code with different numbers of free vars should "
130 "not be possible")
131 try:
132 e.func_code = d.func_code
133 except ValueError:
134 pass
135 else:
136 self.fail("func_code with different numbers of free vars should "
137 "not be possible")
Barry Warsawc1e100f2001-02-26 18:07:26 +0000138
Georg Brandlc8088df2008-02-02 10:18:15 +0000139 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)
Barry Warsawc1e100f2001-02-26 18:07:26 +0000143
Georg Brandlc8088df2008-02-02 10:18:15 +0000144 def test_func_default_args(self):
145 def first_func(a, b):
146 return a+b
147 def second_func(a=1, b=2):
148 return a+b
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)
Georg Brandled4ca822009-09-04 11:19:34 +0000158 try:
159 second_func()
160 except TypeError:
161 pass
162 else:
163 self.fail("func_defaults does not update; deleting it does not "
164 "remove requirement")
Barry Warsawc1e100f2001-02-26 18:07:26 +0000165
Georg Brandled4ca822009-09-04 11:19:34 +0000166
167class InstancemethodAttrTest(FuncAttrsTest):
Georg Brandlc8088df2008-02-02 10:18:15 +0000168 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)
Georg Brandl8ada1772008-02-05 18:32:47 +0000171 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)
Barry Warsaw4a420a02001-01-15 20:30:15 +0000173
Georg Brandlc8088df2008-02-02 10:18:15 +0000174 def test_im_func(self):
175 self.f.b = self.b
176 self.assertEqual(self.f.b.im_func, self.b)
177 self.assertEqual(self.fi.b.im_func, self.b)
Georg Brandl8ada1772008-02-05 18:32:47 +0000178 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)
Barry Warsaw4a420a02001-01-15 20:30:15 +0000180
Georg Brandlc8088df2008-02-02 10:18:15 +0000181 def test_im_self(self):
182 self.assertEqual(self.f.a.im_self, None)
183 self.assertEqual(self.fi.a.im_self, self.fi)
Georg Brandl8ada1772008-02-05 18:32:47 +0000184 self.cannot_set_attr(self.f.a, "im_self", None, TypeError)
185 self.cannot_set_attr(self.fi.a, "im_self", self.fi, TypeError)
Barry Warsaw4a420a02001-01-15 20:30:15 +0000186
Georg Brandlc8088df2008-02-02 10:18:15 +0000187 def test_im_func_non_method(self):
188 # Behavior should be the same when a method is added via an attr
189 # assignment
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))
193 # Test usage
Georg Brandled4ca822009-09-04 11:19:34 +0000194 try:
195 self.f.id.unknown_attr
196 except AttributeError:
197 pass
198 else:
199 self.fail("using unknown attributes should raise AttributeError")
Georg Brandlc8088df2008-02-02 10:18:15 +0000200 # Test assignment and deletion
Georg Brandl8ada1772008-02-05 18:32:47 +0000201 self.cannot_set_attr(self.f.id, 'unknown_attr', 2, AttributeError)
202 self.cannot_set_attr(self.fi.id, 'unknown_attr', 2, AttributeError)
Barry Warsaw4a420a02001-01-15 20:30:15 +0000203
Georg Brandlc8088df2008-02-02 10:18:15 +0000204 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)
Barry Warsawc1e100f2001-02-26 18:07:26 +0000208
Georg Brandled4ca822009-09-04 11:19:34 +0000209
Georg Brandlc8088df2008-02-02 10:18:15 +0000210class ArbitraryFunctionAttrTest(FuncAttrsTest):
211 def test_set_attr(self):
Georg Brandled4ca822009-09-04 11:19:34 +0000212 # setting attributes only works on function objects
Georg Brandlc8088df2008-02-02 10:18:15 +0000213 self.b.known_attr = 7
214 self.assertEqual(self.b.known_attr, 7)
215 for func in [self.f.a, self.fi.a]:
Georg Brandled4ca822009-09-04 11:19:34 +0000216 try:
217 func.known_attr = 7
218 except AttributeError:
219 pass
220 else:
221 self.fail("setting attributes on methods should raise error")
Barry Warsaw4a420a02001-01-15 20:30:15 +0000222
Georg Brandlc8088df2008-02-02 10:18:15 +0000223 def test_delete_unknown_attr(self):
Georg Brandled4ca822009-09-04 11:19:34 +0000224 try:
225 del self.b.unknown_attr
226 except AttributeError:
227 pass
228 else:
229 self.fail("deleting unknown attribute should raise TypeError")
Barry Warsaw4a420a02001-01-15 20:30:15 +0000230
Georg Brandlc8088df2008-02-02 10:18:15 +0000231 def test_setting_attrs_duplicates(self):
Georg Brandled4ca822009-09-04 11:19:34 +0000232 try:
233 self.f.a.klass = self.f
234 except AttributeError:
235 pass
236 else:
237 self.fail("setting arbitrary attribute in unbound function "
238 " should raise AttributeError")
Georg Brandlc8088df2008-02-02 10:18:15 +0000239 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)
Barry Warsaw4a420a02001-01-15 20:30:15 +0000242
Georg Brandlc8088df2008-02-02 10:18:15 +0000243 def test_unset_attr(self):
244 for func in [self.b, self.f.a, self.fi.a]:
Georg Brandled4ca822009-09-04 11:19:34 +0000245 try:
246 func.non_existent_attr
247 except AttributeError:
248 pass
249 else:
250 self.fail("using unknown attributes should raise "
251 "AttributeError")
252
Barry Warsaw4a420a02001-01-15 20:30:15 +0000253
Georg Brandlc8088df2008-02-02 10:18:15 +0000254class FunctionDictsTest(FuncAttrsTest):
255 def test_setting_dict_to_invalid(self):
Georg Brandl8ada1772008-02-05 18:32:47 +0000256 self.cannot_set_attr(self.b, '__dict__', None, TypeError)
257 self.cannot_set_attr(self.b, 'func_dict', None, TypeError)
Georg Brandlc8088df2008-02-02 10:18:15 +0000258 from UserDict import UserDict
259 d = UserDict({'known_attr': 7})
Georg Brandl8ada1772008-02-05 18:32:47 +0000260 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)
Barry Warsaw4a420a02001-01-15 20:30:15 +0000262
Georg Brandlc8088df2008-02-02 10:18:15 +0000263 def test_setting_dict_to_valid(self):
264 d = {'known_attr': 7}
265 self.b.__dict__ = d
266 # Setting dict is only possible on the underlying function objects
267 self.f.a.im_func.__dict__ = d
268 # Test assignment
Georg Brandled4ca822009-09-04 11:19:34 +0000269 self.assertIs(d, self.b.__dict__)
270 self.assertIs(d, self.b.func_dict)
Georg Brandlc8088df2008-02-02 10:18:15 +0000271 # ... and on all the different ways of referencing the method's func
Georg Brandled4ca822009-09-04 11:19:34 +0000272 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__)
Georg Brandlc8088df2008-02-02 10:18:15 +0000276 # Test value
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)
Barry Warsawc1e100f2001-02-26 18:07:26 +0000285
Georg Brandlc8088df2008-02-02 10:18:15 +0000286 def test_delete_func_dict(self):
Georg Brandled4ca822009-09-04 11:19:34 +0000287 try:
288 del self.b.__dict__
289 except TypeError:
290 pass
291 else:
292 self.fail("deleting function dictionary should raise TypeError")
293 try:
294 del self.b.func_dict
295 except TypeError:
296 pass
297 else:
298 self.fail("deleting function dictionary should raise TypeError")
Barry Warsawc1e100f2001-02-26 18:07:26 +0000299
Georg Brandlc8088df2008-02-02 10:18:15 +0000300 def test_unassigned_dict(self):
301 self.assertEqual(self.b.__dict__, {})
Barry Warsaw4a420a02001-01-15 20:30:15 +0000302
Georg Brandlc8088df2008-02-02 10:18:15 +0000303 def test_func_as_dict_key(self):
304 value = "Some string"
305 d = {}
306 d[self.b] = value
307 self.assertEqual(d[self.b], value)
Barry Warsaw4a420a02001-01-15 20:30:15 +0000308
Georg Brandled4ca822009-09-04 11:19:34 +0000309
Georg Brandlc8088df2008-02-02 10:18:15 +0000310class 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)
Georg Brandl8ada1772008-02-05 18:32:47 +0000320 self.cannot_set_attr(self.f.a, "__doc__", docstr, AttributeError)
321 self.cannot_set_attr(self.fi.a, "__doc__", docstr, AttributeError)
Guido van Rossumbd131492001-09-18 03:28:54 +0000322
Georg Brandlc8088df2008-02-02 10:18:15 +0000323 def test_delete_docstring(self):
324 self.b.__doc__ = "The docstring"
325 del self.b.__doc__
326 self.assertEqual(self.b.__doc__, None)
327 self.assertEqual(self.b.func_doc, None)
328 self.b.func_doc = "The docstring"
329 del self.b.func_doc
330 self.assertEqual(self.b.__doc__, None)
331 self.assertEqual(self.b.func_doc, None)
Guido van Rossumd9d1d4a2001-09-17 23:46:56 +0000332
Georg Brandled4ca822009-09-04 11:19:34 +0000333
Raymond Hettinger578a2282009-05-29 04:58:52 +0000334class StaticMethodAttrsTest(unittest.TestCase):
335 def test_func_attribute(self):
336 def f():
337 pass
338
339 c = classmethod(f)
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000340 self.assertTrue(c.__func__ is f)
Raymond Hettinger578a2282009-05-29 04:58:52 +0000341
342 s = staticmethod(f)
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000343 self.assertTrue(s.__func__ is f)
Raymond Hettinger578a2282009-05-29 04:58:52 +0000344
345
Georg Brandlc8088df2008-02-02 10:18:15 +0000346def test_main():
Georg Brandled4ca822009-09-04 11:19:34 +0000347 test_support.run_unittest(FunctionPropertiesTest, InstancemethodAttrTest,
Georg Brandlc8088df2008-02-02 10:18:15 +0000348 ArbitraryFunctionAttrTest, FunctionDictsTest,
Raymond Hettinger578a2282009-05-29 04:58:52 +0000349 FunctionDocstringTest,
350 StaticMethodAttrsTest)
Guido van Rossumd9d1d4a2001-09-17 23:46:56 +0000351
Georg Brandlc8088df2008-02-02 10:18:15 +0000352if __name__ == "__main__":
353 test_main()