diff --git a/mandr/app.py b/mandr/app.py
index 6abe75c7d..2a9acd385 100644
--- a/mandr/app.py
+++ b/mandr/app.py
@@ -1,8 +1,9 @@
-from flask import Flask, Response
+from flask import Flask, Response, request
from pathlib import Path
import json
from jinja2 import Template
from .infomander import InfoMander, VIEWS_KEY
+from .templates import TemplateRenderer
from rich.console import Console
console = Console()
@@ -13,6 +14,7 @@
def fetch_mander(*path):
return InfoMander('/'.join(path))
+
def render_views(*path):
mander = fetch_mander(*path)
view_nav_templ = read_template('partials/views.html')
@@ -24,10 +26,12 @@ def render_views(*path):
first_name=first_name
)
+
def render_info(*path):
mander = fetch_mander(*path)
return '
' + json.dumps({k: str(v) for k, v in mander.fetch().items() if not k.startswith("_")}, indent=2) + '
'
+
def render_logs(*path):
mander = fetch_mander(*path)
view_nav_templ = read_template('partials/logs.html')
@@ -36,15 +40,18 @@ def render_logs(*path):
first_name=list(mander['_logs'].items())[0][0]
)
+
def render_artifacts(*path):
mander = fetch_mander(*path)
view_nav_templ = read_template('partials/artifacts.html')
return view_nav_templ.render(artifacts=list(mander['_artifacts'].items()))
+
def read_template(path):
p = Path(__file__).parent / 'templates' / path
return Template(p.read_text())
+
def render_top_nav(*args):
nav_temp = read_template('partials/nav-top.html')
path_pairs = []
@@ -59,10 +66,12 @@ def render_top_nav(*args):
console.log(f'{path_pairs=}')
return nav_temp.render(path_pairs=path_pairs, links_out=links_out)
+
def render_mid_nav(*args):
nav_temp = read_template('partials/nav-mid.html')
return nav_temp.render(path='/'.join(args))
+
def render_mander(*args):
p = Path(__file__).parent / 'templates' / 'page.html'
t = Template(p.read_text())
@@ -70,8 +79,9 @@ def render_mander(*args):
res += render_mid_nav(*args)
return t.render(body=res)
-@app.route('/', defaults={'path': ''})
-@app.route('/')
+
+@app.route('/', defaults={'path': ''}, methods=['GET', 'POST'])
+@app.route('/', methods=['GET', 'POST'])
def home(path):
if 'favicon' in path:
return Response('', status=400)
@@ -87,7 +97,24 @@ def home(path):
return render_logs(*path_parts[1:])
if path_parts[0] == 'artifacts':
return render_artifacts(*path_parts[1:])
+ if path_parts[0] == 'sketchpad':
+ return render_sketchpad(*path_parts[1:])
+ if path_parts[0] == 'render':
+ return render_template(*path_parts[1:])
return render_mander(*path.split('/'))
+
+def render_sketchpad(*path):
+ mander = fetch_mander(*path)
+ children = [f'{m.path}' for m in mander.children()]
+ return read_template('sketchpad.html').render(children=sorted(children), mander_path=mander.path)
+
+
+def render_template(*path):
+ mander = fetch_mander(*path)
+ template_rendered = TemplateRenderer(mander)
+ return template_rendered.render(request.form['template'])
+
+
if __name__ == '__main__':
app.run(debug=True, reload=True)
diff --git a/mandr/infomander.py b/mandr/infomander.py
index 25f46432e..55ba1249d 100644
--- a/mandr/infomander.py
+++ b/mandr/infomander.py
@@ -20,6 +20,7 @@ class InfoMander:
"""Represents a dictionary, on disk, with a path-like structure."""
def __init__(self, path):
# Set local disk paths
+ self.path = path
self.project_path = Path('.datamander/' + path)
self.cache = Cache(self.project_path / STATS_FOLDER)
@@ -39,7 +40,7 @@ def __init__(self, path):
def _check_key(self, key):
if key in [ARTIFACTS_KEY, TEMPLATES_KEY, VIEWS_KEY, LOGS_KEY]:
raise ValueError(f'Cannot overwrite {key} key. This is reserved for internal use.')
-
+
def add_info(self, key, value, method='overwrite'):
if method == 'overwrite':
self.cache[key] = value
@@ -62,7 +63,7 @@ def add_artifact(self, key, obj, **metadata):
if not file_location.parent.exists():
file_location.parent.mkdir(parents=True)
dump(obj, file_location)
- self._add_to_key(ARTIFACTS_KEY, key, {'path': file_location, **metadata})
+ self._add_to_key(ARTIFACTS_KEY, key, {'obj': obj, **metadata})
def add_view(self, key, html):
self._check_key(key)
diff --git a/mandr/templates.py b/mandr/templates.py
index 994b0c3b7..b87aa8b9c 100644
--- a/mandr/templates.py
+++ b/mandr/templates.py
@@ -7,6 +7,7 @@
def sklearn_model_repr(pipeline):
+ print('pipeline', pipeline)
return estimator_html_repr(pipeline)
@@ -45,6 +46,7 @@ def insert_custom_ui(self, template):
# For each registered element, check if it is there.
for name, func in registry.items():
element_of_interest = f'<{name}'
+ print('element_of_interest', element_of_interest)
start = template.find(element_of_interest)
end = template[start:].find("/>")
substr = template[start:start + end + 2]
@@ -53,11 +55,12 @@ def insert_custom_ui(self, template):
params = {k: self.clean_value(v) for k, v in elems}
for k, v in params.items():
if v.startswith('@mander'):
- params[k] = self.datamander.get(v)
+ params[k] = self.mander.get(v)
ui = func(**params)
- return template.replace(substr, ui)
+ template = template.replace(substr, ui)
return template
def render(self, template):
final_template = self.insert_custom_ui(template)
- return markdown.markdown(Template(final_template).render(**self.datamander.fetch()))
+ res = markdown.markdown(Template(final_template).render(**self.mander.fetch()))
+ return res
diff --git a/mandr/templates/sketchpad.html b/mandr/templates/sketchpad.html
new file mode 100644
index 000000000..c03295ba1
--- /dev/null
+++ b/mandr/templates/sketchpad.html
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+ Template Sketchpad
+
+
+
+
+
+
+
+
+
+
+
+
+
Template Sketchpad
+
The template can be edited on the right and will be live updated.
+
+
+
+
+
\ No newline at end of file