feat: use latest flet, try to fix threading issues

see also, previous comment in pyproject.toml (removed in this commit).

there is some event loop error happening on app exit with latest flet,
which may or may not be solved with this commit.  but since flet is
still essentially in beta phase, seems better to stay on latest
version instead of holding back.

this tries to fix the issue(s) in the following ways:

- timestamp thread is now "daemonized"
- if runtime error happens in timestamp control, ignore and exit thread
- if runtime error happens in main thread error handler, also ignore

we'll see what happens next after some usage
This commit is contained in:
Lance Edgar 2024-07-05 16:41:11 -05:00
parent b8bb42e38c
commit 2a835d9bcb
3 changed files with 24 additions and 16 deletions

View file

@ -28,13 +28,8 @@ dependencies = [
"rattail[db]",
"typer",
# TODO: unfortunately the latest Flet versions as of writing
# (to 0.22.1) include a bug..when running `wuttapos open`
# command then quitting the app, you get an error "Event loop
# is closed" - i tried several versions of python (to 3.12.3)
# but nothing worked despite the claims made in github issue,
# https://github.com/flet-dev/flet/issues/2848
"flet<0.21",
# nb. for now we are just testing one version, for simplicity
"flet==0.23.2",
]

View file

@ -2,7 +2,7 @@
################################################################################
#
# WuttaPOS -- Pythonic Point of Sale System
# Copyright © 2023 Lance Edgar
# Copyright © 2023-2024 Lance Edgar
#
# This file is part of WuttaPOS.
#
@ -79,6 +79,12 @@ def main(page: ft.Page):
])
def handle_error(exc_type, exc_value, exc_traceback):
# nb. ignore this particular error; it is benign
if exc_type is RuntimeError and str(exc_value) == 'Event loop is closed':
log.debug("ignoring error for closed event loop", exc_info=True)
return
extra_context = OrderedDict(email_context)
traceback = ''.join(format_exception(exc_type, exc_value, exc_traceback)).strip()
@ -143,7 +149,7 @@ def main(page: ft.Page):
log.exception("failed to show error bottomsheet")
def sys_exc_hook(exc_type, exc_value, exc_traceback):
handle_error_email(exc_type, exc_value, exc_traceback)
handle_error(exc_type, exc_value, exc_traceback)
sys.__excepthook__(exc_type, exc_value, exc_traceback)
def thread_exc_hook(args):
@ -171,7 +177,7 @@ def main(page: ft.Page):
def clean_exit():
# TODO: this doesn't do anything interesting now, but it could
page.window_destroy()
page.window.destroy()
def keyboard(e):
# exit on ctrl+Q
@ -186,8 +192,8 @@ def main(page: ft.Page):
clean_exit()
# cf. https://flet.dev/docs/controls/page/#window_destroy
page.window_prevent_close = True
page.on_window_event = window_event
page.window.prevent_close = True
page.window.on_event = window_event
# TODO: probably these should be auto-loaded from spec
from wuttapos.views.pos import POSView
@ -222,7 +228,7 @@ def main(page: ft.Page):
# nb. setting this "last minute" on page change seems to be
# more reliable, otherwise the app doesn't always startup in
# full screen for some reason
page.window_full_screen = True
page.window.full_screen = True
page.update()

View file

@ -2,7 +2,7 @@
################################################################################
#
# WuttaPOS -- Pythonic Point of Sale System
# Copyright © 2023 Lance Edgar
# Copyright © 2023-2024 Lance Edgar
#
# This file is part of WuttaPOS.
#
@ -43,7 +43,9 @@ class WuttaTimestamp(WuttaControl):
text = self.render_time(self.app.localtime())
self.display = ft.Text(text, weight=self.weight, size=self.size)
thread = threading.Thread(target=self.update_display)
# nb. daemonized thread should be stopped when app exits
# cf. https://docs.python.org/3/library/threading.html#thread-objects
thread = threading.Thread(target=self.update_display, daemon=True)
thread.start()
return self.display
@ -55,5 +57,10 @@ class WuttaTimestamp(WuttaControl):
while True:
if self.page:
self.display.value = self.render_time(self.app.localtime())
self.update()
try:
self.update()
except RuntimeError as error:
if str(error) == 'Event loop is closed':
break
raise
time.sleep(0.5)