marimo-dev 0.2.2__tar.gz → 0.2.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {marimo_dev-0.2.2 → marimo_dev-0.2.4}/PKG-INFO +1 -1
- {marimo_dev-0.2.2 → marimo_dev-0.2.4}/pyproject.toml +1 -1
- {marimo_dev-0.2.2 → marimo_dev-0.2.4}/src/marimo_dev/__init__.py +3 -1
- {marimo_dev-0.2.2 → marimo_dev-0.2.4}/src/marimo_dev/build.py +6 -6
- marimo_dev-0.2.4/src/marimo_dev/cli.py +25 -0
- {marimo_dev-0.2.2 → marimo_dev-0.2.4}/src/marimo_dev/docs.py +8 -12
- {marimo_dev-0.2.2 → marimo_dev-0.2.4}/src/marimo_dev/read.py +15 -8
- {marimo_dev-0.2.2 → marimo_dev-0.2.4}/README.md +0 -0
- {marimo_dev-0.2.2 → marimo_dev-0.2.4}/src/marimo_dev/core.py +0 -0
- {marimo_dev-0.2.2 → marimo_dev-0.2.4}/src/marimo_dev/pkg.py +0 -0
- {marimo_dev-0.2.2 → marimo_dev-0.2.4}/src/marimo_dev/publish.py +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"""Build and publish python packages from marimo notebooks"""
|
|
2
|
-
__version__ = '0.2.
|
|
2
|
+
__version__ = '0.2.4'
|
|
3
3
|
__author__ = 'Deufel'
|
|
4
4
|
from .core import Config, read_config, Kind, Param, Node
|
|
5
5
|
from .read import inline_doc, parse_params, parse_hash_pipe, parse_class_params, parse_class_methods, parse_ret, src_with_decs, is_export, parse_import, parse_const, parse_export, parse_node, parse_file, read_meta, nb_name, scan
|
|
@@ -7,6 +7,7 @@ from .pkg import clean, write, write_mod, rewrite_imports, write_init
|
|
|
7
7
|
from .docs import cls_sig, fn_sig, sig, write_llms, exp_type, render_param, nb_path, render_node, render_module_page, build_docs, export_wasm, write_nojekyll, html_preview, render_index_page, Icon
|
|
8
8
|
from .build import build, tidy, nuke, get_pypi_name, extract_import_names, pep723_header, bundle
|
|
9
9
|
from .publish import publish
|
|
10
|
+
from .cli import main
|
|
10
11
|
__all__ = [
|
|
11
12
|
"Config",
|
|
12
13
|
"Icon",
|
|
@@ -26,6 +27,7 @@ __all__ = [
|
|
|
26
27
|
"html_preview",
|
|
27
28
|
"inline_doc",
|
|
28
29
|
"is_export",
|
|
30
|
+
"main",
|
|
29
31
|
"nb_name",
|
|
30
32
|
"nb_path",
|
|
31
33
|
"nuke",
|
|
@@ -69,30 +69,30 @@ def bundle(root='.', name=None):
|
|
|
69
69
|
"Bundle all notebooks into a single Python file with PEP 723 dependencies."
|
|
70
70
|
cfg = read_config(root)
|
|
71
71
|
meta, mods = scan(root)
|
|
72
|
-
|
|
72
|
+
|
|
73
73
|
# Collect all nodes
|
|
74
74
|
all_nodes = [n for _, nodes in mods for n in nodes]
|
|
75
|
-
|
|
75
|
+
|
|
76
76
|
# Extract dependencies
|
|
77
77
|
import_names = extract_import_names(all_nodes)
|
|
78
78
|
# Filter out stdlib and local modules
|
|
79
79
|
mod_names = [m for m, _ in mods]
|
|
80
80
|
external = {get_pypi_name(n) for n in import_names if n not in mod_names}
|
|
81
|
-
|
|
81
|
+
|
|
82
82
|
# Build output
|
|
83
83
|
header = pep723_header(external)
|
|
84
84
|
imports = '\n'.join(n.src for n in all_nodes if n.kind == Kind.IMP)
|
|
85
85
|
consts = '\n'.join(n.src for n in all_nodes if n.kind == Kind.CONST)
|
|
86
86
|
exports = '\n\n'.join(clean(n.src) for n in all_nodes if n.kind == Kind.EXP)
|
|
87
|
-
|
|
87
|
+
|
|
88
88
|
content = '\n\n'.join(p for p in [header, imports, consts, exports] if p.strip())
|
|
89
|
-
|
|
89
|
+
|
|
90
90
|
# Determine output path
|
|
91
91
|
if name:
|
|
92
92
|
out_path = Path(root) / name
|
|
93
93
|
else:
|
|
94
94
|
out_path = Path(root) / cfg.out / meta['name'] / '__init__.py'
|
|
95
|
-
|
|
95
|
+
|
|
96
96
|
out_path.parent.mkdir(parents=True, exist_ok=True)
|
|
97
97
|
out_path.write_text(content)
|
|
98
98
|
return f"Bundled to {out_path}"
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
from .build import build, tidy, nuke, bundle
|
|
2
|
+
from .publish import publish
|
|
3
|
+
from .docs import build_docs
|
|
4
|
+
import sys, subprocess
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
def main():
|
|
8
|
+
if len(sys.argv) < 2: print("Usage: md [build|publish|docs|tidy|nuke]"); sys.exit(1)
|
|
9
|
+
cmd = sys.argv[1]
|
|
10
|
+
if cmd == 'build':
|
|
11
|
+
print(f"Built package at: {build()}")
|
|
12
|
+
print(build_docs())
|
|
13
|
+
elif cmd == 'publish':
|
|
14
|
+
test = '--test' in sys.argv or '-t' in sys.argv
|
|
15
|
+
target = "TestPyPI" if test else "PyPI"
|
|
16
|
+
if input(f"Publish to {target}? [y/N] ").lower() != 'y': print("Aborted"); sys.exit(0)
|
|
17
|
+
publish(test=test)
|
|
18
|
+
elif cmd == 'docs': build_docs()
|
|
19
|
+
elif cmd == 'tidy': tidy()
|
|
20
|
+
elif cmd == 'nuke': nuke()
|
|
21
|
+
elif cmd == 'bundle':
|
|
22
|
+
name = sys.argv[2] if len(sys.argv) > 2 else None
|
|
23
|
+
print(bundle(name=name))
|
|
24
|
+
|
|
25
|
+
else: print(f"Unknown command: {cmd}"); sys.exit(1)
|
|
@@ -167,18 +167,14 @@ def build_docs(
|
|
|
167
167
|
(docs_path / f"{mod_name}.html").write_text(to_xml(render_module_page(mod_name, mod_nodes, mod_names, meta, root)))
|
|
168
168
|
return f"Generated index + {len(mods)} module pages in {docs_path}"
|
|
169
169
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
nbs_dir = Path(root) / cfg.nbs
|
|
173
|
-
|
|
174
|
-
wasm_dir =
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
for f in nbs_dir.glob('*.py'):
|
|
179
|
-
name = nb_name(f, root)
|
|
180
|
-
if name:
|
|
181
|
-
os.system(f'marimo export html-wasm {f} -o {wasm_dir}/{name} --mode edit')
|
|
170
|
+
def export_wasm(root='.'):
|
|
171
|
+
cfg = read_config(root)
|
|
172
|
+
nbs_dir = Path(root) / cfg.nbs
|
|
173
|
+
wasm_dir = Path(root) / cfg.docs / 'wasm'
|
|
174
|
+
wasm_dir.mkdir(parents=True, exist_ok=True)
|
|
175
|
+
for f in nbs_dir.glob('*.py'):
|
|
176
|
+
name = nb_name(f, root)
|
|
177
|
+
if name: os.system(f"marimo export html-wasm {f} -o {wasm_dir}/{name} --mode edit")
|
|
182
178
|
|
|
183
179
|
def write_nojekyll(root='.'):
|
|
184
180
|
cfg = read_config(root)
|
|
@@ -118,21 +118,28 @@ def parse_node(
|
|
|
118
118
|
): # yields Node objects for imports, constants, and exports
|
|
119
119
|
"Extract importable nodes from an AST node."
|
|
120
120
|
ls = src.splitlines()
|
|
121
|
-
|
|
121
|
+
|
|
122
122
|
# Handle setup cells
|
|
123
123
|
if isinstance(n, ast.With):
|
|
124
124
|
for s in n.body:
|
|
125
125
|
if (node := parse_import(s, ls)): yield node
|
|
126
126
|
if (node := parse_const(s, ls)): yield node
|
|
127
|
-
|
|
127
|
+
|
|
128
128
|
# Handle export-named cells (e.g. def export(): or def export_main():)
|
|
129
129
|
if isinstance(n, ast.FunctionDef) and n.name.startswith('export'):
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
130
|
+
# Check it's decorated with @app.cell, not @app.function
|
|
131
|
+
is_cell = any(
|
|
132
|
+
(isinstance(d, ast.Attribute) and d.attr == 'cell') or
|
|
133
|
+
(isinstance(d, ast.Name) and d.id == 'cell')
|
|
134
|
+
for d in n.decorator_list
|
|
135
|
+
)
|
|
136
|
+
if is_cell:
|
|
137
|
+
body = [s for s in n.body if not isinstance(s, ast.Return)]
|
|
138
|
+
if body:
|
|
139
|
+
src = '\n\n'.join(ast.unparse(s) for s in body)
|
|
140
|
+
yield Node(Kind.EXP, n.name, src)
|
|
141
|
+
return
|
|
142
|
+
|
|
136
143
|
# Handle decorated exports
|
|
137
144
|
if (node := parse_export(n, ls, cfg)): yield node
|
|
138
145
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|