marimo-dev 0.3.0__tar.gz → 0.3.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.
- {marimo_dev-0.3.0 → marimo_dev-0.3.2}/PKG-INFO +4 -3
- {marimo_dev-0.3.0 → marimo_dev-0.3.2}/README.md +2 -0
- {marimo_dev-0.3.0 → marimo_dev-0.3.2}/pyproject.toml +2 -3
- {marimo_dev-0.3.0 → marimo_dev-0.3.2}/src/marimo_dev/__init__.py +1 -1
- {marimo_dev-0.3.0 → marimo_dev-0.3.2}/src/marimo_dev/core.py +5 -4
- {marimo_dev-0.3.0 → marimo_dev-0.3.2}/src/marimo_dev/pkg.py +1 -1
- {marimo_dev-0.3.0 → marimo_dev-0.3.2}/src/marimo_dev/publish.py +26 -14
- {marimo_dev-0.3.0 → marimo_dev-0.3.2}/src/marimo_dev/read.py +11 -2
- {marimo_dev-0.3.0 → marimo_dev-0.3.2}/src/marimo_dev/build.py +0 -0
- {marimo_dev-0.3.0 → marimo_dev-0.3.2}/src/marimo_dev/cli.py +0 -0
- {marimo_dev-0.3.0 → marimo_dev-0.3.2}/src/marimo_dev/docs.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: marimo-dev
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.2
|
|
4
4
|
Summary: Build and publish python packages from marimo notebooks
|
|
5
5
|
Author: Deufel
|
|
6
6
|
Author-email: Deufel <MDeufel13@gmail.com>
|
|
@@ -13,13 +13,14 @@ Requires-Dist: mohtml>=0.1.11
|
|
|
13
13
|
Requires-Dist: pydantic-ai-slim>=1.50.0
|
|
14
14
|
Requires-Dist: pytest>=9.0.2
|
|
15
15
|
Requires-Dist: python-fasthtml>=0.12.37
|
|
16
|
-
Requires-
|
|
17
|
-
Requires-Python: >=3.13
|
|
16
|
+
Requires-Python: >=3.12
|
|
18
17
|
Project-URL: PyPI, https://pypi.org/project/marimo-dev/
|
|
19
18
|
Project-URL: Repository, https://github.com/deufel/m-dev
|
|
20
19
|
Description-Content-Type: text/markdown
|
|
21
20
|
|
|
22
21
|
# marimo-dev
|
|
22
|
+

|
|
23
|
+
|
|
23
24
|
|
|
24
25
|
> [!WARNING]
|
|
25
26
|
> This project is under active development and is not an official marimo tool - Mar 2026
|
|
@@ -4,10 +4,10 @@ build-backend = "uv_build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "marimo-dev"
|
|
7
|
-
version = "0.3.
|
|
7
|
+
version = "0.3.2"
|
|
8
8
|
description = "Build and publish python packages from marimo notebooks"
|
|
9
9
|
readme = "README.md"
|
|
10
|
-
requires-python = ">=3.
|
|
10
|
+
requires-python = ">=3.12"
|
|
11
11
|
dependencies = [
|
|
12
12
|
"anthropic>=0.84.0",
|
|
13
13
|
"fastcore>=1.10.0",
|
|
@@ -17,7 +17,6 @@ dependencies = [
|
|
|
17
17
|
"pydantic-ai-slim>=1.50.0",
|
|
18
18
|
"pytest>=9.0.2",
|
|
19
19
|
"python-fasthtml>=0.12.37",
|
|
20
|
-
"youtube-transcript-api>=1.2.3",
|
|
21
20
|
]
|
|
22
21
|
|
|
23
22
|
[project.license]
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"""Build and publish python packages from marimo notebooks"""
|
|
2
|
-
__version__ = '0.3.
|
|
2
|
+
__version__ = '0.3.2'
|
|
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
|
|
@@ -21,10 +21,11 @@ def read_config(root='.'):
|
|
|
21
21
|
|
|
22
22
|
class Kind(Enum):
|
|
23
23
|
"Types of nodes in parsed code"
|
|
24
|
-
IMP=
|
|
25
|
-
CONST=
|
|
26
|
-
SETUP=
|
|
27
|
-
EXP=
|
|
24
|
+
IMP="import"
|
|
25
|
+
CONST="const"
|
|
26
|
+
SETUP="setup"
|
|
27
|
+
EXP="export"
|
|
28
|
+
RAW="raw"
|
|
28
29
|
|
|
29
30
|
@dataclass
|
|
30
31
|
class Param:
|
|
@@ -23,7 +23,7 @@ def write_mod(
|
|
|
23
23
|
"Write module file with imports, constants, and exports."
|
|
24
24
|
g = {k: [n for n in nodes if n.kind == k] for k in Kind}
|
|
25
25
|
imports = '\n'.join(rewrite_imports(n.src, mod_names) for n in g[Kind.IMP])
|
|
26
|
-
parts = [imports, '\n'.join(n.src for n in g[Kind.CONST]), '\n'.join(n.src for n in g[Kind.SETUP]), '\n\n'.join(clean(n.src) for n in g[Kind.EXP])]
|
|
26
|
+
parts = [imports, '\n'.join(n.src for n in g[Kind.CONST]), '\n'.join(n.src for n in g[Kind.SETUP]), '\n\n'.join(clean(n.src) for n in g[Kind.EXP]), '\n\n'.join(n.src for n in g[Kind.RAW])]
|
|
27
27
|
write(path, *parts)
|
|
28
28
|
|
|
29
29
|
def rewrite_imports(
|
|
@@ -65,10 +65,16 @@ def check_pypi_auth(test=True):
|
|
|
65
65
|
return {'found': True, 'section': section, 'username': config[section].get('username', ''), 'preview': preview, 'source': str(pypirc)}
|
|
66
66
|
|
|
67
67
|
def publish(
|
|
68
|
-
test
|
|
68
|
+
test=True # When ready to upload to PyPi change this to false
|
|
69
69
|
):
|
|
70
|
-
"Build and publish package to PyPI.
|
|
71
|
-
|
|
70
|
+
"Build and publish package to PyPI."
|
|
71
|
+
platform = 'testpypi' if test else 'pypi'
|
|
72
|
+
auth = check_credentials(platform)
|
|
73
|
+
if not auth['found']:
|
|
74
|
+
print(f"❌ {auth['msg']}")
|
|
75
|
+
return
|
|
76
|
+
|
|
77
|
+
print(f"✅ Authenticated as {auth['username']} ({auth['preview']}) from {auth['source']}")
|
|
72
78
|
print("Rebuilding package from notebooks...")
|
|
73
79
|
build()
|
|
74
80
|
|
|
@@ -76,18 +82,24 @@ def publish(
|
|
|
76
82
|
print("Building distribution...")
|
|
77
83
|
subprocess.run(['uv', 'build'], check=True)
|
|
78
84
|
|
|
79
|
-
|
|
80
|
-
section = 'testpypi' if test else 'pypi'
|
|
81
|
-
|
|
85
|
+
cmd = ['uv', 'publish']
|
|
82
86
|
if test: cmd.extend(['--publish-url', 'https://test.pypi.org/legacy/'])
|
|
83
87
|
else: cmd.extend(['--publish-url', 'https://upload.pypi.org/legacy/'])
|
|
84
88
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
89
|
+
config = configparser.ConfigParser()
|
|
90
|
+
config.read(Path.home() / '.pypirc')
|
|
91
|
+
section = auth['section'] if 'section' in auth else platform
|
|
92
|
+
username = config[section].get('username', '__token__')
|
|
93
|
+
password = config[section].get('password', '')
|
|
94
|
+
cmd.extend(['--username', username, '--password', password])
|
|
91
95
|
|
|
92
|
-
|
|
93
|
-
|
|
96
|
+
target = 'Test PyPI' if test else 'PyPI'
|
|
97
|
+
print(f"Publishing to {target}...")
|
|
98
|
+
try:
|
|
99
|
+
subprocess.run(cmd, capture_output=True, text=True, check=True)
|
|
100
|
+
print(f"✅ Published to {target}!")
|
|
101
|
+
except subprocess.CalledProcessError as e:
|
|
102
|
+
if '403' in (e.stderr or ''):
|
|
103
|
+
print(f"❌ Auth failed. Token may be expired. Regenerate at {CREDENTIALS[platform]['url']}")
|
|
104
|
+
else:
|
|
105
|
+
print(f"❌ Publish failed: {e.stderr}")
|
|
@@ -124,8 +124,8 @@ def parse_node(
|
|
|
124
124
|
for s in n.body:
|
|
125
125
|
if (node := parse_import(s, ls)): yield node
|
|
126
126
|
elif (node := parse_const(s, ls)): yield node
|
|
127
|
-
else: yield Node(Kind.SETUP,
|
|
128
|
-
getattr(s, 'name', '_setup'),
|
|
127
|
+
else: yield Node(Kind.SETUP,
|
|
128
|
+
getattr(s, 'name', '_setup'),
|
|
129
129
|
ast.get_source_segment(src, s) or ast.unparse(s)
|
|
130
130
|
)
|
|
131
131
|
# Handle export-named cells (e.g. def export(): or def export_main():)
|
|
@@ -143,6 +143,15 @@ def parse_node(
|
|
|
143
143
|
yield Node(Kind.EXP, n.name, src)
|
|
144
144
|
return
|
|
145
145
|
|
|
146
|
+
# Handle raw escape hatch cells
|
|
147
|
+
if isinstance(n, ast.FunctionDef) and n.name.startswith('_'):
|
|
148
|
+
body_src = '\n'.join(ls[n.lineno-1:n.end_lineno])
|
|
149
|
+
if '#| raw' in body_src:
|
|
150
|
+
raw_lines = [l for l in body_src.splitlines() if not l.strip().startswith(('#|', '@app.', 'def _(', 'return'))]
|
|
151
|
+
raw_src = '\n'.join(raw_lines).strip()
|
|
152
|
+
if raw_src: yield Node(Kind.RAW, '_raw', raw_src)
|
|
153
|
+
return
|
|
154
|
+
|
|
146
155
|
# Handle decorated exports
|
|
147
156
|
if (node := parse_export(n, ls, cfg)): yield node
|
|
148
157
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|