skill_data.py
Go to the documentation of this file.
1 # Copyright 2018 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 
16 """Module containing methods needed to load skill
17 data such as dialogs, intents and regular expressions.
18 """
19 
20 from os import walk
21 from os.path import splitext, join
22 import re
23 
24 from mycroft.messagebus.message import Message
25 from mycroft.util.format import expand_options
26 
27 
28 def read_vocab_file(path):
29  """ Read voc file.
30 
31  This reads a .voc file, stripping out empty lines comments and expand
32  parentheses. It retruns each line as a list of all expanded
33  alternatives.
34 
35  Arguments:
36  path (str): path to vocab file.
37 
38  Returns:
39  List of Lists of strings.
40  """
41  vocab = []
42  with open(path, 'r', encoding='utf8') as voc_file:
43  for line in voc_file.readlines():
44  if line.startswith('#') or line.strip() == '':
45  continue
46  vocab.append(expand_options(line))
47  return vocab
48 
49 
50 def load_vocab_from_file(path, vocab_type, bus):
51  """Load Mycroft vocabulary from file
52  The vocab is sent to the intent handler using the message bus
53 
54  Args:
55  path: path to vocabulary file (*.voc)
56  vocab_type: keyword name
57  bus: Mycroft messagebus connection
58  skill_id(str): skill id
59  """
60  if path.endswith('.voc'):
61  for parts in read_vocab_file(path):
62  entity = parts[0]
63  bus.emit(Message("register_vocab", {
64  'start': entity, 'end': vocab_type
65  }))
66  for alias in parts[1:]:
67  bus.emit(Message("register_vocab", {
68  'start': alias, 'end': vocab_type, 'alias_of': entity
69  }))
70 
71 
72 def load_regex_from_file(path, bus, skill_id):
73  """Load regex from file
74  The regex is sent to the intent handler using the message bus
75 
76  Args:
77  path: path to vocabulary file (*.voc)
78  bus: Mycroft messagebus connection
79  """
80  if path.endswith('.rx'):
81  with open(path, 'r', encoding='utf8') as reg_file:
82  for line in reg_file.readlines():
83  if line.startswith("#"):
84  continue
85  re.compile(munge_regex(line.strip(), skill_id))
86  bus.emit(
87  Message("register_vocab",
88  {'regex': munge_regex(line.strip(), skill_id)}))
89 
90 
91 def load_vocabulary(basedir, bus, skill_id):
92  """Load vocabulary from all files in the specified directory.
93 
94  Args:
95  basedir (str): path of directory to load from (will recurse)
96  bus (messagebus emitter): messagebus instance used to send the vocab to
97  the intent service
98  skill_id: skill the data belongs to
99  """
100  for path, _, files in walk(basedir):
101  for f in files:
102  if f.endswith(".voc"):
103  vocab_type = to_alnum(skill_id) + splitext(f)[0]
104  load_vocab_from_file(join(path, f), vocab_type, bus)
105 
106 
107 def load_regex(basedir, bus, skill_id):
108  """Load regex from all files in the specified directory.
109 
110  Args:
111  basedir (str): path of directory to load from
112  bus (messagebus emitter): messagebus instance used to send the vocab to
113  the intent service
114  skill_id (str): skill identifier
115  """
116  for path, _, files in walk(basedir):
117  for f in files:
118  if f.endswith(".rx"):
119  load_regex_from_file(join(path, f), bus, skill_id)
120 
121 
122 def to_alnum(skill_id):
123  """Convert a skill id to only alphanumeric characters
124 
125  Non alpha-numeric characters are converted to "_"
126 
127  Args:
128  skill_id (str): identifier to be converted
129  Returns:
130  (str) String of letters
131  """
132  return ''.join(c if c.isalnum() else '_' for c in str(skill_id))
133 
134 
135 def munge_regex(regex, skill_id):
136  """Insert skill id as letters into match groups.
137 
138  Args:
139  regex (str): regex string
140  skill_id (str): skill identifier
141  Returns:
142  (str) munged regex
143  """
144  base = '(?P<' + to_alnum(skill_id)
145  return base.join(regex.split('(?P<'))
146 
147 
148 def munge_intent_parser(intent_parser, name, skill_id):
149  """Rename intent keywords to make them skill exclusive
150  This gives the intent parser an exclusive name in the
151  format <skill_id>:<name>. The keywords are given unique
152  names in the format <Skill id as letters><Intent name>.
153 
154  The function will not munge instances that's already been
155  munged
156 
157  Args:
158  intent_parser: (IntentParser) object to update
159  name: (str) Skill name
160  skill_id: (int) skill identifier
161  """
162  # Munge parser name
163  if str(skill_id) + ':' not in name:
164  intent_parser.name = str(skill_id) + ':' + name
165  else:
166  intent_parser.name = name
167 
168  # Munge keywords
169  skill_id = to_alnum(skill_id)
170  # Munge required keyword
171  reqs = []
172  for i in intent_parser.requires:
173  if skill_id not in i[0]:
174  kw = (skill_id + i[0], skill_id + i[0])
175  reqs.append(kw)
176  else:
177  reqs.append(i)
178  intent_parser.requires = reqs
179 
180  # Munge optional keywords
181  opts = []
182  for i in intent_parser.optional:
183  if skill_id not in i[0]:
184  kw = (skill_id + i[0], skill_id + i[0])
185  opts.append(kw)
186  else:
187  opts.append(i)
188  intent_parser.optional = opts
189 
190  # Munge at_least_one keywords
191  at_least_one = []
192  for i in intent_parser.at_least_one:
193  element = [skill_id + e.replace(skill_id, '') for e in i]
194  at_least_one.append(tuple(element))
195  intent_parser.at_least_one = at_least_one
def load_regex(basedir, bus, skill_id)
Definition: skill_data.py:107
def load_vocabulary(basedir, bus, skill_id)
Definition: skill_data.py:91
def munge_intent_parser(intent_parser, name, skill_id)
Definition: skill_data.py:148
def load_regex_from_file(path, bus, skill_id)
Definition: skill_data.py:72
def munge_regex(regex, skill_id)
Definition: skill_data.py:135
def to_alnum(skill_id)
Definition: skill_data.py:122
def load_vocab_from_file(path, vocab_type, bus)
Definition: skill_data.py:50


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