diff --git a/jupyter_server/terminal/__init__.py b/jupyter_server/terminal/__init__.py index c20001c894..d23c036375 100644 --- a/jupyter_server/terminal/__init__.py +++ b/jupyter_server/terminal/__init__.py @@ -3,8 +3,8 @@ import terminado from ..utils import check_version -if not check_version(terminado.__version__, '0.8.1'): - raise ImportError("terminado >= 0.8.1 required, found %s" % terminado.__version__) +if not check_version(terminado.__version__, '0.8.3'): + raise ImportError("terminado >= 0.8.3 required, found %s" % terminado.__version__) from ipython_genutils.py3compat import which from terminado import NamedTermManager diff --git a/jupyter_server/terminal/api_handlers.py b/jupyter_server/terminal/api_handlers.py index 30d13002ff..3967692092 100644 --- a/jupyter_server/terminal/api_handlers.py +++ b/jupyter_server/terminal/api_handlers.py @@ -21,7 +21,9 @@ def get(self): @web.authenticated def post(self): """POST /terminals creates a new terminal and redirects to it""" - name, _ = self.terminal_manager.new_named_terminal() + data = self.get_json_body() or {} + + name, _ = self.terminal_manager.new_named_terminal(**data) self.finish(json.dumps({'name': name})) # Increase the metric by one because a new terminal was created diff --git a/setup.py b/setup.py index ab25ebd63f..c2a4ca58d2 100755 --- a/setup.py +++ b/setup.py @@ -92,7 +92,7 @@ 'nbconvert', 'ipykernel', # bless IPython kernel for now 'Send2Trash', - 'terminado>=0.8.1', + 'terminado>=0.8.3', 'prometheus_client', "pywin32>=1.0 ; sys_platform == 'win32'" ], diff --git a/tests/conftest.py b/tests/conftest.py index 9d694425b2..6369f8eac3 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1 +1 @@ -pytest_plugins = ['pytest_jupyter_server'] \ No newline at end of file +pytest_plugins = ['pytest_jupyter_server'] diff --git a/tests/test_terminal.py b/tests/test_terminal.py new file mode 100644 index 0000000000..51a6454562 --- /dev/null +++ b/tests/test_terminal.py @@ -0,0 +1,95 @@ +# Only Run tests on MacOS and Linux +import shutil +import pytest +import json +import asyncio +import sys + +# Skip this whole module on Windows. The terminal API leads +# to timeouts on Windows CI. +if sys.platform.startswith('win'): + pytest.skip("Terminal API tests time out on Windows.", allow_module_level=True) + + +@pytest.fixture +def terminal_path(tmp_path): + subdir = tmp_path.joinpath('terminal_path') + subdir.mkdir() + + yield subdir + + shutil.rmtree(str(subdir), ignore_errors=True) + + +async def test_terminal_create(fetch): + await fetch( + 'api', 'terminals', + method='POST', + allow_nonstandard_methods=True, + ) + + resp_list = await fetch( + 'api', 'terminals', + method='GET', + allow_nonstandard_methods=True, + ) + + data = json.loads(resp_list.body.decode()) + + assert len(data) == 1 + + +async def test_terminal_create_with_kwargs(fetch, ws_fetch, terminal_path): + resp_create = await fetch( + 'api', 'terminals', + method='POST', + body=json.dumps({'cwd': str(terminal_path)}), + allow_nonstandard_methods=True, + ) + + data = json.loads(resp_create.body.decode()) + term_name = data['name'] + + resp_get = await fetch( + 'api', 'terminals', term_name, + method='GET', + allow_nonstandard_methods=True, + ) + + data = json.loads(resp_get.body.decode()) + + assert data['name'] == term_name + + +async def test_terminal_create_with_cwd(fetch, ws_fetch, terminal_path): + resp = await fetch( + 'api', 'terminals', + method='POST', + body=json.dumps({'cwd': str(terminal_path)}), + allow_nonstandard_methods=True, + ) + + data = json.loads(resp.body.decode()) + term_name = data['name'] + + ws = await ws_fetch( + 'terminals', 'websocket', term_name + ) + + ws.write_message(json.dumps(['stdin', 'pwd\r\n'])) + + message_stdout = '' + while True: + try: + message = await asyncio.wait_for(ws.read_message(), timeout=1.0) + except asyncio.TimeoutError: + break + + message = json.loads(message) + + if message[0] == 'stdout': + message_stdout += message[1] + + ws.close() + + assert str(terminal_path) in message_stdout