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 from test.test_support import run_doctest, run_unittest, cpython_only 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 @cpython_only 108 def test_newempty(self): 109 import _testcapi 110 co = _testcapi.code_newempty("filename", "funcname", 15) 111 self.assertEqual(co.co_filename, "filename") 112 self.assertEqual(co.co_name, "funcname") 113 self.assertEqual(co.co_firstlineno, 15) 114 115 116 def isinterned(s): 117 return s is intern(('_' + s + '_')[1:-1]) 118 119 class CodeConstsTest(unittest.TestCase): 120 121 def find_const(self, consts, value): 122 for v in consts: 123 if v == value: 124 return v 125 self.assertIn(value, consts) # raises an exception 126 self.fail('Should never be reached') 127 128 def assertIsInterned(self, s): 129 if not isinterned(s): 130 self.fail('String %r is not interned' % (s,)) 131 132 def assertIsNotInterned(self, s): 133 if isinterned(s): 134 self.fail('String %r is interned' % (s,)) 135 136 @cpython_only 137 def test_interned_string(self): 138 co = compile('res = "str_value"', '?', 'exec') 139 v = self.find_const(co.co_consts, 'str_value') 140 self.assertIsInterned(v) 141 142 @cpython_only 143 def test_interned_string_in_tuple(self): 144 co = compile('res = ("str_value",)', '?', 'exec') 145 v = self.find_const(co.co_consts, ('str_value',)) 146 self.assertIsInterned(v[0]) 147 148 @cpython_only 149 def test_interned_string_default(self): 150 def f(a='str_value'): 151 return a 152 self.assertIsInterned(f()) 153 154 @cpython_only 155 def test_interned_string_with_null(self): 156 co = compile(r'res = "str\0value!"', '?', 'exec') 157 v = self.find_const(co.co_consts, 'str\0value!') 158 self.assertIsNotInterned(v) 159 160 161 class CodeWeakRefTest(unittest.TestCase): 162 163 def test_basic(self): 164 # Create a code object in a clean environment so that we know we have 165 # the only reference to it left. 166 namespace = {} 167 exec "def f(): pass" in globals(), namespace 168 f = namespace["f"] 169 del namespace 170 171 self.called = False 172 def callback(code): 173 self.called = True 174 175 # f is now the last reference to the function, and through it, the code 176 # object. While we hold it, check that we can create a weakref and 177 # deref it. Then delete it, and check that the callback gets called and 178 # the reference dies. 179 coderef = weakref.ref(f.__code__, callback) 180 self.assertTrue(bool(coderef())) 181 del f 182 self.assertFalse(bool(coderef())) 183 self.assertTrue(self.called) 184 185 186 def test_main(verbose=None): 187 from test import test_code 188 run_doctest(test_code, verbose) 189 run_unittest(CodeTest, CodeConstsTest, CodeWeakRefTest) 190 191 192 if __name__ == "__main__": 193 test_main() 194