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) 10 name: f 11 argcount: 1 12 names: () 13 varnames: ('x', 'g') 14 cellvars: ('x',) 15 freevars: () 16 nlocals: 2 17 flags: 3 18 consts: ('None', '<code object g>') 19 20 >>> dump(f(4).func_code) 21 name: g 22 argcount: 1 23 names: () 24 varnames: ('y',) 25 cellvars: () 26 freevars: ('x',) 27 nlocals: 1 28 flags: 19 29 consts: ('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) 38 name: h 39 argcount: 2 40 names: () 41 varnames: ('x', 'y', 'a', 'b', 'c') 42 cellvars: () 43 freevars: () 44 nlocals: 5 45 flags: 67 46 consts: ('None',) 47 48 >>> def attrs(obj): 49 ... print obj.attr1 50 ... print obj.attr2 51 ... print obj.attr3 52 53 >>> dump(attrs.func_code) 54 name: attrs 55 argcount: 1 56 names: ('attr1', 'attr2', 'attr3') 57 varnames: ('obj',) 58 cellvars: () 59 freevars: () 60 nlocals: 1 61 flags: 67 62 consts: ('None',) 63 64 >>> def optimize_away(): 65 ... 'doc string' 66 ... 'not a docstring' 67 ... 53 68 ... 53L 69 70 >>> dump(optimize_away.func_code) 71 name: optimize_away 72 argcount: 0 73 names: () 74 varnames: () 75 cellvars: () 76 freevars: () 77 nlocals: 0 78 flags: 67 79 consts: ("'doc string'", 'None') 80 81 """ 82 83 import unittest 84 import weakref 85 import _testcapi 86 87 88 def 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 97 def 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 105 class 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 114 class 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 139 def 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 146 if __name__ == "__main__": 147 test_main() 148