blob: 528ca18ad76b96cb6a1d04547a771ca052dc38ca [file] [log] [blame]
Barry Warsaw408b6d32002-07-30 23:27:12 +00001from test.test_support import verbose, TestFailed, verify
Guido van Rossumd9d1d4a2001-09-17 23:46:56 +00002import 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
Jeremy Hylton4f0dcc92003-01-31 18:33:18 +000012# __module__ is a special attribute
13verify(b.__module__ == __name__)
14verify(verify.__module__ == "test.test_support")
15
Barry Warsaw4a420a02001-01-15 20:30:15 +000016# setting attributes on functions
17try:
18 b.publish
Barry Warsaw033daa42001-08-14 18:28:28 +000019except AttributeError: pass
20else: raise TestFailed, 'expected AttributeError'
Barry Warsaw4a420a02001-01-15 20:30:15 +000021
Guido van Rossumb053cd82006-08-24 03:53:23 +000022if b.__dict__ != {}:
Barry Warsaw033daa42001-08-14 18:28:28 +000023 raise TestFailed, 'expected unassigned func.__dict__ to be {}'
Barry Warsawc1e100f2001-02-26 18:07:26 +000024
Barry Warsaw4a420a02001-01-15 20:30:15 +000025b.publish = 1
Guido van Rossumb053cd82006-08-24 03:53:23 +000026if b.publish != 1:
Barry Warsaw4a420a02001-01-15 20:30:15 +000027 raise TestFailed, 'function attribute not set to expected value'
28
29docstring = 'its docstring'
30b.__doc__ = docstring
Guido van Rossumb053cd82006-08-24 03:53:23 +000031if b.__doc__ != docstring:
Barry Warsaw4a420a02001-01-15 20:30:15 +000032 raise TestFailed, 'problem with setting __doc__ attribute'
33
34if 'publish' not in dir(b):
35 raise TestFailed, 'attribute not in dir()'
36
Barry Warsaw033daa42001-08-14 18:28:28 +000037try:
38 del b.__dict__
Guido van Rossumdb2a9022001-09-18 03:55:22 +000039except TypeError: pass
Barry Warsaw033daa42001-08-14 18:28:28 +000040else: raise TestFailed, 'del func.__dict__ expected TypeError'
Barry Warsawc1e100f2001-02-26 18:07:26 +000041
42b.publish = 1
Barry Warsaw033daa42001-08-14 18:28:28 +000043try:
44 b.__dict__ = None
Guido van Rossumdb2a9022001-09-18 03:55:22 +000045except TypeError: pass
Barry Warsaw033daa42001-08-14 18:28:28 +000046else: raise TestFailed, 'func.__dict__ = None expected TypeError'
Barry Warsawc1e100f2001-02-26 18:07:26 +000047
Barry Warsaw033daa42001-08-14 18:28:28 +000048d = {'hello': 'world'}
49b.__dict__ = d
Neal Norwitz221085d2007-02-25 20:55:47 +000050if b.__dict__ is not d:
Barry Warsaw033daa42001-08-14 18:28:28 +000051 raise TestFailed, 'func.__dict__ assignment to dictionary failed'
Guido van Rossumb053cd82006-08-24 03:53:23 +000052if b.hello != 'world':
Barry Warsaw033daa42001-08-14 18:28:28 +000053 raise TestFailed, 'attribute after func.__dict__ assignment failed'
Barry Warsawc1e100f2001-02-26 18:07:26 +000054
Barry Warsaw4a420a02001-01-15 20:30:15 +000055f1 = F()
56f2 = F()
57
58try:
59 F.a.publish
Barry Warsaw033daa42001-08-14 18:28:28 +000060except AttributeError: pass
61else: raise TestFailed, 'expected AttributeError'
Barry Warsaw4a420a02001-01-15 20:30:15 +000062
63try:
64 f1.a.publish
Barry Warsaw033daa42001-08-14 18:28:28 +000065except AttributeError: pass
66else: raise TestFailed, 'expected AttributeError'
Barry Warsaw4a420a02001-01-15 20:30:15 +000067
Barry Warsawc1e100f2001-02-26 18:07:26 +000068# In Python 2.1 beta 1, we disallowed setting attributes on unbound methods
69# (it was already disallowed on bound methods). See the PEP for details.
70try:
71 F.a.publish = 1
Guido van Rossumbd131492001-09-18 03:28:54 +000072except (AttributeError, TypeError): pass
73else: raise TestFailed, 'expected AttributeError or TypeError'
Barry Warsaw4a420a02001-01-15 20:30:15 +000074
Barry Warsawc1e100f2001-02-26 18:07:26 +000075# But setting it explicitly on the underlying function object is okay.
76F.a.im_func.publish = 1
77
Guido van Rossumb053cd82006-08-24 03:53:23 +000078if F.a.publish != 1:
Barry Warsaw4a420a02001-01-15 20:30:15 +000079 raise TestFailed, 'unbound method attribute not set to expected value'
80
Guido van Rossumb053cd82006-08-24 03:53:23 +000081if f1.a.publish != 1:
Barry Warsaw4a420a02001-01-15 20:30:15 +000082 raise TestFailed, 'bound method attribute access did not work'
83
Guido van Rossumb053cd82006-08-24 03:53:23 +000084if f2.a.publish != 1:
Barry Warsaw4a420a02001-01-15 20:30:15 +000085 raise TestFailed, 'bound method attribute access did not work'
86
87if 'publish' not in dir(F.a):
88 raise TestFailed, 'attribute not in dir()'
89
90try:
91 f1.a.publish = 0
Guido van Rossumbd131492001-09-18 03:28:54 +000092except (AttributeError, TypeError): pass
93else: raise TestFailed, 'expected AttributeError or TypeError'
Barry Warsaw4a420a02001-01-15 20:30:15 +000094
Barry Warsawc1e100f2001-02-26 18:07:26 +000095# See the comment above about the change in semantics for Python 2.1b1
96try:
97 F.a.myclass = F
Guido van Rossumbd131492001-09-18 03:28:54 +000098except (AttributeError, TypeError): pass
99else: raise TestFailed, 'expected AttributeError or TypeError'
Barry Warsawc1e100f2001-02-26 18:07:26 +0000100
101F.a.im_func.myclass = F
102
Barry Warsaw4a420a02001-01-15 20:30:15 +0000103f1.a.myclass
104f2.a.myclass
105f1.a.myclass
106F.a.myclass
107
108if f1.a.myclass is not f2.a.myclass or \
Barry Warsaw033daa42001-08-14 18:28:28 +0000109 f1.a.myclass is not F.a.myclass:
Barry Warsaw4a420a02001-01-15 20:30:15 +0000110 raise TestFailed, 'attributes were not the same'
111
112# try setting __dict__
113try:
114 F.a.__dict__ = (1, 2, 3)
Guido van Rossum56ff3872001-10-22 02:00:09 +0000115except (AttributeError, TypeError): pass
116else: raise TestFailed, 'expected TypeError or AttributeError'
Barry Warsaw4a420a02001-01-15 20:30:15 +0000117
Barry Warsawc1e100f2001-02-26 18:07:26 +0000118F.a.im_func.__dict__ = {'one': 11, 'two': 22, 'three': 33}
119
Guido van Rossumb053cd82006-08-24 03:53:23 +0000120if f1.a.two != 22:
Barry Warsaw4a420a02001-01-15 20:30:15 +0000121 raise TestFailed, 'setting __dict__'
122
123from UserDict import UserDict
124d = UserDict({'four': 44, 'five': 55})
125
126try:
127 F.a.__dict__ = d
Guido van Rossum56ff3872001-10-22 02:00:09 +0000128except (AttributeError, TypeError): pass
Barry Warsaw033daa42001-08-14 18:28:28 +0000129else: raise TestFailed
Barry Warsaw4a420a02001-01-15 20:30:15 +0000130
Guido van Rossumb053cd82006-08-24 03:53:23 +0000131if f2.a.one != f1.a.one != F.a.one != 11:
Barry Warsaw4a420a02001-01-15 20:30:15 +0000132 raise TestFailed
Barry Warsaw534c60f2001-01-15 21:00:02 +0000133
134# im_func may not be a Python method!
135import new
136F.id = new.instancemethod(id, None, F)
137
138eff = F()
Guido van Rossumb053cd82006-08-24 03:53:23 +0000139if eff.id() != id(eff):
Barry Warsaw534c60f2001-01-15 21:00:02 +0000140 raise TestFailed
141
142try:
143 F.id.foo
144except AttributeError: pass
145else: raise TestFailed
146
147try:
148 F.id.foo = 12
Guido van Rossumbd131492001-09-18 03:28:54 +0000149except (AttributeError, TypeError): pass
Barry Warsaw534c60f2001-01-15 21:00:02 +0000150else: raise TestFailed
151
152try:
153 F.id.foo
154except AttributeError: pass
155else: raise TestFailed
156
157try:
158 eff.id.foo
159except AttributeError: pass
160else: raise TestFailed
161
162try:
163 eff.id.foo = 12
Guido van Rossumbd131492001-09-18 03:28:54 +0000164except (AttributeError, TypeError): pass
Barry Warsaw534c60f2001-01-15 21:00:02 +0000165else: raise TestFailed
166
167try:
168 eff.id.foo
169except AttributeError: pass
170else: raise TestFailed
Barry Warsaw2e9b3962001-01-19 19:55:12 +0000171
172# Regression test for a crash in pre-2.1a1
173def another():
174 pass
Barry Warsaw033daa42001-08-14 18:28:28 +0000175
176try:
177 del another.__dict__
Guido van Rossumdb2a9022001-09-18 03:55:22 +0000178except TypeError: pass
Barry Warsaw033daa42001-08-14 18:28:28 +0000179else: raise TestFailed
180
181try:
Neal Norwitz221085d2007-02-25 20:55:47 +0000182 del another.__dict__
Guido van Rossumdb2a9022001-09-18 03:55:22 +0000183except TypeError: pass
Barry Warsaw033daa42001-08-14 18:28:28 +0000184else: raise TestFailed
185
186try:
Neal Norwitz221085d2007-02-25 20:55:47 +0000187 another.__dict__ = None
Guido van Rossumdb2a9022001-09-18 03:55:22 +0000188except TypeError: pass
Barry Warsaw033daa42001-08-14 18:28:28 +0000189else: raise TestFailed
Barry Warsaw2e9b3962001-01-19 19:55:12 +0000190
191try:
192 del another.bar
193except AttributeError: pass
194else: raise TestFailed
195
196# This isn't specifically related to function attributes, but it does test a
197# core dump regression in funcobject.c
Neal Norwitz221085d2007-02-25 20:55:47 +0000198del another.__defaults__
Moshe Zadka497671e2001-01-29 06:21:17 +0000199
200def foo():
Tim Peters10fb3862001-02-09 20:17:14 +0000201 pass
Moshe Zadka497671e2001-01-29 06:21:17 +0000202
203def bar():
Tim Peters10fb3862001-02-09 20:17:14 +0000204 pass
Moshe Zadka497671e2001-01-29 06:21:17 +0000205
206def temp():
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000207 print(1)
Moshe Zadka497671e2001-01-29 06:21:17 +0000208
Barry Warsaw033daa42001-08-14 18:28:28 +0000209if foo==bar:
210 raise TestFailed
Moshe Zadka497671e2001-01-29 06:21:17 +0000211
212d={}
213d[foo] = 1
214
Neal Norwitz221085d2007-02-25 20:55:47 +0000215foo.__code__ = temp.__code__
Moshe Zadka497671e2001-01-29 06:21:17 +0000216
217d[foo]
Guido van Rossumd9d1d4a2001-09-17 23:46:56 +0000218
219# Test all predefined function attributes systematically
220
Armin Rigo89a39462004-10-28 16:32:00 +0000221def cantset(obj, name, value, exception=(AttributeError, TypeError)):
Guido van Rossumbd131492001-09-18 03:28:54 +0000222 verify(hasattr(obj, name)) # Otherwise it's probably a typo
223 try:
224 setattr(obj, name, value)
Armin Rigo89a39462004-10-28 16:32:00 +0000225 except exception:
Guido van Rossumbd131492001-09-18 03:28:54 +0000226 pass
227 else:
228 raise TestFailed, "shouldn't be able to set %s to %r" % (name, value)
229 try:
230 delattr(obj, name)
Guido van Rossum56ff3872001-10-22 02:00:09 +0000231 except (AttributeError, TypeError):
Guido van Rossumbd131492001-09-18 03:28:54 +0000232 pass
233 else:
234 raise TestFailed, "shouldn't be able to del %s" % name
235
Guido van Rossumd9d1d4a2001-09-17 23:46:56 +0000236def test_func_closure():
237 a = 12
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000238 def f(): print(a)
Neal Norwitz221085d2007-02-25 20:55:47 +0000239 c = f.__closure__
Guido van Rossumd9d1d4a2001-09-17 23:46:56 +0000240 verify(isinstance(c, tuple))
241 verify(len(c) == 1)
242 verify(c[0].__class__.__name__ == "cell") # don't have a type object handy
Neal Norwitz221085d2007-02-25 20:55:47 +0000243 cantset(f, "__closure__", c)
Guido van Rossumd9d1d4a2001-09-17 23:46:56 +0000244
245def test_func_doc():
246 def f(): pass
247 verify(f.__doc__ is None)
Guido van Rossumd9d1d4a2001-09-17 23:46:56 +0000248 f.__doc__ = "hello"
249 verify(f.__doc__ == "hello")
Guido van Rossumd9d1d4a2001-09-17 23:46:56 +0000250 del f.__doc__
251 verify(f.__doc__ is None)
Guido van Rossumd9d1d4a2001-09-17 23:46:56 +0000252
253def test_func_globals():
254 def f(): pass
Neal Norwitz221085d2007-02-25 20:55:47 +0000255 verify(f.__globals__ is globals())
256 cantset(f, "__globals__", globals())
Guido van Rossumd9d1d4a2001-09-17 23:46:56 +0000257
258def test_func_name():
259 def f(): pass
260 verify(f.__name__ == "f")
Michael W. Hudson5e897952004-08-12 18:12:44 +0000261 f.__name__ = "g"
262 verify(f.__name__ == "g")
Neal Norwitz221085d2007-02-25 20:55:47 +0000263 cantset(f, "__globals__", 1)
Michael W. Hudson5e897952004-08-12 18:12:44 +0000264 cantset(f, "__name__", 1)
Michael W. Hudsonee319f62005-02-17 10:37:21 +0000265 # test that you can access func.__name__ in restricted mode
266 s = """def f(): pass\nf.__name__"""
Georg Brandl7cae87c2006-09-06 06:51:57 +0000267 exec(s, {'__builtins__':{}})
Tim Petersbf9ac4b2004-08-13 03:57:22 +0000268
Guido van Rossumd9d1d4a2001-09-17 23:46:56 +0000269
270def test_func_code():
Armin Rigo89a39462004-10-28 16:32:00 +0000271 a = b = 24
Guido van Rossumd9d1d4a2001-09-17 23:46:56 +0000272 def f(): pass
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000273 def g(): print(12)
274 def f1(): print(a)
275 def g1(): print(b)
276 def f2(): print(a, b)
Neal Norwitz221085d2007-02-25 20:55:47 +0000277 verify(type(f.__code__) is types.CodeType)
278 f.__code__ = g.__code__
279 cantset(f, "__code__", None)
Armin Rigo89a39462004-10-28 16:32:00 +0000280 # can't change the number of free vars
Neal Norwitz221085d2007-02-25 20:55:47 +0000281 cantset(f, "__code__", f1.__code__, exception=ValueError)
282 cantset(f1, "__code__", f.__code__, exception=ValueError)
283 cantset(f1, "__code__", f2.__code__, exception=ValueError)
284 f1.__code__ = g1.__code__
Guido van Rossumd9d1d4a2001-09-17 23:46:56 +0000285
286def test_func_defaults():
287 def f(a, b): return (a, b)
Neal Norwitz221085d2007-02-25 20:55:47 +0000288 verify(f.__defaults__ is None)
289 f.__defaults__ = (1, 2)
290 verify(f.__defaults__ == (1, 2))
Guido van Rossumd9d1d4a2001-09-17 23:46:56 +0000291 verify(f(10) == (10, 2))
292 def g(a=1, b=2): return (a, b)
Neal Norwitz221085d2007-02-25 20:55:47 +0000293 verify(g.__defaults__ == (1, 2))
294 del g.__defaults__
295 verify(g.__defaults__ is None)
Guido van Rossumd9d1d4a2001-09-17 23:46:56 +0000296 try:
297 g()
298 except TypeError:
299 pass
300 else:
301 raise TestFailed, "shouldn't be allowed to call g() w/o defaults"
302
303def test_func_dict():
304 def f(): pass
305 a = f.__dict__
Guido van Rossumd9d1d4a2001-09-17 23:46:56 +0000306 verify(a == {})
Guido van Rossumd9d1d4a2001-09-17 23:46:56 +0000307 f.hello = 'world'
308 verify(a == {'hello': 'world'})
Neal Norwitz221085d2007-02-25 20:55:47 +0000309 verify(a is f.__dict__)
Guido van Rossumd9d1d4a2001-09-17 23:46:56 +0000310 f.__dict__ = {'world': 'hello'}
311 verify(f.world == "hello")
Neal Norwitz221085d2007-02-25 20:55:47 +0000312 verify(f.__dict__ == {'world': 'hello'})
Guido van Rossumbd131492001-09-18 03:28:54 +0000313 cantset(f, "__dict__", None)
314
315def test_im_class():
316 class C:
317 def foo(self): pass
318 verify(C.foo.im_class is C)
319 verify(C().foo.im_class is C)
320 cantset(C.foo, "im_class", C)
321 cantset(C().foo, "im_class", C)
322
323def test_im_func():
324 def foo(self): pass
325 class C:
Guido van Rossumd9d1d4a2001-09-17 23:46:56 +0000326 pass
Guido van Rossumbd131492001-09-18 03:28:54 +0000327 C.foo = foo
328 verify(C.foo.im_func is foo)
329 verify(C().foo.im_func is foo)
330 cantset(C.foo, "im_func", foo)
331 cantset(C().foo, "im_func", foo)
332
333def test_im_self():
334 class C:
335 def foo(self): pass
336 verify(C.foo.im_self is None)
337 c = C()
338 verify(c.foo.im_self is c)
339 cantset(C.foo, "im_self", None)
340 cantset(c.foo, "im_self", c)
341
342def test_im_dict():
343 class C:
344 def foo(self): pass
345 foo.bar = 42
346 verify(C.foo.__dict__ == {'bar': 42})
347 verify(C().foo.__dict__ == {'bar': 42})
348 cantset(C.foo, "__dict__", C.foo.__dict__)
349 cantset(C().foo, "__dict__", C.foo.__dict__)
350
351def test_im_doc():
352 class C:
353 def foo(self): "hello"
354 verify(C.foo.__doc__ == "hello")
355 verify(C().foo.__doc__ == "hello")
356 cantset(C.foo, "__doc__", "hello")
357 cantset(C().foo, "__doc__", "hello")
358
359def test_im_name():
360 class C:
361 def foo(self): pass
362 verify(C.foo.__name__ == "foo")
363 verify(C().foo.__name__ == "foo")
364 cantset(C.foo, "__name__", "foo")
365 cantset(C().foo, "__name__", "foo")
Guido van Rossumd9d1d4a2001-09-17 23:46:56 +0000366
367def testmore():
368 test_func_closure()
369 test_func_doc()
370 test_func_globals()
371 test_func_name()
372 test_func_code()
373 test_func_defaults()
374 test_func_dict()
Guido van Rossumbd131492001-09-18 03:28:54 +0000375 # Tests for instance method attributes
376 test_im_class()
377 test_im_func()
378 test_im_self()
379 test_im_dict()
380 test_im_doc()
381 test_im_name()
Guido van Rossumd9d1d4a2001-09-17 23:46:56 +0000382
383testmore()