Skip to content

Commit acfe47d

Browse files
committed
Preserve the default lexer in jupytext.default_lexer
Warn if there are multiple lexers
1 parent b11447b commit acfe47d

File tree

6 files changed

+24
-44
lines changed

6 files changed

+24
-44
lines changed

src/jupytext/jupytext.py

+2-11
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,7 @@
3434
set_main_and_cell_language,
3535
)
3636
from .metadata_filter import filter_metadata, update_metadata_filters
37-
from .myst import (
38-
MYST_FORMAT_NAME,
39-
language_to_lexer,
40-
myst_extensions,
41-
myst_to_notebook,
42-
notebook_to_myst,
43-
)
37+
from .myst import MYST_FORMAT_NAME, myst_extensions, myst_to_notebook, notebook_to_myst
4438
from .pandoc import md_to_notebook, notebook_to_md
4539
from .pep8 import pep8_lines_between_cells
4640
from .quarto import notebook_to_qmd, qmd_to_notebook
@@ -242,10 +236,7 @@ def writes(self, nb, metadata=None, **kwargs):
242236
"pygments_lexer", None
243237
)
244238
if default_lexer is None:
245-
language = metadata.get("kernelspec", {}).get(
246-
"language"
247-
) or metadata.get("jupytext", {}).get("main_language")
248-
default_lexer = language_to_lexer(language)
239+
default_lexer = metadata.get("jupytext", {}).get("default_lexer", None)
249240
return notebook_to_myst(
250241
self.filter_notebook(nb, metadata),
251242
default_lexer=default_lexer,

src/jupytext/myst.py

+14-28
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
import json
66
import re
77
import warnings
8-
from collections import Counter
98
from textwrap import dedent
109

1110
import nbformat as nbf
@@ -255,20 +254,6 @@ def read_cell_metadata(token, cell_index):
255254
return metadata
256255

257256

258-
def lexer_to_language(lexer):
259-
"""Convert a lexer name to a language name."""
260-
if lexer == "ipython3":
261-
return "python"
262-
return None
263-
264-
265-
def language_to_lexer(language):
266-
"""Convert a language name to a lexer name."""
267-
if language == "python":
268-
return "ipython3"
269-
return None
270-
271-
272257
def myst_to_notebook(
273258
text,
274259
code_directive=CODE_DIRECTIVE,
@@ -293,6 +278,7 @@ def myst_to_notebook(
293278
tokens = get_parser().parse(text + "\n")
294279
lines = text.splitlines()
295280
md_start_line = 0
281+
default_lexer = None
296282

297283
# get the document metadata
298284
metadata_nb = {}
@@ -325,8 +311,6 @@ def _flush_markdown(start_line, token, md_metadata):
325311
nesting_level = 0
326312
md_metadata = {}
327313

328-
languages = Counter()
329-
330314
for token in tokens:
331315
nesting_level += token.nesting
332316

@@ -339,9 +323,14 @@ def _flush_markdown(start_line, token, md_metadata):
339323
options, body_lines = read_fenced_cell(token, len(notebook.cells), "Code")
340324
assert token.info.startswith(code_directive)
341325
lexer = token.info[len(code_directive) :].strip()
342-
language = lexer_to_language(lexer)
343-
if language:
344-
languages[language] += 1
326+
if lexer:
327+
if not default_lexer:
328+
default_lexer = lexer
329+
elif lexer != default_lexer:
330+
warnings.warn(
331+
f"All code cells in a MyST notebook must have the same language: {lexer}!={default_lexer}"
332+
)
333+
345334
meta = nbf.from_dict(options)
346335
source_map.append(token.map[0] + 1)
347336
notebook.cells.append(
@@ -371,14 +360,11 @@ def _flush_markdown(start_line, token, md_metadata):
371360
if add_source_map:
372361
notebook.metadata["source_map"] = source_map
373362

374-
if "kernelspec" not in notebook.metadata:
375-
for language, count in languages.most_common(1):
376-
if count:
377-
jupytext_metadata = {"main_language": language}
378-
if not notebook.metadata:
379-
jupytext_metadata["notebook_metadata_filter"] = "-all"
380-
notebook.metadata["jupytext"] = jupytext_metadata
381-
break
363+
if "kernelspec" not in notebook.metadata and default_lexer:
364+
jupytext_metadata = {"default_lexer": default_lexer}
365+
if not notebook.metadata:
366+
jupytext_metadata["notebook_metadata_filter"] = "-all"
367+
notebook.metadata["jupytext"] = jupytext_metadata
382368

383369
return notebook
384370

tests/data/notebooks/outputs/myst_to_ipynb/fenced_code_vs_code_cells.ipynb

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
],
4444
"metadata": {
4545
"jupytext": {
46-
"main_language": "python",
46+
"default_lexer": "ipython3",
4747
"notebook_metadata_filter": "-all"
4848
}
4949
},

tests/data/notebooks/outputs/myst_to_ipynb/reference_link.ipynb

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
],
3636
"metadata": {
3737
"jupytext": {
38-
"main_language": "python",
38+
"default_lexer": "ipython3",
3939
"notebook_metadata_filter": "-all"
4040
}
4141
},

tests/functional/simple_notebooks/test_ipynb_to_myst.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,10 @@ async def test_myst_representation_same_cli_or_contents_manager(
229229
line for line in text_api.splitlines() if line.startswith("```{code-cell")
230230
}
231231

232-
assert code_cells == {"```{code-cell} ipython3"}
232+
if language_info == "std":
233+
assert code_cells == {"```{code-cell} ipython3"}
234+
else:
235+
assert code_cells == {"```{code-cell}"}
233236

234237
# We get the same file with the command line jupytext
235238
tmpdir.mkdir("cli").join("notebook.ipynb").write(json.dumps(nb))

tests/unit/test_markdown_in_code_cells.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ def test_triple_backticks_in_code_cell(
5656
def test_triple_backticks_in_code_cell_myst(
5757
no_jupytext_version_number,
5858
nb=new_notebook(
59-
metadata={"main_language": "python"},
59+
metadata={"jupytext": {"default_lexer": "ipython3"}},
6060
cells=[
6161
new_code_cell(
6262
'''a = """
@@ -69,7 +69,7 @@ def test_triple_backticks_in_code_cell_myst(
6969
),
7070
text='''---
7171
jupytext:
72-
main_language: python
72+
default_lexer: ipython3
7373
---
7474
7575
````{code-cell} ipython3

0 commit comments

Comments
 (0)