Example #1
0
def test_eval_assignment():
    ctx = Context()

    # Do not allow assigning to non-trivial expressions
    ast, _ = exp.parse('(1+1*x)*9')
    with raises(Exception):
        ast.value = 10

    # Do not allow assigning to built-in constants
    ast, _ = exp.parse('True')
    with raises(Exception):
        ast.value = 10

    # Do not allow assigning to function calls
    ast, _ = exp.parse('f(1)')
    with raises(Exception):
        ast.value = 10

    # Do not allow assigning to constant lists
    ast, _ = exp.parse("[1,2,3,4]")
    with raises(Exception):
        ast.value = 10

    # Do not allow assigning to constants
    ast, _ = exp.parse("'ahoj'")
    with raises(Exception):
        ast.value = 10

    # Allow assigning to non-existing variables
    ast, _ = exp.parse('x')
    ast.bind_ctx(ctx)
    ast.value = 10
    assert ctx.x == 10

    # Allow assigning to existing variables
    ast.value = 20
    assert ctx.x == 20

    # Allow assigning to list elements
    ctx.lst = [1, 2, 3]
    ctx.x = 0
    ast, _ = exp.parse("lst[x]")
    ast.bind_ctx(ctx)
    ast.value = 20
    assert ctx.lst[0] == 20

    # Allow assigning to non-existing object attributes
    ctx.obj = Context()
    ast, _ = exp.parse('obj.test')
    ast.bind_ctx(ctx)
    ast.value = 30987
    assert ctx.obj.test == 30987

    # Allow assigning to existing object attributes
    ast.value = 40
    assert ctx.obj.test == 40
Example #2
0
def test_parse():
    ctx = Context()

    # Test Simple Arithmetic Expressions
    ast, _ = exp.parse('(1+1*8)*9')
    assert ast.evalctx(ctx) is 81

    # Test Simple Arithmetic Expressions
    ast, _ = exp.parse('(1-1)')
    assert ast.evalctx(ctx) is 0

    # Test Simple Arithmetic Expressions
    ast, _ = exp.parse('(-1)')
    assert ast.evalctx(ctx) is -1

    # Test Boolean Expressions
    ast, _ = exp.parse('True and False')
    assert ast.evalctx(ctx) is False

    ast, _ = exp.parse('True and not False')
    assert ast.evalctx(ctx) is True

    # Test is
    ast, _ = exp.parse("1 is None")
    assert ast.evalctx(ctx) is False

    ast, _ = exp.parse("None is None")
    assert ast.evalctx(ctx) is True

    ast, _ = exp.parse("False is not None")
    assert ast.evalctx(ctx) is True

    # Test Slices
    ctx.s = "abcde"
    ast, _ = exp.parse('s[-1]')
    assert ast.evalctx(ctx) == 'e'
    ast, _ = exp.parse('s[0]')
    assert ast.evalctx(ctx) == 'a'
    ast, _ = exp.parse('s[1:3]')
    assert ast.evalctx(ctx) == 'bc'
    ast, _ = exp.parse('s[0:-1:2]')
    assert ast.evalctx(ctx) == 'ac'
    ast, _ = exp.parse('s[1:]')
    assert ast.evalctx(ctx) == 'bcde'
    ast, _ = exp.parse('s[:-1]')
    assert ast.evalctx(ctx) == 'abcd'

    # Test Lists
    ast, _ = exp.parse('[1,2,3,4]')
    assert ast.evalctx(ctx) == [1, 2, 3, 4]

    # Test Comprehension
    ast, _ = exp.parse('[p+1 for p in [1,2,3,4]]')
    assert ast.evalctx(ctx) == [2, 3, 4, 5]

    ast, _ = exp.parse('[p+1 for p in [1,2,3,4] if p%2==0]')
    assert ast.evalctx(ctx) == [3, 5]

    # Test Builtins
    ast, _ = exp.parse("str(10)")
    assert ast.evalctx(ctx) == "10"

    ast, _ = exp.parse("int('21')")
    assert ast.evalctx(ctx) == 21

    ast, _ = exp.parse("len([1,2,3])")
    assert ast.evalctx(ctx) == 3

    ctx.str = lambda x: "str(" + str(x) + ")"
    ast, _ = exp.parse("str(10)")
    assert str(ast) == "str(10)"
    del ctx.str

    # Test Object Access
    ctx.obj = Context()
    ctx.obj.a = 10
    ctx.obj.b = Context()
    ctx.obj.b.c = 20
    ctx.obj.d = [Context({'a': 30})]

    ast, _ = exp.parse('obj.a')
    assert ast.evalctx(ctx) == 10

    ast, _ = exp.parse('obj.b.c')
    assert ast.evalctx(ctx) == 20

    ast, _ = exp.parse('obj.d[0].a')
    assert ast.evalctx(ctx) == 30

    # Test Array Access
    ast, _ = exp.parse('mylst[0][1][2]')
    ctx.mylst = [[None, [None, None, "Ahoj"]]]
    assert ast.evalctx(ctx) == "Ahoj"

    # Test String slices
    ast, _ = exp.parse('"ahoj"[1:]')
    assert ast.evalctx(ctx) == "hoj"
    ast, _ = exp.parse('"ahoj"[:1]')
    assert ast.evalctx(ctx) == "a"
    ast, _ = exp.parse('"ahoj"[-1]')
    assert ast.evalctx(ctx) == "j"

    # Test array concatenation
    ast, _ = exp.parse('([0]+["mixin"])[1]')
    assert ast.evalctx(ctx) == "mixin"

    # Test Function Calls
    ast, _ = exp.parse('"a,b,c,d".split(",")')
    assert ast.evalctx(ctx) == ['a', 'b', 'c', 'd']

    ctx.func = lambda x, ev: str(x + 10) + ev
    ctx.ch = 20
    ctx.s = 'Hi'
    ast, _ = exp.parse("func(ch,ev=s)")
    ast.bind_ctx(ctx)
    ctx.s = 'Hello'
    assert ast.eval() == '30Hello'
    assert ast.evalctx(ctx) == '30Hello'

    # Test Complex Expressions
    expr = '(1+2*obj.a - 10)'
    ast, _ = exp.parse(expr)
    assert ast.evalctx(ctx) == 11

    expr = '[(1+2*a[1+3] - 10) for a in [[2,1,2,3,4,5],[1,2],[2,2,2,2,2,2,2]] if a[0] % 2 == 0]'
    ast, _ = exp.parse(expr)
    assert ast.evalctx(ctx) == [-1, -5]

    # Test parse cache
    for i in range(10):
        expr = '[(1+2*a[1+3] - 10) for a in [[2,1,2,3,4,5],[1,2],[2,2,2,2,2,2,2]] if a[0] % 2 == 0]'
        ast, _ = exp.parse(expr)
        assert ast.evalctx(ctx) == [-1, -5]