From 90ea94ba9df81d171cbf6eb51bbab5856005eae9 Mon Sep 17 00:00:00 2001 From: daxid <david.rouquet@tetras-libre.fr> Date: Wed, 18 Jan 2023 09:49:22 +0100 Subject: [PATCH] initialize app structure --- launcher.ipynb | 41 +++++++++++++++++++++++++++++++ src/__init__.py | 0 src/appli.py | 49 +++++++++++++++++++++++++++++++++++++ src/callbacks.py | 11 +++++++++ src/components/__init__.py | 0 src/components/component.py | 6 +++++ src/components/window.py | 25 +++++++++++++++++++ src/data.py | 5 ++++ src/view.py | 7 ++++++ 9 files changed, 144 insertions(+) create mode 100644 launcher.ipynb create mode 100644 src/__init__.py create mode 100644 src/appli.py create mode 100644 src/callbacks.py create mode 100644 src/components/__init__.py create mode 100644 src/components/component.py create mode 100644 src/components/window.py create mode 100644 src/data.py create mode 100644 src/view.py diff --git a/launcher.ipynb b/launcher.ipynb new file mode 100644 index 0000000..e85c91c --- /dev/null +++ b/launcher.ipynb @@ -0,0 +1,41 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "1d7eebc2-9325-42ae-8269-47b3091e052c", + "metadata": {}, + "outputs": [], + "source": [ + "from src.data import Data\n", + "from src.view import View\n", + "from src.appli import Appli\n", + "\n", + "data = Data()\n", + "layout = View(data).layout\n", + "appli = Appli(layout, data)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.6" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/src/__init__.py b/src/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/appli.py b/src/appli.py new file mode 100644 index 0000000..53c0b7f --- /dev/null +++ b/src/appli.py @@ -0,0 +1,49 @@ +from jupyter_dash import JupyterDash as Dash +import dash_bootstrap_components as dbc +from src.callbacks import register_callbacks + + +class Appli: + def __init__(self, layout, data): + server_url, host, port, proxy, base_path = self._get_tl_config() + app = Dash( + server_url=server_url, + requests_pathname_prefix=base_path, + ) + app.layout = layout + app.data = data + register_callbacks(app) + app.run_server(mode="inline", host=host, port=port, proxy=proxy) + + + def _get_tl_config(self): + import socket, errno, os + # Find a free port + host = "0.0.0.0" + port = 8050 + end = 9999 + found = False + while not found: + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: + try: + s.bind((host, port)) + found = True + except socket.error as e: + if e.errno == errno.EADDRINUSE: + port = port + 1 + if (port > end): + raise "No available APP port" + else: + raise e + if (os.getenv("HOST", None) is not None): + proto = os.getenv("PROTO") + actualhost = os.getenv("JUPYTER_HOST", os.getenv("VOILA_HOST", "")) + localport = os.getenv("PORT", 80) + intermediatehost = os.getenv("HOST", "localhost") + base_path = f"/{actualhost}/app_proxy/{port}/" + proxified= f"{proto}://{intermediatehost}:{localport}{base_path}" + localurl = f"http://{host}:{port}" + proxy = f"{localurl}::{proxified}" + return ((proxified, host, port, proxy, base_path)) + return ((f"http://localhost:{port}", host, port, None, "/")) + diff --git a/src/callbacks.py b/src/callbacks.py new file mode 100644 index 0000000..c855b16 --- /dev/null +++ b/src/callbacks.py @@ -0,0 +1,11 @@ +from dash import Output, Input + + +def register_callbacks(app): + @app.callback( + Output(component_id="my-output", component_property="children"), + Input(component_id="my-input", component_property="value") + ) + def update_output_div(input_value): + return f"Output: {input_value}" + \ No newline at end of file diff --git a/src/components/__init__.py b/src/components/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/components/component.py b/src/components/component.py new file mode 100644 index 0000000..aad8f9a --- /dev/null +++ b/src/components/component.py @@ -0,0 +1,6 @@ +class Component: + def __init__(self, data): + self.data = data + + def build(self): + raise Error("Not implemented") diff --git a/src/components/window.py b/src/components/window.py new file mode 100644 index 0000000..6cf5e61 --- /dev/null +++ b/src/components/window.py @@ -0,0 +1,25 @@ +from src.components.component import Component +from dash import html, dcc + +class Window(Component): + + def build(self): + return self._layout() + + def _layout(self): + return html.Div(children= + [ + html.H6("Change the value in the text box to see callbacks in action!"), + html.Div(children= + [ + "Input: ", + dcc.Input( + id="my-input", + value=self.data.initial_value, + type="text" + ) + ]), + html.Br(), + html.Div(id="my-output") + ] + ) diff --git a/src/data.py b/src/data.py new file mode 100644 index 0000000..5a954a4 --- /dev/null +++ b/src/data.py @@ -0,0 +1,5 @@ +class Data: + + def __init__(self): + self.initial_value = "my initial value" + \ No newline at end of file diff --git a/src/view.py b/src/view.py new file mode 100644 index 0000000..36fafbe --- /dev/null +++ b/src/view.py @@ -0,0 +1,7 @@ +from src.components.window import Window + + +class View: + def __init__(self, data): + self.layout = Window(data).build() + \ No newline at end of file -- GitLab