def transform_ast(self, node, ctx): # TODO(mdan): Insert list_comprehensions somewhere. unsupported_features_checker.verify(node) # Run initial analysis. graphs = cfg.build(node) node = qual_names.resolve(node) node = activity.resolve(node, ctx, None) node = reaching_definitions.resolve(node, ctx, graphs) anno.dup( node, { anno.Static.DEFINITIONS: anno.Static.ORIG_DEFINITIONS, }, ) node = functions.transform(node, ctx) node = directives.transform(node, ctx) node = break_statements.transform(node, ctx) if ctx.user.options.uses(converter.Feature.ASSERT_STATEMENTS): node = asserts.transform(node, ctx) # Note: sequencing continue canonicalization before for loop one avoids # dealing with the extra loop increment operation that the for # canonicalization creates. node = continue_statements.transform(node, ctx) node = return_statements.transform(node, ctx) if ctx.user.options.uses(converter.Feature.LISTS): node = lists.transform(node, ctx) node = slices.transform(node, ctx) node = call_trees.transform(node, ctx) node = control_flow.transform(node, ctx) node = conditional_expressions.transform(node, ctx) node = logical_expressions.transform(node, ctx) return node
def test_known_called_lambda(self): l = lambda x: x def test_fn(a): return l(a) ns = {'l': l} node, ctx = self.prepare(test_fn, ns) node = call_trees.transform(node, ctx) with self.compiled(node, ns) as result: self.assertEquals(1, result.test_fn(1))
def test_call_to_decorated_function(self): def decorator(f): return f @decorator def called_fn(a): return a def test_fn(a): return called_fn(a) node, ctx = self.prepare(test_fn, {'called_fn': called_fn}) node = call_trees.transform(node, ctx)
def test_known_called_lambda(self): l = lambda x: x def test_fn(a): return l(a) ns = {'l': l} node, ctx = self.prepare(test_fn, ns) node = call_trees.transform(node, ctx) with self.compiled(node, ns) as result: self.assertEquals(1, result.test_fn(1))
def test_known_called_namedtuple(self): nt = collections.namedtuple('TestNamedTuple', ['a']) def test_fn(a): return nt(a) ns = {'nt': nt} node, ctx = self.prepare(test_fn, ns) node = call_trees.transform(node, ctx) with self.compiled(node, ns) as result: self.assertEquals(nt(1), result.test_fn(1))
def test_call_to_decorated_function(self): def decorator(f): return f @decorator def called_fn(a): return a def test_fn(a): return called_fn(a) node, ctx = self.prepare(test_fn, {'called_fn': called_fn}) node = call_trees.transform(node, ctx)
def test_uncompiled_modules(self): def test_fn(a): a = math_ops.multiply(a, constant_op.constant(2)) a = math_ops.add(a, constant_op.constant(1)) return a ns = {'math_ops': math_ops, 'constant_op': constant_op} node, ctx = self.prepare(test_fn, ns, arg_types=set(((math_ops.__name__, ), (constant_op.__name__, )))) node = call_trees.transform(node, ctx) with self.compiled(node, ns) as result: with self.cached_session() as sess: result_tensor = result.test_fn(constant_op.constant(1)) self.assertEquals(self.evaluate(result_tensor), 3)
def test_uncompiled_modules(self): def test_fn(a): a = math_ops.multiply(a, constant_op.constant(2)) a = math_ops.add(a, constant_op.constant(1)) return a ns = {'math_ops': math_ops, 'constant_op': constant_op} node, ctx = self.prepare( test_fn, ns, arg_types=set(((math_ops.__name__,), (constant_op.__name__,)))) node = call_trees.transform(node, ctx) with self.compiled(node, ns) as result: with self.cached_session() as sess: result_tensor = result.test_fn(constant_op.constant(1)) self.assertEquals(sess.run(result_tensor), 3)
def test_basic(self): def test_fn_1(_): raise ValueError('This should not be called in the compiled version.') def other_test_fn_1(a): return a + 1 def test_fn_2(a): return test_fn_1(a) + 1 ns = {'test_fn_1': test_fn_1} node, ctx = self.prepare(test_fn_2, ns) node = call_trees.transform(node, ctx) with self.compiled(node, ns) as result: new_name, _ = ctx.namer.compiled_function_name(('test_fn_1',)) setattr(result, new_name, other_test_fn_1) self.assertEquals(result.test_fn_2(1), 3)
def test_basic_method(self): class TestClass(object): def test_fn_1(self, a): return a + 1 def test_fn_2(self, a): return self.test_fn_1(a) + 1 ns = {'TestClass': TestClass} node, ctx = self.prepare( TestClass.test_fn_2, ns, namer=converter_testing.FakeNoRenameNamer(), arg_types={'self': (TestClass.__name__, TestClass)}) node = call_trees.transform(node, ctx) with self.compiled(node, ns) as result: tc = TestClass() self.assertEquals(3, result.test_fn_2(tc, 1))
def test_basic_method(self): class TestClass(object): def test_fn_1(self, a): return a + 1 def test_fn_2(self, a): return self.test_fn_1(a) + 1 ns = {'TestClass': TestClass} node, ctx = self.prepare( TestClass.test_fn_2, ns, namer=converter_testing.FakeNoRenameNamer(), arg_types={'self': (TestClass.__name__, TestClass)}) node = call_trees.transform(node, ctx) with self.compiled(node, ns) as result: tc = TestClass() self.assertEquals(3, result.test_fn_2(tc, 1))
def transform_ast(self, node, ctx): unsupported_features_checker.verify(node) node = self.initial_analysis(node, ctx) node = functions.transform(node, ctx) node = directives.transform(node, ctx) node = break_statements.transform(node, ctx) if ctx.user.options.uses(converter.Feature.ASSERT_STATEMENTS): node = asserts.transform(node, ctx) # Note: sequencing continue canonicalization before for loop one avoids # dealing with the extra loop increment operation that the for # canonicalization creates. node = continue_statements.transform(node, ctx) node = return_statements.transform(node, ctx) if ctx.user.options.uses(converter.Feature.LISTS): node = lists.transform(node, ctx) node = slices.transform(node, ctx) node = call_trees.transform(node, ctx) node = control_flow.transform(node, ctx) node = conditional_expressions.transform(node, ctx) node = logical_expressions.transform(node, ctx) node = variables.transform(node, ctx) return node
def test_decorated_callee(self): # Using this trick to prevent the Python loader from automatically expanding # the decorator. This simulates the situation found when converting a # function from within an actual decorator. def wrapper_fn(): def dec(f): return f @dec def called_fn(a): return a @dec def test_fn(a): return called_fn(a) return test_fn node, ctx = self.prepare(wrapper_fn, {}) node = node.body[2] node = call_trees.transform(node, ctx)
def test_decorated_callee(self): # Using this trick to prevent the Python loader from automatically expanding # the decorator. This simulates the situation found when converting a # function from within an actual decorator. def wrapper_fn(): def dec(f): return f @dec def called_fn(a): return a @dec def test_fn(a): return called_fn(a) return test_fn node, ctx = self.prepare(wrapper_fn, {}) node = node.body[2] node = call_trees.transform(node, ctx)