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.__code__) 10 name: f 11 argcount: 1 12 kwonlyargcount: 0 13 names: () 14 varnames: ('x', 'g') 15 cellvars: ('x',) 16 freevars: () 17 nlocals: 2 18 flags: 3 19 consts: ('None', '<code object g>', "'f.<locals>.g'") 20 21 >>> dump(f(4).__code__) 22 name: g 23 argcount: 1 24 kwonlyargcount: 0 25 names: () 26 varnames: ('y',) 27 cellvars: () 28 freevars: ('x',) 29 nlocals: 1 30 flags: 19 31 consts: ('None',) 32 33 >>> def h(x, y): 34 ... a = x + y 35 ... b = x - y 36 ... c = a * b 37 ... return c 38 ... 39 40 >>> dump(h.__code__) 41 name: h 42 argcount: 2 43 kwonlyargcount: 0 44 names: () 45 varnames: ('x', 'y', 'a', 'b', 'c') 46 cellvars: () 47 freevars: () 48 nlocals: 5 49 flags: 67 50 consts: ('None',) 51 52 >>> def attrs(obj): 53 ... print(obj.attr1) 54 ... print(obj.attr2) 55 ... print(obj.attr3) 56 57 >>> dump(attrs.__code__) 58 name: attrs 59 argcount: 1 60 kwonlyargcount: 0 61 names: ('print', 'attr1', 'attr2', 'attr3') 62 varnames: ('obj',) 63 cellvars: () 64 freevars: () 65 nlocals: 1 66 flags: 67 67 consts: ('None',) 68 69 >>> def optimize_away(): 70 ... 'doc string' 71 ... 'not a docstring' 72 ... 53 73 ... 0x53 74 75 >>> dump(optimize_away.__code__) 76 name: optimize_away 77 argcount: 0 78 kwonlyargcount: 0 79 names: () 80 varnames: () 81 cellvars: () 82 freevars: () 83 nlocals: 0 84 flags: 67 85 consts: ("'doc string'", 'None') 86 87 >>> def keywordonly_args(a,b,*,k1): 88 ... return a,b,k1 89 ... 90 91 >>> dump(keywordonly_args.__code__) 92 name: keywordonly_args 93 argcount: 2 94 kwonlyargcount: 1 95 names: () 96 varnames: ('a', 'b', 'k1') 97 cellvars: () 98 freevars: () 99 nlocals: 3 100 flags: 67 101 consts: ('None',) 102 103 """ 104 105 import sys 106 import unittest 107 import weakref 108 from test.support import run_doctest, run_unittest, cpython_only 109 110 111 def consts(t): 112 """Yield a doctest-safe sequence of object reprs.""" 113 for elt in t: 114 r = repr(elt) 115 if r.startswith("<code object"): 116 yield "<code object %s>" % elt.co_name 117 else: 118 yield r 119 120 def dump(co): 121 """Print out a text representation of a code object.""" 122 for attr in ["name", "argcount", "kwonlyargcount", "names", "varnames", 123 "cellvars", "freevars", "nlocals", "flags"]: 124 print("%s: %s" % (attr, getattr(co, "co_" + attr))) 125 print("consts:", tuple(consts(co.co_consts))) 126 127 128 class CodeTest(unittest.TestCase): 129 130 @cpython_only 131 def test_newempty(self): 132 import _testcapi 133 co = _testcapi.code_newempty("filename", "funcname", 15) 134 self.assertEqual(co.co_filename, "filename") 135 self.assertEqual(co.co_name, "funcname") 136 self.assertEqual(co.co_firstlineno, 15) 137 138 139 def isinterned(s): 140 return s is sys.intern(('_' + s + '_')[1:-1]) 141 142 class CodeConstsTest(unittest.TestCase): 143 144 def find_const(self, consts, value): 145 for v in consts: 146 if v == value: 147 return v 148 self.assertIn(value, consts) # raises an exception 149 self.fail('Should never be reached') 150 151 def assertIsInterned(self, s): 152 if not isinterned(s): 153 self.fail('String %r is not interned' % (s,)) 154 155 def assertIsNotInterned(self, s): 156 if isinterned(s): 157 self.fail('String %r is interned' % (s,)) 158 159 @cpython_only 160 def test_interned_string(self): 161 co = compile('res = "str_value"', '?', 'exec') 162 v = self.find_const(co.co_consts, 'str_value') 163 self.assertIsInterned(v) 164 165 @cpython_only 166 def test_interned_string_in_tuple(self): 167 co = compile('res = ("str_value",)', '?', 'exec') 168 v = self.find_const(co.co_consts, ('str_value',)) 169 self.assertIsInterned(v[0]) 170 171 @cpython_only 172 def test_interned_string_in_frozenset(self): 173 co = compile('res = a in {"str_value"}', '?', 'exec') 174 v = self.find_const(co.co_consts, frozenset(('str_value',))) 175 self.assertIsInterned(tuple(v)[0]) 176 177 @cpython_only 178 def test_interned_string_default(self): 179 def f(a='str_value'): 180 return a 181 self.assertIsInterned(f()) 182 183 @cpython_only 184 def test_interned_string_with_null(self): 185 co = compile(r'res = "str\0value!"', '?', 'exec') 186 v = self.find_const(co.co_consts, 'str\0value!') 187 self.assertIsNotInterned(v) 188 189 190 class CodeWeakRefTest(unittest.TestCase): 191 192 def test_basic(self): 193 # Create a code object in a clean environment so that we know we have 194 # the only reference to it left. 195 namespace = {} 196 exec("def f(): pass", globals(), namespace) 197 f = namespace["f"] 198 del namespace 199 200 self.called = False 201 def callback(code): 202 self.called = True 203 204 # f is now the last reference to the function, and through it, the code 205 # object. While we hold it, check that we can create a weakref and 206 # deref it. Then delete it, and check that the callback gets called and 207 # the reference dies. 208 coderef = weakref.ref(f.__code__, callback) 209 self.assertTrue(bool(coderef())) 210 del f 211 self.assertFalse(bool(coderef())) 212 self.assertTrue(self.called) 213 214 215 def test_main(verbose=None): 216 from test import test_code 217 run_doctest(test_code, verbose) 218 run_unittest(CodeTest, CodeConstsTest, CodeWeakRefTest) 219 220 221 if __name__ == "__main__": 222 test_main() 223