def test_update_metadata(py_file, tmpdir, capsys): tmp_py = str(tmpdir.join('notebook.py')) tmp_ipynb = str(tmpdir.join('notebook.ipynb')) copyfile(py_file, tmp_py) jupytext([ '--to', 'ipynb', tmp_py, '--update-metadata', '{"jupytext":{"formats":"ipynb,py:light"}}' ]) nb = readf(tmp_ipynb) assert nb.metadata['jupytext']['formats'] == 'ipynb,py:light' jupytext([ '--to', 'py', tmp_ipynb, '--update-metadata', '{"jupytext":{"formats":null}}' ]) nb = readf(tmp_py) assert 'formats' not in nb.metadata['jupytext'] with pytest.raises(SystemExit): jupytext([ '--to', 'ipynb', tmp_py, '--update-metadata', '{"incorrect": "JSON"' ]) out, err = capsys.readouterr() assert 'invalid' in err
def assert_conversion_same_as_mirror(nb_file, ext, mirror_name, format_name=None, compare_notebook=False): dirname, basename = os.path.split(nb_file) file_name, org_ext = os.path.splitext(basename) mirror_file = os.path.join(dirname, '..', 'mirror', mirror_name, file_name + ext) notebook = jupytext.readf(nb_file, format_name=format_name) create_mirror_file_if_missing(mirror_file, notebook, format_name=format_name) # Compare the text representation of the two notebooks if compare_notebook: nb_mirror = jupytext.readf(mirror_file) compare(nb_mirror, notebook) return elif ext == '.ipynb': notebook = jupytext.readf(mirror_file) actual = jupytext.writes(notebook, ext=org_ext, format_name=format_name) with open(nb_file, encoding='utf-8') as fp: expected = fp.read() else: actual = jupytext.writes(notebook, ext=ext, format_name=format_name) with open(mirror_file, encoding='utf-8') as fp: expected = fp.read() if format_name and len(actual.splitlines()) > len(expected.splitlines()): actual = '\n'.join(actual.splitlines()[-len(expected.splitlines()):] + ['']) compare(expected, actual)
def test_apply_black_and_sync_on_paired_notebook(tmpdir, nb_file): # Load real notebook metadata to get the 'auto' extension in --pipe-fmt to work metadata = readf(nb_file).metadata metadata['jupytext'] = {'formats': 'ipynb,py'} assert 'language_info' in metadata nb_org = new_notebook(cells=[new_code_cell('1 +1')], metadata=metadata) nb_black = new_notebook(cells=[new_code_cell('1 + 1')], metadata=metadata) tmp_ipynb = str(tmpdir.join('notebook.ipynb')) tmp_py = str(tmpdir.join('notebook.py')) # Black in place writef(nb_org, tmp_ipynb) jupytext([tmp_ipynb, '--pipe', 'black', '--sync']) nb_now = readf(tmp_ipynb) compare(nb_black, nb_now) assert 'language_info' in nb_now.metadata nb_now = readf(tmp_py) nb_now.metadata['jupytext'].pop('text_representation') nb_black.metadata = { key: nb_black.metadata[key] for key in nb_black.metadata if key in _DEFAULT_NOTEBOOK_METADATA } compare(nb_black, nb_now)
def test_apply_black_on_python_notebooks(nb_file, tmpdir): tmp_ipynb = str(tmpdir.join('notebook.ipynb')) tmp_py = str(tmpdir.join('notebook.py')) copyfile(nb_file, tmp_ipynb) jupytext(args=[tmp_ipynb, '--to', 'py:percent']) system('black', tmp_py) jupytext(args=[tmp_py, '--to', 'ipynb', '--update']) nb1 = readf(nb_file) nb2 = readf(tmp_ipynb) nb3 = readf(tmp_py) assert len(nb1.cells) == len(nb2.cells) assert len(nb1.cells) == len(nb3.cells) for c1, c2 in zip(nb1.cells, nb2.cells): # same content (almost) assert black_invariant(c1.source) == black_invariant(c2.source) # python representation is pep8 assert 'lines_to_next_cell' not in c2.metadata # outputs are preserved assert c1.cell_type == c2.cell_type if c1.cell_type == 'code': compare(c1.outputs, c2.outputs) compare(nb1.metadata, nb2.metadata)
def test_remove_jupytext_metadata(tmpdir): tmp_ipynb = str(tmpdir.join('notebook.ipynb')) nb = new_notebook( metadata={ 'jupytext': { 'main_language': 'python', 'text_representation': { 'extension': '.md', 'format_name': 'markdown', 'format_version': '1.0', 'jupytext_version': '0.8.6' } } }) nbformat.write(nb, tmp_ipynb, version=nbformat.NO_CONVERT) # Jupytext removes the 'text_representation' information from the notebook jupytext([ tmp_ipynb, '--update-metadata', '{"jupytext":{"main_language":null}}' ]) nb2 = readf(tmp_ipynb) assert not nb2.metadata nbformat.write(nb, tmp_ipynb, version=nbformat.NO_CONVERT) jupytext([tmp_ipynb, '--set-formats', 'ipynb,py:light']) nb2 = readf(tmp_ipynb) assert nb2.metadata == { 'jupytext': { 'formats': 'ipynb,py:light', 'main_language': 'python' } }
def test_cli_can_infer_jupytext_format_from_stdin(nb_file, tmpdir): tmp_ipynb = str(tmpdir.join('notebook.ipynb')) tmp_py = str(tmpdir.join('notebook.py')) tmp_rmd = str(tmpdir.join('notebook.Rmd')) nb = readf(nb_file) # read ipynb notebook on stdin, write to python with open(nb_file) as fp, mock.patch('sys.stdin', fp): jupytext(['--to', 'py:percent', '-o', tmp_py]) nb2 = readf(tmp_py) compare_notebooks(nb, nb2) # read python notebook on stdin, write to ipynb with open(tmp_py) as fp, mock.patch('sys.stdin', fp): jupytext(['-o', tmp_ipynb]) nb2 = readf(tmp_ipynb) compare_notebooks(nb, nb2) # read ipynb notebook on stdin, write to R markdown with open(nb_file) as fp, mock.patch('sys.stdin', fp): jupytext(['-o', tmp_rmd]) nb2 = readf(tmp_rmd) compare_notebooks(nb, nb2, 'Rmd') # read markdown notebook on stdin, write to ipynb with open(tmp_rmd) as fp, mock.patch('sys.stdin', fp): jupytext(['-o', tmp_ipynb]) nb2 = readf(tmp_ipynb) compare_notebooks(nb, nb2, 'Rmd')
def test_cli_to_auto(nb_file, ext, tmpdir): tmp_ipynb = str(tmpdir.join('notebook.ipynb')) tmp_text = str(tmpdir.join('notebook' + ext)) nb = readf(nb_file) writef(nb, tmp_ipynb) jupytext(['--to', 'auto', tmp_ipynb]) nb2 = readf(tmp_text) compare_notebooks(nb, nb2)
def assert_conversion_same_as_mirror(nb_file, fmt, mirror_name, compare_notebook=False): dirname, basename = os.path.split(nb_file) file_name, org_ext = os.path.splitext(basename) fmt = long_form_one_format(fmt) ext = fmt['extension'] mirror_file = os.path.join(dirname, '..', 'mirror', mirror_name, full_path(file_name, fmt)) with mock.patch('jupytext.header.INSERT_AND_CHECK_VERSION_NUMBER', False): notebook = jupytext.readf(nb_file, fmt) create_mirror_file_if_missing(mirror_file, notebook, fmt) # Compare the text representation of the two notebooks if compare_notebook: nb_mirror = jupytext.readf(mirror_file) compare(nb_mirror, notebook) return elif ext == '.ipynb': notebook = jupytext.readf(mirror_file) fmt.update({'extension': org_ext}) with mock.patch('jupytext.header.INSERT_AND_CHECK_VERSION_NUMBER', False): actual = jupytext.writes(notebook, fmt) with open(nb_file, encoding='utf-8') as fp: expected = fp.read() else: with mock.patch('jupytext.header.INSERT_AND_CHECK_VERSION_NUMBER', False): actual = jupytext.writes(notebook, fmt) with open(mirror_file, encoding='utf-8') as fp: expected = fp.read() if not actual.endswith('\n'): actual = actual + '\n' compare(expected, actual) # Compare the two notebooks if ext != '.ipynb': with mock.patch('jupytext.header.INSERT_AND_CHECK_VERSION_NUMBER', False): notebook = jupytext.readf(nb_file) nb_mirror = jupytext.readf(mirror_file, fmt) if fmt.get('format_name') == 'sphinx': nb_mirror.cells = nb_mirror.cells[1:] for cell in notebook.cells: cell.metadata = {} for cell in nb_mirror.cells: cell.metadata = {} compare_notebooks(notebook, nb_mirror, fmt) combine_inputs_with_outputs(nb_mirror, notebook) compare_notebooks(notebook, nb_mirror, fmt, compare_outputs=True)
def test_convert_single_file_in_place(nb_file, tmpdir): nb_org = str(tmpdir.join(os.path.basename(nb_file))) base, ext = os.path.splitext(nb_org) nb_other = base + '.py' copyfile(nb_file, nb_org) convert_notebook_files([nb_org], ext='.py') nb1 = readf(nb_org) nb2 = readf(nb_other) compare_notebooks(nb1, nb2)
def test_ipynb_is_ok(nb_file, tmpdir): nb = jupytext.readf(nb_file) tmp_ipynb = 'notebook.ipynb' tmp_rmd = 'notebook.Rmd' cm = TextFileContentsManager() cm.root_dir = str(tmpdir) cm.default_jupytext_formats = 'ipynb,Rmd' cm.save(model=dict(type='notebook', content=nb), path=tmp_rmd) nb2 = jupytext.readf(str(tmpdir.join(tmp_ipynb))) compare_notebooks(nb, nb2)
def test_rmd_is_ok(nb_file, tmpdir): nb = jupytext.readf(nb_file) tmp_ipynb = 'notebook.ipynb' tmp_rmd = 'notebook.Rmd' nb.metadata.setdefault('jupytext', {})['formats'] = 'ipynb,Rmd' cm = TextFileContentsManager() cm.root_dir = str(tmpdir) cm.save(model=dict(type='notebook', content=nb), path=tmp_ipynb) nb2 = jupytext.readf(str(tmpdir.join(tmp_rmd))) compare_notebooks(nb, nb2, 'Rmd')
def test_metadata_filter_is_effective(nb_file, tmpdir): nb = jupytext.readf(nb_file) tmp_ipynb = 'notebook.ipynb' tmp_script = 'notebook.py' # create contents manager cm = jupytext.TextFileContentsManager() cm.root_dir = str(tmpdir) # save notebook to tmpdir with mock.patch('jupytext.header.INSERT_AND_CHECK_VERSION_NUMBER', True): cm.save(model=dict(type='notebook', content=nb), path=tmp_ipynb) # set config cm.default_jupytext_formats = 'ipynb, py' cm.default_notebook_metadata_filter = 'jupytext,-all' cm.default_cell_metadata_filter = '-all' # load notebook with mock.patch('jupytext.header.INSERT_AND_CHECK_VERSION_NUMBER', True): nb = cm.get(tmp_ipynb)['content'] assert nb.metadata['jupytext']['metadata_filter']['cells'] == { 'excluded': 'all' } assert nb.metadata['jupytext']['metadata_filter']['notebook'] == { 'additional': ['jupytext'], 'excluded': 'all' } # save notebook again with mock.patch('jupytext.header.INSERT_AND_CHECK_VERSION_NUMBER', True): cm.save(model=dict(type='notebook', content=nb), path=tmp_ipynb) # read text version with mock.patch('jupytext.header.INSERT_AND_CHECK_VERSION_NUMBER', True): nb2 = jupytext.readf(str(tmpdir.join(tmp_script))) # test no metadata assert set(nb2.metadata.keys()) <= {'jupytext'} for cell in nb2.cells: assert not cell.metadata # read paired notebook with mock.patch('jupytext.header.INSERT_AND_CHECK_VERSION_NUMBER', True): nb3 = cm.get(tmp_script)['content'] compare_notebooks(nb, nb3)
def test_save_in_auto_extension_local(nb_file, tmpdir): # load notebook nb = jupytext.readf(nb_file) nb.metadata.setdefault('jupytext', {})['formats'] = 'ipynb,auto:percent' if 'language_info' not in nb.metadata: return auto_ext = auto_ext_from_metadata(nb.metadata) tmp_ipynb = 'notebook.ipynb' tmp_script = 'notebook' + auto_ext # create contents manager with default load format as percent cm = jupytext.TextFileContentsManager() cm.root_dir = str(tmpdir) # save notebook cm.save(model=dict(type='notebook', content=nb), path=tmp_ipynb) # check that text representation exists, and is in percent format with open(str(tmpdir.join(tmp_script))) as stream: assert read_format_from_metadata(stream.read(), auto_ext) == 'percent' # reload and compare with original notebook model = cm.get(path=tmp_script) compare_notebooks(nb, model['content'])
def test_save_in_pct_and_lgt_auto_extensions(nb_file, tmpdir): # load notebook nb = jupytext.readf(nb_file) if 'language_info' not in nb.metadata: return auto_ext = auto_ext_from_metadata(nb.metadata) tmp_ipynb = 'notebook.ipynb' tmp_pct_script = 'notebook.pct' + auto_ext tmp_lgt_script = 'notebook.lgt' + auto_ext # create contents manager with default load format as percent cm = jupytext.TextFileContentsManager() cm.default_jupytext_formats = 'ipynb,.pct.auto,.lgt.auto' cm.preferred_jupytext_formats_save = '.pct.auto:percent,.lgt.auto:light' cm.root_dir = str(tmpdir) # save notebook cm.save(model=dict(type='notebook', content=nb), path=tmp_ipynb) # check that text representation exists in percent format with open(str(tmpdir.join(tmp_pct_script))) as stream: assert read_format_from_metadata(stream.read(), auto_ext) == 'percent' # check that text representation exists in light format with open(str(tmpdir.join(tmp_lgt_script))) as stream: assert read_format_from_metadata(stream.read(), auto_ext) == 'light'
def test_load_save_rename_nbpy(nb_file, tmpdir): tmp_ipynb = 'notebook.ipynb' tmp_nbpy = 'notebook.nb.py' cm = jupytext.TextFileContentsManager() cm.default_jupytext_formats = 'ipynb,.nb.py' cm.root_dir = str(tmpdir) # open ipynb, save nb.py, reopen nb = jupytext.readf(nb_file) cm.save(model=dict(type='notebook', content=nb), path=tmp_nbpy) nbpy = cm.get(tmp_nbpy) compare_notebooks(nb, nbpy['content']) # save ipynb cm.save(model=dict(type='notebook', content=nb), path=tmp_ipynb) # rename nbpy cm.rename(tmp_nbpy, 'new.nb.py') assert not os.path.isfile(str(tmpdir.join(tmp_ipynb))) assert not os.path.isfile(str(tmpdir.join(tmp_nbpy))) assert os.path.isfile(str(tmpdir.join('new.ipynb'))) assert os.path.isfile(str(tmpdir.join('new.nb.py'))) # rename to a non-matching pattern with pytest.raises(HTTPError): cm.rename_file(tmp_nbpy, 'suffix_missing.py')
def test_pair_notebook_with_dot(nb_file, tmpdir): # Reproduce issue #138 tmp_py = 'file.5.1.py' tmp_ipynb = 'file.5.1.ipynb' cm = jupytext.TextFileContentsManager() cm.root_dir = str(tmpdir) nb = jupytext.readf(nb_file) nb['metadata']['jupytext'] = {'formats': 'ipynb,py:percent'} # save to ipynb and three python flavors cm.save(model=dict(type='notebook', content=nb), path=tmp_ipynb) assert os.path.isfile(str(tmpdir.join(tmp_ipynb))) # read files with open(str(tmpdir.join(tmp_py))) as stream: assert read_format_from_metadata(stream.read(), '.py') == 'percent' model = cm.get(path=tmp_py) assert model['name'] == 'file.5.1.py' compare_notebooks(nb, model['content']) model = cm.get(path=tmp_ipynb) assert model['name'] == 'file.5.1.ipynb' compare_notebooks(nb, model['content'])
def read(cls, path): """ Read a notebook using Jupytext """ assert path.startswith('txt://') nb = jupytext.readf(path[6:]) return nbformat.writes(nb, version=4)
def strip_cells(nb_in, nb_out, the_string): """ Remove all cells with metadata['ctype']==the_string from cell list. Parameters ---------- nb_in: str the path of the notebook to strip cells from nb_out: str the path of the notebook to write to the_string: str the cell type to strip Returns ------- obj a new notebook object with cells stripped """ nb_obj = jp.readf(nb_in) new_list = [] for the_cell in nb_obj['cells']: if 'ctype' in the_cell['metadata']: if the_cell['metadata']['ctype'] == the_string: continue new_list.append(the_cell) nb_obj['cells'] = new_list jp.writef(nb_obj, str(nb_out)) return nb_obj
def main(pynotebook, keyout): keypath = Path(keyout.name) if keypath.suffix != ".json": raise ValueError(f"your output file {keyout} needs to end in .json") nb_obj = jp.readf(pynotebook) answers = nu.get_key(nb_obj) json.dump(answers, keyout, indent=4)
def test_convert_to_percent_format(nb_file, tmpdir): tmp_ipynb = str(tmpdir.join('notebook.ipynb')) tmp_nbpy = str(tmpdir.join('notebook.py')) copyfile(nb_file, tmp_ipynb) jupytext(['--to', 'py:percent', tmp_ipynb]) with open(tmp_nbpy) as stream: py_script = stream.read() assert 'format_name: percent' in py_script nb1 = readf(tmp_ipynb) nb2 = readf(tmp_nbpy) compare_notebooks(nb1, nb2)
def test_cli_can_infer_jupytext_format(nb_file, ext, tmpdir): tmp_ipynb = str(tmpdir.join('notebook.ipynb')) tmp_text = str(tmpdir.join('notebook' + ext)) nb = readf(nb_file) # Light format to Jupyter notebook writef(nb, tmp_text) jupytext(['--to', 'notebook', tmp_text]) nb2 = readf(tmp_ipynb) compare_notebooks(nb, nb2) # Percent format to Jupyter notebook writef(nb, tmp_text, ext + ':percent') jupytext(['--to', 'notebook', tmp_text]) nb2 = readf(tmp_ipynb) compare_notebooks(nb, nb2)
def test_convert_and_update_preserves_notebook(nb_file, fmt, tmpdir): # cannot encode magic parameters in markdown yet if 'magic' in nb_file and fmt == 'md': return tmp_ipynb = str(tmpdir.join('notebook.ipynb')) copyfile(nb_file, tmp_ipynb) ext = long_form_one_format(fmt)['extension'] tmp_text = str(tmpdir.join('notebook' + ext)) jupytext(['--to', fmt, tmp_ipynb]) jupytext(['--to', 'ipynb', '--update', tmp_text]) nb_org = readf(nb_file) nb_now = readf(tmp_ipynb) compare(nb_org, nb_now)
def test_local_format_can_deactivate_pairing(nb_file, ext, tmpdir): """This is a test for #157: local format can be used to deactivate the global pairing""" nb = jupytext.readf(nb_file) nb.metadata['jupytext_formats'] = ext[1:] # py or ipynb # create contents manager with default pairing cm = jupytext.TextFileContentsManager() cm.default_jupytext_formats = 'ipynb,py' cm.root_dir = str(tmpdir) # save notebook cm.save(model=dict(type='notebook', content=nb), path='notebook' + ext) # check that only the text representation exists assert os.path.isfile(str(tmpdir.join('notebook.py'))) == (ext == '.py') assert os.path.isfile(str( tmpdir.join('notebook.ipynb'))) == (ext == '.ipynb') nb2 = cm.get('notebook' + ext)['content'] compare_notebooks(nb, nb2) # resave, check again cm.save(model=dict(type='notebook', content=nb2), path='notebook' + ext) assert os.path.isfile(str(tmpdir.join('notebook.py'))) == (ext == '.py') assert os.path.isfile(str( tmpdir.join('notebook.ipynb'))) == (ext == '.ipynb') nb3 = cm.get('notebook' + ext)['content'] compare_notebooks(nb, nb3)
def test_save_in_auto_extension_global_with_format(nb_file, tmpdir): # load notebook nb = jupytext.readf(nb_file) if nb.metadata.get('jupytext', {}).get('formats'): del nb.metadata['jupytext']['formats'] if 'language_info' not in nb.metadata: return auto_ext = auto_ext_from_metadata(nb.metadata) tmp_ipynb = 'notebook.ipynb' tmp_script = 'notebook' + auto_ext # create contents manager with default load format as percent cm = jupytext.TextFileContentsManager() cm.default_jupytext_formats = 'ipynb,auto:percent' cm.root_dir = str(tmpdir) # save notebook with mock.patch('jupytext.header.INSERT_AND_CHECK_VERSION_NUMBER', True): cm.save(model=dict(type='notebook', content=nb), path=tmp_ipynb) # check that text representation exists, and is in percent format with open(str(tmpdir.join(tmp_script))) as stream: assert read_format_from_metadata(stream.read(), auto_ext) == 'percent' # reload and compare with original notebook with mock.patch('jupytext.header.INSERT_AND_CHECK_VERSION_NUMBER', True): model = cm.get(path=tmp_script) # saving should not create a format entry #95 assert 'formats' not in model['content'].metadata.get('jupytext', {}) compare_notebooks(nb, model['content'])
def test_convert_single_file(nb_file, capsys): nb1 = readf(nb_file) pynb = writes(nb1, ext='.py') convert_notebook_files([nb_file], ext='.py', output='-') out, err = capsys.readouterr() assert err == '' compare(out, pynb)
def main(args=None): parser = make_parser() args = parser.parse_args(args) nb_obj = jp.readf(args.pynotebook) new_nb = nu.update_headers(nb_obj, lhead=args.lhead, chead=args.chead) jp.writef(new_nb, args.pynotebook) jupytext(args=[args.pynotebook, '--to', '..//ipynb', '--execute']) Path(args.pynotebook).touch()
def test_notebook_contents_is_unicode(nb_file): nb = jupytext.readf(nb_file) for cell in nb.cells: if sys.version_info < (3, 0): assert cell.source == '' or isinstance(cell.source, unicode) else: assert isinstance(cell.source, str)
def test_all_files_created(nb_file, tmpdir): nb = jupytext.readf(nb_file) tmp_ipynb = 'notebook.ipynb' tmp_rmd = 'notebook.Rmd' tmp_py = 'notebook.py' nb.metadata['jupytext'] = {'formats': 'ipynb,Rmd,py'} cm = TextFileContentsManager() cm.root_dir = str(tmpdir) cm.save(model=dict(type='notebook', content=nb), path=tmp_ipynb) nb2 = jupytext.readf(str(tmpdir.join(tmp_py))) compare_notebooks(nb, nb2) nb3 = jupytext.readf(str(tmpdir.join(tmp_rmd))) compare_notebooks(nb, nb3, 'Rmd')
def test_convert_to_percent_format(nb_file, tmpdir): tmp_ipynb = str(tmpdir.join('notebook.ipynb')) tmp_nbpy = str(tmpdir.join('notebook.py')) copyfile(nb_file, tmp_ipynb) with mock.patch('jupytext.header.INSERT_AND_CHECK_VERSION_NUMBER', True): jupytext(['--to', 'py:percent', tmp_ipynb]) with open(tmp_nbpy) as stream: py_script = stream.read() assert 'py:percent' in py_script nb1 = readf(tmp_ipynb) nb2 = readf(tmp_nbpy) compare_notebooks(nb1, nb2)
def test_to_cpluplus(nb_file, capsys): nb1 = readf(nb_file) text_cpp = writes(nb1, ext='.cpp') jupytext([nb_file, '--to', 'c++', '--output', '-']) out, err = capsys.readouterr() assert err == '' compare(out, text_cpp)