Skip to content

Commit 49947a2

Browse files
committed
refactor!:deprecate QML upload from bus
never worked right, causes more issues than it helps
1 parent 7f024a7 commit 49947a2

File tree

6 files changed

+33
-140
lines changed

6 files changed

+33
-140
lines changed

README.md

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,6 @@ under mycroft.conf
4040
// "gui_file_server": true,
4141
// "file_server_port": 8000,
4242

43-
// Optional support for collecting GUI files for container support
44-
// The ovos-gui container path for these files will be {XDG_CACHE_HOME}/ovos_gui_file_server.
45-
// With the below configuration, the GUI client will have files prefixed with the configured host path,
46-
// so the example below describes a situation where `{XDG_CACHE_HOME}/ovos_gui_file_server` maps
47-
// to `/tmp/gui_files` on the filesystem where the GUI client is running.
48-
// "gui_file_host_path": "/tmp/gui_files",
49-
5043
// Optionally specify a default qt version for connected clients that don't report it
5144
"default_qt_version": 5
5245
},

ovos_gui/constants.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
from ovos_config.locations import get_xdg_cache_save_path
2+
3+
GUI_CACHE_PATH = get_xdg_cache_save_path('ovos_gui')
4+

ovos_gui/gui_file_server.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
from threading import Thread, Event
66

77
from ovos_config import Configuration
8-
from ovos_utils.file_utils import get_temp_path
98
from ovos_utils.log import LOG
109

1110
_HTTP_SERVER = None

ovos_gui/namespace.py

Lines changed: 10 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,12 @@
4040
over the GUI message bus.
4141
"""
4242
import shutil
43-
from os import makedirs
4443
from os.path import join, dirname, isfile, exists
4544
from threading import Event, Lock, Timer
4645
from typing import List, Union, Optional, Dict
4746

4847
from ovos_config.config import Configuration
49-
from ovos_utils.log import LOG, log_deprecation
48+
from ovos_utils.log import LOG
5049

5150
from ovos_bus_client import Message, MessageBusClient
5251
from ovos_gui.bus import (
@@ -57,7 +56,7 @@
5756
)
5857
from ovos_gui.gui_file_server import start_gui_http_server
5958
from ovos_gui.page import GuiPage
60-
59+
from ovos_gui.constants import GUI_CACHE_PATH
6160
namespace_lock = Lock()
6261

6362
RESERVED_KEYS = ['__from', '__idle']
@@ -433,9 +432,6 @@ def __init__(self, core_bus: MessageBusClient):
433432
self._system_res_dir = join(dirname(__file__), "res", "gui")
434433
self._ready_event = Event()
435434
self.gui_file_server = None
436-
self.gui_file_path = None # HTTP Server local path
437-
self.gui_file_host_path = None # Docker host path
438-
self._connected_frameworks: List[str] = list()
439435
self._init_gui_file_share()
440436
self._define_message_handlers()
441437

@@ -450,20 +446,10 @@ def _init_gui_file_share(self):
450446
If `gui_file_server` is defined, resources will be served via HTTP
451447
"""
452448
config = Configuration().get("gui", {})
453-
self.gui_file_host_path = config.get("gui_file_host_path")
454-
455-
# Check for GUI file sharing via HTTP server or mounted host path
456-
if config.get("gui_file_server") or self.gui_file_host_path:
457-
from ovos_utils.xdg_utils import xdg_cache_home
458-
if config.get("server_path"):
459-
log_deprecation("`server_path` configuration is deprecated. "
460-
"Files will always be saved to "
461-
"XDG_CACHE_HOME/ovos_gui_file_server", "0.1.0")
462-
self.gui_file_path = config.get("server_path") or \
463-
join(xdg_cache_home(), "ovos_gui_file_server")
464-
if config.get("gui_file_server"):
465-
self.gui_file_server = start_gui_http_server(self.gui_file_path)
466-
self._upload_system_resources()
449+
# Check for GUI file sharing via HTTP server
450+
if config.get("gui_file_server"):
451+
self.gui_file_server = start_gui_http_server(GUI_CACHE_PATH)
452+
self._cache_system_resources()
467453

468454
def _define_message_handlers(self):
469455
"""
@@ -474,7 +460,6 @@ def _define_message_handlers(self):
474460
self.core_bus.on("gui.page.delete", self.handle_delete_page)
475461
self.core_bus.on("gui.page.delete.all", self.handle_delete_all_pages)
476462
self.core_bus.on("gui.page.show", self.handle_show_page)
477-
self.core_bus.on("gui.page.upload", self.handle_receive_gui_pages)
478463
self.core_bus.on("gui.status.request", self.handle_status_request)
479464
self.core_bus.on("gui.value.set", self.handle_set_value)
480465
self.core_bus.on("mycroft.gui.connected", self.handle_client_connected)
@@ -485,68 +470,6 @@ def _define_message_handlers(self):
485470

486471
def handle_ready(self, message):
487472
self._ready_event.set()
488-
self.core_bus.on("gui.volunteer_page_upload",
489-
self.handle_gui_pages_available)
490-
491-
def handle_gui_pages_available(self, message: Message):
492-
"""
493-
Handle a skill or plugin advertising that it has GUI pages available to
494-
upload. If there are connected clients, request pages for each connected
495-
GUI framework.
496-
@param message: `gui.volunteer_page_upload` message
497-
"""
498-
if not any((self.gui_file_host_path, self.gui_file_server)):
499-
LOG.debug("No GUI file server running or host path configured")
500-
return
501-
502-
LOG.debug(f"Requesting resources for {self._connected_frameworks}")
503-
for framework in self._connected_frameworks:
504-
skill_id = message.data.get("skill_id")
505-
self.core_bus.emit(message.reply("gui.request_page_upload",
506-
{'skill_id': skill_id,
507-
'framework': framework},
508-
{"source": "gui",
509-
"destination": ["skills",
510-
"PHAL"]}))
511-
512-
def handle_receive_gui_pages(self, message: Message):
513-
"""
514-
Handle GUI resources from a skill or plugin. Pages are written to
515-
`self.server_path` which is accessible via a lightweight HTTP server and
516-
may additionally be mounted to a host path/volume in container setups.
517-
@param message: Message containing UI resource file contents and meta
518-
message.data:
519-
pages: dict page_filename to encoded bytes content;
520-
paths are relative to the `framework` directory, so a page
521-
for framework `all` could be `qt5/subdir/file.qml` and the
522-
equivalent page for framework `qt5` would be
523-
`subdir/file.qml`
524-
framework: `all` if all GUI resources are included, else the
525-
specific GUI framework (i.e. `qt5`, `qt6`)
526-
__from: skill_id of module uploading GUI resources
527-
"""
528-
for page, contents in message.data["pages"].items():
529-
try:
530-
if message.data.get("framework") == "all":
531-
# All GUI resources are uploaded
532-
resource_base_path = join(self.gui_file_path,
533-
message.data['__from'])
534-
else:
535-
resource_base_path = join(self.gui_file_path,
536-
message.data['__from'],
537-
message.data.get('framework') or
538-
"qt5")
539-
byte_contents = bytes.fromhex(contents)
540-
file_path = join(resource_base_path, page)
541-
LOG.debug(f"writing UI file: {file_path}")
542-
makedirs(dirname(file_path), exist_ok=True)
543-
with open(file_path, 'wb+') as f:
544-
f.write(byte_contents)
545-
except Exception as e:
546-
LOG.exception(f"Failed to write {page}: {e}")
547-
if message.data["__from"] == self._active_homescreen:
548-
# Configured home screen skill just uploaded pages, show it again
549-
self.core_bus.emit(message.forward("homescreen.manager.show_active"))
550473

551474
def handle_clear_namespace(self, message: Message):
552475
"""
@@ -952,23 +875,9 @@ def handle_client_connected(self, message: Message):
952875
websocket_config = get_gui_websocket_config()
953876
port = websocket_config["base_port"]
954877
message = message.forward("mycroft.gui.port",
955-
dict(port=port, gui_id=gui_id))
878+
dict(port=port, gui_id=gui_id, framework=framework))
956879
self.core_bus.emit(message)
957880

958-
if self.gui_file_path or self.gui_file_host_path:
959-
if not self._ready_event.wait(90):
960-
LOG.warning("Not reported ready after 90s")
961-
if framework not in self._connected_frameworks:
962-
LOG.debug(f"Requesting page upload for {framework}")
963-
self.core_bus.emit(Message("gui.request_page_upload",
964-
{'framework': framework},
965-
{"source": "gui",
966-
"destination": ["skills", "PHAL"]}))
967-
968-
if framework not in self._connected_frameworks:
969-
LOG.debug(f"Connecting framework: {framework}")
970-
self._connected_frameworks.append(framework)
971-
972881
def handle_page_interaction(self, message: Message):
973882
"""
974883
Handles an event from the GUI indicating a page has been interacted with.
@@ -1037,13 +946,13 @@ def _del_namespace_in_remove_timers(self, namespace_name: str):
1037946
if namespace_name in self.remove_namespace_timers:
1038947
del self.remove_namespace_timers[namespace_name]
1039948

1040-
def _upload_system_resources(self):
949+
def _cache_system_resources(self):
1041950
"""
1042951
Copy system GUI resources to the served file path
1043952
"""
1044-
output_path = join(self.gui_file_path, "system")
953+
output_path = f"{GUI_CACHE_PATH}/system"
1045954
if exists(output_path):
1046955
LOG.info(f"Removing existing system resources before updating")
1047956
shutil.rmtree(output_path)
1048957
shutil.copytree(self._system_res_dir, output_path)
1049-
LOG.debug(f"Copied system resources to {self.gui_file_path}")
958+
LOG.debug(f"Copied system resources from {self._system_res_dir} to {output_path}")

ovos_gui/page.py

Lines changed: 17 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from typing import Union, Optional
33
from dataclasses import dataclass
44
from ovos_utils.log import LOG
5+
from ovos_gui.constants import GUI_CACHE_PATH
56

67

78
@dataclass
@@ -44,45 +45,32 @@ def get_file_extension(framework: str) -> str:
4445
return "qml"
4546
return ""
4647

47-
def get_uri(self, framework: str = "qt5", server_url: str = None) -> str:
48+
@property
49+
def _gui_cache(self):
50+
return f"{GUI_CACHE_PATH}]/{self.res_namespace}"
51+
52+
@property
53+
def res_namespace(self):
54+
return "system" if self.page_id.startswith("SYSTEM") else self.namespace
55+
56+
def get_uri(self, framework: str = "qt5") -> str:
4857
"""
4958
Get a valid URI for this Page.
50-
@param framework: String GUI framework to get resources for
51-
@param server_url: String server URL if available; this could be for a
52-
web server (http://), or a container host path (file://)
59+
@param framework: String GUI framework to get resources for (currently only 'qt5')
5360
@return: Absolute path to the requested resource
5461
"""
5562
if self.url:
5663
LOG.warning(f"Static URI: {self.url}")
5764
return self.url
5865

5966
res_filename = f"{self.page_id}.{self.get_file_extension(framework)}"
60-
res_namespace = "system" if self.page_id.startswith("SYSTEM") else \
61-
self.namespace
62-
if server_url:
63-
if "://" not in server_url:
64-
if server_url.startswith("/"):
65-
LOG.debug(f"No schema in server_url, assuming 'file'")
66-
server_url = f"file://{server_url}"
67-
else:
68-
LOG.debug(f"No schema in server_url, assuming 'http'")
69-
server_url = f"http://{server_url}"
70-
path = f"{server_url}/{res_namespace}/{framework}/{res_filename}"
71-
LOG.info(f"Resolved server URI: {path}")
72-
return path
73-
base_path = self.resource_dirs.get(framework)
74-
if not base_path and self.resource_dirs.get("all"):
75-
file_path = join(self.resource_dirs.get('all'), framework,
76-
res_filename)
67+
if self.res_namespace == "system":
68+
path = join(dirname(__file__), "res", "gui", framework, res_filename)
7769
else:
78-
file_path = join(base_path, res_filename)
79-
if isfile(file_path):
80-
return file_path
81-
# Check system resources
82-
file_path = join(dirname(__file__), "res", "gui", framework,
83-
res_filename)
84-
if isfile(file_path):
85-
return file_path
70+
path = f"{self._gui_cache}/{framework}/{res_filename}"
71+
LOG.debug(f"Resolved page URI: {path}")
72+
if isfile(path):
73+
return path
8674
raise FileNotFoundError(f"Unable to resolve resource file for "
8775
f"resource {res_filename} for framework "
8876
f"{framework}")

test/unittests/test_namespace.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -467,12 +467,12 @@ def test_upload_system_resources(self):
467467
test_dir = join(dirname(__file__), "upload_test")
468468
makedirs(test_dir, exist_ok=True)
469469
self.namespace_manager.gui_file_path = test_dir
470-
self.namespace_manager._upload_system_resources()
470+
self.namespace_manager._cache_system_resources()
471471
self.assertTrue(isdir(join(test_dir, "system", "qt5")))
472472
self.assertTrue(isfile(join(test_dir, "system", "qt5",
473473
"SYSTEM_TextFrame.qml")))
474474
# Test repeated copy doesn't raise any exception
475-
self.namespace_manager._upload_system_resources()
475+
self.namespace_manager._cache_system_resources()
476476
self.assertTrue(isdir(join(test_dir, "system", "qt5")))
477477
self.assertTrue(isfile(join(test_dir, "system", "qt5",
478478
"SYSTEM_TextFrame.qml")))

0 commit comments

Comments
 (0)