Skip to content

Commit 80f23bd

Browse files
github-actions[bot]P403n1x87emmettbutler
authored
fix(internal): no lazy bytecode imports [backport 2.1] (#7171)
Backport 8626bd5 from #7151 to 2.1. Remove any lazy bytecode imports that can cause incompatibilities with the module cloning mechanism. Fixes #7144. ## Checklist - [x] Change(s) are motivated and described in the PR description. - [x] Testing strategy is described if automated tests are not included in the PR. - [x] Risk is outlined (performance impact, potential for breakage, maintainability, etc). - [x] Change is maintainable (easy to change, telemetry, documentation). - [x] [Library release note guidelines](https://ddtrace.readthedocs.io/en/stable/releasenotes.html) are followed. If no release note is required, add label `changelog/no-changelog`. - [x] Documentation is included (in-code, generated user docs, [public corp docs](https://github.com/DataDog/documentation/)). - [x] Backport labels are set (if [applicable](https://ddtrace.readthedocs.io/en/latest/contributing.html#backporting)) ## Reviewer Checklist - [x] Title is accurate. - [x] No unnecessary changes are introduced. - [x] Description motivates each change. - [x] Avoids breaking [API](https://ddtrace.readthedocs.io/en/stable/versioning.html#interfaces) changes unless absolutely necessary. - [x] Testing strategy adequately addresses listed risk(s). - [x] Change is maintainable (easy to change, telemetry, documentation). - [x] Release note makes sense to a user of the library. - [x] Reviewer has explicitly acknowledged and discussed the performance implications of this PR as reported in the benchmarks PR comment. - [x] Backport labels are set in a manner that is consistent with the [release branch maintenance policy](https://ddtrace.readthedocs.io/en/latest/contributing.html#backporting) - [x] If this PR touches code that signs or publishes builds or packages, or handles credentials of any kind, I've requested a review from `@DataDog/security-design-and-guidance`. - [x] This PR doesn't touch any of that. Co-authored-by: Gabriele N. Tornetta <[email protected]> Co-authored-by: Emmett Butler <[email protected]>
1 parent 43c2cfb commit 80f23bd

File tree

4 files changed

+92
-107
lines changed

4 files changed

+92
-107
lines changed

ddtrace/internal/wrapping/__init__.py

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414
except ImportError:
1515
from typing_extensions import Protocol # type: ignore[assignment]
1616

17+
import bytecode as bc
1718
from bytecode import Bytecode
18-
from bytecode import CompilerFlags
1919
from bytecode import Instr
2020

2121
from ddtrace.internal.compat import PYTHON_VERSION_INFO as PY
@@ -38,9 +38,7 @@ def __call__(self, *args, **kwargs):
3838

3939
def _add(lineno):
4040
if PY >= (3, 11):
41-
from bytecode import BinaryOp
42-
43-
return Instr("BINARY_OP", BinaryOp.ADD, lineno=lineno)
41+
return Instr("BINARY_OP", bc.BinaryOp.ADD, lineno=lineno)
4442

4543
return Instr("INPLACE_ADD", lineno=lineno)
4644

@@ -111,8 +109,8 @@ def wrap_bytecode(wrapper, wrapped):
111109

112110
code = wrapped.__code__
113111
lineno = code.co_firstlineno + FIRSTLINENO_OFFSET
114-
varargs = bool(code.co_flags & CompilerFlags.VARARGS)
115-
varkwargs = bool(code.co_flags & CompilerFlags.VARKEYWORDS)
112+
varargs = bool(code.co_flags & bc.CompilerFlags.VARARGS)
113+
varkwargs = bool(code.co_flags & bc.CompilerFlags.VARKEYWORDS)
116114
nargs = code.co_argcount
117115
argnames = code.co_varnames[:nargs]
118116
try:
@@ -137,9 +135,7 @@ def wrap_bytecode(wrapper, wrapped):
137135
]
138136

139137
if code.co_cellvars:
140-
from bytecode import CellVar
141-
142-
instrs[0:0] = [Instr("MAKE_CELL", CellVar(_), lineno=lineno) for _ in code.co_cellvars]
138+
instrs[0:0] = [Instr("MAKE_CELL", bc.CellVar(_), lineno=lineno) for _ in code.co_cellvars]
143139

144140
if code.co_freevars:
145141
instrs.insert(0, Instr("COPY_FREE_VARS", len(code.co_freevars), lineno=lineno))
@@ -148,7 +144,7 @@ def wrap_bytecode(wrapper, wrapped):
148144
if nargs:
149145
instrs.extend(
150146
[
151-
Instr("LOAD_DEREF", CellVar(argname), lineno=lineno)
147+
Instr("LOAD_DEREF", bc.CellVar(argname), lineno=lineno)
152148
if PY >= (3, 11) and argname in code.co_cellvars
153149
else Instr("LOAD_FAST", argname, lineno=lineno)
154150
for argname in argnames
@@ -192,7 +188,7 @@ def wrap_bytecode(wrapper, wrapped):
192188

193189
# If the function has special flags set, like the generator, async generator
194190
# or coroutine, inject unraveling code before the return opcode.
195-
if CompilerFlags.GENERATOR & code.co_flags and not (CompilerFlags.COROUTINE & code.co_flags):
191+
if bc.CompilerFlags.GENERATOR & code.co_flags and not (bc.CompilerFlags.COROUTINE & code.co_flags):
196192
wrap_generator(instrs, code, lineno)
197193
elif PY3:
198194
wrap_async(instrs, code, lineno)
@@ -245,7 +241,7 @@ def wrap(f, wrapper):
245241
nargs += code.kwonlyargcount
246242
except AttributeError:
247243
pass
248-
nargs += bool(code.flags & CompilerFlags.VARARGS) + bool(code.flags & CompilerFlags.VARKEYWORDS)
244+
nargs += bool(code.flags & bc.CompilerFlags.VARARGS) + bool(code.flags & bc.CompilerFlags.VARKEYWORDS)
249245
code.argnames = f.__code__.co_varnames[:nargs]
250246

251247
f.__code__ = code.to_code()

ddtrace/internal/wrapping/asyncs.py

Lines changed: 47 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
import sys
22

3-
from bytecode import Compare
4-
from bytecode import CompilerFlags
3+
import bytecode as bc
54
from bytecode import Instr
6-
from bytecode import Label
75

86
from ddtrace.internal.compat import PYTHON_VERSION_INFO as PY
97

@@ -33,16 +31,16 @@
3331
if PY >= (3, 12):
3432

3533
def wrap_async(instrs, code, lineno):
36-
if CompilerFlags.COROUTINE & code.co_flags:
34+
if bc.CompilerFlags.COROUTINE & code.co_flags:
3735
# DEV: This is just
3836
# >>> return await wrapper(wrapped, args, kwargs)
3937
instrs[0:0] = [
4038
Instr("RETURN_GENERATOR", lineno=lineno),
4139
Instr("POP_TOP", lineno=lineno),
4240
]
4341

44-
send = Label()
45-
send_jb = Label()
42+
send = bc.Label()
43+
send_jb = bc.Label()
4644

4745
instrs[-1:-1] = [
4846
Instr("GET_AWAITABLE", 0, lineno=lineno),
@@ -55,29 +53,25 @@ def wrap_async(instrs, code, lineno):
5553
send,
5654
]
5755

58-
elif CompilerFlags.ASYNC_GENERATOR & code.co_flags:
59-
from bytecode import Intrinsic1Op
60-
from bytecode import TryBegin
61-
from bytecode import TryEnd
62-
56+
elif bc.CompilerFlags.ASYNC_GENERATOR & code.co_flags:
6357
instrs[0:0] = [
6458
Instr("RETURN_GENERATOR", lineno=lineno),
6559
Instr("POP_TOP", lineno=lineno),
6660
]
6761

68-
stopiter = Label()
69-
loop = Label()
70-
genexit = Label()
71-
exc = Label()
72-
propagate = Label()
73-
_yield = Label()
62+
stopiter = bc.Label()
63+
loop = bc.Label()
64+
genexit = bc.Label()
65+
exc = bc.Label()
66+
propagate = bc.Label()
67+
_yield = bc.Label()
7468

75-
try_stopiter = TryBegin(stopiter, push_lasti=False)
76-
try_stopiter_2 = TryBegin(stopiter, push_lasti=False)
77-
try_except = TryBegin(genexit, push_lasti=True)
69+
try_stopiter = bc.TryBegin(stopiter, push_lasti=False)
70+
try_stopiter_2 = bc.TryBegin(stopiter, push_lasti=False)
71+
try_except = bc.TryBegin(genexit, push_lasti=True)
7872

79-
send = [Label() for _ in range(3)]
80-
send_jb = [Label() for _ in range(3)]
73+
send = [bc.Label() for _ in range(3)]
74+
send_jb = [bc.Label() for _ in range(3)]
8175

8276
instrs[-1:] = [
8377
try_stopiter,
@@ -93,15 +87,15 @@ def wrap_async(instrs, code, lineno):
9387
Instr("LOAD_CONST", None, lineno=lineno),
9488
send_jb[0],
9589
Instr("SEND", send[0], lineno=lineno),
96-
TryEnd(try_stopiter),
90+
bc.TryEnd(try_stopiter),
9791
try_except,
9892
Instr("YIELD_VALUE", 3, lineno=lineno),
9993
Instr("RESUME", 3, lineno=lineno),
10094
Instr("JUMP_BACKWARD_NO_INTERRUPT", send_jb[0], lineno=lineno),
10195
send[0],
10296
Instr("END_SEND", lineno=lineno),
10397
_yield,
104-
Instr("CALL_INTRINSIC_1", Intrinsic1Op.INTRINSIC_ASYNC_GEN_WRAP, lineno=lineno),
98+
Instr("CALL_INTRINSIC_1", bc.Intrinsic1Op.INTRINSIC_ASYNC_GEN_WRAP, lineno=lineno),
10599
Instr("YIELD_VALUE", 3, lineno=lineno),
106100
Instr("RESUME", 1, lineno=lineno),
107101
Instr("PUSH_NULL", lineno=lineno),
@@ -110,7 +104,7 @@ def wrap_async(instrs, code, lineno):
110104
Instr("SWAP", 2, lineno=lineno),
111105
Instr("CALL", 1, lineno=lineno),
112106
Instr("JUMP_BACKWARD", loop, lineno=lineno),
113-
TryEnd(try_except),
107+
bc.TryEnd(try_except),
114108
try_stopiter_2,
115109
genexit, # except GeneratorExit:
116110
Instr("PUSH_EXC_INFO", lineno=lineno),
@@ -154,7 +148,7 @@ def wrap_async(instrs, code, lineno):
154148
Instr("SWAP", 2, lineno=lineno),
155149
Instr("POP_EXCEPT", lineno=lineno),
156150
Instr("JUMP_BACKWARD", _yield, lineno=lineno),
157-
TryEnd(try_stopiter_2),
151+
bc.TryEnd(try_stopiter_2),
158152
stopiter, # except StopAsyncIteration:
159153
Instr("PUSH_EXC_INFO", lineno=lineno),
160154
Instr("LOAD_CONST", StopAsyncIteration, lineno=lineno),
@@ -171,16 +165,16 @@ def wrap_async(instrs, code, lineno):
171165
elif PY >= (3, 11):
172166

173167
def wrap_async(instrs, code, lineno):
174-
if CompilerFlags.COROUTINE & code.co_flags:
168+
if bc.CompilerFlags.COROUTINE & code.co_flags:
175169
# DEV: This is just
176170
# >>> return await wrapper(wrapped, args, kwargs)
177171
instrs[0:0] = [
178172
Instr("RETURN_GENERATOR", lineno=lineno),
179173
Instr("POP_TOP", lineno=lineno),
180174
]
181175

182-
send = Label()
183-
send_jb = Label()
176+
send = bc.Label()
177+
send_jb = bc.Label()
184178

185179
instrs[-1:-1] = [
186180
Instr("GET_AWAITABLE", 0, lineno=lineno),
@@ -193,28 +187,25 @@ def wrap_async(instrs, code, lineno):
193187
send,
194188
]
195189

196-
elif CompilerFlags.ASYNC_GENERATOR & code.co_flags:
197-
from bytecode import TryBegin
198-
from bytecode import TryEnd
199-
190+
elif bc.CompilerFlags.ASYNC_GENERATOR & code.co_flags:
200191
instrs[0:0] = [
201192
Instr("RETURN_GENERATOR", lineno=lineno),
202193
Instr("POP_TOP", lineno=lineno),
203194
]
204195

205-
stopiter = Label()
206-
loop = Label()
207-
genexit = Label()
208-
exc = Label()
209-
propagate = Label()
210-
_yield = Label()
196+
stopiter = bc.Label()
197+
loop = bc.Label()
198+
genexit = bc.Label()
199+
exc = bc.Label()
200+
propagate = bc.Label()
201+
_yield = bc.Label()
211202

212-
try_stopiter = TryBegin(stopiter, push_lasti=False)
213-
try_stopiter_2 = TryBegin(stopiter, push_lasti=False)
214-
try_except = TryBegin(genexit, push_lasti=True)
203+
try_stopiter = bc.TryBegin(stopiter, push_lasti=False)
204+
try_stopiter_2 = bc.TryBegin(stopiter, push_lasti=False)
205+
try_except = bc.TryBegin(genexit, push_lasti=True)
215206

216-
send = [Label() for _ in range(3)]
217-
send_jb = [Label() for _ in range(3)]
207+
send = [bc.Label() for _ in range(3)]
208+
send_jb = [bc.Label() for _ in range(3)]
218209

219210
instrs[-1:] = [
220211
try_stopiter,
@@ -231,7 +222,7 @@ def wrap_async(instrs, code, lineno):
231222
Instr("LOAD_CONST", None, lineno=lineno),
232223
send_jb[0],
233224
Instr("SEND", send[0], lineno=lineno),
234-
TryEnd(try_stopiter),
225+
bc.TryEnd(try_stopiter),
235226
try_except,
236227
Instr("YIELD_VALUE", lineno=lineno),
237228
Instr("RESUME", 3, lineno=lineno),
@@ -248,7 +239,7 @@ def wrap_async(instrs, code, lineno):
248239
Instr("PRECALL", 1, lineno=lineno),
249240
Instr("CALL", 1, lineno=lineno),
250241
Instr("JUMP_BACKWARD", loop, lineno=lineno),
251-
TryEnd(try_except),
242+
bc.TryEnd(try_except),
252243
try_stopiter_2,
253244
genexit, # except GeneratorExit:
254245
Instr("PUSH_EXC_INFO", lineno=lineno),
@@ -293,7 +284,7 @@ def wrap_async(instrs, code, lineno):
293284
Instr("SWAP", 2, lineno=lineno),
294285
Instr("POP_EXCEPT", lineno=lineno),
295286
Instr("JUMP_BACKWARD", _yield, lineno=lineno),
296-
TryEnd(try_stopiter_2),
287+
bc.TryEnd(try_stopiter_2),
297288
stopiter, # except StopAsyncIteration:
298289
Instr("PUSH_EXC_INFO", lineno=lineno),
299290
Instr("LOAD_CONST", StopAsyncIteration, lineno=lineno),
@@ -313,7 +304,7 @@ def wrap_async(instrs, code, lineno):
313304
def _compare_exc(label, lineno):
314305
"""Compat helper for comparing exceptions."""
315306
if PY < (3, 9):
316-
return Instr("COMPARE_OP", Compare.EXC_MATCH, lineno=lineno)
307+
return Instr("COMPARE_OP", bc.Compare.EXC_MATCH, lineno=lineno)
317308
return Instr("JUMP_IF_NOT_EXC_MATCH", label, lineno=lineno)
318309

319310
def _jump_if_false(label, lineno):
@@ -336,21 +327,21 @@ def _setup_block(label, lineno):
336327
return Instr("SETUP_FINALLY", label, lineno=lineno)
337328

338329
def wrap_async(instrs, code, lineno):
339-
if CompilerFlags.COROUTINE & code.co_flags:
330+
if bc.CompilerFlags.COROUTINE & code.co_flags:
340331
# DEV: This is just
341332
# >>> return await wrapper(wrapped, args, kwargs)
342333
instrs[-1:-1] = [
343334
Instr("GET_AWAITABLE", lineno=lineno),
344335
Instr("LOAD_CONST", None, lineno=lineno),
345336
Instr("YIELD_FROM", lineno=lineno),
346337
]
347-
elif CompilerFlags.ASYNC_GENERATOR & code.co_flags:
348-
stopiter = Label()
349-
loop = Label()
350-
genexit = Label()
351-
exc = Label()
352-
propagate = Label()
353-
_yield = Label()
338+
elif bc.CompilerFlags.ASYNC_GENERATOR & code.co_flags:
339+
stopiter = bc.Label()
340+
loop = bc.Label()
341+
genexit = bc.Label()
342+
exc = bc.Label()
343+
propagate = bc.Label()
344+
_yield = bc.Label()
354345

355346
instrs[-1:] = [
356347
_setup_block(stopiter, lineno=lineno),

0 commit comments

Comments
 (0)