def test_no_return_while__format(capsys): def f(): def g(): y = 0 x = 0 while x < 10: x = x + 1 while y < 10: y = y + 1 return g() try: parse(f) except MyiaSyntaxError: sys.excepthook(*sys.exc_info()) out, err = capsys.readouterr() reg_pattern = r"========================================" + \ r"========================================\n" + \ r"(.+?)/tests/test_parser\.py:(.+?)\n" + \ r"(.+?): def g\(\):\n" + \ r" \^\^\^\^\^\^\^\^\n" + \ r"(.+?): y = 0\n" + \ r" \^\^\^\^\^\^\^\^\^\n" + \ r"(.+?): x = 0\n" + \ r" \^\^\^\^\^\^\^\^\^\n" + \ r"(.+?): while x < 10:\n" + \ r" \^\^\^\^\^\^\^\^\^\^\^\^\^\^\^\^\^\n" + \ r"(.+?): x = x \+ 1\n" + \ r" \^\^\^\^\^\^\^\^\^\^\^\^\^\^\^\^\^\n" + \ r"(.+?): while y < 10:\n" + \ r" \^\^\^\^\^\^\^\^\^\^\^\^\^\^\^\^\^\n" + \ r"(.+?): y = y \+ 1\n" + \ r" \^\^\^\^\^\^\^\^\^\^\^\^\^\^\^\^\^\n" + \ r"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + \ r"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + \ r"MyiaSyntaxError: Function doesn't return a value in all cases" regex = re.compile(reg_pattern) match = re.match(regex, err) assert match is not None
def test_clone_inline(): def f(x, y): a = x * x b = y * y c = a + b return c g = parse(f) target = _graph_for_inline() new_params = [ONE, TWO] cl = GraphCloner(inline=(g, target, new_params), clone_constants=False) _successful_inlining(cl, g, new_params, target)
def test_no_return__format(capsys): def f(): pass try: parse(f) except MyiaSyntaxError: sys.excepthook(*sys.exc_info()) out, err = capsys.readouterr() reg_pattern = (r"========================================" + r"========================================\n" + r"(.+?)/tests/test_parser\.py:(.+?)\n" + r"(.+?): def f\(\):\n" + r"(.+?) \^\^\^\^\^\^\^\^\n" + r"(.+?): pass\n" + r"(.+?) \^\^\^\^\^\^\^\^\n" + r"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + r"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + r"MyiaSyntaxError: Function doesn't return a value") regex = re.compile(reg_pattern) match = re.match(regex, err) assert match is not None
def test_clone_inline(): def f(x, y): a = x * x b = y * y c = a + b return c g = parse(f) cl = GraphCloner(clone_constants=False) target = _graph_for_inline() new_params = [ONE, TWO] cl.add_clone(g, target, new_params) # We ask twice to test that this doesn't cause problems cl.add_clone(g, target, new_params) _successful_inlining(cl, g, new_params, target)
def test_clone_total(): def f1(x): return x * x def f2(y): return f1(y) + 3 g = parse(f2) idx0 = GraphIndex(g) cl1 = GraphCloner(g, clone_constants=True, total=True) idx1 = GraphIndex(cl1[g]) assert idx1['f2'] is not idx0['f2'] assert idx1['f1'] is not idx0['f1'] cl2 = GraphCloner(g, clone_constants=True, total=False) idx2 = GraphIndex(cl2[g]) assert idx2['f2'] is not idx0['f2'] assert idx2['f1'] is idx0['f1']
def test_unsupported_AST__error(): def a1(): pass with pytest.raises(MyiaSyntaxError): parse(a1) def a2(): import builtins # noqa: F401 with pytest.raises(MyiaSyntaxError): parse(a2) def a3(): assert False with pytest.raises(MyiaSyntaxError): parse(a3)
def test_clone_closure(): def f(x, y): def j(z): a = x + y b = a + z return b c = j(3) return c parsed_f = parse(f) idx = GraphIndex(parsed_f) g = idx['j'] cl = GraphCloner(g, clone_constants=True) idx2 = GraphIndex(cl[g], succ=succ_incoming) for name in 'xy': assert idx[name] is idx2[name] for name in 'zabj': assert idx[name] is not idx2[name]
def test_clone_recursive(): def f(x, y): a = x * x b = y * y return f(a, b) g = parse(f) cl = GraphCloner(g, clone_constants=True) g2 = cl[g] d1 = set(dfs(g.return_, succ_deeper)) d2 = set(dfs(g2.return_, succ_deeper)) # Both node sets should be disjoint assert d1 & d2 == set() # Now test inlining cl2 = GraphCloner(clone_constants=True) target = _graph_for_inline() new_params = [ONE, TWO] cl2.add_clone(g, target, new_params) _successful_inlining(cl2, g, new_params, target) # The recursive call still refers to the original graph new_nodes = set(dfs(cl2[g.output], succ_deeper)) assert any(node.value is g for node in new_nodes) # Now test that inlining+total will fail cl2 = GraphCloner(total=True, clone_constants=True) target = _graph_for_inline() new_params = [ONE, TWO] with pytest.raises(Exception): cl2.add_clone(g, target, new_params) cl2[g.output]
def test_dfs_variants(): def f(x): z = x * x def g(y): return y + z w = z + 3 q = g(w) return q graph = parse(f) (inner_graph_ct, ) = [ x for x in dfs(graph.return_) if x.is_constant_graph() ] inner_graph = inner_graph_ct.value inner_ret = inner_graph.return_ deep = _name_nodes(_dfs(inner_ret, succ_deep)) assert deep == set("return scalar_add y z scalar_mul x".split()) deeper = _name_nodes(_dfs(inner_ret, succ_deeper)) assert deeper == set("return scalar_add y z scalar_mul x w 3 q g".split()) _bound_fv = freevars_boundary(inner_graph, True) bound_fv = _name_nodes(_dfs(inner_ret, succ_deeper, _bound_fv)) assert bound_fv == set("return scalar_add y z".split()) _no_fv = freevars_boundary(inner_graph, False) no_fv = _name_nodes(_dfs(inner_ret, succ_deeper, _no_fv)) assert no_fv == set("return scalar_add y".split()) _excl_root = exclude_from_set([inner_ret]) excl_root = _name_nodes(_dfs(inner_ret, succ_deeper, _excl_root)) assert excl_root == set()
def test_undefined(): def f(): return c # noqa with pytest.raises(NameError): parse(f)
def test_unsupported(): def f(): assert False with pytest.raises(MyiaSyntaxError): parse(f)
def test_disconnected_from_output__warning__format(capsys): def a0(): print(1) return 1 with warnings.catch_warnings(record=True) as w: parse(a0) wa = tuple(w[0].__dict__.values())[:6] myia_warning(*wa) out, err = capsys.readouterr() reg_pattern = r"========================================" + \ r"========================================\n" + \ r"(.+?)/tests/test_parser\.py:(.+?)\n" + \ r"(.+?): print\(1\)\n" + \ r"(.+?) \^\^\^\^\^\^\^\^\n" + \ r"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + \ r"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + \ r"MyiaDisconnectedCodeWarning: " + \ r"Expression was not assigned to a variable\.\n" + \ r"\tAs a result, it is not connected to the output " + \ r"and will not be executed\." regex = re.compile(reg_pattern) match = re.match(regex, err) assert match is not None ######################################################################### def a1(): x = 1 while x < 5: x = x + 1 print(1) return 1 with warnings.catch_warnings(record=True) as w: parse(a1) wa = tuple(w[0].__dict__.values())[:6] myia_warning(*wa) out, err = capsys.readouterr() reg_pattern = r"========================================" + \ r"========================================\n" + \ r"(.+?)/tests/test_parser\.py:(.+?)\n" + \ r"(.+?): print\(1\)\n" + \ r"(.+?) \^\^\^\^\^\^\^\^\n" + \ r"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + \ r"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + \ r"MyiaDisconnectedCodeWarning: " + \ r"Expression was not assigned to a variable\.\n" + \ r"\tAs a result, it is not connected to the output " + \ r"and will not be executed\." regex = re.compile(reg_pattern) match = re.match(regex, err) assert match is not None ######################################################################### def a2(): def b2(): return 1 b2() return 1 with warnings.catch_warnings(record=True) as w: parse(a2) wa = tuple(w[0].__dict__.values())[:6] myia_warning(*wa) out, err = capsys.readouterr() reg_pattern = r"========================================" + \ r"========================================\n" + \ r"(.+?)/tests/test_parser\.py:(.+?)\n" + \ r"(.+?): b2\(\)\n" + \ r"(.+?) \^\^\^\^\n" + \ r"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + \ r"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + \ r"MyiaDisconnectedCodeWarning: " + \ r"Expression was not assigned to a variable\.\n" + \ r"\tAs a result, it is not connected to the output " + \ r"and will not be executed\." regex = re.compile(reg_pattern) match = re.match(regex, err) assert match is not None ######################################################################### def a3(): x = 1 # noqa: F841 return 1 with warnings.catch_warnings(record=True) as w: parse(a3) wa = tuple(w[0].__dict__.values())[:6] myia_warning(*wa) out, err = capsys.readouterr() reg_pattern = r"========================================" + \ r"========================================\n" + \ r"(.+?)/tests/test_parser\.py:(.+?)\n" + \ r"(.+?): x = 1 # noqa: F841\n" + \ r"(.+?) \^\n" + \ r"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + \ r"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + \ r"MyiaDisconnectedCodeWarning: x is not used " + \ r"and will therefore not be computed" regex = re.compile(reg_pattern) match = re.match(regex, err) assert match is not None ######################################################################### def a4(): def b4(): def c4(): x = 1 # noqa: F841 return 1 return c4() return b4 with warnings.catch_warnings(record=True) as w: parse(a4) wa = tuple(w[0].__dict__.values())[:6] myia_warning(*wa) out, err = capsys.readouterr() reg_pattern = r"========================================" + \ r"========================================\n" + \ r"(.+?)/tests/test_parser\.py:(.+?)\n" + \ r"(.+?): x = 1 # noqa: F841\n" + \ r"(.+?) \^\n" + \ r"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + \ r"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + \ r"MyiaDisconnectedCodeWarning: x is not used " + \ r"and will therefore not be computed" regex = re.compile(reg_pattern) match = re.match(regex, err) assert match is not None
def test_no_return(): def f(): """Hello, there is nothing here!""" with pytest.raises(MyiaSyntaxError): parse(f)
def test_disconnected_from_output__warning(): def a0(): print(1) return 1 with pytest.warns(MyiaDisconnectedCodeWarning): parse(a0) def a1(): x = 1 while x < 5: x = x + 1 print(1) return 1 with pytest.warns(MyiaDisconnectedCodeWarning): parse(a1) def a2(): def b2(): return 1 b2() return 1 with pytest.warns(MyiaDisconnectedCodeWarning): parse(a2) # This tests that comments are not raised as warnings. def a3(): """Comment: Blah Blah Blah """ return 1 with pytest.warns(None) as record: parse(a3) assert len(record) == 0 def a4(): x = 1 # noqa: F841 return 1 with pytest.warns(MyiaDisconnectedCodeWarning): parse(a4) def a5(): def b5(): def c5(): x = 1 # noqa: F841 return 1 return c5() return b5 with pytest.warns(MyiaDisconnectedCodeWarning): parse(a5)
def test_dict(): def bad(x): return {x: 2} with pytest.raises(MyiaSyntaxError): parse(bad)
def test_unsupported_AST__error__format(capsys): def a1(): pass return 1 try: parse(a1) except MyiaSyntaxError: sys.excepthook(*sys.exc_info()) out, err = capsys.readouterr() reg_pattern = r"========================================" + \ r"========================================\n" + \ r"(.+?)/tests/test_parser\.py:(.+?)\n" + \ r"(.+?): pass\n" + \ r"(.+?) \^\^\^\^\n" + \ r"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + \ r"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + \ r"MyiaSyntaxError: Pass not supported" regex = re.compile(reg_pattern) match = re.match(regex, err) assert match is not None ######################################################################### def a2(): import builtins # noqa: F401 return 1 try: parse(a2) except MyiaSyntaxError: sys.excepthook(*sys.exc_info()) out, err = capsys.readouterr() reg_pattern = r"========================================" + \ r"========================================\n" + \ r"(.+?)/tests/test_parser\.py:(.+?)\n" + \ r"(.+?): import builtins # noqa: F401\n" + \ r"(.+?) \^\^\^\^\^\^\^\^\^\^\^\^\^\^\^\n" + \ r"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + \ r"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + \ r"MyiaSyntaxError: Import not supported" regex = re.compile(reg_pattern) match = re.match(regex, err) assert match is not None ######################################################################### def a3(): assert True return 1 try: parse(a3) except MyiaSyntaxError: sys.excepthook(*sys.exc_info()) out, err = capsys.readouterr() reg_pattern = r"========================================" + \ r"========================================\n" + \ r"(.+?)/tests/test_parser\.py:(.+?)\n" + \ r"(.+?): assert True\n" + \ r"(.+?) \^\^\^\^\^\^\^\^\^\^\^\n" + \ r"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + \ r"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + \ r"MyiaSyntaxError: Assert not supported" regex = re.compile(reg_pattern) match = re.match(regex, err) assert match is not None
def test_defined_later(): def f(): return c # noqa with pytest.raises(UnboundLocalError): parse(f) c = 3