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__) 10name: f 11argcount: 1 12kwonlyargcount: 0 13names: () 14varnames: ('x', 'g') 15cellvars: ('x',) 16freevars: () 17nlocals: 2 18flags: 3 19consts: ('None', '<code object g>', "'f.<locals>.g'") 20 21>>> dump(f(4).__code__) 22name: g 23argcount: 1 24kwonlyargcount: 0 25names: () 26varnames: ('y',) 27cellvars: () 28freevars: ('x',) 29nlocals: 1 30flags: 19 31consts: ('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__) 41name: h 42argcount: 2 43kwonlyargcount: 0 44names: () 45varnames: ('x', 'y', 'a', 'b', 'c') 46cellvars: () 47freevars: () 48nlocals: 5 49flags: 67 50consts: ('None',) 51 52>>> def attrs(obj): 53... print(obj.attr1) 54... print(obj.attr2) 55... print(obj.attr3) 56 57>>> dump(attrs.__code__) 58name: attrs 59argcount: 1 60kwonlyargcount: 0 61names: ('print', 'attr1', 'attr2', 'attr3') 62varnames: ('obj',) 63cellvars: () 64freevars: () 65nlocals: 1 66flags: 67 67consts: ('None',) 68 69>>> def optimize_away(): 70... 'doc string' 71... 'not a docstring' 72... 53 73... 0x53 74 75>>> dump(optimize_away.__code__) 76name: optimize_away 77argcount: 0 78kwonlyargcount: 0 79names: () 80varnames: () 81cellvars: () 82freevars: () 83nlocals: 0 84flags: 67 85consts: ("'doc string'", 'None') 86 87>>> def keywordonly_args(a,b,*,k1): 88... return a,b,k1 89... 90 91>>> dump(keywordonly_args.__code__) 92name: keywordonly_args 93argcount: 2 94kwonlyargcount: 1 95names: () 96varnames: ('a', 'b', 'k1') 97cellvars: () 98freevars: () 99nlocals: 3 100flags: 67 101consts: ('None',) 102 103""" 104 105import sys 106import unittest 107import weakref 108from test.support import run_doctest, run_unittest, cpython_only 109 110 111def 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 120def 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 128class 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 139def isinterned(s): 140 return s is sys.intern(('_' + s + '_')[1:-1]) 141 142class 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 190class 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 215def test_main(verbose=None): 216 from test import test_code 217 run_doctest(test_code, verbose) 218 run_unittest(CodeTest, CodeConstsTest, CodeWeakRefTest) 219 220 221if __name__ == "__main__": 222 test_main() 223