from compiler.ast import * import datetime import sys import unittest from geniusql import astwalk from geniusql.test.lambdas import * #------------------------------------------------------------------------------- # Now we'll map up these same functions to their decompiled versions based on # the appropriate version of python. class Results_Python26(object): # Python 2.5 stopped putting arguments in co_names, # and stopped prepending None to co_consts (except when CO_NESTED?). lambda_parser_tests = [ { 'function': f_in_op, 'results': astwalk.AST( Compare( Name('x'), [('in', Const([1, 2, 3, 4, 5]))] ), ['x'] ), }, { 'function': f_add_op, 'results': astwalk.AST( Add(( Name('x'), Const(datetime.date(2004, 1, 1)) )), ['x'] ) }, { 'function': f_kwargs_and_op, 'results': astwalk.AST( And(( Compare( Getattr(Name('x'), 'Date'), [('==', Const(datetime.date(2004, 1, 1)))] ), Compare( Getattr(Name('x'), 'Qty'), [( '<', Subscript( Name('kw'), 'OP_APPLY', [Const('Size')] )) ] ) )), ['x'], dstar_args='kw' ) }, { 'function': f_mix_names_global_locals_attrs, 'results': astwalk.AST( Or(( Compare( Const(4), [('!=', Getattr(Name('x'), 'amount'))] ), Compare( Mul(( Name('amount'), Const(3) )), [('>', Const(20))] ) )), ['x', 'amount'] ) }, { 'function': f_constant_multiplication, 'results': astwalk.AST( Mul(( Const(60), Name('x') )), ['x'] ) }, { 'function': f_array_slice_subscript, 'results': astwalk.AST( Compare( Const([3, 4]), [( '==', UnarySub( Subscript( Name('x'), 'OP_APPLY', [Const('offset')] ) ) )] ), ['x'] ) }, { 'function': f_const_attr, 'results': astwalk.AST( Or(( Const(True), Compare( Const(5), [('==', Getattr(Name('x'), 'Qty'))] ) )), ['x'] ) }, { 'function': f_nested_conditionals, 'results': astwalk.AST( Not( And(( Compare( Getattr(Name('x'), 'a'), [('==', Const(3))] ), Or(( Compare( Getattr(Name('x'), 'b'), [('>', Const(1))] ), Compare( Getattr(Name('x'), 'b'), [('<', Const(-10))] ) )) )) ), ['x'] ) }, { 'function': f_nested_conditionals_2, 'results': astwalk.AST( Not( Or(( And(( Compare( Getattr(Name('x'), 'a'), [('==', Const(3))] ), Compare( Getattr(Name('x'), 'b'), [('>', Const(1))] ), )), Compare( Getattr(Name('x'), 'b'), [('<', Const(-10))] ) )) ), ['x'] ) }, { 'function': f_unicode_const, 'results': astwalk.AST( Compare( Getattr(Name('x'), 'Name'), [('==', Const(u'Dimsdale'))] ), ['x'] ) }, { 'function': f_unicode_const_getattr, 'results': astwalk.AST( Compare( Getattr(Name('x'), 'Name'), [('==', Const(u'Dimsdale'))] ), ['x'] ) }, { 'function': f_unicode_multiple_args, 'results': astwalk.AST( And(( Compare( Getattr(Name('x'), 'Qty'), [('>', Const(1))] ), And(( Compare( Getattr(Name('y'), 'Qty'), [('>', Const(20))] ), Compare( Getattr(Name('z'), 'Type'), [('==', Const('A'))] ) )) )), ['x', 'y', 'z'], dstar_args='kw' ) }, { 'function': f_closure_example, 'results': astwalk.AST(Const(10)), }, ] lambda_deparser_tests = [ { 'function': f_in_op, 'results': 'lambda x: x in [1, 2, 3, 4, 5]', }, { 'function': f_add_op, 'results': 'lambda x: x + datetime.date(2004, 1, 1)', }, { 'function': f_kwargs_and_op, 'results': "lambda x, **kw: (x.Date == datetime.date(2004, 1, 1)) and (x.Qty < kw['Size'])", }, { 'function': f_mix_names_global_locals_attrs, 'results': "lambda x, amount: (4 != x.amount) or (amount * 3 > 20)", }, { 'function': f_constant_multiplication, 'results': "lambda x: 60 * x", }, { 'function': f_array_slice_subscript, 'results': "lambda x: [3, 4] == -(x['offset'])", }, { 'function': f_const_attr, 'results': "lambda x: (True) or (5 == x.Qty)", }, { 'function': f_nested_conditionals, 'results': "lambda x: not ((x.a == 3) and ((x.b > 1) or (x.b < -10)))", }, { 'function': f_nested_conditionals_2, 'results': "lambda x: not (((x.a == 3) and (x.b > 1)) or (x.b < -10))", }, { 'function': f_unicode_const, 'results': "lambda x: x.Name == u'Dimsdale'", }, { 'function': f_unicode_const_getattr, 'results': "lambda x: x.Name == u'Dimsdale'", }, { 'function': f_unicode_multiple_args, 'results': "lambda x, y, z, **kw: (x.Qty > 1) and ((y.Qty > 20) and (z.Type == 'A'))", }, { 'function': f_closure_example, 'results': "lambda: 10", }, ] #------------------------------------------------------------------------------- class Results_Python27(object): lambda_parser_tests = [ { 'function': f_in_op, 'results': astwalk.AST( Compare( Name('x'), [('in', Const([1, 2, 3, 4, 5]))] ), ['x'] ), }, { 'function': f_add_op, 'results': astwalk.AST( Add(( Name('x'), Const(datetime.date(2004, 1, 1)) )), ['x'] ) }, { 'function': f_kwargs_and_op, 'results': astwalk.AST( And(( Compare( Getattr(Name('x'), 'Date'), [('==', Const(datetime.date(2004, 1, 1)))] ), Compare( Getattr(Name('x'), 'Qty'), [( '<', Subscript( Name('kw'), 'OP_APPLY', [Const('Size')] )) ] ) )), ['x'], dstar_args='kw' ) }, { 'function': f_mix_names_global_locals_attrs, 'results': astwalk.AST( Or(( Compare( Const(4), [('!=', Getattr(Name('x'), 'amount'))] ), Compare( Mul(( Name('amount'), Const(3) )), [('>', Const(20))] ) )), ['x', 'amount'] ) }, { 'function': f_constant_multiplication, 'results': astwalk.AST( Mul(( Const(60), Name('x') )), ['x'] ) }, { 'function': f_array_slice_subscript, 'results': astwalk.AST( Compare( Const([3, 4]), [( '==', UnarySub( Subscript( Name('x'), 'OP_APPLY', [Const('offset')] ) ) )] ), ['x'] ) }, { 'function': f_const_attr, 'results': astwalk.AST( Or(( Const(True), Compare( Const(5), [('==', Getattr(Name('x'), 'Qty'))] ) )), ['x'] ) }, { 'function': f_nested_conditionals, 'results': astwalk.AST( Not( And(( Compare( Getattr(Name('x'), 'a'), [('==', Const(3))] ), Or(( Compare( Getattr(Name('x'), 'b'), [('>', Const(1))] ), Compare( Getattr(Name('x'), 'b'), [('<', Const(-10))] ) )) )) ), ['x'] ) }, { 'function': f_nested_conditionals_2, 'results': astwalk.AST( Not( Or(( And(( Compare( Getattr(Name('x'), 'a'), [('==', Const(3))] ), Compare( Getattr(Name('x'), 'b'), [('>', Const(1))] ), )), Compare( Getattr(Name('x'), 'b'), [('<', Const(-10))] ) )) ), ['x'] ) }, { 'function': f_unicode_const, 'results': astwalk.AST( Compare( Getattr(Name('x'), 'Name'), [('==', Const(u'Dimsdale'))] ), ['x'] ) }, { 'function': f_unicode_const_getattr, 'results': astwalk.AST( Compare( Getattr(Name('x'), 'Name'), [('==', Const(u'Dimsdale'))] ), ['x'] ) }, { 'function': f_unicode_multiple_args, 'results': astwalk.AST( And(( Compare( Getattr(Name('x'), 'Qty'), [('>', Const(1))] ), And(( Compare( Getattr(Name('y'), 'Qty'), [('>', Const(20))] ), Compare( Getattr(Name('z'), 'Type'), [('==', Const('A'))] ) )) )), ['x', 'y', 'z'], dstar_args='kw' ) }, { 'function': f_closure_example, 'results': astwalk.AST(Const(10)), }, ] lambda_deparser_tests = [ { 'function': f_in_op, 'results': 'lambda x: x in [1, 2, 3, 4, 5]', }, { 'function': f_add_op, 'results': 'lambda x: x + datetime.date(2004, 1, 1)', }, { 'function': f_kwargs_and_op, 'results': "lambda x, **kw: (x.Date == datetime.date(2004, 1, 1)) and (x.Qty < kw['Size'])", }, { 'function': f_mix_names_global_locals_attrs, 'results': "lambda x, amount: (4 != x.amount) or (amount * 3 > 20)", }, { 'function': f_constant_multiplication, 'results': "lambda x: 60 * x", }, { 'function': f_array_slice_subscript, 'results': "lambda x: [3, 4] == -(x['offset'])", }, { 'function': f_const_attr, 'results': "lambda x: (True) or (5 == x.Qty)", }, { 'function': f_nested_conditionals, 'results': "lambda x: not ((x.a == 3) and ((x.b > 1) or (x.b < -10)))", }, { 'function': f_nested_conditionals_2, 'results': "lambda x: not (((x.a == 3) and (x.b > 1)) or (x.b < -10))", }, { 'function': f_unicode_const, 'results': "lambda x: x.Name == u'Dimsdale'", }, { 'function': f_unicode_const_getattr, 'results': "lambda x: x.Name == u'Dimsdale'", }, { 'function': f_unicode_multiple_args, 'results': "lambda x, y, z, **kw: (x.Qty > 1) and ((y.Qty > 20) and (z.Type == 'A'))", }, { 'function': f_closure_example, 'results': "lambda: 10", }, ] Results = Results_Python26 if sys.version_info >= (2, 7): Results = Results_Python27 elif sys.version_info >= (2, 6): Results = Results_Python26 else: raise RuntimeError("Python 2.5 and below no longer supported.") class LambdaParserTests(unittest.TestCase): def test_LambdaParser(self): for test_case in Results.lambda_parser_tests: lp = astwalk.LambdaParser(test_case['function']) ## lp.verbose = True lp.walk() self.assertEqual(repr(lp.ast), repr(test_case['results'])) def test_LambdaDeparser(self): count = 0 for test_case in Results.lambda_deparser_tests: lp = astwalk.LambdaParser(test_case['function']) lp.walk() r = astwalk.LambdaDeparser(lp.ast).code() self.assertEqual(r, test_case['results']) count += 1 self.assertEqual(count, 13, "There are 13 deparser tests, not all ran.") ## ## # Test BUILD_LIST, BUILD_TUPLE ## builder = lambda a, b: [a, min(b)] ## self.assertEqual(astwalk.LambdaDeparser(builder).code(), ## "lambda a, b: [a, min(b)]") ## builder = lambda a, b, c: (c, [b.next(), a], c.ID) ## self.assertEqual(astwalk.LambdaDeparser(builder).code(), ## "lambda a, b, c: (c, [b.next(), a], c.ID)") ## ## # Test MapStackObject ## e = lambda t: {'x': 3, 'y': 5} ## ld = astwalk.LambdaDeparser(e) ## c = ld.code() ## self.assertEqual(c, "lambda t: {'y': 5, 'x': 3}", (c, ld.stack)) ## ## e = lambda t:{'x':{'a':10}, 'y':5} ## ld = astwalk.LambdaDeparser(e) ## c = ld.code() ## self.assertEqual(c, "lambda t: {'y': 5, 'x': {'a': 10}}", (c, ld.stack)) ## ## e = lambda t:{'x':str({'a':10}), 'y':5} ## ld = astwalk.LambdaDeparser(e) ## c = ld.code() ## self.assertEqual(c, "lambda t: {'y': 5, 'x': str({'a': 10})}", (c, ld.stack)) ## ## e = lambda t: [{'x': 10}, {'y': 5}] ## ld = astwalk.LambdaDeparser(e) ## c = ld.code() ## self.assertEqual(c, "lambda t: [{'x': 10}, {'y': 5}]", (c, ld.stack)) ## if __name__ == "__main__": unittest.main(__name__)