| from test.test_support import verbose, TestFailed, verify | 
 | import types | 
 |  | 
 | class F: | 
 |     def a(self): | 
 |         pass | 
 |  | 
 | def b(): | 
 |     'my docstring' | 
 |     pass | 
 |  | 
 | # __module__ is a special attribute | 
 | verify(b.__module__ == __name__) | 
 | verify(verify.__module__ == "test.test_support") | 
 |  | 
 | # setting attributes on functions | 
 | try: | 
 |     b.publish | 
 | except AttributeError: pass | 
 | else: raise TestFailed, 'expected AttributeError' | 
 |  | 
 | if b.__dict__ <> {}: | 
 |     raise TestFailed, 'expected unassigned func.__dict__ to be {}' | 
 |  | 
 | b.publish = 1 | 
 | if b.publish <> 1: | 
 |     raise TestFailed, 'function attribute not set to expected value' | 
 |  | 
 | docstring = 'its docstring' | 
 | b.__doc__ = docstring | 
 | if b.__doc__ <> docstring: | 
 |     raise TestFailed, 'problem with setting __doc__ attribute' | 
 |  | 
 | if 'publish' not in dir(b): | 
 |     raise TestFailed, 'attribute not in dir()' | 
 |  | 
 | try: | 
 |     del b.__dict__ | 
 | except TypeError: pass | 
 | else: raise TestFailed, 'del func.__dict__ expected TypeError' | 
 |  | 
 | b.publish = 1 | 
 | try: | 
 |     b.__dict__ = None | 
 | except TypeError: pass | 
 | else: raise TestFailed, 'func.__dict__ = None expected TypeError' | 
 |  | 
 | d = {'hello': 'world'} | 
 | b.__dict__ = d | 
 | if b.func_dict is not d: | 
 |     raise TestFailed, 'func.__dict__ assignment to dictionary failed' | 
 | if b.hello <> 'world': | 
 |     raise TestFailed, 'attribute after func.__dict__ assignment failed' | 
 |  | 
 | f1 = F() | 
 | f2 = F() | 
 |  | 
 | try: | 
 |     F.a.publish | 
 | except AttributeError: pass | 
 | else: raise TestFailed, 'expected AttributeError' | 
 |  | 
 | try: | 
 |     f1.a.publish | 
 | except AttributeError: pass | 
 | else: raise TestFailed, 'expected AttributeError' | 
 |  | 
 | # In Python 2.1 beta 1, we disallowed setting attributes on unbound methods | 
 | # (it was already disallowed on bound methods).  See the PEP for details. | 
 | try: | 
 |     F.a.publish = 1 | 
 | except (AttributeError, TypeError): pass | 
 | else: raise TestFailed, 'expected AttributeError or TypeError' | 
 |  | 
 | # But setting it explicitly on the underlying function object is okay. | 
 | F.a.im_func.publish = 1 | 
 |  | 
 | if F.a.publish <> 1: | 
 |     raise TestFailed, 'unbound method attribute not set to expected value' | 
 |  | 
 | if f1.a.publish <> 1: | 
 |     raise TestFailed, 'bound method attribute access did not work' | 
 |  | 
 | if f2.a.publish <> 1: | 
 |     raise TestFailed, 'bound method attribute access did not work' | 
 |  | 
 | if 'publish' not in dir(F.a): | 
 |     raise TestFailed, 'attribute not in dir()' | 
 |  | 
 | try: | 
 |     f1.a.publish = 0 | 
 | except (AttributeError, TypeError): pass | 
 | else: raise TestFailed, 'expected AttributeError or TypeError' | 
 |  | 
 | # See the comment above about the change in semantics for Python 2.1b1 | 
 | try: | 
 |     F.a.myclass = F | 
 | except (AttributeError, TypeError): pass | 
 | else: raise TestFailed, 'expected AttributeError or TypeError' | 
 |  | 
 | F.a.im_func.myclass = F | 
 |  | 
 | f1.a.myclass | 
 | f2.a.myclass | 
 | f1.a.myclass | 
 | F.a.myclass | 
 |  | 
 | if f1.a.myclass is not f2.a.myclass or \ | 
 |        f1.a.myclass is not F.a.myclass: | 
 |     raise TestFailed, 'attributes were not the same' | 
 |  | 
 | # try setting __dict__ | 
 | try: | 
 |     F.a.__dict__ = (1, 2, 3) | 
 | except (AttributeError, TypeError): pass | 
 | else: raise TestFailed, 'expected TypeError or AttributeError' | 
 |  | 
 | F.a.im_func.__dict__ = {'one': 11, 'two': 22, 'three': 33} | 
 |  | 
 | if f1.a.two <> 22: | 
 |     raise TestFailed, 'setting __dict__' | 
 |  | 
 | from UserDict import UserDict | 
 | d = UserDict({'four': 44, 'five': 55}) | 
 |  | 
 | try: | 
 |     F.a.__dict__ = d | 
 | except (AttributeError, TypeError): pass | 
 | else: raise TestFailed | 
 |  | 
 | if f2.a.one <> f1.a.one <> F.a.one <> 11: | 
 |     raise TestFailed | 
 |  | 
 | # im_func may not be a Python method! | 
 | import new | 
 | F.id = new.instancemethod(id, None, F) | 
 |  | 
 | eff = F() | 
 | if eff.id() <> id(eff): | 
 |     raise TestFailed | 
 |  | 
 | try: | 
 |     F.id.foo | 
 | except AttributeError: pass | 
 | else: raise TestFailed | 
 |  | 
 | try: | 
 |     F.id.foo = 12 | 
 | except (AttributeError, TypeError): pass | 
 | else: raise TestFailed | 
 |  | 
 | try: | 
 |     F.id.foo | 
 | except AttributeError: pass | 
 | else: raise TestFailed | 
 |  | 
 | try: | 
 |     eff.id.foo | 
 | except AttributeError: pass | 
 | else: raise TestFailed | 
 |  | 
 | try: | 
 |     eff.id.foo = 12 | 
 | except (AttributeError, TypeError): pass | 
 | else: raise TestFailed | 
 |  | 
 | try: | 
 |     eff.id.foo | 
 | except AttributeError: pass | 
 | else: raise TestFailed | 
 |  | 
 | # Regression test for a crash in pre-2.1a1 | 
 | def another(): | 
 |     pass | 
 |  | 
 | try: | 
 |     del another.__dict__ | 
 | except TypeError: pass | 
 | else: raise TestFailed | 
 |  | 
 | try: | 
 |     del another.func_dict | 
 | except TypeError: pass | 
 | else: raise TestFailed | 
 |  | 
 | try: | 
 |     another.func_dict = None | 
 | except TypeError: pass | 
 | else: raise TestFailed | 
 |  | 
 | try: | 
 |     del another.bar | 
 | except AttributeError: pass | 
 | else: raise TestFailed | 
 |  | 
 | # This isn't specifically related to function attributes, but it does test a | 
 | # core dump regression in funcobject.c | 
 | del another.func_defaults | 
 |  | 
 | def foo(): | 
 |     pass | 
 |  | 
 | def bar(): | 
 |     pass | 
 |  | 
 | def temp(): | 
 |     print 1 | 
 |  | 
 | if foo==bar: | 
 |     raise TestFailed | 
 |  | 
 | d={} | 
 | d[foo] = 1 | 
 |  | 
 | foo.func_code = temp.func_code | 
 |  | 
 | d[foo] | 
 |  | 
 | # Test all predefined function attributes systematically | 
 |  | 
 | def cantset(obj, name, value): | 
 |     verify(hasattr(obj, name)) # Otherwise it's probably a typo | 
 |     try: | 
 |         setattr(obj, name, value) | 
 |     except (AttributeError, TypeError): | 
 |         pass | 
 |     else: | 
 |         raise TestFailed, "shouldn't be able to set %s to %r" % (name, value) | 
 |     try: | 
 |         delattr(obj, name) | 
 |     except (AttributeError, TypeError): | 
 |         pass | 
 |     else: | 
 |         raise TestFailed, "shouldn't be able to del %s" % name | 
 |  | 
 | def test_func_closure(): | 
 |     a = 12 | 
 |     def f(): print a | 
 |     c = f.func_closure | 
 |     verify(isinstance(c, tuple)) | 
 |     verify(len(c) == 1) | 
 |     verify(c[0].__class__.__name__ == "cell") # don't have a type object handy | 
 |     cantset(f, "func_closure", c) | 
 |  | 
 | def test_func_doc(): | 
 |     def f(): pass | 
 |     verify(f.__doc__ is None) | 
 |     verify(f.func_doc is None) | 
 |     f.__doc__ = "hello" | 
 |     verify(f.__doc__ == "hello") | 
 |     verify(f.func_doc == "hello") | 
 |     del f.__doc__ | 
 |     verify(f.__doc__ is None) | 
 |     verify(f.func_doc is None) | 
 |     f.func_doc = "world" | 
 |     verify(f.__doc__ == "world") | 
 |     verify(f.func_doc == "world") | 
 |     del f.func_doc | 
 |     verify(f.func_doc is None) | 
 |     verify(f.__doc__ is None) | 
 |  | 
 | def test_func_globals(): | 
 |     def f(): pass | 
 |     verify(f.func_globals is globals()) | 
 |     cantset(f, "func_globals", globals()) | 
 |  | 
 | def test_func_name(): | 
 |     def f(): pass | 
 |     verify(f.__name__ == "f") | 
 |     verify(f.func_name == "f") | 
 |     cantset(f, "func_name", "f") | 
 |     cantset(f, "__name__", "f") | 
 |  | 
 | def test_func_code(): | 
 |     def f(): pass | 
 |     def g(): print 12 | 
 |     verify(type(f.func_code) is types.CodeType) | 
 |     f.func_code = g.func_code | 
 |     cantset(f, "func_code", None) | 
 |  | 
 | def test_func_defaults(): | 
 |     def f(a, b): return (a, b) | 
 |     verify(f.func_defaults is None) | 
 |     f.func_defaults = (1, 2) | 
 |     verify(f.func_defaults == (1, 2)) | 
 |     verify(f(10) == (10, 2)) | 
 |     def g(a=1, b=2): return (a, b) | 
 |     verify(g.func_defaults == (1, 2)) | 
 |     del g.func_defaults | 
 |     verify(g.func_defaults is None) | 
 |     try: | 
 |         g() | 
 |     except TypeError: | 
 |         pass | 
 |     else: | 
 |         raise TestFailed, "shouldn't be allowed to call g() w/o defaults" | 
 |  | 
 | def test_func_dict(): | 
 |     def f(): pass | 
 |     a = f.__dict__ | 
 |     b = f.func_dict | 
 |     verify(a == {}) | 
 |     verify(a is b) | 
 |     f.hello = 'world' | 
 |     verify(a == {'hello': 'world'}) | 
 |     verify(f.func_dict is a is f.__dict__) | 
 |     f.func_dict = {} | 
 |     verify(not hasattr(f, "hello")) | 
 |     f.__dict__ = {'world': 'hello'} | 
 |     verify(f.world == "hello") | 
 |     verify(f.__dict__ is f.func_dict == {'world': 'hello'}) | 
 |     cantset(f, "func_dict", None) | 
 |     cantset(f, "__dict__", None) | 
 |  | 
 | def test_im_class(): | 
 |     class C: | 
 |         def foo(self): pass | 
 |     verify(C.foo.im_class is C) | 
 |     verify(C().foo.im_class is C) | 
 |     cantset(C.foo, "im_class", C) | 
 |     cantset(C().foo, "im_class", C) | 
 |  | 
 | def test_im_func(): | 
 |     def foo(self): pass | 
 |     class C: | 
 |         pass | 
 |     C.foo = foo | 
 |     verify(C.foo.im_func is foo) | 
 |     verify(C().foo.im_func is foo) | 
 |     cantset(C.foo, "im_func", foo) | 
 |     cantset(C().foo, "im_func", foo) | 
 |  | 
 | def test_im_self(): | 
 |     class C: | 
 |         def foo(self): pass | 
 |     verify(C.foo.im_self is None) | 
 |     c = C() | 
 |     verify(c.foo.im_self is c) | 
 |     cantset(C.foo, "im_self", None) | 
 |     cantset(c.foo, "im_self", c) | 
 |  | 
 | def test_im_dict(): | 
 |     class C: | 
 |         def foo(self): pass | 
 |         foo.bar = 42 | 
 |     verify(C.foo.__dict__ == {'bar': 42}) | 
 |     verify(C().foo.__dict__ == {'bar': 42}) | 
 |     cantset(C.foo, "__dict__", C.foo.__dict__) | 
 |     cantset(C().foo, "__dict__", C.foo.__dict__) | 
 |  | 
 | def test_im_doc(): | 
 |     class C: | 
 |         def foo(self): "hello" | 
 |     verify(C.foo.__doc__ == "hello") | 
 |     verify(C().foo.__doc__ == "hello") | 
 |     cantset(C.foo, "__doc__", "hello") | 
 |     cantset(C().foo, "__doc__", "hello") | 
 |  | 
 | def test_im_name(): | 
 |     class C: | 
 |         def foo(self): pass | 
 |     verify(C.foo.__name__ == "foo") | 
 |     verify(C().foo.__name__ == "foo") | 
 |     cantset(C.foo, "__name__", "foo") | 
 |     cantset(C().foo, "__name__", "foo") | 
 |  | 
 | def testmore(): | 
 |     test_func_closure() | 
 |     test_func_doc() | 
 |     test_func_globals() | 
 |     test_func_name() | 
 |     test_func_code() | 
 |     test_func_defaults() | 
 |     test_func_dict() | 
 |     # Tests for instance method attributes | 
 |     test_im_class() | 
 |     test_im_func() | 
 |     test_im_self() | 
 |     test_im_dict() | 
 |     test_im_doc() | 
 |     test_im_name() | 
 |  | 
 | testmore() |