From 1846abeadc8b3c37f9fd236e2188a8dccca39767 Mon Sep 17 00:00:00 2001 From: vincent d warmerdam Date: Thu, 20 Jun 2024 13:45:20 +0200 Subject: [PATCH 1/3] finally --- mandr/app.py | 39 ++++++++++++++++++++++++++++- mandr/templates/sketchpad.html | 45 ++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 mandr/templates/sketchpad.html diff --git a/mandr/app.py b/mandr/app.py index 6abe75c7..39100d24 100644 --- a/mandr/app.py +++ b/mandr/app.py @@ -1,4 +1,4 @@ -from flask import Flask, Response +from flask import Flask, Response, request from pathlib import Path import json from jinja2 import Template @@ -13,6 +13,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 +25,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 +39,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 +65,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,6 +78,7 @@ def render_mander(*args): res += render_mid_nav(*args) return t.render(body=res) + @app.route('/', defaults={'path': ''}) @app.route('/') def home(path): @@ -89,5 +98,33 @@ def home(path): return render_artifacts(*path_parts[1:]) return render_mander(*path.split('/')) + +@app.route('/sketchpad') +def sketchpad(): + return read_template('sketchpad.html').render() + + +@app.post('/autocomplete') +def autocomplete(): + last_path = Path(request.form['path']) + if (Path('.datamander') / last_path).exists(): + entry_path = Path(f'.datamander/{last_path}') + else: + entry_path = Path(f'.datamander/{last_path.parent}') + console.log(f'{entry_path=} {last_path=}') + if entry_path.exists() and entry_path.parts[0] == '.datamander' and entry_path.is_dir(): + paths = entry_path.iterdir() + else: + paths = Path('.datamander').iterdir() + print(request.form) + return ''.join(f'

{p}

' for p in paths if p.is_dir() and not p.parts[-1].startswith('.')) + + +@app.post('/render') +def render(): + print(request.form) + return 'this is the rendered template/mander combo' + + if __name__ == '__main__': app.run(debug=True, reload=True) diff --git a/mandr/templates/sketchpad.html b/mandr/templates/sketchpad.html new file mode 100644 index 00000000..4e81442d --- /dev/null +++ b/mandr/templates/sketchpad.html @@ -0,0 +1,45 @@ + + + + + + + Template Sketchpad + + + + + + + + + + +
+
+

Template Sketchpad

+ The template can be edited on the right and will be live updated. +
+
+
+

Mander path

+ +

+
+

Template

+ +
+ +
+
+

Rendered output

+
+
+

+
+
+
+
+
+ + \ No newline at end of file From e6535fc7dbc92281277cd62e79308281031c82e6 Mon Sep 17 00:00:00 2001 From: vincent d warmerdam Date: Thu, 20 Jun 2024 15:27:19 +0200 Subject: [PATCH 2/3] scrathpad --- mandr/app.py | 40 +++++++++++++--------------------- mandr/infomander.py | 1 + mandr/templates.py | 7 ++++-- mandr/templates/sketchpad.html | 15 +++++++------ 4 files changed, 29 insertions(+), 34 deletions(-) diff --git a/mandr/app.py b/mandr/app.py index 39100d24..2a9acd38 100644 --- a/mandr/app.py +++ b/mandr/app.py @@ -3,6 +3,7 @@ import json from jinja2 import Template from .infomander import InfoMander, VIEWS_KEY +from .templates import TemplateRenderer from rich.console import Console console = Console() @@ -79,8 +80,8 @@ def render_mander(*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) @@ -96,34 +97,23 @@ 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('/')) -@app.route('/sketchpad') -def sketchpad(): - return read_template('sketchpad.html').render() - - -@app.post('/autocomplete') -def autocomplete(): - last_path = Path(request.form['path']) - if (Path('.datamander') / last_path).exists(): - entry_path = Path(f'.datamander/{last_path}') - else: - entry_path = Path(f'.datamander/{last_path.parent}') - console.log(f'{entry_path=} {last_path=}') - if entry_path.exists() and entry_path.parts[0] == '.datamander' and entry_path.is_dir(): - paths = entry_path.iterdir() - else: - paths = Path('.datamander').iterdir() - print(request.form) - return ''.join(f'

{p}

' for p in paths if p.is_dir() and not p.parts[-1].startswith('.')) +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) -@app.post('/render') -def render(): - print(request.form) - return 'this is the rendered template/mander combo' +def render_template(*path): + mander = fetch_mander(*path) + template_rendered = TemplateRenderer(mander) + return template_rendered.render(request.form['template']) if __name__ == '__main__': diff --git a/mandr/infomander.py b/mandr/infomander.py index 25f46432..30293a5a 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) diff --git a/mandr/templates.py b/mandr/templates.py index 994b0c3b..fc522657 100644 --- a/mandr/templates.py +++ b/mandr/templates.py @@ -53,11 +53,14 @@ 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) return template def render(self, template): final_template = self.insert_custom_ui(template) - return markdown.markdown(Template(final_template).render(**self.datamander.fetch())) + print(self.mander) + res = markdown.markdown(Template(final_template).render(**self.mander.fetch())) + print(res) + return res diff --git a/mandr/templates/sketchpad.html b/mandr/templates/sketchpad.html index 4e81442d..3933f238 100644 --- a/mandr/templates/sketchpad.html +++ b/mandr/templates/sketchpad.html @@ -6,7 +6,7 @@ Template Sketchpad - + @@ -22,19 +22,20 @@

Template Sketchpad

-

Mander path

- -

-
+ {% for child in children %}
+ {{child}} + {% endfor %}

Template

- +

Rendered output

-
+
+
+


From fe0a18a771e617b9c74b16d32fc855951ab3985f Mon Sep 17 00:00:00 2001 From: vincent d warmerdam Date: Fri, 21 Jun 2024 10:24:32 +0200 Subject: [PATCH 3/3] mrg --- mandr/infomander.py | 4 ++-- mandr/templates.py | 6 +++--- mandr/templates/sketchpad.html | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/mandr/infomander.py b/mandr/infomander.py index 30293a5a..55ba1249 100644 --- a/mandr/infomander.py +++ b/mandr/infomander.py @@ -40,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 @@ -63,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 fc522657..b87aa8b9 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] @@ -55,12 +57,10 @@ def insert_custom_ui(self, template): if v.startswith('@mander'): 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) - print(self.mander) res = markdown.markdown(Template(final_template).render(**self.mander.fetch())) - print(res) return res diff --git a/mandr/templates/sketchpad.html b/mandr/templates/sketchpad.html index 3933f238..c03295ba 100644 --- a/mandr/templates/sketchpad.html +++ b/mandr/templates/sketchpad.html @@ -28,7 +28,7 @@

Template Sketchpad

Template

- +

Rendered output