Skip to content

Commit cc3b282

Browse files
committed
Extract and lift inline script metadata in marimo convert
1 parent 931cc50 commit cc3b282

File tree

2 files changed

+32
-5
lines changed

2 files changed

+32
-5
lines changed

marimo/_convert/ipynb.py

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@
33

44
import ast
55
import json
6+
import re
67
import sys
78
from collections import defaultdict
8-
from typing import Any, Callable, Dict, List
9+
from typing import Any, Callable, Dict, List, Union
910

1011
from marimo._ast.compiler import compile_cell
1112
from marimo._ast.transformers import NameTransformer
@@ -603,6 +604,21 @@ def transform_strip_whitespace(sources: List[str]) -> List[str]:
603604
return [source.strip() for source in sources]
604605

605606

607+
def extract_inline_meta(script: str) -> tuple[str | None, str]:
608+
"""
609+
Extract PEP 723 metadata from a Python source.
610+
611+
Returns a tuple of the metadata comment and the remaining script.
612+
"""
613+
if match := re.search(
614+
r"(?m)^# /// (?P<type>[a-zA-Z0-9-]+)$\s(?P<content>(^#(| .*)$\s)+)^# ///$",
615+
script,
616+
):
617+
meta_comment = match.group(0)
618+
return meta_comment, script.replace(meta_comment, "").strip()
619+
return None, script
620+
621+
606622
def _transform_sources(
607623
sources: list[str], metadata: list[dict[str, Any]]
608624
) -> list[str]:
@@ -627,6 +643,7 @@ def convert_from_ipynb(raw_notebook: str) -> str:
627643
notebook = json.loads(raw_notebook)
628644
sources: List[str] = []
629645
metadata: List[Dict[str, Any]] = []
646+
inline_meta: Union[str, None] = None
630647

631648
for cell in notebook["cells"]:
632649
source = (
@@ -636,7 +653,14 @@ def convert_from_ipynb(raw_notebook: str) -> str:
636653
)
637654
if cell["cell_type"] == "markdown":
638655
source = markdown_to_marimo(source)
639-
sources.append(source)
640-
metadata.append(cell.get("metadata", {}))
656+
elif inline_meta is None:
657+
# Eagerly find PEP 723 metadata, first match wins
658+
inline_meta, source = extract_inline_meta(source)
659+
660+
if source:
661+
sources.append(source)
662+
metadata.append(cell.get("metadata", {}))
641663

642-
return generate_from_sources(_transform_sources(sources, metadata))
664+
return generate_from_sources(
665+
_transform_sources(sources, metadata), header_comments=inline_meta
666+
)

marimo/_convert/utils.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@ def markdown_to_marimo(source: str) -> str:
2323

2424

2525
def generate_from_sources(
26-
sources: list[str], config: Optional[_AppConfig] = None
26+
sources: list[str],
27+
config: Optional[_AppConfig] = None,
28+
header_comments: Optional[str] = None,
2729
) -> str:
2830
"""
2931
Given a list of Python source code,
@@ -34,4 +36,5 @@ def generate_from_sources(
3436
["__" for _ in sources],
3537
[CellConfig() for _ in range(len(sources))],
3638
config=config,
39+
header_comments=header_comments,
3740
)

0 commit comments

Comments
 (0)