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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: marimo-dev
3
- Version: 0.2.2
3
+ Version: 0.2.4
4
4
  Summary: Build and publish python packages from marimo notebooks
5
5
  Author: Deufel
6
6
  Author-email: Deufel <MDeufel13@gmail.com>
@@ -4,7 +4,7 @@ build-backend = "uv_build"
4
4
 
5
5
  [project]
6
6
  name = "marimo-dev"
7
- version = "0.2.2"
7
+ version = "0.2.4"
8
8
  description = "Build and publish python packages from marimo notebooks"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.12"
@@ -1,5 +1,5 @@
1
1
  """Build and publish python packages from marimo notebooks"""
2
- __version__ = '0.2.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
- cfg = read_config(root)
171
-
172
- nbs_dir = Path(root) / cfg.nbs
173
-
174
- wasm_dir = Path(root) / cfg.docs / 'wasm'
175
-
176
- wasm_dir.mkdir(parents=True, exist_ok=True)
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
- body = [s for s in n.body if not isinstance(s, ast.Return)]
131
- if body:
132
- src = '\n\n'.join(ast.unparse(s) for s in body)
133
- yield Node(Kind.EXP, n.name, src)
134
- return
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