# -*- coding: utf-8 -*- """Tests the xonsh parser.""" import ast import builtins import textwrap import itertools import pytest from xonsh.ast import AST, With, Pass from xonsh.parser import Parser from tools import VER_FULL, skip_if_py34, nodes_equal # a lot of col_offset data changed from Py v3.5.0 -> v3.5.1 INC_ATTRS = (3, 5, 1) <= VER_FULL @pytest.fixture(autouse=True) def xonsh_builtins_autouse(xonsh_builtins): return xonsh_builtins PARSER = Parser(lexer_optimize=False, yacc_optimize=False, yacc_debug=True) def check_ast(inp, run=True, mode='eval'): __tracebackhide__ = True # expect a Python AST exp = ast.parse(inp, mode=mode) # observe something from xonsh obs = PARSER.parse(inp, debug_level=0) # Check that they are equal assert nodes_equal(exp, obs) # round trip by running xonsh AST via Python if run: exec(compile(obs, '', mode)) def check_stmts(inp, run=True, mode='exec'): __tracebackhide__ = True if not inp.endswith('\n'): inp += '\n' check_ast(inp, run=run, mode=mode) def check_xonsh_ast(xenv, inp, run=True, mode='eval', debug_level=0, return_obs=False): __tracebackhide__ = True builtins.__xonsh_env__ = xenv obs = PARSER.parse(inp, debug_level=debug_level) if obs is None: return # comment only bytecode = compile(obs, '', mode) if run: exec(bytecode) return obs if return_obs else True def check_xonsh(xenv, inp, run=True, mode='exec'): __tracebackhide__ = True if not inp.endswith('\n'): inp += '\n' check_xonsh_ast(xenv, inp, run=run, mode=mode) # # Tests # # # expressions # def test_int_literal(): check_ast('42') def test_float_literal(): check_ast('42.0') def test_imag_literal(): check_ast('42j') def test_float_imag_literal(): check_ast('42.0j') def test_complex(): check_ast('42+84j') def test_str_literal(): check_ast('"hello"') def test_bytes_literal(): check_ast('b"hello"') check_ast('B"hello"') def test_raw_literal(): check_ast('r"hell\o"') check_ast('R"hell\o"') def test_raw_bytes_literal(): check_ast('br"hell\o"') check_ast('RB"hell\o"') check_ast('Br"hell\o"') check_ast('rB"hell\o"') def test_unary_plus(): check_ast('+1') def test_unary_minus(): check_ast('-1') def test_unary_invert(): check_ast('~1') def test_binop_plus(): check_ast('42 + 65') def test_binop_minus(): check_ast('42 - 65') def test_binop_times(): check_ast('42 * 65') @skip_if_py34 def test_binop_matmult(): check_ast('x @ y', False) def test_binop_div(): check_ast('42 / 65') def test_binop_mod(): check_ast('42 % 65') def test_binop_floordiv(): check_ast('42 // 65') def test_binop_pow(): check_ast('2 ** 2') def test_plus_pow(): check_ast('42 + 2 ** 2') def test_plus_plus(): check_ast('42 + 65 + 6') def test_plus_minus(): check_ast('42 + 65 - 6') def test_minus_plus(): check_ast('42 - 65 + 6') def test_minus_minus(): check_ast('42 - 65 - 6') def test_minus_plus_minus(): check_ast('42 - 65 + 6 - 28') def test_times_plus(): check_ast('42 * 65 + 6') def test_plus_times(): check_ast('42 + 65 * 6') def test_times_times(): check_ast('42 * 65 * 6') def test_times_div(): check_ast('42 * 65 / 6') def test_times_div_mod(): check_ast('42 * 65 / 6 % 28') def test_times_div_mod_floor(): check_ast('42 * 65 / 6 % 28 // 13') def test_str_str(): check_ast('"hello" \'mom\'') def test_str_str_str(): check_ast('"hello" \'mom\' "wow"') def test_str_plus_str(): check_ast('"hello" + \'mom\'') def test_str_times_int(): check_ast('"hello" * 20') def test_int_times_str(): check_ast('2*"hello"') def test_group_plus_times(): check_ast('(42 + 65) * 20') def test_plus_group_times(): check_ast('42 + (65 * 20)') def test_group(): check_ast('(42)') def test_lt(): check_ast('42 < 65') def test_gt(): check_ast('42 > 65') def test_eq(): check_ast('42 == 65') def test_le(): check_ast('42 <= 65') def test_ge(): check_ast('42 >= 65') def test_ne(): check_ast('42 != 65') def test_in(): check_ast('"4" in "65"') def test_is(): check_ast('42 is 65') def test_not_in(): check_ast('"4" not in "65"') def test_is_not(): check_ast('42 is not 65') def test_lt_lt(): check_ast('42 < 65 < 105') def test_lt_lt_lt(): check_ast('42 < 65 < 105 < 77') def test_not(): check_ast('not 0') def test_or(): check_ast('1 or 0') def test_or_or(): check_ast('1 or 0 or 42') def test_and(): check_ast('1 and 0') def test_and_and(): check_ast('1 and 0 and 2') def test_and_or(): check_ast('1 and 0 or 2') def test_or_and(): check_ast('1 or 0 and 2') def test_group_and_and(): check_ast('(1 and 0) and 2') def test_group_and_or(): check_ast('(1 and 0) or 2') def test_if_else_expr(): check_ast('42 if True else 65') def test_if_else_expr_expr(): check_ast('42+5 if 1 == 2 else 65-5') def test_str_idx(): check_ast('"hello"[0]') def test_str_slice(): check_ast('"hello"[0:3]') def test_str_step(): check_ast('"hello"[0:3:1]') def test_str_slice_all(): check_ast('"hello"[:]') def test_str_slice_upper(): check_ast('"hello"[5:]') def test_str_slice_lower(): check_ast('"hello"[:3]') def test_str_slice_other(): check_ast('"hello"[::2]') def test_str_slice_lower_other(): check_ast('"hello"[:3:2]') def test_str_slice_upper_other(): check_ast('"hello"[3::2]') def test_str_2slice(): check_ast('"hello"[0:3,0:3]', False) def test_str_2step(): check_ast('"hello"[0:3:1,0:4:2]', False) def test_str_2slice_all(): check_ast('"hello"[:,:]', False) def test_str_2slice_upper(): check_ast('"hello"[5:,5:]', False) def test_str_2slice_lower(): check_ast('"hello"[:3,:3]', False) def test_str_2slice_lowerupper(): check_ast('"hello"[5:,:3]', False) def test_str_2slice_other(): check_ast('"hello"[::2,::2]', False) def test_str_2slice_lower_other(): check_ast('"hello"[:3:2,:3:2]', False) def test_str_2slice_upper_other(): check_ast('"hello"[3::2,3::2]', False) def test_str_3slice(): check_ast('"hello"[0:3,0:3,0:3]', False) def test_str_3step(): check_ast('"hello"[0:3:1,0:4:2,1:3:2]', False) def test_str_3slice_all(): check_ast('"hello"[:,:,:]', False) def test_str_3slice_upper(): check_ast('"hello"[5:,5:,5:]', False) def test_str_3slice_lower(): check_ast('"hello"[:3,:3,:3]', False) def test_str_3slice_lowerlowerupper(): check_ast('"hello"[:3,:3,:3]', False) def test_str_3slice_lowerupperlower(): check_ast('"hello"[:3,5:,:3]', False) def test_str_3slice_lowerupperupper(): check_ast('"hello"[:3,5:,5:]', False) def test_str_3slice_upperlowerlower(): check_ast('"hello"[5:,5:,:3]', False) def test_str_3slice_upperlowerupper(): check_ast('"hello"[5:,:3,5:]', False) def test_str_3slice_upperupperlower(): check_ast('"hello"[5:,5:,:3]', False) def test_str_3slice_other(): check_ast('"hello"[::2,::2,::2]', False) def test_str_3slice_lower_other(): check_ast('"hello"[:3:2,:3:2,:3:2]', False) def test_str_3slice_upper_other(): check_ast('"hello"[3::2,3::2,3::2]', False) def test_str_slice_true(): check_ast('"hello"[0:3,True]', False) def test_str_true_slice(): check_ast('"hello"[True,0:3]', False) def test_list_empty(): check_ast('[]') def test_list_one(): check_ast('[1]') def test_list_one_comma(): check_ast('[1,]') def test_list_two(): check_ast('[1, 42]') def test_list_three(): check_ast('[1, 42, 65]') def test_list_three_comma(): check_ast('[1, 42, 65,]') def test_list_one_nested(): check_ast('[[1]]') def test_list_list_four_nested(): check_ast('[[1], [2], [3], [4]]') def test_list_tuple_three_nested(): check_ast('[(1,), (2,), (3,)]') def test_list_set_tuple_three_nested(): check_ast('[{(1,)}, {(2,)}, {(3,)}]') def test_list_tuple_one_nested(): check_ast('[(1,)]') def test_tuple_tuple_one_nested(): check_ast('((1,),)') def test_dict_list_one_nested(): check_ast('{1: [2]}') def test_dict_list_one_nested_comma(): check_ast('{1: [2],}') def test_dict_tuple_one_nested(): check_ast('{1: (2,)}') def test_dict_tuple_one_nested_comma(): check_ast('{1: (2,),}') def test_dict_list_two_nested(): check_ast('{1: [2], 3: [4]}') def test_set_tuple_one_nested(): check_ast('{(1,)}') def test_set_tuple_two_nested(): check_ast('{(1,), (2,)}') def test_tuple_empty(): check_ast('()') def test_tuple_one_bare(): check_ast('1,') def test_tuple_two_bare(): check_ast('1, 42') def test_tuple_three_bare(): check_ast('1, 42, 65') def test_tuple_three_bare_comma(): check_ast('1, 42, 65,') def test_tuple_one_comma(): check_ast('(1,)') def test_tuple_two(): check_ast('(1, 42)') def test_tuple_three(): check_ast('(1, 42, 65)') def test_tuple_three_comma(): check_ast('(1, 42, 65,)') def test_bare_tuple_of_tuples(): check_ast('(),') check_ast('((),),(1,)') check_ast('(),(),') check_ast('[],') check_ast('[],[]') check_ast('[],()') check_ast('(),[],') check_ast('((),[()],)') def test_set_one(): check_ast('{42}') def test_set_one_comma(): check_ast('{42,}') def test_set_two(): check_ast('{42, 65}') def test_set_two_comma(): check_ast('{42, 65,}') def test_set_three(): check_ast('{42, 65, 45}') def test_dict_empty(): check_ast('{}') def test_dict_one(): check_ast('{42: 65}') def test_dict_one_comma(): check_ast('{42: 65,}') def test_dict_two(): check_ast('{42: 65, 6: 28}') def test_dict_two_comma(): check_ast('{42: 65, 6: 28,}') def test_dict_three(): check_ast('{42: 65, 6: 28, 1: 2}') @skip_if_py34 def test_dict_from_dict_two_xy(): check_ast('{"x": 1, **{"y": 2}}') @skip_if_py34 def test_dict_from_dict_two_x_first(): check_ast('{"x": 1, **{"x": 2}}') @skip_if_py34 def test_dict_from_dict_two_x_second(): check_ast('{**{"x": 2}, "x": 1}') @skip_if_py34 def test_unpack_range_tuple(): check_stmts('*range(4),') @skip_if_py34 def test_unpack_range_tuple_4(): check_stmts('*range(4), 4') @skip_if_py34 def test_unpack_range_tuple_parens(): check_ast('(*range(4),)') @skip_if_py34 def test_unpack_range_tuple_parens_4(): check_ast('(*range(4), 4)') @skip_if_py34 def test_unpack_range_list(): check_ast('[*range(4)]') @skip_if_py34 def test_unpack_range_list_4(): check_ast('[*range(4), 4]') @skip_if_py34 def test_unpack_range_set(): check_ast('{*range(4)}') @skip_if_py34 def test_unpack_range_set_4(): check_ast('{*range(4), 4}') def test_true(): check_ast('True') def test_false(): check_ast('False') def test_none(): check_ast('None') def test_elipssis(): check_ast('...') def test_not_implemented_name(): check_ast('NotImplemented') def test_genexpr(): check_ast('(x for x in "mom")') def test_genexpr_if(): check_ast('(x for x in "mom" if True)') def test_genexpr_if_and(): check_ast('(x for x in "mom" if True and x == "m")') def test_dbl_genexpr(): check_ast('(x+y for x in "mom" for y in "dad")') def test_genexpr_if_genexpr(): check_ast('(x+y for x in "mom" if True for y in "dad")') def test_genexpr_if_genexpr_if(): check_ast('(x+y for x in "mom" if True for y in "dad" if y == "d")') def test_listcomp(): check_ast('[x for x in "mom"]') def test_listcomp_if(): check_ast('[x for x in "mom" if True]') def test_listcomp_if_and(): check_ast('[x for x in "mom" if True and x == "m"]') def test_dbl_listcomp(): check_ast('[x+y for x in "mom" for y in "dad"]') def test_listcomp_if_listcomp(): check_ast('[x+y for x in "mom" if True for y in "dad"]') def test_listcomp_if_listcomp_if(): check_ast('[x+y for x in "mom" if True for y in "dad" if y == "d"]') def test_setcomp(): check_ast('{x for x in "mom"}') def test_setcomp_if(): check_ast('{x for x in "mom" if True}') def test_setcomp_if_and(): check_ast('{x for x in "mom" if True and x == "m"}') def test_dbl_setcomp(): check_ast('{x+y for x in "mom" for y in "dad"}') def test_setcomp_if_setcomp(): check_ast('{x+y for x in "mom" if True for y in "dad"}') def test_setcomp_if_setcomp_if(): check_ast('{x+y for x in "mom" if True for y in "dad" if y == "d"}') def test_dictcomp(): check_ast('{x: x for x in "mom"}') def test_dictcomp_unpack_parens(): check_ast('{k: v for (k, v) in {"x": 42}.items()}') def test_dictcomp_unpack_no_parens(): check_ast('{k: v for k, v in {"x": 42}.items()}') def test_dictcomp_if(): check_ast('{x: x for x in "mom" if True}') def test_dictcomp_if_and(): check_ast('{x: x for x in "mom" if True and x == "m"}') def test_dbl_dictcomp(): check_ast('{x: y for x in "mom" for y in "dad"}') def test_dictcomp_if_dictcomp(): check_ast('{x: y for x in "mom" if True for y in "dad"}') def test_dictcomp_if_dictcomp_if(): check_ast('{x: y for x in "mom" if True for y in "dad" if y == "d"}') def test_lambda(): check_ast('lambda: 42') def test_lambda_x(): check_ast('lambda x: x') def test_lambda_kwx(): check_ast('lambda x=42: x') def test_lambda_x_y(): check_ast('lambda x, y: x') def test_lambda_x_y_z(): check_ast('lambda x, y, z: x') def test_lambda_x_kwy(): check_ast('lambda x, y=42: x') def test_lambda_kwx_kwy(): check_ast('lambda x=65, y=42: x') def test_lambda_kwx_kwy_kwz(): check_ast('lambda x=65, y=42, z=1: x') def test_lambda_x_comma(): check_ast('lambda x,: x') def test_lambda_x_y_comma(): check_ast('lambda x, y,: x') def test_lambda_x_y_z_comma(): check_ast('lambda x, y, z,: x') def test_lambda_x_kwy_comma(): check_ast('lambda x, y=42,: x') def test_lambda_kwx_kwy_comma(): check_ast('lambda x=65, y=42,: x') def test_lambda_kwx_kwy_kwz_comma(): check_ast('lambda x=65, y=42, z=1,: x') def test_lambda_args(): check_ast('lambda *args: 42') def test_lambda_args_x(): check_ast('lambda *args, x: 42') def test_lambda_args_x_y(): check_ast('lambda *args, x, y: 42') def test_lambda_args_x_kwy(): check_ast('lambda *args, x, y=10: 42') def test_lambda_args_kwx_y(): check_ast('lambda *args, x=10, y: 42') def test_lambda_args_kwx_kwy(): check_ast('lambda *args, x=42, y=65: 42') def test_lambda_x_args(): check_ast('lambda x, *args: 42') def test_lambda_x_args_y(): check_ast('lambda x, *args, y: 42') def test_lambda_x_args_y_z(): check_ast('lambda x, *args, y, z: 42') def test_lambda_kwargs(): check_ast('lambda **kwargs: 42') def test_lambda_x_kwargs(): check_ast('lambda x, **kwargs: 42') def test_lambda_x_y_kwargs(): check_ast('lambda x, y, **kwargs: 42') def test_lambda_x_kwy_kwargs(): check_ast('lambda x, y=42, **kwargs: 42') def test_lambda_args_kwargs(): check_ast('lambda *args, **kwargs: 42') def test_lambda_x_args_kwargs(): check_ast('lambda x, *args, **kwargs: 42') def test_lambda_x_y_args_kwargs(): check_ast('lambda x, y, *args, **kwargs: 42') def test_lambda_kwx_args_kwargs(): check_ast('lambda x=10, *args, **kwargs: 42') def test_lambda_x_kwy_args_kwargs(): check_ast('lambda x, y=42, *args, **kwargs: 42') def test_lambda_x_args_y_kwargs(): check_ast('lambda x, *args, y, **kwargs: 42') def test_lambda_x_args_kwy_kwargs(): check_ast('lambda x, *args, y=42, **kwargs: 42') def test_lambda_args_y_kwargs(): check_ast('lambda *args, y, **kwargs: 42') def test_lambda_star_x(): check_ast('lambda *, x: 42') def test_lambda_star_x_y(): check_ast('lambda *, x, y: 42') def test_lambda_star_x_kwargs(): check_ast('lambda *, x, **kwargs: 42') def test_lambda_star_kwx_kwargs(): check_ast('lambda *, x=42, **kwargs: 42') def test_lambda_x_star_y(): check_ast('lambda x, *, y: 42') def test_lambda_x_y_star_z(): check_ast('lambda x, y, *, z: 42') def test_lambda_x_kwy_star_y(): check_ast('lambda x, y=42, *, z: 42') def test_lambda_x_kwy_star_kwy(): check_ast('lambda x, y=42, *, z=65: 42') def test_lambda_x_star_y_kwargs(): check_ast('lambda x, *, y, **kwargs: 42') def test_call_range(): check_ast('range(6)') def test_call_range_comma(): check_ast('range(6,)') def test_call_range_x_y(): check_ast('range(6, 10)') def test_call_range_x_y_comma(): check_ast('range(6, 10,)') def test_call_range_x_y_z(): check_ast('range(6, 10, 2)') def test_call_dict_kwx(): check_ast('dict(start=10)') def test_call_dict_kwx_comma(): check_ast('dict(start=10,)') def test_call_dict_kwx_kwy(): check_ast('dict(start=10, stop=42)') def test_call_tuple_gen(): check_ast('tuple(x for x in [1, 2, 3])') def test_call_tuple_genifs(): check_ast('tuple(x for x in [1, 2, 3] if x < 3)') def test_call_range_star(): check_ast('range(*[1, 2, 3])') def test_call_range_x_star(): check_ast('range(1, *[2, 3])') def test_call_int(): check_ast('int(*["42"], base=8)') def test_call_int_base_dict(): check_ast('int(*["42"], **{"base": 8})') def test_call_dict_kwargs(): check_ast('dict(**{"base": 8})') @skip_if_py34 def test_call_list_many_star_args(): check_ast('min(*[1, 2], 3, *[4, 5])') @skip_if_py34 def test_call_list_many_starstar_args(): check_ast('dict(**{"a": 2}, v=3, **{"c": 5})') @skip_if_py34 def test_call_list_many_star_and_starstar_args(): check_ast('x(*[("a", 2)], *[("v", 3)], **{"c": 5})', False) def test_call_alot(): check_ast('x(1, *args, **kwargs)', False) def test_call_alot_next(): check_ast('x(x=1, *args, **kwargs)', False) def test_call_alot_next_next(): check_ast('x(x=1, *args, y=42, **kwargs)', False) def test_getattr(): check_ast('list.append') def test_getattr_getattr(): check_ast('list.append.__str__') def test_dict_tuple_key(): check_ast('{(42, 1): 65}') def test_dict_tuple_key_get(): check_ast('{(42, 1): 65}[42, 1]') def test_dict_tuple_key_get_3(): check_ast('{(42, 1, 3): 65}[42, 1, 3]') def test_pipe_op(): check_ast('{42} | {65}') def test_pipe_op_two(): check_ast('{42} | {65} | {1}') def test_pipe_op_three(): check_ast('{42} | {65} | {1} | {7}') def test_xor_op(): check_ast('{42} ^ {65}') def test_xor_op_two(): check_ast('{42} ^ {65} ^ {1}') def test_xor_op_three(): check_ast('{42} ^ {65} ^ {1} ^ {7}') def test_xor_pipe(): check_ast('{42} ^ {65} | {1}') def test_amp_op(): check_ast('{42} & {65}') def test_amp_op_two(): check_ast('{42} & {65} & {1}') def test_amp_op_three(): check_ast('{42} & {65} & {1} & {7}') def test_lshift_op(): check_ast('42 << 65') def test_lshift_op_two(): check_ast('42 << 65 << 1') def test_lshift_op_three(): check_ast('42 << 65 << 1 << 7') def test_rshift_op(): check_ast('42 >> 65') def test_rshift_op_two(): check_ast('42 >> 65 >> 1') def test_rshift_op_three(): check_ast('42 >> 65 >> 1 >> 7') # # statements # def test_equals(): check_stmts('x = 42') def test_equals_semi(): check_stmts('x = 42;') def test_x_y_equals_semi(): check_stmts('x = y = 42') def test_equals_two(): check_stmts('x = 42; y = 65') def test_equals_two_semi(): check_stmts('x = 42; y = 65;') def test_equals_three(): check_stmts('x = 42; y = 65; z = 6') def test_equals_three_semi(): check_stmts('x = 42; y = 65; z = 6;') def test_plus_eq(): check_stmts('x = 42; x += 65') def test_sub_eq(): check_stmts('x = 42; x -= 2') def test_times_eq(): check_stmts('x = 42; x *= 2') @skip_if_py34 def test_matmult_eq(): check_stmts('x @= y', False) def test_div_eq(): check_stmts('x = 42; x /= 2') def test_floordiv_eq(): check_stmts('x = 42; x //= 2') def test_pow_eq(): check_stmts('x = 42; x **= 2') def test_mod_eq(): check_stmts('x = 42; x %= 2') def test_xor_eq(): check_stmts('x = 42; x ^= 2') def test_ampersand_eq(): check_stmts('x = 42; x &= 2') def test_bitor_eq(): check_stmts('x = 42; x |= 2') def test_lshift_eq(): check_stmts('x = 42; x <<= 2') def test_rshift_eq(): check_stmts('x = 42; x >>= 2') def test_bare_unpack(): check_stmts('x, y = 42, 65') def test_lhand_group_unpack(): check_stmts('(x, y) = 42, 65') def test_rhand_group_unpack(): check_stmts('x, y = (42, 65)') def test_grouped_unpack(): check_stmts('(x, y) = (42, 65)') def test_double_grouped_unpack(): check_stmts('(x, y) = (z, a) = (7, 8)') def test_double_ungrouped_unpack(): check_stmts('x, y = z, a = 7, 8') def test_stary_eq(): check_stmts('*y, = [1, 2, 3]') def test_stary_x(): check_stmts('*y, x = [1, 2, 3]') def test_tuple_x_stary(): check_stmts('(x, *y) = [1, 2, 3]') def test_list_x_stary(): check_stmts('[x, *y] = [1, 2, 3]') def test_bare_x_stary(): check_stmts('x, *y = [1, 2, 3]') def test_bare_x_stary_z(): check_stmts('x, *y, z = [1, 2, 2, 3]') def test_equals_list(): check_stmts('x = [42]; x[0] = 65') def test_equals_dict(): check_stmts('x = {42: 65}; x[42] = 3') def test_equals_attr(): check_stmts('class X(object):\n pass\nx = X()\nx.a = 65') def test_dict_keys(): check_stmts('x = {"x": 1}\nx.keys()') def test_assert_msg(): check_stmts('assert True, "wow mom"') def test_assert(): check_stmts('assert True') def test_pass(): check_stmts('pass') def test_del(): check_stmts('x = 42; del x') def test_del_comma(): check_stmts('x = 42; del x,') def test_del_two(): check_stmts('x = 42; y = 65; del x, y') def test_del_two_comma(): check_stmts('x = 42; y = 65; del x, y,') def test_del_with_parens(): check_stmts('x = 42; y = 65; del (x, y)') def test_raise(): check_stmts('raise', False) def test_raise_x(): check_stmts('raise TypeError', False) def test_raise_x_from(): check_stmts('raise TypeError from x', False) def test_import_x(): check_stmts('import x', False) def test_import_xy(): check_stmts('import x.y', False) def test_import_xyz(): check_stmts('import x.y.z', False) def test_from_x_import_y(): check_stmts('from x import y', False) def test_from_dot_import_y(): check_stmts('from . import y', False) def test_from_dotx_import_y(): check_stmts('from .x import y', False) def test_from_dotdotx_import_y(): check_stmts('from ..x import y', False) def test_from_dotdotdotx_import_y(): check_stmts('from ...x import y', False) def test_from_dotdotdotdotx_import_y(): check_stmts('from ....x import y', False) def test_from_import_x_y(): check_stmts('import x, y', False) def test_from_import_x_y_z(): check_stmts('import x, y, z', False) def test_from_dot_import_x_y(): check_stmts('from . import x, y', False) def test_from_dot_import_x_y_z(): check_stmts('from . import x, y, z', False) def test_from_dot_import_group_x_y(): check_stmts('from . import (x, y)', False) def test_import_x_as_y(): check_stmts('import x as y', False) def test_import_xy_as_z(): check_stmts('import x.y as z', False) def test_import_x_y_as_z(): check_stmts('import x, y as z', False) def test_import_x_as_y_z(): check_stmts('import x as y, z', False) def test_import_x_as_y_z_as_a(): check_stmts('import x as y, z as a', False) def test_from_dot_import_x_as_y(): check_stmts('from . import x as y', False) def test_from_x_import_star(): check_stmts('from x import *', False) def test_from_x_import_y_as_z(): check_stmts('from x import y as z', False) def test_from_x_import_y_as_z_a_as_b(): check_stmts('from x import y as z, a as b', False) def test_from_dotx_import_y_as_z_a_as_b_c_as_d(): check_stmts('from .x import y as z, a as b, c as d', False) def test_continue(): check_stmts('continue', False) def test_break(): check_stmts('break', False) def test_global(): check_stmts('global x', False) def test_global_xy(): check_stmts('global x, y', False) def test_nonlocal_x(): check_stmts('nonlocal x', False) def test_nonlocal_xy(): check_stmts('nonlocal x, y', False) def test_yield(): check_stmts('yield', False) def test_yield_x(): check_stmts('yield x', False) def test_yield_x_comma(): check_stmts('yield x,', False) def test_yield_x_y(): check_stmts('yield x, y', False) def test_yield_from_x(): check_stmts('yield from x', False) def test_return(): check_stmts('return', False) def test_return_x(): check_stmts('return x', False) def test_return_x_comma(): check_stmts('return x,', False) def test_return_x_y(): check_stmts('return x, y', False) def test_if_true(): check_stmts('if True:\n pass') def test_if_true_twolines(): check_stmts('if True:\n pass\n pass') def test_if_true_twolines_deindent(): check_stmts('if True:\n pass\n pass\npass') def test_if_true_else(): check_stmts('if True:\n pass\nelse: \n pass') def test_if_true_x(): check_stmts('if True:\n x = 42') def test_if_switch(): check_stmts('x = 42\nif x == 1:\n pass') def test_if_switch_elif1_else(): check_stmts('x = 42\nif x == 1:\n pass\n' 'elif x == 2:\n pass\nelse:\n pass') def test_if_switch_elif2_else(): check_stmts('x = 42\nif x == 1:\n pass\n' 'elif x == 2:\n pass\n' 'elif x == 3:\n pass\n' 'elif x == 4:\n pass\n' 'else:\n pass') def test_if_nested(): check_stmts('x = 42\nif x == 1:\n pass\n if x == 4:\n pass') def test_while(): check_stmts('while False:\n pass') def test_while_else(): check_stmts('while False:\n pass\nelse:\n pass') def test_for(): check_stmts('for x in range(6):\n pass') def test_for_zip(): check_stmts('for x, y in zip(range(6), "123456"):\n pass') def test_for_idx(): check_stmts('x = [42]\nfor x[0] in range(3):\n pass') def test_for_zip_idx(): check_stmts('x = [42]\nfor x[0], y in zip(range(6), "123456"):\n' ' pass') def test_for_attr(): check_stmts('for x.a in range(3):\n pass', False) def test_for_zip_attr(): check_stmts('for x.a, y in zip(range(6), "123456"):\n pass', False) def test_for_else(): check_stmts('for x in range(6):\n pass\nelse: pass') @skip_if_py34 def test_async_for(): check_stmts("async def f():\n async for x in y:\n pass\n", False) def test_with(): check_stmts('with x:\n pass', False) def test_with_as(): check_stmts('with x as y:\n pass', False) def test_with_xy(): check_stmts('with x, y:\n pass', False) def test_with_x_as_y_z(): check_stmts('with x as y, z:\n pass', False) def test_with_x_as_y_a_as_b(): check_stmts('with x as y, a as b:\n pass', False) def test_with_in_func(): check_stmts("def f():\n with x:\n pass\n") @skip_if_py34 def test_async_with(): check_stmts("async def f():\n async with x as y:\n pass\n", False) def test_try(): check_stmts('try:\n pass\nexcept:\n pass', False) def test_try_except_t(): check_stmts('try:\n pass\nexcept TypeError:\n pass', False) def test_try_except_t_as_e(): check_stmts('try:\n pass\nexcept TypeError as e:\n pass', False) def test_try_except_t_u(): check_stmts('try:\n pass\nexcept (TypeError, SyntaxError):\n pass', False) def test_try_except_t_u_as_e(): check_stmts('try:\n pass\nexcept (TypeError, SyntaxError) as e:\n pass', False) def test_try_except_t_except_u(): check_stmts('try:\n pass\nexcept TypeError:\n pass\n' 'except SyntaxError as f:\n pass', False) def test_try_except_else(): check_stmts('try:\n pass\nexcept:\n pass\nelse: pass', False) def test_try_except_finally(): check_stmts('try:\n pass\nexcept:\n pass\nfinally: pass', False) def test_try_except_else_finally(): check_stmts('try:\n pass\nexcept:\n pass\nelse:\n pass' '\nfinally: pass', False) def test_try_finally(): check_stmts('try:\n pass\nfinally: pass', False) def test_func(): check_stmts('def f():\n pass') def test_func_ret(): check_stmts('def f():\n return') def test_func_ret_42(): check_stmts('def f():\n return 42') def test_func_ret_42_65(): check_stmts('def f():\n return 42, 65') def test_func_rarrow(): check_stmts('def f() -> int:\n pass') def test_func_x(): check_stmts('def f(x):\n return x') def test_func_kwx(): check_stmts('def f(x=42):\n return x') def test_func_x_y(): check_stmts('def f(x, y):\n return x') def test_func_x_y_z(): check_stmts('def f(x, y, z):\n return x') def test_func_x_kwy(): check_stmts('def f(x, y=42):\n return x') def test_func_kwx_kwy(): check_stmts('def f(x=65, y=42):\n return x') def test_func_kwx_kwy_kwz(): check_stmts('def f(x=65, y=42, z=1):\n return x') def test_func_x_comma(): check_stmts('def f(x,):\n return x') def test_func_x_y_comma(): check_stmts('def f(x, y,):\n return x') def test_func_x_y_z_comma(): check_stmts('def f(x, y, z,):\n return x') def test_func_x_kwy_comma(): check_stmts('def f(x, y=42,):\n return x') def test_func_kwx_kwy_comma(): check_stmts('def f(x=65, y=42,):\n return x') def test_func_kwx_kwy_kwz_comma(): check_stmts('def f(x=65, y=42, z=1,):\n return x') def test_func_args(): check_stmts('def f(*args):\n return 42') def test_func_args_x(): check_stmts('def f(*args, x):\n return 42') def test_func_args_x_y(): check_stmts('def f(*args, x, y):\n return 42') def test_func_args_x_kwy(): check_stmts('def f(*args, x, y=10):\n return 42') def test_func_args_kwx_y(): check_stmts('def f(*args, x=10, y):\n return 42') def test_func_args_kwx_kwy(): check_stmts('def f(*args, x=42, y=65):\n return 42') def test_func_x_args(): check_stmts('def f(x, *args):\n return 42') def test_func_x_args_y(): check_stmts('def f(x, *args, y):\n return 42') def test_func_x_args_y_z(): check_stmts('def f(x, *args, y, z):\n return 42') def test_func_kwargs(): check_stmts('def f(**kwargs):\n return 42') def test_func_x_kwargs(): check_stmts('def f(x, **kwargs):\n return 42') def test_func_x_y_kwargs(): check_stmts('def f(x, y, **kwargs):\n return 42') def test_func_x_kwy_kwargs(): check_stmts('def f(x, y=42, **kwargs):\n return 42') def test_func_args_kwargs(): check_stmts('def f(*args, **kwargs):\n return 42') def test_func_x_args_kwargs(): check_stmts('def f(x, *args, **kwargs):\n return 42') def test_func_x_y_args_kwargs(): check_stmts('def f(x, y, *args, **kwargs):\n return 42') def test_func_kwx_args_kwargs(): check_stmts('def f(x=10, *args, **kwargs):\n return 42') def test_func_x_kwy_args_kwargs(): check_stmts('def f(x, y=42, *args, **kwargs):\n return 42') def test_func_x_args_y_kwargs(): check_stmts('def f(x, *args, y, **kwargs):\n return 42') def test_func_x_args_kwy_kwargs(): check_stmts('def f(x, *args, y=42, **kwargs):\n return 42') def test_func_args_y_kwargs(): check_stmts('def f(*args, y, **kwargs):\n return 42') def test_func_star_x(): check_stmts('def f(*, x):\n return 42') def test_func_star_x_y(): check_stmts('def f(*, x, y):\n return 42') def test_func_star_x_kwargs(): check_stmts('def f(*, x, **kwargs):\n return 42') def test_func_star_kwx_kwargs(): check_stmts('def f(*, x=42, **kwargs):\n return 42') def test_func_x_star_y(): check_stmts('def f(x, *, y):\n return 42') def test_func_x_y_star_z(): check_stmts('def f(x, y, *, z):\n return 42') def test_func_x_kwy_star_y(): check_stmts('def f(x, y=42, *, z):\n return 42') def test_func_x_kwy_star_kwy(): check_stmts('def f(x, y=42, *, z=65):\n return 42') def test_func_x_star_y_kwargs(): check_stmts('def f(x, *, y, **kwargs):\n return 42') def test_func_tx(): check_stmts('def f(x:int):\n return x') def test_func_txy(): check_stmts('def f(x:int, y:float=10.0):\n return x') def test_class(): check_stmts('class X:\n pass') def test_class_obj(): check_stmts('class X(object):\n pass') def test_class_int_flt(): check_stmts('class X(int, object):\n pass') def test_class_obj_kw(): # technically valid syntax, though it will fail to compile check_stmts('class X(object=5):\n pass', False) def test_decorator(): check_stmts('@g\ndef f():\n pass', False) def test_decorator_2(): check_stmts('@h\n@g\ndef f():\n pass', False) def test_decorator_call(): check_stmts('@g()\ndef f():\n pass', False) def test_decorator_call_args(): check_stmts('@g(x, y=10)\ndef f():\n pass', False) def test_decorator_dot_call_args(): check_stmts('@h.g(x, y=10)\ndef f():\n pass', False) def test_decorator_dot_dot_call_args(): check_stmts('@i.h.g(x, y=10)\ndef f():\n pass', False) def test_broken_prompt_func(): code = ('def prompt():\n' " return '{user}'.format(\n" " user='me')\n") check_stmts(code, False) def test_class_with_methods(): code = ('class Test:\n' ' def __init__(self):\n' ' self.msg("hello world")\n' ' def msg(self, m):\n' ' print(m)\n') check_stmts(code, False) def test_nested_functions(): code = ('def test(x):\n' ' def test2(y):\n' ' return y+x\n' ' return test2\n') check_stmts(code, False) def test_function_blank_line(): code = ('def foo():\n' ' ascii_art = [\n' ' "(╯°□°)╯︵ ┻━┻",\n' ' "¯\\_(ツ)_/¯",\n' ' "┻━┻︵ \\(°□°)/ ︵ ┻━┻",\n' ' ]\n' '\n' ' import random\n' ' i = random.randint(0,len(ascii_art)) - 1\n' ' print(" Get to work!")\n' ' print(ascii_art[i])\n') check_stmts(code, False) @skip_if_py34 def test_async_func(): check_stmts('async def f():\n pass\n') @skip_if_py34 def test_async_decorator(): check_stmts('@g\nasync def f():\n pass', False) @skip_if_py34 def test_async_await(): check_stmts("async def f():\n await fut\n", False) # # Xonsh specific syntax # def test_path_literal(): check_xonsh_ast({}, 'p"/foo"', False) check_xonsh_ast({}, 'pr"/foo"', False) check_xonsh_ast({}, 'rp"/foo"', False) check_xonsh_ast({}, 'pR"/foo"', False) check_xonsh_ast({}, 'Rp"/foo"', False) def test_dollar_name(): check_xonsh_ast({'WAKKA': 42}, '$WAKKA') def test_dollar_py(): check_xonsh({'WAKKA': 42}, 'x = "WAKKA"; y = ${x}') def test_dollar_py_test(): check_xonsh_ast({'WAKKA': 42}, '${None or "WAKKA"}') def test_dollar_py_recursive_name(): check_xonsh_ast({'WAKKA': 42, 'JAWAKA': 'WAKKA'}, '${$JAWAKA}') def test_dollar_py_test_recursive_name(): check_xonsh_ast({'WAKKA': 42, 'JAWAKA': 'WAKKA'}, '${None or $JAWAKA}') def test_dollar_py_test_recursive_test(): check_xonsh_ast({'WAKKA': 42, 'JAWAKA': 'WAKKA'}, '${${"JAWA" + $JAWAKA[-2:]}}') def test_dollar_name_set(): check_xonsh({'WAKKA': 42}, '$WAKKA = 42') def test_dollar_py_set(): check_xonsh({'WAKKA': 42}, 'x = "WAKKA"; ${x} = 65') def test_dollar_sub(): check_xonsh_ast({}, '$(ls)', False) def test_dollar_sub_space(): check_xonsh_ast({}, '$(ls )', False) def test_ls_dot(): check_xonsh_ast({}, '$(ls .)', False) def test_lambda_in_atparens(): check_xonsh_ast({}, '$(echo hello | @(lambda a, s=None: "hey!") foo bar baz)', False) def test_nested_madness(): check_xonsh_ast({}, '$(@$(which echo) ls | @(lambda a, s=None: $(@(s.strip()) @(a[1]))) foo -la baz)', False) def test_ls_dot_nesting(): check_xonsh_ast({}, '$(ls @(None or "."))', False) def test_ls_dot_nesting_var(): check_xonsh({}, 'x = "."; $(ls @(None or x))', False) def test_ls_dot_str(): check_xonsh_ast({}, '$(ls ".")', False) def test_ls_nest_ls(): check_xonsh_ast({}, '$(ls $(ls))', False) def test_ls_nest_ls_dashl(): check_xonsh_ast({}, '$(ls $(ls) -l)', False) def test_ls_envvar_strval(): check_xonsh_ast({'WAKKA': '.'}, '$(ls $WAKKA)', False) def test_ls_envvar_listval(): check_xonsh_ast({'WAKKA': ['.', '.']}, '$(ls $WAKKA)', False) def test_bang_sub(): check_xonsh_ast({}, '!(ls)', False) def test_bang_sub_space(): check_xonsh_ast({}, '!(ls )', False) def test_bang_ls_dot(): check_xonsh_ast({}, '!(ls .)', False) def test_bang_ls_dot_nesting(): check_xonsh_ast({}, '!(ls @(None or "."))', False) def test_bang_ls_dot_nesting_var(): check_xonsh({}, 'x = "."; !(ls @(None or x))', False) def test_bang_ls_dot_str(): check_xonsh_ast({}, '!(ls ".")', False) def test_bang_ls_nest_ls(): check_xonsh_ast({}, '!(ls $(ls))', False) def test_bang_ls_nest_ls_dashl(): check_xonsh_ast({}, '!(ls $(ls) -l)', False) def test_bang_ls_envvar_strval(): check_xonsh_ast({'WAKKA': '.'}, '!(ls $WAKKA)', False) def test_bang_ls_envvar_listval(): check_xonsh_ast({'WAKKA': ['.', '.']}, '!(ls $WAKKA)', False) def test_question(): check_xonsh_ast({}, 'range?') def test_dobquestion(): check_xonsh_ast({}, 'range??') def test_question_chain(): check_xonsh_ast({}, 'range?.index?') def test_ls_regex(): check_xonsh_ast({}, '$(ls `[Ff]+i*LE` -l)', False) def test_backtick(): check_xonsh_ast({}, 'print(`.*`)', False) def test_ls_regex_octothorpe(): check_xonsh_ast({}, '$(ls `#[Ff]+i*LE` -l)', False) def test_ls_explicitregex(): check_xonsh_ast({}, '$(ls r`[Ff]+i*LE` -l)', False) def test_rbacktick(): check_xonsh_ast({}, 'print(r`.*`)', False) def test_ls_explicitregex_octothorpe(): check_xonsh_ast({}, '$(ls r`#[Ff]+i*LE` -l)', False) def test_ls_glob(): check_xonsh_ast({}, '$(ls g`[Ff]+i*LE` -l)', False) def test_gbacktick(): check_xonsh_ast({}, 'print(g`.*`)', False) def test_pbacktrick(): check_xonsh_ast({}, 'print(p`.*`)', False) def test_pgbacktick(): check_xonsh_ast({}, 'print(pg`.*`)', False) def test_prbacktick(): check_xonsh_ast({}, 'print(pr`.*`)', False) def test_ls_glob_octothorpe(): check_xonsh_ast({}, '$(ls g`#[Ff]+i*LE` -l)', False) def test_ls_customsearch(): check_xonsh_ast({}, '$(ls @foo`[Ff]+i*LE` -l)', False) def test_custombacktick(): check_xonsh_ast({}, 'print(@foo`.*`)', False) def test_ls_customsearch_octothorpe(): check_xonsh_ast({}, '$(ls @foo`#[Ff]+i*LE` -l)', False) def test_injection(): check_xonsh_ast({}, '$[@$(which python)]', False) def test_rhs_nested_injection(): check_xonsh_ast({}, '$[ls @$(dirname @$(which python))]', False) def test_backtick_octothorpe(): check_xonsh_ast({}, 'print(`#.*`)', False) def test_uncaptured_sub(): check_xonsh_ast({}, '$[ls]', False) def test_hiddenobj_sub(): check_xonsh_ast({}, '![ls]', False) def test_slash_envarv_echo(): check_xonsh_ast({}, '![echo $HOME/place]', False) def test_echo_double_eq(): check_xonsh_ast({}, '![echo yo==yo]', False) def test_bang_two_cmds_one_pipe(): check_xonsh_ast({}, '!(ls | grep wakka)', False) def test_bang_three_cmds_two_pipes(): check_xonsh_ast({}, '!(ls | grep wakka | grep jawaka)', False) def test_bang_one_cmd_write(): check_xonsh_ast({}, '!(ls > x.py)', False) def test_bang_one_cmd_append(): check_xonsh_ast({}, '!(ls >> x.py)', False) def test_bang_two_cmds_write(): check_xonsh_ast({}, '!(ls | grep wakka > x.py)', False) def test_bang_two_cmds_append(): check_xonsh_ast({}, '!(ls | grep wakka >> x.py)', False) def test_bang_cmd_background(): check_xonsh_ast({}, '!(emacs ugggh &)', False) def test_bang_cmd_background_nospace(): check_xonsh_ast({}, '!(emacs ugggh&)', False) def test_bang_git_quotes_no_space(): check_xonsh_ast({}, '![git commit -am "wakka"]', False) def test_bang_git_quotes_space(): check_xonsh_ast({}, '![git commit -am "wakka jawaka"]', False) def test_bang_git_two_quotes_space(): check_xonsh({}, '![git commit -am "wakka jawaka"]\n' '![git commit -am "flock jawaka"]\n', False) def test_bang_git_two_quotes_space_space(): check_xonsh({}, '![git commit -am "wakka jawaka" ]\n' '![git commit -am "flock jawaka milwaka" ]\n', False) def test_bang_ls_quotes_3_space(): check_xonsh_ast({}, '![ls "wakka jawaka baraka"]', False) def test_two_cmds_one_pipe(): check_xonsh_ast({}, '$(ls | grep wakka)', False) def test_three_cmds_two_pipes(): check_xonsh_ast({}, '$(ls | grep wakka | grep jawaka)', False) def test_two_cmds_one_and_brackets(): check_xonsh_ast({}, '![ls me] and ![grep wakka]', False) def test_three_cmds_two_ands(): check_xonsh_ast({}, '![ls] and ![grep wakka] and ![grep jawaka]', False) def test_two_cmds_one_doubleamps(): check_xonsh_ast({}, '![ls] && ![grep wakka]', False) def test_three_cmds_two_doubleamps(): check_xonsh_ast({}, '![ls] && ![grep wakka] && ![grep jawaka]', False) def test_two_cmds_one_or(): check_xonsh_ast({}, '![ls] or ![grep wakka]', False) def test_three_cmds_two_ors(): check_xonsh_ast({}, '![ls] or ![grep wakka] or ![grep jawaka]', False) def test_two_cmds_one_doublepipe(): check_xonsh_ast({}, '![ls] || ![grep wakka]', False) def test_three_cmds_two_doublepipe(): check_xonsh_ast({}, '![ls] || ![grep wakka] || ![grep jawaka]', False) def test_one_cmd_write(): check_xonsh_ast({}, '$(ls > x.py)', False) def test_one_cmd_append(): check_xonsh_ast({}, '$(ls >> x.py)', False) def test_two_cmds_write(): check_xonsh_ast({}, '$(ls | grep wakka > x.py)', False) def test_two_cmds_append(): check_xonsh_ast({}, '$(ls | grep wakka >> x.py)', False) def test_cmd_background(): check_xonsh_ast({}, '$(emacs ugggh &)', False) def test_cmd_background_nospace(): check_xonsh_ast({}, '$(emacs ugggh&)', False) def test_git_quotes_no_space(): check_xonsh_ast({}, '$[git commit -am "wakka"]', False) def test_git_quotes_space(): check_xonsh_ast({}, '$[git commit -am "wakka jawaka"]', False) def test_git_two_quotes_space(): check_xonsh({}, '$[git commit -am "wakka jawaka"]\n' '$[git commit -am "flock jawaka"]\n', False) def test_git_two_quotes_space_space(): check_xonsh({}, '$[git commit -am "wakka jawaka" ]\n' '$[git commit -am "flock jawaka milwaka" ]\n', False) def test_ls_quotes_3_space(): check_xonsh_ast({}, '$[ls "wakka jawaka baraka"]', False) def test_echo_comma(): check_xonsh_ast({}, '![echo ,]', False) def test_echo_internal_comma(): check_xonsh_ast({}, '![echo 1,2]', False) def test_comment_only(): check_xonsh_ast({}, '# hello') def test_echo_slash_question(): check_xonsh_ast({}, '![echo /?]', False) def test_bad_quotes(): with pytest.raises(SyntaxError): check_xonsh_ast({}, '![echo """hello]', False) def test_redirect(): assert check_xonsh_ast({}, '$[cat < input.txt]', False) assert check_xonsh_ast({}, '$[< input.txt cat]', False) @pytest.mark.parametrize('case', [ '![(cat)]', '![(cat;)]', #'![(cd path; ls; cd)]', #'![(echo "abc"; sleep 1; echo "def")]', #'![(echo "abc"; sleep 1; echo "def") | grep abc]', ]) def test_use_subshell(case): check_xonsh_ast({}, case, False, debug_level=0) @pytest.mark.parametrize('case', [ '$[cat < /path/to/input.txt]', '$[(cat) < /path/to/input.txt]', '$[< /path/to/input.txt cat]', '![< /path/to/input.txt]', '![< /path/to/input.txt > /path/to/output.txt]', ]) def test_redirect_abspath(case): assert check_xonsh_ast({}, case, False) @pytest.mark.parametrize('case', ['', 'o', 'out', '1']) def test_redirect_output(case): assert check_xonsh_ast({}, '$[echo "test" {}> test.txt]'.format(case), False) assert check_xonsh_ast({}, '$[< input.txt echo "test" {}> test.txt]'.format(case), False) assert check_xonsh_ast({}, '$[echo "test" {}> test.txt < input.txt]'.format(case), False) @pytest.mark.parametrize('case', ['e', 'err', '2']) def test_redirect_error(case): assert check_xonsh_ast({}, '$[echo "test" {}> test.txt]'.format(case), False) assert check_xonsh_ast({}, '$[< input.txt echo "test" {}> test.txt]'.format(case), False) assert check_xonsh_ast({}, '$[echo "test" {}> test.txt < input.txt]'.format(case), False) @pytest.mark.parametrize('case', ['a', 'all', '&']) def test_redirect_all(case): assert check_xonsh_ast({}, '$[echo "test" {}> test.txt]'.format(case), False) assert check_xonsh_ast({}, '$[< input.txt echo "test" {}> test.txt]'.format(case), False) assert check_xonsh_ast({}, '$[echo "test" {}> test.txt < input.txt]'.format(case), False) @pytest.mark.parametrize('r', ['e>o', 'e>out', 'err>o', '2>1', 'e>1', 'err>1', '2>out', '2>o', 'err>&1', 'e>&1', '2>&1' ]) @pytest.mark.parametrize('o', ['', 'o', 'out', '1']) def test_redirect_error_to_output(r, o): assert check_xonsh_ast({}, '$[echo "test" {} {}> test.txt]'.format(r, o), False) assert check_xonsh_ast({}, '$[< input.txt echo "test" {} {}> test.txt]'.format(r, o), False) assert check_xonsh_ast({}, '$[echo "test" {} {}> test.txt < input.txt]'.format(r, o), False) @pytest.mark.parametrize('r', ['o>e', 'o>err', 'out>e', '1>2', 'o>2', 'out>2', '1>err', '1>e', 'out>&2', 'o>&2', '1>&2' ]) @pytest.mark.parametrize('e', ['e', 'err', '2']) def test_redirect_output_to_error(r, e): assert check_xonsh_ast({}, '$[echo "test" {} {}> test.txt]'.format(r, e), False) assert check_xonsh_ast({}, '$[< input.txt echo "test" {} {}> test.txt]'.format(r, e), False) assert check_xonsh_ast({}, '$[echo "test" {} {}> test.txt < input.txt]'.format(r, e), False) def test_macro_call_empty(): assert check_xonsh_ast({}, 'f!()', False) MACRO_ARGS = [ 'x', 'True', 'None', 'import os', 'x=10', '"oh no, mom"', '...', ' ... ', 'if True:\n pass', '{x: y}', '{x: y, 42: 5}', '{1, 2, 3,}', '(x,y)', '(x, y)', '((x, y), z)', 'g()', 'range(10)', 'range(1, 10, 2)', '()', '{}', '[]', '[1, 2]', '@(x)', '!(ls -l)', '![ls -l]', '$(ls -l)', '${x + y}', '$[ls -l]', '@$(which xonsh)', ] @pytest.mark.parametrize('s', MACRO_ARGS) def test_macro_call_one_arg(s): f = 'f!({})'.format(s) tree = check_xonsh_ast({}, f, False, return_obs=True) assert isinstance(tree, AST) args = tree.body.args[1].elts assert len(args) == 1 assert args[0].s == s.strip() @pytest.mark.parametrize('s,t', itertools.product(MACRO_ARGS[::2], MACRO_ARGS[1::2])) def test_macro_call_two_args(s, t): f = 'f!({}, {})'.format(s, t) tree = check_xonsh_ast({}, f, False, return_obs=True) assert isinstance(tree, AST) args = tree.body.args[1].elts assert len(args) == 2 assert args[0].s == s.strip() assert args[1].s == t.strip() @pytest.mark.parametrize('s,t,u', itertools.product(MACRO_ARGS[::3], MACRO_ARGS[1::3], MACRO_ARGS[2::3])) def test_macro_call_three_args(s, t, u): f = 'f!({}, {}, {})'.format(s, t, u) tree = check_xonsh_ast({}, f, False, return_obs=True) assert isinstance(tree, AST) args = tree.body.args[1].elts assert len(args) == 3 assert args[0].s == s.strip() assert args[1].s == t.strip() assert args[2].s == u.strip() @pytest.mark.parametrize('s', MACRO_ARGS) def test_macro_call_one_trailing(s): f = 'f!({0},)'.format(s) tree = check_xonsh_ast({}, f, False, return_obs=True) assert isinstance(tree, AST) args = tree.body.args[1].elts assert len(args) == 1 assert args[0].s == s.strip() @pytest.mark.parametrize('s', MACRO_ARGS) def test_macro_call_one_trailing_space(s): f = 'f!( {0}, )'.format(s) tree = check_xonsh_ast({}, f, False, return_obs=True) assert isinstance(tree, AST) args = tree.body.args[1].elts assert len(args) == 1 assert args[0].s == s.strip() SUBPROC_MACRO_OC = [ ('!(', ')'), ('$(', ')'), ('![', ']'), ('$[', ']'), ] @pytest.mark.parametrize('opener, closer', SUBPROC_MACRO_OC) @pytest.mark.parametrize('body', ['echo!', 'echo !', 'echo ! ']) def test_empty_subprocbang(opener, closer, body): tree = check_xonsh_ast({}, opener + body + closer, False, return_obs=True) assert isinstance(tree, AST) cmd = tree.body.args[0].elts assert len(cmd) == 2 assert cmd[1].s == '' @pytest.mark.parametrize('opener, closer', SUBPROC_MACRO_OC) @pytest.mark.parametrize('body', ['echo!x', 'echo !x', 'echo !x', 'echo ! x']) def test_single_subprocbang(opener, closer, body): tree = check_xonsh_ast({}, opener + body + closer, False, return_obs=True) assert isinstance(tree, AST) cmd = tree.body.args[0].elts assert len(cmd) == 2 assert cmd[1].s == 'x' @pytest.mark.parametrize('opener, closer', SUBPROC_MACRO_OC) @pytest.mark.parametrize('body', ['echo -n!x', 'echo -n!x', 'echo -n !x', 'echo -n ! x']) def test_arg_single_subprocbang(opener, closer, body): tree = check_xonsh_ast({}, opener + body + closer, False, return_obs=True) assert isinstance(tree, AST) cmd = tree.body.args[0].elts assert len(cmd) == 3 assert cmd[2].s == 'x' @pytest.mark.parametrize('opener, closer', SUBPROC_MACRO_OC) @pytest.mark.parametrize('ipener, iloser', [ ('$(', ')'), ('@$(', ')'), ('$[', ']'), ]) @pytest.mark.parametrize('body', ['echo -n!x', 'echo -n!x', 'echo -n !x', 'echo -n ! x']) def test_arg_single_subprocbang_nested(opener, closer, ipener, iloser, body): code = opener + 'echo ' + ipener + body + iloser + closer tree = check_xonsh_ast({}, opener + body + closer, False, return_obs=True) assert isinstance(tree, AST) cmd = tree.body.args[0].elts assert len(cmd) == 3 assert cmd[2].s == 'x' @pytest.mark.parametrize('opener, closer', SUBPROC_MACRO_OC) @pytest.mark.parametrize('body', [ 'echo!x + y', 'echo !x + y', 'echo !x + y', 'echo ! x + y', 'timeit! bang! and more', 'timeit! recurse() and more', 'timeit! recurse[] and more', 'timeit! recurse!() and more', 'timeit! recurse![] and more', 'timeit! recurse$() and more', 'timeit! recurse$[] and more', 'timeit! recurse!() and more', 'timeit!!!!', 'timeit! (!)', 'timeit! [!]', 'timeit!!(ls)', 'timeit!"!)"', ]) def test_many_subprocbang(opener, closer, body): tree = check_xonsh_ast({}, opener + body + closer, False, return_obs=True) assert isinstance(tree, AST) cmd = tree.body.args[0].elts assert len(cmd) == 2 assert cmd[1].s == body.partition('!')[-1].strip() WITH_BANG_RAWSUITES = [ 'pass\n', 'x = 42\ny = 12\n', 'export PATH="yo:momma"\necho $PATH\n', ('with q as t:\n' ' v = 10\n' '\n'), ('with q as t:\n' ' v = 10\n' '\n' 'for x in range(6):\n' ' if True:\n' ' pass\n' ' else:\n' ' ls -l\n' '\n' 'a = 42\n'), ] @pytest.mark.parametrize('body', WITH_BANG_RAWSUITES) def test_withbang_single_suite(body): code = 'with! x:\n{}'.format(textwrap.indent(body, ' ')) tree = check_xonsh_ast({}, code, False, return_obs=True, mode='exec') assert isinstance(tree, AST) wither = tree.body[0] assert isinstance(wither, With) assert len(wither.body) == 1 assert isinstance(wither.body[0], Pass) assert len(wither.items) == 1 item = wither.items[0] s = item.context_expr.args[1].s assert s == body @pytest.mark.parametrize('body', WITH_BANG_RAWSUITES) def test_withbang_as_single_suite(body): code = 'with! x as y:\n{}'.format(textwrap.indent(body, ' ')) tree = check_xonsh_ast({}, code, False, return_obs=True, mode='exec') assert isinstance(tree, AST) wither = tree.body[0] assert isinstance(wither, With) assert len(wither.body) == 1 assert isinstance(wither.body[0], Pass) assert len(wither.items) == 1 item = wither.items[0] assert item.optional_vars.id == 'y' s = item.context_expr.args[1].s assert s == body @pytest.mark.parametrize('body', WITH_BANG_RAWSUITES) def test_withbang_single_suite_trailing(body): code = 'with! x:\n{}\nprint(x)\n'.format(textwrap.indent(body, ' ')) tree = check_xonsh_ast({}, code, False, return_obs=True, mode='exec', #debug_level=100 ) assert isinstance(tree, AST) wither = tree.body[0] assert isinstance(wither, With) assert len(wither.body) == 1 assert isinstance(wither.body[0], Pass) assert len(wither.items) == 1 item = wither.items[0] s = item.context_expr.args[1].s assert s == body + '\n' WITH_BANG_RAWSIMPLE = [ 'pass', 'x = 42; y = 12', 'export PATH="yo:momma"; echo $PATH', '[1,\n 2,\n 3]' ] @pytest.mark.parametrize('body', WITH_BANG_RAWSIMPLE) def test_withbang_single_simple(body): code = 'with! x: {}\n'.format(body) tree = check_xonsh_ast({}, code, False, return_obs=True, mode='exec') assert isinstance(tree, AST) wither = tree.body[0] assert isinstance(wither, With) assert len(wither.body) == 1 assert isinstance(wither.body[0], Pass) assert len(wither.items) == 1 item = wither.items[0] s = item.context_expr.args[1].s assert s == body @pytest.mark.parametrize('body', WITH_BANG_RAWSIMPLE) def test_withbang_single_simple_opt(body): code = 'with! x as y: {}\n'.format(body) tree = check_xonsh_ast({}, code, False, return_obs=True, mode='exec') assert isinstance(tree, AST) wither = tree.body[0] assert isinstance(wither, With) assert len(wither.body) == 1 assert isinstance(wither.body[0], Pass) assert len(wither.items) == 1 item = wither.items[0] assert item.optional_vars.id == 'y' s = item.context_expr.args[1].s assert s == body @pytest.mark.parametrize('body', WITH_BANG_RAWSUITES) def test_withbang_as_many_suite(body): code = 'with! x as a, y as b, z as c:\n{}' code = code.format(textwrap.indent(body, ' ')) tree = check_xonsh_ast({}, code, False, return_obs=True, mode='exec') assert isinstance(tree, AST) wither = tree.body[0] assert isinstance(wither, With) assert len(wither.body) == 1 assert isinstance(wither.body[0], Pass) assert len(wither.items) == 3 for i, targ in enumerate('abc'): item = wither.items[i] assert item.optional_vars.id == targ s = item.context_expr.args[1].s assert s == body # test invalid expressions def test_syntax_error_del_literal(): with pytest.raises(SyntaxError): PARSER.parse('del 7') def test_syntax_error_del_constant(): with pytest.raises(SyntaxError): PARSER.parse('del True') def test_syntax_error_del_emptytuple(): with pytest.raises(SyntaxError): PARSER.parse('del ()') def test_syntax_error_del_call(): with pytest.raises(SyntaxError): PARSER.parse('del foo()') def test_syntax_error_del_lambda(): with pytest.raises(SyntaxError): PARSER.parse('del lambda x: "yay"') def test_syntax_error_del_ifexp(): with pytest.raises(SyntaxError): PARSER.parse('del x if y else z') @pytest.mark.parametrize('exp', ['[i for i in foo]', '{i for i in foo}', '(i for i in foo)', '{k:v for k,v in d.items()}']) def test_syntax_error_del_comps(exp): with pytest.raises(SyntaxError): PARSER.parse('del {}'.format(exp)) @pytest.mark.parametrize('exp', ['x + y', 'x and y', '-x']) def test_syntax_error_del_ops(exp): with pytest.raises(SyntaxError): PARSER.parse('del {}'.format(exp)) @pytest.mark.parametrize('exp', ['x > y', 'x > y == z']) def test_syntax_error_del_cmp(exp): with pytest.raises(SyntaxError): PARSER.parse('del {}'.format(exp)) def test_syntax_error_lonely_del(): with pytest.raises(SyntaxError): PARSER.parse('del') def test_syntax_error_assign_literal(): with pytest.raises(SyntaxError): PARSER.parse('7 = x') def test_syntax_error_assign_constant(): with pytest.raises(SyntaxError): PARSER.parse('True = 8') def test_syntax_error_assign_emptytuple(): with pytest.raises(SyntaxError): PARSER.parse('() = x') def test_syntax_error_assign_call(): with pytest.raises(SyntaxError): PARSER.parse('foo() = x') def test_syntax_error_assign_lambda(): with pytest.raises(SyntaxError): PARSER.parse('lambda x: "yay" = y') def test_syntax_error_assign_ifexp(): with pytest.raises(SyntaxError): PARSER.parse('x if y else z = 8') @pytest.mark.parametrize('exp', ['[i for i in foo]', '{i for i in foo}', '(i for i in foo)', '{k:v for k,v in d.items()}']) def test_syntax_error_assign_comps(exp): with pytest.raises(SyntaxError): PARSER.parse('{} = z'.format(exp)) @pytest.mark.parametrize('exp', ['x + y', 'x and y', '-x']) def test_syntax_error_assign_ops(exp): with pytest.raises(SyntaxError): PARSER.parse('{} = z'.format(exp)) @pytest.mark.parametrize('exp', ['x > y', 'x > y == z']) def test_syntax_error_assign_cmp(exp): with pytest.raises(SyntaxError): PARSER.parse('{} = a'.format(exp)) def test_syntax_error_augassign_literal(): with pytest.raises(SyntaxError): PARSER.parse('7 += x') def test_syntax_error_augassign_constant(): with pytest.raises(SyntaxError): PARSER.parse('True += 8') def test_syntax_error_augassign_emptytuple(): with pytest.raises(SyntaxError): PARSER.parse('() += x') def test_syntax_error_augassign_call(): with pytest.raises(SyntaxError): PARSER.parse('foo() += x') def test_syntax_error_augassign_lambda(): with pytest.raises(SyntaxError): PARSER.parse('lambda x: "yay" += y') def test_syntax_error_augassign_ifexp(): with pytest.raises(SyntaxError): PARSER.parse('x if y else z += 8') @pytest.mark.parametrize('exp', ['[i for i in foo]', '{i for i in foo}', '(i for i in foo)', '{k:v for k,v in d.items()}']) def test_syntax_error_augassign_comps(exp): with pytest.raises(SyntaxError): PARSER.parse('{} += z'.format(exp)) @pytest.mark.parametrize('exp', ['x + y', 'x and y', '-x']) def test_syntax_error_augassign_ops(exp): with pytest.raises(SyntaxError): PARSER.parse('{} += z'.format(exp)) @pytest.mark.parametrize('exp', ['x > y', 'x > y +=+= z']) def test_syntax_error_augassign_cmp(exp): with pytest.raises(SyntaxError): PARSER.parse('{} += a'.format(exp))