aboutsummaryrefslogtreecommitdiffstats
path: root/sources/pyside6/tests/pysidetest/enum_test.py
diff options
context:
space:
mode:
Diffstat (limited to 'sources/pyside6/tests/pysidetest/enum_test.py')
-rw-r--r--sources/pyside6/tests/pysidetest/enum_test.py136
1 files changed, 136 insertions, 0 deletions
diff --git a/sources/pyside6/tests/pysidetest/enum_test.py b/sources/pyside6/tests/pysidetest/enum_test.py
index 34f90702a..832834530 100644
--- a/sources/pyside6/tests/pysidetest/enum_test.py
+++ b/sources/pyside6/tests/pysidetest/enum_test.py
@@ -13,6 +13,8 @@ init_test_paths(True)
from PySide6.QtCore import Qt
from testbinding import Enum1, TestObjectWithoutNamespace
+import dis
+
class ListConnectionTest(unittest.TestCase):
@@ -45,6 +47,140 @@ class ListConnectionTest(unittest.TestCase):
self.assertTrue(Qt.AlignBottom > Qt.AlignHCenter)
+# PYSIDE-1735: We are testing that opcodes do what they are supposed to do.
+# This is needed in the PyEnum forgiveness mode where we need
+# to introspect the code if an Enum was called with no args.
+class InvestigateOpcodesTest(unittest.TestCase):
+
+ def probe_function1(self):
+ x = Qt.Alignment
+
+ def probe_function2(self):
+ x = Qt.Alignment()
+
+ @staticmethod
+ def read_code(func, **kw):
+ return list(instr[:3] for instr in dis.Bytecode(func, **kw))
+
+ @staticmethod
+ def get_sizes(func, **kw):
+ ops = list((instr.opname, instr.offset) for instr in dis.Bytecode(func, **kw))
+ res = []
+ for idx in range(1, len(ops)):
+ res.append((ops[idx - 1][0], ops[idx][1] - ops[idx - 1][1]))
+ return sorted(res, key=lambda x: (x[1], x[0]))
+
+ _sin = sys.implementation.name
+
+ @unittest.skipIf(hasattr(sys.flags, "nogil"), f"{_sin} has different opcodes")
+ def testByteCode(self):
+ import dis
+ # opname, opcode, arg
+ result_1 = [('LOAD_GLOBAL', 116, 0),
+ ('LOAD_ATTR', 106, 1),
+ ('STORE_FAST', 125, 1),
+ ('LOAD_CONST', 100, 0),
+ ('RETURN_VALUE', 83, None)]
+
+ result_2 = [('LOAD_GLOBAL', 116, 0),
+ ('LOAD_METHOD', 160, 1),
+ ('CALL_METHOD', 161, 0),
+ ('STORE_FAST', 125, 1),
+ ('LOAD_CONST', 100, 0),
+ ('RETURN_VALUE', 83, None)]
+
+ if sys.version_info[:2] <= (3, 6):
+
+ result_2 = [('LOAD_GLOBAL', 116, 0),
+ ('LOAD_ATTR', 106, 1),
+ ('CALL_FUNCTION', 131, 0),
+ ('STORE_FAST', 125, 1),
+ ('LOAD_CONST', 100, 0),
+ ('RETURN_VALUE', 83, None)]
+
+ if sys.version_info[:2] == (3, 11):
+ # Note: Python 3.11 is a bit more complex because it can optimize itself.
+ # Opcodes are a bit different, and a hidden second code object is used.
+ # We investigate this a bit, because we want to be warned when things change.
+ QUICKENING_WARMUP_DELAY = 8
+
+ result_1 = [('RESUME', 151, 0),
+ ('LOAD_GLOBAL', 116, 0),
+ ('LOAD_ATTR', 106, 1),
+ ('STORE_FAST', 125, 1),
+ ('LOAD_CONST', 100, 0),
+ ('RETURN_VALUE', 83, None)]
+
+ result_2 = [('RESUME', 151, 0),
+ ('LOAD_GLOBAL', 116, 1),
+ ('LOAD_ATTR', 106, 1),
+ ('PRECALL', 166, 0),
+ ('CALL', 171, 0),
+ ('STORE_FAST', 125, 1),
+ ('LOAD_CONST', 100, 0),
+ ('RETURN_VALUE', 83, None)]
+
+ sizes_2 = [('LOAD_CONST', 2),
+ ('RESUME', 2),
+ ('STORE_FAST', 2),
+ ('PRECALL', 4),
+ ('CALL', 10),
+ ('LOAD_ATTR', 10),
+ ('LOAD_GLOBAL', 12)]
+
+ self.assertEqual(self.read_code(self.probe_function2, adaptive=True), result_2)
+ self.assertEqual(self.get_sizes(self.probe_function2, adaptive=True), sizes_2)
+
+ @staticmethod
+ def code_quicken(f, times):
+ # running the code triggers acceleration after some runs.
+ for _ in range(times):
+ f()
+
+ code_quicken(self.probe_function2, QUICKENING_WARMUP_DELAY - 1)
+ self.assertEqual(self.read_code(self.probe_function2, adaptive=True), result_2)
+ self.assertEqual(self.get_sizes(self.probe_function2, adaptive=True), sizes_2)
+
+ result_3 = [('RESUME_QUICK', 150, 0),
+ ('LOAD_GLOBAL_MODULE', 55, 1),
+ ('LOAD_ATTR_ADAPTIVE', 39, 1),
+ ('PRECALL_ADAPTIVE', 64, 0),
+ ('CALL_ADAPTIVE', 22, 0),
+ ('STORE_FAST', 125, 1),
+ ('LOAD_CONST', 100, 0),
+ ('RETURN_VALUE', 83, None)]
+
+ sizes_3 = [('LOAD_CONST', 2),
+ ('RESUME_QUICK', 2),
+ ('STORE_FAST', 2),
+ ('PRECALL_ADAPTIVE', 4),
+ ('CALL_ADAPTIVE', 10),
+ ('LOAD_ATTR_ADAPTIVE', 10),
+ ('LOAD_GLOBAL_MODULE', 12)]
+
+ code_quicken(self.probe_function2, 1)
+ self.assertEqual(self.read_code(self.probe_function2, adaptive=True), result_3)
+ self.assertEqual(self.get_sizes(self.probe_function2, adaptive=True), sizes_3)
+
+ if sys.version_info[:2] >= (3, 12):
+
+ result_1 = [('RESUME', 151, 0),
+ ('LOAD_GLOBAL', 116, 0),
+ ('LOAD_ATTR', 106, 2),
+ ('STORE_FAST', 125, 1),
+ ('RETURN_CONST', 121, 0)]
+
+ result_2 = [('RESUME', 151, 0),
+ ('LOAD_GLOBAL', 116, 1),
+ ('LOAD_ATTR', 106, 2),
+ ('CALL', 171, 0),
+ ('STORE_FAST', 125, 1),
+ ('RETURN_CONST', 121, 0)]
+
+ self.assertEqual(self.read_code(self.probe_function1), result_1)
+ self.assertEqual(self.read_code(self.probe_function2), result_2)
+
+
if __name__ == '__main__':
unittest.main()