nbval
nbval copied to clipboard
WIP: Fix handling of bad magics
Fixes #147
Before I can get to the actual fix, I'm having some problems with the test framework :)
-
Where is
--nbval-lax
tested? I.e. I wasn't sure where to put my tests. In the end, I copy/pastedtest_timeouts.py
. -
I'm having an issue running both new tests together:
traitlets.traitlets.TraitError: The 'session' trait of a KernelManager instance must be a Session, but a value of class 'jupyter_client.session.Session' (i.e. <jupyter_client.session.Session object at 0x7f5507c33c10>) was specified.
full version:
$ pytest -v tests/test_magics.py =============================== test session starts ================================ platform linux -- Python 3.7.6, pytest-5.4.1, py-1.8.1, pluggy-0.12.0 -- /home/sefkw/mc3/envs/celltestsui/bin/python cachedir: .pytest_cache metadata: {'Python': '3.7.6', 'Platform': 'Linux-5.4.0-7634-generic-x86_64-with-debian-bullseye-sid', 'Packages': {'pytest': '5.4.1', 'py': '1.8.1', 'pluggy': '0.12.0'}, 'Plugins': {'xdist': '1.32.0', 'html': '2.1.1', 'metadata': '1.8.0', 'cov': '2.8.1', 'forked': '1.1.2', 'nbval': '0.9.5'}} rootdir: /home/sefkw/code/external/nbval plugins: xdist-1.32.0, html-2.1.1, metadata-1.8.0, cov-2.8.1, forked-1.1.2, nbval-0.9.5 collected 2 itemstests/test_magics.py::test_magics[%dirs-expected_passes0] PASSED [ 50%] tests/test_magics.py::test_magics[%this_magic_does_not_exist-expected_passes1] FAILED [100%]
===================================== FAILURES ===================================== _____________ test_magics[%this_magic_does_not_exist-expected_passes1] _____________
testdir = <Testdir local('/tmp/pytest-of-sefkw/pytest-36/test_magics1')> magic = '%this_magic_does_not_exist', expected_passes = [False]
@pytest.mark.parametrize("magic, expected_passes", [ (r"%dirs", [True]), (r"%this_magic_does_not_exist", [False]) ]) def test_magics(testdir, magic, expected_passes): # Setup notebook to test: sources = [ # In [1]: magic, ] nb = build_nb(sources) # Write notebook to test dir nbformat.write(nb, os.path.join( str(testdir.tmpdir), 'test_magics.ipynb')) # Run tests result = testdir.inline_run('--nbval-lax', '--current-env', '-s') reports = result.getreports('pytest_runtest_logreport') # Setup and teardown of cells should have no issues: setup_teardown = [r for r in reports if r.when != 'call'] for r in setup_teardown:
assert r.passed
E AssertionError: assert False E + where False = <TestReport 'test_magics.ipynb::Cell 0' when='setup' outcome='failed'>.passed
/home/sefkw/code/external/nbval/tests/test_magics.py:35: AssertionError ------------------------------- Captured stdout call ------------------------------- =============================== test session starts ================================ platform linux -- Python 3.7.6, pytest-5.4.1, py-1.8.1, pluggy-0.12.0 rootdir: /tmp/pytest-of-sefkw/pytest-36/test_magics1 plugins: xdist-1.32.0, html-2.1.1, metadata-1.8.0, cov-2.8.1, forked-1.1.2, nbval-0.9.5 collected 1 item
test_magics.ipynb E
====================================== ERRORS ====================================== ___________________ ERROR at setup of test_magics.ipynb::Cell 0 ____________________
self = <traitlets.traitlets.Instance object at 0x7f5509cf8650> obj = <jupyter_client.manager.KernelManager object at 0x7f5507dd5f10> cls = <class 'jupyter_client.manager.KernelManager'>
def get(self, obj, cls=None): try:
value = obj._trait_values[self.name]
E KeyError: 'session'
/home/sefkw/mc3/envs/celltestsui/lib/python3.7/site-packages/traitlets/traitlets.py:528: KeyError
During handling of the above exception, another exception occurred:
cls = <class '_pytest.runner.CallInfo'> func = <function call_runtest_hook.
. at 0x7f5507bede60> when = 'setup' reraise = (<class '_pytest.outcomes.Exit'>, <class 'KeyboardInterrupt'>) @classmethod def from_call(cls, func, when, reraise=None) -> "CallInfo": #: context of invocation: one of "setup", "call", #: "teardown", "memocollect" start = time() excinfo = None try:
result = func()
/home/sefkw/mc3/envs/celltestsui/lib/python3.7/site-packages/_pytest/runner.py:244:
lambda: ihook(item=item, **kwds), when=when, reraise=reraise
)
/home/sefkw/mc3/envs/celltestsui/lib/python3.7/site-packages/_pytest/runner.py:217:
self = <_HookCaller 'pytest_runtest_setup'>, args = () kwargs = {'item': <IPyNbCell Cell 0>}, notincall = set()
def __call__(self, *args, **kwargs): if args: raise TypeError("hook calling supports only keyword arguments") assert not self.is_historic() if self.spec and self.spec.argnames: notincall = ( set(self.spec.argnames) - set(["__multicall__"]) - set(kwargs.keys()) ) if notincall: warnings.warn( "Argument(s) {} which are declared in the hookspec " "can not be found in this hook call".format(tuple(notincall)), stacklevel=2, )
return self._hookexec(self, self.get_hookimpls(), kwargs)
/home/sefkw/mc3/envs/celltestsui/lib/python3.7/site-packages/pluggy/hooks.py:289:
self = <_pytest.config.PytestPluginManager object at 0x7f5504ba3a90> hook = <_HookCaller 'pytest_runtest_setup'> methods = [<HookImpl plugin_name='nose', plugin=<module '_pytest.nose' from '/home/sefkw/mc3/envs/celltestsui/lib/python3.7/site...xture=None>>, <HookImpl plugin_name='logging-plugin', plugin=<_pytest.logging.LoggingPlugin object at 0x7f5504b52b50>>] kwargs = {'item': <IPyNbCell Cell 0>}
def _hookexec(self, hook, methods, kwargs): # called from all hookcaller instances. # enable_tracing will set its own wrapping function at self._inner_hookexec
return self._inner_hookexec(hook, methods, kwargs)
/home/sefkw/mc3/envs/celltestsui/lib/python3.7/site-packages/pluggy/manager.py:87:
self = <pluggy._tracing._TracedHookExecution object at 0x7f5504ba3050> hook = <_HookCaller 'pytest_runtest_setup'> hook_impls = [<HookImpl plugin_name='nose', plugin=<module '_pytest.nose' from '/home/sefkw/mc3/envs/celltestsui/lib/python3.7/site...xture=None>>, <HookImpl plugin_name='logging-plugin', plugin=<_pytest.logging.LoggingPlugin object at 0x7f5504b52b50>>] kwargs = {'item': <IPyNbCell Cell 0>}
def __call__(self, hook, hook_impls, kwargs): self.before(hook.name, hook_impls, kwargs) outcome = _Result.from_call(lambda: self.oldcall(hook, hook_impls, kwargs)) self.after(outcome, hook.name, hook_impls, kwargs)
return outcome.get_result()
/home/sefkw/mc3/envs/celltestsui/lib/python3.7/site-packages/pluggy/_tracing.py:80:
self = <pluggy.callers._Result object at 0x7f5504b5d390>
def get_result(self): """Get the result(s) for this hook call. If the hook was marked as a ``firstresult`` only a single value will be returned otherwise a list of results. """ __tracebackhide__ = True if self._excinfo is None: return self._result else: ex = self._excinfo if _py3:
raise ex[1].with_traceback(ex[2])
/home/sefkw/mc3/envs/celltestsui/lib/python3.7/site-packages/pluggy/callers.py:80:
cls = <class 'pluggy.callers._Result'> func = <function _TracedHookExecution.call.
. at 0x7f5507bf1440> @classmethod def from_call(cls, func): __tracebackhide__ = True result = excinfo = None try:
result = func()
/home/sefkw/mc3/envs/celltestsui/lib/python3.7/site-packages/pluggy/callers.py:52:
outcome = _Result.from_call(lambda: self.oldcall(hook, hook_impls, kwargs))
/home/sefkw/mc3/envs/celltestsui/lib/python3.7/site-packages/pluggy/_tracing.py:78:
hook = <_HookCaller 'pytest_runtest_setup'> methods = [<HookImpl plugin_name='nose', plugin=<module '_pytest.nose' from '/home/sefkw/mc3/envs/celltestsui/lib/python3.7/site...xture=None>>, <HookImpl plugin_name='logging-plugin', plugin=<_pytest.logging.LoggingPlugin object at 0x7f5504b52b50>>] kwargs = {'item': <IPyNbCell Cell 0>}
self._inner_hookexec = lambda hook, methods, kwargs: hook.multicall( methods, kwargs,
firstresult=hook.spec.opts.get("firstresult") if hook.spec else False,
)
/home/sefkw/mc3/envs/celltestsui/lib/python3.7/site-packages/pluggy/manager.py:81:
hook_impls = [<HookImpl plugin_name='nose', plugin=<module '_pytest.nose' from '/home/sefkw/mc3/envs/celltestsui/lib/python3.7/site...xture=None>>, <HookImpl plugin_name='logging-plugin', plugin=<_pytest.logging.LoggingPlugin object at 0x7f5504b52b50>>] caller_kwargs = {'item': <IPyNbCell Cell 0>}, firstresult = False
def _multicall(hook_impls, caller_kwargs, firstresult=False): """Execute a call into multiple python functions/methods and return the result(s). ``caller_kwargs`` comes from _HookCaller.__call__(). """ __tracebackhide__ = True results = [] excinfo = None try: # run impl and wrapper setup functions in a loop teardowns = [] try: for hook_impl in reversed(hook_impls): try: args = [caller_kwargs[argname] for argname in hook_impl.argnames] except KeyError: for argname in hook_impl.argnames: if argname not in caller_kwargs: raise HookCallError( "hook call must provide argument %r" % (argname,) ) if hook_impl.hookwrapper: try: gen = hook_impl.function(*args) next(gen) # first yield teardowns.append(gen) except StopIteration: _raise_wrapfail(gen, "did not yield") else: res = hook_impl.function(*args) if res is not None: results.append(res) if firstresult: # halt further impl calls break except BaseException: excinfo = sys.exc_info() finally: if firstresult: # first result hooks return a single value outcome = _Result(results[0] if results else None, excinfo) else: outcome = _Result(results, excinfo) # run all wrapper post-yield blocks for gen in reversed(teardowns): try: gen.send(outcome) _raise_wrapfail(gen, "has second yield") except StopIteration: pass
return outcome.get_result()
/home/sefkw/mc3/envs/celltestsui/lib/python3.7/site-packages/pluggy/callers.py:208:
self = <pluggy.callers._Result object at 0x7f5504b5d210>
def get_result(self): """Get the result(s) for this hook call. If the hook was marked as a ``firstresult`` only a single value will be returned otherwise a list of results. """ __tracebackhide__ = True if self._excinfo is None: return self._result else: ex = self._excinfo if _py3:
raise ex[1].with_traceback(ex[2])
/home/sefkw/mc3/envs/celltestsui/lib/python3.7/site-packages/pluggy/callers.py:80:
hook_impls = [<HookImpl plugin_name='nose', plugin=<module '_pytest.nose' from '/home/sefkw/mc3/envs/celltestsui/lib/python3.7/site...xture=None>>, <HookImpl plugin_name='logging-plugin', plugin=<_pytest.logging.LoggingPlugin object at 0x7f5504b52b50>>] caller_kwargs = {'item': <IPyNbCell Cell 0>}, firstresult = False
def _multicall(hook_impls, caller_kwargs, firstresult=False): """Execute a call into multiple python functions/methods and return the result(s). ``caller_kwargs`` comes from _HookCaller.__call__(). """ __tracebackhide__ = True results = [] excinfo = None try: # run impl and wrapper setup functions in a loop teardowns = [] try: for hook_impl in reversed(hook_impls): try: args = [caller_kwargs[argname] for argname in hook_impl.argnames] except KeyError: for argname in hook_impl.argnames: if argname not in caller_kwargs: raise HookCallError( "hook call must provide argument %r" % (argname,) ) if hook_impl.hookwrapper: try: gen = hook_impl.function(*args) next(gen) # first yield teardowns.append(gen) except StopIteration: _raise_wrapfail(gen, "did not yield") else:
res = hook_impl.function(*args)
/home/sefkw/mc3/envs/celltestsui/lib/python3.7/site-packages/pluggy/callers.py:187:
item = <IPyNbCell Cell 0>
def pytest_runtest_setup(item): _update_current_test_var(item, "setup")
item.session._setupstate.prepare(item)
/home/sefkw/mc3/envs/celltestsui/lib/python3.7/site-packages/_pytest/runner.py:123:
self = <_pytest.runner.SetupState object at 0x7f5504b64450> colitem = <IPyNbCell Cell 0>
def prepare(self, colitem): """ setup objects along the collector chain to the test-method and teardown previously setup objects.""" needed_collectors = colitem.listchain() self._teardown_towards(needed_collectors) # check if the last collection node has raised an error for col in self.stack: if hasattr(col, "_prepare_exc"): exc = col._prepare_exc raise exc for col in needed_collectors[len(self.stack) :]: self.stack.append(col) try: col.setup() except TEST_OUTCOME as e: col._prepare_exc = e
raise e
/home/sefkw/mc3/envs/celltestsui/lib/python3.7/site-packages/_pytest/runner.py:376:
self = <_pytest.runner.SetupState object at 0x7f5504b64450> colitem = <IPyNbCell Cell 0>
def prepare(self, colitem): """ setup objects along the collector chain to the test-method and teardown previously setup objects.""" needed_collectors = colitem.listchain() self._teardown_towards(needed_collectors) # check if the last collection node has raised an error for col in self.stack: if hasattr(col, "_prepare_exc"): exc = col._prepare_exc raise exc for col in needed_collectors[len(self.stack) :]: self.stack.append(col) try:
col.setup()
/home/sefkw/mc3/envs/celltestsui/lib/python3.7/site-packages/_pytest/runner.py:373:
self = <IPyNbFile test_magics.ipynb>
def setup(self): """ Called by pytest to setup the collector cells in . Here we start a kernel and setup the sanitize patterns. """ if self.parent.config.option.current_env: kernel_name = CURRENT_ENV_KERNEL_NAME else: kernel_name = self.nb.metadata.get( 'kernelspec', {}).get('name', 'python')
self.kernel = RunningKernel(kernel_name, str(self.fspath.dirname))
/home/sefkw/code/external/nbval/nbval/plugin.py:233:
self = <nbval.kernel.RunningKernel object at 0x7f5504b5d250> kernel_name = ':nbval-parent-env' cwd = '/tmp/pytest-of-sefkw/pytest-36/test_magics1'
def __init__(self, kernel_name, cwd=None): """ Initialise a new kernel specify that matplotlib is inline and connect the stderr. Stores the active kernel process and its manager. """ self.km, self.kc = start_new_kernel( kernel_name=kernel_name, stderr=open(os.devnull, 'w'),
cwd=cwd,
)
/home/sefkw/code/external/nbval/nbval/kernel.py:88:
startup_timeout = 60, kernel_name = ':nbval-parent-env' kwargs = {'cwd': '/tmp/pytest-of-sefkw/pytest-36/test_magics1', 'stderr': <_io.TextIOWrapper name='/dev/null' mode='w' encoding='UTF-8'>} km = <jupyter_client.manager.KernelManager object at 0x7f5507dd5f10>
def start_new_kernel(startup_timeout=60, kernel_name='python', **kwargs): """Start a new kernel, and return its Manager and Client""" logger.debug('Starting new kernel: "%s"' % kernel_name) km = KernelManager(kernel_name=kernel_name, kernel_spec_manager=NbvalKernelspecManager())
km.start_kernel(**kwargs)
/home/sefkw/code/external/nbval/nbval/kernel.py:53:
self = <jupyter_client.manager.KernelManager object at 0x7f5507dd5f10> kw = {'cwd': '/tmp/pytest-of-sefkw/pytest-36/test_magics1', 'stderr': <_io.TextIOWrapper name='/dev/null' mode='w' encoding='UTF-8'>}
def start_kernel(self, **kw): """Starts a kernel on this host in a separate process. If random ports (port=0) are being used, this method must be called before the channels are created. Parameters ---------- `**kw` : optional keyword arguments that are passed down to build the kernel_cmd and launching the kernel (e.g. Popen kwargs). """
kernel_cmd, kw = self.pre_start_kernel(**kw)
/home/sefkw/mc3/envs/celltestsui/lib/python3.7/site-packages/jupyter_client/manager.py:301:
self = <jupyter_client.manager.KernelManager object at 0x7f5507dd5f10> kw = {'cwd': '/tmp/pytest-of-sefkw/pytest-36/test_magics1', 'stderr': <_io.TextIOWrapper name='/dev/null' mode='w' encoding='UTF-8'>}
def pre_start_kernel(self, **kw): """Prepares a kernel for startup in a separate process. If random ports (port=0) are being used, this method must be called before the channels are created. Parameters ---------- `**kw` : optional keyword arguments that are passed down to build the kernel_cmd and launching the kernel (e.g. Popen kwargs). """ if self.transport == 'tcp' and not is_local_ip(self.ip): raise RuntimeError("Can only launch a kernel on a local interface. " "This one is not: %s." "Make sure that the '*_address' attributes are " "configured properly. " "Currently valid addresses are: %s" % (self.ip, local_ips()) ) # write connection file / get default ports
self.write_connection_file()
/home/sefkw/mc3/envs/celltestsui/lib/python3.7/site-packages/jupyter_client/manager.py:248:
self = <jupyter_client.manager.KernelManager object at 0x7f5507dd5f10>
def write_connection_file(self): """Write connection info to JSON dict in self.connection_file.""" if self._connection_file_written and os.path.exists(self.connection_file): return self.connection_file, cfg = write_connection_file(self.connection_file,
transport=self.transport, ip=self.ip, key=self.session.key,
stdin_port=self.stdin_port, iopub_port=self.iopub_port, shell_port=self.shell_port, hb_port=self.hb_port, control_port=self.control_port, signature_scheme=self.session.signature_scheme, kernel_name=self.kernel_name )
/home/sefkw/mc3/envs/celltestsui/lib/python3.7/site-packages/jupyter_client/connect.py:469:
self = <traitlets.traitlets.Instance object at 0x7f5509cf8650> obj = <jupyter_client.manager.KernelManager object at 0x7f5507dd5f10> cls = <class 'jupyter_client.manager.KernelManager'>
def __get__(self, obj, cls=None): """Get the value of the trait by self.name for the instance. Default values are instantiated when :meth:`HasTraits.__new__` is called. Thus by the time this method gets called either the default value or a user defined value (they called :meth:`__set__`) is in the :class:`HasTraits` instance. """ if obj is None: return self else:
return self.get(obj, cls)
/home/sefkw/mc3/envs/celltestsui/lib/python3.7/site-packages/traitlets/traitlets.py:556:
self = <traitlets.traitlets.Instance object at 0x7f5509cf8650> obj = <jupyter_client.manager.KernelManager object at 0x7f5507dd5f10> cls = <class 'jupyter_client.manager.KernelManager'>
def get(self, obj, cls=None): try: value = obj._trait_values[self.name] except KeyError: # Check for a dynamic initializer. dynamic_default = self._dynamic_default_callable(obj) if dynamic_default is None: raise TraitError("No default value found for %s trait of %r" % (self.name, obj))
value = self._validate(obj, dynamic_default())
/home/sefkw/mc3/envs/celltestsui/lib/python3.7/site-packages/traitlets/traitlets.py:535:
self = <traitlets.traitlets.Instance object at 0x7f5509cf8650> obj = <jupyter_client.manager.KernelManager object at 0x7f5507dd5f10> value = <jupyter_client.session.Session object at 0x7f5507c33c10>
def _validate(self, obj, value): if value is None and self.allow_none: return value if hasattr(self, 'validate'):
value = self.validate(obj, value)
/home/sefkw/mc3/envs/celltestsui/lib/python3.7/site-packages/traitlets/traitlets.py:591:
self = <traitlets.traitlets.Instance object at 0x7f5509cf8650> obj = <jupyter_client.manager.KernelManager object at 0x7f5507dd5f10> value = <jupyter_client.session.Session object at 0x7f5507c33c10>
def validate(self, obj, value): if isinstance(value, self.klass): return value else:
self.error(obj, value)
/home/sefkw/mc3/envs/celltestsui/lib/python3.7/site-packages/traitlets/traitlets.py:1677:
self = <traitlets.traitlets.Instance object at 0x7f5509cf8650> obj = <jupyter_client.manager.KernelManager object at 0x7f5507dd5f10> value = <jupyter_client.session.Session object at 0x7f5507c33c10>
def error(self, obj, value): kind = type(value) if six.PY2 and kind is InstanceType: msg = 'class %s' % value.__class__.__name__ else: msg = '%s (i.e. %s)' % ( str( kind )[1:-1], repr( value ) ) if obj is not None: e = "The '%s' trait of %s instance must be %s, but a value of %s was specified." \ % (self.name, class_of(obj), self.info(), msg) else: e = "The '%s' trait must be %s, but a value of %r was specified." \ % (self.name, self.info(), msg)
raise TraitError(e)
E traitlets.traitlets.TraitError: The 'session' trait of a KernelManager instance must be a Session, but a value of class 'jupyter_client.session.Session' (i.e. <jupyter_client.session.Session object at 0x7f5507c33c10>) was specified.
/home/sefkw/mc3/envs/celltestsui/lib/python3.7/site-packages/traitlets/traitlets.py:1524: TraitError ================================= warnings summary ================================= /home/sefkw/code/external/nbval/nbval/plugin.py:115 /home/sefkw/code/external/nbval/nbval/plugin.py:115: PytestDeprecationWarning: direct construction of IPyNbFile has been deprecated, please use IPyNbFile.from_parent return IPyNbFile(path, parent)
/home/sefkw/code/external/nbval/nbval/plugin.py:312 /home/sefkw/code/external/nbval/nbval/plugin.py:312: PytestDeprecationWarning: direct construction of IPyNbCell has been deprecated, please use IPyNbCell.from_parent cell, options)
-- Docs: https://docs.pytest.org/en/latest/warnings.html ============================= short test summary info ============================== ERROR test_magics.ipynb::Cell 0 - traitlets.traitlets.TraitError: The 'session' t... =========================== 2 warnings, 1 error in 0.21s =========================== ================================= warnings summary ================================= tests/test_magics.py::test_magics[%dirs-expected_passes0] tests/test_magics.py::test_magics[%this_magic_does_not_exist-expected_passes1] /home/sefkw/mc3/envs/celltestsui/lib/python3.7/site-packages/_pytest/terminal.py:289: PytestDeprecationWarning: TerminalReporter.writer attribute is deprecated, use TerminalReporter._tw instead at your own risk. See https://docs.pytest.org/en/latest/deprecations.html#terminalreporter-writer for more information. "TerminalReporter.writer attribute is deprecated, use TerminalReporter._tw instead at your own risk.\n"
-- Docs: https://docs.pytest.org/en/latest/warnings.html ============================= short test summary info ============================== FAILED tests/test_magics.py::test_magics[%this_magic_does_not_exist-expected_passes1] ===================== 1 failed, 1 passed, 2 warnings in 1.17s =====================
Hmm, re. problem 2 above: travis does not have the problem. So I guess it's related to my environment; I'll try a new environment and see what happens.
I had been using conda. I tried in a newly created python virtualenv (using my system python 3) - same problem :(
I suppose I should compare the packages here to the ones on travis:
(nbv) $ python --version
Python 3.8.2
(nbv) $ pip freeze
attrs==19.3.0
backcall==0.2.0
coverage==5.1
cycler==0.10.0
decorator==4.4.2
ipykernel==5.3.0
ipython==7.15.0
ipython-genutils==0.2.0
jedi==0.17.0
jsonschema==3.2.0
jupyter-client==6.1.3
jupyter-core==4.6.3
kiwisolver==1.2.0
matplotlib==3.2.1
more-itertools==8.3.0
mpmath==1.1.0
nbformat==5.0.7
-e [email protected]:ceball/nbval.git@ab7f9e8129848eabda3ce2633f5305ccfa81131c#egg=nbval
numpy==1.18.5
packaging==20.4
parso==0.7.0
pexpect==4.8.0
pickleshare==0.7.5
pluggy==0.13.1
prompt-toolkit==3.0.5
ptyprocess==0.6.0
py==1.8.1
Pygments==2.6.1
pyparsing==2.4.7
pyrsistent==0.16.0
pytest==5.4.3
pytest-cov==2.9.0
python-dateutil==2.8.1
pyzmq==19.0.1
six==1.15.0
sympy==1.6
tornado==6.0.4
traitlets==4.3.3
wcwidth==0.2.4
It's not the dependencies. Locally I get
- Same correct result as on travis if I run
py.test -v tests --nbval --current-env --sanitize-with tests/sanitize_defaults.cfg --ignore tests/ipynb-test-samples
- The weird
traitlets.traitlets.TraitError: The 'session' trait of a KernelManager instance must be a Session, but a value of class 'jupyter_client.session.Session' (i.e. <jupyter_client.session.Session object at 0x7f353ffdea00>) was specified.
if I append-k test_magics
to the above command.
I could try to narrow down, but I don't suppose you want to take a guess @vidartf ?
Ok, the test results are now as I expect, i.e. they reflect the bug I'll fix in this PR: %this_magic_does_not_exist
passes silently (which is wrong, hence causing the tests added to this PR to fail).
=================================== FAILURES ===================================
________________ test_magics[%this_magic_does_not_exist-False] _________________
testdir = <Testdir local('/tmp/pytest-of-travis/pytest-0/test_magics2')>
magic = '%this_magic_does_not_exist', expected_pass = False
@pytest.mark.parametrize("magic, expected_pass", [
(r"%dirs", True),
(r"%precision bad", False),
(r"%this_magic_does_not_exist", False)
])
def test_magics(testdir, magic, expected_pass):
nb = build_nb([
# In [1]:
magic,
])
nb_name = 'test_magics'
nbformat.write(nb, os.path.join(
str(testdir.tmpdir), nb_name+".ipynb"))
# using subprocess because otherwise second and subsequent tests always fail (some state left over somewhere in the jupyter stack)
result = testdir.runpytest_subprocess('--nbval-lax', '--current-env', '-s', '-v')
> assert result.ret == (not expected_pass)
E assert <ExitCode.OK: 0> == True
E +<ExitCode.OK: 0>
E -True