2022-05-23 00:16:32 +04:00

458 lines
14 KiB
Python

"""Tests for adapting Jupyter msg spec versions"""
# Copyright (c) Jupyter Development Team.
# Distributed under the terms of the Modified BSD License.
import copy
import json
from unittest import TestCase
from jupyter_client.adapter import adapt
from jupyter_client.adapter import code_to_line
from jupyter_client.adapter import V4toV5
from jupyter_client.session import Session
def test_default_version():
s = Session()
msg = s.msg("msg_type")
msg["header"].pop("version")
original = copy.deepcopy(msg)
adapted = adapt(original)
assert adapted["header"]["version"] == V4toV5.version
def test_code_to_line_no_code():
line, pos = code_to_line("", 0)
assert line == ""
assert pos == 0
class AdapterTest(TestCase):
def setUp(self):
self.session = Session()
def adapt(self, msg, version=None):
original = copy.deepcopy(msg)
adapted = adapt(msg, version or self.to_version)
return original, adapted
def check_header(self, msg):
pass
class V4toV5TestCase(AdapterTest):
from_version = 4
to_version = 5
def msg(self, msg_type, content):
"""Create a v4 msg (same as v5, minus version header)"""
msg = self.session.msg(msg_type, content)
msg["header"].pop("version")
return msg
def test_same_version(self):
msg = self.msg("execute_result", content={"status": "ok"})
original, adapted = self.adapt(msg, self.from_version)
self.assertEqual(original, adapted)
def test_no_adapt(self):
msg = self.msg("input_reply", {"value": "some text"})
v4, v5 = self.adapt(msg)
self.assertEqual(v5["header"]["version"], V4toV5.version)
v5["header"].pop("version")
self.assertEqual(v4, v5)
def test_rename_type(self):
for v5_type, v4_type in [
("execute_result", "pyout"),
("execute_input", "pyin"),
("error", "pyerr"),
]:
msg = self.msg(v4_type, {"key": "value"})
v4, v5 = self.adapt(msg)
self.assertEqual(v5["header"]["version"], V4toV5.version)
self.assertEqual(v5["header"]["msg_type"], v5_type)
self.assertEqual(v4["content"], v5["content"])
def test_execute_request(self):
msg = self.msg(
"execute_request",
{
"code": "a=5",
"silent": False,
"user_expressions": {"a": "apple"},
"user_variables": ["b"],
},
)
v4, v5 = self.adapt(msg)
self.assertEqual(v4["header"]["msg_type"], v5["header"]["msg_type"])
v4c = v4["content"]
v5c = v5["content"]
self.assertEqual(v5c["user_expressions"], {"a": "apple", "b": "b"})
self.assertNotIn("user_variables", v5c)
self.assertEqual(v5c["code"], v4c["code"])
def test_execute_reply(self):
msg = self.msg(
"execute_reply",
{
"status": "ok",
"execution_count": 7,
"user_variables": {"a": 1},
"user_expressions": {"a+a": 2},
"payload": [{"source": "page", "text": "blah"}],
},
)
v4, v5 = self.adapt(msg)
v5c = v5["content"]
self.assertNotIn("user_variables", v5c)
self.assertEqual(v5c["user_expressions"], {"a": 1, "a+a": 2})
self.assertEqual(v5c["payload"], [{"source": "page", "data": {"text/plain": "blah"}}])
def test_complete_request(self):
msg = self.msg(
"complete_request",
{
"text": "a.is",
"line": "foo = a.is",
"block": None,
"cursor_pos": 10,
},
)
v4, v5 = self.adapt(msg)
v4c = v4["content"]
v5c = v5["content"]
for key in ("text", "line", "block"):
self.assertNotIn(key, v5c)
self.assertEqual(v5c["cursor_pos"], v4c["cursor_pos"])
self.assertEqual(v5c["code"], v4c["line"])
def test_complete_reply(self):
msg = self.msg(
"complete_reply",
{
"matched_text": "a.is",
"matches": [
"a.isalnum",
"a.isalpha",
"a.isdigit",
"a.islower",
],
},
)
v4, v5 = self.adapt(msg)
v4c = v4["content"]
v5c = v5["content"]
self.assertEqual(v5c["matches"], v4c["matches"])
self.assertEqual(v5c["metadata"], {})
self.assertEqual(v5c["cursor_start"], -4)
self.assertEqual(v5c["cursor_end"], None)
def test_object_info_request(self):
msg = self.msg(
"object_info_request",
{
"oname": "foo",
"detail_level": 1,
},
)
v4, v5 = self.adapt(msg)
self.assertEqual(v5["header"]["msg_type"], "inspect_request")
v4c = v4["content"]
v5c = v5["content"]
self.assertEqual(v5c["code"], v4c["oname"])
self.assertEqual(v5c["cursor_pos"], len(v4c["oname"]))
self.assertEqual(v5c["detail_level"], v4c["detail_level"])
def test_object_info_reply(self):
msg = self.msg(
"object_info_reply",
{
"name": "foo",
"found": True,
"status": "ok",
"definition": "foo(a=5)",
"docstring": "the docstring",
},
)
v4, v5 = self.adapt(msg)
self.assertEqual(v5["header"]["msg_type"], "inspect_reply")
v4c = v4["content"]
v5c = v5["content"]
self.assertEqual(sorted(v5c), ["data", "found", "metadata", "status"])
text = v5c["data"]["text/plain"]
self.assertEqual(text, "\n".join([v4c["definition"], v4c["docstring"]]))
def test_object_info_reply_not_found(self):
msg = self.msg(
"object_info_reply",
{
"name": "foo",
"found": False,
},
)
v4, v5 = self.adapt(msg)
self.assertEqual(v5["header"]["msg_type"], "inspect_reply")
v4["content"]
v5c = v5["content"]
self.assertEqual(
v5c,
{
"status": "ok",
"found": False,
"data": {},
"metadata": {},
},
)
def test_kernel_info_reply(self):
msg = self.msg(
"kernel_info_reply",
{
"language": "python",
"language_version": [2, 8, 0],
"ipython_version": [1, 2, 3],
},
)
v4, v5 = self.adapt(msg)
v4["content"]
v5c = v5["content"]
self.assertEqual(
v5c,
{
"protocol_version": "4.1",
"implementation": "ipython",
"implementation_version": "1.2.3",
"language_info": {
"name": "python",
"version": "2.8.0",
},
"banner": "",
},
)
# iopub channel
def test_display_data(self):
jsondata = dict(a=5)
msg = self.msg(
"display_data",
{
"data": {
"text/plain": "some text",
"application/json": json.dumps(jsondata),
},
"metadata": {"text/plain": {"key": "value"}},
},
)
v4, v5 = self.adapt(msg)
v4c = v4["content"]
v5c = v5["content"]
self.assertEqual(v5c["metadata"], v4c["metadata"])
self.assertEqual(v5c["data"]["text/plain"], v4c["data"]["text/plain"])
self.assertEqual(v5c["data"]["application/json"], jsondata)
# stdin channel
def test_input_request(self):
msg = self.msg("input_request", {"prompt": "$>"})
v4, v5 = self.adapt(msg)
self.assertEqual(v5["content"]["prompt"], v4["content"]["prompt"])
self.assertFalse(v5["content"]["password"])
class V5toV4TestCase(AdapterTest):
from_version = 5
to_version = 4
def msg(self, msg_type, content):
return self.session.msg(msg_type, content)
def test_same_version(self):
msg = self.msg("execute_result", content={"status": "ok"})
original, adapted = self.adapt(msg, self.from_version)
self.assertEqual(original, adapted)
def test_no_adapt(self):
msg = self.msg("input_reply", {"value": "some text"})
v5, v4 = self.adapt(msg)
self.assertNotIn("version", v4["header"])
v5["header"].pop("version")
self.assertEqual(v4, v5)
def test_rename_type(self):
for v5_type, v4_type in [
("execute_result", "pyout"),
("execute_input", "pyin"),
("error", "pyerr"),
]:
msg = self.msg(v5_type, {"key": "value"})
v5, v4 = self.adapt(msg)
self.assertEqual(v4["header"]["msg_type"], v4_type)
assert "version" not in v4["header"]
self.assertEqual(v4["content"], v5["content"])
def test_execute_request(self):
msg = self.msg(
"execute_request",
{
"code": "a=5",
"silent": False,
"user_expressions": {"a": "apple"},
},
)
v5, v4 = self.adapt(msg)
self.assertEqual(v4["header"]["msg_type"], v5["header"]["msg_type"])
v4c = v4["content"]
v5c = v5["content"]
self.assertEqual(v4c["user_variables"], [])
self.assertEqual(v5c["code"], v4c["code"])
def test_complete_request(self):
msg = self.msg(
"complete_request",
{
"code": "def foo():\n a.is\nfoo()",
"cursor_pos": 19,
},
)
v5, v4 = self.adapt(msg)
v4c = v4["content"]
v5c = v5["content"]
self.assertNotIn("code", v4c)
self.assertEqual(v4c["line"], v5c["code"].splitlines(True)[1])
self.assertEqual(v4c["cursor_pos"], 8)
self.assertEqual(v4c["text"], "")
self.assertEqual(v4c["block"], None)
def test_complete_reply(self):
msg = self.msg(
"complete_reply",
{
"cursor_start": 10,
"cursor_end": 14,
"matches": [
"a.isalnum",
"a.isalpha",
"a.isdigit",
"a.islower",
],
"metadata": {},
},
)
v5, v4 = self.adapt(msg)
v4c = v4["content"]
v5c = v5["content"]
self.assertEqual(v4c["matched_text"], "a.is")
self.assertEqual(v4c["matches"], v5c["matches"])
def test_inspect_request(self):
msg = self.msg(
"inspect_request",
{
"code": "def foo():\n apple\nbar()",
"cursor_pos": 18,
"detail_level": 1,
},
)
v5, v4 = self.adapt(msg)
self.assertEqual(v4["header"]["msg_type"], "object_info_request")
v4c = v4["content"]
v5c = v5["content"]
self.assertEqual(v4c["oname"], "apple")
self.assertEqual(v5c["detail_level"], v4c["detail_level"])
def test_inspect_request_token(self):
line = "something(range(10), kwarg=smth) ; xxx.xxx.xxx( firstarg, rand(234,23), kwarg1=2,"
msg = self.msg(
"inspect_request",
{
"code": line,
"cursor_pos": len(line) - 1,
"detail_level": 1,
},
)
v5, v4 = self.adapt(msg)
self.assertEqual(v4["header"]["msg_type"], "object_info_request")
v4c = v4["content"]
v5c = v5["content"]
self.assertEqual(v4c["oname"], "xxx.xxx.xxx")
self.assertEqual(v5c["detail_level"], v4c["detail_level"])
def test_inspect_reply(self):
msg = self.msg(
"inspect_reply",
{
"name": "foo",
"found": True,
"data": {"text/plain": "some text"},
"metadata": {},
},
)
v5, v4 = self.adapt(msg)
self.assertEqual(v4["header"]["msg_type"], "object_info_reply")
v4c = v4["content"]
v5["content"]
self.assertEqual(sorted(v4c), ["found", "oname"])
self.assertEqual(v4c["found"], False)
def test_kernel_info_reply(self):
msg = self.msg(
"kernel_info_reply",
{
"protocol_version": "5.0",
"implementation": "ipython",
"implementation_version": "1.2.3",
"language_info": {
"name": "python",
"version": "2.8.0",
"mimetype": "text/x-python",
},
"banner": "the banner",
},
)
v5, v4 = self.adapt(msg)
v4c = v4["content"]
v5c = v5["content"]
v5c["language_info"]
self.assertEqual(
v4c,
{
"protocol_version": [5, 0],
"language": "python",
"language_version": [2, 8, 0],
"ipython_version": [1, 2, 3],
},
)
# iopub channel
def test_display_data(self):
jsondata = dict(a=5)
msg = self.msg(
"display_data",
{
"data": {
"text/plain": "some text",
"application/json": jsondata,
},
"metadata": {"text/plain": {"key": "value"}},
},
)
v5, v4 = self.adapt(msg)
v4c = v4["content"]
v5c = v5["content"]
self.assertEqual(v5c["metadata"], v4c["metadata"])
self.assertEqual(v5c["data"]["text/plain"], v4c["data"]["text/plain"])
self.assertEqual(v4c["data"]["application/json"], json.dumps(jsondata))
# stdin channel
def test_input_request(self):
msg = self.msg("input_request", {"prompt": "$>", "password": True})
v5, v4 = self.adapt(msg)
self.assertEqual(v5["content"]["prompt"], v4["content"]["prompt"])
self.assertNotIn("password", v4["content"])