scripts/mycroft/dialog/__init__.py
Go to the documentation of this file.
1 # Copyright 2017 Mycroft AI Inc.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 #
15 import random
16 import os
17 import re
18 from pathlib import Path
19 from os.path import join
20 
21 from mycroft.util import resolve_resource_file
22 from mycroft.util.format import expand_options
23 from mycroft.util.log import LOG
24 
25 
26 __doc__ = """
27 
28 """
29 
30 
32  """
33  A dialog template renderer based on the mustache templating language.
34  """
35 
36  def __init__(self):
37  self.templates = {}
38 
39  def load_template_file(self, template_name, filename):
40  """
41  Load a template by file name into the templates cache.
42 
43  Args:
44  template_name (str): a unique identifier for a group of templates
45  filename (str): a fully qualified filename of a mustache template.
46  """
47  with open(filename, 'r', encoding='utf8') as f:
48  for line in f:
49  template_text = line.strip()
50  # Skip all lines starting with '#' and all empty lines
51  if (not template_text.startswith('#') and
52  template_text != ''):
53  if template_name not in self.templates:
54  self.templates[template_name] = []
55 
56  # convert to standard python format string syntax. From
57  # double (or more) '{' followed by any number of
58  # whitespace followed by actual key followed by any number
59  # of whitespace followed by double (or more) '}'
60  template_text = re.sub(r'\{\{+\s*(.*?)\s*\}\}+', r'{\1}',
61  template_text)
62 
63  self.templates[template_name].append(template_text)
64 
65  def render(self, template_name, context=None, index=None):
66  """
67  Given a template name, pick a template and render it using the context.
68  If no matching template exists use template_name as template.
69 
70  Args:
71  template_name (str): the name of a template group.
72  context (dict): dictionary representing values to be rendered
73  index (int): optional, the specific index in the collection of
74  templates
75 
76  Returns:
77  str: the rendered string
78  """
79  context = context or {}
80  if template_name not in self.templates:
81  # When not found, return the name itself as the dialog
82  # This allows things like render("record.not.found") to either
83  # find a translation file "record.not.found.dialog" or return
84  # "record not found" literal.
85  return template_name.replace(".", " ")
86 
87  template_functions = self.templates.get(template_name)
88  if index is None:
89  line = random.choice(template_functions)
90  else:
91  line = template_functions[index % len(template_functions)]
92  # Replace {key} in line with matching values from context
93  line = line.format(**context)
94  line = random.choice(expand_options(line))
95  return line
96 
97 
99  """
100  Loads a collection of dialog files into a renderer implementation.
101  """
102 
103  def __init__(self, renderer_factory=MustacheDialogRenderer):
104  self.__renderer = renderer_factory()
105 
106  def load(self, dialog_dir):
107  """
108  Load all dialog files within the specified directory.
109 
110  Args:
111  dialog_dir (str): directory that contains dialog files
112 
113  Returns:
114  a loaded instance of a dialog renderer
115  """
116  directory = Path(dialog_dir)
117  if not directory.exists() or not directory.is_dir():
118  LOG.warning("No dialog files found: {}".format(dialog_dir))
119  return self.__renderer
120 
121  for path, _, files in os.walk(str(directory)):
122  for f in files:
123  if f.endswith(".dialog"):
124  self.__renderer.load_template_file(
125  f.replace('.dialog', ''),
126  join(path, f))
127  return self.__renderer
128 
129 
130 def get(phrase, lang=None, context=None):
131  """
132  Looks up a resource file for the given phrase. If no file
133  is found, the requested phrase is returned as the string.
134  This will use the default language for translations.
135 
136  Args:
137  phrase (str): resource phrase to retrieve/translate
138  lang (str): the language to use
139  context (dict): values to be inserted into the string
140 
141  Returns:
142  str: a randomized and/or translated version of the phrase
143  """
144 
145  if not lang:
146  from mycroft.configuration import Configuration
147  lang = Configuration.get().get("lang")
148 
149  filename = "text/" + lang.lower() + "/" + phrase + ".dialog"
150  template = resolve_resource_file(filename)
151  if not template:
152  LOG.debug("Resource file not found: {}".format(filename))
153  return phrase
154 
155  stache = MustacheDialogRenderer()
156  stache.load_template_file("template", template)
157  if not context:
158  context = {}
159  return stache.render("template", context)
def resolve_resource_file(res_name)
def load_template_file(self, template_name, filename)
def __init__(self, renderer_factory=MustacheDialogRenderer)
def render(self, template_name, context=None, index=None)
def get(phrase, lang=None, context=None)


mycroft_ros
Author(s):
autogenerated on Mon Apr 26 2021 02:35:40