Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat:skilljson and homescreen #283

Merged
merged 8 commits into from
Nov 15, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
error handling and logs
  • Loading branch information
JarbasAl committed Nov 14, 2024
commit 3e2940da21459bbae10fd751bd18b98e19b26aab
61 changes: 27 additions & 34 deletions ovos_workshop/resource_files.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,14 @@
# limitations under the License.
#
"""Handling of skill data such as intents and regular expressions."""
import abc
import json
import re
from collections import namedtuple
from os import walk
from os.path import dirname
from pathlib import Path
from typing import List, Optional, Tuple, Dict
from typing import List, Optional, Tuple, Dict, Any

from langcodes import tag_distance
from ovos_config.config import Configuration
Expand Down Expand Up @@ -256,12 +257,18 @@ def locate_base_directory(self, skill_directory: str) -> Optional[str]:
return

# check for lang resources shipped by the skill
possible_directories = (
Path(skill_directory, "locale", self.language),
Path(skill_directory, resource_subdirectory, self.language),
Path(skill_directory, resource_subdirectory),
Path(skill_directory, "text", self.language),
)
if resource_subdirectory:
possible_directories = (
Path(skill_directory, "locale", self.language),
Path(skill_directory, resource_subdirectory, self.language),
Path(skill_directory, resource_subdirectory),
Path(skill_directory, "text", self.language),
)
else:
possible_directories = (
Path(skill_directory, "locale", self.language),
Path(skill_directory, "text", self.language),
)
for directory in possible_directories:
if directory.exists():
self.base_directory = directory
Expand All @@ -281,7 +288,7 @@ def locate_base_directory(self, skill_directory: str) -> Optional[str]:
if self.user_directory:
self.base_directory = self.user_directory

def _get_resource_subdirectory(self) -> str:
def _get_resource_subdirectory(self) -> Optional[str]:
"""Returns the subdirectory for this resource type.

In the older directory schemes, several resource types were stored
Expand All @@ -297,10 +304,10 @@ def _get_resource_subdirectory(self) -> str:
template="dialog",
vocab="vocab",
word="dialog",
qml="ui"
qml="gui"
)

return subdirectories[self.resource_type]
return subdirectories.get(self.resource_type)


class ResourceFile:
Expand All @@ -317,7 +324,7 @@ def __init__(self, resource_type: ResourceType, resource_name: str):
self.resource_name = resource_name
self.file_path = self._locate()

def _locate(self) -> str:
def _locate(self) -> Optional[str]:
"""Locates a resource file in the skill's locale directory.

A skill's locale directory can contain a subdirectory structure defined
Expand Down Expand Up @@ -347,22 +354,12 @@ def _locate(self) -> str:
if file_name in file_names:
file_path = Path(directory, file_name)

# check the core resources
if file_path is None and self.resource_type.language:
sub_path = Path("text", self.resource_type.language, file_name)
file_path = resolve_resource_file(str(sub_path),
config=Configuration())

# check non-lang specific core resources
if file_path is None:
file_path = resolve_resource_file(file_name,
config=Configuration())

if file_path is None:
LOG.error(f"Could not find resource file {file_name}")
LOG.debug(f"Could not find resource file {file_name} for lang: {self.resource_type.language}")

return file_path

@abc.abstractmethod
def load(self):
"""Override in subclass to define resource type loading behavior."""
pass
Expand Down Expand Up @@ -400,13 +397,6 @@ def _locate(self):
if x.is_file() and file_name == x.name:
file_path = Path(self.resource_type.base_directory, file_name)

# check the core resources
if file_path is None:
file_path = resolve_resource_file(file_name,
config=Configuration()) or \
resolve_resource_file(f"ui/{file_name}",
config=Configuration())

if file_path is None:
LOG.error(f"Could not find resource file {file_name}")

Expand All @@ -417,10 +407,13 @@ def load(self):


class JsonFile(ResourceFile):
def load(self) -> Dict[str, str]:
def load(self) -> Dict[str, Any]:
if self.file_path is not None:
with open(self.file_path) as f:
return json.load(f)
try:
with open(self.file_path) as f:
return json.load(f)
except Exception as e:
LOG.error(f"Failed to load {self.file_path}: {e}")
return {}


Expand Down Expand Up @@ -657,7 +650,7 @@ def _define_resource_types(self) -> SkillResourceTypes:
vocabulary=ResourceType("vocab", ".voc", self.language),
word=ResourceType("word", ".word", self.language),
qml=ResourceType("qml", ".qml"),
json=ResourceType("json", ".json")
json=ResourceType("json", ".json", self.language)
)
for resource_type in resource_types.values():
if self.skill_id:
Expand Down
17 changes: 9 additions & 8 deletions ovos_workshop/skills/ovos.py
Original file line number Diff line number Diff line change
Expand Up @@ -816,7 +816,7 @@ def _startup(self, bus: MessageBusClient, skill_id: str = ""):
self.load_data_files()
self._register_skill_json()
self._register_decorated()
self._register_app_launcher()
#self._register_app_launcher()
self.register_resting_screen()

self.status.set_started()
Expand Down Expand Up @@ -847,12 +847,9 @@ def _register_skill_json(self, root_directory: Optional[str] = None):
if utts:
self.log.info(f"Registering example utterances with homescreen for lang: {lang} - {utts}")
self.bus.emit(Message("homescreen.register.examples",
{"skill_id": self.skill_id, "utterances": utts}))
{"skill_id": self.skill_id, "utterances": utts, "lang": lang}))

def _register_app_launcher(self):
# homescreen might load after this skill and miss the original events
self.add_event("homescreen.metadata.get", self.handle_homescreen_loaded)

# register app launcher if registered via decorator
for attr_name in get_non_properties(self):
method = getattr(self, attr_name)
Expand Down Expand Up @@ -1131,6 +1128,9 @@ def _register_system_event_handlers(self):
self.add_event(f"{self.skill_id}.converse.get_response", self.__handle_get_response,
speak_errors=False)

# homescreen might load after this skill and miss the original events
self.add_event("homescreen.metadata.get", self.handle_homescreen_loaded)

def _send_public_api(self, message: Message):
"""
Respond with the skill's public api.
Expand Down Expand Up @@ -1514,7 +1514,7 @@ def register_regex(self, regex_str: str, lang: Optional[str] = None):
def handle_homescreen_loaded(self, message: Message):
"""homescreen loaded, we should re-register any metadata we want to provide"""
self._register_skill_json()
self._register_app_launcher()
#self._register_app_launcher()

def handle_enable_intent(self, message: Message):
"""
Expand Down Expand Up @@ -1723,7 +1723,7 @@ def speak_dialog(self, key: str, data: Optional[dict] = None,
expect_response, wait, meta={'dialog': key, 'data': data}
)
else:
self.log.warning(
self.log.error(
'dialog_render is None, does the locale/dialog folder exist?'
)
self.speak(key, expect_response, wait, {})
Expand Down Expand Up @@ -2096,7 +2096,8 @@ def ask_selection(self, options: List[str], dialog: str = '',
Returns:
string: list element selected by user, or None
"""
assert isinstance(options, list)
if not isinstance(options, list):
raise ValueError("invalid value for 'options', must be a list of strings")

if not len(options):
return None
Expand Down