From 7b1b30d66770f3c75a9039f9d316551912a964e1 Mon Sep 17 00:00:00 2001 From: Krytech Date: Fri, 3 May 2024 12:33:05 +0200 Subject: [PATCH 1/7] Flask chart added --- docs/source/examples/gui_examples.md | 24 +++++++++++++++++++++++- lightweight_charts/widgets.py | 13 +++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/docs/source/examples/gui_examples.md b/docs/source/examples/gui_examples.md index 06780680..e6f88787 100644 --- a/docs/source/examples/gui_examples.md +++ b/docs/source/examples/gui_examples.md @@ -95,4 +95,26 @@ df = pd.read_csv('ohlcv.csv') chart.set(df) chart.load() -``` \ No newline at end of file +``` +___ + +## Flask + +```python +from lightweight_charts.widgets import FlaskChart +from flask import Flask +import pandas as pd + +app = Flask(__name__) + +@app.route('/') +def static_chart(): + df = pd.read_csv('./1_setting_data/ohlcv.csv') + + chart = FlaskChart(title='My Static Chart') + chart.set(df) + return chart.load() + +if __name__ == '__main__': + app.run() +``` diff --git a/lightweight_charts/widgets.py b/lightweight_charts/widgets.py index ff276782..924739a3 100644 --- a/lightweight_charts/widgets.py +++ b/lightweight_charts/widgets.py @@ -4,6 +4,10 @@ from .util import parse_event_message from lightweight_charts import abstract +from flask import render_template +import jinja2 +import re + try: import wx.html2 except ImportError: @@ -126,6 +130,15 @@ def load(self): def _load(self): pass +class FlaskChart(StaticLWC): + def __init__(self, title='Lightweight Chart', *args, **kwargs): + super().__init__(*args, **kwargs) + self.title = title + + def load(self): + super().load() + self._html = re.sub(r'.*?', f'{self.title}', self._html, flags=re.DOTALL) + return render_template(jinja2.Template(f'{self._html}')) class StreamlitChart(StaticLWC): def __init__(self, width=None, height=None, inner_width=1, inner_height=1, scale_candles_only: bool = False, toolbox: bool = False): From ff6c1567e7b3fd0d7b20564c90cce54f5b8d4672 Mon Sep 17 00:00:00 2001 From: Krytech Date: Fri, 3 May 2024 12:40:45 +0200 Subject: [PATCH 2/7] Flask chart added --- docs/source/examples/gui_examples.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/examples/gui_examples.md b/docs/source/examples/gui_examples.md index e6f88787..3aba2346 100644 --- a/docs/source/examples/gui_examples.md +++ b/docs/source/examples/gui_examples.md @@ -109,7 +109,7 @@ app = Flask(__name__) @app.route('/') def static_chart(): - df = pd.read_csv('./1_setting_data/ohlcv.csv') + df = pd.read_csv('ohlcv.csv') chart = FlaskChart(title='My Static Chart') chart.set(df) From ea074e0e06d6100a8fe6e6888fbdf63272763b8e Mon Sep 17 00:00:00 2001 From: Krytech Date: Wed, 15 May 2024 17:43:49 +0200 Subject: [PATCH 3/7] update --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index 13df00e4..d0f65ebc 100644 --- a/setup.py +++ b/setup.py @@ -11,6 +11,7 @@ install_requires=[ 'pandas', 'pywebview>=4.3', + 'flask', ], package_data={ 'lightweight_charts': ['js/*.js'], From b7eb99f7107e7ae2b72c2bdf678dbcfe2f8975d7 Mon Sep 17 00:00:00 2001 From: Krytech Date: Wed, 15 May 2024 17:54:46 +0200 Subject: [PATCH 4/7] update --- docs/source/examples/gui_examples.md | 22 ---------------------- lightweight_charts/widgets.py | 13 ------------- setup.py | 1 - 3 files changed, 36 deletions(-) diff --git a/docs/source/examples/gui_examples.md b/docs/source/examples/gui_examples.md index 3aba2346..73a3d79c 100644 --- a/docs/source/examples/gui_examples.md +++ b/docs/source/examples/gui_examples.md @@ -96,25 +96,3 @@ chart.set(df) chart.load() ``` -___ - -## Flask - -```python -from lightweight_charts.widgets import FlaskChart -from flask import Flask -import pandas as pd - -app = Flask(__name__) - -@app.route('/') -def static_chart(): - df = pd.read_csv('ohlcv.csv') - - chart = FlaskChart(title='My Static Chart') - chart.set(df) - return chart.load() - -if __name__ == '__main__': - app.run() -``` diff --git a/lightweight_charts/widgets.py b/lightweight_charts/widgets.py index 924739a3..ff276782 100644 --- a/lightweight_charts/widgets.py +++ b/lightweight_charts/widgets.py @@ -4,10 +4,6 @@ from .util import parse_event_message from lightweight_charts import abstract -from flask import render_template -import jinja2 -import re - try: import wx.html2 except ImportError: @@ -130,15 +126,6 @@ def load(self): def _load(self): pass -class FlaskChart(StaticLWC): - def __init__(self, title='Lightweight Chart', *args, **kwargs): - super().__init__(*args, **kwargs) - self.title = title - - def load(self): - super().load() - self._html = re.sub(r'.*?', f'{self.title}', self._html, flags=re.DOTALL) - return render_template(jinja2.Template(f'{self._html}')) class StreamlitChart(StaticLWC): def __init__(self, width=None, height=None, inner_width=1, inner_height=1, scale_candles_only: bool = False, toolbox: bool = False): diff --git a/setup.py b/setup.py index d0f65ebc..13df00e4 100644 --- a/setup.py +++ b/setup.py @@ -11,7 +11,6 @@ install_requires=[ 'pandas', 'pywebview>=4.3', - 'flask', ], package_data={ 'lightweight_charts': ['js/*.js'], From 01e692be6f4879afc55d29d114aa5edcf6995e1c Mon Sep 17 00:00:00 2001 From: Krytech Date: Wed, 15 May 2024 18:05:11 +0200 Subject: [PATCH 5/7] frameless chart option added --- lightweight_charts/chart.py | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/lightweight_charts/chart.py b/lightweight_charts/chart.py index 19eb805a..64748d80 100644 --- a/lightweight_charts/chart.py +++ b/lightweight_charts/chart.py @@ -2,6 +2,12 @@ import multiprocessing as mp import webview +# temporary until we fix to pywebview v5 +try: + from webview.errors import JavascriptException +except ModuleNotFoundError: + JavascriptException = Exception + from lightweight_charts import abstract from .util import parse_event_message, FLOAT @@ -16,7 +22,7 @@ def callback(self, message: str): class PyWV: def __init__(self, q, start_ev, exit_ev, loaded, emit_queue, return_queue, html, debug, - width, height, x, y, screen, on_top, maximize, title): + width, height, x, y, screen, on_top, maximize, title, frameless): self.queue = q self.return_queue = return_queue self.exit = exit_ev @@ -25,13 +31,13 @@ def __init__(self, q, start_ev, exit_ev, loaded, emit_queue, return_queue, html, self.html = html self.windows = [] - self.create_window(width, height, x, y, screen, on_top, maximize, title) + self.create_window(width, height, x, y, screen, on_top, maximize, title, frameless) start_ev.wait() webview.start(debug=debug) self.exit.set() - def create_window(self, width, height, x, y, screen=None, on_top=False, maximize=False, title=''): + def create_window(self, width, height, x, y, screen=None, on_top=False, maximize=False, title='', frameless=False): screen = webview.screens[screen] if screen is not None else None if maximize: if screen is None: @@ -40,7 +46,7 @@ def create_window(self, width, height, x, y, screen=None, on_top=False, maximize else: width, height = screen.width, screen.height self.windows.append(webview.create_window( - title, html=self.html, js_api=self.callback_api, + title, html=self.html, js_api=self.callback_api, frameless=frameless, width=width, height=height, x=x, y=y, screen=screen, on_top=on_top, background_color='#000000')) self.windows[-1].events.loaded += lambda: self.loop(self.loaded[len(self.windows)-1]) @@ -61,8 +67,12 @@ def loop(self, loaded): self.return_queue.put(self.windows[i].evaluate_js(arg[14:])) else: self.windows[i].evaluate_js(arg) - except KeyError: + except KeyError as e: return + except JavascriptException as e: + pass + # msg = eval(str(e)) + # raise JavascriptException(f"\n\nscript -> '{arg}',\nerror -> {msg['name']}[{msg['line']}:{msg['column']}]\n{msg['message']}") class Chart(abstract.AbstractChart): @@ -76,7 +86,7 @@ class Chart(abstract.AbstractChart): def __init__(self, width: int = 800, height: int = 600, x: int = None, y: int = None, title: str = '', screen: int = None, on_top: bool = False, maximize: bool = False, debug: bool = False, toolbox: bool = False, inner_width: float = 1.0, inner_height: float = 1.0, - scale_candles_only: bool = False, position: FLOAT = 'left'): + scale_candles_only: bool = False, position: FLOAT = 'left', frameless: bool = False): self._i = Chart._window_num self._loaded = Chart._loaded_list[self._i] abstract.Window._return_q = Chart._return_q @@ -90,13 +100,13 @@ def __init__(self, width: int = 800, height: int = 600, x: int = None, y: int = self._process = mp.Process(target=PyWV, args=( self._q, self._start, self._exit, Chart._loaded_list, self._emit_q, self._return_q, abstract.TEMPLATE, debug, - width, height, x, y, screen, on_top, maximize, title + width, height, x, y, screen, on_top, maximize, title, frameless ), daemon=True) self._process.start() else: window.handlers = Chart._main_window_handlers super().__init__(window, inner_width, inner_height, scale_candles_only, toolbox, position=position) - self._q.put(('create_window', (width, height, x, y, screen, on_top, maximize, title))) + self._q.put(('create_window', (width, height, x, y, screen, on_top, maximize, title, frameless))) def show(self, block: bool = False): """ From a83921da8315ba2adae086c073ed03e8b61f4d93 Mon Sep 17 00:00:00 2001 From: Krytech Date: Thu, 16 May 2024 10:41:40 +0200 Subject: [PATCH 6/7] easy_drag = False --- lightweight_charts/chart.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lightweight_charts/chart.py b/lightweight_charts/chart.py index 64748d80..6d7abb45 100644 --- a/lightweight_charts/chart.py +++ b/lightweight_charts/chart.py @@ -22,7 +22,7 @@ def callback(self, message: str): class PyWV: def __init__(self, q, start_ev, exit_ev, loaded, emit_queue, return_queue, html, debug, - width, height, x, y, screen, on_top, maximize, title, frameless): + width, height, x, y, screen, on_top, maximize, title, frameless, easy_drag): self.queue = q self.return_queue = return_queue self.exit = exit_ev @@ -31,13 +31,13 @@ def __init__(self, q, start_ev, exit_ev, loaded, emit_queue, return_queue, html, self.html = html self.windows = [] - self.create_window(width, height, x, y, screen, on_top, maximize, title, frameless) + self.create_window(width, height, x, y, screen, on_top, maximize, title, frameless, easy_drag) start_ev.wait() webview.start(debug=debug) self.exit.set() - def create_window(self, width, height, x, y, screen=None, on_top=False, maximize=False, title='', frameless=False): + def create_window(self, width, height, x, y, screen=None, on_top=False, maximize=False, title='', frameless=False, easy_drag=False): screen = webview.screens[screen] if screen is not None else None if maximize: if screen is None: @@ -46,7 +46,7 @@ def create_window(self, width, height, x, y, screen=None, on_top=False, maximize else: width, height = screen.width, screen.height self.windows.append(webview.create_window( - title, html=self.html, js_api=self.callback_api, frameless=frameless, + title, html=self.html, js_api=self.callback_api, frameless=frameless, easy_drag=easy_drag, width=width, height=height, x=x, y=y, screen=screen, on_top=on_top, background_color='#000000')) self.windows[-1].events.loaded += lambda: self.loop(self.loaded[len(self.windows)-1]) @@ -86,7 +86,7 @@ class Chart(abstract.AbstractChart): def __init__(self, width: int = 800, height: int = 600, x: int = None, y: int = None, title: str = '', screen: int = None, on_top: bool = False, maximize: bool = False, debug: bool = False, toolbox: bool = False, inner_width: float = 1.0, inner_height: float = 1.0, - scale_candles_only: bool = False, position: FLOAT = 'left', frameless: bool = False): + scale_candles_only: bool = False, position: FLOAT = 'left', frameless: bool = False, easy_drag: bool = False): self._i = Chart._window_num self._loaded = Chart._loaded_list[self._i] abstract.Window._return_q = Chart._return_q @@ -100,13 +100,13 @@ def __init__(self, width: int = 800, height: int = 600, x: int = None, y: int = self._process = mp.Process(target=PyWV, args=( self._q, self._start, self._exit, Chart._loaded_list, self._emit_q, self._return_q, abstract.TEMPLATE, debug, - width, height, x, y, screen, on_top, maximize, title, frameless + width, height, x, y, screen, on_top, maximize, title, frameless, easy_drag ), daemon=True) self._process.start() else: window.handlers = Chart._main_window_handlers super().__init__(window, inner_width, inner_height, scale_candles_only, toolbox, position=position) - self._q.put(('create_window', (width, height, x, y, screen, on_top, maximize, title, frameless))) + self._q.put(('create_window', (width, height, x, y, screen, on_top, maximize, title, frameless, easy_drag))) def show(self, block: bool = False): """ From 4351ade3d5be2cd3afe7246bd111d534bdccca0a Mon Sep 17 00:00:00 2001 From: Krytech Date: Wed, 5 Jun 2024 16:20:07 +0200 Subject: [PATCH 7/7] merge 2.0 --- lightweight_charts/chart.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/lightweight_charts/chart.py b/lightweight_charts/chart.py index 305534c8..38d4f68d 100644 --- a/lightweight_charts/chart.py +++ b/lightweight_charts/chart.py @@ -36,7 +36,7 @@ def __init__(self, q, emit_q, return_q, loaded_event): def create_window( self, width, height, x, y, screen=None, on_top=False, - maximize=False, title='' + maximize=False, title='', frameless=False, easy_drag=False ): screen = webview.screens[screen] if screen is not None else None if maximize: @@ -56,7 +56,9 @@ def create_window( y=y, screen=screen, on_top=on_top, - background_color='#000000') + background_color='#000000', + frameless=frameless, + easy_drag=easy_drag) ) self.windows[-1].events.loaded += lambda: self.loaded_event.set() @@ -115,11 +117,11 @@ def _reset(self): def create_window( self, width, height, x, y, screen=None, on_top=False, - maximize=False, title='' + maximize=False, title='', frameless=False, easy_drag=False ): self.function_call_queue.put(( 'create_window', - (width, height, x, y, screen, on_top, maximize, title) + (width, height, x, y, screen, on_top, maximize, title, frameless, easy_drag) )) self.max_window_num += 1 return self.max_window_num @@ -165,11 +167,13 @@ def __init__( inner_width: float = 1.0, inner_height: float = 1.0, scale_candles_only: bool = False, - position: FLOAT = 'left' + position: FLOAT = 'left', + frameless: bool = False, + easy_drag: bool = False ): Chart.WV.debug = debug self._i = Chart.WV.create_window( - width, height, x, y, screen, on_top, maximize, title + width, height, x, y, screen, on_top, maximize, title, frameless, easy_drag ) window = abstract.Window(