Пример #1
0
 def test_slice(self):
     code = Bytecode()
     code.first_lineno = 3
     code.extend([
         Instr("LOAD_CONST", 7),
         Instr("STORE_NAME", "x"),
         SetLineno(4),
         Instr("LOAD_CONST", 8),
         Instr("STORE_NAME", "y"),
         SetLineno(5),
         Instr("LOAD_CONST", 9),
         Instr("STORE_NAME", "z"),
     ])
     sliced_code = code[:]
     self.assertEqual(code, sliced_code)
     for name in (
             "argcount",
             "posonlyargcount",
             "kwonlyargcount",
             "first_lineno",
             "name",
             "filename",
             "docstring",
             "cellvars",
             "freevars",
             "argnames",
     ):
         self.assertEqual(getattr(code, name, None),
                          getattr(sliced_code, name, None))
Пример #2
0
    def test_setlineno(self):
        # x = 7
        # y = 8
        # z = 9
        code = Bytecode()
        code.first_lineno = 3
        code.extend([
            Instr("LOAD_CONST", 7),
            Instr("STORE_NAME", "x"),
            SetLineno(4),
            Instr("LOAD_CONST", 8),
            Instr("STORE_NAME", "y"),
            SetLineno(5),
            Instr("LOAD_CONST", 9),
            Instr("STORE_NAME", "z"),
        ])

        concrete = code.to_concrete_bytecode()
        self.assertEqual(concrete.consts, [7, 8, 9])
        self.assertEqual(concrete.names, ["x", "y", "z"])
        self.assertListEqual(
            list(concrete),
            [
                ConcreteInstr("LOAD_CONST", 0, lineno=3),
                ConcreteInstr("STORE_NAME", 0, lineno=3),
                ConcreteInstr("LOAD_CONST", 1, lineno=4),
                ConcreteInstr("STORE_NAME", 1, lineno=4),
                ConcreteInstr("LOAD_CONST", 2, lineno=5),
                ConcreteInstr("STORE_NAME", 2, lineno=5),
            ],
        )
Пример #3
0
 def test_build_tuple(self):
     # x = (1, 2, 3)
     code = Bytecode([
         Instr("LOAD_CONST", 1),
         Instr("LOAD_CONST", 2),
         Instr("LOAD_CONST", 3),
         Instr("BUILD_TUPLE", 3),
         Instr("STORE_NAME", "x"),
     ])
     self.check(code, Instr("LOAD_CONST", (1, 2, 3)),
                Instr("STORE_NAME", "x"))
Пример #4
0
    def build_tuple_unpack_seq(self, instr):
        next_instr = self.get_next_instr("UNPACK_SEQUENCE")
        if next_instr is None or next_instr.arg != instr.arg:
            return

        if instr.arg < 1:
            return

        if self.const_stack and instr.arg <= len(self.const_stack):
            nconst = instr.arg
            start = self.index - 1

            # Rewrite LOAD_CONST instructions in the reverse order
            load_consts = self.block[start - nconst:start]
            self.block[start - nconst:start] = reversed(load_consts)

            # Remove BUILD_TUPLE+UNPACK_SEQUENCE
            self.block[start:start + 2] = ()
            self.index -= 2
            self.const_stack.clear()
            return

        if instr.arg == 1:
            # Replace BUILD_TUPLE 1 + UNPACK_SEQUENCE 1 with NOP
            del self.block[self.index - 1:self.index + 1]
        elif instr.arg == 2:
            # Replace BUILD_TUPLE 2 + UNPACK_SEQUENCE 2 with ROT_TWO
            rot2 = Instr("ROT_TWO", lineno=instr.lineno)
            self.block[self.index - 1:self.index + 1] = (rot2, )
            self.index -= 1
            self.const_stack.clear()
        elif instr.arg == 3:
            # Replace BUILD_TUPLE 3 + UNPACK_SEQUENCE 3
            # with ROT_THREE + ROT_TWO
            rot3 = Instr("ROT_THREE", lineno=instr.lineno)
            rot2 = Instr("ROT_TWO", lineno=instr.lineno)
            self.block[self.index - 1:self.index + 1] = (rot3, rot2)
            self.index -= 1
            self.const_stack.clear()
Пример #5
0
    def test_blocks_broken_jump(self):
        block = BasicBlock()
        code = ControlFlowGraph()
        code[0].append(Instr("JUMP_ABSOLUTE", block))

        expected = textwrap.dedent(
            """
            block1:
                JUMP_ABSOLUTE <error: unknown block>

        """
        ).lstrip("\n")
        self.check_dump_bytecode(code, expected)
Пример #6
0
    def test_split_block_end(self):
        code = self.sample_code()

        # split at the end of the last block requires to add a new empty block
        label = code.split_block(code[0], 2)
        self.assertIs(label, code[1])
        self.assertBlocksEqual(
            code,
            [Instr("LOAD_CONST", 1, lineno=1), Instr("STORE_NAME", "x", lineno=1)],
            [],
        )
        self.check_getitem(code)

        # split at the end of a block which is not the end doesn't require to
        # add a new block
        label = code.split_block(code[0], 2)
        self.assertIs(label, code[1])
        self.assertBlocksEqual(
            code,
            [Instr("LOAD_CONST", 1, lineno=1), Instr("STORE_NAME", "x", lineno=1)],
            [],
        )
Пример #7
0
    def test_load_classderef(self):
        concrete = ConcreteBytecode()
        concrete.cellvars = ["__class__"]
        concrete.freevars = ["__class__"]
        concrete.extend([
            ConcreteInstr("LOAD_CLASSDEREF", 1),
            ConcreteInstr("STORE_DEREF", 1)
        ])

        bytecode = concrete.to_bytecode()
        self.assertEqual(bytecode.freevars, ["__class__"])
        self.assertEqual(bytecode.cellvars, ["__class__"])
        self.assertEqual(
            list(bytecode),
            [
                Instr("LOAD_CLASSDEREF", FreeVar("__class__"), lineno=1),
                Instr("STORE_DEREF", FreeVar("__class__"), lineno=1),
            ],
        )

        concrete = bytecode.to_concrete_bytecode()
        self.assertEqual(concrete.freevars, ["__class__"])
        self.assertEqual(concrete.cellvars, ["__class__"])
        self.assertEqual(
            list(concrete),
            [
                ConcreteInstr("LOAD_CLASSDEREF", 1, lineno=1),
                ConcreteInstr("STORE_DEREF", 1, lineno=1),
            ],
        )

        code = concrete.to_code()
        self.assertEqual(code.co_freevars, ("__class__", ))
        self.assertEqual(code.co_cellvars, ("__class__", ))
        self.assertEqual(
            code.co_code,
            b"\x94\x01\x89\x01",
        )
Пример #8
0
 def test_negative_size_unary_with_disable_check_of_pre_and_post(self):
     opnames = (
         "UNARY_POSITIVE",
         "UNARY_NEGATIVE",
         "UNARY_NOT",
         "UNARY_INVERT",
     )
     for opname in opnames:
         with self.subTest():
             code = Bytecode()
             code.first_lineno = 1
             code.extend([Instr(opname)])
             co = code.to_code(check_pre_and_post=False)
             self.assertEqual(co.co_stacksize, 0)
Пример #9
0
 def test_negative_size_unary(self):
     opnames = (
         "UNARY_POSITIVE",
         "UNARY_NEGATIVE",
         "UNARY_NOT",
         "UNARY_INVERT",
     )
     for opname in opnames:
         with self.subTest():
             code = Bytecode()
             code.first_lineno = 1
             code.extend([Instr(opname)])
             with self.assertRaises(RuntimeError):
                 code.compute_stacksize()
Пример #10
0
    def test_freevar(self):
        concrete = ConcreteBytecode()
        concrete.freevars = ["x"]
        concrete.append(ConcreteInstr("LOAD_DEREF", 0))
        code = concrete.to_code()

        concrete = ConcreteBytecode.from_code(code)
        self.assertEqual(concrete.cellvars, [])
        self.assertEqual(concrete.freevars, ["x"])
        self.assertEqual(list(concrete), [ConcreteInstr("LOAD_DEREF", 0, lineno=1)])

        bytecode = concrete.to_bytecode()
        self.assertEqual(bytecode.cellvars, [])
        self.assertEqual(list(bytecode), [Instr("LOAD_DEREF", FreeVar("x"), lineno=1)])
Пример #11
0
    def test_label_at_the_end(self):
        label = Label()
        code = Bytecode([
            Instr("LOAD_NAME", "x"),
            Instr("UNARY_NOT"),
            Instr("POP_JUMP_IF_FALSE", label),
            Instr("LOAD_CONST", 9),
            Instr("STORE_NAME", "y"),
            label,
        ])

        cfg = ControlFlowGraph.from_bytecode(code)
        self.assertBlocksEqual(
            cfg,
            [
                Instr("LOAD_NAME", "x"),
                Instr("UNARY_NOT"),
                Instr("POP_JUMP_IF_FALSE", cfg[2]),
            ],
            [Instr("LOAD_CONST", 9),
             Instr("STORE_NAME", "y")],
            [],
        )
Пример #12
0
    def test_jumps(self):
        # if test:
        #     x = 12
        # else:
        #     x = 37
        code = Bytecode()
        label_else = Label()
        label_return = Label()
        code.extend([
            Instr("LOAD_NAME", "test", lineno=1),
            Instr("POP_JUMP_IF_FALSE", label_else),
            Instr("LOAD_CONST", 12, lineno=2),
            Instr("STORE_NAME", "x"),
            Instr("JUMP_FORWARD", label_return),
            label_else,
            Instr("LOAD_CONST", 37, lineno=4),
            Instr("STORE_NAME", "x"),
            label_return,
            Instr("LOAD_CONST", None, lineno=4),
            Instr("RETURN_VALUE"),
        ])

        code = code.to_concrete_bytecode()
        expected = [
            ConcreteInstr("LOAD_NAME", 0, lineno=1),
            ConcreteInstr("POP_JUMP_IF_FALSE",
                          5 if OFFSET_AS_INSTRUCTION else 10,
                          lineno=1),
            ConcreteInstr("LOAD_CONST", 0, lineno=2),
            ConcreteInstr("STORE_NAME", 1, lineno=2),
            ConcreteInstr("JUMP_FORWARD",
                          2 if OFFSET_AS_INSTRUCTION else 4,
                          lineno=2),
            ConcreteInstr("LOAD_CONST", 1, lineno=4),
            ConcreteInstr("STORE_NAME", 1, lineno=4),
            ConcreteInstr("LOAD_CONST", 2, lineno=4),
            ConcreteInstr("RETURN_VALUE", lineno=4),
        ]
        self.assertListEqual(list(code), expected)
        self.assertListEqual(code.consts, [12, 37, None])
        self.assertListEqual(code.names, ["test", "x"])
        self.assertListEqual(code.varnames, [])
Пример #13
0
 def check_bin_op(left, op, right, result):
     code = Bytecode([
         Instr("LOAD_CONST", left),
         Instr("LOAD_CONST", right),
         Instr(op),
         Instr("STORE_NAME", "x"),
     ])
     self.check(code, Instr("LOAD_CONST", result),
                Instr("STORE_NAME", "x"))
Пример #14
0
    def test_dead_code_jump(self):
        label = Label()
        code = Bytecode([
            Instr("LOAD_NAME", "x"),
            Instr("JUMP_ABSOLUTE", label),
            # dead code
            Instr("LOAD_NAME", "y"),
            Instr("STORE_NAME", "test"),
            label,
            Instr("STORE_NAME", "test"),
        ])

        self.check(code, Instr("LOAD_NAME", "x"), Instr("STORE_NAME", "test"))
Пример #15
0
 def test_negative_size_binary(self):
     opnames = (
         "BINARY_POWER",
         "BINARY_MULTIPLY",
         "BINARY_MATRIX_MULTIPLY",
         "BINARY_FLOOR_DIVIDE",
         "BINARY_TRUE_DIVIDE",
         "BINARY_MODULO",
         "BINARY_ADD",
         "BINARY_SUBTRACT",
         "BINARY_SUBSCR",
         "BINARY_LSHIFT",
         "BINARY_RSHIFT",
         "BINARY_AND",
         "BINARY_XOR",
         "BINARY_OR",
     )
     for opname in opnames:
         with self.subTest():
             code = Bytecode()
             code.first_lineno = 1
             code.extend([Instr("LOAD_CONST", 1), Instr(opname)])
             with self.assertRaises(RuntimeError):
                 code.compute_stacksize()
Пример #16
0
 def test_negative_size_binary_with_disable_check_of_pre_and_post(self):
     opnames = (
         "BINARY_POWER",
         "BINARY_MULTIPLY",
         "BINARY_MATRIX_MULTIPLY",
         "BINARY_FLOOR_DIVIDE",
         "BINARY_TRUE_DIVIDE",
         "BINARY_MODULO",
         "BINARY_ADD",
         "BINARY_SUBTRACT",
         "BINARY_SUBSCR",
         "BINARY_LSHIFT",
         "BINARY_RSHIFT",
         "BINARY_AND",
         "BINARY_XOR",
         "BINARY_OR",
     )
     for opname in opnames:
         with self.subTest():
             code = Bytecode()
             code.first_lineno = 1
             code.extend([Instr("LOAD_CONST", 1), Instr(opname)])
             co = code.to_code(check_pre_and_post=False)
             self.assertEqual(co.co_stacksize, 1)
Пример #17
0
    def replace_load_const(self, nconst, instr, result):
        # FIXME: remove temporary computed constants?
        # FIXME: or at least reuse existing constants?

        self.in_consts = True

        load_const = Instr("LOAD_CONST", result, lineno=instr.lineno)
        start = self.index - nconst - 1
        self.block[start:self.index] = (load_const, )
        self.index -= nconst

        if nconst:
            del self.const_stack[-nconst:]
        self.const_stack.append(result)
        self.in_consts = True
Пример #18
0
    def test_negative_size_build(self):
        opnames = (
            "BUILD_TUPLE",
            "BUILD_LIST",
            "BUILD_SET",
        )
        if sys.version_info >= (3, 6):
            opnames = (*opnames, "BUILD_STRING")

        for opname in opnames:
            with self.subTest():
                code = Bytecode()
                code.first_lineno = 1
                code.extend([Instr(opname, 1)])
                with self.assertRaises(RuntimeError):
                    code.compute_stacksize()
Пример #19
0
    def test_compare(self):
        instr = Instr("LOAD_CONST", 3, lineno=7)
        self.assertEqual(instr, Instr("LOAD_CONST", 3, lineno=7))
        self.assertNotEqual(instr, 1)

        # different lineno
        self.assertNotEqual(instr, Instr("LOAD_CONST", 3))
        self.assertNotEqual(instr, Instr("LOAD_CONST", 3, lineno=6))
        # different op
        self.assertNotEqual(instr, Instr("LOAD_FAST", "x", lineno=7))
        # different arg
        self.assertNotEqual(instr, Instr("LOAD_CONST", 4, lineno=7))
Пример #20
0
    def test_compute_jumps_convergence(self):
        # Consider the following sequence of instructions:
        #
        #     JUMP_ABSOLUTE Label1
        #     JUMP_ABSOLUTE Label2
        #     ...126 instructions...
        #   Label1:                 Offset 254 on first pass, 256 second pass
        #     NOP
        #     ... many more instructions ...
        #   Label2:                 Offset > 256 on first pass
        #
        # On first pass of compute_jumps(), Label2 will be at address 254, so
        # that value encodes into the single byte arg of JUMP_ABSOLUTE.
        #
        # On second pass compute_jumps() the instr at Label1 will have offset
        # of 256 so will also be given an EXTENDED_ARG.
        #
        # Thus we need to make an additional pass.  This test only verifies
        # case where 2 passes is insufficient but three is enough.
        #
        # On Python > 3.10 we need to double the number since the offset is now
        # in term of instructions and not bytes.

        # Create code from comment above.
        code = Bytecode()
        label1 = Label()
        label2 = Label()
        nop = "NOP"
        code.append(Instr("JUMP_ABSOLUTE", label1))
        code.append(Instr("JUMP_ABSOLUTE", label2))
        # Need 254 * 2 + 2 since the arg will change by 1 instruction rather than 2
        # bytes.
        for x in range(4, 510 if OFFSET_AS_INSTRUCTION else 254, 2):
            code.append(Instr(nop))
        code.append(label1)
        code.append(Instr(nop))
        for x in range(
                514 if OFFSET_AS_INSTRUCTION else 256,
                600 if OFFSET_AS_INSTRUCTION else 300,
                2,
        ):
            code.append(Instr(nop))
        code.append(label2)
        code.append(Instr(nop))

        # This should pass by default.
        code.to_code()

        # Try with max of two passes:  it should raise
        with self.assertRaises(RuntimeError):
            code.to_code(compute_jumps_passes=2)
Пример #21
0
    def test_label2(self):
        bytecode = Bytecode()
        label = Label()
        bytecode.extend([
            Instr("LOAD_NAME", "test", lineno=1),
            Instr("POP_JUMP_IF_FALSE", label),
            Instr("LOAD_CONST", 5, lineno=2),
            Instr("STORE_NAME", "x"),
            Instr("JUMP_FORWARD", label),
            Instr("LOAD_CONST", 7, lineno=4),
            Instr("STORE_NAME", "x"),
            label,
            Instr("LOAD_CONST", None),
            Instr("RETURN_VALUE"),
        ])

        concrete = bytecode.to_concrete_bytecode()
        expected = [
            ConcreteInstr("LOAD_NAME", 0, lineno=1),
            ConcreteInstr("POP_JUMP_IF_FALSE",
                          7 if OFFSET_AS_INSTRUCTION else 14,
                          lineno=1),
            ConcreteInstr("LOAD_CONST", 0, lineno=2),
            ConcreteInstr("STORE_NAME", 1, lineno=2),
            ConcreteInstr("JUMP_FORWARD",
                          2 if OFFSET_AS_INSTRUCTION else 4,
                          lineno=2),
            ConcreteInstr("LOAD_CONST", 1, lineno=4),
            ConcreteInstr("STORE_NAME", 1, lineno=4),
            ConcreteInstr("LOAD_CONST", 2, lineno=4),
            ConcreteInstr("RETURN_VALUE", lineno=4),
        ]
        self.assertListEqual(list(concrete), expected)
        self.assertListEqual(concrete.consts, [5, 7, None])
        self.assertListEqual(concrete.names, ["test", "x"])
        self.assertListEqual(concrete.varnames, [])
Пример #22
0
 def test_handling_of_set_lineno(self):
     code = Bytecode()
     code.first_lineno = 3
     code.extend([
         Instr("LOAD_CONST", 7),
         Instr("STORE_NAME", "x"),
         SetLineno(4),
         Instr("LOAD_CONST", 8),
         Instr("STORE_NAME", "y"),
         SetLineno(5),
         Instr("LOAD_CONST", 9),
         Instr("STORE_NAME", "z"),
     ])
     self.assertEqual(code.compute_stacksize(), 1)
Пример #23
0
    def test_stack_effects(self):
        # Verify all opcodes are handled and that "jump=None" really returns
        # the max of the other cases.
        from _pydevd_frame_eval.vendored.bytecode.concrete import ConcreteInstr

        def check(instr):
            jump = instr.stack_effect(jump=True)
            no_jump = instr.stack_effect(jump=False)
            max_effect = instr.stack_effect(jump=None)
            self.assertEqual(instr.stack_effect(), max_effect)
            self.assertEqual(max_effect, max(jump, no_jump))

            if not instr.has_jump():
                self.assertEqual(jump, no_jump)

        for name, op in opcode.opmap.items():
            with self.subTest(name):
                # Use ConcreteInstr instead of Instr because it doesn't care
                # what kind of argument it is constructed with.
                if op < opcode.HAVE_ARGUMENT:
                    check(ConcreteInstr(name))
                else:
                    for arg in range(256):
                        check(ConcreteInstr(name, arg))

        # LOAD_CONST uses a concrete python object as its oparg, however, in
        #       dis.stack_effect(opcode.opmap['LOAD_CONST'], oparg),
        # oparg should be the index of that python object in the constants.
        #
        # Fortunately, for an instruction whose oparg isn't equivalent to its
        # form in binary files(pyc format), the stack effect is a
        # constant which does not depend on its oparg.
        #
        # The second argument of dis.stack_effect cannot be
        # more than 2**31 - 1. If stack effect of an instruction is
        # independent of its oparg, we pass 0 as the second argument
        # of dis.stack_effect.
        # (As a result we can calculate stack_effect for
        #  any LOAD_CONST instructions, even for large integers)

        for arg in 2 ** 31, 2 ** 32, 2 ** 63, 2 ** 64, -1:
            self.assertEqual(Instr("LOAD_CONST", arg).stack_effect(), 1)
Пример #24
0
 def mk_if_then_else(depth):
     instructions = []
     for i in range(depth):
         label_else = Label()
         instructions.extend([
             Instr("LOAD_FAST", "x"),
             Instr("POP_JUMP_IF_FALSE", label_else),
             Instr("LOAD_GLOBAL", "f{}".format(i)),
             Instr("RETURN_VALUE"),
             label_else,
         ])
     instructions.extend(
         [Instr("LOAD_CONST", None),
          Instr("RETURN_VALUE")])
     return instructions
Пример #25
0
    def test_compute_jumps_convergence(self):
        # Consider the following sequence of instructions:
        #
        #     JUMP_ABSOLUTE Label1
        #     JUMP_ABSOLUTE Label2
        #     ...126 instructions...
        #   Label1:                 Offset 254 on first pass, 256 second pass
        #     NOP
        #     ... many more instructions ...
        #   Label2:                 Offset > 256 on first pass
        #
        # On first pass of compute_jumps(), Label2 will be at address 254, so
        # that value encodes into the single byte arg of JUMP_ABSOLUTE.
        #
        # On second pass compute_jumps() the instr at Label1 will have offset
        # of 256 so will also be given an EXTENDED_ARG.
        #
        # Thus we need to make an additional pass.  This test only verifies
        # case where 2 passes is insufficient but three is enough.

        if not WORDCODE:
            # Could be done pre-WORDCODE, but that requires 2**16 bytes of
            # code.
            return

        # Create code from comment above.
        code = Bytecode()
        label1 = Label()
        label2 = Label()
        nop = "NOP"
        code.append(Instr("JUMP_ABSOLUTE", label1))
        code.append(Instr("JUMP_ABSOLUTE", label2))
        for x in range(4, 254, 2):
            code.append(Instr(nop))
        code.append(label1)
        code.append(Instr(nop))
        for x in range(256, 300, 2):
            code.append(Instr(nop))
        code.append(label2)
        code.append(Instr(nop))

        # This should pass by default.
        code.to_code()

        # Try with max of two passes:  it should raise
        with self.assertRaises(RuntimeError):
            code.to_code(compute_jumps_passes=2)
Пример #26
0
    def test_to_code(self):
        code = Bytecode()
        code.first_lineno = 50
        code.extend([
            Instr("LOAD_NAME", "print"),
            Instr("LOAD_CONST", "%s"),
            Instr("LOAD_GLOBAL", "a"),
            Instr("BINARY_MODULO"),
            Instr("CALL_FUNCTION", 1),
            Instr("RETURN_VALUE"),
        ])
        co = code.to_code()
        # hopefully this is obvious from inspection? :-)
        self.assertEqual(co.co_stacksize, 3)

        co = code.to_code(stacksize=42)
        self.assertEqual(co.co_stacksize, 42)
Пример #27
0
 def test_from_code_load_fast(self):
     code = get_code(
         """
         def func():
             x = 33
             y = x
     """,
         function=True,
     )
     code = Bytecode.from_code(code)
     self.assertEqual(
         code,
         [
             Instr("LOAD_CONST", 33, lineno=2),
             Instr("STORE_FAST", "x", lineno=2),
             Instr("LOAD_FAST", "x", lineno=3),
             Instr("STORE_FAST", "y", lineno=3),
             Instr("LOAD_CONST", None, lineno=3),
             Instr("RETURN_VALUE", lineno=3),
         ],
     )
Пример #28
0
    def test_attr(self):
        instr = Instr("LOAD_CONST", 3, lineno=5)
        self.assertEqual(instr.name, "LOAD_CONST")
        self.assertEqual(instr.opcode, 100)
        self.assertEqual(instr.arg, 3)
        self.assertEqual(instr.lineno, 5)

        # invalid values/types
        self.assertRaises(ValueError, setattr, instr, "lineno", 0)
        self.assertRaises(TypeError, setattr, instr, "lineno", 1.0)
        self.assertRaises(TypeError, setattr, instr, "name", 5)
        self.assertRaises(TypeError, setattr, instr, "opcode", 1.0)
        self.assertRaises(ValueError, setattr, instr, "opcode", -1)
        self.assertRaises(ValueError, setattr, instr, "opcode", 255)

        # arg can take any attribute but cannot be deleted
        instr.arg = -8
        instr.arg = object()
        self.assertRaises(AttributeError, delattr, instr, "arg")

        # no argument
        instr = Instr("ROT_TWO")
        self.assertIs(instr.arg, UNSET)
Пример #29
0
    def test_invalid_arg(self):
        label = Label()
        block = BasicBlock()

        # EXTENDED_ARG
        self.assertRaises(ValueError, Instr, "EXTENDED_ARG", 0)

        # has_jump()
        self.assertRaises(TypeError, Instr, "JUMP_ABSOLUTE", 1)
        self.assertRaises(TypeError, Instr, "JUMP_ABSOLUTE", 1.0)
        Instr("JUMP_ABSOLUTE", label)
        Instr("JUMP_ABSOLUTE", block)

        # hasfree
        self.assertRaises(TypeError, Instr, "LOAD_DEREF", "x")
        Instr("LOAD_DEREF", CellVar("x"))
        Instr("LOAD_DEREF", FreeVar("x"))

        # haslocal
        self.assertRaises(TypeError, Instr, "LOAD_FAST", 1)
        Instr("LOAD_FAST", "x")

        # hasname
        self.assertRaises(TypeError, Instr, "LOAD_NAME", 1)
        Instr("LOAD_NAME", "x")

        # hasconst
        self.assertRaises(ValueError, Instr, "LOAD_CONST")  # UNSET
        self.assertRaises(ValueError, Instr, "LOAD_CONST", label)
        self.assertRaises(ValueError, Instr, "LOAD_CONST", block)
        Instr("LOAD_CONST", 1.0)
        Instr("LOAD_CONST", object())

        # hascompare
        self.assertRaises(TypeError, Instr, "COMPARE_OP", 1)
        Instr("COMPARE_OP", Compare.EQ)

        # HAVE_ARGUMENT
        self.assertRaises(ValueError, Instr, "CALL_FUNCTION", -1)
        self.assertRaises(TypeError, Instr, "CALL_FUNCTION", 3.0)
        Instr("CALL_FUNCTION", 3)

        # test maximum argument
        self.assertRaises(ValueError, Instr, "CALL_FUNCTION", 2147483647 + 1)
        instr = Instr("CALL_FUNCTION", 2147483647)
        self.assertEqual(instr.arg, 2147483647)

        # not HAVE_ARGUMENT
        self.assertRaises(ValueError, Instr, "NOP", 0)
        Instr("NOP")
Пример #30
0
    def test_const_key_equal(self):
        neg_zero = -0.0
        pos_zero = +0.0

        # int and float: 0 == 0.0
        self.assertNotEqual(Instr("LOAD_CONST", 0), Instr("LOAD_CONST", 0.0))

        # float: -0.0 == +0.0
        self.assertNotEqual(
            Instr("LOAD_CONST", neg_zero), Instr("LOAD_CONST", pos_zero)
        )

        # complex
        self.assertNotEqual(
            Instr("LOAD_CONST", complex(neg_zero, 1.0)),
            Instr("LOAD_CONST", complex(pos_zero, 1.0)),
        )
        self.assertNotEqual(
            Instr("LOAD_CONST", complex(1.0, neg_zero)),
            Instr("LOAD_CONST", complex(1.0, pos_zero)),
        )

        # tuple
        self.assertNotEqual(Instr("LOAD_CONST", (0,)), Instr("LOAD_CONST", (0.0,)))
        nested_tuple1 = (0,)
        nested_tuple1 = (nested_tuple1,)
        nested_tuple2 = (0.0,)
        nested_tuple2 = (nested_tuple2,)
        self.assertNotEqual(
            Instr("LOAD_CONST", nested_tuple1), Instr("LOAD_CONST", nested_tuple2)
        )

        # frozenset
        self.assertNotEqual(
            Instr("LOAD_CONST", frozenset({0})), Instr("LOAD_CONST", frozenset({0.0}))
        )