File: test_code.py

package info (click to toggle)
pypy3 7.3.19%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 212,236 kB
  • sloc: python: 2,098,316; ansic: 540,565; sh: 21,462; asm: 14,419; cpp: 4,451; makefile: 4,209; objc: 761; xml: 530; exp: 499; javascript: 314; pascal: 244; lisp: 45; csh: 12; awk: 4
file content (220 lines) | stat: -rw-r--r-- 7,861 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
from pypy.interpreter.pycode import PyCode
from pypy.interpreter import gateway
from pypy.interpreter.astcompiler import consts
import py

class TestCode:
    def test_code_eq_corner_cases(self):
        space = self.space
        def make_code_with_const(w_obj):
            return PyCode(space, 0, 0, 0, 0, 1, 0, '', [w_obj], [], [], '', '', '', 0, '', [], [], False)
        def cmp_code_consts(w_obj1, w_obj2):
            w_code1 = make_code_with_const(w_obj1)
            w_code2 = make_code_with_const(w_obj2)

            # code objects in co_consts are compared by identity
            # (we never share them in the bytecode compiler, it happens
            # extremely rarely and is not useful anyway)

            res1 = space.is_true(space.eq(w_code1, w_code2))
            res2 = space.is_true(space.eq(w_code2, w_code1))
            if res1:
                # if the code objects are equal, the hash should be the same
                h1 = space.int_w(w_code1.descr_code__hash__())
                h2 = space.int_w(w_code2.descr_code__hash__())
                assert h1 == h2

            # check reflexivity
            assert res1 == res2


            # wrapping as code doesn't change the result
            w_codecode1 = make_code_with_const(w_code1)
            w_codecode2 = make_code_with_const(w_code2)
            assert space.is_true(space.eq(w_codecode1, w_codecode2)) == res1

            # check that tupleization doesn't change the result
            if not space.isinstance_w(w_obj1, space.w_tuple):
                res3 = cmp_code_consts(space.newtuple([space.w_None, w_obj1]),
                                       space.newtuple([space.w_None, w_obj2]))
                assert res3 == res1
            return res1

        assert cmp_code_consts(space.w_None, space.w_None)

        # floats
        assert not cmp_code_consts(space.newfloat(0.0), space.newfloat(-0.0))
        assert cmp_code_consts(space.newfloat(float('nan')), space.newfloat(float('nan')))

        # complex
        assert not cmp_code_consts(space.newcomplex(0.0, 0.0), space.newcomplex(0.0, -0.0))
        assert not cmp_code_consts(space.newcomplex(0.0, 0.0), space.newcomplex(-0.0, 0.0))
        assert not cmp_code_consts(space.newcomplex(0.0, 0.0), space.newcomplex(-0.0, -0.0))
        assert not cmp_code_consts(space.newcomplex(-0.0, 0.0), space.newcomplex(0.0, -0.0))
        assert not cmp_code_consts(space.newcomplex(-0.0, 0.0), space.newcomplex(-0.0, -0.0))
        assert not cmp_code_consts(space.newcomplex(0.0, -0.0), space.newcomplex(-0.0, -0.0))

        # code objects: we compare them by identity, PyPy doesn't share them ever


class AppTestCodeIntrospection:
    def setup_class(cls):
        filename = __file__
        if filename[-3:] != '.py':
            filename = filename[:-1]

        cls.w_file = cls.space.wrap(filename)
        cls.w_CO_NOFREE = cls.space.wrap(consts.CO_NOFREE)

    def test_attributes(self):
        def f(): pass
        def g(x, *y, **z): "docstring"
        assert hasattr(f.__code__, 'co_code')
        assert hasattr(g.__code__, 'co_code')

        testcases = [
            (f.__code__, {'co_name': 'f',
                           'co_names': (),
                           'co_varnames': (),
                           'co_argcount': 0,
                           'co_posonlyargcount': 0,
                           'co_kwonlyargcount': 0,
                           'co_consts': (None,)
                           }),
            (g.__code__, {'co_name': 'g',
                           'co_names': (),
                           'co_varnames': ('x', 'y', 'z'),
                           'co_argcount': 1,
                           'co_posonlyargcount': 0,
                           'co_kwonlyargcount': 0,
                           'co_consts': ("docstring", None),
                           }),
            ]

        import sys
        if hasattr(sys, 'pypy_objspaceclass'): 
            testcases += [
                (abs.__code__, {'co_name': 'abs',
                                 'co_varnames': ('val',),
                                 'co_argcount': 1,
                           'co_posonlyargcount': 0,
                                 'co_kwonlyargcount': 0,
                                 'co_flags': 0,
                                 'co_consts': ("abs(number) -> number\n\nReturn the absolute value of the argument.",),
                                 }),
                (object.__init__.__code__,
                                {#'co_name': '__init__',   XXX getting descr__init__
                                 'co_varnames': ('obj', 'args', 'keywords'),
                                 'co_argcount': 1,
                                 'co_posonlyargcount': 0,
                                 'co_kwonlyargcount': 0,
                                 'co_flags': 0x000C,  # VARARGS|VARKEYWORDS
                                 }),
                ]

        # in PyPy, built-in functions have code objects
        # that emulate some attributes
        for code, expected in testcases:
            assert hasattr(code, '__class__')
            assert not hasattr(code,'__dict__')
            for key, value in expected.items():
                assert getattr(code, key) == value


    def test_posonlyargcount(self):
        """
        def f(a, b, /, c): pass
        assert f.__code__.co_argcount == 3
        assert f.__code__.co_posonlyargcount == 2
        """


    def test_kwonlyargcount(self):
        """
        def f(*args, a, b, **kw): pass
        assert f.__code__.co_kwonlyargcount == 2
        """

    def test_co_names(self):
        src = '''if 1:
        def foo():
            pass

        g = 3

        def f(x, y):
            z = x + y
            foo(g)
'''
        d = {}
        exec(src, d)

        assert list(sorted(d['f'].__code__.co_names)) == ['foo', 'g']

    def test_hash(self):
        d1 = {}
        exec("def f(): pass", d1)
        d2 = {}
        exec("def f(): pass", d2)
        assert d1['f'].__code__ == d2['f'].__code__
        assert hash(d1['f'].__code__) == hash(d2['f'].__code__)

    def test_repr(self):
        def f():
            xxx
        res = repr(f.__code__)
        assert res.startswith("<code object f at 0x")
        assert ', file "%s", line ' % f.__code__.co_filename in res
        assert res.endswith('>')

    def test_code_extra(self):
        assert compile("x = x + 1", 'baz', 'exec').co_flags & self.CO_NOFREE

        d = {}
        exec("""if 1:
        def f():
            "docstring"
            'stuff'
            56
""", d)

        # check for new flag, CO_NOFREE
        assert d['f'].__code__.co_flags & self.CO_NOFREE

        exec("""if 1:
        def f(x):
            def g(y):
                return x+y
            return g
""", d)

        # CO_NESTED
        assert d['f'](4).__code__.co_flags & 0x10
        assert d['f'].__code__.co_flags & 0x10 == 0

    def test_code_eq_non_code(self):
        class A(object):
            def __eq__(self, other):
                return 23
            def __ne__(self, other):
                return 41
        def f(): pass
        assert (f.__code__ == A()) == 23
        assert (f.__code__ != A()) == 41

    def test_issue1844(self):
        import types
        args = (1, 0, 0, 1, 0, 0, b'', (), (), (), '', 'operator', 'operator', 0, b'')
        # previously raised a MemoryError when translated
        types.CodeType(*args)

    def test_replace(self):
        co = compile("x = x + 1", 'baz', 'exec')
        co2 = co.replace(co_flags=co.co_flags | 0x100)
        assert co2.co_name == co.co_name # in theory need to check them all
        assert co2.co_flags == co.co_flags | 0x100

        with raises(TypeError):
            co.replace(1)
        with raises(TypeError):
            co.replace(abc=123)