33
44import ast
55import json
6+ import re
67import sys
78from collections import defaultdict
8- from typing import Any , Callable , Dict , List
9+ from typing import Any , Callable , Dict , List , Union
910
1011from marimo ._ast .compiler import compile_cell
1112from 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+
606622def _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+ )
0 commit comments