Replaced my dumb way of calculating seconds to midnight with Tim Peters' much more...
[python.git] / Lib / test / test_funcattrs.py
blob7a083b70dfbf18a7b22c24b7434903f8e0b43a66
1 from test.test_support import verbose, TestFailed, verify
2 import types
4 class F:
5 def a(self):
6 pass
8 def b():
9 'my docstring'
10 pass
12 # __module__ is a special attribute
13 verify(b.__module__ == __name__)
14 verify(verify.__module__ == "test.test_support")
16 # setting attributes on functions
17 try:
18 b.publish
19 except AttributeError: pass
20 else: raise TestFailed, 'expected AttributeError'
22 if b.__dict__ <> {}:
23 raise TestFailed, 'expected unassigned func.__dict__ to be {}'
25 b.publish = 1
26 if b.publish <> 1:
27 raise TestFailed, 'function attribute not set to expected value'
29 docstring = 'its docstring'
30 b.__doc__ = docstring
31 if b.__doc__ <> docstring:
32 raise TestFailed, 'problem with setting __doc__ attribute'
34 if 'publish' not in dir(b):
35 raise TestFailed, 'attribute not in dir()'
37 try:
38 del b.__dict__
39 except TypeError: pass
40 else: raise TestFailed, 'del func.__dict__ expected TypeError'
42 b.publish = 1
43 try:
44 b.__dict__ = None
45 except TypeError: pass
46 else: raise TestFailed, 'func.__dict__ = None expected TypeError'
48 d = {'hello': 'world'}
49 b.__dict__ = d
50 if b.func_dict is not d:
51 raise TestFailed, 'func.__dict__ assignment to dictionary failed'
52 if b.hello <> 'world':
53 raise TestFailed, 'attribute after func.__dict__ assignment failed'
55 f1 = F()
56 f2 = F()
58 try:
59 F.a.publish
60 except AttributeError: pass
61 else: raise TestFailed, 'expected AttributeError'
63 try:
64 f1.a.publish
65 except AttributeError: pass
66 else: raise TestFailed, 'expected AttributeError'
68 # 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.
70 try:
71 F.a.publish = 1
72 except (AttributeError, TypeError): pass
73 else: raise TestFailed, 'expected AttributeError or TypeError'
75 # But setting it explicitly on the underlying function object is okay.
76 F.a.im_func.publish = 1
78 if F.a.publish <> 1:
79 raise TestFailed, 'unbound method attribute not set to expected value'
81 if f1.a.publish <> 1:
82 raise TestFailed, 'bound method attribute access did not work'
84 if f2.a.publish <> 1:
85 raise TestFailed, 'bound method attribute access did not work'
87 if 'publish' not in dir(F.a):
88 raise TestFailed, 'attribute not in dir()'
90 try:
91 f1.a.publish = 0
92 except (AttributeError, TypeError): pass
93 else: raise TestFailed, 'expected AttributeError or TypeError'
95 # See the comment above about the change in semantics for Python 2.1b1
96 try:
97 F.a.myclass = F
98 except (AttributeError, TypeError): pass
99 else: raise TestFailed, 'expected AttributeError or TypeError'
101 F.a.im_func.myclass = F
103 f1.a.myclass
104 f2.a.myclass
105 f1.a.myclass
106 F.a.myclass
108 if f1.a.myclass is not f2.a.myclass or \
109 f1.a.myclass is not F.a.myclass:
110 raise TestFailed, 'attributes were not the same'
112 # try setting __dict__
113 try:
114 F.a.__dict__ = (1, 2, 3)
115 except (AttributeError, TypeError): pass
116 else: raise TestFailed, 'expected TypeError or AttributeError'
118 F.a.im_func.__dict__ = {'one': 11, 'two': 22, 'three': 33}
120 if f1.a.two <> 22:
121 raise TestFailed, 'setting __dict__'
123 from UserDict import UserDict
124 d = UserDict({'four': 44, 'five': 55})
126 try:
127 F.a.__dict__ = d
128 except (AttributeError, TypeError): pass
129 else: raise TestFailed
131 if f2.a.one <> f1.a.one <> F.a.one <> 11:
132 raise TestFailed
134 # im_func may not be a Python method!
135 import new
136 F.id = new.instancemethod(id, None, F)
138 eff = F()
139 if eff.id() <> id(eff):
140 raise TestFailed
142 try:
143 F.id.foo
144 except AttributeError: pass
145 else: raise TestFailed
147 try:
148 F.id.foo = 12
149 except (AttributeError, TypeError): pass
150 else: raise TestFailed
152 try:
153 F.id.foo
154 except AttributeError: pass
155 else: raise TestFailed
157 try:
158 eff.id.foo
159 except AttributeError: pass
160 else: raise TestFailed
162 try:
163 eff.id.foo = 12
164 except (AttributeError, TypeError): pass
165 else: raise TestFailed
167 try:
168 eff.id.foo
169 except AttributeError: pass
170 else: raise TestFailed
172 # Regression test for a crash in pre-2.1a1
173 def another():
174 pass
176 try:
177 del another.__dict__
178 except TypeError: pass
179 else: raise TestFailed
181 try:
182 del another.func_dict
183 except TypeError: pass
184 else: raise TestFailed
186 try:
187 another.func_dict = None
188 except TypeError: pass
189 else: raise TestFailed
191 try:
192 del another.bar
193 except AttributeError: pass
194 else: raise TestFailed
196 # This isn't specifically related to function attributes, but it does test a
197 # core dump regression in funcobject.c
198 del another.func_defaults
200 def foo():
201 pass
203 def bar():
204 pass
206 def temp():
207 print 1
209 if foo==bar:
210 raise TestFailed
212 d={}
213 d[foo] = 1
215 foo.func_code = temp.func_code
217 d[foo]
219 # Test all predefined function attributes systematically
221 def cantset(obj, name, value, exception=(AttributeError, TypeError)):
222 verify(hasattr(obj, name)) # Otherwise it's probably a typo
223 try:
224 setattr(obj, name, value)
225 except exception:
226 pass
227 else:
228 raise TestFailed, "shouldn't be able to set %s to %r" % (name, value)
229 try:
230 delattr(obj, name)
231 except (AttributeError, TypeError):
232 pass
233 else:
234 raise TestFailed, "shouldn't be able to del %s" % name
236 def test_func_closure():
237 a = 12
238 def f(): print a
239 c = f.func_closure
240 verify(isinstance(c, tuple))
241 verify(len(c) == 1)
242 verify(c[0].__class__.__name__ == "cell") # don't have a type object handy
243 cantset(f, "func_closure", c)
245 def test_func_doc():
246 def f(): pass
247 verify(f.__doc__ is None)
248 verify(f.func_doc is None)
249 f.__doc__ = "hello"
250 verify(f.__doc__ == "hello")
251 verify(f.func_doc == "hello")
252 del f.__doc__
253 verify(f.__doc__ is None)
254 verify(f.func_doc is None)
255 f.func_doc = "world"
256 verify(f.__doc__ == "world")
257 verify(f.func_doc == "world")
258 del f.func_doc
259 verify(f.func_doc is None)
260 verify(f.__doc__ is None)
262 def test_func_globals():
263 def f(): pass
264 verify(f.func_globals is globals())
265 cantset(f, "func_globals", globals())
267 def test_func_name():
268 def f(): pass
269 verify(f.__name__ == "f")
270 verify(f.func_name == "f")
271 f.__name__ = "g"
272 verify(f.__name__ == "g")
273 verify(f.func_name == "g")
274 f.func_name = "h"
275 verify(f.__name__ == "h")
276 verify(f.func_name == "h")
277 cantset(f, "func_globals", 1)
278 cantset(f, "__name__", 1)
279 # test that you can access func.__name__ in restricted mode
280 s = """def f(): pass\nf.__name__"""
281 exec s in {'__builtins__':{}}
284 def test_func_code():
285 a = b = 24
286 def f(): pass
287 def g(): print 12
288 def f1(): print a
289 def g1(): print b
290 def f2(): print a, b
291 verify(type(f.func_code) is types.CodeType)
292 f.func_code = g.func_code
293 cantset(f, "func_code", None)
294 # can't change the number of free vars
295 cantset(f, "func_code", f1.func_code, exception=ValueError)
296 cantset(f1, "func_code", f.func_code, exception=ValueError)
297 cantset(f1, "func_code", f2.func_code, exception=ValueError)
298 f1.func_code = g1.func_code
300 def test_func_defaults():
301 def f(a, b): return (a, b)
302 verify(f.func_defaults is None)
303 f.func_defaults = (1, 2)
304 verify(f.func_defaults == (1, 2))
305 verify(f(10) == (10, 2))
306 def g(a=1, b=2): return (a, b)
307 verify(g.func_defaults == (1, 2))
308 del g.func_defaults
309 verify(g.func_defaults is None)
310 try:
312 except TypeError:
313 pass
314 else:
315 raise TestFailed, "shouldn't be allowed to call g() w/o defaults"
317 def test_func_dict():
318 def f(): pass
319 a = f.__dict__
320 b = f.func_dict
321 verify(a == {})
322 verify(a is b)
323 f.hello = 'world'
324 verify(a == {'hello': 'world'})
325 verify(f.func_dict is a is f.__dict__)
326 f.func_dict = {}
327 verify(not hasattr(f, "hello"))
328 f.__dict__ = {'world': 'hello'}
329 verify(f.world == "hello")
330 verify(f.__dict__ is f.func_dict == {'world': 'hello'})
331 cantset(f, "func_dict", None)
332 cantset(f, "__dict__", None)
334 def test_im_class():
335 class C:
336 def foo(self): pass
337 verify(C.foo.im_class is C)
338 verify(C().foo.im_class is C)
339 cantset(C.foo, "im_class", C)
340 cantset(C().foo, "im_class", C)
342 def test_im_func():
343 def foo(self): pass
344 class C:
345 pass
346 C.foo = foo
347 verify(C.foo.im_func is foo)
348 verify(C().foo.im_func is foo)
349 cantset(C.foo, "im_func", foo)
350 cantset(C().foo, "im_func", foo)
352 def test_im_self():
353 class C:
354 def foo(self): pass
355 verify(C.foo.im_self is None)
356 c = C()
357 verify(c.foo.im_self is c)
358 cantset(C.foo, "im_self", None)
359 cantset(c.foo, "im_self", c)
361 def test_im_dict():
362 class C:
363 def foo(self): pass
364 foo.bar = 42
365 verify(C.foo.__dict__ == {'bar': 42})
366 verify(C().foo.__dict__ == {'bar': 42})
367 cantset(C.foo, "__dict__", C.foo.__dict__)
368 cantset(C().foo, "__dict__", C.foo.__dict__)
370 def test_im_doc():
371 class C:
372 def foo(self): "hello"
373 verify(C.foo.__doc__ == "hello")
374 verify(C().foo.__doc__ == "hello")
375 cantset(C.foo, "__doc__", "hello")
376 cantset(C().foo, "__doc__", "hello")
378 def test_im_name():
379 class C:
380 def foo(self): pass
381 verify(C.foo.__name__ == "foo")
382 verify(C().foo.__name__ == "foo")
383 cantset(C.foo, "__name__", "foo")
384 cantset(C().foo, "__name__", "foo")
386 def testmore():
387 test_func_closure()
388 test_func_doc()
389 test_func_globals()
390 test_func_name()
391 test_func_code()
392 test_func_defaults()
393 test_func_dict()
394 # Tests for instance method attributes
395 test_im_class()
396 test_im_func()
397 test_im_self()
398 test_im_dict()
399 test_im_doc()
400 test_im_name()
402 testmore()