From 021e7a60a090b19670d415cf18653fa42f7d4544 Mon Sep 17 00:00:00 2001 From: Marc Wouts Date: Mon, 8 Jul 2019 23:19:23 +0200 Subject: [PATCH 1/5] Update HISTORY.rst --- HISTORY.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/HISTORY.rst b/HISTORY.rst index bf4e9283a..e122392e3 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -11,6 +11,7 @@ Release History - New ``--execute`` option in Jupytext CLI (#231) - The ``--set-formats`` option in Jupytext CLI also triggers ``--sync``, allowing shorter commands. - ``jupytext``'s ``read`` and ``write`` functions can be used as drop-in replacements for ``nbformat``'s ones (#262). +- ``jupytext --sync`` will now skip unpaired notebooks (#281). - The JupyterLab extension was updated. It now works on on text files (#213) and has a new option to include (or not) the metadata in the text representation of the notebook. - Jupytext's contents manager class is derived dynamically from the default CM class for compatibility with From a1372ac02d60747df9fe7986a6bd7a71d1f6ddb4 Mon Sep 17 00:00:00 2001 From: Marc Wouts Date: Tue, 9 Jul 2019 00:24:39 +0200 Subject: [PATCH 2/5] Implement compare using difflib #279 --- jupytext/compare.py | 19 +++++++++- tests/test_compare.py | 83 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+), 1 deletion(-) diff --git a/jupytext/compare.py b/jupytext/compare.py index d89574962..2ac1c925c 100644 --- a/jupytext/compare.py +++ b/jupytext/compare.py @@ -1,8 +1,9 @@ """Compare two Jupyter notebooks""" import re +import json +import difflib from copy import copy -from testfixtures import compare from .cell_metadata import _IGNORE_CELL_METADATA from .header import _DEFAULT_NOTEBOOK_METADATA from .metadata_filter import filter_metadata @@ -13,6 +14,22 @@ _BLANK_LINE = re.compile(r'^\s*$') +def _multilines(obj): + try: + return obj.splitlines() + except AttributeError: + return json.dumps(obj, indent=True, sort_keys=True).splitlines() + + +def compare(actual, expected): + """Compare two strings, lists or dict-like objects""" + if actual != expected: + raise AssertionError('\n' + '\n'.join(difflib.unified_diff( + _multilines(actual), + _multilines(expected), + 'first', 'second', lineterm=''))) + + def filtered_cell(cell, preserve_outputs, cell_metadata_filter): """Cell type, metadata and source from given cell""" metadata = copy(cell.metadata) diff --git a/tests/test_compare.py b/tests/test_compare.py index d4f37664c..af600ac52 100644 --- a/tests/test_compare.py +++ b/tests/test_compare.py @@ -1,8 +1,91 @@ import pytest from nbformat.v4.nbbase import new_notebook, new_markdown_cell, new_code_cell, new_raw_cell +from jupytext.compare import compare from jupytext.compare import compare_notebooks, NotebookDifference, test_round_trip_conversion as round_trip_conversion +def notebook_metadata(): + return { + "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.7.3" + }, + "toc": { + "base_numbering": 1, + "nav_menu": {}, + "number_sections": True, + "sideBar": True, + "skip_h1_title": False, + "title_cell": "Table of Contents", + "title_sidebar": "Contents", + "toc_cell": False, + "toc_position": {}, + "toc_section_display": True, + "toc_window_display": False + } + } + + +@pytest.fixture() +def notebook_1(): + return new_notebook( + metadata=notebook_metadata(), + cells=[new_markdown_cell('First markdown cell'), + new_code_cell('1 + 1'), + new_markdown_cell('Second markdown cell')]) + + +@pytest.fixture() +def notebook_2(): + metadata = notebook_metadata() + metadata['language_info']['version'] = '3.6.8' + return new_notebook( + metadata=metadata, + cells=[new_markdown_cell('First markdown cell'), + new_code_cell('1 + 1'), + new_markdown_cell('Modified markdown cell')]) + + +def test_compare_on_notebooks(notebook_1, notebook_2): + with pytest.raises(AssertionError) as err: + compare(notebook_1, notebook_2) + + assert str(err.value) == """ +--- first ++++ second +@@ -15,7 +15,7 @@ + { + "cell_type": "markdown", + "metadata": {}, +- "source": "Second markdown cell" ++ "source": "Modified markdown cell" + } + ], + "metadata": { +@@ -34,7 +34,7 @@ + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", +- "version": "3.7.3" ++ "version": "3.6.8" + }, + "toc": { + "base_numbering": 1,""" + + def test_raise_on_different_metadata(): ref = new_notebook(metadata={'kernelspec': {'language': 'python', 'name': 'python', 'display_name': 'Python'}}, cells=[new_markdown_cell('Cell one')]) From 696d0a9778d668683b5a58e86f1dfbca475fb4fc Mon Sep 17 00:00:00 2001 From: Marc Wouts Date: Tue, 9 Jul 2019 00:25:24 +0200 Subject: [PATCH 3/5] Remove dependency on testfixtures #279 --- requirements.txt | 1 - setup.py | 2 +- tests/test_active_cells.py | 2 +- tests/test_black.py | 2 +- tests/test_cell_metadata.py | 2 +- tests/test_cli.py | 2 +- tests/test_contentsmanager.py | 47 +++++++++++++++++++- tests/test_escape_magics.py | 2 +- tests/test_formats.py | 2 +- tests/test_header.py | 2 +- tests/test_mirror.py | 2 +- tests/test_paired_paths.py | 14 +++--- tests/test_pep8.py | 2 +- tests/test_preserve_empty_cells.py | 2 +- tests/test_read_all_py.py | 2 +- tests/test_read_folding_markers.py | 2 +- tests/test_read_simple_R.py | 2 +- tests/test_read_simple_bare.py | 2 +- tests/test_read_simple_clojure.py | 2 +- tests/test_read_simple_hydrogen.py | 2 +- tests/test_read_simple_ipynb.py | 2 +- tests/test_read_simple_julia.py | 2 +- tests/test_read_simple_markdown.py | 2 +- tests/test_read_simple_pandoc.py | 2 +- tests/test_read_simple_percent.py | 2 +- tests/test_read_simple_python.py | 2 +- tests/test_read_simple_rmd.py | 2 +- tests/test_read_simple_scheme.py | 2 +- tests/test_read_simple_sphinx.py | 2 +- tests/test_rmd_to_ipynb.py | 2 +- tests/test_write_does_not_modify_notebook.py | 2 +- 31 files changed, 81 insertions(+), 37 deletions(-) diff --git a/requirements.txt b/requirements.txt index 800aacc61..435242de5 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,3 @@ nbformat>=4.0.0 pyyaml mock -testfixtures diff --git a/setup.py b/setup.py index b01777a50..9fce69534 100644 --- a/setup.py +++ b/setup.py @@ -35,7 +35,7 @@ ('share/jupyter/lab/extensions', ['packages/labextension/jupyterlab-jupytext-1.0.0.tgz'])], entry_points={'console_scripts': ['jupytext = jupytext.cli:jupytext_cli']}, tests_require=['pytest'], - install_requires=['nbformat>=4.0.0', 'mock', 'pyyaml', 'testfixtures'], + install_requires=['nbformat>=4.0.0', 'mock', 'pyyaml'], license='MIT', classifiers=['Development Status :: 5 - Production/Stable', 'License :: OSI Approved :: MIT License', diff --git a/tests/test_active_cells.py b/tests/test_active_cells.py index bcd59eff1..d2c45bdd5 100644 --- a/tests/test_active_cells.py +++ b/tests/test_active_cells.py @@ -1,6 +1,6 @@ import mock import pytest -from testfixtures import compare +from jupytext.compare import compare import jupytext from .utils import skip_if_dict_is_not_ordered diff --git a/tests/test_black.py b/tests/test_black.py index 558e9f048..e365b72cb 100644 --- a/tests/test_black.py +++ b/tests/test_black.py @@ -1,7 +1,7 @@ import os import pytest from shutil import copyfile -from testfixtures import compare +from jupytext.compare import compare from nbformat.v4.nbbase import new_notebook, new_code_cell from .utils import list_notebooks, requires_black, requires_flake8, requires_autopep8 diff --git a/tests/test_cell_metadata.py b/tests/test_cell_metadata.py index 55dcc96df..fb1ad142f 100644 --- a/tests/test_cell_metadata.py +++ b/tests/test_cell_metadata.py @@ -1,5 +1,5 @@ import pytest -from testfixtures import compare +from jupytext.compare import compare from jupytext.cell_metadata import rmd_options_to_metadata, metadata_to_rmd_options, parse_rmd_options from jupytext.cell_metadata import _IGNORE_CELL_METADATA, RMarkdownOptionParsingError, try_eval_metadata from jupytext.cell_metadata import json_options_to_metadata, metadata_to_json_options diff --git a/tests/test_cli.py b/tests/test_cli.py index b38d5dbd5..68e9079d6 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -7,7 +7,7 @@ import nbformat import itertools from shutil import copyfile -from testfixtures import compare +from jupytext.compare import compare from argparse import ArgumentTypeError from nbformat.v4.nbbase import new_notebook, new_markdown_cell, new_code_cell from jupyter_client.kernelspec import find_kernel_specs, get_kernel_spec diff --git a/tests/test_contentsmanager.py b/tests/test_contentsmanager.py index 43f0d3739..cbad9b0e4 100644 --- a/tests/test_contentsmanager.py +++ b/tests/test_contentsmanager.py @@ -8,7 +8,7 @@ import shutil from nbformat.v4.nbbase import new_notebook, new_markdown_cell, new_code_cell from tornado.web import HTTPError -from testfixtures import compare +from jupytext.compare import compare import jupytext from jupytext.jupytext import writes, write, read from jupytext.compare import compare_notebooks @@ -51,6 +51,51 @@ def test_rename_inconsistent_path(tmpdir): assert os.path.isfile(org_file) +def test_pair_unpair_notebook(tmpdir): + tmp_ipynb = 'notebook.ipynb' + tmp_md = 'notebook.md' + + nb = new_notebook( + metadata={'kernelspec': {'display_name': 'Python3', 'language': 'python', 'name': 'python3'}}, + cells=[new_code_cell('1 + 1', outputs=[ + { + "data": { + "text/plain": [ + "2" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ])]) + + cm = jupytext.TextFileContentsManager() + cm.root_dir = str(tmpdir) + + # save notebook + cm.save(model=dict(type='notebook', content=nb), path=tmp_ipynb) + assert not os.path.isfile(str(tmpdir.join(tmp_md))) + + # pair notebook + nb['metadata']['jupytext'] = {'formats': 'ipynb,md'} + cm.save(model=dict(type='notebook', content=nb), path=tmp_ipynb) + assert os.path.isfile(str(tmpdir.join(tmp_md))) + + # reload and get outputs + nb2 = cm.get(tmp_md)['content'] + compare_notebooks(nb2, nb) + + # unpair and save as md + del nb['metadata']['jupytext'] + cm.save(model=dict(type='notebook', content=nb), path=tmp_md) + nb2 = cm.get(tmp_md)['content'] + + # we get no outputs here + compare_notebooks(nb2, nb, compare_outputs=False) + assert len(nb2.cells[0]['outputs']) == 0 + + @skip_if_dict_is_not_ordered @pytest.mark.parametrize('nb_file', list_notebooks('ipynb', skip='66')) def test_load_save_rename(nb_file, tmpdir): diff --git a/tests/test_escape_magics.py b/tests/test_escape_magics.py index fd09c21af..df0f3f029 100644 --- a/tests/test_escape_magics.py +++ b/tests/test_escape_magics.py @@ -1,7 +1,7 @@ import pytest import mock from nbformat.v4.nbbase import new_code_cell, new_notebook -from testfixtures import compare +from jupytext.compare import compare from jupytext.magics import comment_magic, uncomment_magic, unesc, is_magic from jupytext.compare import compare_notebooks import jupytext diff --git a/tests/test_formats.py b/tests/test_formats.py index 5a267717a..afde9ff7c 100644 --- a/tests/test_formats.py +++ b/tests/test_formats.py @@ -1,5 +1,5 @@ import pytest -from testfixtures import compare +from jupytext.compare import compare from nbformat.v4.nbbase import new_notebook import jupytext from jupytext.formats import guess_format, divine_format, read_format_from_metadata, rearrange_jupytext_metadata diff --git a/tests/test_header.py b/tests/test_header.py index f8a986847..486432f7a 100644 --- a/tests/test_header.py +++ b/tests/test_header.py @@ -1,6 +1,6 @@ from nbformat.v4.nbbase import new_notebook, new_raw_cell, new_markdown_cell import mock -from testfixtures import compare +from jupytext.compare import compare import jupytext from jupytext.header import uncomment_line, header_to_metadata_and_cell, metadata_and_cell_to_header from jupytext.formats import get_format_implementation diff --git a/tests/test_mirror.py b/tests/test_mirror.py index baeeb3dcd..72337e667 100644 --- a/tests/test_mirror.py +++ b/tests/test_mirror.py @@ -8,7 +8,7 @@ import mock import pytest from nbformat.v4.nbbase import new_notebook -from testfixtures import compare +from jupytext.compare import compare import jupytext from jupytext.compare import compare_notebooks, combine_inputs_with_outputs diff --git a/tests/test_paired_paths.py b/tests/test_paired_paths.py index 685118849..069dda42e 100644 --- a/tests/test_paired_paths.py +++ b/tests/test_paired_paths.py @@ -1,5 +1,5 @@ import pytest -from testfixtures import compare +from jupytext.compare import compare from jupytext.contentsmanager import TextFileContentsManager from jupytext.paired_paths import InconsistentPath, paired_paths, base_path from jupytext.formats import long_form_one_format, long_form_multiple_formats, short_form_multiple_formats @@ -8,8 +8,8 @@ def test_simple_pair(): formats = long_form_multiple_formats('ipynb,py') expected_paths = ['notebook.ipynb', 'notebook.py'] - compare(zip(expected_paths, formats), paired_paths('notebook.ipynb', 'ipynb', formats)) - compare(zip(expected_paths, formats), paired_paths('notebook.py', 'py', formats)) + compare(list(zip(expected_paths, formats)), paired_paths('notebook.ipynb', 'ipynb', formats)) + compare(list(zip(expected_paths, formats)), paired_paths('notebook.py', 'py', formats)) def test_base_path(): @@ -23,7 +23,7 @@ def test_many_and_suffix(): formats = long_form_multiple_formats('ipynb,.pct.py,_lgt.py') expected_paths = ['notebook.ipynb', 'notebook.pct.py', 'notebook_lgt.py'] for fmt, path in zip(formats, expected_paths): - compare(zip(expected_paths, formats), paired_paths(path, fmt, formats)) + compare(list(zip(expected_paths, formats)), paired_paths(path, fmt, formats)) with pytest.raises(InconsistentPath): paired_paths('wrong_suffix.py', 'py', formats) @@ -41,12 +41,12 @@ def test_prefix_and_suffix(): 'parent/script_folder/NOTEBOOK_NAME_in_percent_format.py', 'parent/script_folder/NOTEBOOK_NAME_in_light_format.py'] for fmt, path in zip(formats, expected_paths): - compare(zip(expected_paths, formats), paired_paths(path, fmt, formats)) + compare(list(zip(expected_paths, formats)), paired_paths(path, fmt, formats)) # without the parent folder expected_paths = [path[7:] for path in expected_paths] for fmt, path in zip(formats, expected_paths): - compare(zip(expected_paths, formats), paired_paths(path, fmt, formats)) + compare(list(zip(expected_paths, formats)), paired_paths(path, fmt, formats)) # Not the expected parent folder with pytest.raises(InconsistentPath): @@ -69,7 +69,7 @@ def test_prefix_on_root_174(): expected_paths = ['/Untitled.ipynb', '/python/Untitled.py'] for fmt, path in zip(formats, expected_paths): - compare(zip(expected_paths, formats), paired_paths(path, fmt, formats)) + compare(list(zip(expected_paths, formats)), paired_paths(path, fmt, formats)) def test_duplicated_paths(): diff --git a/tests/test_pep8.py b/tests/test_pep8.py index 5f08ea967..6e66ff316 100644 --- a/tests/test_pep8.py +++ b/tests/test_pep8.py @@ -1,5 +1,5 @@ import pytest -from testfixtures import compare +from jupytext.compare import compare from jupytext import read, reads, writes from jupytext.pep8 import next_instruction_is_function_or_class, cell_ends_with_function_or_class from jupytext.pep8 import cell_ends_with_code, cell_has_code, pep8_lines_between_cells diff --git a/tests/test_preserve_empty_cells.py b/tests/test_preserve_empty_cells.py index c3e78bd1d..07594e8f6 100644 --- a/tests/test_preserve_empty_cells.py +++ b/tests/test_preserve_empty_cells.py @@ -1,5 +1,5 @@ import pytest -from testfixtures import compare +from jupytext.compare import compare from nbformat.v4.nbbase import new_notebook, new_code_cell, new_markdown_cell import jupytext from jupytext.compare import compare_notebooks diff --git a/tests/test_read_all_py.py b/tests/test_read_all_py.py index decced2a0..f229261a0 100644 --- a/tests/test_read_all_py.py +++ b/tests/test_read_all_py.py @@ -1,5 +1,5 @@ import pytest -from testfixtures import compare +from jupytext.compare import compare import jupytext from .utils import list_notebooks diff --git a/tests/test_read_folding_markers.py b/tests/test_read_folding_markers.py index e687040c5..e236063f7 100644 --- a/tests/test_read_folding_markers.py +++ b/tests/test_read_folding_markers.py @@ -1,4 +1,4 @@ -from testfixtures import compare +from jupytext.compare import compare import jupytext diff --git a/tests/test_read_simple_R.py b/tests/test_read_simple_R.py index 74e03447e..be184f313 100644 --- a/tests/test_read_simple_R.py +++ b/tests/test_read_simple_R.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- import pytest -from testfixtures import compare +from jupytext.compare import compare import jupytext diff --git a/tests/test_read_simple_bare.py b/tests/test_read_simple_bare.py index 56ea993fb..4833228c1 100644 --- a/tests/test_read_simple_bare.py +++ b/tests/test_read_simple_bare.py @@ -1,5 +1,5 @@ from nbformat.v4.nbbase import new_notebook, new_code_cell, new_markdown_cell -from testfixtures import compare +from jupytext.compare import compare from jupytext import reads, writes from jupytext.combine import combine_inputs_with_outputs diff --git a/tests/test_read_simple_clojure.py b/tests/test_read_simple_clojure.py index 84ee10f6f..eed7d2b96 100644 --- a/tests/test_read_simple_clojure.py +++ b/tests/test_read_simple_clojure.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -from testfixtures import compare +from jupytext.compare import compare import jupytext diff --git a/tests/test_read_simple_hydrogen.py b/tests/test_read_simple_hydrogen.py index 91b5a6bcd..8d9f874da 100644 --- a/tests/test_read_simple_hydrogen.py +++ b/tests/test_read_simple_hydrogen.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -from testfixtures import compare +from jupytext.compare import compare import jupytext diff --git a/tests/test_read_simple_ipynb.py b/tests/test_read_simple_ipynb.py index 5b2ed257f..0250af851 100644 --- a/tests/test_read_simple_ipynb.py +++ b/tests/test_read_simple_ipynb.py @@ -1,6 +1,6 @@ import nbformat from nbformat.v4.nbbase import new_notebook -from testfixtures import compare +from jupytext.compare import compare import jupytext diff --git a/tests/test_read_simple_julia.py b/tests/test_read_simple_julia.py index 811dc6945..7ef3e7e91 100644 --- a/tests/test_read_simple_julia.py +++ b/tests/test_read_simple_julia.py @@ -1,4 +1,4 @@ -from testfixtures import compare +from jupytext.compare import compare import jupytext diff --git a/tests/test_read_simple_markdown.py b/tests/test_read_simple_markdown.py index cd8f27001..eee67fc63 100644 --- a/tests/test_read_simple_markdown.py +++ b/tests/test_read_simple_markdown.py @@ -1,6 +1,6 @@ import mock from nbformat.v4.nbbase import new_code_cell, new_raw_cell, new_markdown_cell -from testfixtures import compare +from jupytext.compare import compare import jupytext from jupytext.combine import combine_inputs_with_outputs diff --git a/tests/test_read_simple_pandoc.py b/tests/test_read_simple_pandoc.py index 31bf803aa..93c39acbf 100644 --- a/tests/test_read_simple_pandoc.py +++ b/tests/test_read_simple_pandoc.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -from testfixtures import compare +from jupytext.compare import compare from nbformat.v4.nbbase import new_notebook, new_markdown_cell from jupytext.compare import compare_notebooks import jupytext diff --git a/tests/test_read_simple_percent.py b/tests/test_read_simple_percent.py index 50be774ed..29ebfa3b8 100644 --- a/tests/test_read_simple_percent.py +++ b/tests/test_read_simple_percent.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- from nbformat.v4.nbbase import new_notebook, new_code_cell -from testfixtures import compare +from jupytext.compare import compare import jupytext diff --git a/tests/test_read_simple_python.py b/tests/test_read_simple_python.py index 17ceb1400..705199791 100644 --- a/tests/test_read_simple_python.py +++ b/tests/test_read_simple_python.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- from nbformat.v4.nbbase import new_markdown_cell, new_code_cell, new_notebook -from testfixtures import compare +from jupytext.compare import compare import jupytext from jupytext.compare import compare_notebooks diff --git a/tests/test_read_simple_rmd.py b/tests/test_read_simple_rmd.py index 7dba89065..ed7c50de4 100644 --- a/tests/test_read_simple_rmd.py +++ b/tests/test_read_simple_rmd.py @@ -1,5 +1,5 @@ import re -from testfixtures import compare +from jupytext.compare import compare import jupytext from .utils import skip_if_dict_is_not_ordered diff --git a/tests/test_read_simple_scheme.py b/tests/test_read_simple_scheme.py index ef532a530..5579afc52 100644 --- a/tests/test_read_simple_scheme.py +++ b/tests/test_read_simple_scheme.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -from testfixtures import compare +from jupytext.compare import compare import jupytext diff --git a/tests/test_read_simple_sphinx.py b/tests/test_read_simple_sphinx.py index 3fb01c1fd..594464d84 100644 --- a/tests/test_read_simple_sphinx.py +++ b/tests/test_read_simple_sphinx.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -from testfixtures import compare +from jupytext.compare import compare import jupytext diff --git a/tests/test_rmd_to_ipynb.py b/tests/test_rmd_to_ipynb.py index c38a9da2f..94c1cf6b9 100644 --- a/tests/test_rmd_to_ipynb.py +++ b/tests/test_rmd_to_ipynb.py @@ -1,6 +1,6 @@ import mock import pytest -from testfixtures import compare +from jupytext.compare import compare import jupytext from .utils import list_notebooks from .utils import skip_if_dict_is_not_ordered diff --git a/tests/test_write_does_not_modify_notebook.py b/tests/test_write_does_not_modify_notebook.py index 6cafefdc3..a4fb2389b 100644 --- a/tests/test_write_does_not_modify_notebook.py +++ b/tests/test_write_does_not_modify_notebook.py @@ -1,6 +1,6 @@ import pytest from copy import deepcopy -from testfixtures import compare +from jupytext.compare import compare from itertools import product from jupytext import read, write, writes from jupytext.formats import long_form_one_format From 4b1aac2b1d8892f7c0f96a412882e0c28e6c9fca Mon Sep 17 00:00:00 2001 From: Marc Wouts Date: Tue, 9 Jul 2019 00:26:40 +0200 Subject: [PATCH 4/5] Update HISTORY.rst --- HISTORY.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/HISTORY.rst b/HISTORY.rst index e122392e3..c300d4fdd 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -16,6 +16,7 @@ Release History (or not) the metadata in the text representation of the notebook. - Jupytext's contents manager class is derived dynamically from the default CM class for compatibility with ``jupyter_server`` (#270) +- Removed dependency on ``testfixtures`` (#279) **BugFixes** From 04c1cb84e97c327fa343343b5e30db32429990e1 Mon Sep 17 00:00:00 2001 From: Marc Wouts Date: Tue, 9 Jul 2019 07:39:10 +0200 Subject: [PATCH 5/5] Fix test on Python 2.7 #279 --- jupytext/compare.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/jupytext/compare.py b/jupytext/compare.py index 2ac1c925c..260f31e47 100644 --- a/jupytext/compare.py +++ b/jupytext/compare.py @@ -18,7 +18,9 @@ def _multilines(obj): try: return obj.splitlines() except AttributeError: - return json.dumps(obj, indent=True, sort_keys=True).splitlines() + # Remove the final blank space on Python 2.7 + # return json.dumps(obj, indent=True, sort_keys=True).splitlines() + return [line.rstrip() for line in json.dumps(obj, indent=True, sort_keys=True).splitlines()] def compare(actual, expected):