marimo-export 0.0.0__tar.gz → 0.0.2__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.
Files changed (172) hide show
  1. {marimo_export-0.0.0 → marimo_export-0.0.2}/LICENSE +2 -1
  2. marimo_export-0.0.2/PKG-INFO +160 -0
  3. marimo_export-0.0.2/README.md +119 -0
  4. marimo_export-0.0.2/pyproject.toml +65 -0
  5. marimo_export-0.0.2/pyproject.toml.orig +50 -0
  6. marimo_export-0.0.2/src/marimo_export/__init__.py +76 -0
  7. marimo_export-0.0.2/src/marimo_export/_blob_asset.py +83 -0
  8. marimo_export-0.0.2/src/marimo_export/_build.py +38 -0
  9. marimo_export-0.0.2/src/marimo_export/_cell_ids.py +28 -0
  10. marimo_export-0.0.2/src/marimo_export/_cli/__init__.py +1 -0
  11. marimo_export-0.0.2/src/marimo_export/_cli/arguments.py +285 -0
  12. marimo_export-0.0.2/src/marimo_export/_cli/commands.py +227 -0
  13. marimo_export-0.0.2/src/marimo_export/_cli/errors.py +78 -0
  14. marimo_export-0.0.2/src/marimo_export/_cli/render.py +420 -0
  15. marimo_export-0.0.2/src/marimo_export/_client_protocol.py +450 -0
  16. marimo_export-0.0.2/src/marimo_export/_control_roots.py +166 -0
  17. marimo_export-0.0.2/src/marimo_export/_delivery.py +22 -0
  18. marimo_export-0.0.2/src/marimo_export/_delivery_validation.py +100 -0
  19. marimo_export-0.0.2/src/marimo_export/_diagnostics.py +103 -0
  20. marimo_export-0.0.2/src/marimo_export/_directory.py +252 -0
  21. marimo_export-0.0.2/src/marimo_export/_directory_native.py +53 -0
  22. marimo_export-0.0.2/src/marimo_export/_directory_security.py +210 -0
  23. marimo_export-0.0.2/src/marimo_export/_directory_target.py +147 -0
  24. marimo_export-0.0.2/src/marimo_export/_execution/__init__.py +31 -0
  25. marimo_export-0.0.2/src/marimo_export/_execution/plan.py +915 -0
  26. marimo_export-0.0.2/src/marimo_export/_format.py +139 -0
  27. marimo_export-0.0.2/src/marimo_export/_http_url.py +81 -0
  28. marimo_export-0.0.2/src/marimo_export/_identity.py +73 -0
  29. marimo_export-0.0.2/src/marimo_export/_json.py +683 -0
  30. marimo_export-0.0.2/src/marimo_export/_limits.py +6 -0
  31. marimo_export-0.0.2/src/marimo_export/_marimo/__init__.py +1 -0
  32. marimo_export-0.0.2/src/marimo_export/_marimo/anywidget.py +22 -0
  33. marimo_export-0.0.2/src/marimo_export/_marimo/blob.py +14 -0
  34. marimo_export-0.0.2/src/marimo_export/_marimo/bridge.py +492 -0
  35. marimo_export-0.0.2/src/marimo_export/_marimo/capabilities.py +201 -0
  36. marimo_export-0.0.2/src/marimo_export/_marimo/compat/__init__.py +1 -0
  37. marimo_export-0.0.2/src/marimo_export/_marimo/compat/anywidget.py +320 -0
  38. marimo_export-0.0.2/src/marimo_export/_marimo/compat/anywidget_assets.py +853 -0
  39. marimo_export-0.0.2/src/marimo_export/_marimo/compat/blob.py +24 -0
  40. marimo_export-0.0.2/src/marimo_export/_marimo/compat/cache/__init__.py +3 -0
  41. marimo_export-0.0.2/src/marimo_export/_marimo/compat/cache/attempts.py +218 -0
  42. marimo_export-0.0.2/src/marimo_export/_marimo/compat/cache/barrier.py +38 -0
  43. marimo_export-0.0.2/src/marimo_export/_marimo/compat/cache/host.py +247 -0
  44. marimo_export-0.0.2/src/marimo_export/_marimo/compat/cache/lifecycle.py +52 -0
  45. marimo_export-0.0.2/src/marimo_export/_marimo/compat/cache/loader.py +65 -0
  46. marimo_export-0.0.2/src/marimo_export/_marimo/compat/cache/patch.py +218 -0
  47. marimo_export-0.0.2/src/marimo_export/_marimo/compat/cache/probe.py +159 -0
  48. marimo_export-0.0.2/src/marimo_export/_marimo/compat/cache/receipts.py +199 -0
  49. marimo_export-0.0.2/src/marimo_export/_marimo/compat/child_run.py +539 -0
  50. marimo_export-0.0.2/src/marimo_export/_marimo/compat/execution.py +570 -0
  51. marimo_export-0.0.2/src/marimo_export/_marimo/compat/exporter_identity.py +314 -0
  52. marimo_export-0.0.2/src/marimo_export/_marimo/compat/exporters.py +305 -0
  53. marimo_export-0.0.2/src/marimo_export/_marimo/compat/file_closure.py +436 -0
  54. marimo_export-0.0.2/src/marimo_export/_marimo/compat/inspection.py +714 -0
  55. marimo_export-0.0.2/src/marimo_export/_marimo/compat/kernel.py +39 -0
  56. marimo_export-0.0.2/src/marimo_export/_marimo/compat/managed_kernel.py +56 -0
  57. marimo_export-0.0.2/src/marimo_export/_marimo/compat/managed_server.py +82 -0
  58. marimo_export-0.0.2/src/marimo_export/_marimo/compat/observations.py +303 -0
  59. marimo_export-0.0.2/src/marimo_export/_marimo/compat/output_data.py +572 -0
  60. marimo_export-0.0.2/src/marimo_export/_marimo/compat/projections.py +475 -0
  61. marimo_export-0.0.2/src/marimo_export/_marimo/compat/receipts.py +259 -0
  62. marimo_export-0.0.2/src/marimo_export/_marimo/compat/release.json +44 -0
  63. marimo_export-0.0.2/src/marimo_export/_marimo/compat/replay.py +277 -0
  64. marimo_export-0.0.2/src/marimo_export/_marimo/compat/transfer.py +20 -0
  65. marimo_export-0.0.2/src/marimo_export/_marimo/composition.py +98 -0
  66. marimo_export-0.0.2/src/marimo_export/_marimo/entrypoints.py +31 -0
  67. marimo_export-0.0.2/src/marimo_export/_marimo/managed_server.py +6 -0
  68. marimo_export-0.0.2/src/marimo_export/_marimo/transfer.py +439 -0
  69. marimo_export-0.0.2/src/marimo_export/_media_type.py +136 -0
  70. marimo_export-0.0.2/src/marimo_export/_notebook.py +96 -0
  71. marimo_export-0.0.2/src/marimo_export/_observations/__init__.py +1 -0
  72. marimo_export-0.0.2/src/marimo_export/_observations/candidates.py +97 -0
  73. marimo_export-0.0.2/src/marimo_export/_observations/ledger.py +291 -0
  74. marimo_export-0.0.2/src/marimo_export/_observations/queue.py +120 -0
  75. marimo_export-0.0.2/src/marimo_export/_observations/source.py +46 -0
  76. marimo_export-0.0.2/src/marimo_export/_portable.py +142 -0
  77. marimo_export-0.0.2/src/marimo_export/_prepared_integrity.py +163 -0
  78. marimo_export-0.0.2/src/marimo_export/_publication.py +394 -0
  79. marimo_export-0.0.2/src/marimo_export/_remote/__init__.py +15 -0
  80. marimo_export-0.0.2/src/marimo_export/_remote/auth.py +105 -0
  81. marimo_export-0.0.2/src/marimo_export/_remote/client.py +822 -0
  82. marimo_export-0.0.2/src/marimo_export/_remote/managed.py +919 -0
  83. marimo_export-0.0.2/src/marimo_export/_remote/sse.py +128 -0
  84. marimo_export-0.0.2/src/marimo_export/_remote/windows_job.py +210 -0
  85. marimo_export-0.0.2/src/marimo_export/_repository/__init__.py +1 -0
  86. marimo_export-0.0.2/src/marimo_export/_repository/artifact_access.py +244 -0
  87. marimo_export-0.0.2/src/marimo_export/_repository/artifact_commit.py +289 -0
  88. marimo_export-0.0.2/src/marimo_export/_repository/artifact_context.py +34 -0
  89. marimo_export-0.0.2/src/marimo_export/_repository/artifact_lifecycle.py +569 -0
  90. marimo_export-0.0.2/src/marimo_export/_repository/artifacts.py +162 -0
  91. marimo_export-0.0.2/src/marimo_export/_repository/capabilities.py +61 -0
  92. marimo_export-0.0.2/src/marimo_export/_repository/files.py +562 -0
  93. marimo_export-0.0.2/src/marimo_export/_repository/handles.py +353 -0
  94. marimo_export-0.0.2/src/marimo_export/_repository/leases.py +621 -0
  95. marimo_export-0.0.2/src/marimo_export/_repository/models.py +398 -0
  96. marimo_export-0.0.2/src/marimo_export/_repository/observations.py +129 -0
  97. marimo_export-0.0.2/src/marimo_export/_repository/paths.py +114 -0
  98. marimo_export-0.0.2/src/marimo_export/_repository/preparation.py +310 -0
  99. marimo_export-0.0.2/src/marimo_export/_repository/sqlite/__init__.py +1 -0
  100. marimo_export-0.0.2/src/marimo_export/_repository/sqlite/artifacts.py +148 -0
  101. marimo_export-0.0.2/src/marimo_export/_repository/sqlite/catalog.py +631 -0
  102. marimo_export-0.0.2/src/marimo_export/_repository/sqlite/generations.py +325 -0
  103. marimo_export-0.0.2/src/marimo_export/_repository/sqlite/leases.py +351 -0
  104. marimo_export-0.0.2/src/marimo_export/_repository/sqlite/maintenance.py +177 -0
  105. marimo_export-0.0.2/src/marimo_export/_repository/sqlite/observations.py +362 -0
  106. marimo_export-0.0.2/src/marimo_export/_repository/sqlite/open.py +68 -0
  107. marimo_export-0.0.2/src/marimo_export/_repository/sqlite/prepared_states.py +248 -0
  108. marimo_export-0.0.2/src/marimo_export/_repository/sqlite/records.py +91 -0
  109. marimo_export-0.0.2/src/marimo_export/_repository/sqlite/recovery.py +549 -0
  110. marimo_export-0.0.2/src/marimo_export/_repository/sqlite/retention.py +340 -0
  111. marimo_export-0.0.2/src/marimo_export/_repository/sqlite/retired.py +58 -0
  112. marimo_export-0.0.2/src/marimo_export/_repository/sqlite/schema.py +343 -0
  113. marimo_export-0.0.2/src/marimo_export/_repository/sqlite/status.py +35 -0
  114. marimo_export-0.0.2/src/marimo_export/_secure_io.py +390 -0
  115. marimo_export-0.0.2/src/marimo_export/_selector.py +106 -0
  116. marimo_export-0.0.2/src/marimo_export/_services/__init__.py +1 -0
  117. marimo_export-0.0.2/src/marimo_export/_services/capture_export.py +225 -0
  118. marimo_export-0.0.2/src/marimo_export/_services/export_artifacts.py +211 -0
  119. marimo_export-0.0.2/src/marimo_export/_services/identity.py +426 -0
  120. marimo_export-0.0.2/src/marimo_export/_services/plan_export.py +250 -0
  121. marimo_export-0.0.2/src/marimo_export/_services/plan_wire.py +171 -0
  122. marimo_export-0.0.2/src/marimo_export/_services/preparation_support.py +141 -0
  123. marimo_export-0.0.2/src/marimo_export/_services/prepare_export.py +160 -0
  124. marimo_export-0.0.2/src/marimo_export/_services/state_preparation.py +182 -0
  125. marimo_export-0.0.2/src/marimo_export/_services/write_export.py +152 -0
  126. marimo_export-0.0.2/src/marimo_export/_snapshot.py +307 -0
  127. marimo_export-0.0.2/src/marimo_export/_writer.py +243 -0
  128. marimo_export-0.0.2/src/marimo_export/cli.py +97 -0
  129. marimo_export-0.0.2/src/marimo_export/client.py +364 -0
  130. marimo_export-0.0.2/src/marimo_export/delivery.py +240 -0
  131. marimo_export-0.0.2/src/marimo_export/descriptors.py +525 -0
  132. marimo_export-0.0.2/src/marimo_export/diagnostics.py +102 -0
  133. marimo_export-0.0.2/src/marimo_export/errors.py +119 -0
  134. marimo_export-0.0.2/src/marimo_export/exporters/__init__.py +5 -0
  135. marimo_export-0.0.2/src/marimo_export/exporters/_anywidget_payload.py +574 -0
  136. marimo_export-0.0.2/src/marimo_export/exporters/_definitions.py +213 -0
  137. marimo_export-0.0.2/src/marimo_export/exporters/_optional.py +15 -0
  138. marimo_export-0.0.2/src/marimo_export/exporters/_runtime/__init__.py +1 -0
  139. marimo_export-0.0.2/src/marimo_export/exporters/_runtime/altair.py +68 -0
  140. marimo_export-0.0.2/src/marimo_export/exporters/_runtime/anywidget.py +21 -0
  141. marimo_export-0.0.2/src/marimo_export/exporters/_runtime/blob.py +52 -0
  142. marimo_export-0.0.2/src/marimo_export/exporters/_runtime/parquet.py +70 -0
  143. marimo_export-0.0.2/src/marimo_export/exporters/_spec.py +139 -0
  144. marimo_export-0.0.2/src/marimo_export/exporters/altair.py +18 -0
  145. marimo_export-0.0.2/src/marimo_export/exporters/anywidget.py +12 -0
  146. marimo_export-0.0.2/src/marimo_export/exporters/blob.py +61 -0
  147. marimo_export-0.0.2/src/marimo_export/exporters/parquet.py +26 -0
  148. marimo_export-0.0.2/src/marimo_export/index.py +572 -0
  149. marimo_export-0.0.2/src/marimo_export/inspection.py +381 -0
  150. marimo_export-0.0.2/src/marimo_export/integration.py +119 -0
  151. marimo_export-0.0.2/src/marimo_export/limits.py +44 -0
  152. marimo_export-0.0.2/src/marimo_export/manifest.py +39 -0
  153. marimo_export-0.0.2/src/marimo_export/observations.py +105 -0
  154. marimo_export-0.0.2/src/marimo_export/outputs.py +64 -0
  155. marimo_export-0.0.2/src/marimo_export/planning.py +272 -0
  156. marimo_export-0.0.2/src/marimo_export/prepared.py +503 -0
  157. marimo_export-0.0.2/src/marimo_export/producer.py +318 -0
  158. marimo_export-0.0.2/src/marimo_export/progress.py +108 -0
  159. marimo_export-0.0.2/src/marimo_export/publication.py +176 -0
  160. marimo_export-0.0.2/src/marimo_export/py.typed +0 -0
  161. marimo_export-0.0.2/src/marimo_export/reader.py +762 -0
  162. marimo_export-0.0.2/src/marimo_export/repository.py +214 -0
  163. marimo_export-0.0.2/src/marimo_export/result.py +265 -0
  164. marimo_export-0.0.2/src/marimo_export/sessions.py +25 -0
  165. marimo_export-0.0.2/src/marimo_export/spec.py +1097 -0
  166. marimo_export-0.0.2/src/marimo_export/verification.py +15 -0
  167. marimo_export-0.0.2/src/marimo_export/wire.py +95 -0
  168. marimo_export-0.0.0/.gitignore +0 -49
  169. marimo_export-0.0.0/PKG-INFO +0 -14
  170. marimo_export-0.0.0/README.md +0 -3
  171. marimo_export-0.0.0/pyproject.toml +0 -19
  172. marimo_export-0.0.0/src/marimo_export/__init__.py +0 -1
@@ -1,3 +1,4 @@
1
+
1
2
  Apache License
2
3
  Version 2.0, January 2004
3
4
  http://www.apache.org/licenses/
@@ -186,7 +187,7 @@
186
187
  same "printed page" as the copyright notice for easier
187
188
  identification within third-party archives.
188
189
 
189
- Copyright [yyyy] [name of copyright owner]
190
+ Copyright 2026 marimo team
190
191
 
191
192
  Licensed under the Apache License, Version 2.0 (the "License");
192
193
  you may not use this file except in compliance with the License.
@@ -0,0 +1,160 @@
1
+ Metadata-Version: 2.4
2
+ Name: marimo-export
3
+ Version: 0.0.2
4
+ Summary: Precompute and read verified exports of selected marimo notebook results.
5
+ Keywords: cache,export,marimo,notebook
6
+ Author: marimo team
7
+ License-Expression: Apache-2.0
8
+ License-File: LICENSE
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Programming Language :: Python :: 3 :: Only
11
+ Classifier: Programming Language :: Python :: 3.10
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Programming Language :: Python :: 3.13
15
+ Classifier: Programming Language :: Python :: 3.14
16
+ Requires-Dist: cryptography==50.0.1
17
+ Requires-Dist: idna==3.19
18
+ Requires-Dist: marimo==0.24.0
19
+ Requires-Dist: msgspec>=0.20
20
+ Requires-Dist: numpy>=1.23.5
21
+ Requires-Dist: pydantic>=2,<3
22
+ Requires-Dist: pyyaml>=6.0.1
23
+ Requires-Dist: altair>=5,<7 ; extra == 'all'
24
+ Requires-Dist: anywidget>=0.9,<1 ; extra == 'all'
25
+ Requires-Dist: pyarrow>=15 ; extra == 'all'
26
+ Requires-Dist: vl-convert-python>=1.8 ; extra == 'all'
27
+ Requires-Dist: anywidget>=0.9,<1 ; extra == 'anywidget'
28
+ Requires-Dist: altair>=5,<7 ; extra == 'charts'
29
+ Requires-Dist: vl-convert-python>=1.8 ; extra == 'charts'
30
+ Requires-Dist: pyarrow>=15 ; extra == 'parquet'
31
+ Requires-Python: >=3.10
32
+ Project-URL: Homepage, https://marimo-team.github.io/marimo-export/
33
+ Project-URL: Documentation, https://marimo-team.github.io/marimo-export/
34
+ Project-URL: Repository, https://github.com/marimo-team/marimo-export
35
+ Project-URL: Issues, https://github.com/marimo-team/marimo-export/issues
36
+ Provides-Extra: all
37
+ Provides-Extra: anywidget
38
+ Provides-Extra: charts
39
+ Provides-Extra: parquet
40
+ Description-Content-Type: text/markdown
41
+
42
+ # marimo-export
43
+
44
+ The `marimo-export` Python package plans, prepares, writes, opens, and verifies
45
+ notebook exports from saved [marimo](https://marimo.io/) notebooks or named live sessions.
46
+
47
+ [uv](https://docs.astral.sh/uv/) adds the package to a Python project:
48
+
49
+ ```bash
50
+ uv add marimo-export
51
+ ```
52
+
53
+ The package requires Python 3.10 or newer, is tested on Python 3.10 through
54
+ 3.14, and installs the marimo release pinned by its package metadata.
55
+
56
+ The examples use the repository's
57
+ [`report.py`](https://github.com/marimo-team/marimo-export/blob/main/examples/quickstart/report.py)
58
+ and
59
+ [`report.export.yaml`](https://github.com/marimo-team/marimo-export/blob/main/examples/quickstart/report.export.yaml).
60
+ Download both files into the current directory before running them.
61
+
62
+ ## Run the CLI from PyPI
63
+
64
+ ```bash
65
+ uvx marimo-export build report.py \
66
+ --spec report.export.yaml \
67
+ --output dist/report
68
+ uvx marimo-export verify dist/report
69
+ ```
70
+
71
+ `build` prepares missing states, writes the export, verifies every declared
72
+ asset, and closes the notebook process it started.
73
+
74
+ ## Build from Python
75
+
76
+ ```python
77
+ from pathlib import Path
78
+
79
+ from marimo_export import ExportSpec, build
80
+
81
+ Path("dist").mkdir(exist_ok=True)
82
+ spec = ExportSpec.from_file("report.export.yaml")
83
+ result = build("report.py", spec=spec, output="dist/report")
84
+
85
+ print(result.path)
86
+ ```
87
+
88
+ A matching later call with a new destination or `replace=True` can reuse the
89
+ prepared export before notebook startup.
90
+
91
+ ## Read the export
92
+
93
+ ```python
94
+ from marimo_export import open_export, verify_export
95
+
96
+ export = open_export("dist/report")
97
+ summary = export.state("monthly").output("summary").json()
98
+ verified = verify_export("dist/report")
99
+
100
+ print(dict(summary))
101
+ print(verified.states, verified.outputs)
102
+ ```
103
+
104
+ ```text
105
+ {'days': 30, 'label': 'Last 30 days'}
106
+ 2 2
107
+ ```
108
+
109
+ Opening validates canonical `index.json` and leaves asset data lazy. Complete
110
+ verification reads every declared asset and returns exported-state,
111
+ state-output-pair, unique-asset, and verified-byte counts. The example has two
112
+ states and one output name, so `verified.outputs` is `2`.
113
+
114
+ ## Capture a live session
115
+
116
+ After opening `report.py` in a running marimo server, `capture()` borrows the
117
+ named session and returns a leased `PreparedExport`:
118
+
119
+ ```python
120
+ from marimo_export import ExportSpec, capture
121
+
122
+ spec = ExportSpec.from_file("report.export.yaml")
123
+
124
+ with capture(
125
+ "http://127.0.0.1:2718",
126
+ session="SESSION_ID",
127
+ spec=spec,
128
+ ) as prepared:
129
+ prepared.write("dist/report", replace=True)
130
+ ```
131
+
132
+ `replace=True` replaces the complete destination directory. Keep unrelated
133
+ application files outside `dist/report`.
134
+
135
+ Use `marimo-export inspect SERVER` to find session IDs. The selected session
136
+ remains active after capture. The live notebook environment and the client must
137
+ load the same marimo-export implementation and exporter dependencies.
138
+
139
+ ## Install output exporters
140
+
141
+ Install the optional families selected by your `ExportSpec`:
142
+
143
+ ```bash
144
+ uv add "marimo-export[charts,parquet,anywidget]"
145
+ ```
146
+
147
+ The base package supports JSON, native marimo values, and custom exporter
148
+ callables. The optional families add Altair and PNG charts, Parquet tables, and
149
+ AnyWidget bundles.
150
+
151
+ ## Learn the complete API
152
+
153
+ - [Getting started](https://marimo-team.github.io/marimo-export/guide/getting-started)
154
+ - [Python API](https://marimo-team.github.io/marimo-export/reference/python-api)
155
+ - [Choose states and outputs](https://marimo-team.github.io/marimo-export/guide/choose-states)
156
+ - [CLI reference](https://marimo-team.github.io/marimo-export/reference/cli)
157
+ - [Use notebook exports with agents](https://marimo-team.github.io/marimo-export/guide/agents-and-automation)
158
+
159
+ Preparing an export executes notebook code with the notebook environment's file,
160
+ credential, network, and package access.
@@ -0,0 +1,119 @@
1
+ # marimo-export
2
+
3
+ The `marimo-export` Python package plans, prepares, writes, opens, and verifies
4
+ notebook exports from saved [marimo](https://marimo.io/) notebooks or named live sessions.
5
+
6
+ [uv](https://docs.astral.sh/uv/) adds the package to a Python project:
7
+
8
+ ```bash
9
+ uv add marimo-export
10
+ ```
11
+
12
+ The package requires Python 3.10 or newer, is tested on Python 3.10 through
13
+ 3.14, and installs the marimo release pinned by its package metadata.
14
+
15
+ The examples use the repository's
16
+ [`report.py`](https://github.com/marimo-team/marimo-export/blob/main/examples/quickstart/report.py)
17
+ and
18
+ [`report.export.yaml`](https://github.com/marimo-team/marimo-export/blob/main/examples/quickstart/report.export.yaml).
19
+ Download both files into the current directory before running them.
20
+
21
+ ## Run the CLI from PyPI
22
+
23
+ ```bash
24
+ uvx marimo-export build report.py \
25
+ --spec report.export.yaml \
26
+ --output dist/report
27
+ uvx marimo-export verify dist/report
28
+ ```
29
+
30
+ `build` prepares missing states, writes the export, verifies every declared
31
+ asset, and closes the notebook process it started.
32
+
33
+ ## Build from Python
34
+
35
+ ```python
36
+ from pathlib import Path
37
+
38
+ from marimo_export import ExportSpec, build
39
+
40
+ Path("dist").mkdir(exist_ok=True)
41
+ spec = ExportSpec.from_file("report.export.yaml")
42
+ result = build("report.py", spec=spec, output="dist/report")
43
+
44
+ print(result.path)
45
+ ```
46
+
47
+ A matching later call with a new destination or `replace=True` can reuse the
48
+ prepared export before notebook startup.
49
+
50
+ ## Read the export
51
+
52
+ ```python
53
+ from marimo_export import open_export, verify_export
54
+
55
+ export = open_export("dist/report")
56
+ summary = export.state("monthly").output("summary").json()
57
+ verified = verify_export("dist/report")
58
+
59
+ print(dict(summary))
60
+ print(verified.states, verified.outputs)
61
+ ```
62
+
63
+ ```text
64
+ {'days': 30, 'label': 'Last 30 days'}
65
+ 2 2
66
+ ```
67
+
68
+ Opening validates canonical `index.json` and leaves asset data lazy. Complete
69
+ verification reads every declared asset and returns exported-state,
70
+ state-output-pair, unique-asset, and verified-byte counts. The example has two
71
+ states and one output name, so `verified.outputs` is `2`.
72
+
73
+ ## Capture a live session
74
+
75
+ After opening `report.py` in a running marimo server, `capture()` borrows the
76
+ named session and returns a leased `PreparedExport`:
77
+
78
+ ```python
79
+ from marimo_export import ExportSpec, capture
80
+
81
+ spec = ExportSpec.from_file("report.export.yaml")
82
+
83
+ with capture(
84
+ "http://127.0.0.1:2718",
85
+ session="SESSION_ID",
86
+ spec=spec,
87
+ ) as prepared:
88
+ prepared.write("dist/report", replace=True)
89
+ ```
90
+
91
+ `replace=True` replaces the complete destination directory. Keep unrelated
92
+ application files outside `dist/report`.
93
+
94
+ Use `marimo-export inspect SERVER` to find session IDs. The selected session
95
+ remains active after capture. The live notebook environment and the client must
96
+ load the same marimo-export implementation and exporter dependencies.
97
+
98
+ ## Install output exporters
99
+
100
+ Install the optional families selected by your `ExportSpec`:
101
+
102
+ ```bash
103
+ uv add "marimo-export[charts,parquet,anywidget]"
104
+ ```
105
+
106
+ The base package supports JSON, native marimo values, and custom exporter
107
+ callables. The optional families add Altair and PNG charts, Parquet tables, and
108
+ AnyWidget bundles.
109
+
110
+ ## Learn the complete API
111
+
112
+ - [Getting started](https://marimo-team.github.io/marimo-export/guide/getting-started)
113
+ - [Python API](https://marimo-team.github.io/marimo-export/reference/python-api)
114
+ - [Choose states and outputs](https://marimo-team.github.io/marimo-export/guide/choose-states)
115
+ - [CLI reference](https://marimo-team.github.io/marimo-export/reference/cli)
116
+ - [Use notebook exports with agents](https://marimo-team.github.io/marimo-export/guide/agents-and-automation)
117
+
118
+ Preparing an export executes notebook code with the notebook environment's file,
119
+ credential, network, and package access.
@@ -0,0 +1,65 @@
1
+ [build-system]
2
+ requires = ["uv_build>=0.11.28,<0.13.0"]
3
+ build-backend = "uv_build"
4
+
5
+ [project]
6
+ name = "marimo-export"
7
+ version = "0.0.2"
8
+ description = "Precompute and read verified exports of selected marimo notebook results."
9
+ readme = "README.md"
10
+ license = "Apache-2.0"
11
+ license-files = ["LICENSE"]
12
+ requires-python = ">=3.10"
13
+ dependencies = [
14
+ "cryptography==50.0.1",
15
+ "idna==3.19",
16
+ "marimo==0.24.0",
17
+ "msgspec>=0.20",
18
+ "numpy>=1.23.5",
19
+ "pydantic>=2,<3",
20
+ "PyYAML>=6.0.1",
21
+ ]
22
+ keywords = [
23
+ "cache",
24
+ "export",
25
+ "marimo",
26
+ "notebook",
27
+ ]
28
+ classifiers = [
29
+ "Programming Language :: Python :: 3",
30
+ "Programming Language :: Python :: 3 :: Only",
31
+ "Programming Language :: Python :: 3.10",
32
+ "Programming Language :: Python :: 3.11",
33
+ "Programming Language :: Python :: 3.12",
34
+ "Programming Language :: Python :: 3.13",
35
+ "Programming Language :: Python :: 3.14",
36
+ ]
37
+
38
+ [[project.authors]]
39
+ name = "marimo team"
40
+
41
+ [project.urls]
42
+ Homepage = "https://marimo-team.github.io/marimo-export/"
43
+ Documentation = "https://marimo-team.github.io/marimo-export/"
44
+ Repository = "https://github.com/marimo-team/marimo-export"
45
+ Issues = "https://github.com/marimo-team/marimo-export/issues"
46
+
47
+ [project.scripts]
48
+ marimo-export = "marimo_export.cli:main"
49
+
50
+ [project.entry-points."marimo.kernel.lifespan"]
51
+ marimo-export = "marimo_export._marimo.entrypoints:kernel_lifespan"
52
+
53
+ [project.optional-dependencies]
54
+ anywidget = ["anywidget>=0.9,<1"]
55
+ charts = [
56
+ "altair>=5,<7",
57
+ "vl-convert-python>=1.8",
58
+ ]
59
+ parquet = ["pyarrow>=15"]
60
+ all = [
61
+ "altair>=5,<7",
62
+ "anywidget>=0.9,<1",
63
+ "pyarrow>=15",
64
+ "vl-convert-python>=1.8",
65
+ ]
@@ -0,0 +1,50 @@
1
+ [build-system]
2
+ requires = ["uv_build>=0.11.28,<0.13.0"]
3
+ build-backend = "uv_build"
4
+
5
+ [project]
6
+ name = "marimo-export"
7
+ version = "0.0.2"
8
+ description = "Precompute and read verified exports of selected marimo notebook results."
9
+ readme = "README.md"
10
+ license = "Apache-2.0"
11
+ license-files = ["LICENSE"]
12
+ authors = [{ name = "marimo team" }]
13
+ requires-python = ">=3.10"
14
+ dependencies = [
15
+ "cryptography==50.0.1",
16
+ "idna==3.19",
17
+ "marimo==0.24.0",
18
+ "msgspec>=0.20",
19
+ "numpy>=1.23.5",
20
+ "pydantic>=2,<3",
21
+ "PyYAML>=6.0.1",
22
+ ]
23
+ keywords = ["cache", "export", "marimo", "notebook"]
24
+ classifiers = [
25
+ "Programming Language :: Python :: 3",
26
+ "Programming Language :: Python :: 3 :: Only",
27
+ "Programming Language :: Python :: 3.10",
28
+ "Programming Language :: Python :: 3.11",
29
+ "Programming Language :: Python :: 3.12",
30
+ "Programming Language :: Python :: 3.13",
31
+ "Programming Language :: Python :: 3.14",
32
+ ]
33
+
34
+ [project.urls]
35
+ Homepage = "https://marimo-team.github.io/marimo-export/"
36
+ Documentation = "https://marimo-team.github.io/marimo-export/"
37
+ Repository = "https://github.com/marimo-team/marimo-export"
38
+ Issues = "https://github.com/marimo-team/marimo-export/issues"
39
+
40
+ [project.scripts]
41
+ marimo-export = "marimo_export.cli:main"
42
+
43
+ [project.entry-points."marimo.kernel.lifespan"]
44
+ marimo-export = "marimo_export._marimo.entrypoints:kernel_lifespan"
45
+
46
+ [project.optional-dependencies]
47
+ anywidget = ["anywidget>=0.9,<1"]
48
+ charts = ["altair>=5,<7", "vl-convert-python>=1.8"]
49
+ parquet = ["pyarrow>=15"]
50
+ all = ["altair>=5,<7", "anywidget>=0.9,<1", "pyarrow>=15", "vl-convert-python>=1.8"]
@@ -0,0 +1,76 @@
1
+ """Create and read verified exports of prepared marimo notebook results."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from importlib import import_module
6
+ from typing import TYPE_CHECKING, Any
7
+
8
+ from marimo_export._identity import implementation_identity as _implementation_identity
9
+
10
+ _LOADED_SOURCE_IDENTITY = _implementation_identity()
11
+
12
+ if TYPE_CHECKING:
13
+ from marimo_export._build import build
14
+ from marimo_export._services.capture_export import capture
15
+ from marimo_export._services.plan_export import plan
16
+ from marimo_export._services.prepare_export import prepare
17
+ from marimo_export.planning import ExportPlan
18
+ from marimo_export.prepared import PreparedExport
19
+ from marimo_export.progress import ProgressEvent
20
+ from marimo_export.reader import NotebookExport, open_export
21
+ from marimo_export.repository import ExportRepository
22
+ from marimo_export.result import ExportResult
23
+ from marimo_export.spec import ExportSpec, OutputSpec, StateSpace
24
+ from marimo_export.verification import VerificationResult, verify_export
25
+
26
+ _EXPORTS = {
27
+ "ExportPlan": ("marimo_export.planning", "ExportPlan"),
28
+ "ExportRepository": ("marimo_export.repository", "ExportRepository"),
29
+ "ExportResult": ("marimo_export.result", "ExportResult"),
30
+ "ExportSpec": ("marimo_export.spec", "ExportSpec"),
31
+ "NotebookExport": ("marimo_export.reader", "NotebookExport"),
32
+ "OutputSpec": ("marimo_export.spec", "OutputSpec"),
33
+ "PreparedExport": ("marimo_export.prepared", "PreparedExport"),
34
+ "ProgressEvent": ("marimo_export.progress", "ProgressEvent"),
35
+ "StateSpace": ("marimo_export.spec", "StateSpace"),
36
+ "VerificationResult": ("marimo_export.verification", "VerificationResult"),
37
+ "build": ("marimo_export._build", "build"),
38
+ "capture": ("marimo_export._services.capture_export", "capture"),
39
+ "open_export": ("marimo_export.reader", "open_export"),
40
+ "plan": ("marimo_export._services.plan_export", "plan"),
41
+ "prepare": ("marimo_export._services.prepare_export", "prepare"),
42
+ "verify_export": ("marimo_export.verification", "verify_export"),
43
+ }
44
+
45
+ __all__ = (
46
+ "ExportPlan",
47
+ "ExportRepository",
48
+ "ExportResult",
49
+ "ExportSpec",
50
+ "NotebookExport",
51
+ "OutputSpec",
52
+ "PreparedExport",
53
+ "ProgressEvent",
54
+ "StateSpace",
55
+ "VerificationResult",
56
+ "build",
57
+ "capture",
58
+ "open_export",
59
+ "plan",
60
+ "prepare",
61
+ "verify_export",
62
+ )
63
+
64
+
65
+ def __getattr__(name: str) -> Any:
66
+ try:
67
+ module_name, attribute = _EXPORTS[name]
68
+ except KeyError as error:
69
+ raise AttributeError(f"module {__name__!r} has no attribute {name!r}") from error
70
+ value = getattr(import_module(module_name), attribute)
71
+ globals()[name] = value
72
+ return value
73
+
74
+
75
+ def __dir__() -> list[str]:
76
+ return sorted({*globals(), *__all__})
@@ -0,0 +1,83 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+ from typing import cast
5
+
6
+ import msgspec
7
+
8
+ from marimo_export._json import JsonObject, canonical_bytes, portable_json_object
9
+ from marimo_export._media_type import MAX_BLOB_METADATA_JSON_BYTES, validate_media_type
10
+ from marimo_export._portable import validate_portable_basename
11
+
12
+ _FIELDS = ("data", "media_type", "filename", "metadata")
13
+
14
+
15
+ @dataclass(frozen=True, slots=True)
16
+ class BlobAssetEnvelope:
17
+ """The verified native marimo BlobAsset MessagePack envelope."""
18
+
19
+ data: bytes
20
+ media_type: str | None
21
+ filename: str | None
22
+ metadata: JsonObject
23
+
24
+
25
+ def decode_blob_asset(
26
+ data: bytes,
27
+ *,
28
+ maximum_bytes: int | None = None,
29
+ ) -> BlobAssetEnvelope:
30
+ """Strictly decode the exact MessagePack shape emitted by marimo."""
31
+
32
+ if not isinstance(data, bytes):
33
+ raise TypeError("BlobAsset MessagePack must be bytes")
34
+ if maximum_bytes is not None and (
35
+ not isinstance(maximum_bytes, int) or isinstance(maximum_bytes, bool) or maximum_bytes <= 0
36
+ ):
37
+ raise TypeError("maximum_bytes must be a positive integer")
38
+ if maximum_bytes is not None and len(data) > maximum_bytes:
39
+ raise ValueError(f"BlobAsset MessagePack exceeds the {maximum_bytes} byte limit")
40
+
41
+ try:
42
+ decoded = msgspec.msgpack.decode(data)
43
+ except msgspec.DecodeError as error:
44
+ raise ValueError("BlobAsset is invalid MessagePack") from error
45
+ if not isinstance(decoded, dict) or tuple(decoded) != _FIELDS:
46
+ raise ValueError("BlobAsset does not use the native four-field envelope")
47
+ if msgspec.msgpack.encode(decoded) != data:
48
+ raise ValueError("BlobAsset MessagePack is not canonical")
49
+
50
+ payload = decoded["data"]
51
+ media_type = decoded["media_type"]
52
+ filename = decoded["filename"]
53
+ metadata = decoded["metadata"]
54
+ if not isinstance(payload, bytes):
55
+ raise ValueError("BlobAsset data must be bytes")
56
+ if media_type is not None:
57
+ try:
58
+ media_type = validate_media_type(media_type, "BlobAsset media_type")
59
+ except (TypeError, ValueError) as error:
60
+ raise ValueError("BlobAsset media_type is invalid") from error
61
+ if filename is not None:
62
+ try:
63
+ filename = validate_portable_basename(filename, "BlobAsset filename")
64
+ except (TypeError, ValueError) as error:
65
+ raise ValueError("BlobAsset filename is invalid") from error
66
+ try:
67
+ metadata_object = portable_json_object(metadata, "BlobAsset metadata")
68
+ except (TypeError, ValueError) as error:
69
+ raise ValueError("BlobAsset metadata must be portable JSON") from error
70
+ if len(canonical_bytes(metadata_object)) > MAX_BLOB_METADATA_JSON_BYTES:
71
+ raise ValueError(
72
+ f"BlobAsset metadata exceeds {MAX_BLOB_METADATA_JSON_BYTES} canonical JSON bytes"
73
+ )
74
+
75
+ return BlobAssetEnvelope(
76
+ data=payload,
77
+ media_type=cast(str | None, media_type),
78
+ filename=cast(str | None, filename),
79
+ metadata=metadata_object,
80
+ )
81
+
82
+
83
+ __all__ = ["BlobAssetEnvelope", "decode_blob_asset"]
@@ -0,0 +1,38 @@
1
+ from __future__ import annotations
2
+
3
+ from collections.abc import Callable
4
+
5
+ from marimo_export._delivery import preflight_export_destination
6
+ from marimo_export._services.prepare_export import prepare
7
+ from marimo_export.progress import ProgressEvent
8
+ from marimo_export.repository import ExportRepository
9
+ from marimo_export.result import ExportResult
10
+ from marimo_export.spec import ExportSpec, StrPath
11
+
12
+
13
+ def build(
14
+ notebook: StrPath,
15
+ *,
16
+ spec: ExportSpec,
17
+ output: StrPath,
18
+ repository: ExportRepository | None = None,
19
+ timeout: float = 30.0,
20
+ replace: bool = False,
21
+ progress: Callable[[ProgressEvent], None] | None = None,
22
+ cancelled: Callable[[], bool] | None = None,
23
+ ) -> ExportResult:
24
+ """Prepare, write, and verify one notebook export."""
25
+
26
+ preflight_export_destination(output, replace=replace)
27
+ with prepare(
28
+ notebook,
29
+ spec=spec,
30
+ repository=repository,
31
+ timeout=timeout,
32
+ progress=progress,
33
+ cancelled=cancelled,
34
+ ) as prepared:
35
+ return prepared.write(output, replace=replace, progress=progress)
36
+
37
+
38
+ __all__ = ["build"]
@@ -0,0 +1,28 @@
1
+ """Normalize Marimo cell identifiers at adapter boundaries."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from uuid import UUID
6
+
7
+ _MAX_CELL_ID_BYTES = 1_024
8
+ _UUID_LENGTH = 36
9
+
10
+
11
+ def canonical_cell_id(value: object) -> str:
12
+ """Remove Marimo's external UUIDv4 scope from one native cell ID."""
13
+
14
+ cell_id = str(value)
15
+ if not cell_id or len(cell_id.encode("utf-8")) > _MAX_CELL_ID_BYTES:
16
+ raise ValueError("cell ID must be a bounded non-empty string")
17
+ if len(cell_id) <= _UUID_LENGTH:
18
+ return cell_id
19
+ prefix = cell_id[:_UUID_LENGTH]
20
+ suffix = cell_id[_UUID_LENGTH:]
21
+ try:
22
+ external = UUID(prefix, version=4)
23
+ except ValueError:
24
+ return cell_id
25
+ return suffix if suffix and str(external) == prefix else cell_id
26
+
27
+
28
+ __all__ = ["canonical_cell_id"]
@@ -0,0 +1 @@
1
+ """Command-line parsing, delegation, rendering, and failure policy."""