blob: 21ef432b0adab7745aca55075ce945a765d8afe2 [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 +00005def cannot_set_attr(obj, name, value, exceptions):
6 # This method is not called as a test (name doesn't start with 'test'),
7 # but may be used by other tests.
8 try: setattr(obj, name, value)
9 except exceptions: pass
10 else: self.fail("shouldn't be able to set %s to %r" % (name, value))
11 try: delattr(obj, name)
12 except exceptions: pass
13 else: self.fail("shouldn't be able to del %s" % name)
Barry Warsaw4a420a02001-01-15 20:30:15 +000014
Georg Brandlc8088df2008-02-02 10:18:15 +000015class FuncAttrsTest(unittest.TestCase):
16 def setUp(self):
17 class F:
18 def a(self):
19 pass
20 def b():
21 return 3
22 self.f = F
23 self.fi = F()
24 self.b = b
Barry Warsaw4a420a02001-01-15 20:30:15 +000025
Georg Brandlc8088df2008-02-02 10:18:15 +000026class FunctionPropertiesTest(FuncAttrsTest):
27 # Include the external setUp method that is common to all tests
28 def test_module(self):
29 self.assertEqual(self.b.__module__, __name__)
Jeremy Hylton4f0dcc92003-01-31 18:33:18 +000030
Georg Brandlc8088df2008-02-02 10:18:15 +000031 def test_dir_includes_correct_attrs(self):
32 self.b.known_attr = 7
33 self.assert_('known_attr' in dir(self.b),
34 "set attributes not in dir listing of method")
35 # Test on underlying function object of method
36 self.f.a.im_func.known_attr = 7
37 self.assert_('known_attr' in dir(self.f.a),
38 "set attribute on unbound method implementation in class not in "
39 "dir")
40 self.assert_('known_attr' in dir(self.fi.a),
41 "set attribute on unbound method implementations, should show up"
42 " in next dir")
Barry Warsaw4a420a02001-01-15 20:30:15 +000043
Georg Brandlc8088df2008-02-02 10:18:15 +000044 def test_duplicate_function_equality(self):
45 # Body of `duplicate' is the exact same as self.b
46 def duplicate():
47 'my docstring'
48 return 3
49 self.assertNotEqual(self.b, duplicate)
Barry Warsawc1e100f2001-02-26 18:07:26 +000050
Georg Brandlc8088df2008-02-02 10:18:15 +000051 def test_copying_func_code(self):
52 def test(): pass
53 self.assertEqual(test(), None)
54 test.func_code = self.b.func_code
55 self.assertEqual(test(), 3) # self.b always returns 3, arbitrarily
Barry Warsaw4a420a02001-01-15 20:30:15 +000056
Georg Brandlc8088df2008-02-02 10:18:15 +000057 def test_func_globals(self):
58 self.assertEqual(self.b.func_globals, globals())
59 cannot_set_attr(self.b, 'func_globals', 2, TypeError)
Barry Warsaw4a420a02001-01-15 20:30:15 +000060
Georg Brandlc8088df2008-02-02 10:18:15 +000061 def test_func_name(self):
62 self.assertEqual(self.b.__name__, 'b')
63 self.assertEqual(self.b.func_name, 'b')
64 self.b.__name__ = 'c'
65 self.assertEqual(self.b.__name__, 'c')
66 self.assertEqual(self.b.func_name, 'c')
67 self.b.func_name = 'd'
68 self.assertEqual(self.b.__name__, 'd')
69 self.assertEqual(self.b.func_name, 'd')
70 # __name__ and func_name must be a string
71 cannot_set_attr(self.b, '__name__', 7, TypeError)
72 cannot_set_attr(self.b, 'func_name', 7, TypeError)
73 # __name__ must be available when in restricted mode. Exec will raise
74 # AttributeError if __name__ is not available on f.
75 s = """def f(): pass\nf.__name__"""
76 exec s in {'__builtins__': {}}
77 # Test on methods, too
78 self.assertEqual(self.f.a.__name__, 'a')
79 self.assertEqual(self.fi.a.__name__, 'a')
80 cannot_set_attr(self.f.a, "__name__", 'a', AttributeError)
81 cannot_set_attr(self.fi.a, "__name__", 'a', AttributeError)
Barry Warsaw4a420a02001-01-15 20:30:15 +000082
Georg Brandlc8088df2008-02-02 10:18:15 +000083 def test_func_code(self):
84 num_one, num_two = 7, 8
85 def a(): pass
86 def b(): return 12
87 def c(): return num_one
88 def d(): return num_two
89 def e(): return num_one, num_two
90 for func in [a, b, c, d, e]:
91 self.assertEqual(type(func.func_code), types.CodeType)
92 self.assertEqual(c(), 7)
93 self.assertEqual(d(), 8)
94 d.func_code = c.func_code
95 self.assertEqual(c.func_code, d.func_code)
96 self.assertEqual(c(), 7)
97 # self.assertEqual(d(), 7)
98 try: b.func_code = c.func_code
99 except ValueError: pass
100 else: self.fail(
101 "func_code with different numbers of free vars should not be "
102 "possible")
103 try: e.func_code = d.func_code
104 except ValueError: pass
105 else: self.fail(
106 "func_code with different numbers of free vars should not be "
107 "possible")
Barry Warsawc1e100f2001-02-26 18:07:26 +0000108
Georg Brandlc8088df2008-02-02 10:18:15 +0000109 def test_blank_func_defaults(self):
110 self.assertEqual(self.b.func_defaults, None)
111 del self.b.func_defaults
112 self.assertEqual(self.b.func_defaults, None)
Barry Warsawc1e100f2001-02-26 18:07:26 +0000113
Georg Brandlc8088df2008-02-02 10:18:15 +0000114 def test_func_default_args(self):
115 def first_func(a, b):
116 return a+b
117 def second_func(a=1, b=2):
118 return a+b
119 self.assertEqual(first_func.func_defaults, None)
120 self.assertEqual(second_func.func_defaults, (1, 2))
121 first_func.func_defaults = (1, 2)
122 self.assertEqual(first_func.func_defaults, (1, 2))
123 self.assertEqual(first_func(), 3)
124 self.assertEqual(first_func(3), 5)
125 self.assertEqual(first_func(3, 5), 8)
126 del second_func.func_defaults
127 self.assertEqual(second_func.func_defaults, None)
128 try: second_func()
129 except TypeError: pass
130 else: self.fail(
131 "func_defaults does not update; deleting it does not remove "
132 "requirement")
Barry Warsawc1e100f2001-02-26 18:07:26 +0000133
Georg Brandlc8088df2008-02-02 10:18:15 +0000134class ImplicitReferencesTest(FuncAttrsTest):
135 def test_im_class(self):
136 self.assertEqual(self.f.a.im_class, self.f)
137 self.assertEqual(self.fi.a.im_class, self.f)
138 cannot_set_attr(self.f.a, "im_class", self.f, TypeError)
139 cannot_set_attr(self.fi.a, "im_class", self.f, TypeError)
Barry Warsaw4a420a02001-01-15 20:30:15 +0000140
Georg Brandlc8088df2008-02-02 10:18:15 +0000141 def test_im_func(self):
142 self.f.b = self.b
143 self.assertEqual(self.f.b.im_func, self.b)
144 self.assertEqual(self.fi.b.im_func, self.b)
145 cannot_set_attr(self.f.b, "im_func", self.b, TypeError)
146 cannot_set_attr(self.fi.b, "im_func", self.b, TypeError)
Barry Warsaw4a420a02001-01-15 20:30:15 +0000147
Georg Brandlc8088df2008-02-02 10:18:15 +0000148 def test_im_self(self):
149 self.assertEqual(self.f.a.im_self, None)
150 self.assertEqual(self.fi.a.im_self, self.fi)
151 cannot_set_attr(self.f.a, "im_self", None, TypeError)
152 cannot_set_attr(self.fi.a, "im_self", self.fi, TypeError)
Barry Warsaw4a420a02001-01-15 20:30:15 +0000153
Georg Brandlc8088df2008-02-02 10:18:15 +0000154 def test_im_func_non_method(self):
155 # Behavior should be the same when a method is added via an attr
156 # assignment
157 self.f.id = types.MethodType(id, None, self.f)
158 self.assertEqual(self.fi.id(), id(self.fi))
159 self.assertNotEqual(self.fi.id(), id(self.f))
160 # Test usage
161 try: self.f.id.unknown_attr
162 except AttributeError: pass
163 else: self.fail("using unknown attributes should raise AttributeError")
164 # Test assignment and deletion
165 cannot_set_attr(self.f.id, 'unknown_attr', 2, AttributeError)
166 cannot_set_attr(self.fi.id, 'unknown_attr', 2, AttributeError)
Barry Warsaw4a420a02001-01-15 20:30:15 +0000167
Georg Brandlc8088df2008-02-02 10:18:15 +0000168 def test_implicit_method_properties(self):
169 self.f.a.im_func.known_attr = 7
170 self.assertEqual(self.f.a.known_attr, 7)
171 self.assertEqual(self.fi.a.known_attr, 7)
Barry Warsawc1e100f2001-02-26 18:07:26 +0000172
Georg Brandlc8088df2008-02-02 10:18:15 +0000173class ArbitraryFunctionAttrTest(FuncAttrsTest):
174 def test_set_attr(self):
175 self.b.known_attr = 7
176 self.assertEqual(self.b.known_attr, 7)
177 for func in [self.f.a, self.fi.a]:
178 try: func.known_attr = 7
179 except AttributeError: pass
180 else: self.fail("setting attributes on methods should raise error")
Barry Warsaw4a420a02001-01-15 20:30:15 +0000181
Georg Brandlc8088df2008-02-02 10:18:15 +0000182 def test_delete_unknown_attr(self):
183 try: del self.b.unknown_attr
184 except AttributeError: pass
185 else: self.fail("deleting unknown attribute should raise TypeError")
Barry Warsaw4a420a02001-01-15 20:30:15 +0000186
Georg Brandlc8088df2008-02-02 10:18:15 +0000187 def test_setting_attrs_duplicates(self):
188 try: self.f.a.klass = self.f
189 except AttributeError: pass
190 else: self.fail("setting arbitrary attribute in unbound function "
191 " should raise AttributeError")
192 self.f.a.im_func.klass = self.f
193 for method in [self.f.a, self.fi.a, self.fi.a.im_func]:
194 self.assertEqual(method.klass, self.f)
Barry Warsaw4a420a02001-01-15 20:30:15 +0000195
Georg Brandlc8088df2008-02-02 10:18:15 +0000196 def test_unset_attr(self):
197 for func in [self.b, self.f.a, self.fi.a]:
198 try: func.non_existant_attr
199 except AttributeError: pass
200 else: self.fail("using unknown attributes should raise "
201 "AttributeError")
Barry Warsaw4a420a02001-01-15 20:30:15 +0000202
Georg Brandlc8088df2008-02-02 10:18:15 +0000203class FunctionDictsTest(FuncAttrsTest):
204 def test_setting_dict_to_invalid(self):
205 cannot_set_attr(self.b, '__dict__', None, TypeError)
206 cannot_set_attr(self.b, 'func_dict', None, TypeError)
207 from UserDict import UserDict
208 d = UserDict({'known_attr': 7})
209 cannot_set_attr(self.f.a.im_func, '__dict__', d, TypeError)
210 cannot_set_attr(self.fi.a.im_func, '__dict__', d, TypeError)
Barry Warsaw4a420a02001-01-15 20:30:15 +0000211
Georg Brandlc8088df2008-02-02 10:18:15 +0000212 def test_setting_dict_to_valid(self):
213 d = {'known_attr': 7}
214 self.b.__dict__ = d
215 # Setting dict is only possible on the underlying function objects
216 self.f.a.im_func.__dict__ = d
217 # Test assignment
218 self.assertEqual(d, self.b.__dict__)
219 self.assertEqual(d, self.b.func_dict)
220 # ... and on all the different ways of referencing the method's func
221 self.assertEqual(d, self.f.a.im_func.__dict__)
222 self.assertEqual(d, self.f.a.__dict__)
223 self.assertEqual(d, self.fi.a.im_func.__dict__)
224 self.assertEqual(d, self.fi.a.__dict__)
225 # Test value
226 self.assertEqual(self.b.known_attr, 7)
227 self.assertEqual(self.b.__dict__['known_attr'], 7)
228 self.assertEqual(self.b.func_dict['known_attr'], 7)
229 # ... and again, on all the different method's names
230 self.assertEqual(self.f.a.im_func.known_attr, 7)
231 self.assertEqual(self.f.a.known_attr, 7)
232 self.assertEqual(self.fi.a.im_func.known_attr, 7)
233 self.assertEqual(self.fi.a.known_attr, 7)
Barry Warsawc1e100f2001-02-26 18:07:26 +0000234
Georg Brandlc8088df2008-02-02 10:18:15 +0000235 def test_delete_func_dict(self):
236 try: del self.b.__dict__
237 except TypeError: pass
238 else: self.fail("deleting function dictionary should raise TypeError")
239 try: del self.b.func_dict
240 except TypeError: pass
241 else: self.fail("deleting function dictionary should raise TypeError")
Barry Warsawc1e100f2001-02-26 18:07:26 +0000242
Georg Brandlc8088df2008-02-02 10:18:15 +0000243 def test_unassigned_dict(self):
244 self.assertEqual(self.b.__dict__, {})
Barry Warsaw4a420a02001-01-15 20:30:15 +0000245
Georg Brandlc8088df2008-02-02 10:18:15 +0000246 def test_func_as_dict_key(self):
247 value = "Some string"
248 d = {}
249 d[self.b] = value
250 self.assertEqual(d[self.b], value)
Barry Warsaw4a420a02001-01-15 20:30:15 +0000251
Georg Brandlc8088df2008-02-02 10:18:15 +0000252class FunctionDocstringTest(FuncAttrsTest):
253 def test_set_docstring_attr(self):
254 self.assertEqual(self.b.__doc__, None)
255 self.assertEqual(self.b.func_doc, None)
256 docstr = "A test method that does nothing"
257 self.b.__doc__ = self.f.a.im_func.__doc__ = docstr
258 self.assertEqual(self.b.__doc__, docstr)
259 self.assertEqual(self.b.func_doc, docstr)
260 self.assertEqual(self.f.a.__doc__, docstr)
261 self.assertEqual(self.fi.a.__doc__, docstr)
262 cannot_set_attr(self.f.a, "__doc__", docstr, AttributeError)
263 cannot_set_attr(self.fi.a, "__doc__", docstr, AttributeError)
Guido van Rossumbd131492001-09-18 03:28:54 +0000264
Georg Brandlc8088df2008-02-02 10:18:15 +0000265 def test_delete_docstring(self):
266 self.b.__doc__ = "The docstring"
267 del self.b.__doc__
268 self.assertEqual(self.b.__doc__, None)
269 self.assertEqual(self.b.func_doc, None)
270 self.b.func_doc = "The docstring"
271 del self.b.func_doc
272 self.assertEqual(self.b.__doc__, None)
273 self.assertEqual(self.b.func_doc, None)
Guido van Rossumd9d1d4a2001-09-17 23:46:56 +0000274
Georg Brandlc8088df2008-02-02 10:18:15 +0000275def test_main():
276 test_support.run_unittest(FunctionPropertiesTest, ImplicitReferencesTest,
277 ArbitraryFunctionAttrTest, FunctionDictsTest,
278 FunctionDocstringTest)
Guido van Rossumd9d1d4a2001-09-17 23:46:56 +0000279
Georg Brandlc8088df2008-02-02 10:18:15 +0000280if __name__ == "__main__":
281 test_main()