2015-11-16 14:04:32 -08:00
|
|
|
# -*- coding: utf-8 -*-
|
2015-01-23 19:23:45 -06:00
|
|
|
"""Tests the xonsh lexer."""
|
2015-01-23 20:25:56 -06:00
|
|
|
from __future__ import unicode_literals, print_function
|
2015-01-23 19:23:45 -06:00
|
|
|
import os
|
|
|
|
import sys
|
2015-01-23 20:25:56 -06:00
|
|
|
from collections import Sequence
|
2015-01-24 00:17:08 -06:00
|
|
|
sys.path.insert(0, os.path.abspath('..')) # FIXME
|
2015-04-02 19:42:38 -05:00
|
|
|
from pprint import pformat
|
2015-01-23 19:23:45 -06:00
|
|
|
|
2016-05-07 21:34:19 +02:00
|
|
|
try:
|
|
|
|
from ply.lex import LexToken
|
|
|
|
except ImportError:
|
|
|
|
from xonsh.ply.lex import LexToken
|
2016-06-22 23:12:11 +03:00
|
|
|
|
2015-01-23 20:25:56 -06:00
|
|
|
|
2015-01-23 19:23:45 -06:00
|
|
|
from xonsh.lexer import Lexer
|
|
|
|
|
2015-03-07 11:47:32 -06:00
|
|
|
LEXER_ARGS = {'lextab': 'lexer_test_table', 'debug': 0}
|
2015-01-23 20:25:56 -06:00
|
|
|
|
|
|
|
def ensure_tuple(x):
|
|
|
|
if isinstance(x, LexToken):
|
2015-03-13 19:20:26 -05:00
|
|
|
# line numbers can no longer be solely determined from the lexer
|
|
|
|
#x = (x.type, x.value, x.lineno, x.lexpos)
|
|
|
|
x = (x.type, x.value, x.lexpos)
|
2015-01-23 20:25:56 -06:00
|
|
|
elif isinstance(x, tuple):
|
|
|
|
pass
|
|
|
|
elif isinstance(x, Sequence):
|
|
|
|
x = tuple(x)
|
|
|
|
else:
|
|
|
|
raise TypeError('{0} is not a sequence'.format(x))
|
|
|
|
return x
|
|
|
|
|
|
|
|
def tokens_equal(x, y):
|
|
|
|
"""Tests whether two token are equal."""
|
|
|
|
xtup = ensure_tuple(x)
|
|
|
|
ytup = ensure_tuple(y)
|
|
|
|
return xtup == ytup
|
|
|
|
|
|
|
|
def assert_token_equal(x, y):
|
|
|
|
"""Asserts that two tokens are equal."""
|
|
|
|
if not tokens_equal(x, y):
|
|
|
|
msg = 'The tokens differ: {0!r} != {1!r}'.format(x, y)
|
|
|
|
raise AssertionError(msg)
|
2016-06-22 23:12:11 +03:00
|
|
|
return True
|
2015-01-23 20:25:56 -06:00
|
|
|
|
|
|
|
def assert_tokens_equal(x, y):
|
|
|
|
"""Asserts that two token sequences are equal."""
|
|
|
|
if len(x) != len(y):
|
|
|
|
msg = 'The tokens sequences have different lengths: {0!r} != {1!r}\n'
|
|
|
|
msg += '# x\n{2}\n\n# y\n{3}'
|
|
|
|
raise AssertionError(msg.format(len(x), len(y), pformat(x), pformat(y)))
|
|
|
|
diffs = []
|
|
|
|
diffs = [(a, b) for a, b in zip(x, y) if not tokens_equal(a, b)]
|
|
|
|
if len(diffs) > 0:
|
2015-03-24 22:09:50 -04:00
|
|
|
msg = ['The token sequences differ: ']
|
2015-01-23 20:25:56 -06:00
|
|
|
for a, b in diffs:
|
2015-01-23 20:45:45 -06:00
|
|
|
msg += ['', '- ' + repr(a), '+ ' + repr(b)]
|
2015-01-23 20:25:56 -06:00
|
|
|
msg = '\n'.join(msg)
|
|
|
|
raise AssertionError(msg)
|
2016-06-22 23:12:11 +03:00
|
|
|
return True
|
2015-01-23 20:25:56 -06:00
|
|
|
|
2015-04-02 19:42:38 -05:00
|
|
|
def check_token(inp, exp):
|
2015-01-23 19:23:45 -06:00
|
|
|
l = Lexer()
|
2015-04-02 19:42:38 -05:00
|
|
|
l.input(inp)
|
2015-01-23 20:41:45 -06:00
|
|
|
obs = list(l)
|
2015-01-23 23:16:24 -06:00
|
|
|
if len(obs) != 1:
|
|
|
|
msg = 'The observed sequence does not have length-1: {0!r} != 1\n'
|
|
|
|
msg += '# obs\n{1}'
|
|
|
|
raise AssertionError(msg.format(len(obs), pformat(obs)))
|
2016-06-22 23:12:11 +03:00
|
|
|
return assert_token_equal(exp, obs[0])
|
2015-01-23 20:25:56 -06:00
|
|
|
|
2015-04-02 19:42:38 -05:00
|
|
|
def check_tokens(inp, exp):
|
2015-01-23 20:25:56 -06:00
|
|
|
l = Lexer()
|
2015-04-02 19:42:38 -05:00
|
|
|
l.input(inp)
|
2015-01-23 20:25:56 -06:00
|
|
|
obs = list(l)
|
2016-06-22 23:12:11 +03:00
|
|
|
return assert_tokens_equal(exp, obs)
|
2015-01-23 20:41:45 -06:00
|
|
|
|
2015-05-19 18:05:49 -04:00
|
|
|
def check_tokens_subproc(inp, exp):
|
|
|
|
l = Lexer()
|
|
|
|
l.input('$[{}]'.format(inp))
|
|
|
|
obs = list(l)[1:-1]
|
2016-06-22 23:12:11 +03:00
|
|
|
return assert_tokens_equal(exp, obs)
|
2015-01-23 20:41:45 -06:00
|
|
|
|
|
|
|
def test_int_literal():
|
2016-06-22 23:12:11 +03:00
|
|
|
assert check_token('42', ['NUMBER', '42', 0])
|
2015-01-23 20:41:45 -06:00
|
|
|
|
2015-01-23 23:39:42 -06:00
|
|
|
def test_hex_literal():
|
2016-06-22 23:12:11 +03:00
|
|
|
assert check_token('0x42', ['NUMBER', '0x42', 0])
|
2015-01-23 23:39:42 -06:00
|
|
|
|
|
|
|
def test_oct_o_literal():
|
2016-06-22 23:12:11 +03:00
|
|
|
assert check_token('0o42', ['NUMBER', '0o42', 0])
|
2015-01-23 23:39:42 -06:00
|
|
|
|
|
|
|
def test_bin_literal():
|
2016-06-22 23:12:11 +03:00
|
|
|
assert check_token('0b101010', ['NUMBER', '0b101010', 0])
|
2015-01-23 23:39:42 -06:00
|
|
|
|
2015-01-23 20:41:45 -06:00
|
|
|
def test_indent():
|
2015-07-29 23:58:25 +02:00
|
|
|
exp = [('INDENT', ' \t ', 0),
|
2015-03-24 22:09:50 -04:00
|
|
|
('NUMBER', '42', 5),
|
|
|
|
('DEDENT', '', 0)]
|
2016-06-22 23:12:11 +03:00
|
|
|
assert check_tokens(' \t 42', exp)
|
2015-01-23 19:23:45 -06:00
|
|
|
|
2015-01-23 20:35:54 -06:00
|
|
|
def test_post_whitespace():
|
2015-04-02 19:42:38 -05:00
|
|
|
inp = '42 \t '
|
2015-03-24 22:09:50 -04:00
|
|
|
exp = [('NUMBER', '42', 0)]
|
2016-06-22 23:12:11 +03:00
|
|
|
assert check_tokens(inp, exp)
|
2015-01-23 20:35:54 -06:00
|
|
|
|
2015-01-23 20:45:45 -06:00
|
|
|
def test_internal_whitespace():
|
2015-04-02 19:42:38 -05:00
|
|
|
inp = '42 +\t65'
|
2015-07-29 23:58:25 +02:00
|
|
|
exp = [('NUMBER', '42', 0),
|
2015-03-13 19:20:26 -05:00
|
|
|
('PLUS', '+', 4),
|
2015-03-24 22:09:50 -04:00
|
|
|
('NUMBER', '65', 6),]
|
2016-06-22 23:12:11 +03:00
|
|
|
assert check_tokens(inp, exp)
|
2015-01-23 20:45:45 -06:00
|
|
|
|
2015-01-23 23:16:24 -06:00
|
|
|
def test_indent_internal_whitespace():
|
2015-04-02 19:42:38 -05:00
|
|
|
inp = ' 42 +\t65'
|
2015-03-13 19:20:26 -05:00
|
|
|
exp = [('INDENT', ' ', 0),
|
2015-07-29 23:58:25 +02:00
|
|
|
('NUMBER', '42', 1),
|
2015-03-13 19:20:26 -05:00
|
|
|
('PLUS', '+', 5),
|
2015-03-24 22:09:50 -04:00
|
|
|
('NUMBER', '65', 7),
|
|
|
|
('DEDENT', '', 0)]
|
2016-06-22 23:12:11 +03:00
|
|
|
assert check_tokens(inp, exp)
|
2015-01-23 23:16:24 -06:00
|
|
|
|
|
|
|
def test_assignment():
|
2015-04-02 19:42:38 -05:00
|
|
|
inp = 'x = 42'
|
2015-03-13 19:20:26 -05:00
|
|
|
exp = [('NAME', 'x', 0),
|
|
|
|
('EQUALS', '=', 2),
|
2015-07-29 23:58:25 +02:00
|
|
|
('NUMBER', '42', 4),]
|
2016-06-22 23:12:11 +03:00
|
|
|
assert check_tokens(inp, exp)
|
2015-01-23 23:16:24 -06:00
|
|
|
|
|
|
|
def test_multiline():
|
2015-04-02 19:42:38 -05:00
|
|
|
inp = 'x\ny'
|
2015-03-13 19:20:26 -05:00
|
|
|
exp = [('NAME', 'x', 0),
|
|
|
|
('NEWLINE', '\n', 1),
|
2015-03-24 22:09:50 -04:00
|
|
|
('NAME', 'y', 0),]
|
2016-06-22 23:12:11 +03:00
|
|
|
assert check_tokens(inp, exp)
|
2015-01-23 23:16:24 -06:00
|
|
|
|
2016-05-20 19:46:46 -04:00
|
|
|
def test_atdollar_expression():
|
|
|
|
inp = '@$(which python)'
|
|
|
|
exp = [('ATDOLLAR_LPAREN', '@$(', 0),
|
|
|
|
('NAME', 'which', 3),
|
|
|
|
('WS', ' ', 8),
|
|
|
|
('NAME', 'python', 9),
|
|
|
|
('RPAREN', ')', 15)]
|
2016-06-22 23:12:11 +03:00
|
|
|
assert check_tokens(inp, exp)
|
2016-05-20 19:46:46 -04:00
|
|
|
|
2015-01-23 23:16:24 -06:00
|
|
|
def test_and():
|
2016-06-22 23:12:11 +03:00
|
|
|
assert check_token('and', ['AND', 'and', 0])
|
2015-01-23 23:16:24 -06:00
|
|
|
|
2016-02-09 00:43:21 -05:00
|
|
|
def test_ampersand():
|
2016-06-22 23:12:11 +03:00
|
|
|
assert check_token('&', ['AMPERSAND', '&', 0])
|
2016-02-09 00:43:21 -05:00
|
|
|
|
2016-05-20 19:46:46 -04:00
|
|
|
def test_atdollar():
|
2016-06-22 23:12:11 +03:00
|
|
|
assert check_token('@$', ['ATDOLLAR', '@$', 0])
|
2016-05-20 19:46:46 -04:00
|
|
|
|
2016-02-09 00:31:15 -05:00
|
|
|
def test_doubleamp():
|
2016-06-22 23:12:11 +03:00
|
|
|
assert check_token('&&', ['AND', 'and', 0])
|
2016-02-09 00:31:15 -05:00
|
|
|
|
2016-02-09 00:43:21 -05:00
|
|
|
def test_pipe():
|
2016-06-22 23:12:11 +03:00
|
|
|
assert check_token('|', ['PIPE', '|', 0])
|
2016-02-09 00:43:21 -05:00
|
|
|
|
|
|
|
def test_doublepipe():
|
2016-06-22 23:12:11 +03:00
|
|
|
assert check_token('||', ['OR', 'or', 0])
|
2016-02-09 00:43:21 -05:00
|
|
|
|
2015-01-23 23:16:24 -06:00
|
|
|
def test_single_quote_literal():
|
2016-06-22 23:12:11 +03:00
|
|
|
assert check_token("'yo'", ['STRING', "'yo'", 0])
|
2015-01-23 23:16:24 -06:00
|
|
|
|
|
|
|
def test_double_quote_literal():
|
2016-06-22 23:12:11 +03:00
|
|
|
assert check_token('"yo"', ['STRING', '"yo"', 0])
|
2015-01-23 23:16:24 -06:00
|
|
|
|
|
|
|
def test_triple_single_quote_literal():
|
2016-06-22 23:12:11 +03:00
|
|
|
assert check_token("'''yo'''", ['STRING', "'''yo'''", 0])
|
2015-01-23 23:16:24 -06:00
|
|
|
|
|
|
|
def test_triple_double_quote_literal():
|
2016-06-22 23:12:11 +03:00
|
|
|
assert check_token('"""yo"""', ['STRING', '"""yo"""', 0])
|
2015-01-23 23:16:24 -06:00
|
|
|
|
|
|
|
def test_single_raw_string_literal():
|
2016-06-22 23:12:11 +03:00
|
|
|
assert check_token("r'yo'", ['STRING', "r'yo'", 0])
|
2015-01-23 23:16:24 -06:00
|
|
|
|
|
|
|
def test_double_raw_string_literal():
|
2016-06-22 23:12:11 +03:00
|
|
|
assert check_token('r"yo"', ['STRING', 'r"yo"', 0])
|
2015-01-23 23:16:24 -06:00
|
|
|
|
|
|
|
def test_single_unicode_literal():
|
2016-06-22 23:12:11 +03:00
|
|
|
assert check_token("u'yo'", ['STRING', "u'yo'", 0])
|
2015-01-23 23:16:24 -06:00
|
|
|
|
|
|
|
def test_double_unicode_literal():
|
2016-06-22 23:12:11 +03:00
|
|
|
assert check_token('u"yo"', ['STRING', 'u"yo"', 0])
|
2015-01-23 23:16:24 -06:00
|
|
|
|
|
|
|
def test_single_bytes_literal():
|
2016-06-22 23:12:11 +03:00
|
|
|
assert check_token("b'yo'", ['STRING', "b'yo'", 0])
|
2015-01-23 23:16:24 -06:00
|
|
|
|
2016-05-19 19:23:42 -04:00
|
|
|
def test_regex_globs():
|
|
|
|
for i in ('.*', r'\d*', '.*#{1,2}'):
|
2016-06-11 21:35:39 -04:00
|
|
|
for p in ('', 'r', 'g', '@somethingelse'):
|
2016-06-08 22:53:15 -04:00
|
|
|
c = '{}`{}`'.format(p,i)
|
2016-06-22 23:12:11 +03:00
|
|
|
assert check_token(c, ['SEARCHPATH', c, 0])
|
2016-05-19 19:23:42 -04:00
|
|
|
|
2015-01-23 23:39:42 -06:00
|
|
|
def test_float_literals():
|
2015-07-29 23:58:25 +02:00
|
|
|
cases = ['0.0', '.0', '0.', '1e10', '1.e42', '0.1e42', '0.5e-42',
|
2015-01-23 23:43:59 -06:00
|
|
|
'5E10', '5e+42']
|
2015-01-23 23:39:42 -06:00
|
|
|
for s in cases:
|
2016-06-22 23:12:11 +03:00
|
|
|
assert check_token(s, ['NUMBER', s, 0])
|
2015-01-23 20:25:56 -06:00
|
|
|
|
2015-05-19 18:05:49 -04:00
|
|
|
def test_ioredir():
|
|
|
|
cases = ['2>1', 'err>out', 'o>', 'all>', 'e>o', 'e>', 'out>', '2>&1']
|
|
|
|
for s in cases:
|
2016-06-22 23:12:11 +03:00
|
|
|
assert check_tokens_subproc(s, [('IOREDIRECT', s, 2)])
|