marimo-jupyter-extension 0.1.0__py3-none-any.whl
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_jupyter_extension/__init__.py +58 -0
- marimo_jupyter_extension/config.py +82 -0
- marimo_jupyter_extension/convert.py +31 -0
- marimo_jupyter_extension/etc/jupyter_server_config.d/marimo_jupyter_extension.json +7 -0
- marimo_jupyter_extension/executable.py +63 -0
- marimo_jupyter_extension/exporter.py +70 -0
- marimo_jupyter_extension/handlers.py +179 -0
- marimo_jupyter_extension/icon.svg +84 -0
- marimo_jupyter_extension/labextension/package.json +86 -0
- marimo_jupyter_extension/labextension/schemas/@marimo-team/jupyter-extension/package.json.orig +77 -0
- marimo_jupyter_extension/labextension/schemas/@marimo-team/jupyter-extension/plugin.json +7 -0
- marimo_jupyter_extension/labextension/static/510.5a6289689ce7a0453fc4.js +1 -0
- marimo_jupyter_extension/labextension/static/remoteEntry.705371d091b7d314fd9e.js +1 -0
- marimo_jupyter_extension/labextension/static/style.js +4 -0
- marimo_jupyter_extension/labextension/static/third-party-licenses.json +16 -0
- marimo_jupyter_extension-0.1.0.data/data/etc/jupyter/jupyter_server_config.d/marimo_jupyter_extension.json +7 -0
- marimo_jupyter_extension-0.1.0.data/data/share/jupyter/labextensions/@marimo-team/jupyter-extension/install.json +5 -0
- marimo_jupyter_extension-0.1.0.data/data/share/jupyter/labextensions/@marimo-team/jupyter-extension/package.json +86 -0
- marimo_jupyter_extension-0.1.0.data/data/share/jupyter/labextensions/@marimo-team/jupyter-extension/schemas/@marimo-team/jupyter-extension/package.json.orig +77 -0
- marimo_jupyter_extension-0.1.0.data/data/share/jupyter/labextensions/@marimo-team/jupyter-extension/schemas/@marimo-team/jupyter-extension/plugin.json +7 -0
- marimo_jupyter_extension-0.1.0.data/data/share/jupyter/labextensions/@marimo-team/jupyter-extension/static/510.5a6289689ce7a0453fc4.js +1 -0
- marimo_jupyter_extension-0.1.0.data/data/share/jupyter/labextensions/@marimo-team/jupyter-extension/static/remoteEntry.705371d091b7d314fd9e.js +1 -0
- marimo_jupyter_extension-0.1.0.data/data/share/jupyter/labextensions/@marimo-team/jupyter-extension/static/style.js +4 -0
- marimo_jupyter_extension-0.1.0.data/data/share/jupyter/labextensions/@marimo-team/jupyter-extension/static/third-party-licenses.json +16 -0
- marimo_jupyter_extension-0.1.0.dist-info/METADATA +174 -0
- marimo_jupyter_extension-0.1.0.dist-info/RECORD +30 -0
- marimo_jupyter_extension-0.1.0.dist-info/WHEEL +4 -0
- marimo_jupyter_extension-0.1.0.dist-info/entry_points.txt +5 -0
- marimo_jupyter_extension-0.1.0.dist-info/licenses/LICENSE +201 -0
- marimo_jupyter_extension-0.1.0.dist-info/licenses/NOTICE +21 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"""Jupyter extension to proxy Marimo.
|
|
2
|
+
|
|
3
|
+
This module provides the setup function for jupyter-server-proxy to launch
|
|
4
|
+
marimo.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import base64
|
|
8
|
+
import os
|
|
9
|
+
import secrets
|
|
10
|
+
|
|
11
|
+
from .config import get_config
|
|
12
|
+
from .executable import get_marimo_command
|
|
13
|
+
|
|
14
|
+
__version__ = "0.1.0"
|
|
15
|
+
__all__ = ["setup_marimoserver"]
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def setup_marimoserver():
|
|
19
|
+
"""Setup function for jupyter-server-proxy.
|
|
20
|
+
|
|
21
|
+
Returns a configuration dictionary that jupyter-server-proxy uses to
|
|
22
|
+
launch and proxy marimo.
|
|
23
|
+
"""
|
|
24
|
+
token = secrets.token_urlsafe(16)
|
|
25
|
+
config = get_config()
|
|
26
|
+
|
|
27
|
+
# Get marimo command based on config
|
|
28
|
+
marimo_cmd = get_marimo_command(config)
|
|
29
|
+
|
|
30
|
+
return {
|
|
31
|
+
"command": [
|
|
32
|
+
*marimo_cmd,
|
|
33
|
+
"edit",
|
|
34
|
+
"--sandbox",
|
|
35
|
+
"--port",
|
|
36
|
+
"{port}",
|
|
37
|
+
"--base-url",
|
|
38
|
+
config.base_url,
|
|
39
|
+
"--token",
|
|
40
|
+
"--token-password",
|
|
41
|
+
token,
|
|
42
|
+
"--headless",
|
|
43
|
+
"--no-skew-protection",
|
|
44
|
+
],
|
|
45
|
+
"timeout": config.timeout,
|
|
46
|
+
"absolute_url": True,
|
|
47
|
+
"request_headers_override": {
|
|
48
|
+
"Authorization": "Basic "
|
|
49
|
+
+ base64.b64encode(b" :" + token.encode()).decode()
|
|
50
|
+
},
|
|
51
|
+
"launcher_entry": {
|
|
52
|
+
"icon_path": os.path.join(
|
|
53
|
+
os.path.dirname(os.path.abspath(__file__)), "icon.svg"
|
|
54
|
+
),
|
|
55
|
+
# Disabled - our labextension provides the launcher
|
|
56
|
+
"enabled": False,
|
|
57
|
+
},
|
|
58
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"""Configuration for marimo-jupyter-extension."""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
from traitlets import Int, Unicode, default
|
|
8
|
+
from traitlets.config import Configurable
|
|
9
|
+
|
|
10
|
+
DEFAULT_TIMEOUT = 60
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class MarimoProxyConfig(Configurable):
|
|
14
|
+
"""Configuration for marimo-jupyter-extension.
|
|
15
|
+
|
|
16
|
+
Can be configured in jupyterhub_config.py:
|
|
17
|
+
c.MarimoProxyConfig.marimo_path = "/opt/bin/marimo"
|
|
18
|
+
c.MarimoProxyConfig.uvx_path = "/usr/local/bin/uvx" # enables uvx mode
|
|
19
|
+
c.MarimoProxyConfig.timeout = 120
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
marimo_path = Unicode(
|
|
23
|
+
allow_none=True,
|
|
24
|
+
help="Explicit path to marimo executable. If not set, searches PATH.",
|
|
25
|
+
).tag(config=True)
|
|
26
|
+
|
|
27
|
+
uvx_path = Unicode(
|
|
28
|
+
allow_none=True,
|
|
29
|
+
help=(
|
|
30
|
+
"Path to uvx executable. If set, uses 'uvx marimo' instead "
|
|
31
|
+
"of marimo directly."
|
|
32
|
+
),
|
|
33
|
+
).tag(config=True)
|
|
34
|
+
|
|
35
|
+
timeout = Int(
|
|
36
|
+
DEFAULT_TIMEOUT,
|
|
37
|
+
help="Timeout in seconds for marimo to start.",
|
|
38
|
+
).tag(config=True)
|
|
39
|
+
|
|
40
|
+
@default("marimo_path")
|
|
41
|
+
def _default_marimo_path(self):
|
|
42
|
+
return None
|
|
43
|
+
|
|
44
|
+
@default("uvx_path")
|
|
45
|
+
def _default_uvx_path(self):
|
|
46
|
+
# Derive uvx from $UV if set (standard uv environment variable)
|
|
47
|
+
if uv_path := os.environ.get("UV"):
|
|
48
|
+
return str(Path(uv_path).parent / "uvx")
|
|
49
|
+
return None
|
|
50
|
+
|
|
51
|
+
@default("timeout")
|
|
52
|
+
def _default_timeout(self):
|
|
53
|
+
return DEFAULT_TIMEOUT
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@dataclass(frozen=True)
|
|
57
|
+
class Config:
|
|
58
|
+
"""Resolved configuration (immutable snapshot)."""
|
|
59
|
+
|
|
60
|
+
marimo_path: str | None # Explicit marimo path
|
|
61
|
+
uvx_path: str | None # If set, use uvx mode
|
|
62
|
+
timeout: int
|
|
63
|
+
base_url: str
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def get_config(traitlets_config: MarimoProxyConfig | None = None) -> Config:
|
|
67
|
+
"""Load configuration from Traitlets or defaults."""
|
|
68
|
+
# Use traitlets config if provided, otherwise create default
|
|
69
|
+
cfg = traitlets_config or MarimoProxyConfig()
|
|
70
|
+
|
|
71
|
+
return Config(
|
|
72
|
+
marimo_path=cfg.marimo_path,
|
|
73
|
+
uvx_path=cfg.uvx_path,
|
|
74
|
+
timeout=cfg.timeout,
|
|
75
|
+
base_url=_get_base_url(),
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def _get_base_url() -> str:
|
|
80
|
+
"""Get base URL, gracefully handling non-JupyterHub environments."""
|
|
81
|
+
prefix = os.environ.get("JUPYTERHUB_SERVICE_PREFIX", "/")
|
|
82
|
+
return f"{prefix}marimo"
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"""Shared notebook conversion logic."""
|
|
2
|
+
|
|
3
|
+
import subprocess
|
|
4
|
+
|
|
5
|
+
from .config import get_config
|
|
6
|
+
from .executable import get_marimo_command
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def convert_notebook_to_marimo(input_path: str, output_path: str) -> None:
|
|
10
|
+
"""Convert a Jupyter notebook to marimo format.
|
|
11
|
+
|
|
12
|
+
Args:
|
|
13
|
+
input_path: Path to input .ipynb file
|
|
14
|
+
output_path: Path to output .py file
|
|
15
|
+
|
|
16
|
+
Raises:
|
|
17
|
+
RuntimeError: If conversion fails
|
|
18
|
+
"""
|
|
19
|
+
config = get_config()
|
|
20
|
+
marimo_cmd = get_marimo_command(config)
|
|
21
|
+
|
|
22
|
+
result = subprocess.run(
|
|
23
|
+
[*marimo_cmd, "convert", input_path, "-o", output_path],
|
|
24
|
+
capture_output=True,
|
|
25
|
+
text=True,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
if result.returncode != 0:
|
|
29
|
+
raise RuntimeError(
|
|
30
|
+
f"marimo convert failed: {result.stderr or result.stdout}"
|
|
31
|
+
)
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"""Executable discovery for marimo."""
|
|
2
|
+
|
|
3
|
+
import shutil
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
from .config import Config
|
|
7
|
+
|
|
8
|
+
COMMON_LOCATIONS = [
|
|
9
|
+
"~/.local/bin/marimo",
|
|
10
|
+
"/opt/bin/marimo",
|
|
11
|
+
"/usr/local/bin/marimo",
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def get_marimo_command(config: Config) -> list[str]:
|
|
16
|
+
"""Get marimo command based on configuration.
|
|
17
|
+
|
|
18
|
+
Args:
|
|
19
|
+
config: Config dataclass with marimo_path and uvx_path
|
|
20
|
+
|
|
21
|
+
Logic:
|
|
22
|
+
- If uvx_path is set → use uvx mode: [uvx_path, 'marimo']
|
|
23
|
+
- If marimo_path is set → use it directly: [marimo_path]
|
|
24
|
+
- Otherwise → search PATH and common locations
|
|
25
|
+
- If not found → raise FileNotFoundError
|
|
26
|
+
|
|
27
|
+
Returns:
|
|
28
|
+
Command as list, e.g. ['/usr/bin/marimo'] or ['/usr/bin/uvx', 'marimo']
|
|
29
|
+
"""
|
|
30
|
+
# uvx mode (opt-in via explicit uvx_path)
|
|
31
|
+
if config.uvx_path:
|
|
32
|
+
return [config.uvx_path, "marimo[sandbox]==0.19.4"]
|
|
33
|
+
|
|
34
|
+
# Explicit marimo path
|
|
35
|
+
if config.marimo_path:
|
|
36
|
+
return [config.marimo_path]
|
|
37
|
+
|
|
38
|
+
# Search for marimo
|
|
39
|
+
if found := _find_marimo():
|
|
40
|
+
return [found]
|
|
41
|
+
|
|
42
|
+
raise FileNotFoundError(
|
|
43
|
+
"marimo executable not found.\n"
|
|
44
|
+
"Solutions:\n"
|
|
45
|
+
" - Install marimo: pip install marimo\n"
|
|
46
|
+
" - Configure MarimoProxyConfig.marimo_path in jupyterhub_config.py\n"
|
|
47
|
+
" - Configure MarimoProxyConfig.uvx_path to use uvx marimo"
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def _find_marimo() -> str | None:
|
|
52
|
+
"""Search for marimo in PATH and common locations."""
|
|
53
|
+
# Check system PATH
|
|
54
|
+
if which := shutil.which("marimo"):
|
|
55
|
+
return which
|
|
56
|
+
|
|
57
|
+
# Check common locations
|
|
58
|
+
for location in COMMON_LOCATIONS:
|
|
59
|
+
candidate = Path(location).expanduser()
|
|
60
|
+
if candidate.exists() and candidate.is_file():
|
|
61
|
+
return str(candidate)
|
|
62
|
+
|
|
63
|
+
return None
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"""nbconvert exporter for marimo format."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
import tempfile
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
from nbconvert.exporters import Exporter
|
|
8
|
+
from traitlets import default
|
|
9
|
+
|
|
10
|
+
from .convert import convert_notebook_to_marimo
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class MarimoExporter(Exporter):
|
|
14
|
+
"""Export Jupyter notebooks to marimo .py format.
|
|
15
|
+
|
|
16
|
+
This exporter integrates with JupyterLab's "File > Save and Export
|
|
17
|
+
Notebook As" menu.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
export_from_notebook = "marimo"
|
|
21
|
+
output_mimetype = "text/x-python"
|
|
22
|
+
|
|
23
|
+
@default("file_extension")
|
|
24
|
+
def _file_extension_default(self):
|
|
25
|
+
return ".py"
|
|
26
|
+
|
|
27
|
+
def from_notebook_node(self, nb, resources=None, **kwargs):
|
|
28
|
+
"""Convert notebook to marimo format.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
nb: NotebookNode object
|
|
32
|
+
resources: Additional resources (paths, metadata, etc.)
|
|
33
|
+
**kwargs: Additional keyword arguments
|
|
34
|
+
|
|
35
|
+
Returns:
|
|
36
|
+
Tuple of (output, resources) where output is the converted string
|
|
37
|
+
"""
|
|
38
|
+
if resources is None:
|
|
39
|
+
resources = {}
|
|
40
|
+
|
|
41
|
+
# Write notebook to temporary file
|
|
42
|
+
with tempfile.NamedTemporaryFile(
|
|
43
|
+
mode="w", suffix=".ipynb", delete=False
|
|
44
|
+
) as tmp_in:
|
|
45
|
+
json.dump(nb, tmp_in)
|
|
46
|
+
tmp_in_path = tmp_in.name
|
|
47
|
+
|
|
48
|
+
# Create temporary output file
|
|
49
|
+
with tempfile.NamedTemporaryFile(
|
|
50
|
+
mode="w", suffix=".py", delete=False
|
|
51
|
+
) as tmp_out:
|
|
52
|
+
tmp_out_path = tmp_out.name
|
|
53
|
+
|
|
54
|
+
try:
|
|
55
|
+
# Convert notebook using shared conversion logic
|
|
56
|
+
convert_notebook_to_marimo(tmp_in_path, tmp_out_path)
|
|
57
|
+
|
|
58
|
+
# Read converted output
|
|
59
|
+
with open(tmp_out_path) as f:
|
|
60
|
+
output = f.read()
|
|
61
|
+
|
|
62
|
+
# Set output extension for nbconvert handler
|
|
63
|
+
resources["output_extension"] = ".py"
|
|
64
|
+
|
|
65
|
+
return (output, resources)
|
|
66
|
+
|
|
67
|
+
finally:
|
|
68
|
+
# Clean up temporary files
|
|
69
|
+
Path(tmp_in_path).unlink(missing_ok=True)
|
|
70
|
+
Path(tmp_out_path).unlink(missing_ok=True)
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
"""Jupyter server extension handlers for marimo tools."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
from jupyter_server.base.handlers import JupyterHandler
|
|
7
|
+
from jupyter_server.utils import url_path_join
|
|
8
|
+
from tornado import web
|
|
9
|
+
|
|
10
|
+
from .convert import convert_notebook_to_marimo
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _find_marimo_proxy_state(web_app):
|
|
14
|
+
"""Find the marimo proxy handler's state dict.
|
|
15
|
+
|
|
16
|
+
Searches through the web_app's registered handlers to find the
|
|
17
|
+
jupyter-server-proxy handler for marimo and returns its state dict.
|
|
18
|
+
"""
|
|
19
|
+
for host_pattern, handlers in web_app.handlers:
|
|
20
|
+
for spec in handlers:
|
|
21
|
+
if hasattr(spec, "kwargs") and "state" in spec.kwargs:
|
|
22
|
+
if "marimo" in str(spec.regex.pattern):
|
|
23
|
+
return spec.kwargs["state"]
|
|
24
|
+
return None
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class ConvertHandler(JupyterHandler):
|
|
28
|
+
"""Handler for converting Jupyter notebooks to marimo format."""
|
|
29
|
+
|
|
30
|
+
@web.authenticated
|
|
31
|
+
async def post(self):
|
|
32
|
+
"""Convert a Jupyter notebook to marimo format.
|
|
33
|
+
|
|
34
|
+
POST /marimo-tools/convert
|
|
35
|
+
Body: {"input": "notebook.ipynb", "output": "notebook.py"}
|
|
36
|
+
"""
|
|
37
|
+
data = json.loads(self.request.body)
|
|
38
|
+
input_path = data.get("input")
|
|
39
|
+
output_path = data.get("output")
|
|
40
|
+
|
|
41
|
+
if not input_path or not output_path:
|
|
42
|
+
self.set_status(400)
|
|
43
|
+
self.finish(
|
|
44
|
+
{"success": False, "error": "Missing input or output path"}
|
|
45
|
+
)
|
|
46
|
+
return
|
|
47
|
+
|
|
48
|
+
try:
|
|
49
|
+
convert_notebook_to_marimo(input_path, output_path)
|
|
50
|
+
self.finish({"success": True, "output": output_path})
|
|
51
|
+
except RuntimeError as e:
|
|
52
|
+
self.set_status(500)
|
|
53
|
+
self.finish({"success": False, "error": str(e)})
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class RestartHandler(JupyterHandler):
|
|
57
|
+
"""Handler for restarting the marimo server."""
|
|
58
|
+
|
|
59
|
+
@web.authenticated
|
|
60
|
+
async def post(self):
|
|
61
|
+
"""Restart the marimo server.
|
|
62
|
+
|
|
63
|
+
POST /marimo-tools/restart
|
|
64
|
+
|
|
65
|
+
Finds the jupyter-server-proxy handler's state, kills the current
|
|
66
|
+
process, and clears the state so the next request spawns a new process.
|
|
67
|
+
"""
|
|
68
|
+
proxy_state = _find_marimo_proxy_state(self.application)
|
|
69
|
+
|
|
70
|
+
if not proxy_state:
|
|
71
|
+
self.set_status(503)
|
|
72
|
+
self.finish(
|
|
73
|
+
{"success": False, "error": "Proxy not initialized yet"}
|
|
74
|
+
)
|
|
75
|
+
return
|
|
76
|
+
|
|
77
|
+
try:
|
|
78
|
+
async with proxy_state["proc_lock"]:
|
|
79
|
+
proc = proxy_state.get("proc")
|
|
80
|
+
if proc and proc != "process not managed":
|
|
81
|
+
try:
|
|
82
|
+
await proc.kill()
|
|
83
|
+
except Exception:
|
|
84
|
+
pass # Already dead
|
|
85
|
+
# Clear the process reference so next request spawns new one
|
|
86
|
+
if "proc" in proxy_state:
|
|
87
|
+
del proxy_state["proc"]
|
|
88
|
+
|
|
89
|
+
self.finish({"success": True, "message": "Server restarting"})
|
|
90
|
+
except Exception as e:
|
|
91
|
+
self.set_status(500)
|
|
92
|
+
self.finish({"success": False, "error": str(e)})
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
class CreateStubHandler(JupyterHandler):
|
|
96
|
+
"""Handler for creating marimo notebook stub files."""
|
|
97
|
+
|
|
98
|
+
@web.authenticated
|
|
99
|
+
async def post(self):
|
|
100
|
+
"""Create a marimo notebook stub with PEP 723 metadata.
|
|
101
|
+
|
|
102
|
+
POST /marimo-tools/create-stub
|
|
103
|
+
Body: {"path": "notebook.py", "venv": "/path/to/python"}
|
|
104
|
+
"""
|
|
105
|
+
data = json.loads(self.request.body)
|
|
106
|
+
path = data.get("path")
|
|
107
|
+
venv = data.get("venv")
|
|
108
|
+
|
|
109
|
+
if not path:
|
|
110
|
+
self.set_status(400)
|
|
111
|
+
self.finish({"success": False, "error": "Missing path"})
|
|
112
|
+
return
|
|
113
|
+
|
|
114
|
+
# Build stub content
|
|
115
|
+
lines = []
|
|
116
|
+
|
|
117
|
+
# Add PEP 723 header if venv is specified
|
|
118
|
+
if venv:
|
|
119
|
+
# Extract venv directory from python executable path
|
|
120
|
+
# e.g., /path/to/venv/bin/python3.12 -> /path/to/venv
|
|
121
|
+
venv_path = Path(venv)
|
|
122
|
+
if venv_path.parent.name == "bin":
|
|
123
|
+
venv_path = venv_path.parent.parent
|
|
124
|
+
lines.extend(
|
|
125
|
+
[
|
|
126
|
+
"# /// script",
|
|
127
|
+
"# [tool.marimo.venv]",
|
|
128
|
+
f'# path = "{venv_path}"',
|
|
129
|
+
"# ///",
|
|
130
|
+
"",
|
|
131
|
+
]
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
# Add marimo app boilerplate
|
|
135
|
+
lines.extend(
|
|
136
|
+
[
|
|
137
|
+
"import marimo",
|
|
138
|
+
"",
|
|
139
|
+
'__generated_with = "0.19.2"',
|
|
140
|
+
'app = marimo.App(width="medium")',
|
|
141
|
+
"",
|
|
142
|
+
"",
|
|
143
|
+
'if __name__ == "__main__":',
|
|
144
|
+
" app.run()",
|
|
145
|
+
"",
|
|
146
|
+
]
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
content = "\n".join(lines)
|
|
150
|
+
|
|
151
|
+
try:
|
|
152
|
+
file_path = Path(path)
|
|
153
|
+
file_path.write_text(content)
|
|
154
|
+
self.finish({"success": True, "path": path})
|
|
155
|
+
except Exception as e:
|
|
156
|
+
self.set_status(500)
|
|
157
|
+
self.finish({"success": False, "error": str(e)})
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def _jupyter_server_extension_points():
|
|
161
|
+
"""Return the server extension points for this package."""
|
|
162
|
+
return [{"module": "marimo_jupyter_extension.handlers"}]
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def _load_jupyter_server_extension(server_app):
|
|
166
|
+
"""Load the jupyter server extension."""
|
|
167
|
+
base_url = server_app.web_app.settings["base_url"]
|
|
168
|
+
server_app.web_app.add_handlers(
|
|
169
|
+
".*",
|
|
170
|
+
[
|
|
171
|
+
(url_path_join(base_url, "marimo-tools/convert"), ConvertHandler),
|
|
172
|
+
(url_path_join(base_url, "marimo-tools/restart"), RestartHandler),
|
|
173
|
+
(
|
|
174
|
+
url_path_join(base_url, "marimo-tools/create-stub"),
|
|
175
|
+
CreateStubHandler,
|
|
176
|
+
),
|
|
177
|
+
],
|
|
178
|
+
)
|
|
179
|
+
server_app.log.info("marimo-jupyter-extension tools extension loaded")
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
|
2
|
+
<svg
|
|
3
|
+
width="97.645645"
|
|
4
|
+
height="100.87186"
|
|
5
|
+
viewbox="0 0 73.234231 75.653891"
|
|
6
|
+
version="1.1"
|
|
7
|
+
id="svg1568"
|
|
8
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
9
|
+
xmlns:svg="http://www.w3.org/2000/svg">
|
|
10
|
+
<defs
|
|
11
|
+
id="defs1572" />
|
|
12
|
+
<g
|
|
13
|
+
id="surface1"
|
|
14
|
+
transform="matrix(0.32633463,0,0,0.32633463,-159.18374,-120.45361)">
|
|
15
|
+
<path
|
|
16
|
+
style="fill:#1c7361;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
|
17
|
+
d="m 517.37109,413.55859 c 1.51172,-1.78125 3.1875,-4.15625 2.10547,-6.26172 6.04688,-3.5625 11.39063,-8.26171 15.76172,-13.76562 -2.375,1.89062 -4.96484,3.40234 -7.71875,4.58984 20.67578,-20.40625 51.76953,-29.6914 80.32422,-23.96875 -22.99609,-0.86328 -46.42188,5.23438 -65.42578,18.19141 -19.05469,12.90234 -33.51953,32.71094 -39.07813,55.05859 8.41797,-24.45312 26.17969,-45.55859 48.85157,-57.97265 -1.78125,1.83593 -3.56641,3.72265 -5.39844,5.55859 8.63672,-3.5625 16.46094,-8.90625 25.04687,-12.63281 25.20703,-11.01172 55.54297,-6.85547 79.02344,7.5039 23.48047,14.35938 40.37891,37.89454 50.20313,63.58985 4.3164,11.22656 7.33984,23.69531 3.50781,35.08594 -0.86328,-14.84375 -5.72266,-29.14844 -12.03906,-42.58985 -10.47266,-22.40234 -25.47657,-43.39844 -46.58204,-56.24609 -21.10546,-12.79297 -49.01562,-16.19531 -70.60546,-4.15625 11.0664,-1.1875 22.23828,-1.83594 33.19531,-0.26953 20.62109,2.91406 39.67578,13.71093 54.14062,28.66015 14.41407,15.00782 24.40235,33.95313 30.28516,53.8711 5.72266,19.48828 7.60937,40.97265 0.26953,59.97265 21.42969,-34.65625 17.86719,-82.91015 -8.3125,-114.05859 -10.95703,-13.00781 -25.15625,-22.99609 -40.48437,-30.22656 -17.70704,-8.3125 -37.14063,-13.11719 -56.67969,-12.57813 -19.53906,0.53906 -39.08203,6.64063 -54.67969,18.40625 12.95313,-11.44531 29.84766,-17.92187 47.01563,-19.70312 17.21875,-1.72657 34.65234,1.08203 51.01171,6.58593 34.00391,11.55079 64.98829,37.03125 74.97657,71.52344 2.53515,8.85156 3.66797,18.02735 4.69531,27.20703 0.86328,7.9336 1.56641,15.86719 1.40234,23.85547 -0.7539,39.46094 -25.96484,78.00391 -62.72265,92.41406 -10.41797,4.05079 -21.42969,6.26172 -32.4961,7.82813 -17.70703,2.48047 -36.05859,3.23828 -53.11718,-2.05078 -8.79688,-2.75391 -17.00391,-7.01953 -24.61329,-12.25391 -31.52343,-21.59375 -51.4414,-59.21484 -51.4414,-97.43359 0,-6.80078 0.59375,-13.54688 1.51172,-20.24219 0.80859,-6.15234 1.88672,-12.25391 3.66797,-18.19141 2.69921,-8.74609 6.91015,-17.0039 12.47265,-24.28906 0.96875,-0.59375 1.94141,-1.24219 2.85938,-1.89062 -12.79297,27.04297 -20.40625,59 -8.69141,86.58203 -4.21094,-17.97266 -4.48047,-36.8125 -0.75391,-54.84375 1.1875,-0.42969 2.375,-0.91406 3.50782,-1.40235 0.0547,-1.1875 0.10547,-2.32031 0.16015,-3.50781 -0.86328,0.97266 -1.67187,1.94141 -2.53515,2.85938 1.99609,-14.30469 8.14843,-27.85157 17.3789,-38.8086 m 8.69141,-0.70312 c 3.34766,-2.26563 6.69531,-4.53516 10.04297,-6.80078 -2.10547,4.26562 -5.99219,7.60937 -10.52735,9.12109 -21.05078,21.75391 -27.53125,54.19531 -25.04687,84.31641 0.97266,11.39062 3.29297,23.21093 10.63281,31.95703 -5.125,-21.05469 -5.39844,-43.29297 -0.69922,-64.45313 0.91797,-0.0547 1.23828,1.13282 1.23828,2.05078 0.37891,14.19922 -2.05078,28.39454 -1.02343,42.58985 1.02343,14.14453 6.3164,29.09765 18.1914,36.8164 9.28516,6.04297 18.51563,12.08985 27.7461,18.13672 -21.59375,-6.91015 -40.4336,-21.91797 -52.08985,-41.34765 3.12891,8.47265 7.5,16.51562 12.89844,23.75 -0.69922,-1.94532 -1.34766,-3.94141 -2.05078,-5.9375 5.45312,5.1289 10.95703,10.14843 16.41016,15.22265 3.99609,3.72266 10.25781,7.5 14.35937,3.9375 0.64844,1.35157 -0.53906,3.02344 -1.99609,3.40235 -1.46094,0.43359 -3.02344,0 -4.48047,-0.4336 6.53125,4.69922 13.33203,9.01563 20.34765,12.95703 -1.02343,0.16016 -1.34765,1.67188 -0.69921,2.53516 0.64453,0.86719 1.72656,1.08203 2.75,1.35156 25.75,5.5586 53.17187,3.50782 77.78515,-5.99218 -21.16015,4.96484 -43.72265,6.10156 -64.23437,-1.07813 -17.32813,-6.04687 -32.4961,-17.97656 -42.42969,-33.35937 -3.18359,-4.96875 -5.82813,-10.20313 -8.25781,-15.54688 -7.82813,-17.59766 -12.79297,-36.8125 -11.39063,-56.03125 1.40625,-19.21484 9.82422,-38.37891 24.94141,-50.25391 1.5625,-1.24218 3.50781,-2.42968 5.44922,-1.94531 -14.89844,10.79688 -23.75,28.66406 -26.07032,46.91016 -2.32031,18.29687 1.45704,36.86719 8.09766,54.03125 4.75,12.14844 11.0625,23.91406 19.75391,33.6289 3.72656,4.15625 7.9375,7.9375 12.73828,10.79688 8.80078,5.28906 19.21875,7.28906 29.42187,8.58203 13.8711,1.78125 27.85157,2.53906 41.83203,2.21484 -17.65234,4.15625 -36.11328,1.1875 -53.98046,-1.78125 30.33984,11.39063 65.91015,4.42579 91.98437,-14.73828 5.17969,-3.83203 10.09375,-8.09375 14.03125,-13.22265 6.04688,-7.88282 9.66406,-17.48828 11.5,-27.26172 4.75,-25.47656 -2.05078,-52.08985 -14.41406,-74.92188 -8.58203,-15.87109 -19.97266,-30.55078 -34.97656,-40.53906 -14.03516,-9.28516 -30.71485,-14.19531 -47.50391,-15.11328 -25.80078,-1.51172 -53.11328,7.01562 -70.28125,26.44922 m 576.75,588.17969 c 11.60547,2.91406 23.32031,5.01953 35.19531,6.42578 -14.57422,3.34375 -29.58203,-1.78125 -43.66797,-6.80078 -8.3164,-2.91797 -16.73437,-5.94141 -24.45312,-10.25782 -18.67969,-10.36328 -32.71485,-28.125 -40.86328,-47.8789 -1.40235,-3.50781 -2.69922,-7.01953 -3.77735,-10.58203 -0.10937,-0.42969 -0.43359,0.59375 0,0.3789 0.42969,-0.16015 0.375,-0.80859 0.16016,-1.24218 -4.85938,-11.71094 -7.82813,-24.28907 -8.74609,-36.92188 -0.91797,19.10938 3.83203,38.32422 12.46875,55.4375 9.39453,18.62109 23.48437,34.98047 41.1875,46.04297 17.65234,11.06641 38.91796,16.67969 59.64843,14.68359 29.14844,-2.85937 54.73438,-19.86328 78.21485,-37.30078 -10.36328,13.71094 -26.07032,22.1875 -41.34766,30.17578 26.39453,-7.39453 47.55469,-28.28515 60.29688,-52.57422 -6.31641,10.79297 -16.19532,19.26954 -26.9375,25.63672 -10.79688,6.3711 -22.61719,10.79688 -34.4375,15.0625 -5.1836,1.89063 -10.41797,3.72266 -15.76172,5.23438 -15.27735,4.375 -31.36328,5.88672 -47.17969,4.48047 m 107.95703,-36.48828 c 2.69922,-2.53907 5.34766,-5.12891 7.50391,-8.04297 3.40234,-4.69532 5.66797,-10.14844 7.82812,-15.54688 2.91406,-7.33984 5.88281,-14.73828 6.64063,-22.61719 -1.40625,1.24219 -1.89063,3.07813 -2.42969,4.85938 -7.17969,24.88281 -24.9375,46.58203 -47.98828,58.45703 10.85156,-2.42969 20.1875,-9.5 28.44531,-17.10937 m -131.92187,26.44921 c 1.13281,0.26954 2.53515,0.75391 2.58984,1.89063 0.42969,-0.75781 1.72656,-0.75781 2.21094,0 0.21875,-0.0547 0.0547,-0.43359 -0.21485,-0.54297 -1.61718,-0.86328 -3.23828,-1.72656 -4.80468,-2.58984 -6.53125,-3.50782 -12.52344,-7.87891 -17.86719,-12.95313 -0.64844,1.40235 -0.16016,3.1836 1.08203,4.04688 2.375,1.72656 4.75,3.45312 7.125,5.18359 2.85937,2.375 6.26172,4.10156 9.87891,4.96484 m 155.89062,-81.61718 c -0.21484,3.99609 -0.43359,8.04297 -0.70312,12.03906 -0.0508,0.53906 -0.0508,1.07812 -0.0508,1.61719 -0.0547,0.97265 -0.10937,1.94531 -0.21875,2.86328 -0.0547,1.1875 -0.10546,2.26562 -0.10546,3.45312 2.26562,-9.17578 3.07421,-18.78515 2.375,-28.17578 -0.26954,-0.10937 -0.54297,-0.26953 -0.75782,-0.43359 -0.16015,2.85937 -0.3789,5.72265 -0.53906,8.63672 m -209.8164,-59.16016 c -0.3789,0.69922 -0.70312,1.40234 -1.02734,2.10547 0.37891,0.48437 1.07813,-0.10938 1.24219,-0.70313 0.16015,-0.53906 0.32422,-1.29687 0.91797,-1.34765 -0.26953,-0.27344 -0.53907,-0.54297 -0.8086,-0.8125 -0.10937,0.21875 -0.21875,0.53906 -0.10937,0.75781 m 39.02734,-44.80469 c 0.53906,-0.42968 1.07813,-0.86328 1.61719,-1.34765 -0.91797,-0.37891 -2.10547,0.10547 -2.48047,1.07812 0.26953,0.10938 0.53906,0.21485 0.86328,0.26953 m 1.67188,-2.53515 c 1.1875,0.26953 2.53906,-0.0547 3.50781,-0.86328 -1.23828,-0.0547 -2.48047,0.21484 -3.50781,0.86328 m -42.96485,54.78906 c -0.0547,-0.26953 -0.10937,-0.53906 -0.10937,-0.75781 -1.02735,0.3789 -1.51172,1.78125 -0.91797,2.69922 0.21484,-0.69922 0.53906,-1.34766 1.02734,-1.94141 m -6.10156,27.52734 c -0.26953,0.37891 -0.0547,1.02735 0.43359,1.08203 0.26954,-0.86328 0.21485,-1.78125 -0.0547,-2.69921 -0.53907,0.26953 -0.70313,1.02343 -0.37891,1.51171"
|
|
18
|
+
id="path1533" />
|
|
19
|
+
<path
|
|
20
|
+
style="fill:#1c7361;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
|
21
|
+
d="m 527.08984,398.39062 c 0.10547,0.16016 0.21485,0.375 0.32422,0.53907 -0.48828,0.69922 -1.40625,1.02343 -2.21484,0.80859 0.43359,-0.59375 1.08203,-1.02344 1.78125,-1.1875"
|
|
22
|
+
id="path1535" />
|
|
23
|
+
<path
|
|
24
|
+
style="fill:#1c7361;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
|
25
|
+
d="m 522.82422,401.84375 c 0.75781,-0.26953 1.5664,-0.43359 2.375,-0.37891 -0.16016,1.1875 -2.16016,1.51172 -2.64453,0.37891"
|
|
26
|
+
id="path1537" />
|
|
27
|
+
<path
|
|
28
|
+
style="fill:#1c7361;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
|
29
|
+
d="m 520.125,399.35937 c 0.48828,-0.7539 1.40234,-1.29296 2.375,-1.1875 0.21484,0.54297 0.0547,1.1875 -0.37891,1.56641 -0.7539,0.10938 -1.67187,0.21484 -2.21093,-0.37891"
|
|
30
|
+
id="path1539" />
|
|
31
|
+
<path
|
|
32
|
+
style="fill:#1c7361;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
|
33
|
+
d="m 671.42969,402.92187 c 0.32422,-0.0508 0.64843,0.26954 0.59375,0.59375 -0.0547,0.32422 -0.42969,0.54297 -0.75391,0.4336 -0.48828,-0.53906 -0.97266,-1.13281 -1.45703,-1.72656 0.53906,-0.4336 1.50781,-0.0547 1.61719,0.59375"
|
|
34
|
+
id="path1541" />
|
|
35
|
+
<path
|
|
36
|
+
style="fill:#1c7361;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
|
37
|
+
d="m 524.98437,394.93359 c 0.37891,-0.42968 1.13282,-0.42968 1.56641,-0.0547 -0.70312,0.70312 -1.62109,1.1875 -2.59375,1.51171 -0.10547,-0.59375 0.43359,-1.29296 1.02734,-1.24218"
|
|
38
|
+
id="path1543" />
|
|
39
|
+
<path
|
|
40
|
+
style="fill:#1c7361;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
|
41
|
+
d="m 516.13281,445.13672 c 0.48438,-0.70313 1.78125,-0.4336 1.94141,0.42969 -0.64844,-0.10547 -1.34766,0.10937 -1.78125,0.59375 -0.26953,0.10937 -0.70313,-0.10547 -0.70313,-0.42969 -0.0508,-0.26953 0.27344,-0.59375 0.59375,-0.54297"
|
|
42
|
+
id="path1545" />
|
|
43
|
+
<path
|
|
44
|
+
style="fill:#1c7361;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
|
45
|
+
d="m 547.00781,410.58984 c 0.26953,-0.10937 0.64844,-0.21875 0.91797,-0.10937 0.32422,0.10937 0.48438,0.59375 0.26953,0.80859 -1.02734,0.64844 -2.21484,1.02735 -3.40234,1.08203 0.54297,-0.75781 1.35156,-1.35156 2.21484,-1.78125"
|
|
46
|
+
id="path1547" />
|
|
47
|
+
<path
|
|
48
|
+
style="fill:#1c7361;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
|
49
|
+
d="m 562.92969,579.27344 c 0.54297,0.3789 1.13672,0.75781 1.67578,1.13281 -1.1875,0.48828 -2.58985,0.21875 -3.5625,-0.64453 -0.21485,-0.37891 0.21484,-0.91797 0.59375,-0.91797 0.48437,-0.0547 0.91797,0.21484 1.29297,0.42969"
|
|
50
|
+
id="path1549" />
|
|
51
|
+
<path
|
|
52
|
+
style="fill:#1c7361;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
|
53
|
+
d="m 538.26172,405.62109 c -0.26953,-0.80859 -0.0547,-1.78125 0.59375,-2.375 0.43359,-0.10547 0.86328,-0.42968 1.02734,-0.91797 0.69922,0.26954 1.34766,0.54297 2.05078,0.8125 -1.1875,0.8086 -2.42968,1.61719 -3.67187,2.48047"
|
|
54
|
+
id="path1551" />
|
|
55
|
+
<path
|
|
56
|
+
style="fill:#1c7361;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
|
57
|
+
d="m 511.92187,463.59766 c 0,-0.32422 0,-0.64844 0,-0.97266 0.53907,-0.26953 1.13282,-0.26953 1.61719,-0.0547 -0.96875,1.02735 -1.51172,2.42969 -1.40234,3.83203 -0.59375,-0.42968 -1.24219,-0.91797 -1.89063,-1.34765 0.54297,-0.4336 1.13672,-0.91797 1.73047,-1.40625"
|
|
58
|
+
id="path1553" />
|
|
59
|
+
<path
|
|
60
|
+
style="fill:#1c7361;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
|
61
|
+
d="m 508.35937,415.93359 c 0.21485,-1.67578 1.1875,-3.1875 2.53516,-4.21093 0.37891,-0.26954 0.97266,-0.4336 1.1875,-0.0547 -1.1875,1.1875 -2.16016,2.53515 -2.85937,4.04687 -0.16407,0.27344 -0.59375,0.4336 -0.86329,0.21875"
|
|
62
|
+
id="path1555" />
|
|
63
|
+
<path
|
|
64
|
+
style="fill:#1c7361;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
|
65
|
+
d="m 513.91797,449.39844 c 1.07812,-0.8086 2.10547,-1.61719 3.18359,-2.42969 -0.26953,1.02734 -0.53906,1.94531 -0.80859,2.96875 -0.37891,0.21875 -0.64844,0.59766 -1.02344,0.8125 -0.37891,0.21484 -0.91797,0.26953 -1.1875,-0.10938 -0.21875,-0.3789 0.375,-0.91796 0.59375,-0.53906 -0.21875,-0.21484 -0.48828,-0.43359 -0.75781,-0.70312"
|
|
66
|
+
id="path1557" />
|
|
67
|
+
<path
|
|
68
|
+
style="fill:#1c7361;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
|
69
|
+
d="m 555.05078,407.56641 c -0.10937,0.26953 -0.21484,0.53906 -0.10937,0.86328 -0.86329,0.16015 -1.67188,0.32422 -2.42969,0.48437 -0.10547,0.32422 -0.21485,0.64844 -0.32031,0.97266 -0.64844,-0.0547 -1.29688,-0.0547 -1.89063,-0.0547 -0.53906,-0.26953 0,-1.02344 0.53906,-1.29297 1.07813,-0.54297 2.21485,-0.86719 3.40235,-1.02734 -0.16407,-0.26953 -0.32422,-0.48438 -0.48828,-0.75391 0.86328,-0.70312 1.89062,-1.1875 3.02343,-1.51172 0.21485,0.375 0.26953,0.8086 0.16407,1.23828 -0.37891,0.16407 -0.75782,0.21875 -1.13672,0.10938 0.0547,0.26953 0.10937,0.53906 0.16406,0.86328 -0.37891,0.10938 -0.64844,0.16406 -0.91797,0.10938"
|
|
70
|
+
id="path1559" />
|
|
71
|
+
<path
|
|
72
|
+
style="fill:#1c7361;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
|
73
|
+
d="m 512.83984,412.64062 c 0.42969,-0.26953 1.02344,-0.3789 1.51172,-0.26953 -0.21875,-0.26953 -0.3789,-0.54297 -0.54297,-0.8125 0.54297,-0.10547 1.08203,-0.21484 1.67578,-0.26953 0.21485,-0.53906 0.21485,-1.1875 0,-1.72656 0.59375,-0.0547 1.24219,0.0547 1.78125,0.26953 0.16016,0.21484 0.21485,0.53906 0.16016,0.80859 -0.26953,0.10938 -0.59375,0.21875 -0.91797,0.32422 -0.10547,0.54297 -0.26953,1.08203 -0.375,1.6211 -0.26953,0.16015 -0.70312,0.21484 -1.02734,0.10937 -0.48438,2.91406 -3.67188,4.58594 -4.80469,7.28516 -0.37891,0.91797 -0.75391,2.10547 -1.72656,2.10547 -0.26953,-0.32422 -0.21485,-0.91797 0.16015,-1.1875 -0.375,-0.10938 -0.69921,-0.21485 -1.02343,-0.32422 -0.0547,-0.59375 0.91797,-0.42969 1.40234,-0.0547 0.43359,-0.375 0.0547,-1.24219 -0.48437,-1.24219 0.59375,-0.48437 0.97265,-1.23828 1.07812,-1.99609 0.59375,0.0547 1.1875,-0.16016 1.56641,-0.59375 -0.4336,0.10937 -0.91797,-0.21484 -1.02735,-0.69922 0.86328,0.16016 1.73047,-0.64844 1.67578,-1.51172 0.64844,-0.3789 1.29297,-0.75781 1.94141,-1.13672 -0.26953,-0.16015 -0.64844,-0.42968 -1.02344,-0.69922"
|
|
74
|
+
id="path1561" />
|
|
75
|
+
<path
|
|
76
|
+
style="fill:#1c7361;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
|
77
|
+
d="m 682.38672,415.5 c -1.1875,-1.61719 -2.42969,-3.18359 -3.9375,-4.53516 -2.10547,-1.88672 -4.80469,-3.5625 -5.23828,-6.36718 12.6875,10.74218 22.45703,24.9375 27.90625,40.64453 0.48828,0.43359 -0.0508,1.40625 -0.64453,1.24218 -4.75,-10.95703 -10.85157,-21.42968 -18.08594,-30.98437"
|
|
78
|
+
id="path1563" />
|
|
79
|
+
<path
|
|
80
|
+
style="fill:#1c7361;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
|
81
|
+
d="m 539.88281,406.97266 c 2.21094,-1.78125 4.75,-3.45704 5.66797,-6.15625 0.26953,-0.75391 1.02344,-1.34766 1.72656,-1.78125 10.90235,-6.85547 23.64453,-10.63282 36.48828,-10.84766 -6.42187,1.72656 -12.79296,3.39844 -19.21484,5.12891 -9.98437,2.64453 -17.32812,10.90234 -24.07422,18.78515 -5.83203,6.85547 -11.71484,13.71094 -17.54297,20.61719 -0.70312,1.89062 -1.35156,3.83203 -2.05078,5.72266 -0.26953,0.86328 -0.59375,1.72656 -1.35156,2.26562 -0.69922,0.54297 -1.88672,0.54297 -2.32031,-0.26953 2.58984,-4.53125 5.18359,-9.12109 7.82812,-13.71094 4.21094,-7.125 8.41797,-14.46484 14.84375,-19.7539"
|
|
82
|
+
id="path1565" />
|
|
83
|
+
</g>
|
|
84
|
+
</svg>
|