def test_notebook_with_python3_magic( no_jupytext_version_number, nb=new_notebook( metadata={ "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3", } }, cells=[ new_code_cell("%%python2\na = 1\nprint a"), new_code_cell("%%python3\nb = 2\nprint(b)"), ], ), text="""--- jupyter: kernelspec: display_name: Python 3 language: python name: python3 --- ```python2 a = 1 print a ``` ```python3 b = 2 print(b) ``` """, ): md = jupytext.writes(nb, "md") compare(md, text) nb2 = jupytext.reads(md, "md") compare_notebooks(nb2, nb)
def test_read_write_script_with_metadata_241(no_jupytext_version_number, rsnb="""#!/usr/bin/env scriptisto // --- // jupyter: // jupytext: // text_representation: // extension: .rs // format_name: light // kernelspec: // display_name: Rust // language: rust // name: rust // --- let mut a: i32 = 2; a += 1; """): nb = jupytext.reads(rsnb, 'rs') assert 'executable' in nb.metadata['jupytext'] rsnb2 = jupytext.writes(nb, 'rs') compare(rsnb, rsnb2)
def test_default_cell_markers_in_contents_manager_does_not_impact_light_format( tmpdir): tmp_ipynb = str(tmpdir.join("notebook.ipynb")) tmp_py = str(tmpdir.join("notebook.py")) cm = jupytext.TextFileContentsManager() cm.root_dir = str(tmpdir) cm.default_cell_markers = "'''" nb = new_notebook( cells=[new_code_cell("1 + 1"), new_markdown_cell("a\nlong\ncell")], metadata={ "jupytext": { "formats": "ipynb,py", "notebook_metadata_filter": "-all" } }, ) cm.save(model=dict(type="notebook", content=nb), path="notebook.ipynb") assert os.path.isfile(tmp_ipynb) assert os.path.isfile(tmp_py) with open(tmp_py) as fp: text = fp.read() compare( text, """1 + 1 # a # long # cell """, ) nb2 = jupytext.read(tmp_py) compare_notebooks(nb, nb2)
def test_read_markdown_IDL(no_jupytext_version_number, text='''--- jupyter: kernelspec: display_name: IDL [conda env:gdl] * language: IDL name: conda-env-gdl-idl --- # A sample IDL Markdown notebook ```IDL a = 1 ``` '''): nb = jupytext.reads(text, 'md') assert len(nb.cells) == 2 assert nb.cells[1].cell_type == 'code' assert nb.cells[1].source == 'a = 1' text2 = jupytext.writes(nb, 'md') compare(text2, text)
def test_read_raw_cell_markdown_version_1_1_with_mimetype( header="""--- jupyter: jupytext: text_representation: extension: .md format_name: markdown format_version: '1.1' jupytext_version: 1.1.0-rc0 kernelspec: display_name: Python 3 language: python name: python3 --- """, markdown_11="""```raw_mimetype="text/restructuredtext" .. meta:: :description: Topic: Integrated Development Environments, Difficulty: Easy, Category: Tools :keywords: python, introduction, IDE, PyCharm, VSCode, Jupyter, recommendation, tools ``` """, markdown_12="""<!-- #raw raw_mimetype="text/restructuredtext" --> .. meta:: :description: Topic: Integrated Development Environments, Difficulty: Easy, Category: Tools :keywords: python, introduction, IDE, PyCharm, VSCode, Jupyter, recommendation, tools <!-- #endraw --> """): nb = jupytext.reads(header + '\n' + markdown_11, 'md') compare( nb.cells[0], new_raw_cell(source=""".. meta:: :description: Topic: Integrated Development Environments, Difficulty: Easy, Category: Tools :keywords: python, introduction, IDE, PyCharm, VSCode, Jupyter, recommendation, tools""", metadata={'raw_mimetype': 'text/restructuredtext'})) md2 = jupytext.writes(nb, 'md') assert "format_version: '1.1'" not in md2 nb.metadata['jupytext']['notebook_metadata_filter'] = '-all' md2 = jupytext.writes(nb, 'md') compare(md2, markdown_12)
def test_prefix_and_suffix(): short_formats = 'notebook_folder/notebook_prefix_/_notebook_suffix.ipynb,' \ 'script_folder//_in_percent_format.py:percent,' \ 'script_folder//_in_light_format.py' formats = long_form_multiple_formats(short_formats) assert short_form_multiple_formats(formats) == short_formats expected_paths = [ 'parent/notebook_folder/notebook_prefix_NOTEBOOK_NAME_notebook_suffix.ipynb', '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(paired_paths(path, fmt, formats), list(zip(expected_paths, formats))) # without the parent folder expected_paths = [path[7:] for path in expected_paths] for fmt, path in zip(formats, expected_paths): compare(paired_paths(path, fmt, formats), list(zip(expected_paths, formats))) # Not the expected parent folder with pytest.raises(InconsistentPath): paired_paths( 'script_folder_incorrect/NOTEBOOK_NAME_in_percent_format.py', formats[1], formats) # Not the expected suffix with pytest.raises(InconsistentPath): paired_paths('parent/script_folder/NOTEBOOK_NAME_in_LIGHT_format.py', formats[2], formats) # Not the expected extension with pytest.raises(InconsistentPath): paired_paths( 'notebook_folder/notebook_prefix_NOTEBOOK_NAME_notebook_suffix.py', formats[0], formats)
def test_jupyter_book_options_to_rmarkdown(md, rmd): """By default, Jupyter Book tags are mapped to R Markdown options, and vice versa #337""" md = ("```python " + md + """ 1 + 1 ``` """) rmd = ("```{python " + rmd + """} 1 + 1 ``` """) nb_md = jupytext.reads(md, "md") nb_rmd = jupytext.reads(rmd, "Rmd") compare_notebooks(nb_rmd, nb_md) md2 = jupytext.writes(nb_rmd, "md") compare(md2, md) rmd = rmd.replace('"hide"', "'hide'") rmd2 = jupytext.writes(nb_md, "Rmd") compare(rmd2, rmd)
def test_python_kernel_preserves_R_files(nb_file, tmpdir): """Opening a R file with a Jupyter server that has no R kernel should not modify the file""" tmp_r_file = str(tmpdir.join('script.R')) with open(nb_file) as fp: script = fp.read() with open(tmp_r_file, 'w') as fp: fp.write(script) # create contents manager cm = jupytext.TextFileContentsManager() cm.root_dir = str(tmpdir) # open notebook, set Python kernel and save model = cm.get('script.R') model['content'].metadata['kernelspec'] = kernelspec_from_language( 'python') cm.save(model=model, path='script.R') with open(tmp_r_file) as fp: script2 = fp.read() compare(script, script2)
def test_simple_cs(lang): source = """// A Hello World! program in C#. Console.WriteLine("Hello World!"); """ md = """```{lang} {source} ``` """.format( lang=lang, source=source ) nb = jupytext.reads(md, "md") assert nb.metadata["jupytext"]["main_language"] == "csharp" assert len(nb.cells) == 1 assert nb.cells[0].cell_type == "code" cs = jupytext.writes(nb, "cs") assert source in cs if lang != "csharp": assert cs.startswith('// + language="{lang}"'.format(lang=lang)) md2 = jupytext.writes(nb, "md") compare(md2, md)
def test_read_simple_file(script=""";; --- ;; title: Simple file ;; --- ;; Here we have some text ;; And below we have some code (define a 35) """): for file_extension in ('ss', 'scm'): nb = jupytext.reads(script, file_extension) assert len(nb.cells) == 3 assert nb.cells[0].cell_type == 'raw' assert nb.cells[0].source == '---\ntitle: Simple file\n---' assert nb.cells[1].cell_type == 'markdown' assert nb.cells[1].source == 'Here we have some text\n' \ 'And below we have some code' assert nb.cells[2].cell_type == 'code' compare(nb.cells[2].source, '(define a 35)') script2 = jupytext.writes(nb, file_extension) compare(script2, script)
def test_read_explicit_markdown_cell_with_triple_quote_307( script="""# {{{ {"special": "metadata", "cell_type": "markdown"} # some text ''' # }}} print('hello world') # {{{ {"special": "metadata", "cell_type": "markdown"} # more text ''' # }}} """): notebook = jupytext.reads(script, 'py') assert len(notebook.cells) == 3 assert notebook.cells[0].cell_type == 'markdown' assert notebook.cells[0].source == "some text '''" assert notebook.cells[1].cell_type == 'code' assert notebook.cells[1].source == "print('hello world')" assert notebook.cells[2].cell_type == 'markdown' assert notebook.cells[2].source == "more text '''" script2 = jupytext.writes(notebook, 'py') compare(script2, script)
def test_load_save_py_freeze_metadata(script, tmpdir): tmp_nbpy = 'notebook.py' cm = jupytext.TextFileContentsManager() cm.root_dir = str(tmpdir) # read original file with open(script) as fp: text_py = fp.read() # write to tmp_nbpy with open(str(tmpdir.join(tmp_nbpy)), 'w') as fp: fp.write(text_py) # open and save notebook nb = cm.get(tmp_nbpy)['content'] cm.save(model=dict(type='notebook', content=nb), path=tmp_nbpy) with open(str(tmpdir.join(tmp_nbpy))) as fp: text_py2 = fp.read() compare(text_py, text_py2)
def test_default_cell_markers_in_contents_manager(tmpdir): tmp_ipynb = str(tmpdir.join('notebook.ipynb')) tmp_py = str(tmpdir.join('notebook.py')) cm = jupytext.TextFileContentsManager() cm.root_dir = str(tmpdir) cm.default_cell_markers = "'''" nb = new_notebook( cells=[new_code_cell('1 + 1'), new_markdown_cell('a\nlong\ncell')], metadata={ 'jupytext': { 'formats': 'ipynb,py:percent', 'notebook_metadata_filter': '-all' } }) cm.save(model=dict(type='notebook', content=nb), path='notebook.ipynb') assert os.path.isfile(tmp_ipynb) assert os.path.isfile(tmp_py) with open(tmp_py) as fp: text = fp.read() compare(text, """# %% 1 + 1 # %% [markdown] ''' a long cell ''' """) nb2 = jupytext.read(tmp_py) compare_notebooks(nb, nb2)
def test_alternate_tree_four_five_backticks( no_jupytext_version_number, nb=new_notebook( metadata={"main_language": "python"}, cells=[ new_code_cell('a = """\n```\n"""'), new_code_cell("b = 2"), new_code_cell('c = """\n````\n"""'), ], ), text='''--- jupyter: jupytext: main_language: python --- ````python a = """ ``` """ ```` ```python b = 2 ``` `````python c = """ ```` """ ````` ''', ): actual_text = writes(nb, fmt="md") compare(actual_text, text) actual_nb = reads(text, fmt="md") compare_notebooks(actual_nb, nb)
def test_read_mostly_R_markdown_file(markdown="""```R ls() ``` ```R cat(stringi::stri_rand_lipsum(3), sep='\n\n') ``` """): nb = jupytext.reads(markdown, 'md') assert nb.metadata['jupytext']['main_language'] == 'R' compare(nb.cells, [{'cell_type': 'code', 'metadata': {}, 'execution_count': None, 'source': 'ls()', 'outputs': []}, {'cell_type': 'code', 'metadata': {}, 'execution_count': None, 'source': "cat(stringi::stri_rand_lipsum(3), sep='\n\n')", 'outputs': []}]) markdown2 = jupytext.writes(nb, 'md') compare(markdown2, markdown)
def test_escape_start_pattern(ext, rnb="""#' The code start pattern '#+' can #' appear in code and markdown cells. #' In markdown cells it is escaped like here: #' #+ fig.width=12 # In code cells like this one, it is also escaped # #+ cell_name language="python" 1 + 1 """): nb = jupytext.reads(rnb, ext) assert len(nb.cells) == 3 assert nb.cells[0].cell_type == 'markdown' assert nb.cells[1].cell_type == 'markdown' assert nb.cells[2].cell_type == 'code' assert nb.cells[1].source == '''In markdown cells it is escaped like here: #+ fig.width=12''' assert (nb.cells[2].source == '''# In code cells like this one, it is also escaped #+ cell_name language="python" 1 + 1''') rnb2 = jupytext.writes(nb, ext) compare(rnb, rnb2)
def test_rearrange_jupytext_metadata_metadata_filter(): metadata = { 'jupytext': { 'metadata_filter': { 'notebook': { 'additional': ['one', 'two'], 'excluded': 'all' }, 'cells': { 'additional': 'all', 'excluded': ['three', 'four'] } } } } rearrange_jupytext_metadata(metadata) compare( { 'jupytext': { 'notebook_metadata_filter': 'one,two,-all', 'cell_metadata_filter': 'all,-three,-four' } }, metadata)
def test_read_mostly_R_markdown_file( markdown="""```R ls() ``` ```R cat(stringi::stri_rand_lipsum(3), sep='\n\n') ``` """, ): nb = jupytext.reads(markdown, "md") assert nb.metadata["jupytext"]["main_language"] == "R" compare_cells( nb.cells, [ new_code_cell("ls()"), new_code_cell("cat(stringi::stri_rand_lipsum(3), sep='\n\n')"), ], compare_ids=False, ) markdown2 = jupytext.writes(nb, "md") compare(markdown2, markdown)
def test_one_blank_lines_after_endofcell(pynb="""# + # This is a code cell with explicit end of cell 1 + 1 2 + 2 # - # This cell is a cell with implicit start 1 + 1 """): nb = jupytext.reads(pynb, 'py') assert len(nb.cells) == 2 assert nb.cells[0].cell_type == 'code' assert (nb.cells[0].source == '''# This is a code cell with explicit end of cell 1 + 1 2 + 2''') assert nb.cells[1].cell_type == 'code' assert nb.cells[1].source == '''# This cell is a cell with implicit start 1 + 1''' pynb2 = jupytext.writes(nb, 'py') compare(pynb, pynb2)
def test_multiline_python_magic(no_jupytext_version_number): nb = new_notebook(cells=[ new_code_cell("""%load_ext watermark %watermark -u -n -t -z \\ -p jupytext -v def g(x): return x+1""") ]) text = jupytext.writes(nb, "py") compare( text, """# + # %load_ext watermark # %watermark -u -n -t -z \\ # -p jupytext -v def g(x): return x+1 """, ) compare_notebooks(jupytext.reads(text, "py"), nb)
def test_escape_start_pattern(pynb="""# The code start pattern '# +' can # appear in code and markdown cells. # In markdown cells it is escaped like here: # # + {"sample_metadata": "value"} # In code cells like this one, it is also escaped # # + {"sample_metadata": "value"} 1 + 1 """, ): nb = jupytext.reads(pynb, "py") assert len(nb.cells) == 3 assert nb.cells[0].cell_type == "markdown" assert nb.cells[1].cell_type == "markdown" assert nb.cells[2].cell_type == "code" assert (nb.cells[1].source == """In markdown cells it is escaped like here: # + {"sample_metadata": "value"}""") assert (nb.cells[2].source == """# In code cells like this one, it is also escaped # + {"sample_metadata": "value"} 1 + 1""") pynb2 = jupytext.writes(nb, "py") compare(pynb2, pynb)
def test_indented_comment(text="""def f(): return 1 # f returns 1 def g(): return 2 # h returns 3 def h(): return 3 """, ref=new_notebook(cells=[new_code_cell("""def f(): return 1 # f returns 1"""), new_code_cell('def g():\n return 2'), new_code_cell('# h returns 3\ndef h():\n return 3')])): nb = jupytext.reads(text, 'py') compare_notebooks(nb, ref) py = jupytext.writes(nb, 'py') compare(py, text)
def test_one_blank_lines_after_endofcell(pynb="""# + # This is a code cell with explicit end of cell 1 + 1 2 + 2 # - # This cell is a cell with implicit start 1 + 1 """, ): nb = jupytext.reads(pynb, "py") assert len(nb.cells) == 2 assert nb.cells[0].cell_type == "code" assert (nb.cells[0].source == """# This is a code cell with explicit end of cell 1 + 1 2 + 2""") assert nb.cells[1].cell_type == "code" assert (nb.cells[1].source == """# This cell is a cell with implicit start 1 + 1""") pynb2 = jupytext.writes(nb, "py") compare(pynb2, pynb)
def test_header_to_html_comment(no_jupytext_version_number): metadata = { "jupytext": { "mainlanguage": "python", "hide_notebook_metadata": True } } nb = new_notebook(metadata=metadata, cells=[]) header, lines_to_next_cell = metadata_and_cell_to_header( nb, metadata, get_format_implementation(".md"), ".md") compare( "\n".join(header), """<!-- --- jupyter: jupytext: hide_notebook_metadata: true mainlanguage: python --- -->""", )
def test_mark_cell_with_no_title_and_inner_region( script="""# This is a markdown cell # region {"key": "value"} a = 1 # region An inner region b = 2 # endregion def f(x): return x + 1 # endregion d = 4 """): nb = jupytext.reads(script, 'py') assert nb.cells[0].cell_type == 'markdown' assert nb.cells[0].source == 'This is a markdown cell' assert nb.cells[1].cell_type == 'code' assert nb.cells[1].source == '# region {"key": "value"}\na = 1' assert nb.cells[2].cell_type == 'code' assert nb.cells[2].metadata['title'] == 'An inner region' assert nb.cells[2].source == 'b = 2' assert nb.cells[3].cell_type == 'code' assert nb.cells[3].source == 'def f(x):\n return x + 1' assert nb.cells[4].cell_type == 'code' assert nb.cells[4].source == '# endregion' assert nb.cells[5].cell_type == 'code' assert nb.cells[5].source == 'd = 4' assert len(nb.cells) == 6 script2 = jupytext.writes(nb, 'py') compare(script, script2)
def test_pair_plain_script(py_file, tmpdir): tmp_py = 'notebook.py' tmp_ipynb = 'notebook.ipynb' cm = jupytext.TextFileContentsManager() cm.root_dir = str(tmpdir) # open py file, pair, save with cm nb = jupytext.read(py_file) nb.metadata['jupytext']['formats'] = 'ipynb,py:hydrogen' cm.save(model=dict(type='notebook', content=nb), path=tmp_py) assert os.path.isfile(str(tmpdir.join(tmp_py))) assert os.path.isfile(str(tmpdir.join(tmp_ipynb))) # Make sure we've not changed the script with open(py_file) as fp: script = fp.read() with open(str(tmpdir.join(tmp_py))) as fp: script2 = fp.read() compare(script, script2) # reopen py file with the cm nb2 = cm.get(tmp_py)['content'] compare_notebooks(nb, nb2) assert nb2.metadata['jupytext']['formats'] == 'ipynb,py:hydrogen' # remove the pairing and save del nb.metadata['jupytext']['formats'] cm.save(model=dict(type='notebook', content=nb), path=tmp_py) # reopen py file with the cm nb2 = cm.get(tmp_py)['content'] compare_notebooks(nb, nb2) assert 'formats' not in nb2.metadata['jupytext']
def test_read_md_and_markdown_regions(markdown="""Some text <!-- #md --> A long cell <!-- #endmd --> <!-- #markdown --> Another long cell <!-- #endmarkdown --> """): nb = jupytext.reads(markdown, 'md') assert nb.metadata['jupytext']['main_language'] == 'python' compare(nb.cells, [ new_markdown_cell('Some text'), new_markdown_cell("""A long cell""", metadata={'region_name': 'md'}), new_markdown_cell("""Another long cell""", metadata={'region_name': 'markdown'}) ]) markdown2 = jupytext.writes(nb, 'md') compare(markdown, markdown2)
def test_read_simple_file(text="""println!("Hello world"); eprintln!("Hello error"); format!("Hello {}", "world") // A Function pub fn fib(x: i32) -> i32 { if x <= 2 {0} else {fib(x - 2) + fib(x - 1)} } // This is a // Markdown cell // This is a magic instruction // :vars // This is a rust identifier ::std::mem::drop """, ): nb = jupytext.reads(text, "rs") compare_notebooks( nb, new_notebook(cells=[ new_code_cell("""println!("Hello world"); eprintln!("Hello error"); format!("Hello {}", "world")"""), new_code_cell("""// A Function pub fn fib(x: i32) -> i32 { if x <= 2 {0} else {fib(x - 2) + fib(x - 1)} }"""), new_markdown_cell("This is a\nMarkdown cell"), new_code_cell("""// This is a magic instruction :vars"""), new_code_cell("""// This is a rust identifier ::std::mem::drop"""), ]), ) compare(jupytext.writes(nb, "rs"), text)
def test_mark_cell_with_no_title_and_inner_region( script="""# This is a markdown cell # region {"key": "value"} a = 1 # region An inner region b = 2 # endregion def f(x): return x + 1 # endregion d = 4 """, ): nb = jupytext.reads(script, "py") assert nb.cells[0].cell_type == "markdown" assert nb.cells[0].source == "This is a markdown cell" assert nb.cells[1].cell_type == "code" assert nb.cells[1].source == '# region {"key": "value"}\na = 1' assert nb.cells[2].cell_type == "code" assert nb.cells[2].metadata["title"] == "An inner region" assert nb.cells[2].source == "b = 2" assert nb.cells[3].cell_type == "code" assert nb.cells[3].source == "def f(x):\n return x + 1" assert nb.cells[4].cell_type == "code" assert nb.cells[4].source == "# endregion" assert nb.cells[5].cell_type == "code" assert nb.cells[5].source == "d = 4" assert len(nb.cells) == 6 script2 = jupytext.writes(nb, "py") compare(script2, script)
def test_read_simple_file( script="""// --- // title: Simple file // --- // Here we have some text // And below we have some code System.out.println("Hello World"); """, ): nb = jupytext.reads(script, "java") assert len(nb.cells) == 3 assert nb.cells[0].cell_type == "raw" assert nb.cells[0].source == "---\ntitle: Simple file\n---" assert nb.cells[1].cell_type == "markdown" assert ( nb.cells[1].source == "Here we have some text\n" "And below we have some code" ) assert nb.cells[2].cell_type == "code" assert nb.cells[2].source == """System.out.println("Hello World");""" script2 = jupytext.writes(nb, "java") compare(script2, script)