1"""This module includes tests of the code object representation. 2 3>>> def f(x): 4... def g(y): 5... return x + y 6... return g 7... 8 9>>> dump(f.func_code) 10name: f 11argcount: 1 12names: () 13varnames: ('x', 'g') 14cellvars: ('x',) 15freevars: () 16nlocals: 2 17flags: 3 18consts: ('None', '<code object g>') 19 20>>> dump(f(4).func_code) 21name: g 22argcount: 1 23names: () 24varnames: ('y',) 25cellvars: () 26freevars: ('x',) 27nlocals: 1 28flags: 19 29consts: ('None',) 30 31>>> def h(x, y): 32... a = x + y 33... b = x - y 34... c = a * b 35... return c 36... 37>>> dump(h.func_code) 38name: h 39argcount: 2 40names: () 41varnames: ('x', 'y', 'a', 'b', 'c') 42cellvars: () 43freevars: () 44nlocals: 5 45flags: 67 46consts: ('None',) 47 48>>> def attrs(obj): 49... print obj.attr1 50... print obj.attr2 51... print obj.attr3 52 53>>> dump(attrs.func_code) 54name: attrs 55argcount: 1 56names: ('attr1', 'attr2', 'attr3') 57varnames: ('obj',) 58cellvars: () 59freevars: () 60nlocals: 1 61flags: 67 62consts: ('None',) 63 64>>> def optimize_away(): 65... 'doc string' 66... 'not a docstring' 67... 53 68... 53L 69 70>>> dump(optimize_away.func_code) 71name: optimize_away 72argcount: 0 73names: () 74varnames: () 75cellvars: () 76freevars: () 77nlocals: 0 78flags: 67 79consts: ("'doc string'", 'None') 80 81""" 82 83import unittest 84import weakref 85import _testcapi 86 87 88def consts(t): 89 """Yield a doctest-safe sequence of object reprs.""" 90 for elt in t: 91 r = repr(elt) 92 if r.startswith("<code object"): 93 yield "<code object %s>" % elt.co_name 94 else: 95 yield r 96 97def dump(co): 98 """Print out a text representation of a code object.""" 99 for attr in ["name", "argcount", "names", "varnames", "cellvars", 100 "freevars", "nlocals", "flags"]: 101 print "%s: %s" % (attr, getattr(co, "co_" + attr)) 102 print "consts:", tuple(consts(co.co_consts)) 103 104 105class CodeTest(unittest.TestCase): 106 107 def test_newempty(self): 108 co = _testcapi.code_newempty("filename", "funcname", 15) 109 self.assertEqual(co.co_filename, "filename") 110 self.assertEqual(co.co_name, "funcname") 111 self.assertEqual(co.co_firstlineno, 15) 112 113 114class CodeWeakRefTest(unittest.TestCase): 115 116 def test_basic(self): 117 # Create a code object in a clean environment so that we know we have 118 # the only reference to it left. 119 namespace = {} 120 exec "def f(): pass" in globals(), namespace 121 f = namespace["f"] 122 del namespace 123 124 self.called = False 125 def callback(code): 126 self.called = True 127 128 # f is now the last reference to the function, and through it, the code 129 # object. While we hold it, check that we can create a weakref and 130 # deref it. Then delete it, and check that the callback gets called and 131 # the reference dies. 132 coderef = weakref.ref(f.__code__, callback) 133 self.assertTrue(bool(coderef())) 134 del f 135 self.assertFalse(bool(coderef())) 136 self.assertTrue(self.called) 137 138 139def test_main(verbose=None): 140 from test.test_support import run_doctest, run_unittest 141 from test import test_code 142 run_doctest(test_code, verbose) 143 run_unittest(CodeTest, CodeWeakRefTest) 144 145 146if __name__ == "__main__": 147 test_main() 148