Uploaded Test files

This commit is contained in:
Batuhan Berk Başoğlu 2020-11-12 11:05:57 -05:00
parent f584ad9d97
commit 2e81cb7d99
16627 changed files with 2065359 additions and 102444 deletions

View file

@ -0,0 +1,55 @@
"""utility functions for preprocessor tests"""
# Copyright (c) IPython Development Team.
# Distributed under the terms of the Modified BSD License.
from nbformat import v4 as nbformat
from ...tests.base import TestsBase
from ...exporters.exporter import ResourcesDict
class PreprocessorTestsBase(TestsBase):
"""Contains test functions preprocessor tests"""
def build_notebook(self, with_json_outputs=False):
"""Build a notebook in memory for use with preprocessor tests"""
outputs = [
nbformat.new_output("stream", name="stdout", text="a"),
nbformat.new_output("display_data", data={'text/plain': 'b'}),
nbformat.new_output("stream", name="stdout", text="c"),
nbformat.new_output("stream", name="stdout", text="d"),
nbformat.new_output("stream", name="stderr", text="e"),
nbformat.new_output("stream", name="stderr", text="f"),
nbformat.new_output("display_data", data={'image/png': 'Zw=='}), # g
nbformat.new_output("display_data", data={'application/pdf': 'aA=='}), # h
]
if with_json_outputs:
outputs.extend([
nbformat.new_output(
"display_data", data={'application/json': [1, 2, 3]}
), # j
nbformat.new_output(
"display_data", data={'application/json': {'a': 1, 'c': {'b': 2}}}
), # k
nbformat.new_output(
"display_data", data={'application/json': 'abc'}
), # l
nbformat.new_output(
"display_data", data={'application/json': 15.03}
), # m
])
cells=[nbformat.new_code_cell(source="$ e $", execution_count=1, outputs=outputs),
nbformat.new_markdown_cell(source="$ e $")]
return nbformat.new_notebook(cells=cells)
def build_resources(self):
"""Build an empty resources dictionary."""
res = ResourcesDict()
res['metadata'] = ResourcesDict()
return res

View file

@ -0,0 +1,28 @@
from jupyter_client.manager import KernelManager
class FakeCustomKernelManager(KernelManager):
expected_methods = {
'__init__': 0,
'client': 0,
'start_kernel': 0,
}
def __init__(self, *args, **kwargs):
self.log.info('FakeCustomKernelManager initialized')
self.expected_methods['__init__'] += 1
super().__init__(*args, **kwargs)
def start_kernel(self, *args, **kwargs):
self.log.info('FakeCustomKernelManager started a kernel')
self.expected_methods['start_kernel'] += 1
return super().start_kernel(
*args,
**kwargs)
def client(self, *args, **kwargs):
self.log.info('FakeCustomKernelManager created a client')
self.expected_methods['client'] += 1
return super().client(
*args,
**kwargs)

View file

@ -0,0 +1,26 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Hello World\n"
]
}
],
"source": [
"print(\"Hello World\")"
]
}
],
"metadata": {},
"nbformat": 4,
"nbformat_minor": 0
}

View file

@ -0,0 +1,49 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"this is a code cell\n"
]
}
],
"source": [
"print('this is a code cell')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# This is a markdown cell"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.2"
}
},
"nbformat": 4,
"nbformat_minor": 4
}

View file

@ -0,0 +1,133 @@
"""
Module with tests for the clearmetadata preprocessor.
"""
# Copyright (c) IPython Development Team.
# Distributed under the terms of the Modified BSD License.
from .base import PreprocessorTestsBase
from ..clearmetadata import ClearMetadataPreprocessor
class TestClearMetadata(PreprocessorTestsBase):
"""Contains test functions for clearmetadata.py"""
def build_notebook(self):
notebook = super().build_notebook()
notebook.metadata = {
'language_info': {'name': 'python', 'version': '3.6.7'},
'kernelspec': {'language': 'python', 'name': 'python3'}
}
# Add a test field to the first cell
if 'metadata' not in notebook.cells[0]:
notebook.cells[0].metadata = {}
notebook.cells[0].metadata['test_field'] = 'test_value'
notebook.cells[0].metadata['test_nested'] = { 'test_keep': 'keep', 'test_filtered': 'filter' }
notebook.cells[0].metadata['executeTime'] = dict([('end_time', '09:31:50'),
('start_time', '09:31:49')])
return notebook
def build_preprocessor(self, **kwargs):
"""Make an instance of a preprocessor"""
preprocessor = ClearMetadataPreprocessor(**kwargs)
preprocessor.enabled = True
return preprocessor
def test_constructor(self):
"""Can a ClearMetadataPreprocessor be constructed?"""
self.build_preprocessor()
def test_default_output(self):
"""Test the output of the ClearMetadataPreprocessor"""
nb = self.build_notebook()
res = self.build_resources()
preprocessor = self.build_preprocessor()
nb, res = preprocessor(nb, res)
assert not nb.cells[0].metadata
# By default we only perserve the langauge name
assert nb.metadata == {'language_info': {'name': 'python'}}
def test_cell_only(self):
"""Test the output of the ClearMetadataPreprocessor"""
nb = self.build_notebook()
res = self.build_resources()
preprocessor = self.build_preprocessor(clear_notebook_metadata=False)
nb, res = preprocessor(nb, res)
assert not nb.cells[0].metadata
assert nb.metadata
def test_notebook_only(self):
"""Test the output of the ClearMetadataPreprocessor"""
nb = self.build_notebook()
res = self.build_resources()
preprocessor = self.build_preprocessor(clear_cell_metadata=False, preserve_nb_metadata_mask=set())
nb, res = preprocessor(nb, res)
assert nb.cells[0].metadata
assert not nb.metadata
def test_selective_cell_metadata(self):
"""Test the output of the ClearMetadataPreprocessor"""
nb = self.build_notebook()
res = self.build_resources()
preprocessor = self.build_preprocessor(
preserve_cell_metadata_mask=['test_field'],
preserve_nb_metadata_mask=set()
)
nb, res = preprocessor(nb, res)
assert nb.cells[0].metadata == { 'test_field': 'test_value' }
assert not nb.metadata
def test_selective_cell_tuple_metadata(self):
"""Test the output of the ClearMetadataPreprocessor"""
nb = self.build_notebook()
res = self.build_resources()
# Ensure that a tuple length 1 works as well as a string key
preprocessor = self.build_preprocessor(
preserve_cell_metadata_mask=[('test_field',)],
preserve_nb_metadata_mask=set()
)
nb, res = preprocessor(nb, res)
assert nb.cells[0].metadata == { 'test_field': 'test_value' }
assert not nb.metadata
def test_nested_cell_metadata(self):
"""Test the output of the ClearMetadataPreprocessor"""
nb = self.build_notebook()
res = self.build_resources()
preprocessor = self.build_preprocessor(
preserve_cell_metadata_mask=[('test_nested', 'test_keep')],
preserve_nb_metadata_mask=set()
)
nb, res = preprocessor(nb, res)
assert nb.cells[0].metadata == { 'test_nested': { 'test_keep': 'keep' } }
assert not nb.metadata
def test_nested_cell_tuple_metadata(self):
"""Test the output of the ClearMetadataPreprocessor"""
nb = self.build_notebook()
res = self.build_resources()
# Ensure that a tuple length 1 works as well as a string key
preprocessor = self.build_preprocessor(
preserve_cell_metadata_mask=[('test_nested', ('test_keep',))],
preserve_nb_metadata_mask=set()
)
nb, res = preprocessor(nb, res)
assert nb.cells[0].metadata == { 'test_nested': { 'test_keep': 'keep' } }
assert not nb.metadata
def test_selective_notebook_metadata(self):
"""Test the output of the ClearMetadataPreprocessor"""
nb = self.build_notebook()
res = self.build_resources()
preprocessor = self.build_preprocessor(preserve_nb_metadata_mask=['kernelspec'])
nb, res = preprocessor(nb, res)
assert not nb.cells[0].metadata
assert nb.metadata == { 'kernelspec': { 'language': 'python', 'name': 'python3' } }

View file

@ -0,0 +1,49 @@
"""
Module with tests for the clearoutput preprocessor.
"""
# Copyright (c) IPython Development Team.
# Distributed under the terms of the Modified BSD License.
from .base import PreprocessorTestsBase
from ..clearoutput import ClearOutputPreprocessor
class TestClearOutput(PreprocessorTestsBase):
"""Contains test functions for clearoutput.py"""
def build_notebook(self):
notebook = super().build_notebook()
# Add a test field to the first cell
if 'metadata' not in notebook.cells[0]:
notebook.cells[0].metadata = {}
notebook.cells[0].metadata['test_field'] = 'test_value'
return notebook
def build_preprocessor(self):
"""Make an instance of a preprocessor"""
preprocessor = ClearOutputPreprocessor()
preprocessor.enabled = True
return preprocessor
def test_constructor(self):
"""Can a ClearOutputPreprocessor be constructed?"""
self.build_preprocessor()
def test_output(self):
"""Test the output of the ClearOutputPreprocessor"""
for remove_test_field in [False, True]:
nb = self.build_notebook()
res = self.build_resources()
preprocessor = self.build_preprocessor()
# Also remove the test field in addition to defaults
if remove_test_field:
preprocessor.remove_metadata_fields.add('test_field')
nb, res = preprocessor(nb, res)
assert nb.cells[0].outputs == []
assert nb.cells[0].execution_count is None
if 'metadata' in nb.cells[0]:
for field in preprocessor.remove_metadata_fields:
assert field not in nb.cells[0].metadata
# Ensure the test field is only removed when added to the traitlet
assert remove_test_field or 'test_field' in nb.cells[0].metadata

View file

@ -0,0 +1,58 @@
"""Tests for the coalescestreams preprocessor"""
# Copyright (c) IPython Development Team.
# Distributed under the terms of the Modified BSD License.
from nbformat import v4 as nbformat
from .base import PreprocessorTestsBase
from ..coalescestreams import coalesce_streams
class TestCoalesceStreams(PreprocessorTestsBase):
"""Contains test functions for coalescestreams.py"""
def test_coalesce_streams(self):
"""coalesce_streams preprocessor output test"""
nb = self.build_notebook()
res = self.build_resources()
nb, res = coalesce_streams(nb, res)
outputs = nb.cells[0].outputs
self.assertEqual(outputs[0].text, "a")
self.assertEqual(outputs[1].output_type, "display_data")
self.assertEqual(outputs[2].text, "cd")
self.assertEqual(outputs[3].text, "ef")
def test_coalesce_sequenced_streams(self):
"""Can the coalesce streams preprocessor merge a sequence of streams?"""
outputs = [nbformat.new_output(output_type="stream", name="stdout", text="0"),
nbformat.new_output(output_type="stream", name="stdout", text="1"),
nbformat.new_output(output_type="stream", name="stdout", text="2"),
nbformat.new_output(output_type="stream", name="stdout", text="3"),
nbformat.new_output(output_type="stream", name="stdout", text="4"),
nbformat.new_output(output_type="stream", name="stdout", text="5"),
nbformat.new_output(output_type="stream", name="stdout", text="6"),
nbformat.new_output(output_type="stream", name="stdout", text="7")]
cells=[nbformat.new_code_cell(source="# None", execution_count=1,outputs=outputs)]
nb = nbformat.new_notebook(cells=cells)
res = self.build_resources()
nb, res = coalesce_streams(nb, res)
outputs = nb.cells[0].outputs
self.assertEqual(outputs[0].text, u'01234567')
def test_coalesce_replace_streams(self):
"""Are \\r characters handled?"""
outputs = [nbformat.new_output(output_type="stream", name="stdout", text="z"),
nbformat.new_output(output_type="stream", name="stdout", text="\ra"),
nbformat.new_output(output_type="stream", name="stdout", text="\nz\rb"),
nbformat.new_output(output_type="stream", name="stdout", text="\nz"),
nbformat.new_output(output_type="stream", name="stdout", text="\rc\n"),
nbformat.new_output(output_type="stream", name="stdout", text="z\rz\rd")]
cells=[nbformat.new_code_cell(source="# None", execution_count=1,outputs=outputs)]
nb = nbformat.new_notebook(cells=cells)
res = self.build_resources()
nb, res = coalesce_streams(nb, res)
outputs = nb.cells[0].outputs
self.assertEqual(outputs[0].text, u'a\nb\nc\nd')

View file

@ -0,0 +1,47 @@
"""
Module with tests for the csshtmlheader preprocessor
"""
#-----------------------------------------------------------------------------
# Copyright (c) 2013, the IPython Development Team.
#
# Distributed under the terms of the Modified BSD License.
#
# The full license is in the file COPYING.txt, distributed with this software.
#-----------------------------------------------------------------------------
#-----------------------------------------------------------------------------
# Imports
#-----------------------------------------------------------------------------
from .base import PreprocessorTestsBase
from ..csshtmlheader import CSSHTMLHeaderPreprocessor
#-----------------------------------------------------------------------------
# Class
#-----------------------------------------------------------------------------
class TestCSSHTMLHeader(PreprocessorTestsBase):
"""Contains test functions for csshtmlheader.py"""
def build_preprocessor(self):
"""Make an instance of a preprocessor"""
preprocessor = CSSHTMLHeaderPreprocessor()
preprocessor.enabled = True
return preprocessor
def test_constructor(self):
"""Can a CSSHTMLHeaderPreprocessor be constructed?"""
self.build_preprocessor()
def test_output(self):
"""Test the output of the CSSHTMLHeaderPreprocessor"""
nb = self.build_notebook()
res = self.build_resources()
preprocessor = self.build_preprocessor()
nb, res = preprocessor(nb, res)
assert 'css' in res['inlining']

View file

@ -0,0 +1,109 @@
# coding=utf-8
"""
Module with tests for the execute preprocessor.
"""
# Copyright (c) IPython Development Team.
# Distributed under the terms of the Modified BSD License.
import os
import re
import pytest
import nbformat
from copy import deepcopy
from ..execute import ExecutePreprocessor, executenb
addr_pat = re.compile(r'0x[0-9a-f]{7,9}')
def normalize_output(output):
"""
Normalizes (most) outputs for comparison.
"""
output = dict(output)
if 'metadata' in output:
del output['metadata']
if 'text' in output:
output['text'] = re.sub(addr_pat, '<HEXADDR>', output['text'])
if 'text/plain' in output.get('data', {}):
output['data']['text/plain'] = \
re.sub(addr_pat, '<HEXADDR>', output['data']['text/plain'])
for key, value in output.get('data', {}).items():
if isinstance(value, str):
output['data'][key] = value
return output
def assert_notebooks_equal(expected, actual):
expected_cells = expected['cells']
actual_cells = actual['cells']
assert len(expected_cells) == len(actual_cells)
for expected_cell, actual_cell in zip(expected_cells, actual_cells):
expected_outputs = expected_cell.get('outputs', [])
actual_outputs = actual_cell.get('outputs', [])
normalized_expected_outputs = list(map(normalize_output, expected_outputs))
normalized_actual_outputs = list(map(normalize_output, actual_outputs))
assert normalized_expected_outputs == normalized_actual_outputs
expected_execution_count = expected_cell.get('execution_count', None)
actual_execution_count = actual_cell.get('execution_count', None)
assert expected_execution_count == actual_execution_count
def test_basic_execution():
preprocessor = ExecutePreprocessor()
fname = os.path.join(os.path.dirname(__file__), 'files', 'HelloWorld.ipynb')
with open(fname) as f:
input_nb = nbformat.read(f, 4)
output_nb, _ = preprocessor.preprocess(deepcopy(input_nb))
assert_notebooks_equal(input_nb, output_nb)
def test_mixed_markdown_execution():
preprocessor = ExecutePreprocessor()
fname = os.path.join(os.path.dirname(__file__), 'files', 'MixedMarkdown.ipynb')
with open(fname) as f:
input_nb = nbformat.read(f, 4)
output_nb, _ = preprocessor.preprocess(deepcopy(input_nb))
assert_notebooks_equal(input_nb, output_nb)
def test_executenb():
fname = os.path.join(os.path.dirname(__file__), 'files', 'HelloWorld.ipynb')
with open(fname) as f:
input_nb = nbformat.read(f, 4)
with pytest.warns(FutureWarning):
output_nb = executenb(deepcopy(input_nb))
assert_notebooks_equal(input_nb, output_nb)
def test_populate_language_info():
preprocessor = ExecutePreprocessor(kernel_name="python")
nb = nbformat.v4.new_notebook() # Certainly has no language_info.
preprocessor.preprocess(nb, resources={})
# Should mutate input
assert 'language_info' in nb.metadata # See that a basic attribute is filled in
def test_preprocess_cell():
class CellReplacer(ExecutePreprocessor):
def preprocess_cell(self, cell, resources, index, **kwargs):
cell.source = "print('Ignored')"
return super().preprocess_cell(cell, resources, index, **kwargs)
preprocessor = CellReplacer()
fname = os.path.join(os.path.dirname(__file__), 'files', 'HelloWorld.ipynb')
with open(fname) as f:
input_nb = nbformat.read(f, 4)
output_nb, _ = preprocessor.preprocess(deepcopy(input_nb))
expected_nb = deepcopy(input_nb)
for cell in expected_nb.cells:
cell.source = "print('Ignored')"
for output in cell.outputs:
output.text = 'Ignored\n'
assert_notebooks_equal(expected_nb, output_nb)

View file

@ -0,0 +1,86 @@
"""Tests for the extractoutput preprocessor"""
# Copyright (c) IPython Development Team.
# Distributed under the terms of the Modified BSD License.
import json
from .base import PreprocessorTestsBase
from ..extractoutput import ExtractOutputPreprocessor
class TestExtractOutput(PreprocessorTestsBase):
"""Contains test functions for extractoutput.py"""
def build_preprocessor(self):
"""Make an instance of a preprocessor"""
preprocessor = ExtractOutputPreprocessor()
preprocessor.extract_output_types = {'text/plain', 'image/png', 'application/pdf'}
preprocessor.enabled = True
return preprocessor
def test_constructor(self):
"""Can a ExtractOutputPreprocessor be constructed?"""
self.build_preprocessor()
def test_output(self):
"""Test the output of the ExtractOutputPreprocessor"""
nb = self.build_notebook()
res = self.build_resources()
preprocessor = self.build_preprocessor()
nb, res = preprocessor(nb, res)
# Check if text was extracted.
output = nb.cells[0].outputs[1]
self.assertIn('filenames', output.metadata)
self.assertIn('text/plain', output.metadata.filenames)
text_filename = output.metadata.filenames['text/plain']
# Check if png was extracted.
output = nb.cells[0].outputs[6]
self.assertIn('filenames', output.metadata)
self.assertIn('image/png', output.metadata.filenames)
png_filename = output.metadata.filenames['image/png']
# Check that pdf was extracted
output = nb.cells[0].outputs[7]
self.assertIn('filenames', output.metadata)
self.assertIn('application/pdf', output.metadata.filenames)
pdf_filename = output.metadata.filenames['application/pdf']
# Verify text output
self.assertIn(text_filename, res['outputs'])
self.assertEqual(res['outputs'][text_filename], b'b')
# Verify png output
self.assertIn(png_filename, res['outputs'])
self.assertEqual(res['outputs'][png_filename], b'g')
# Verify pdf output
self.assertIn(pdf_filename, res['outputs'])
self.assertEqual(res['outputs'][pdf_filename], b'h')
def test_json_extraction(self):
nb = self.build_notebook(with_json_outputs=True)
res = self.build_resources()
preprocessor = self.build_preprocessor()
preprocessor.extract_output_types = {'application/json'}
nb, res = preprocessor(nb, res)
reference = self.build_notebook(with_json_outputs=True).cells[0].outputs
# Verify cell untouched
self.assertEqual(
[out.get('data') for out in nb.cells[0].outputs],
[out.get('data') for out in reference]
)
outputs = sorted(res['outputs'].values())
reference_files = []
for out in reference:
try:
data = out['data']['application/json']
reference_files.append(json.dumps(data).encode())
except KeyError:
pass
# Verify equivalence of extracted outputs.
self.assertEqual(sorted(outputs), sorted(reference_files))

View file

@ -0,0 +1,50 @@
"""Tests for the HighlightMagics preprocessor"""
from .base import PreprocessorTestsBase
from ..highlightmagics import HighlightMagicsPreprocessor
class TestHighlightMagics(PreprocessorTestsBase):
"""Contains test functions for highlightmagics.py"""
def build_preprocessor(self):
"""Make an instance of a preprocessor"""
preprocessor = HighlightMagicsPreprocessor()
preprocessor.enabled = True
return preprocessor
def test_constructor(self):
"""Can a HighlightMagicsPreprocessor be constructed?"""
self.build_preprocessor()
def test_tagging(self):
"""Test the HighlightMagicsPreprocessor tagging"""
nb = self.build_notebook()
res = self.build_resources()
preprocessor = self.build_preprocessor()
nb.cells[0].source = """%%R -i x,y -o XYcoef
lm.fit <- lm(y~x)
par(mfrow=c(2,2))
print(summary(lm.fit))
plot(lm.fit)
XYcoef <- coef(lm.fit)"""
nb, res = preprocessor(nb, res)
assert('magics_language' in nb.cells[0]['metadata'])
self.assertEqual(nb.cells[0]['metadata']['magics_language'], 'r')
def test_no_false_positive(self):
"""Test that HighlightMagicsPreprocessor does not tag false positives"""
nb = self.build_notebook()
res = self.build_resources()
preprocessor = self.build_preprocessor()
nb.cells[0].source = """# this should not be detected
print(\"""
%%R -i x, y
\""")"""
nb, res = preprocessor(nb, res)
assert('magics_language' not in nb.cells[0]['metadata'])

View file

@ -0,0 +1,54 @@
"""Tests for the latex preprocessor"""
# Copyright (c) IPython Development Team.
# Distributed under the terms of the Modified BSD License.
from .base import PreprocessorTestsBase
from ..latex import LatexPreprocessor
class TestLatex(PreprocessorTestsBase):
"""Contains test functions for latex.py"""
def build_preprocessor(self):
"""Make an instance of a preprocessor"""
preprocessor = LatexPreprocessor()
preprocessor.enabled = True
return preprocessor
def test_constructor(self):
"""Can a LatexPreprocessor be constructed?"""
self.build_preprocessor()
def test_output(self):
"""Test the output of the LatexPreprocessor"""
nb = self.build_notebook()
res = self.build_resources()
preprocessor = self.build_preprocessor()
nb, res = preprocessor(nb, res)
# Make sure the code cell wasn't modified.
self.assertEqual(nb.cells[0].source, '$ e $')
# Verify that the markdown cell wasn't processed.
self.assertEqual(nb.cells[1].source, '$ e $')
def test_highlight(self):
"""Check that highlighting style can be changed"""
nb = self.build_notebook()
res = self.build_resources()
preprocessor = self.build_preprocessor()
# Set the style to a known builtin that's not the default
preprocessor.style='colorful'
nb, res = preprocessor(nb, res)
style_defs = res['latex']['pygments_definitions']
# Get the default
from pygments.formatters import LatexFormatter
default_defs = LatexFormatter(style='default').get_style_defs()
# Verify that the style was in fact changed
assert style_defs != default_defs

View file

@ -0,0 +1,71 @@
"""
Module with tests for the RegexRemovePreprocessor.
"""
# Copyright (c) IPython Development Team.
# Distributed under the terms of the Modified BSD License.
import re
from nbformat import v4 as nbformat, from_dict
from .base import PreprocessorTestsBase
from ..regexremove import RegexRemovePreprocessor
class TestRegexRemove(PreprocessorTestsBase):
"""Contains test functions for regexremove.py"""
def build_notebook(self):
notebook = super().build_notebook()
# Add a few empty cells
notebook.cells.extend([
nbformat.new_code_cell(''),
nbformat.new_markdown_cell(' '),
nbformat.new_raw_cell('\n'),
nbformat.new_raw_cell('\t'),
])
return notebook
def build_preprocessor(self):
"""Make an instance of a preprocessor"""
preprocessor = RegexRemovePreprocessor()
preprocessor.enabled = True
return preprocessor
def test_constructor(self):
"""Can a RegexRemovePreprocessor be constructed?"""
self.build_preprocessor()
def test_output(self):
"""Test the output of the RegexRemovePreprocessor"""
pattern_lookup = {
'disallow_whitespace': [r'\s*\Z'],
'disallow_tab_newline': [r'\t\Z', r'\n\Z']
}
expected_cell_count = {
'default': 6, # nothing is removed
'disallow_whitespace': 2, # all "empty" cells are removed
'disallow_tab_newline': 4, # cells with tab and newline are removed
'none': 6,
}
for method in ['default', 'disallow_whitespace', 'disallow_tab_newline', 'none']:
nb = self.build_notebook()
res = self.build_resources()
# Build the preprocessor and extend the list of patterns or use an empty list
preprocessor = self.build_preprocessor()
if method == 'none':
preprocessor.patterns = []
else:
preprocessor.patterns.extend(pattern_lookup.get(method, []))
nb, res = preprocessor(nb, res)
self.assertEqual(len(nb.cells), expected_cell_count[method])
# Make sure none of the cells match the pattern
patterns = list(map(re.compile, preprocessor.patterns))
for cell in nb.cells:
for pattern in patterns:
self.assertFalse(pattern.match(cell.source))

View file

@ -0,0 +1,208 @@
"""Tests for the HTMLSanitize preprocessor"""
from .base import PreprocessorTestsBase
from ..sanitize import SanitizeHTML
from nbformat import v4 as nbformat
class TestSanitizer(PreprocessorTestsBase):
"""Contains test functions for sanitize.py"""
maxDiff = None
def build_preprocessor(self):
"""Make an instance of a preprocessor"""
preprocessor = SanitizeHTML()
preprocessor.enabled = True
return preprocessor
def preprocess_source(self, cell_type, source, preprocessor):
nb = self.build_notebook()
res = self.build_resources()
nb.cells[0].cell_type = cell_type
nb.cells[0].source = source
nb, res = preprocessor(nb, res)
return nb.cells[0].source
def test_constructor(self):
"""Can a SanitizeHTML be constructed?"""
self.build_preprocessor()
def test_svg_handling(self):
"""
Test to make sure that svgs are handled 'properly'
We only allow <img> tags (via markdown syntax) and not all the other ways
to embed svg: <object>, <embed>, <iframe> nor inline <svg>
"""
preprocessor = self.build_preprocessor()
preprocessor.strip = True
self.assertEqual(
self.preprocess_source(
'markdown',
"""
![some image](http://example.com/something.svg)
<object data="something.svg" type="image/svg+xml"></object>
<embed data="something.svg" type="image/svg+xml" />
<iframe src="http://example.com/something.svg"></iframe>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 68 65">
<path fill="#1A374D" d="M42 27v-20c0-3.7-3.3-7-7-7s-7 3.3-7 7v21l12 15-7 15.7c14.5 13.9 35 2.8 35-13.7 0-13.3-13.4-21.8-26-18zm6 25c-3.9 0-7-3.1-7-7s3.1-7 7-7 7 3.1 7 7-3.1 7-7 7z"/>
<path d="M14 27v-20c0-3.7-3.3-7-7-7s-7 3.3-7 7v41c0 8.2 9.2 17 20 17s20-9.2 20-20c0-13.3-13.4-21.8-26-18zm6 25c-3.9 0-7-3.1-7-7s3.1-7 7-7 7 3.1 7 7-3.1 7-7 7z"/>
</svg>
""",
preprocessor
).strip(),
"""
![some image](http://example.com/something.svg)
""".strip(),
)
def test_tag_whitelist_stripping(self):
"""Test tag whitelisting + stripping out offending tags"""
preprocessor = self.build_preprocessor()
preprocessor.strip = True
self.assertEqual(
self.preprocess_source(
'markdown',
'_A_ <em>few</em> <script>tags</script>',
preprocessor
),
'_A_ <em>few</em> tags'
)
def test_comment_stripping(self):
"""Test HTML comment stripping"""
preprocessor = self.build_preprocessor()
self.assertEqual(
self.preprocess_source(
'markdown',
'_A_ <em>few</em> <!-- tags -->',
preprocessor
),
'_A_ <em>few</em> '
)
preprocessor.strip_comments = False
self.assertEqual(
self.preprocess_source(
'markdown',
'_A_ <em>few</em> <!-- tags -->',
preprocessor
),
'_A_ <em>few</em> <!-- tags -->'
)
def test_attributes_whitelist(self):
"""Test style"""
preprocessor = self.build_preprocessor()
preprocessor.attributes['a'] = ['href', 'title']
self.assertEqual(
self.preprocess_source(
'markdown',
'<a href="link" rel="nofollow">Hi</a>',
preprocessor
),
'<a href="link">Hi</a>'
)
def test_style_whitelist(self):
"""Test style"""
preprocessor = self.build_preprocessor()
if '*' in preprocessor.attributes:
preprocessor.attributes['*'].append('style')
else:
preprocessor.attributes['*'] = ['style']
preprocessor.styles = [
'color',
]
self.assertEqual(
self.preprocess_source(
'markdown',
'_A_ <em style="color: blue; background-color: pink">'
'few</em> <script>tags</script>',
preprocessor
),
'_A_ <em style="color: blue;">few</em> '
'&lt;script&gt;tags&lt;/script&gt;'
)
def test_tag_passthrough(self):
"""Test passing through raw output"""
preprocessor = self.build_preprocessor()
self.assertEqual(
self.preprocess_source(
'raw',
'_A_ <em>few</em> <script>tags</script>',
preprocessor
),
'_A_ <em>few</em> &lt;script&gt;tags&lt;/script&gt;'
)
def test_output_sanitizing(self):
"""Test that outputs are also sanitized properly"""
preprocessor = self.build_preprocessor()
nb = self.build_notebook()
outputs = [
nbformat.new_output("display_data", data={
'text/plain': 'b',
'text/html': '<script>more evil</script>',
'text/css': '<style> * {display:none}</style>'
}),
nbformat.new_output('stream', name='stdout', text="wat"),
nbformat.new_output('stream', name='stdout', text="<script>Evil tag</script>")
]
nb.cells[0].outputs = outputs
res = self.build_resources()
nb, res = preprocessor(nb, res)
expected_output = [
{
'data': {
'text/html': '&lt;script&gt;more evil&lt;/script&gt;',
'text/plain': 'b'
},
'metadata': {},
'output_type': 'display_data',
},
{
'name': 'stdout',
'output_type': 'stream',
'text': 'wat'
},
{
'name': 'stdout',
'output_type':
'stream', 'text': '<script>Evil tag</script>'
}
]
self.assertEqual(nb.cells[0].outputs, expected_output)
def test_tag_whitelist(self):
"""Test tag whitelisting"""
preprocessor = self.build_preprocessor()
self.assertEqual(
self.preprocess_source(
'markdown',
'_A_ <em>few</em> <script>tags</script>',
preprocessor
),
'_A_ <em>few</em> &lt;script&gt;tags&lt;/script&gt;'
)

View file

@ -0,0 +1,94 @@
"""Tests for the svg2pdf preprocessor"""
# Copyright (c) IPython Development Team.
# Distributed under the terms of the Modified BSD License.
from nbformat import v4 as nbformat
from unittest.mock import patch, Mock
from .base import PreprocessorTestsBase
from ..svg2pdf import SVG2PDFPreprocessor
from ...tests.utils import onlyif_cmds_exist
class Testsvg2pdf(PreprocessorTestsBase):
"""Contains test functions for svg2pdf.py"""
simple_svg = """<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
version="1.0"
x="0.00000000"
y="0.00000000"
width="500.00000"
height="500.00000"
id="svg2">
<defs
id="defs4" />
<g
id="layer1">
<rect
width="300.00000"
height="300.00000"
x="100.00000"
y="100.00000"
style="opacity:1.0000000;fill:none;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#000000;stroke-width:8.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.00000000;stroke-opacity:1.0000000"
id="rect5719" />
</g>
</svg>"""
def build_notebook(self):
"""Build a reveal slides notebook in memory for use with tests.
Overrides base in PreprocessorTestsBase"""
outputs = [nbformat.new_output(output_type='display_data',
data={'image/svg+xml':self.simple_svg})
]
cells=[nbformat.new_code_cell(source="", execution_count=1, outputs=outputs)]
return nbformat.new_notebook(cells=cells)
def build_preprocessor(self, **kwargs):
"""Make an instance of a preprocessor"""
preprocessor = SVG2PDFPreprocessor(**kwargs)
preprocessor.enabled = True
return preprocessor
def test_constructor(self):
"""Can a SVG2PDFPreprocessor be constructed?"""
self.build_preprocessor()
@onlyif_cmds_exist('inkscape')
def test_output(self):
"""Test the output of the SVG2PDFPreprocessor"""
nb = self.build_notebook()
res = self.build_resources()
preprocessor = self.build_preprocessor()
nb, res = preprocessor(nb, res)
self.assertIn('application/pdf', nb.cells[0].outputs[0].data)
@patch('subprocess.Popen')
def test_inkscape_version_default(self, mock_popen):
mock_popen().communicate.return_value = (b'Inkscape 0.92.3 (2405546, 2018-03-11)', b'')
mock_popen().returncode = 0
preprocessor = self.build_preprocessor()
assert preprocessor.inkscape_version == '0.92.3'
def test_inkscape_pre_v1_command(self):
preprocessor = self.build_preprocessor(inkscape_version='0.92.3')
assert preprocessor.command == '0.92.3'
def test_inkscape_pre_v1_command(self):
preprocessor = self.build_preprocessor(inkscape='fake-inkscape', inkscape_version='0.92.3')
assert preprocessor.command == 'fake-inkscape --without-gui --export-pdf="{to_filename}" "{from_filename}"'
def test_inkscape_v1_command(self):
preprocessor = self.build_preprocessor(inkscape='fake-inkscape', inkscape_version='1.0beta2')
assert preprocessor.command == 'fake-inkscape --export-filename="{to_filename}" "{from_filename}"'

View file

@ -0,0 +1,83 @@
"""
Module with tests for the TagRemovePreprocessor.
"""
# Copyright (c) IPython Development Team.
# Distributed under the terms of the Modified BSD License.
from nbformat import v4 as nbformat
from .base import PreprocessorTestsBase
from ..tagremove import TagRemovePreprocessor
class TestTagRemove(PreprocessorTestsBase):
"""Contains test functions for tagremove.py"""
def build_notebook(self):
"""
Build a notebook to have metadata tags for cells, output_areas, and
individual outputs.
"""
notebook = super().build_notebook()
# Add a few empty cells
notebook.cells[0].outputs.extend(
[nbformat.new_output("display_data",
data={'text/plain': 'i'},
metadata={'tags': ["hide_one_output"]}
),
])
outputs_to_be_removed = [
nbformat.new_output("display_data",
data={'text/plain': "remove_my_output"}),
]
outputs_to_be_kept = [
nbformat.new_output("stream",
name="stdout",
text="remove_my_output",
),
]
notebook.cells.extend(
[nbformat.new_code_cell(source="display('remove_my_output')",
execution_count=2,
outputs=outputs_to_be_removed,
metadata={"tags": ["hide_all_outputs"]}),
nbformat.new_code_cell(source="print('remove this cell')",
execution_count=3,
outputs=outputs_to_be_kept,
metadata={"tags": ["hide_this_cell"]}),
]
)
return notebook
def build_preprocessor(self):
"""Make an instance of a preprocessor"""
preprocessor = TagRemovePreprocessor()
preprocessor.enabled = True
return preprocessor
def test_constructor(self):
"""Can a TagRemovePreprocessor be constructed?"""
self.build_preprocessor()
def test_output(self):
"""Test the output of the TagRemovePreprocessor"""
nb = self.build_notebook()
res = self.build_resources()
preprocessor = self.build_preprocessor()
preprocessor.remove_cell_tags.add("hide_this_cell")
preprocessor.remove_all_outputs_tags.add('hide_all_outputs')
preprocessor.remove_single_output_tags.add('hide_one_output')
nb, res = preprocessor(nb, res)
# checks that we can remove entire cells
self.assertEqual(len(nb.cells), 3)
# checks that we can remove output areas
self.assertEqual(len(nb.cells[-1].outputs), 0)
# checks that we can remove individual outputs
self.assertEqual(len(nb.cells[0].outputs), 8)