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()
|
---|