Version 0.3: code_page_something not optional?
martinRenou opened this issue · comments
Using the last release of jupyter_kernel_test
(0.3), I found that not testing code_page_something
results in an error.
The following example works fine:
import unittest
import jupyter_kernel_test
class PythonTests(jupyter_kernel_test.KernelTests):
kernel_name = "python3"
language_name = "python"
code_page_something = "?print"
def test_python_stdout(self):
reply, output_msgs = self.execute_helper(code='print(3)')
self.assertEqual(output_msgs[0]['msg_type'], 'stream')
self.assertEqual(output_msgs[0]['content']['name'], 'stdout')
self.assertEqual(output_msgs[0]['content']['text'], '3\n')
if __name__ == '__main__':
unittest.main()
But this one doesn't work:
import unittest
import jupyter_kernel_test
class PythonTests(jupyter_kernel_test.KernelTests):
kernel_name = "python3"
language_name = "python"
def test_python_stdout(self):
reply, output_msgs = self.execute_helper(code='print(3)')
self.assertEqual(output_msgs[0]['msg_type'], 'stream')
self.assertEqual(output_msgs[0]['content']['name'], 'stdout')
self.assertEqual(output_msgs[0]['content']['text'], '3\n')
if __name__ == '__main__':
unittest.main()
And results in this error:
test_xeus_python_kernel.py:13:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
../../../../miniconda3/envs/dev/lib/python3.6/site-packages/jupyter_kernel_test/__init__.py:67: in execute_helper
validate_message(busy_msg, 'status', msg_id)
../../../../miniconda3/envs/dev/lib/python3.6/site-packages/jupyter_kernel_test/messagespec.py:172: in validate_message
nt.assert_equal(msg['parent_header']['msg_id'], parent)
E AssertionError: 'd80cd30e-c108ad4a7797aaf0152d3e30' != 'cdcc4f0b-f60040a52145d517bdad7f23'
E - d80cd30e-c108ad4a7797aaf0152d3e30
E + cdcc4f0b-f60040a52145d517bdad7f23
After printing messages, I guess that the kernel_info_reply
is not used in the second case, and instead of receiving the execute_reply
it first receives the kernel_info_reply
, resulting in this error.
This has been tested with three different kernel implementations (python3, xeus-cling, xeus-python)
Yup, it's definitely meant to be optional. Can you try on master? There have been some major changes since 0.3.
I have a weird error on master: jupyter_kernel_mgmt.kernelspec.NoSuchKernel: No such kernel named
Kernel name is apparently an empty string. I'm using jupyter_kernel_mgmt
0.3.0.
Hmm, strange. Can you show the full traceback? I've been changing jupyter_kernel_mgmt quite a bit recently as I tried to adapt nbconvert and notebook to use it; it's possible the code in this repo needs some changes to match.
Sure:
_____________________________________________________________________________ ERROR at setup of KernelTests.test_kernel_info ______________________________________________________________________________
self = <jupyter_kernel_mgmt.kernelspec.KernelSpecManager object at 0x7f623d984d30>, kernel_name = ''
def get_kernel_spec(self, kernel_name):
"""Returns a :class:`KernelSpec` instance for the given kernel_name.
Raises :exc:`NoSuchKernel` if the given kernel name is not found.
"""
d = self.find_kernel_specs()
try:
> resource_dir = d[kernel_name.lower()]
E KeyError: ''
../../../../miniconda3/envs/test/lib/python3.7/site-packages/jupyter_kernel_mgmt/kernelspec.py:160: KeyError
During handling of the above exception, another exception occurred:
cls = <class 'jupyter_kernel_test.KernelTests'>
@classmethod
def setUpClass(cls):
> conn_info, km = cls.launch_kernel()
../../../../miniconda3/envs/test/lib/python3.7/site-packages/jupyter_kernel_test/__init__.py:31:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
../../../../miniconda3/envs/test/lib/python3.7/site-packages/jupyter_kernel_test/__init__.py:27: in launch_kernel
return kf.launch(name=name)
../../../../miniconda3/envs/test/lib/python3.7/site-packages/jupyter_kernel_mgmt/discovery.py:173: in launch
return provider.launch(kernel_id, cwd)
../../../../miniconda3/envs/test/lib/python3.7/site-packages/jupyter_kernel_mgmt/discovery.py:71: in launch
spec = self.ksm.get_kernel_spec(name)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <jupyter_kernel_mgmt.kernelspec.KernelSpecManager object at 0x7f623d984d30>, kernel_name = ''
def get_kernel_spec(self, kernel_name):
"""Returns a :class:`KernelSpec` instance for the given kernel_name.
Raises :exc:`NoSuchKernel` if the given kernel name is not found.
"""
d = self.find_kernel_specs()
try:
resource_dir = d[kernel_name.lower()]
except KeyError:
> raise NoSuchKernel(kernel_name)
E jupyter_kernel_mgmt.kernelspec.NoSuchKernel: No such kernel named
../../../../miniconda3/envs/test/lib/python3.7/site-packages/jupyter_kernel_mgmt/kernelspec.py:162: NoSuchKernel
That looks like cls.kernel_name
is not set. Is it possible there's a typo? jupyter_kernel_test
should probably check for that and throw a more informative error.
I'm using this test:
import unittest
from jupyter_kernel_test import KernelTests
class PythonTests(KernelTests):
kernel_name = "python3"
language_name = "python"
code_page_something = "?print"
def test_python_stdout(self):
reply, output_msgs = self.execute_helper(code='print(3)')
self.assertEqual(output_msgs[0]['msg_type'], 'stream')
self.assertEqual(output_msgs[0]['content']['name'], 'stdout')
self.assertEqual(output_msgs[0]['content']['text'], '3\n')
if __name__ == '__main__':
unittest.main()
It's really strange.
Ah, I think I remember this. If you do from jupyter_kernel_test import KernelTests
, then it tries to run the base class as tests as well as your subclass. Maybe we should tweak the name to avoid that.
Nice catch! I can open an other specific issue for this one.
Ok so now it fails differently:
_____________________________________________________________________________________ PythonTests.test_python_stdout ______________________________________________________________________________________
self = <test_kernel.PythonTests testMethod=test_python_stdout>
def test_python_stdout(self):
> reply, output_msgs = self.execute_helper(code='print(3)')
test_kernel.py:11:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
../../../../miniconda3/envs/test/lib/python3.7/site-packages/jupyter_kernel_test/__init__.py:68: in execute_helper
self.kc.loop_client.add_handler('iopub', output_msgs.append)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <jupyter_kernel_mgmt.client.IOLoopKernelClient object at 0x7f30b050acc0>, handler = 'iopub', channels = <built-in method append of list object at 0x7f30aa56fa88>
def add_handler(self, handler, channels):
"""Add a callback for received messages on one or more channels.
Parameters
----------
handler : function
Will be called for each message received with the message dictionary
as a single argument.
channels : set or str
Channel names: 'shell', 'iopub', 'stdin' or 'control'
"""
if isinstance(channels, str):
channels = {channels}
> invalid_channels = channels - self.handler_channels
E TypeError: unsupported operand type(s) for -: 'builtin_function_or_method' and 'frozenset'
../../../../miniconda3/envs/test/lib/python3.7/site-packages/jupyter_kernel_mgmt/client.py:134: TypeError
I'm sorry I'm just reporting, not really helping... I'm on other stuff at the same time
Actually the issue has already been reported: #7
Yup, that was me changing APIs around. The parameters for add_handler
need to be switched around.
The error from add_handler
should be fixed now in master (e7844c7).
Thanks! It works! I'm not seeing the issue anymore. There was still one thing, I guess the README is not valid anymore:
def test_mykernel_stderr(self):
reply, output_msgs = self.execute_helper(code='print_err "oops"')
self.assertEqual(output_msgs[0]['msg_type'], 'stream')
self.assertEqual(output_msgs[0]['content']['name'], 'stderr')
self.assertEqual(output_msgs[0]['content']['text'], 'oops\n')
should be replaced by
def test_mykernel_stderr(self):
reply, output_msgs = self.execute_helper(code='print_err "oops"')
# self.assertEqual(output_msgs[0]['msg_type'], 'stream')
self.assertEqual(output_msgs[0].content['name'], 'stderr')
self.assertEqual(output_msgs[0].content['text'], 'oops\n')
I'm note sure how to adapt the msg_type
line to the new version of master
Thank you for your help! Do you plan to make a release?
I might wait a while for a release, because the new kernel APIs are still in flux (hence these problems ;-). I'm working on integrating them into notebook and nbconvert as well, but it's not settled yet.
The msg_type
bit should become .header['msg_type']
. The old API copied it to the top-level for convenience, whereas the new one doesn't.
Do you want to make a PR to update the README? You might also want to add a note that master is different to 0.3, because it might be a while before it's ready for a new release. We can always make a branch off before the new APIs were landed (in 41850aa) if it becomes necessary.
Sure, I'll do that :)