1 From 76b56ff67b20729ab14630ce0473e68bb3e5d267 Mon Sep 17 00:00:00 2001
2 From: Stefano Rivera <stefano@rivera.za.net>
3 Date: Tue, 6 Dec 2022 07:50:33 -0400
4 Subject: [PATCH 01/21] Declare support for Python 3.11
8 1 file changed, 3 insertions(+), 2 deletions(-)
10 diff --git a/setup.py b/setup.py
11 index 342e8e3d..fb2b4428 100644
14 @@ -70,6 +70,7 @@ def test_suite():
15 'Programming Language :: Python :: 3.8',
16 'Programming Language :: Python :: 3.9',
17 'Programming Language :: Python :: 3.10',
18 + 'Programming Language :: Python :: 3.11',
19 'Programming Language :: Python :: Implementation :: PyPy',
20 'Topic :: Software Development :: Libraries',
22 @@ -110,8 +111,8 @@ def test_suite():
24 if __name__ == "__main__":
25 pv = sys.version_info[:2]
26 - if pv not in ((3, 6), (3, 7), (3, 8), (3, 9), (3, 10)):
27 - s = "Sorry, but %s %s requires Python of one of the following versions: 3.6-3.10." \
28 + if pv not in ((3, 6), (3, 7), (3, 8), (3, 9), (3, 10), (3, 11)):
29 + s = "Sorry, but %s %s requires Python of one of the following versions: 3.6-3.11." \
30 " You have version %s"
31 print(s % (name, version, sys.version.split(' ', 1)[0]))
34 From df800959fd5ec367df438c686265675e386f3434 Mon Sep 17 00:00:00 2001
35 From: Stefano Rivera <stefano@rivera.za.net>
36 Date: Tue, 6 Dec 2022 14:08:39 -0400
37 Subject: [PATCH 02/21] Add some simpler tests to help find Decompiler mistakes
40 pony/orm/tests/test_decompiler.py | 78 ++++++++++++++++++++++++++++++-
41 1 file changed, 77 insertions(+), 1 deletion(-)
43 diff --git a/pony/orm/tests/test_decompiler.py b/pony/orm/tests/test_decompiler.py
44 index 2a181806..189f611a 100644
45 --- a/pony/orm/tests/test_decompiler.py
46 +++ b/pony/orm/tests/test_decompiler.py
52 from pony.orm.decompiling import Decompiler
53 from pony.orm.asttranslation import ast2src
54 @@ -93,7 +95,81 @@ def get_condition_values(cond):
57 class TestDecompiler(unittest.TestCase):
59 + def assertDecompilesTo(self, src, expected):
60 + code = compile(src, '<?>', 'eval').co_consts[0]
62 + print(dis.dis(code))
63 + dc = Decompiler(code)
64 + expected = textwrap.dedent(expected).strip()
66 + self.assertMultiLineEqual(expected, ast.dump(dc.ast, indent=2))
68 + def test_ast1(self):
69 + self.assertDecompilesTo(
70 + '(a for a in [] if x and y and z and j)',
73 + elt=Name(id='a', ctx=Load()),
76 + target=Name(id='a', ctx=Store()),
77 + iter=Name(id='.0', ctx=Load()),
82 + Name(id='x', ctx=Load()),
83 + Name(id='y', ctx=Load()),
84 + Name(id='z', ctx=Load()),
85 + Name(id='j', ctx=Load())])],
89 + def test_ast2(self):
90 + self.assertDecompilesTo(
91 + 'lambda x, y, z, j: (x and y and z and j)',
96 + Name(id='x', ctx=Load()),
97 + Name(id='y', ctx=Load()),
98 + Name(id='z', ctx=Load()),
99 + Name(id='j', ctx=Load())])
102 + def test_ast3(self):
103 + self.assertDecompilesTo(
104 + '(m for m in [] if x and y and z and j for n in [] if x and y and z and j)',
107 + elt=Name(id='m', ctx=Load()),
110 + target=Name(id='m', ctx=Store()),
111 + iter=Name(id='.0', ctx=Load()),
116 + Name(id='x', ctx=Load()),
117 + Name(id='y', ctx=Load()),
118 + Name(id='z', ctx=Load()),
119 + Name(id='j', ctx=Load())])],
122 + target=Name(id='n', ctx=Store()),
123 + iter=Constant(value=()),
128 + Name(id='x', ctx=Load()),
129 + Name(id='y', ctx=Load()),
130 + Name(id='z', ctx=Load()),
131 + Name(id='j', ctx=Load())])],
136 for i, gen in enumerate(generate_gens()):
138 From 7cb3fe95dd6f263d46ee852d34e3ca3f3f58d69f Mon Sep 17 00:00:00 2001
139 From: Stefano Rivera <stefano@rivera.za.net>
140 Date: Tue, 6 Dec 2022 07:58:15 -0400
141 Subject: [PATCH 03/21] Add support for JUMP_NO_INTERRUPT (bpo-46409)
144 pony/orm/decompiling.py | 3 ++-
145 1 file changed, 2 insertions(+), 1 deletion(-)
147 diff --git a/pony/orm/decompiling.py b/pony/orm/decompiling.py
148 index 62e1ff9f..ad3c7e9b 100644
149 --- a/pony/orm/decompiling.py
150 +++ b/pony/orm/decompiling.py
151 @@ -209,7 +209,8 @@ def get_instructions(decompiler):
153 if opname == 'FOR_ITER':
154 decompiler.for_iter_pos = decompiler.pos
155 - if opname == 'JUMP_ABSOLUTE' and arg[0] == decompiler.for_iter_pos:
156 + if (opname in ('JUMP_ABSOLUTE', 'JUMP_NO_INTERRUPT')
157 + and arg[0] == decompiler.for_iter_pos):
158 decompiler.abs_jump_to_top = decompiler.pos
162 From 95a7a89769d8a43be34f77adcd6cf2a8a710db78 Mon Sep 17 00:00:00 2001
163 From: Stefano Rivera <stefano@rivera.za.net>
164 Date: Tue, 6 Dec 2022 08:05:02 -0400
165 Subject: [PATCH 04/21] Add support for RETURN_GENERATOR (bpo-46409)
168 pony/orm/decompiling.py | 3 +++
169 1 file changed, 3 insertions(+)
171 diff --git a/pony/orm/decompiling.py b/pony/orm/decompiling.py
172 index ad3c7e9b..6c2c3a33 100644
173 --- a/pony/orm/decompiling.py
174 +++ b/pony/orm/decompiling.py
175 @@ -705,6 +705,9 @@ def RETURN_VALUE(decompiler):
176 expr = decompiler.stack.pop()
177 return simplify(expr)
179 + def RETURN_GENERATOR(decompiler):
182 def ROT_TWO(decompiler):
183 tos = decompiler.stack.pop()
184 tos1 = decompiler.stack.pop()
186 From 0e1d55146535368a7ecfae1c7b305facb82445bf Mon Sep 17 00:00:00 2001
187 From: Stefano Rivera <stefano@rivera.za.net>
188 Date: Tue, 6 Dec 2022 09:45:06 -0400
189 Subject: [PATCH 05/21] Add support for 3.11's POP_JUMP_* (bpo-47120)
192 pony/orm/decompiling.py | 7 ++++++-
193 1 file changed, 6 insertions(+), 1 deletion(-)
195 diff --git a/pony/orm/decompiling.py b/pony/orm/decompiling.py
196 index 6c2c3a33..7788e061 100644
197 --- a/pony/orm/decompiling.py
198 +++ b/pony/orm/decompiling.py
199 @@ -195,7 +195,8 @@ def get_instructions(decompiler):
201 arg = [code.co_names[oparg]]
203 - arg = [i + oparg * (2 if PY310 else 1)]
204 + arg = [i + oparg * (2 if PY310 else 1)
205 + * (-1 if 'BACKWARD' in opname else 1)]
207 arg = [code.co_varnames[oparg]]
208 elif op in hascompare:
209 @@ -693,6 +694,10 @@ def MAKE_FUNCTION(decompiler, argc):
211 return ast.Lambda(args, func_decompiler.ast)
213 + POP_JUMP_BACKWARD_IF_FALSE = JUMP_IF_FALSE
214 + POP_JUMP_BACKWARD_IF_TRUE = JUMP_IF_TRUE
215 + POP_JUMP_FORWARD_IF_FALSE = JUMP_IF_FALSE
216 + POP_JUMP_FORWARD_IF_TRUE = JUMP_IF_TRUE
217 POP_JUMP_IF_FALSE = JUMP_IF_FALSE
218 POP_JUMP_IF_TRUE = JUMP_IF_TRUE
221 From 84120f593f1ccc81d5a32cec7e8aec17999577d3 Mon Sep 17 00:00:00 2001
222 From: Stefano Rivera <stefano@rivera.za.net>
223 Date: Tue, 6 Dec 2022 09:45:45 -0400
224 Subject: [PATCH 06/21] Add support for CACHE (GH-90997)
227 pony/orm/decompiling.py | 3 +++
228 1 file changed, 3 insertions(+)
230 diff --git a/pony/orm/decompiling.py b/pony/orm/decompiling.py
231 index 7788e061..630c88bc 100644
232 --- a/pony/orm/decompiling.py
233 +++ b/pony/orm/decompiling.py
234 @@ -396,6 +396,9 @@ def _call_function(decompiler, args, keywords=None):
236 return ast.Call(tos, args, keywords)
238 + def CACHE(decompiler):
241 def CALL_FUNCTION_VAR(decompiler, argc):
242 return decompiler.CALL_FUNCTION(argc, decompiler.stack.pop())
245 From abcd8c9ae9a76d370a3f322257a177dabf8243b3 Mon Sep 17 00:00:00 2001
246 From: Stefano Rivera <stefano@rivera.za.net>
247 Date: Tue, 6 Dec 2022 09:46:52 -0400
248 Subject: [PATCH 07/21] Add support for PRECALL (bpo-44525)
251 pony/orm/decompiling.py | 3 +++
252 1 file changed, 3 insertions(+)
254 diff --git a/pony/orm/decompiling.py b/pony/orm/decompiling.py
255 index 630c88bc..125211bf 100644
256 --- a/pony/orm/decompiling.py
257 +++ b/pony/orm/decompiling.py
258 @@ -707,6 +707,9 @@ def MAKE_FUNCTION(decompiler, argc):
259 def POP_TOP(decompiler):
262 + def PRECALL(decompiler, argc):
265 def RETURN_VALUE(decompiler):
266 if decompiler.next_pos != decompiler.end:
267 throw(DecompileError)
269 From 536b6184e49a28e0f9ffbc17de49552fe21d68dc Mon Sep 17 00:00:00 2001
270 From: Stefano Rivera <stefano@rivera.za.net>
271 Date: Tue, 6 Dec 2022 09:47:00 -0400
272 Subject: [PATCH 08/21] Add support for RESUME (bpo-45923)
275 pony/orm/decompiling.py | 3 +++
276 1 file changed, 3 insertions(+)
278 diff --git a/pony/orm/decompiling.py b/pony/orm/decompiling.py
279 index 125211bf..c3ebd403 100644
280 --- a/pony/orm/decompiling.py
281 +++ b/pony/orm/decompiling.py
282 @@ -719,6 +719,9 @@ def RETURN_VALUE(decompiler):
283 def RETURN_GENERATOR(decompiler):
286 + def RESUME(decompiler, where):
289 def ROT_TWO(decompiler):
290 tos = decompiler.stack.pop()
291 tos1 = decompiler.stack.pop()
293 From 740257657ae6bff2324b63a497b782e1ffa440b6 Mon Sep 17 00:00:00 2001
294 From: Stefano Rivera <stefano@rivera.za.net>
295 Date: Tue, 6 Dec 2022 09:47:16 -0400
296 Subject: [PATCH 09/21] Add support for CALL and KW_NAMES (bpo-46329)
299 pony/orm/decompiling.py | 25 +++++++++++++++++++++++++
300 1 file changed, 25 insertions(+)
302 diff --git a/pony/orm/decompiling.py b/pony/orm/decompiling.py
303 index c3ebd403..4ac1b48e 100644
304 --- a/pony/orm/decompiling.py
305 +++ b/pony/orm/decompiling.py
306 @@ -150,6 +150,7 @@ def __init__(decompiler, code, start=0, end=None):
307 decompiler.conditions_end = 0
308 decompiler.instructions = []
309 decompiler.instructions_map = {}
310 + decompiler.kw_names = None
311 decompiler.or_jumps = set()
312 decompiler.get_instructions()
313 decompiler.analyze_jumps()
314 @@ -399,6 +400,26 @@ def _call_function(decompiler, args, keywords=None):
315 def CACHE(decompiler):
318 + def CALL(decompiler, argc):
319 + values = decompiler.pop_items(argc)
321 + keys = decompiler.kw_names
322 + decompiler.kw_names = None
327 + args = values[:-len(keys)]
328 + keywords = [ast.keyword(k, v) for k, v in zip(keys, values[-len(keys):])]
330 + self = decompiler.stack.pop()
331 + callable_ = decompiler.stack.pop()
332 + if callable_ is None:
335 + args.insert(0, self)
336 + return ast.Call(callable_, args, keywords)
338 def CALL_FUNCTION_VAR(decompiler, argc):
339 return decompiler.CALL_FUNCTION(argc, decompiler.stack.pop())
341 @@ -601,6 +622,10 @@ def JUMP_FORWARD(decompiler, endpos):
342 decompiler.targets[endpos] = if_exp
345 + def KW_NAMES(decompiler, kw_names):
347 + decompiler.kw_names = kw_names
349 def IS_OP(decompiler, invert):
350 return decompiler.COMPARE_OP('is not' if invert else 'is')
353 From 0a26047efd0b083ce93eeaddf2cbd6de569617f6 Mon Sep 17 00:00:00 2001
354 From: Stefano Rivera <stefano@rivera.za.net>
355 Date: Tue, 6 Dec 2022 11:39:11 -0400
356 Subject: [PATCH 10/21] In Python 3.11, MAKE_FUNCTION gets the qualname from
357 the code object (bpo-44530)
360 pony/orm/decompiling.py | 3 ++-
361 1 file changed, 2 insertions(+), 1 deletion(-)
363 diff --git a/pony/orm/decompiling.py b/pony/orm/decompiling.py
364 index 4ac1b48e..91718e53 100644
365 --- a/pony/orm/decompiling.py
366 +++ b/pony/orm/decompiling.py
367 @@ -686,7 +686,8 @@ def MAKE_CLOSURE(decompiler, argc):
368 def MAKE_FUNCTION(decompiler, argc):
370 if sys.version_info >= (3, 6):
371 - qualname = decompiler.stack.pop()
372 + if sys.version_info < (3, 11):
373 + qualname = decompiler.stack.pop()
374 tos = decompiler.stack.pop()
376 func_closure = decompiler.stack.pop()
378 From a03eb4543f2b0bf2c5f3c1d073ddb8875784d75c Mon Sep 17 00:00:00 2001
379 From: Stefano Rivera <stefano@rivera.za.net>
380 Date: Tue, 6 Dec 2022 12:08:30 -0400
381 Subject: [PATCH 11/21] In Python 3.11 LOAD_GLOBAL can push a NULL onto the
385 pony/orm/decompiling.py | 14 ++++++++++++--
386 1 file changed, 12 insertions(+), 2 deletions(-)
388 diff --git a/pony/orm/decompiling.py b/pony/orm/decompiling.py
389 index 91718e53..ce32d839 100644
390 --- a/pony/orm/decompiling.py
391 +++ b/pony/orm/decompiling.py
392 @@ -161,6 +161,7 @@ def __init__(decompiler, code, start=0, end=None):
393 throw(DecompileError, 'Compiled code should represent a single expression')
394 def get_instructions(decompiler):
395 PY36 = sys.version_info >= (3, 6)
396 + PY311 = sys.version_info >= (3, 11)
398 code = decompiler.code
399 co_code = code.co_code
400 @@ -194,7 +195,14 @@ def get_instructions(decompiler):
402 arg = [code.co_consts[oparg]]
404 - arg = [code.co_names[oparg]]
405 + if opname == 'LOAD_GLOBAL':
408 + push_null = oparg & 1
410 + arg = [code.co_names[oparg], push_null]
412 + arg = [code.co_names[oparg]]
414 arg = [i + oparg * (2 if PY310 else 1)
415 * (-1 if 'BACKWARD' in opname else 1)]
416 @@ -666,7 +674,9 @@ def LOAD_FAST(decompiler, varname):
417 decompiler.names.add(varname)
418 return ast.Name(varname, ast.Load())
420 - def LOAD_GLOBAL(decompiler, varname):
421 + def LOAD_GLOBAL(decompiler, varname, push_null):
423 + decompiler.stack.append(None)
424 decompiler.names.add(varname)
425 return ast.Name(varname, ast.Load())
428 From 0eed3fdb7ab7b441bd8bd7cca7f0d28310ef0ff9 Mon Sep 17 00:00:00 2001
429 From: Stefano Rivera <stefano@rivera.za.net>
430 Date: Tue, 6 Dec 2022 14:54:53 -0400
431 Subject: [PATCH 12/21] Free variable offsets change in Python 3.11 (bpo-43693)
434 pony/orm/decompiling.py | 2 ++
435 1 file changed, 2 insertions(+)
437 diff --git a/pony/orm/decompiling.py b/pony/orm/decompiling.py
438 index ce32d839..e2647af1 100644
439 --- a/pony/orm/decompiling.py
440 +++ b/pony/orm/decompiling.py
441 @@ -211,6 +211,8 @@ def get_instructions(decompiler):
442 elif op in hascompare:
443 arg = [cmp_op[oparg]]
446 + oparg -= len(code.co_varnames)
449 arg = [oparg * (2 if PY310 else 1)]
451 From b117f2415a4ed5e850388f5a3cbaad06cdb40b88 Mon Sep 17 00:00:00 2001
452 From: Stefano Rivera <stefano@rivera.za.net>
453 Date: Tue, 6 Dec 2022 14:56:28 -0400
454 Subject: [PATCH 13/21] Add support for COPY_FREE_VARS (bpo-44525)
457 pony/orm/decompiling.py | 3 +++
458 1 file changed, 3 insertions(+)
460 diff --git a/pony/orm/decompiling.py b/pony/orm/decompiling.py
461 index e2647af1..abcfeab2 100644
462 --- a/pony/orm/decompiling.py
463 +++ b/pony/orm/decompiling.py
464 @@ -491,6 +491,9 @@ def COMPARE_OP(decompiler, op):
465 op = operator_mapping[op]()
466 return ast.Compare(oper1, [op], [oper2])
468 + def COPY_FREE_VARS(decompiler, n):
471 def CONTAINS_OP(decompiler, invert):
472 return decompiler.COMPARE_OP('not in' if invert else 'in')
475 From c0436ca293ce5ecdedc691cd63fdefe88e97c6a8 Mon Sep 17 00:00:00 2001
476 From: Stefano Rivera <stefano@rivera.za.net>
477 Date: Tue, 6 Dec 2022 15:24:08 -0400
478 Subject: [PATCH 14/21] Add support for BINARY_OP (bpo-45636)
481 pony/orm/decompiling.py | 32 ++++++++++++++++++++++++++++++++
482 1 file changed, 32 insertions(+)
484 diff --git a/pony/orm/decompiling.py b/pony/orm/decompiling.py
485 index abcfeab2..d278000b 100644
486 --- a/pony/orm/decompiling.py
487 +++ b/pony/orm/decompiling.py
489 from opcode import opname as opnames, HAVE_ARGUMENT, EXTENDED_ARG, cmp_op
490 from opcode import hasconst, hasname, hasjrel, haslocal, hascompare, hasfree, hasjabs
491 from collections import defaultdict
493 + from opcode import _nb_ops as nb_ops
497 #from pony.thirdparty.compiler import ast, parse
499 @@ -313,6 +317,34 @@ def store(decompiler, node):
500 BINARY_TRUE_DIVIDE = BINARY_DIVIDE
501 BINARY_MODULO = binop(ast.Mod)
503 + def BINARY_OP(decompiler, opcode):
504 + opname, symbol = nb_ops[opcode]
505 + inplace = opname.startswith('NB_INPLACE_')
506 + opname = opname.split('_', 2 if inplace else 1)[-1]
511 + "FLOOR_DIVIDE": ast.FloorDiv,
512 + "LSHIFT": ast.LShift,
513 + "MATRIX_MULTIPLY": ast.MatMult,
514 + "MULTIPLY": ast.Mult,
515 + "REMAINDER": ast.Mod,
518 + "RSHIFT": ast.RShift,
519 + "SUBTRACT": ast.Sub,
520 + "TRUE_DIVIDE": ast.Div,
524 + oper2 = decompiler.stack.pop()
525 + oper1 = decompiler.stack.pop()
526 + r = ast.BinOp(left=oper1, op=op(), right=oper2)
528 + r = ast.Name(oper1, r)
531 def BINARY_SUBSCR(decompiler):
532 node2 = decompiler.stack.pop()
533 node1 = decompiler.stack.pop()
535 From 7d3c17693f73f6fcad87a63d005f8319d6387fb5 Mon Sep 17 00:00:00 2001
536 From: Stefano Rivera <stefano@rivera.za.net>
537 Date: Tue, 6 Dec 2022 15:41:46 -0400
538 Subject: [PATCH 15/21] Add support for PUSH_NULL (bpo-46329)
541 pony/orm/decompiling.py | 3 +++
542 1 file changed, 3 insertions(+)
544 diff --git a/pony/orm/decompiling.py b/pony/orm/decompiling.py
545 index d278000b..da98d0f1 100644
546 --- a/pony/orm/decompiling.py
547 +++ b/pony/orm/decompiling.py
548 @@ -783,6 +783,9 @@ def POP_TOP(decompiler):
549 def PRECALL(decompiler, argc):
552 + def PUSH_NULL(decompiler):
553 + decompiler.stack.append(None)
555 def RETURN_VALUE(decompiler):
556 if decompiler.next_pos != decompiler.end:
557 throw(DecompileError)
559 From 9f2e9c273205194fcc770e7539586997684febf0 Mon Sep 17 00:00:00 2001
560 From: =?UTF-8?q?Timo=20R=C3=B6hling?= <timo.roehling@fkie.fraunhofer.de>
561 Date: Wed, 14 Dec 2022 18:34:38 +0100
562 Subject: [PATCH 16/21] Add PY311 compat constant
565 pony/orm/decompiling.py | 5 ++---
566 pony/py23compat.py | 1 +
567 2 files changed, 3 insertions(+), 3 deletions(-)
569 diff --git a/pony/orm/decompiling.py b/pony/orm/decompiling.py
570 index da98d0f1..fbfb74a9 100644
571 --- a/pony/orm/decompiling.py
572 +++ b/pony/orm/decompiling.py
574 from __future__ import absolute_import, print_function, division
575 -from pony.py23compat import PY37, PYPY, PY38, PY39, PY310
576 +from pony.py23compat import PY37, PYPY, PY38, PY39, PY310, PY311
578 import sys, types, inspect
579 from opcode import opname as opnames, HAVE_ARGUMENT, EXTENDED_ARG, cmp_op
580 @@ -165,7 +165,6 @@ def __init__(decompiler, code, start=0, end=None):
581 throw(DecompileError, 'Compiled code should represent a single expression')
582 def get_instructions(decompiler):
583 PY36 = sys.version_info >= (3, 6)
584 - PY311 = sys.version_info >= (3, 11)
586 code = decompiler.code
587 co_code = code.co_code
588 @@ -733,7 +732,7 @@ def MAKE_CLOSURE(decompiler, argc):
589 def MAKE_FUNCTION(decompiler, argc):
591 if sys.version_info >= (3, 6):
592 - if sys.version_info < (3, 11):
594 qualname = decompiler.stack.pop()
595 tos = decompiler.stack.pop()
597 diff --git a/pony/py23compat.py b/pony/py23compat.py
598 index 6deac83f..17caf7e4 100644
599 --- a/pony/py23compat.py
600 +++ b/pony/py23compat.py
602 PY38 = sys.version_info[:2] >= (3, 8)
603 PY39 = sys.version_info[:2] >= (3, 9)
604 PY310 = sys.version_info[:2] >= (3, 10)
605 +PY311 = sys.version_info[:2] >= (3, 11)
610 From b41ef5759949b2b88fc664106e70900bcf7f493f Mon Sep 17 00:00:00 2001
611 From: =?UTF-8?q?Timo=20R=C3=B6hling?= <timo.roehling@fkie.fraunhofer.de>
612 Date: Wed, 14 Dec 2022 18:35:35 +0100
613 Subject: [PATCH 17/21] Fix CALL opcode and handle NULL special cases
616 pony/orm/decompiling.py | 14 +++++++++++---
617 1 file changed, 11 insertions(+), 3 deletions(-)
619 diff --git a/pony/orm/decompiling.py b/pony/orm/decompiling.py
620 index fbfb74a9..e3e2f5b5 100644
621 --- a/pony/orm/decompiling.py
622 +++ b/pony/orm/decompiling.py
623 @@ -448,7 +448,7 @@ def CALL(decompiler, argc):
624 decompiler.kw_names = None
630 args = values[:-len(keys)]
631 keywords = [ast.keyword(k, v) for k, v in zip(keys, values[-len(keys):])]
632 @@ -459,7 +459,8 @@ def CALL(decompiler, argc):
636 - return ast.Call(callable_, args, keywords)
637 + decompiler.stack.append(callable_)
638 + return decompiler._call_function(args, keywords)
640 def CALL_FUNCTION_VAR(decompiler, argc):
641 return decompiler.CALL_FUNCTION(argc, decompiler.stack.pop())
642 @@ -629,6 +630,10 @@ def process_target(decompiler, pos, partial=False):
644 if not decompiler.stack:
646 + if decompiler.stack[-1] is None:
647 + decompiler.stack.pop()
648 + if not decompiler.stack:
650 top2 = decompiler.stack[-1]
651 if isinstance(top2, ast.comprehension):
653 @@ -717,7 +722,10 @@ def LOAD_GLOBAL(decompiler, varname, push_null):
654 return ast.Name(varname, ast.Load())
656 def LOAD_METHOD(decompiler, methname):
657 - return decompiler.LOAD_ATTR(methname)
658 + result = decompiler.LOAD_ATTR(methname)
660 + decompiler.stack.append(None)
663 LOOKUP_METHOD = LOAD_METHOD # For PyPy
666 From 21a01e7356d6d4234a92e78f31d23e4011238aa4 Mon Sep 17 00:00:00 2001
667 From: =?UTF-8?q?Timo=20R=C3=B6hling?= <timo.roehling@fkie.fraunhofer.de>
668 Date: Wed, 14 Dec 2022 18:36:57 +0100
669 Subject: [PATCH 18/21] Add MAKE_CELL opcode
672 pony/orm/decompiling.py | 3 +++
673 1 file changed, 3 insertions(+)
675 diff --git a/pony/orm/decompiling.py b/pony/orm/decompiling.py
676 index e3e2f5b5..a14c2c54 100644
677 --- a/pony/orm/decompiling.py
678 +++ b/pony/orm/decompiling.py
679 @@ -733,6 +733,9 @@ def LOAD_NAME(decompiler, varname):
680 decompiler.names.add(varname)
681 return ast.Name(varname, ast.Load())
683 + def MAKE_CELL(decompiler, freevar):
686 def MAKE_CLOSURE(decompiler, argc):
687 decompiler.stack[-3:-2] = [] # ignore freevars
688 return decompiler.MAKE_FUNCTION(argc)
690 From 592ed4ab682b448d4af8ad6b71d916262277b769 Mon Sep 17 00:00:00 2001
691 From: =?UTF-8?q?Timo=20R=C3=B6hling?= <timo.roehling@fkie.fraunhofer.de>
692 Date: Wed, 14 Dec 2022 18:37:34 +0100
693 Subject: [PATCH 19/21] Add JUMP_IF_NONE and JUMP_IF_NOT_NONE opcodes
696 pony/orm/decompiling.py | 35 +++++++++++++++++++++++++++++++++++
697 1 file changed, 35 insertions(+)
699 diff --git a/pony/orm/decompiling.py b/pony/orm/decompiling.py
700 index a14c2c54..d0397239 100644
701 --- a/pony/orm/decompiling.py
702 +++ b/pony/orm/decompiling.py
703 @@ -614,6 +614,37 @@ def conditional_jump_new(decompiler, endpos, if_true):
704 decompiler.targets.setdefault(endpos, clause)
707 + def conditional_jump_none_impl(decompiler, endpos, negate):
708 + expr = decompiler.stack.pop()
710 + if decompiler.pos >= decompiler.conditions_end:
711 + clausetype = ast.And if negate else ast.Or
712 + elif decompiler.pos in decompiler.or_jumps:
713 + clausetype = ast.Or
717 + clausetype = ast.And
720 + expr = ast.Compare(expr, [op()], [ast.Constant(None)])
721 + decompiler.stack.append(expr)
723 + if decompiler.next_pos in decompiler.targets:
724 + decompiler.process_target(decompiler.next_pos)
726 + expr = decompiler.stack.pop()
727 + clause = ast.BoolOp(op=clausetype(), values=[expr])
728 + clause.endpos = endpos
729 + decompiler.targets.setdefault(endpos, clause)
732 + def jump_if_none(decompiler, endpos):
733 + return decompiler.conditional_jump_none_impl(endpos, True)
735 + def jump_if_not_none(decompiler, endpos):
736 + return decompiler.conditional_jump_none_impl(endpos, False)
738 def process_target(decompiler, pos, partial=False):
741 @@ -786,6 +817,10 @@ def MAKE_FUNCTION(decompiler, argc):
742 POP_JUMP_FORWARD_IF_TRUE = JUMP_IF_TRUE
743 POP_JUMP_IF_FALSE = JUMP_IF_FALSE
744 POP_JUMP_IF_TRUE = JUMP_IF_TRUE
745 + POP_JUMP_BACKWARD_IF_NONE = jump_if_none
746 + POP_JUMP_BACKWARD_IF_NOT_NONE = jump_if_not_none
747 + POP_JUMP_FORWARD_IF_NONE = jump_if_none
748 + POP_JUMP_FORWARD_IF_NOT_NONE = jump_if_not_none
750 def POP_TOP(decompiler):
753 From 01026c2b043a9d468d88bceff53062ac8f653ba1 Mon Sep 17 00:00:00 2001
754 From: Jochen Sprickerhof <git@jochen.sprickerhof.de>
755 Date: Mon, 19 Dec 2022 10:27:02 +0100
756 Subject: [PATCH 20/21] fixup! Add some simpler tests to help find Decompiler
760 pony/orm/tests/test_decompiler.py | 5 +++++
761 1 file changed, 5 insertions(+)
763 diff --git a/pony/orm/tests/test_decompiler.py b/pony/orm/tests/test_decompiler.py
764 index 189f611a..72fdc654 100644
765 --- a/pony/orm/tests/test_decompiler.py
766 +++ b/pony/orm/tests/test_decompiler.py
773 from pony.orm.decompiling import Decompiler
774 from pony.orm.asttranslation import ast2src
775 @@ -96,6 +97,10 @@ def get_condition_values(cond):
777 class TestDecompiler(unittest.TestCase):
778 def assertDecompilesTo(self, src, expected):
779 + # skip test due to ast.dump has no indent parameter
780 + if sys.version_info[:2] <= (3, 8):
783 code = compile(src, '<?>', 'eval').co_consts[0]
787 From 3ac71610c0c304c3200a2c583e94d3e93fe3889e Mon Sep 17 00:00:00 2001
788 From: =?UTF-8?q?Timo=20R=C3=B6hling?= <roehling@debian.org>
789 Date: Wed, 5 Apr 2023 09:40:08 +0200
790 Subject: [PATCH 21/21] Fix negation for JUMP_IF_NONE / JUMP_IF_NOT_NONE
793 pony/orm/decompiling.py | 22 ++++++++++++----------
794 1 file changed, 12 insertions(+), 10 deletions(-)
796 diff --git a/pony/orm/decompiling.py b/pony/orm/decompiling.py
797 index d0397239..71e67801 100644
798 --- a/pony/orm/decompiling.py
799 +++ b/pony/orm/decompiling.py
800 @@ -616,17 +616,13 @@ def conditional_jump_new(decompiler, endpos, if_true):
802 def conditional_jump_none_impl(decompiler, endpos, negate):
803 expr = decompiler.stack.pop()
805 - if decompiler.pos >= decompiler.conditions_end:
806 - clausetype = ast.And if negate else ast.Or
807 - elif decompiler.pos in decompiler.or_jumps:
808 + assert(decompiler.pos < decompiler.conditions_end)
809 + if decompiler.pos in decompiler.or_jumps:
813 + op = ast.IsNot if negate else ast.Is
818 + op = ast.Is if negate else ast.IsNot
819 expr = ast.Compare(expr, [op()], [ast.Constant(None)])
820 decompiler.stack.append(expr)
822 @@ -640,10 +636,10 @@ def conditional_jump_none_impl(decompiler, endpos, negate):
825 def jump_if_none(decompiler, endpos):
826 - return decompiler.conditional_jump_none_impl(endpos, True)
827 + return decompiler.conditional_jump_none_impl(endpos, False)
829 def jump_if_not_none(decompiler, endpos):
830 - return decompiler.conditional_jump_none_impl(endpos, False)
831 + return decompiler.conditional_jump_none_impl(endpos, True)
833 def process_target(decompiler, pos, partial=False):
835 @@ -998,6 +994,12 @@ def YIELD_VALUE(decompiler):
836 (a for a in T1 if a in select(b for b in T2))
837 (a for a in T1 if a in (b for b in T2 if b in (c for c in T3 if c == a)))
838 (a for a in T1 if a > x and a in (b for b in T1 if b < y) and a < z)
839 + (a for a in T if a.b is None)
840 + (a for a in T if a.b is not None)
841 + (a for a in T if a.b is None or a.b == c)
842 + (a for a in T if a.b is not None or a.b == c)
843 + (a for a in T if a.b is None and a.c == d)
844 + (a for a in T if a.b is not None and a.c == d)
846 ## should throw InvalidQuery due to using [] inside of a query
847 ## (a for a in T1 if a in [b for b in T2 if b in [(c, d) for c in T3]])