def test_cellvar_freevar(self): concrete = ConcreteBytecode() concrete.cellvars = ["cell"] concrete.freevars = ["free"] concrete.append(ConcreteInstr("LOAD_DEREF", 0)) concrete.append(ConcreteInstr("LOAD_DEREF", 1)) code = concrete.to_code() concrete = ConcreteBytecode.from_code(code) self.assertEqual(concrete.cellvars, ["cell"]) self.assertEqual(concrete.freevars, ["free"]) self.assertEqual( list(concrete), [ ConcreteInstr("LOAD_DEREF", 0, lineno=1), ConcreteInstr("LOAD_DEREF", 1, lineno=1), ], ) bytecode = concrete.to_bytecode() self.assertEqual(bytecode.cellvars, ["cell"]) self.assertEqual( list(bytecode), [ Instr("LOAD_DEREF", CellVar("cell"), lineno=1), Instr("LOAD_DEREF", FreeVar("free"), lineno=1), ], )
def test_eq(self): code = ConcreteBytecode() self.assertFalse(code == 1) for name, val in ( ("names", ["a"]), ("varnames", ["a"]), ("consts", [1]), ("argcount", 1), ("kwonlyargcount", 2), ("flags", CompilerFlags(CompilerFlags.GENERATOR)), ("first_lineno", 10), ("filename", "xxxx.py"), ("name", "__x"), ("docstring", "x-x-x"), ("cellvars", [CellVar("x")]), ("freevars", [FreeVar("x")]), ): c = ConcreteBytecode() setattr(c, name, val) # For obscure reasons using assertNotEqual here fail self.assertFalse(code == c) if sys.version_info > (3, 8): c = ConcreteBytecode() c.posonlyargcount = 10 self.assertFalse(code == c) c = ConcreteBytecode() c.consts = [1] code.consts = [1] c.append(ConcreteInstr("LOAD_CONST", 0)) self.assertFalse(code == c)
def test_invalid_types(self): code = ConcreteBytecode() code.append(Label()) with self.assertRaises(ValueError): list(code) with self.assertRaises(ValueError): code.legalize() with self.assertRaises(ValueError): ConcreteBytecode([Label()])
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)])
def test_async_gen_no_flag_is_async_None(self): # Test inference in the absence of any flag set on the bytecode # Infer generator code = ConcreteBytecode() code.append(ConcreteInstr("YIELD_VALUE")) code.update_flags() self.assertTrue(bool(code.flags & CompilerFlags.GENERATOR)) # Infer coroutine code = ConcreteBytecode() code.append(ConcreteInstr("GET_AWAITABLE")) code.update_flags() self.assertTrue(bool(code.flags & CompilerFlags.COROUTINE)) # Infer coroutine or async generator for i, expected in ( ("YIELD_VALUE", CompilerFlags.ASYNC_GENERATOR), ("YIELD_FROM", CompilerFlags.COROUTINE), ): code = ConcreteBytecode() code.append(ConcreteInstr("GET_AWAITABLE")) code.append(ConcreteInstr(i)) code.update_flags() self.assertTrue(bool(code.flags & expected))
def test_async_gen_no_flag_is_async_False(self): # Test inference when we request a non-async function # Infer generator code = ConcreteBytecode() code.append(ConcreteInstr("YIELD_VALUE")) code.flags = CompilerFlags(CompilerFlags.COROUTINE) code.update_flags(is_async=False) self.assertTrue(bool(code.flags & CompilerFlags.GENERATOR)) # Abort on coroutine code = ConcreteBytecode() code.append(ConcreteInstr("GET_AWAITABLE")) code.flags = CompilerFlags(CompilerFlags.COROUTINE) with self.assertRaises(ValueError): code.update_flags(is_async=False)
def test_async_gen_no_flag_is_async_True(self): # Test inference when we request an async function # Force coroutine code = ConcreteBytecode() code.update_flags(is_async=True) self.assertTrue(bool(code.flags & CompilerFlags.COROUTINE)) # Infer coroutine or async generator for i, expected in ( ("YIELD_VALUE", CompilerFlags.ASYNC_GENERATOR), ("YIELD_FROM", CompilerFlags.COROUTINE), ): code = ConcreteBytecode() code.append(ConcreteInstr(i)) code.update_flags(is_async=True) self.assertTrue(bool(code.flags & expected))
def test_async_gen_flags(self): # Test inference in the presence of pre-existing flags for is_async in (None, True): # Infer generator code = ConcreteBytecode() code.append(ConcreteInstr("YIELD_VALUE")) for f, expected in ( (CompilerFlags.COROUTINE, CompilerFlags.ASYNC_GENERATOR), (CompilerFlags.ASYNC_GENERATOR, CompilerFlags.ASYNC_GENERATOR), (CompilerFlags.ITERABLE_COROUTINE, CompilerFlags.ITERABLE_COROUTINE), ): code.flags = CompilerFlags(f) code.update_flags(is_async=is_async) self.assertTrue(bool(code.flags & expected)) # Infer coroutine code = ConcreteBytecode() code.append(ConcreteInstr("YIELD_FROM")) for f, expected in ( (CompilerFlags.COROUTINE, CompilerFlags.COROUTINE), (CompilerFlags.ASYNC_GENERATOR, CompilerFlags.COROUTINE), (CompilerFlags.ITERABLE_COROUTINE, CompilerFlags.ITERABLE_COROUTINE), ): code.flags = CompilerFlags(f) code.update_flags(is_async=is_async) self.assertTrue(bool(code.flags & expected)) # Crash on ITERABLE_COROUTINE with async bytecode code = ConcreteBytecode() code.append(ConcreteInstr("GET_AWAITABLE")) code.flags = CompilerFlags(CompilerFlags.ITERABLE_COROUTINE) with self.assertRaises(ValueError): code.update_flags(is_async=is_async)