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

fix:typing and docstrs #21

Open
wants to merge 5 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
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
3 changes: 1 addition & 2 deletions ovos_padatious/__main__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import inspect
import json
from os.path import basename, splitext

from argparse import ArgumentParser
from os.path import basename, splitext

from ovos_padatious import IntentContainer

Expand Down
185 changes: 2 additions & 183 deletions ovos_padatious/bracket_expansion.py
Original file line number Diff line number Diff line change
@@ -1,183 +1,2 @@
# Copyright 2017 Mycroft AI, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


class Fragment(object):
"""(Abstract) empty sentence fragment"""

def __init__(self, tree):
"""
Construct a sentence tree fragment which is merely a wrapper for
a list of Strings

Args:
tree (?): Base tree for the sentence fragment, type depends on
subclass, refer to those subclasses
"""
self._tree = tree

def tree(self):
"""Return the represented sentence tree as raw data."""
return self._tree

def expand(self):
"""
Expanded version of the fragment. In this case an empty sentence.

Returns:
List<List<str>>: A list with an empty sentence (= token/string list)
"""
return [[]]

def __str__(self):
return self._tree.__str__()

def __repr__(self):
return self._tree.__repr__()


class Word(Fragment):
"""
Single word in the sentence tree.

Construct with a string as argument.
"""

def expand(self):
"""
Creates one sentence that contains exactly that word.

Returns:
List<List<str>>: A list with the given string as sentence
(= token/string list)
"""
return [[self._tree]]


class Sentence(Fragment):
"""
A Sentence made of several concatenations/words.

Construct with a List<Fragment> as argument.
"""

def expand(self):
"""
Creates a combination of all sub-sentences.

Returns:
List<List<str>>: A list with all subsentence expansions combined in
every possible way
"""
old_expanded = [[]]
for sub in self._tree:
sub_expanded = sub.expand()
new_expanded = []
while len(old_expanded) > 0:
sentence = old_expanded.pop()
for new in sub_expanded:
new_expanded.append(sentence + new)
old_expanded = new_expanded
return old_expanded


class Options(Fragment):
"""
A Combination of possible sub-sentences.

Construct with List<Fragment> as argument.
"""

def expand(self):
"""
Returns all of its options as seperated sub-sentences.

Returns:
List<List<str>>: A list containing the sentences created by all
expansions of its sub-sentences
"""
options = []
for option in self._tree:
options.extend(option.expand())
return options


class SentenceTreeParser(object):
"""
Generate sentence token trees from a list of tokens
['1', '(', '2', '|', '3, ')'] -> [['1', '2'], ['1', '3']]
"""

def __init__(self, tokens):
self.tokens = tokens

def _parse(self):
"""
Generate sentence token trees
['1', '(', '2', '|', '3, ')'] -> ['1', ['2', '3']]
"""
self._current_position = 0
return self._parse_expr()

def _parse_expr(self):
"""
Generate sentence token trees from the current position to
the next closing parentheses / end of the list and return it
['1', '(', '2', '|', '3, ')'] -> ['1', [['2'], ['3']]]
['2', '|', '3'] -> [['2'], ['3']]
"""
# List of all generated sentences
sentence_list = []
# Currently active sentence
cur_sentence = []
sentence_list.append(Sentence(cur_sentence))
# Determine which form the current expression has
while self._current_position < len(self.tokens):
cur = self.tokens[self._current_position]
self._current_position += 1
if cur == '(':
# Parse the subexpression
subexpr = self._parse_expr()
# Check if the subexpression only has one branch
# -> If so, append "(" and ")" and add it as is
normal_brackets = False
if len(subexpr.tree()) == 1:
normal_brackets = True
cur_sentence.append(Word('('))
# add it to the sentence
cur_sentence.append(subexpr)
if normal_brackets:
cur_sentence.append(Word(')'))
elif cur == '|':
# Begin parsing a new sentence
cur_sentence = []
sentence_list.append(Sentence(cur_sentence))
elif cur == ')':
# End parsing the current subexpression
break
# TODO anything special about {sth}?
else:
cur_sentence.append(Word(cur))
return Options(sentence_list)

def _expand_tree(self, tree):
"""
Expand a list of sub sentences to all combinated sentences.
['1', ['2', '3']] -> [['1', '2'], ['1', '3']]
"""
return tree.expand()

def expand_parentheses(self):
tree = self._parse()
return self._expand_tree(tree)
# backwards compat
from ovos_utils.bracket_expansion import *
63 changes: 53 additions & 10 deletions ovos_padatious/entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,38 +13,81 @@
# limitations under the License.

from os.path import join
from typing import Any, Type

from ovos_padatious.simple_intent import SimpleIntent
from ovos_padatious.trainable import Trainable


class Entity(SimpleIntent, Trainable):
def __init__(self, name, *args, **kwargs):
def __init__(self, name: str, *args: Any, **kwargs: Any) -> None:
"""
Initializes an Entity instance.

Args:
name (str): The name of the entity.
*args: Additional positional arguments.
**kwargs: Additional keyword arguments.
"""
SimpleIntent.__init__(self, name)
Trainable.__init__(self, name, *args, **kwargs)

@staticmethod
def verify_name(token):
if token[0] in '{}' or token[-1] in '{}':
raise ValueError('token must not be surrounded in braces (ie. {word} should be word)')
def verify_name(token: str) -> None:
"""
Verifies that the token is not surrounded by braces.

Args:
token (str): The token to verify.

Raises:
ValueError: If the token is surrounded by braces.
"""
if token.startswith('{') or token.endswith('}'):
raise ValueError('Token must not be surrounded in braces (e.g., {word} should be word)')

@staticmethod
def wrap_name(name):
"""Wraps SkillName:entity into SkillName:{entity}"""
def wrap_name(name: str) -> str:
"""
Wraps the skill name and entity into a specific format.

Args:
name (str): The skill name or entity name.

Returns:
str: Wrapped name in the format SkillName:{entity}.
"""
if ':' in name:
parts = name.split(':')
intent_name, ent_name = parts[0], parts[1:]
return intent_name + ':{' + ':'.join(ent_name) + '}'
return f"{intent_name}:{{{':'.join(ent_name)}}}"
else:
return '{' + name + '}'
return f"{{{name}}}"

def save(self, folder: str) -> None:
"""
Saves the entity to the specified folder.

def save(self, folder):
Args:
folder (str): The folder path where the entity should be saved.
"""
prefix = join(folder, self.name)
SimpleIntent.save(self, prefix)
self.save_hash(prefix)

@classmethod
def from_file(cls, name, folder):
def from_file(cls: Type['Entity'], name: str, folder: str) -> 'Entity':
"""
Creates an Entity instance from a file.

Args:
cls (Type[Entity]): The class itself.
name (str): The name of the entity.
folder (str): The folder path where the entity file is located.

Returns:
Entity: The loaded Entity instance.
"""
self = super(Entity, cls).from_file(name, join(folder, name))
self.load_hash(join(folder, name))
return self
Loading
Loading