Add test for readline shell (#4447)

* fix: ReadlineShell pass stdin/out to Cmd's constructor

* test: add test for readline shell

* chore: increase required coverage

* test:

* fix: failing ci pipeline

* fix: failing ci test
This commit is contained in:
Noorhteen Raja NJ 2021-09-03 00:45:20 +05:30 committed by GitHub
parent 9d9c071927
commit e25ab34e32
Failed to generate hash of commit
5 changed files with 61 additions and 13 deletions

View file

@ -27,7 +27,7 @@ exclude_lines =
skip_covered = true
skip_empty = true
show_missing = true
sort = Cover
sort = Miss
# something is better than nothing :)
fail_under = 55
# keep improving ;)
fail_under = 60

View file

@ -183,6 +183,22 @@ def ptk_shell(xonsh_execer):
inp.close()
@pytest.fixture
def readline_shell(xonsh_execer, tmpdir, mocker):
from xonsh.readline_shell import ReadlineShell
inp_path = tmpdir / "in"
inp = inp_path.open("w+")
out_path = tmpdir / "out"
out = out_path.open("w+")
shell = ReadlineShell(execer=xonsh_execer, ctx={}, stdin=inp, stdout=out)
mocker.patch.object(shell, "_load_remaining_input_into_queue")
yield shell
inp.close()
out.close()
def pytest_configure(config):
"""Abort test run if --flake8 requested, since it would hang on parser_test.py"""
if config.getoption("--flake8", ""):

View file

@ -23,3 +23,24 @@ def test_render_completions(prefix, completion, prefix_len, readline_completion)
assert _render_completions({completion}, prefix, prefix_len) == [
readline_completion
]
@pytest.mark.parametrize(
"line, exp",
[
[repr("hello"), "hello"],
["2 * 3", "6"],
],
)
def test_rl_prompt_cmdloop(line, exp, readline_shell, capsys):
shell = readline_shell
shell.use_rawinput = False
shell.stdin.write(f"{line}\nexit\n") # note: terminate with '\n'
shell.stdin.seek(0)
shell.cmdloop()
# xonsh, doesn't write all its output to shell.stdout
# so capture sys.stdout
out, err = capsys.readouterr()
# sometimes the output has ansii color codes
assert exp in out.strip()

View file

@ -299,11 +299,18 @@ class Tee:
return s
class BaseShell(object):
class BaseShell:
"""The xonsh shell."""
def __init__(self, execer, ctx, **kwargs):
super().__init__()
"""
Notes
-----
classes inheriting multiple base classes should call them explicitly
as done for ``ReadlineShell``
"""
self.execer = execer
self.ctx = ctx
self.completer = Completer() if kwargs.get("completer", True) else None

View file

@ -320,7 +320,11 @@ class ReadlineShell(BaseShell, cmd.Cmd):
"""The readline based xonsh shell."""
def __init__(self, completekey="tab", stdin=None, stdout=None, **kwargs):
super().__init__(completekey=completekey, stdin=stdin, stdout=stdout, **kwargs)
BaseShell.__init__(self, **kwargs)
# super() doesn't pass the stdin/stdout to Cmd's init method correctly.
# so calling it explicitly
cmd.Cmd.__init__(self, completekey=completekey, stdin=stdin, stdout=stdout)
setup_readline()
self._current_indent = ""
self._current_prompt = ""
@ -533,16 +537,16 @@ class ReadlineShell(BaseShell, cmd.Cmd):
(C) Python Software Foundation, 2015.
"""
self.preloop()
if self.use_rawinput and self.completekey:
try:
import readline
try:
import readline
if self.use_rawinput and self.completekey:
self.old_completer = readline.get_completer()
readline.set_completer(self.complete)
readline.parse_and_bind(self.completekey + ": complete")
have_readline = True
except ImportError:
have_readline = False
have_readline = True
except ImportError:
have_readline = False
try:
if intro is not None:
self.intro = intro
@ -606,7 +610,7 @@ class ReadlineShell(BaseShell, cmd.Cmd):
try:
self._cmdloop(intro=intro)
except (KeyboardInterrupt, SystemExit):
print() # Gives a newline
print(file=self.stdout) # Gives a newline
fix_readline_state_after_ctrl_c()
self.reset_buffer()
intro = None