Skip to content
This repository was archived by the owner on Sep 26, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 0 additions & 13 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,19 +55,6 @@ jobs:
user: ceball
password: $PYPI_PWD

- <<: *default
stage: pip_dev_package
install: true
script: true
deploy:
provider: pypi
server: https://test.pypi.org/legacy/
distributions: "sdist bdist_wheel"
on:
tags: true
user: ceball
password: $PYPI_PWD

# TODO: don't need to clone the repo
- stage: test_latest_release
python: 3.7
Expand Down
3 changes: 3 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ configuration in setup.cfg, pytest.ini, or tox.ini::
nbsmoke_flakes_cell_magics_blacklist = bash
ruby

# add your own magic handlers (python file containing line_magic_handlers and cell_magic_handlers as dictionaries magic_name: callable)
nbsmoke_magic_handlers = path/to/file.py


nbsmoke supports ``# noqa`` comments to mark that something
should be ignored during lint checking.
Expand Down
2 changes: 2 additions & 0 deletions nbsmoke/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ def pytest_addoption(parser):
parser.addini('nbsmoke_flakes_cell_magics_blacklist', "cell magics you don't want to see - i.e. treat as lint.")
parser.addini('nbsmoke_flakes_line_magics_blacklist', "line magics you don't want to see - i.e. treat as lint")

parser.addini('nbsmoke_magic_handlers', "path to .py file containing custom magic handlers")


@contextlib.contextmanager
def cwd(d):
Expand Down
3 changes: 2 additions & 1 deletion nbsmoke/lint/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ def runtest(self):

magics_processor = magics.Processor(
extra_line_blacklist = _get_list_from_conf('nbsmoke_flakes_line_magics_blacklist', self.parent.parent.config),
extra_cell_blacklist = _get_list_from_conf('nbsmoke_flakes_cell_magics_blacklist', self.parent.parent.config))
extra_cell_blacklist = _get_list_from_conf('nbsmoke_flakes_cell_magics_blacklist', self.parent.parent.config),
extra_magic_handlers = self.parent.parent.config.getini('nbsmoke_magic_handlers'))
magics_processor.insert_get_ipython(nb)

ipy, _ = nbconvert.PythonExporter().from_notebook_node(nb)
Expand Down
23 changes: 20 additions & 3 deletions nbsmoke/lint/magics/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,27 @@
# TODO: suddenly had to make some fns into a class to support blacklists; should rework.
class Processor(object):

def __init__(self, extra_cell_blacklist=None, extra_line_blacklist=None):
def __init__(self, extra_cell_blacklist=None, extra_line_blacklist=None, extra_magic_handlers=None):
self.blacklisted_cell = (extra_cell_blacklist or []) + BLACKLISTED_CELL_MAGICS
self.blacklisted_line = (extra_line_blacklist or []) + BLACKLISTED_LINE_MAGICS
self.extra_cell_magic_handlers = dict(other_cell_magic_handlers)
self.extra_line_magic_handlers = dict(other_line_magic_handlers)

if extra_magic_handlers:
user_cell_magic_handlers, user_line_magic_handlers = self._load_user_magic_handlers(extra_magic_handlers)
self.extra_cell_magic_handlers.update(user_cell_magic_handlers)
self.extra_line_magic_handlers.update(user_line_magic_handlers)


@staticmethod
def _load_user_magic_handlers(path):
from importlib import util
spec = util.spec_from_file_location("_nbsmoke_user_magic_handlers", path)
mod = util.module_from_spec(spec)
spec.loader.exec_module(mod)
return mod.cell_magic_handlers, mod.line_magic_handlers


@staticmethod
def insert_get_ipython(nb):
# define and use get_ipython (for pyflakes)
Expand Down Expand Up @@ -152,9 +169,9 @@ def _process(self, magic):
if isinstance(magic, NotMagic):
content = magic.line
elif isinstance(magic, LineMagic):
content = _process_magics(magic, other_line_magic_handlers, IGNORED_LINE_MAGICS, self.blacklisted_line, SIMPLE_LINE_MAGICS)
content = _process_magics(magic, self.extra_line_magic_handlers, IGNORED_LINE_MAGICS, self.blacklisted_line, SIMPLE_LINE_MAGICS)
elif isinstance(magic, CellMagic):
content = _process_magics(magic, other_cell_magic_handlers, IGNORED_CELL_MAGICS, self.blacklisted_cell)
content = _process_magics(magic, self.extra_cell_magic_handlers, IGNORED_CELL_MAGICS, self.blacklisted_cell)
else:
raise
return content
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def read(fname):
# * Optional: process ipython magics (required import: IPython)
'jupyter_client',
'nbformat',
'nbconvert <6',
'nbconvert',
'ipykernel'],
extras_require = extras_require,
entry_points={
Expand Down
12 changes: 5 additions & 7 deletions tests/test_lint_magics.py
Original file line number Diff line number Diff line change
Expand Up @@ -425,14 +425,12 @@ def test_lint_magics_warn_about_unhandled(testdir):
".*nbsmoke doesn't know how to process the.*cellmagicnonexistentthree.*CellMagic and has ignored it.*"])

def test_optional_import_warn(testdir):
testdir.makeini(r"""
[pytest]
nbsmoke_magic_handlers = my_magic_handlers.py
""")
testdir.makefile('.ipynb', testing123=nb_optional_dep)
###
# what a hack
def not_clever_magics_handler(magic):
raise ImportError("Amazing dependency is missing")
import nbsmoke.lint.magics as M
M.other_line_magic_handlers['clever_magic'] = not_clever_magics_handler
###
testdir.makefile(".py", my_magic_handlers="def not_clever_magics_handler(magic):\n raise ImportError('Amazing dependency is missing')\n\nline_magic_handlers=dict(clever_magic=not_clever_magics_handler);cell_magic_handlers={}")
result = testdir.runpytest(*lint_args)
assert result.ret == 1
result.stdout.re_match_lines_random(
Expand Down
15 changes: 9 additions & 6 deletions tests/test_run.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,30 @@

from . import nb_basic, run_args

# tests are run in subprocess because otherwise some state seems to be left
# around somewhere in jupyter (https://github.com/pyviz-dev/nbsmoke/issues/45)

# maybe this test is overkill now we check for certain output in the run tests?
def test_definitely_ran_paranoid(testdir):
assert not os.path.exists('sigh')
testdir.makefile('.ipynb', testing123=nb_basic%{'the_source':"open('x','w').write('y')"})
result = testdir.runpytest(*run_args)
result = testdir.runpytest_subprocess(*run_args)
assert result.ret==0
with open('x','r') as f:
assert f.read() == 'y'
assert os.path.isfile('sigh')

def test_run_good(testdir):
testdir.makefile('.ipynb', testing123=nb_basic%{'the_source':"1/1"})
result = testdir.runpytest(*run_args)
result = testdir.runpytest_subprocess(*run_args)
assert result.ret == 0
result.stdout.re_match_lines_random(
[".*collected 1 item$",
".*testing123.ipynb.*PASSED.*"])

def test_run_bad(testdir):
testdir.makefile('.ipynb', testing123=nb_basic%{'the_source':"1/0"})
result = testdir.runpytest(*run_args)
result = testdir.runpytest_subprocess(*run_args)
assert result.ret == 1
result.stdout.re_match_lines_random([".*ZeroDivisionError.*"])

Expand All @@ -37,7 +40,7 @@ def test_run_good_html(testdir):

testdir.makefile('.ipynb', testing123=nb_basic%{'the_source':"42"})

result = testdir.runpytest(*(run_args+['--store-html=%s'%testdir.tmpdir.strpath]))
result = testdir.runpytest_subprocess(*(run_args+['--store-html=%s'%testdir.tmpdir.strpath]))
assert result.ret == 0

# test that html has happened
Expand Down Expand Up @@ -65,7 +68,7 @@ def test_skip_run(testdir):
testdir.makefile('.ipynb', alsoskipme=nb_basic%{'the_source':"1/0"})
testdir.makefile('.ipynb', skipmetoo=nb_basic%{'the_source':"1/0"})
testdir.makefile('.ipynb', skipmenot=nb_basic%{'the_source':"1/1"})
result = testdir.runpytest(*run_args)
result = testdir.runpytest_subprocess(*run_args)
assert result.ret == 0
result.stdout.re_match_lines_random(
[".*collected 4 items$",
Expand All @@ -79,5 +82,5 @@ def test_cwd_like_jupyter_notebook(testdir):
p.write("content")
testdir.makefile('.ipynb', testing123=nb_basic%{'the_source':"import os; assert os.path.isfile('hello.txt')"})
shutil.move('testing123.ipynb', 'sub')
result = testdir.runpytest(*run_args)
result = testdir.runpytest_subprocess(*run_args)
assert result.ret == 0
4 changes: 0 additions & 4 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,6 @@ envlist = py36,py37,py38,pypy,flake8,dev
commands = py.test -v {posargs:tests}
extras = all

[testenv:py27]
commands = py.test -v {posargs:tests}
extras = verify

[testenv:coverage]
setdevelop = True
passenv = TRAVIS TRAVIS_*
Expand Down