mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	 ee319f66ab
			
		
	
	
		ee319f66ab
		
	
	
	
	
		
			
			[ 1124295 ] Function's __name__ no longer accessible in restricted mode which I introduced with a bit of mindless copy-paste when making __name__ writable. You can't assign to __name__ in restricted mode, which I'm going to pretend was intentional :)
		
			
				
	
	
		
			402 lines
		
	
	
	
		
			9.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			402 lines
		
	
	
	
		
			9.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| 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, exception=(AttributeError, TypeError)):
 | |
|     verify(hasattr(obj, name)) # Otherwise it's probably a typo
 | |
|     try:
 | |
|         setattr(obj, name, value)
 | |
|     except exception:
 | |
|         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")
 | |
|     f.__name__ = "g"
 | |
|     verify(f.__name__ == "g")
 | |
|     verify(f.func_name == "g")
 | |
|     f.func_name = "h"
 | |
|     verify(f.__name__ == "h")
 | |
|     verify(f.func_name == "h")
 | |
|     cantset(f, "func_globals", 1)
 | |
|     cantset(f, "__name__", 1)
 | |
|     # test that you can access func.__name__ in restricted mode
 | |
|     s = """def f(): pass\nf.__name__"""
 | |
|     exec s in {'__builtins__':{}}
 | |
| 
 | |
| 
 | |
| def test_func_code():
 | |
|     a = b = 24
 | |
|     def f(): pass
 | |
|     def g(): print 12
 | |
|     def f1(): print a
 | |
|     def g1(): print b
 | |
|     def f2(): print a, b
 | |
|     verify(type(f.func_code) is types.CodeType)
 | |
|     f.func_code = g.func_code
 | |
|     cantset(f, "func_code", None)
 | |
|     # can't change the number of free vars
 | |
|     cantset(f,  "func_code", f1.func_code, exception=ValueError)
 | |
|     cantset(f1, "func_code",  f.func_code, exception=ValueError)
 | |
|     cantset(f1, "func_code", f2.func_code, exception=ValueError)
 | |
|     f1.func_code = g1.func_code
 | |
| 
 | |
| 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()
 |