blob: 2411f6a63a284bbefa0596b4e1dc9e0a1802373c [file] [log] [blame]
Guido van Rossumd9d1d4a2001-09-17 23:46:56 +00001from test_support import verbose, TestFailed, verify
2import types
Barry Warsaw4a420a02001-01-15 20:30:15 +00003
4class F:
5 def a(self):
6 pass
7
8def b():
9 'my docstring'
10 pass
11
12# setting attributes on functions
13try:
14 b.publish
Barry Warsaw033daa42001-08-14 18:28:28 +000015except AttributeError: pass
16else: raise TestFailed, 'expected AttributeError'
Barry Warsaw4a420a02001-01-15 20:30:15 +000017
Barry Warsaw033daa42001-08-14 18:28:28 +000018if b.__dict__ <> {}:
19 raise TestFailed, 'expected unassigned func.__dict__ to be {}'
Barry Warsawc1e100f2001-02-26 18:07:26 +000020
Barry Warsaw4a420a02001-01-15 20:30:15 +000021b.publish = 1
22if b.publish <> 1:
23 raise TestFailed, 'function attribute not set to expected value'
24
25docstring = 'its docstring'
26b.__doc__ = docstring
27if b.__doc__ <> docstring:
28 raise TestFailed, 'problem with setting __doc__ attribute'
29
30if 'publish' not in dir(b):
31 raise TestFailed, 'attribute not in dir()'
32
Barry Warsaw033daa42001-08-14 18:28:28 +000033try:
34 del b.__dict__
Guido van Rossumdb2a9022001-09-18 03:55:22 +000035except TypeError: pass
Barry Warsaw033daa42001-08-14 18:28:28 +000036else: raise TestFailed, 'del func.__dict__ expected TypeError'
Barry Warsawc1e100f2001-02-26 18:07:26 +000037
38b.publish = 1
Barry Warsaw033daa42001-08-14 18:28:28 +000039try:
40 b.__dict__ = None
Guido van Rossumdb2a9022001-09-18 03:55:22 +000041except TypeError: pass
Barry Warsaw033daa42001-08-14 18:28:28 +000042else: raise TestFailed, 'func.__dict__ = None expected TypeError'
Barry Warsawc1e100f2001-02-26 18:07:26 +000043
Barry Warsaw033daa42001-08-14 18:28:28 +000044d = {'hello': 'world'}
45b.__dict__ = d
46if b.func_dict is not d:
47 raise TestFailed, 'func.__dict__ assignment to dictionary failed'
48if b.hello <> 'world':
49 raise TestFailed, 'attribute after func.__dict__ assignment failed'
Barry Warsawc1e100f2001-02-26 18:07:26 +000050
Barry Warsaw4a420a02001-01-15 20:30:15 +000051f1 = F()
52f2 = F()
53
54try:
55 F.a.publish
Barry Warsaw033daa42001-08-14 18:28:28 +000056except AttributeError: pass
57else: raise TestFailed, 'expected AttributeError'
Barry Warsaw4a420a02001-01-15 20:30:15 +000058
59try:
60 f1.a.publish
Barry Warsaw033daa42001-08-14 18:28:28 +000061except AttributeError: pass
62else: raise TestFailed, 'expected AttributeError'
Barry Warsaw4a420a02001-01-15 20:30:15 +000063
Barry Warsawc1e100f2001-02-26 18:07:26 +000064# In Python 2.1 beta 1, we disallowed setting attributes on unbound methods
65# (it was already disallowed on bound methods). See the PEP for details.
66try:
67 F.a.publish = 1
Guido van Rossumbd131492001-09-18 03:28:54 +000068except (AttributeError, TypeError): pass
69else: raise TestFailed, 'expected AttributeError or TypeError'
Barry Warsaw4a420a02001-01-15 20:30:15 +000070
Barry Warsawc1e100f2001-02-26 18:07:26 +000071# But setting it explicitly on the underlying function object is okay.
72F.a.im_func.publish = 1
73
Barry Warsaw4a420a02001-01-15 20:30:15 +000074if F.a.publish <> 1:
75 raise TestFailed, 'unbound method attribute not set to expected value'
76
77if f1.a.publish <> 1:
78 raise TestFailed, 'bound method attribute access did not work'
79
80if f2.a.publish <> 1:
81 raise TestFailed, 'bound method attribute access did not work'
82
83if 'publish' not in dir(F.a):
84 raise TestFailed, 'attribute not in dir()'
85
86try:
87 f1.a.publish = 0
Guido van Rossumbd131492001-09-18 03:28:54 +000088except (AttributeError, TypeError): pass
89else: raise TestFailed, 'expected AttributeError or TypeError'
Barry Warsaw4a420a02001-01-15 20:30:15 +000090
Barry Warsawc1e100f2001-02-26 18:07:26 +000091# See the comment above about the change in semantics for Python 2.1b1
92try:
93 F.a.myclass = F
Guido van Rossumbd131492001-09-18 03:28:54 +000094except (AttributeError, TypeError): pass
95else: raise TestFailed, 'expected AttributeError or TypeError'
Barry Warsawc1e100f2001-02-26 18:07:26 +000096
97F.a.im_func.myclass = F
98
Barry Warsaw4a420a02001-01-15 20:30:15 +000099f1.a.myclass
100f2.a.myclass
101f1.a.myclass
102F.a.myclass
103
104if f1.a.myclass is not f2.a.myclass or \
Barry Warsaw033daa42001-08-14 18:28:28 +0000105 f1.a.myclass is not F.a.myclass:
Barry Warsaw4a420a02001-01-15 20:30:15 +0000106 raise TestFailed, 'attributes were not the same'
107
108# try setting __dict__
109try:
110 F.a.__dict__ = (1, 2, 3)
Guido van Rossumdb2a9022001-09-18 03:55:22 +0000111except TypeError: pass
Barry Warsaw033daa42001-08-14 18:28:28 +0000112else: raise TestFailed, 'expected TypeError'
Barry Warsaw4a420a02001-01-15 20:30:15 +0000113
Barry Warsawc1e100f2001-02-26 18:07:26 +0000114F.a.im_func.__dict__ = {'one': 11, 'two': 22, 'three': 33}
115
Barry Warsaw4a420a02001-01-15 20:30:15 +0000116if f1.a.two <> 22:
117 raise TestFailed, 'setting __dict__'
118
119from UserDict import UserDict
120d = UserDict({'four': 44, 'five': 55})
121
122try:
123 F.a.__dict__ = d
Guido van Rossumdb2a9022001-09-18 03:55:22 +0000124except TypeError: pass
Barry Warsaw033daa42001-08-14 18:28:28 +0000125else: raise TestFailed
Barry Warsaw4a420a02001-01-15 20:30:15 +0000126
127if f2.a.one <> f1.a.one <> F.a.one <> 11:
128 raise TestFailed
Barry Warsaw534c60f2001-01-15 21:00:02 +0000129
130# im_func may not be a Python method!
131import new
132F.id = new.instancemethod(id, None, F)
133
134eff = F()
135if eff.id() <> id(eff):
136 raise TestFailed
137
138try:
139 F.id.foo
140except AttributeError: pass
141else: raise TestFailed
142
143try:
144 F.id.foo = 12
Guido van Rossumbd131492001-09-18 03:28:54 +0000145except (AttributeError, TypeError): pass
Barry Warsaw534c60f2001-01-15 21:00:02 +0000146else: raise TestFailed
147
148try:
149 F.id.foo
150except AttributeError: pass
151else: raise TestFailed
152
153try:
154 eff.id.foo
155except AttributeError: pass
156else: raise TestFailed
157
158try:
159 eff.id.foo = 12
Guido van Rossumbd131492001-09-18 03:28:54 +0000160except (AttributeError, TypeError): pass
Barry Warsaw534c60f2001-01-15 21:00:02 +0000161else: raise TestFailed
162
163try:
164 eff.id.foo
165except AttributeError: pass
166else: raise TestFailed
Barry Warsaw2e9b3962001-01-19 19:55:12 +0000167
168# Regression test for a crash in pre-2.1a1
169def another():
170 pass
Barry Warsaw033daa42001-08-14 18:28:28 +0000171
172try:
173 del another.__dict__
Guido van Rossumdb2a9022001-09-18 03:55:22 +0000174except TypeError: pass
Barry Warsaw033daa42001-08-14 18:28:28 +0000175else: raise TestFailed
176
177try:
178 del another.func_dict
Guido van Rossumdb2a9022001-09-18 03:55:22 +0000179except TypeError: pass
Barry Warsaw033daa42001-08-14 18:28:28 +0000180else: raise TestFailed
181
182try:
183 another.func_dict = None
Guido van Rossumdb2a9022001-09-18 03:55:22 +0000184except TypeError: pass
Barry Warsaw033daa42001-08-14 18:28:28 +0000185else: raise TestFailed
Barry Warsaw2e9b3962001-01-19 19:55:12 +0000186
187try:
188 del another.bar
189except AttributeError: pass
190else: raise TestFailed
191
192# This isn't specifically related to function attributes, but it does test a
193# core dump regression in funcobject.c
194del another.func_defaults
Moshe Zadka497671e2001-01-29 06:21:17 +0000195
196def foo():
Tim Peters10fb3862001-02-09 20:17:14 +0000197 pass
Moshe Zadka497671e2001-01-29 06:21:17 +0000198
199def bar():
Tim Peters10fb3862001-02-09 20:17:14 +0000200 pass
Moshe Zadka497671e2001-01-29 06:21:17 +0000201
202def temp():
Tim Peters10fb3862001-02-09 20:17:14 +0000203 print 1
Moshe Zadka497671e2001-01-29 06:21:17 +0000204
Barry Warsaw033daa42001-08-14 18:28:28 +0000205if foo==bar:
206 raise TestFailed
Moshe Zadka497671e2001-01-29 06:21:17 +0000207
208d={}
209d[foo] = 1
210
211foo.func_code = temp.func_code
212
213d[foo]
Guido van Rossumd9d1d4a2001-09-17 23:46:56 +0000214
215# Test all predefined function attributes systematically
216
Guido van Rossumbd131492001-09-18 03:28:54 +0000217def cantset(obj, name, value):
218 verify(hasattr(obj, name)) # Otherwise it's probably a typo
219 try:
220 setattr(obj, name, value)
Guido van Rossumdb2a9022001-09-18 03:55:22 +0000221 except TypeError:
Guido van Rossumbd131492001-09-18 03:28:54 +0000222 pass
223 else:
224 raise TestFailed, "shouldn't be able to set %s to %r" % (name, value)
225 try:
226 delattr(obj, name)
Guido van Rossumdb2a9022001-09-18 03:55:22 +0000227 except TypeError:
Guido van Rossumbd131492001-09-18 03:28:54 +0000228 pass
229 else:
230 raise TestFailed, "shouldn't be able to del %s" % name
231
Guido van Rossumd9d1d4a2001-09-17 23:46:56 +0000232def test_func_closure():
233 a = 12
234 def f(): print a
235 c = f.func_closure
236 verify(isinstance(c, tuple))
237 verify(len(c) == 1)
238 verify(c[0].__class__.__name__ == "cell") # don't have a type object handy
Guido van Rossumbd131492001-09-18 03:28:54 +0000239 cantset(f, "func_closure", c)
Guido van Rossumd9d1d4a2001-09-17 23:46:56 +0000240
241def test_func_doc():
242 def f(): pass
243 verify(f.__doc__ is None)
244 verify(f.func_doc is None)
245 f.__doc__ = "hello"
246 verify(f.__doc__ == "hello")
247 verify(f.func_doc == "hello")
248 del f.__doc__
249 verify(f.__doc__ is None)
250 verify(f.func_doc is None)
251 f.func_doc = "world"
252 verify(f.__doc__ == "world")
253 verify(f.func_doc == "world")
254 del f.func_doc
255 verify(f.func_doc is None)
256 verify(f.__doc__ is None)
257
258def test_func_globals():
259 def f(): pass
260 verify(f.func_globals is globals())
Guido van Rossumbd131492001-09-18 03:28:54 +0000261 cantset(f, "func_globals", globals())
Guido van Rossumd9d1d4a2001-09-17 23:46:56 +0000262
263def test_func_name():
264 def f(): pass
265 verify(f.__name__ == "f")
266 verify(f.func_name == "f")
Guido van Rossumbd131492001-09-18 03:28:54 +0000267 cantset(f, "func_name", "f")
268 cantset(f, "__name__", "f")
Guido van Rossumd9d1d4a2001-09-17 23:46:56 +0000269
270def test_func_code():
271 def f(): pass
272 def g(): print 12
273 verify(type(f.func_code) is types.CodeType)
274 f.func_code = g.func_code
Guido van Rossumbd131492001-09-18 03:28:54 +0000275 cantset(f, "func_code", None)
Guido van Rossumd9d1d4a2001-09-17 23:46:56 +0000276
277def test_func_defaults():
278 def f(a, b): return (a, b)
279 verify(f.func_defaults is None)
280 f.func_defaults = (1, 2)
281 verify(f.func_defaults == (1, 2))
282 verify(f(10) == (10, 2))
283 def g(a=1, b=2): return (a, b)
284 verify(g.func_defaults == (1, 2))
285 del g.func_defaults
286 verify(g.func_defaults is None)
287 try:
288 g()
289 except TypeError:
290 pass
291 else:
292 raise TestFailed, "shouldn't be allowed to call g() w/o defaults"
293
294def test_func_dict():
295 def f(): pass
296 a = f.__dict__
297 b = f.func_dict
298 verify(a == {})
299 verify(a is b)
300 f.hello = 'world'
301 verify(a == {'hello': 'world'})
302 verify(f.func_dict is a is f.__dict__)
303 f.func_dict = {}
Guido van Rossumbd131492001-09-18 03:28:54 +0000304 verify(not hasattr(f, "hello"))
Guido van Rossumd9d1d4a2001-09-17 23:46:56 +0000305 f.__dict__ = {'world': 'hello'}
306 verify(f.world == "hello")
307 verify(f.__dict__ is f.func_dict == {'world': 'hello'})
Guido van Rossumbd131492001-09-18 03:28:54 +0000308 cantset(f, "func_dict", None)
309 cantset(f, "__dict__", None)
310
311def test_im_class():
312 class C:
313 def foo(self): pass
314 verify(C.foo.im_class is C)
315 verify(C().foo.im_class is C)
316 cantset(C.foo, "im_class", C)
317 cantset(C().foo, "im_class", C)
318
319def test_im_func():
320 def foo(self): pass
321 class C:
Guido van Rossumd9d1d4a2001-09-17 23:46:56 +0000322 pass
Guido van Rossumbd131492001-09-18 03:28:54 +0000323 C.foo = foo
324 verify(C.foo.im_func is foo)
325 verify(C().foo.im_func is foo)
326 cantset(C.foo, "im_func", foo)
327 cantset(C().foo, "im_func", foo)
328
329def test_im_self():
330 class C:
331 def foo(self): pass
332 verify(C.foo.im_self is None)
333 c = C()
334 verify(c.foo.im_self is c)
335 cantset(C.foo, "im_self", None)
336 cantset(c.foo, "im_self", c)
337
338def test_im_dict():
339 class C:
340 def foo(self): pass
341 foo.bar = 42
342 verify(C.foo.__dict__ == {'bar': 42})
343 verify(C().foo.__dict__ == {'bar': 42})
344 cantset(C.foo, "__dict__", C.foo.__dict__)
345 cantset(C().foo, "__dict__", C.foo.__dict__)
346
347def test_im_doc():
348 class C:
349 def foo(self): "hello"
350 verify(C.foo.__doc__ == "hello")
351 verify(C().foo.__doc__ == "hello")
352 cantset(C.foo, "__doc__", "hello")
353 cantset(C().foo, "__doc__", "hello")
354
355def test_im_name():
356 class C:
357 def foo(self): pass
358 verify(C.foo.__name__ == "foo")
359 verify(C().foo.__name__ == "foo")
360 cantset(C.foo, "__name__", "foo")
361 cantset(C().foo, "__name__", "foo")
Guido van Rossumd9d1d4a2001-09-17 23:46:56 +0000362
363def testmore():
364 test_func_closure()
365 test_func_doc()
366 test_func_globals()
367 test_func_name()
368 test_func_code()
369 test_func_defaults()
370 test_func_dict()
Guido van Rossumbd131492001-09-18 03:28:54 +0000371 # Tests for instance method attributes
372 test_im_class()
373 test_im_func()
374 test_im_self()
375 test_im_dict()
376 test_im_doc()
377 test_im_name()
Guido van Rossumd9d1d4a2001-09-17 23:46:56 +0000378
379testmore()