Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New option cell_id_to_title #1270

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Jupytext ChangeLog
- The `rst2md` tests have been fixed by requiring `sphinx<8` ([#1266](https://github.com/mwouts/jupytext/issues/1266))

**Added**
- The Jupytext configuration has a new option `cell_id_to_title` that maps the cell id to a cell title ([#1263](https://github.com/mwouts/jupytext/issues/1263))
- Jupytext is now tested with Python 3.13 ([#1242](https://github.com/mwouts/jupytext/issues/1242)). Thanks to [Jerry James](https://github.com/jamesjer) for the suggested fixes!


Expand Down
1 change: 1 addition & 0 deletions src/jupytext/combine.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ def combine_inputs_with_outputs(nb_source, nb_outputs, fmt=None):

# Cell text is taken from the source notebook
cell.source = source_cell.source
cell.id = source_cell.id

# We also restore the cell metadata that has been filtered
cell.metadata = restore_filtered_metadata(
Expand Down
6 changes: 6 additions & 0 deletions src/jupytext/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,12 @@ class JupytextConfiguration(Configurable):
config=True,
)

cell_id_to_title = Bool(
False,
help="Map the cell id to a cell title in text formats",
config=True,
)

split_at_heading = Bool(
False,
help="Split markdown cells on headings (Markdown and R Markdown formats only)",
Expand Down
8 changes: 8 additions & 0 deletions src/jupytext/jupytext.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,11 @@ def reads(self, s, **_):
filtered_cells.append(cell)
cells = filtered_cells

if self.config.cell_id_to_title:
for cell in cells:
if "title" in cell.metadata:
cell.id = cell.metadata.pop("title").replace(" ", "_")

return new_notebook(cells=cells, metadata=metadata)

def filter_notebook(self, nb, metadata, preserve_cell_ids=False):
Expand Down Expand Up @@ -283,6 +288,9 @@ def writes(self, nb, metadata=None, **kwargs):
split_at_heading = self.fmt.get("split_at_heading", False)

for cell in nb.cells:
if self.config.cell_id_to_title and hasattr(cell, "id"):
cell.metadata = {"title": cell.id, **cell.metadata}

if looking_for_first_markdown_cell and cell.cell_type == "markdown":
cell.metadata.setdefault("cell_marker", '"""')
looking_for_first_markdown_cell = False
Expand Down
2 changes: 1 addition & 1 deletion src/jupytext/version.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
"""Jupytext's version number"""

__version__ = "1.16.4"
__version__ = "1.16.5-dev"
110 changes: 110 additions & 0 deletions tests/functional/simple_notebooks/test_cell_id_to_title.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import pytest
from nbformat.v4.nbbase import new_code_cell, new_markdown_cell, new_notebook

from jupytext.compare import compare, compare_notebooks
from jupytext.config import JupytextConfiguration
from jupytext.jupytext import reads, writes


@pytest.fixture
def notebook_with_custom_ids(python_notebook):
return new_notebook(
metadata=python_notebook.metadata,
cells=[
new_markdown_cell(
id="first_markdown_cell", source="This is a markdown cell"
),
new_code_cell(id="first_code_cell", source="1 + 1"),
],
)


@pytest.fixture
def py_light_with_custom_ids():
return """# ---
# jupyter:
# kernelspec:
# display_name: Python 3
# language: python
# name: python_kernel
# ---

# + first_markdown_cell [markdown]
# This is a markdown cell

# + first_code_cell
1 + 1
"""


@pytest.fixture
def py_percent_with_custom_ids():
return """# ---
# jupyter:
# kernelspec:
# display_name: Python 3
# language: python
# name: python_kernel
# ---

# %% first_markdown_cell [markdown]
# This is a markdown cell

# %% first_code_cell
1 + 1
"""


@pytest.fixture
def config():
c = JupytextConfiguration()
c.cell_id_to_title = True
return c


def test_cell_id_to_py_light(
notebook_with_custom_ids,
py_light_with_custom_ids,
config,
no_jupytext_version_number,
):
compare(
writes(notebook_with_custom_ids, fmt="py:light", config=config),
py_light_with_custom_ids,
)


def test_cell_id_from_py_light(
notebook_with_custom_ids,
py_light_with_custom_ids,
config,
no_jupytext_version_number,
):
compare_notebooks(
reads(py_light_with_custom_ids, fmt="py:light", config=config),
notebook_with_custom_ids,
)


def test_cell_id_to_py_percent(
notebook_with_custom_ids,
py_percent_with_custom_ids,
config,
no_jupytext_version_number,
):
compare(
writes(notebook_with_custom_ids, fmt="py:percent", config=config),
py_percent_with_custom_ids,
)


def test_cell_id_from_py_percent(
notebook_with_custom_ids,
py_percent_with_custom_ids,
config,
no_jupytext_version_number,
):
compare_notebooks(
reads(py_percent_with_custom_ids, fmt="py:percent", config=config),
notebook_with_custom_ids,
)
Loading