def example_1() -> ast.Program: """ Instantiates program example 1 as a native AST """ return ast.Program( ast.Body([ # source = live remote "www.coviddata.com/stream" ast.Loader(ast.Var("source"), ast.Source("www.coviddata.com/stream")), # map source "case_date" to number date ast.Mapper(ast.Var("source"), "case_date", ast.Declare(ast.Type(Types.NUMBER), ast.Var("date"))), # number count = 0 ast.Assigner(ast.Declare(ast.Type(Types.NUMBER), ast.Var("count")), ast.Value(IntegerValue(0))), # on new data from source count++ ast.Trigger(ast.Var("source"), ast.MathFuncs([ast.Increment(ast.Var( "count"))])), # plot xy date age titled age_graph ast.Plotter(ast.Graph(ScatterXYGraph()), ast.VarAxis(ast.Var("date")), ast.VarAxis(ast.Var("age")), "age_graph"), # plot line xy date log(count) titled cases_log ast.Plotter(ast.Graph(LineXYGraph()), ast.VarAxis(ast.Var("date")), ast.FuncAxis(ast.BuiltinFunc(NumFunction.LOG, ast.Var( "count"))), "age_graph"), ]))
def simple_plot_example() -> ast.Program: return ast.Program(ast.Body([ ast.Plotter(ast.Graph(ScatterXYGraph()), ast.VarAxis(ast.Var("t")), ast.FuncAxis(ast.BuiltinFunc(NumFunction.SIN, ast.Var( "t"))), "sine_wave"), ]))
def test_invalid_host(self): e = Evaluator() p = ast.Program( ast.Body([ ast.Loader(ast.Var("source"), ast.Source("https://covid-apiiii.com/api/reports")), ast.Trigger(ast.Var("source"), ast.MathFuncs([ast.Increment(ast.Var( "count"))])), ])) code, err = e.evaluate(p, duration=4000) self.assertNotEqual(0, code) self.assertTrue(isinstance(err, DataLoaderError))
def test_duplicate_name(self): e = Evaluator() p = ast.Program( ast.Body([ ast.Loader(ast.Var("source"), ast.Source("www.source.com")), ast.Loader(ast.Var("source"), ast.Source("www.source2.com")), ])) code, err = e.evaluate(p, duration=4000) self.assertNotEqual(0, code) self.assertTrue(isinstance(err, DataLoaderError))
def test_simple_func_baseline(self): e = Evaluator() p = ast.Program( ast.Body([ ast.Loader(ast.Var("source"), ast.Source("https://covid-api.com/api/reports")), ast.Assigner(ast.Declare(ast.Type(Types.NUMBER), ast.Var("count")), ast.Value(IntegerValue(20))), ast.Trigger(ast.Var("source"), ast.MathFuncs([])), ])) code, err = e.evaluate(p, duration=7000) self.assertEqual(0, code) self.assertEqual(20, cast(IntegerValue, e.env.get_val("count")).value)
def test_valid_source(self): e = Evaluator() p = ast.Program( ast.Body([ ast.Loader(ast.Var("source"), ast.Source("https://covid-api.com/api/reports")), ast.Assigner(ast.Declare(ast.Type(Types.NUMBER), ast.Var("count")), ast.Value(IntegerValue(0))), ast.Trigger(ast.Var("source"), ast.MathFuncs([ast.Increment(ast.Var( "count"))])), ])) code, err = e.evaluate(p, duration=4000) self.assertEqual(0, code)
def test_pow_overflow(self): e = Evaluator() p = ast.Program( ast.Body([ ast.Loader(ast.Var("source"), ast.Source("https://covid-api.com/api/reports")), ast.Assigner(ast.Declare(ast.Type(Types.NUMBER), ast.Var("count")), ast.Value(FloatValue(1.1))), ast.Trigger(ast.Var("source"), ast.MathFuncs([ast.SimpleFunc( ast.Var("count"), ast.Operand(ConcreteNumOp.EXP), ast.Value(IntegerValue(2)))])), ])) code, err = e.evaluate(p, duration=10000) self.assertNotEqual(0, code)
def test_diff_math_funcs_(self): self.assertFalse( ast_equal( ast.Program( ast.Body([ ast.Trigger( ast.Var("source"), ast.MathFuncs([ast.Increment(ast.Var("count"))])) ])), ast.Program( ast.Body([ ast.Trigger( ast.Var("source"), ast.MathFuncs([ast.Decrement(ast.Var("count"))])) ]))))
def test_identical_commands(self): self.assertTrue( ast_equal( ast.Program( ast.Body([ ast.commands_ast.Loader( ast.Var("source"), ast.Source("www.coviddata.com/stream")), ])), ast.Program( ast.Body([ ast.commands_ast.Loader( ast.Var("source"), ast.Source("www.coviddata.com/stream")), ]))))
def test_different_load_var_names(self): self.assertFalse( ast_equal( ast.Program( ast.Body([ ast.commands_ast.Loader( ast.Var("source"), ast.Source("www.coviddata.com/stream")), ])), ast.Program( ast.Body([ ast.commands_ast.Loader( ast.Var("source1"), ast.Source("www.coviddata.com/stream")), ]))))
def test_diff_load_url(self): self.assertFalse( ast_equal( ast.Program( ast.Body([ ast.commands_ast.Loader( ast.Var("source"), ast.Source("https://www.coviddata.com/stream")), ])), ast.Program( ast.Body([ ast.commands_ast.Loader( ast.Var("source"), ast.Source("www.coviddata.com/stream")), ]))))
def test_diff_commands(self): self.assertFalse( ast_equal( ast.Program( ast.Body([ ast.commands_ast.Loader( ast.Var("source"), ast.Source("www.coviddata.com/stream")), ])), ast.Program( ast.Body([ ast.Mapper( ast.Var("source"), "case_date", ast.Declare(ast.Type(Types.NUMBER), ast.Var("date"))) ]))))
def parseSimpFunc(self) -> ast.SimpleFunc: var = ast.Var(self.tokenizer.get_next()) op = self.tokenizer.get_next() op += self.tokenizer.get_next() concrete_op: NumOp = self.operators[op] value = self.parseValue() return ast.SimpleFunc(var, ast.Operand(concrete_op), value)
def parseFastFunc(self) -> ast.FastFunc: token = self.tokenizer.get_next() var = ast.Var(token[:-2]) operator = token[-2:] if operator == '++': return ast.Increment(var) else: return ast.Decrement(var)
def test_diff_map_declare_var(self): self.assertFalse( ast_equal( ast.Program( ast.Body([ ast.Mapper( ast.Var("source"), "case_date", ast.Declare(ast.Type(Types.NUMBER), ast.Var("date"))) ])), ast.Program( ast.Body([ ast.Mapper( ast.Var("source"), "case_date", ast.Declare(ast.Type(Types.NUMBER), ast.Var("count"))) ]))))
def parseVar(self) -> ast.Var: v = self.tokenizer.get_next() if v.startswith(")") or not v: raise ParseError("No variable found") elif v[0].isupper(): raise ParseError("Variables must start with a lowercase") elif v[0].isdigit(): raise ParseError("Variables cannot start with a number") else: return ast.Var(v)
def test_plot_undefined_axis(self): """ Should briefly create a plot then error """ print("Testing undefined variable in Axis") program = ast.Program( ast.Body([ ast.Loader(ast.Var("source"), ast.Source("https://covid-api.com/api/reports")), ast.Mapper( ast.Var("source"), "confirmed", ast.Declare(ast.Type(Types.NUMBER), ast.Var("confirmed"))), ast.Plotter( ast.Graph(ScatterXYGraph()), ast.VarAxis(ast.Var("t")), ast.FuncAxis(ast.BuiltinFunc(NumFunction.SIN, ast.Var("t"))), "sine_wave"), ])) e = Evaluator(graphics=False) code, err = e.evaluate(program, duration=4000) self.assertNotEqual(0, code) self.assertTrue(isinstance(err, UndefinedVariableError))
def test_program_construction(self): try: v: ast.Var = ast.Var("placeholder") t: ast.Type = ast.Type(primitives.Types.NUMBER) d: ast.Declare = ast.Declare(t, v) b: ast.Body = ast.Body([ ast.commands_ast.Assigner(d, 4), ast.commands_ast.Assigner(d, "hello") ]) p: ast.Program = ast.Program(b) except TypeError: self.fail("Failed to build")
def test_regular(self): p_expected: ast.Program = ast.Program( ast.Body([ # source = live remote "https://covid-api.com/api/reports" ast.Loader(ast.Var("source"), ast.Source("https://covid-api.com/api/reports")), # map source "confirmed" to number confirmed ast.Mapper( ast.Var("source"), "confirmed", ast.Declare(ast.Type(Types.NUMBER), ast.Var("confirmed"))), # number count = 0 ast.Assigner( ast.Declare(ast.Type(Types.NUMBER), ast.Var("count")), ast.Value(values.IntegerValue(0))), # observe(source) do count++ ast.Trigger(ast.Var("source"), ast.MathFuncs([ast.Increment(ast.Var("count"))])), # plot line_xy(count,confirmed) called "confirmed_cases" ast.Plotter(ast.Graph(graphs.LineXYGraph()), ast.VarAxis(ast.Var("count")), ast.VarAxis(ast.Var("confirmed")), "confirmed_cases"), ])) def parse(content) -> ast.Program: t = Tokenizer(content) t.tokenize() return Parser(t).parseProgram() p: ast.Program = read_program_file( "tests/res/programs/regular_program.mstx", parse) self.assertTrue(ast_equal(p_expected, p))
def test_regular_program(self): """ Should successfully create a plot and update with new values """ print("Testing a full program") p = ast.Program( ast.Body([ # source = live remote "https://covid-api.com/api/reports" ast.Loader(ast.Var("source"), ast.Source("https://covid-api.com/api/reports")), # map source "confirmed" to number confirmed ast.Mapper( ast.Var("source"), "confirmed", ast.Declare(ast.Type(Types.NUMBER), ast.Var("confirmed"))), # number count = 0 ast.Assigner( ast.Declare(ast.Type(Types.NUMBER), ast.Var("count")), ast.Value(values.IntegerValue(0))), # observe(source) do count++ ast.Trigger(ast.Var("source"), ast.MathFuncs([ast.Increment(ast.Var("count"))])), # plot line_xy(count,confirmed) called "confirmed_cases" ast.Plotter(ast.Graph(graphs.LineXYGraph()), ast.VarAxis(ast.Var("count")), ast.VarAxis(ast.Var("confirmed")), "confirmed_cases"), ])) e = Evaluator(graphics=True) code, err = e.evaluate(p, duration=7000) self.assertEqual(0, code)