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 85from test.test_support import run_doctest, run_unittest, cpython_only 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 @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 116def isinterned(s): 117 return s is intern(('_' + s + '_')[1:-1]) 118 119class 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 161class 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 186def test_main(verbose=None): 187 from test import test_code 188 run_doctest(test_code, verbose) 189 run_unittest(CodeTest, CodeConstsTest, CodeWeakRefTest) 190 191 192if __name__ == "__main__": 193 test_main() 194