Bug Fixes:

- Screen now defaults to the active screen rather than the `0` screen.
- `null` values given in chart data are now removed and replaced with whitespace.
- Closing the chart window now cleanly exits.
- Fixed a bug causing the `offset` parameter to be greater than `0` when there is no offset.
This commit is contained in:
louisnw
2023-09-29 12:03:49 +01:00
parent d43e7c24e7
commit 2bd4c7c037
6 changed files with 19 additions and 10 deletions

View File

@ -3,7 +3,7 @@ import os.path
project = 'lightweight-charts-python' project = 'lightweight-charts-python'
copyright = '2023, louisnw' copyright = '2023, louisnw'
author = 'louisnw' author = 'louisnw'
release = '1.0.17.6' release = '1.0.17.7'
extensions = [ extensions = [
"myst_parser", "myst_parser",

View File

@ -324,11 +324,11 @@ ___
```{py:method} hotkey(modifier: 'ctrl' | 'alt' | 'shift' | 'meta', key: 'str' | 'int' | 'tuple', func: callable) ```{py:method} hotkey(modifier: 'ctrl' | 'alt' | 'shift' | 'meta' | None, key: 'str' | 'int' | 'tuple', func: callable)
Adds a global hotkey to the chart window, which will execute the method or function given. Adds a global hotkey to the chart window, which will execute the method or function given.
When using a number in `key`, it should be given as an integer. If multiple key commands are needed for the same function, a tuple can be passed to `key`. If multiple key commands are needed for the same function, a tuple can be passed to `key`.
``` ```
___ ___

View File

@ -134,6 +134,7 @@ class SeriesCommon(Pane):
self._last_bar = None self._last_bar = None
self.name = name self.name = name
self.num_decimals = 2 self.num_decimals = 2
self.offset = 0
def _set_interval(self, df: pd.DataFrame): def _set_interval(self, df: pd.DataFrame):
if not pd.api.types.is_datetime64_any_dtype(df['time']): if not pd.api.types.is_datetime64_any_dtype(df['time']):
@ -155,7 +156,7 @@ class SeriesCommon(Pane):
value = value.total_seconds() value = value.total_seconds()
if value == 0: if value == 0:
continue continue
elif value > self._interval: elif value >= self._interval:
break break
self.offset = value self.offset = value
break break

View File

@ -31,8 +31,8 @@ class PyWV:
webview.start(debug=debug) webview.start(debug=debug)
self.exit.set() self.exit.set()
def create_window(self, width, height, x, y, screen=0, on_top=False, maximize=False): def create_window(self, width, height, x, y, screen=None, on_top=False, maximize=False):
screen = webview.screens[screen] screen = webview.screens[screen] if screen is not None else None
if maximize: if maximize:
width, height = screen.width, screen.height width, height = screen.width, screen.height
self.windows.append(webview.create_window( self.windows.append(webview.create_window(
@ -69,7 +69,7 @@ class Chart(abstract.AbstractChart):
_q, _emit_q, _return_q = (mp.Queue() for _ in range(3)) _q, _emit_q, _return_q = (mp.Queue() for _ in range(3))
_loaded_list = [mp.Event() for _ in range(MAX_WINDOWS)] _loaded_list = [mp.Event() for _ in range(MAX_WINDOWS)]
def __init__(self, width: int = 800, height: int = 600, x: int = None, y: int = None, screen: int = 0, def __init__(self, width: int = 800, height: int = 600, x: int = None, y: int = None, screen: int = None,
on_top: bool = False, maximize: bool = False, debug: bool = False, toolbox: bool = False, 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): inner_width: float = 1.0, inner_height: float = 1.0, scale_candles_only: bool = False):
self._i = Chart._window_num self._i = Chart._window_num
@ -121,6 +121,7 @@ class Chart(abstract.AbstractChart):
if self._exit.is_set(): if self._exit.is_set():
self._exit.clear() self._exit.clear()
self.is_alive = False self.is_alive = False
self.exit()
return return
elif not self._emit_q.empty(): elif not self._emit_q.empty():
func, args = parse_event_message(self.win, self._emit_q.get()) func, args = parse_event_message(self.win, self._emit_q.get())
@ -146,4 +147,5 @@ class Chart(abstract.AbstractChart):
Chart._main_window_handlers = None Chart._main_window_handlers = None
Chart._window_num = 0 Chart._window_num = 0
Chart._q = mp.Queue() Chart._q = mp.Queue()
Chart._exit.clear(), Chart._start.clear()
self.is_alive = False self.is_alive = False

View File

@ -1,4 +1,5 @@
import asyncio import asyncio
import json
from datetime import datetime from datetime import datetime
from random import choices from random import choices
from typing import Literal, Union from typing import Literal, Union
@ -34,8 +35,13 @@ def parse_event_message(window, string):
def js_data(data: Union[pd.DataFrame, pd.Series]): def js_data(data: Union[pd.DataFrame, pd.Series]):
orient = 'columns' if isinstance(data, pd.Series) else 'records' if isinstance(data, pd.DataFrame):
return data.to_json(orient=orient, default_handler=lambda x: 'null' if pd.isna(x) else x) d = data.to_dict(orient='records')
filtered_records = [{k: v for k, v in record.items() if v is not None} for record in d]
else:
d = data.to_dict()
filtered_records = {k: v for k, v in d.items()}
return json.dumps(filtered_records, indent=2)
def jbool(b: bool): return 'true' if b is True else 'false' if b is False else None def jbool(b: bool): return 'true' if b is True else 'false' if b is False else None

View File

@ -5,7 +5,7 @@ with open('README.md', 'r', encoding='utf-8') as f:
setup( setup(
name='lightweight_charts', name='lightweight_charts',
version='1.0.17.6', version='1.0.17.7',
packages=find_packages(), packages=find_packages(),
python_requires='>=3.8', python_requires='>=3.8',
install_requires=[ install_requires=[