mirror of
https://github.com/bytedream/aionlib.git
synced 2025-05-09 20:05:08 +02:00
Add files via upload
This commit is contained in:
parent
5ecf598a78
commit
8e6659e315
34
README.md
Normal file
34
README.md
Normal file
@ -0,0 +1,34 @@
|
||||
**_aionlib_ - library support for [aion](https://github.com/blueShard-dev/aion)**
|
||||
|
||||
- [Introduction](#introduction)
|
||||
- [Installation](#installation)
|
||||
- [Todo](#todo)
|
||||
- [License](#license)
|
||||
|
||||
# Introduction
|
||||
|
||||
**aionlib** is the official library support for the [aion](https://github.com/blueShard-dev/aion_project)
|
||||
|
||||
# Installation
|
||||
|
||||
To install **aionlib** with pip3, type:
|
||||
|
||||
```
|
||||
sudo pip3 install aionlib
|
||||
```
|
||||
|
||||
If you want to install **aionlib** from github, type:
|
||||
|
||||
```
|
||||
sudo git clone https://github.com/blueShard-dev/aionlib
|
||||
cd aionlib
|
||||
sudo python3 setup.py install
|
||||
```
|
||||
|
||||
# Todo
|
||||
|
||||
- [ ] tutorial for all classes / functions
|
||||
|
||||
# License
|
||||
|
||||
This project is licensed under the Mozilla Public Licence 2.0 (MPL-2.0) License - see the [LICENSE](License) file for more details
|
36
aionlib/__init__.py
Normal file
36
aionlib/__init__.py
Normal file
@ -0,0 +1,36 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
__author__ = "blueShard"
|
||||
__license__ = "GPL-3.0"
|
||||
__version__ = "0.1.0"
|
||||
|
||||
from ._utils import start_check as _start_check
|
||||
|
||||
_start_check()
|
||||
|
||||
is_aion = _start_check.is_aion
|
||||
is_linux = _start_check.is_linux
|
||||
|
||||
from ._utils import aion_data_path, aion_path
|
||||
|
||||
from . import config, language, logging, plugin, utils, variable
|
||||
|
||||
|
||||
def speech_output(speech_output: str) -> None:
|
||||
"""
|
||||
plays a output of an artificial voice from the given words
|
||||
|
||||
:param speech_output: str
|
||||
the words to be said
|
||||
syntax: <speech output words>
|
||||
example: "This is an test"
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
if is_aion:
|
||||
from ._utils import import_aion_internal_file
|
||||
return import_aion_internal_file("__init__").speech_output(speech_output)
|
||||
else:
|
||||
from ._utils import no_aion
|
||||
no_aion()
|
881
aionlib/_utils.py
Normal file
881
aionlib/_utils.py
Normal file
@ -0,0 +1,881 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
from glob import glob as _glob
|
||||
|
||||
from xml.dom import minidom as _minidom
|
||||
import xml.etree.ElementTree as _ET
|
||||
|
||||
|
||||
aion_data_path = "/etc/aion_data"
|
||||
aion_path = "".join(_glob("/usr/local/aion-*"))
|
||||
|
||||
|
||||
def import_aion_internal_file(fname: str):
|
||||
"""
|
||||
imports an file from the aion core
|
||||
|
||||
:param fname: str
|
||||
name of the file
|
||||
syntax: <filename>
|
||||
example: "version.py"
|
||||
:return: a imported module from the aion core
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
from . import is_aion
|
||||
|
||||
if is_aion:
|
||||
from importlib import import_module
|
||||
from sys import path
|
||||
path.insert(0, aion_path + "/aion_core")
|
||||
return import_module(fname)
|
||||
else:
|
||||
no_aion()
|
||||
|
||||
|
||||
def no_aion() -> None:
|
||||
"""
|
||||
a function which get called from some 'aionlib' functions if aion is not installed but required
|
||||
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def start_check() -> None:
|
||||
"""
|
||||
checks if system is linux and if aion is installed
|
||||
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
from colorama import Fore
|
||||
from os.path import isdir
|
||||
from platform import system
|
||||
|
||||
if system().lower() != "linux":
|
||||
print(Fore.RED + "It seems like you not using Linux (Raspbian on Raspberry Pi recommended). To use the whole library run this library on Linux (recommended Raspbian on Raspberry Pi)" + Fore.RESET)
|
||||
start_check.is_linux = False
|
||||
else:
|
||||
start_check.is_linux = True
|
||||
|
||||
if isdir(aion_path) is False:
|
||||
print(Fore.RED + "It seems like you haven't installed aion. To use the whole library install aion" + Fore.RESET)
|
||||
start_check.is_aion = False
|
||||
else:
|
||||
start_check.is_aion = True
|
||||
|
||||
|
||||
class BaseXMLBuilder:
|
||||
"""
|
||||
a class to simple build a '.xml' file
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
|
||||
def __init__(self, root_name: str = "root", **root_extra: str) -> None:
|
||||
"""
|
||||
:param root_name: str, optional
|
||||
name of the root element of the xml file
|
||||
syntax: <root name>
|
||||
example: "root"
|
||||
:param root_extra: kwargs, optional
|
||||
attributes for the root element
|
||||
syntax: <key>=<value>
|
||||
example: author="blueShard"
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
self.root_name = root_name
|
||||
|
||||
self._element_list = [self.root_name]
|
||||
self._root = _ET.Element(root_name, **root_extra)
|
||||
|
||||
def _prettify(self, string: str = None) -> str:
|
||||
"""
|
||||
prettifies the given string
|
||||
|
||||
:param string: str
|
||||
string to prettify
|
||||
syntax: <string>
|
||||
example: "<root><test_element></test_element></root>"
|
||||
:return: str
|
||||
returns the_prettified string
|
||||
syntax: <string>
|
||||
example: "<root>
|
||||
<test_element>
|
||||
</test_element>
|
||||
</root>"
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
if string is None:
|
||||
reparsed = _minidom.parseString(_ET.tostring(self._root, "utf-8"))
|
||||
else:
|
||||
reparsed = _minidom.parseString(bytes(string, "utf-8", errors="ignore"))
|
||||
pre_output = reparsed.toprettyxml(indent=" ")
|
||||
return "\n".join(pre_output.split("\n")[1:])
|
||||
|
||||
def create_root_element(self, name: str, text: str = None, attrib: dict = {}, **extra: str) -> None:
|
||||
"""
|
||||
creates a new entry as a sub element of the root element
|
||||
|
||||
:param name: str
|
||||
name of the new element
|
||||
syntax: <name>
|
||||
example: "root_child"
|
||||
:param text: str, optional
|
||||
text of the new element
|
||||
syntax: <text>
|
||||
example: "This is a root element"
|
||||
:param attrib: dict, optional
|
||||
attributes for the new element
|
||||
syntax: {<key>, <value>}
|
||||
example: {"author": "blueShard"}
|
||||
:param extra: kwargs, optional
|
||||
attributes for the new element
|
||||
syntax: <key>=<value>
|
||||
example: author="blueShard"
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
if text:
|
||||
element = _ET.Element(name, attrib, **extra).text = text
|
||||
else:
|
||||
element = _ET.Element(name, attrib, **extra)
|
||||
|
||||
self._root.append(element)
|
||||
self._element_list.append(name)
|
||||
|
||||
def create_sub_element(self, parent_name: str, name: str, text: str = None, attrib: dict = {}, parent_attrib: dict = None, **extra: str) -> None:
|
||||
"""
|
||||
creates a sub element of an parent element
|
||||
|
||||
:param parent_name: str
|
||||
name of the parent element to which the sub element should be added
|
||||
syntax: <parent name>
|
||||
example: "root_child"
|
||||
:param name: str
|
||||
name of the new sub element you want to add
|
||||
syntax: <name>
|
||||
example: "sub_child"
|
||||
:param text: str, optional
|
||||
text of the new sub element
|
||||
syntax: <text>
|
||||
example: "This is a sub element"
|
||||
:param attrib: dict, optional
|
||||
attributes for the new element
|
||||
syntax: {<key>, <value>}
|
||||
example: {"author": "blueShard"}
|
||||
:param parent_attrib: dict, optional
|
||||
attributes of the new sub element
|
||||
syntax: {<key>: <value>}
|
||||
example: {"language": "en_US"}
|
||||
:param extra: kwargs, optional
|
||||
attributes of the new sub element
|
||||
syntax: <key>=<value>
|
||||
example: language="en_US"
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
|
||||
if parent_name in self._element_list:
|
||||
for parent in self._root.iter(parent_name):
|
||||
if parent_attrib:
|
||||
if parent.attrib == parent_attrib:
|
||||
if text:
|
||||
_ET.SubElement(parent, name, attrib, **extra).text = text
|
||||
else:
|
||||
_ET.SubElement(parent, name, attrib, **extra)
|
||||
self._element_list.append(name)
|
||||
else:
|
||||
if text:
|
||||
_ET.SubElement(parent, name, attrib, **extra).text = text
|
||||
else:
|
||||
_ET.SubElement(parent, name, attrib, **extra)
|
||||
self._element_list.append(name)
|
||||
else:
|
||||
raise IndexError("Couldn't find parent '" + parent_name + "'. The available parents are in this list: " + str(self._element_list))
|
||||
|
||||
def get_string(self, pretty_print: bool = True) -> str:
|
||||
"""
|
||||
get sting of the xml tree
|
||||
|
||||
:param pretty_print: bool, optional
|
||||
sets True or False if the xml tree string should be pretty printed
|
||||
syntax: <boolean>
|
||||
example: True
|
||||
:return: str
|
||||
returns the string of the builded xml tree
|
||||
syntax: <xml tree>
|
||||
example: "<root>
|
||||
<root_child author="blueShard">
|
||||
<sub_child>This is a sub element</sub_child>
|
||||
</root_child>
|
||||
</root>"
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
if pretty_print is True:
|
||||
return self._prettify()
|
||||
else:
|
||||
return _ET.tostring(self._root, "utf-8").decode("ascii")
|
||||
|
||||
def write(self, fname: str, mode: str = "w", pretty_print: bool = True) -> None:
|
||||
"""
|
||||
writes the xml tree to a file
|
||||
|
||||
:param fname: str
|
||||
filename of file you want to write
|
||||
syntax: <filename>
|
||||
example: "/home/pi/text.xml"
|
||||
:param mode: str, optional
|
||||
mode to write on file
|
||||
syntax: <mode>
|
||||
example: "w"
|
||||
:param pretty_print: bool, optional
|
||||
sets True or False if the xml tree string should be pretty printed
|
||||
syntax: <boolean>
|
||||
example: True
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
with open(fname, mode=mode) as file:
|
||||
file.write(self.get_string(pretty_print))
|
||||
file.close()
|
||||
|
||||
|
||||
class BaseXMLReader:
|
||||
|
||||
"""
|
||||
a class to simple reead '.xml' file
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
|
||||
def __init__(self, fname: str) -> None:
|
||||
"""
|
||||
makes the fname and auto_write available for all class methods and set all variables
|
||||
|
||||
:param fname: str
|
||||
filename of the file you want to read
|
||||
syntax: <filename>
|
||||
example: "/home/pi/test.xml"
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
self.fname = fname
|
||||
|
||||
self._tree = _ET.parse(self.fname)
|
||||
self._root = self._tree.getroot()
|
||||
|
||||
self.get_infos._root = self._root
|
||||
|
||||
def _prettify(self, string: str = None) -> str:
|
||||
"""
|
||||
prettifies the given string
|
||||
|
||||
:param string: str
|
||||
string to prettify
|
||||
syntax: <string>
|
||||
example: "<root><test_element></test_element></root>"
|
||||
:return: str
|
||||
returns the_prettified string
|
||||
syntax: <string>
|
||||
example: "<root>
|
||||
<test_element>
|
||||
</test_element>
|
||||
</root>"
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
if string is None:
|
||||
reparsed = _minidom.parseString(_ET.tostring(self._root, "utf-8"))
|
||||
else:
|
||||
reparsed = _minidom.parseString(bytes(string, "utf-8", errors="ignore"))
|
||||
pre_output = reparsed.toprettyxml(indent=" ")
|
||||
return "\n".join(pre_output.split("\n")[1:])
|
||||
|
||||
class get_infos(dict):
|
||||
"""
|
||||
a modified dict class with indexing items
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
|
||||
def __init__(self, elem_tags: (str, list) = []) -> dict:
|
||||
"""
|
||||
get infos about an element in the file
|
||||
|
||||
:param elem_tags: list
|
||||
name of elements you want to get infos about
|
||||
syntax: [<element tags>]
|
||||
example: ["sub_child"]
|
||||
:return: dict
|
||||
returns a dict of names from the given elements with a list of dictionaries of found elements (complex description xD)
|
||||
syntax: {<element>: [{"parent": {"tag": <parent tag>, "text": <text of the parent element>, "attrib": {<attributes of the parent element>}}, "childs": [<childs of the element>], "tag": <tag of the element>, "text": <text of the element>, "attrib": {<attributes of the element>}}]}
|
||||
example: {"sub_child": [{"parent": {"tag": "root_child", "text": "", "attrib": {"author": "blueShard"}}, "childs": ["sub_child"], "tag": "sub_child", "text": "This is a sub element", "attrib": {}}]}
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
if isinstance(elem_tags, str):
|
||||
elem_tags = [elem_tags]
|
||||
|
||||
child_list = []
|
||||
return_dict = {}
|
||||
for elem in elem_tags:
|
||||
if elem == "<all>":
|
||||
continue
|
||||
elif elem == "<root>":
|
||||
return_dict[self._root.tag] = []
|
||||
else:
|
||||
return_dict[elem] = []
|
||||
|
||||
all_child_list = []
|
||||
|
||||
if "<all>" in elem_tags:
|
||||
if self._root.tag in return_dict:
|
||||
pass
|
||||
else:
|
||||
return_dict[self._root.tag] = []
|
||||
return_dict[self._root.tag].append(
|
||||
{"parent": {"tag": "", "text": "", "attrib": {}}, "childs": [child.tag for child in self._root], "tag": self._root.tag, "text": "", "attrib": self._root.attrib})
|
||||
for root_child in self._root:
|
||||
if root_child.tag in return_dict:
|
||||
pass
|
||||
else:
|
||||
return_dict[root_child.tag] = []
|
||||
return_dict[root_child.tag].append(
|
||||
{"parent": {"tag": self._root.tag, "text": self._root.text, "attrib": self._root.attrib}, "childs": [sub_root_child.tag for sub_root_child in root_child],
|
||||
"tag": root_child.tag, "text": root_child.text, "attrib": root_child.attrib})
|
||||
all_child_list.append(root_child)
|
||||
for parent in list(all_child_list):
|
||||
for child in parent:
|
||||
if child.tag in return_dict:
|
||||
pass
|
||||
else:
|
||||
return_dict[child.tag] = []
|
||||
return_dict[child.tag].append(
|
||||
{"parent": {"tag": parent.tag, "text": parent.text, "attrib": parent.attrib}, "childs": [sub_child.tag for sub_child in child], "tag": child.tag, "text": child.text,
|
||||
"attrib": child.attrib})
|
||||
all_child_list.append(child)
|
||||
if child in all_child_list:
|
||||
all_child_list.remove(child)
|
||||
else:
|
||||
if self._root.tag in return_dict:
|
||||
return_dict[self._root.tag].append({"parent": {}, "childs": [child.tag for child in self._root], "tag": self._root.tag, "text": "", "attrib": self._root.attrib})
|
||||
for root_child in self._root:
|
||||
if root_child.tag in return_dict:
|
||||
return_dict[root_child.tag].append(
|
||||
{"parent": {"tag": self._root.tag, "text": self._root.text, "attrib": self._root.attrib}, "childs": [sub_root_child.tag for sub_root_child in root_child],
|
||||
"tag": root_child.tag, "text": root_child.text, "attrib": root_child.attrib})
|
||||
else:
|
||||
child_list.append(root_child)
|
||||
for parent in list(child_list):
|
||||
for child in parent:
|
||||
if child.tag in return_dict:
|
||||
return_dict[child.tag].append(
|
||||
{"parent": {"tag": parent.tag, "text": parent.text, "attrib": parent.attrib}, "childs": [sub_child.tag for sub_child in child], "tag": child.tag, "text": child.text,
|
||||
"attrib": child.attrib})
|
||||
else:
|
||||
child_list.append(child)
|
||||
if child in child_list:
|
||||
child_list.remove(child)
|
||||
|
||||
self._return_dict = return_dict
|
||||
|
||||
self.items._return_dict_keys = return_dict.keys()
|
||||
self.items._return_dict_values = return_dict.values()
|
||||
self.keys._return_dict_keys = return_dict.keys()
|
||||
self.values._return_dict_values = return_dict.values()
|
||||
|
||||
super().__init__(self._return_dict)
|
||||
|
||||
def __iter__(self):
|
||||
return iter(self._return_dict)
|
||||
|
||||
def __next__(self):
|
||||
return self._return_dict
|
||||
|
||||
def __repr__(self):
|
||||
return self._return_dict
|
||||
|
||||
def __str__(self):
|
||||
return str(self._return_dict)
|
||||
|
||||
def index(self, index: int) -> dict:
|
||||
"""
|
||||
index a key-value pair in a dict
|
||||
|
||||
:param index: int
|
||||
index of the key-value pair you want to get
|
||||
syntax: <index>
|
||||
example: 5
|
||||
:return: dict
|
||||
returns the key-value pair of the given index
|
||||
syntax: {<key>: <value>}
|
||||
example: {"test_key": "test_value"}
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
i = 0
|
||||
for key, value in self._return_dict.items():
|
||||
if i == index:
|
||||
return {key: value}
|
||||
else:
|
||||
i += 1
|
||||
raise IndexError("dict index out of range")
|
||||
|
||||
class items:
|
||||
"""
|
||||
a modified items() function from dict with indexing items
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def __getitem__(self, item):
|
||||
return tuple(self._return_dict_items)[item]
|
||||
|
||||
def __iter__(self):
|
||||
return iter(self._return_dict_items)
|
||||
|
||||
def __len__(self):
|
||||
return len(self._return_dict_items)
|
||||
|
||||
def __next__(self):
|
||||
return self._return_dict_items
|
||||
|
||||
def __repr__(self):
|
||||
return self._return_dict_items
|
||||
|
||||
def __str__(self):
|
||||
return str(self._return_dict_items)
|
||||
|
||||
def index(self, index: int):
|
||||
"""
|
||||
index a key-value pair in a dict
|
||||
|
||||
:param index: int
|
||||
index of the key-value pair you want to get
|
||||
syntax: <index>
|
||||
example: 5
|
||||
:return: the given index in the values
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
return {list(self._return_dict_keys)[index]: list(self._return_dict_values)[index]}
|
||||
|
||||
class keys:
|
||||
"""
|
||||
a modified keys() function from dict with indexing items
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def __iter__(self):
|
||||
return iter(self._return_dict_keys)
|
||||
|
||||
def __len__(self):
|
||||
return len(list(self._return_dict_keys))
|
||||
|
||||
def __next__(self):
|
||||
return self._return_dict_keys
|
||||
|
||||
def __repr__(self):
|
||||
return self._return_dict_keys
|
||||
|
||||
def __str__(self):
|
||||
return str(self._return_dict_keys)
|
||||
|
||||
def index(self, index: int):
|
||||
"""
|
||||
index a key in a dict
|
||||
|
||||
:param index: int
|
||||
index of the key you want to get
|
||||
syntax: <index>
|
||||
example: 5
|
||||
:return: the given index in the keys
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
return list(self._return_dict_keys)[index]
|
||||
|
||||
class values:
|
||||
"""
|
||||
a modified values() function from dict with indexing items
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def __iter__(self):
|
||||
return iter(self._return_dict_values)
|
||||
|
||||
def __len__(self):
|
||||
return len(list(self._return_dict_values))
|
||||
|
||||
def __next__(self):
|
||||
return self._return_dict_values
|
||||
|
||||
def __repr__(self):
|
||||
return self._return_dict_values
|
||||
|
||||
def __str__(self):
|
||||
return str(self._return_dict_values)
|
||||
|
||||
def index(self, index: int):
|
||||
"""
|
||||
index a value in a dict
|
||||
|
||||
:param index: int
|
||||
index of the value you want to get
|
||||
syntax: <index>
|
||||
example: 5
|
||||
:return: the given index in the values
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
return list(self._return_dict_values)[index]
|
||||
|
||||
def get_string(self, pretty_print: bool = True) -> str:
|
||||
"""
|
||||
gets the string of the xml tree in the file
|
||||
|
||||
:param pretty_print: bool, optional
|
||||
sets True or False if the xml tree string should be pretty printed
|
||||
syntax: <boolean>
|
||||
example: True
|
||||
:return: str
|
||||
returns the string of the xml tree
|
||||
syntax: <xml tree>
|
||||
example: "<root>
|
||||
<root_child author="blueShard">
|
||||
<sub_child>This is a sub element</sub_child>
|
||||
</root_child>
|
||||
</root>"
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
string = _ET.tostring(self._root, "utf-8").decode("ascii")
|
||||
if pretty_print is True:
|
||||
if "\n" in string:
|
||||
return string
|
||||
else:
|
||||
return self._prettify()
|
||||
else:
|
||||
if "\n" in string:
|
||||
return "".join([line.strip() for line in _ET.tostring(self._root, "utf-8").decode("ascii").split("\n")])
|
||||
else:
|
||||
return string
|
||||
|
||||
|
||||
class BaseXMLWriter:
|
||||
"""
|
||||
a class to simple change/write a '.xml' file
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
|
||||
def __init__(self, fname: str, auto_write: bool = False) -> None:
|
||||
"""
|
||||
:param fname: str
|
||||
filename of the file you want to write to
|
||||
syntax: <filename>
|
||||
example: "/home/pi/test.xml"
|
||||
:param auto_write: bool, optional
|
||||
sets if after every change to the getted xml tree the changes should be write to the file
|
||||
syntax: <boolean>
|
||||
example: False
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
self.auto_write = auto_write
|
||||
self.fname = fname
|
||||
|
||||
self._root = _ET.fromstring("".join([item.replace("\n", "").strip() for item in [line for line in open(self.fname, "r")]]))
|
||||
|
||||
def _prettify(self, string: str = None) -> str:
|
||||
"""
|
||||
prettifies the given string
|
||||
|
||||
:param string: str
|
||||
string to prettify
|
||||
syntax: <string>
|
||||
example: "<root><test_element></test_element></root>"
|
||||
|
||||
:return: str
|
||||
returns the_prettified string
|
||||
syntax: <string>
|
||||
example: "<root>
|
||||
<test_element>
|
||||
</test_element>
|
||||
</root>"
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
if string is None:
|
||||
reparsed = _minidom.parseString(_ET.tostring(self._root, "utf-8"))
|
||||
else:
|
||||
reparsed = _minidom.parseString(string)
|
||||
pre_output = reparsed.toprettyxml(indent=" ")
|
||||
return "\n".join(pre_output.split("\n")[1:])
|
||||
|
||||
def add(self, parent_tag: str, elem_tag: str, text: str = None, attrib: dict = {}, parent_attrib: dict = None, **extra: str) -> None:
|
||||
"""
|
||||
adds an element to xml tree
|
||||
|
||||
:param parent_tag : str
|
||||
name of the parent element
|
||||
syntax: <parent name>
|
||||
example: "root_child"
|
||||
:param elem_tag : str
|
||||
name of the element you want to add
|
||||
syntax: <element name>
|
||||
example: "second_sub_child"
|
||||
:param text : str, optional
|
||||
text of the element you want to add
|
||||
syntax: <text>
|
||||
example: "This is the second sub child"
|
||||
:param attrib : dict
|
||||
attributes for the new element
|
||||
syntax: {<key>, <value>}
|
||||
example: {"author": "blueShard"}
|
||||
:param parent_attrib : dict, optional
|
||||
attributes of the parent element
|
||||
syntax: {<key>: <value>}
|
||||
example: {"author": "blueShard"}
|
||||
:param extra : kwargs, optional
|
||||
attributes of the new element
|
||||
syntax: <key>=<value>
|
||||
example: language="de_DE"
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
if parent_tag == "<root>":
|
||||
parent_tag = self._root.tag
|
||||
|
||||
if parent_tag == self._root.tag:
|
||||
if parent_attrib:
|
||||
if parent_attrib == self._root.attrib:
|
||||
if text:
|
||||
root_text_element = _ET.Element(elem_tag, attrib, **extra)
|
||||
root_text_element.text = text
|
||||
self._root.append(root_text_element)
|
||||
else:
|
||||
self._root.append(_ET.Element(elem_tag, attrib, **extra))
|
||||
else:
|
||||
if text:
|
||||
root_text_element = _ET.Element(elem_tag, attrib, **extra)
|
||||
root_text_element.text = text
|
||||
self._root.append(root_text_element)
|
||||
else:
|
||||
self._root.append(_ET.Element(elem_tag, attrib, **extra))
|
||||
else:
|
||||
for parent in self._root.iter(parent_tag):
|
||||
if parent_attrib:
|
||||
if parent.attrib == parent_attrib:
|
||||
if text:
|
||||
_ET.SubElement(parent, elem_tag).text = text
|
||||
else:
|
||||
_ET.SubElement(parent, elem_tag, attrib, **extra)
|
||||
else:
|
||||
if text:
|
||||
_ET.SubElement(parent, elem_tag).text = text
|
||||
else:
|
||||
_ET.SubElement(parent, elem_tag, attrib, **extra)
|
||||
|
||||
if self.auto_write is True:
|
||||
self.write()
|
||||
|
||||
def get_string(self, pretty_print: bool = False) -> str:
|
||||
"""
|
||||
gets the string of the xml tree in the file
|
||||
|
||||
:param pretty_print: bool, optional
|
||||
sets True or False if the xml tree string should be pretty printed
|
||||
syntax: <boolean>
|
||||
example: True
|
||||
:return: str
|
||||
returns the string of the xml tree
|
||||
syntax: <xml tree>
|
||||
example: "<root>
|
||||
<root_child author="blueShard">
|
||||
<sub_child>This is a sub element</sub_child>
|
||||
<second_sub_child language="de_DE"/>
|
||||
</root_child>
|
||||
</root>"
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
string = _ET.tostring(self._root, "utf-8").decode("ascii")
|
||||
if pretty_print is True:
|
||||
if "\n" in string:
|
||||
return string
|
||||
else:
|
||||
return self._prettify()
|
||||
else:
|
||||
if "\n" in string:
|
||||
return "".join([line.strip() for line in _ET.tostring(self._root, "utf-8").decode("ascii").split("\n")])
|
||||
else:
|
||||
return string
|
||||
|
||||
def remove(self, parent_tag: str, elem_tag: str, parent_attrib: dict = None) -> None:
|
||||
"""
|
||||
removes an element from the xml tree
|
||||
|
||||
:param parent_tag : str
|
||||
name of the parent element
|
||||
syntax: <parent name>
|
||||
example: "root_child"
|
||||
:param elem_tag : str
|
||||
name of the element you want to remove
|
||||
syntax: <element name>
|
||||
example: "second_sub_child"
|
||||
:param parent_attrib : dict, optional
|
||||
attributes of the parent element
|
||||
syntax: {<key>: <value>}
|
||||
example: {"author": "blueShard"}
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
if parent_tag == "<root>":
|
||||
parent_tag = self._root.tag
|
||||
|
||||
if parent_tag == self._root.tag:
|
||||
for child in self._root:
|
||||
if child.tag == elem_tag:
|
||||
if parent_attrib:
|
||||
if self._root.attrib == parent_attrib:
|
||||
self._root.remove(child)
|
||||
else:
|
||||
self._root.remove(child)
|
||||
|
||||
for parent in self._root.iter(parent_tag):
|
||||
for child in parent:
|
||||
if child.tag == elem_tag:
|
||||
if parent_attrib:
|
||||
if parent.attrib == parent_attrib:
|
||||
parent.remove(child)
|
||||
else:
|
||||
parent.remove(child)
|
||||
|
||||
if self.auto_write is True:
|
||||
self.write()
|
||||
|
||||
def update(self, parent_tag: str, elem_tag: str, text: str = None, attrib: dict = {}, parent_attrib: dict = None, **extra: str) -> None:
|
||||
"""
|
||||
updates an element in the xml tree
|
||||
|
||||
:param parent_tag : str
|
||||
name of the parent element
|
||||
syntax: <parent name>
|
||||
example: "root_child"
|
||||
:param elem_tag : str
|
||||
name of the element you want to update
|
||||
syntax: <element name>
|
||||
example: "second_sub_child"
|
||||
:param text : str, optional
|
||||
new text of the updated element
|
||||
syntax: <text>
|
||||
example: "New text of the second sub child"
|
||||
:param attrib : dict
|
||||
attributes for the new element
|
||||
syntax: {<key>, <value>}
|
||||
example: {"author": "blueShard"}
|
||||
:param parent_attrib : dict, optional
|
||||
attributes of the parent element
|
||||
syntax: {<key>: <value>}
|
||||
example: {"author": "blueShard"}
|
||||
:param extra : kwargs, optional
|
||||
new attributes of the updated element
|
||||
syntax: <key>=<value>
|
||||
example: language="de_DE"
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
if parent_tag == "<root>":
|
||||
parent_tag = self._root.tag
|
||||
|
||||
if parent_tag == self._root.tag:
|
||||
for child in self._root:
|
||||
if child.tag == elem_tag:
|
||||
if parent_attrib:
|
||||
if self._root.attrib == parent_attrib:
|
||||
if text:
|
||||
child.text = str(text)
|
||||
for key, value in attrib.items():
|
||||
child.set(str(key), str(value))
|
||||
for key, value in extra.items():
|
||||
child.set(key, str(value))
|
||||
else:
|
||||
if text:
|
||||
child.text = str(text)
|
||||
for key, value in attrib.items():
|
||||
child.set(str(key), str(value))
|
||||
for key, value in extra.items():
|
||||
child.set(key, str(value))
|
||||
for parent in self._root.iter(parent_tag):
|
||||
for child in parent:
|
||||
if child.tag == elem_tag:
|
||||
if parent_attrib:
|
||||
if parent.attrib == parent_attrib:
|
||||
if text:
|
||||
child.text = str(text)
|
||||
for key, value in attrib.items():
|
||||
child.set(str(key), str(value))
|
||||
for key, value in extra.items():
|
||||
child.set(key, str(value))
|
||||
else:
|
||||
if text:
|
||||
child.text = str(text)
|
||||
for key, value in attrib.items():
|
||||
child.set(str(key), str(value))
|
||||
for key, value in extra.items():
|
||||
child.set(key, str(value))
|
||||
|
||||
if self.auto_write is True:
|
||||
self.write()
|
||||
|
||||
def write(self, mode: str = "w", pretty_print: bool = True) -> None:
|
||||
"""
|
||||
writes the xml tree to a file
|
||||
|
||||
:param mode : str, optional
|
||||
mode to write on file
|
||||
syntax: <mode>
|
||||
example: "w"
|
||||
:param pretty_print : bool, optional
|
||||
sets True or False if the xml tree string should be pretty printed
|
||||
syntax: <boolean>
|
||||
example: True
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
with open(self.fname, mode=mode) as file:
|
||||
if pretty_print is False:
|
||||
file.write(_ET.tostring(self._root, "utf-8").decode("ascii"))
|
||||
else:
|
||||
file.write(self._prettify())
|
||||
file.close()
|
125
aionlib/acph.py
Normal file
125
aionlib/acph.py
Normal file
@ -0,0 +1,125 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
|
||||
def add_acph(fname: str, skill: str, acph_dict: dict = {}) -> None:
|
||||
"""
|
||||
adds an new entry(s) to from argument 'language_locale' given language
|
||||
|
||||
:param fname: str
|
||||
name of the file where the activate phrases should be added
|
||||
syntax: <file name>
|
||||
example: "/home/pi/test.acph"
|
||||
:param skill: str
|
||||
skill name to which the acph belongs
|
||||
syntax: "<skill name>"
|
||||
example: "test_skill"
|
||||
:param acph_dict: dict, optional
|
||||
defines a word or a sentence from which a method is called
|
||||
syntax: {<activate phrase>: <method that should get called after the activate phrase was said>}
|
||||
example: {"start test": "MyTestMethod"}
|
||||
NOTE: in key 'activate_phrase' you can use the '__and__' statement. This checks if the words before and after '__and__' are in the sentence that the user has spoken in
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
try:
|
||||
from .utils import BaseXMLWriter
|
||||
except ImportError:
|
||||
from utils import BaseXMLWriter
|
||||
|
||||
acph_writer = BaseXMLWriter(fname)
|
||||
for acph, method in acph_dict:
|
||||
if exist_acph(fname, acph):
|
||||
raise IndexError("the activate phrase " + acph + " already exist")
|
||||
acph_writer.add("<root>", acph, skill=skill, method=method)
|
||||
acph_writer.write()
|
||||
|
||||
|
||||
def create_acph_file(language_locale: str, skill_acph_dict_dict: dict = {}) -> None:
|
||||
"""
|
||||
creates a new '.acph' file for given language locale with given skill_acph_dict_dict
|
||||
|
||||
:param language_locale: str
|
||||
language locale of language from which the new file is to be created
|
||||
syntax: <language_locale>
|
||||
example: "en_US"
|
||||
:param skill_acph_dict_dict: dict, optional
|
||||
skill name you want to add specific entries
|
||||
syntax: {<skill name>: {<activate phrase>: <method that should get called after the activate phrase was said>}}
|
||||
example: {"test_skill": {"start test": "MyTestMethod"}}
|
||||
NOTE: in key 'activate_phrase' you can use the '__and__' statement. This checks if the words before and after '__and__' are in the sentence that the user has spoken in
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
try:
|
||||
from .utils import BaseXMLBuilder
|
||||
except ImportError:
|
||||
from utils import BaseXMLBuilder
|
||||
|
||||
acph_builder = BaseXMLBuilder(language_locale)
|
||||
for skill, acph_dict in skill_acph_dict_dict.items():
|
||||
for acph, method in acph_dict.items():
|
||||
acph_builder.create_root_element(acph, skill=skill, method=method)
|
||||
|
||||
acph_builder.write(language_locale + ".acph")
|
||||
|
||||
|
||||
def delete_acph(fname: str, acph_list: list = []) -> None:
|
||||
"""
|
||||
deletes entries from '<language_locale>.acph'
|
||||
|
||||
:param fname: str
|
||||
file from which the activate phases is being deleted
|
||||
syntax: <language locale>
|
||||
example: "/home/pi/test.acph"
|
||||
:param acph_list: list, optional
|
||||
name of the activate phases you want to remove
|
||||
syntax: [<activate phase name>]
|
||||
example: ["test_acph"]
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
try:
|
||||
from .utils import BaseXMLWriter
|
||||
except ImportError:
|
||||
from utils import BaseXMLWriter
|
||||
|
||||
acph_writer = BaseXMLWriter(fname)
|
||||
for item in acph_list:
|
||||
acph_writer.remove("<root>", str(item))
|
||||
acph_writer.write()
|
||||
|
||||
|
||||
def exist_acph(fname: str, acph: str) -> bool:
|
||||
"""
|
||||
checks if a entry exist
|
||||
|
||||
:param fname: str
|
||||
file from which the activate phrase should be search
|
||||
syntax: <language locale>
|
||||
example: "en_US"
|
||||
:param acph: str
|
||||
activate phrase you want to check if exists
|
||||
syntax: <acph name>
|
||||
example: "start test"
|
||||
:return: bool
|
||||
returns True if acph exist / False if not
|
||||
syntax: <boolean>
|
||||
example: False
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
try:
|
||||
from .utils import BaseXMLReader
|
||||
except ImportError:
|
||||
from utils import BaseXMLReader
|
||||
|
||||
acph = acph.replace(" ", "_")
|
||||
|
||||
acph_reader = BaseXMLReader(fname)
|
||||
for item in acph_reader.get_infos(["<root>"]).items().index(0):
|
||||
if acph in item["childs"]:
|
||||
return True
|
||||
else:
|
||||
return False
|
373
aionlib/config.py
Normal file
373
aionlib/config.py
Normal file
@ -0,0 +1,373 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
from . import is_aion
|
||||
from ._utils import no_aion
|
||||
|
||||
if is_aion:
|
||||
from ._utils import import_aion_internal_file as _import_aion_internal_files
|
||||
_config = _import_aion_internal_files("config")
|
||||
|
||||
|
||||
class Aion:
|
||||
|
||||
def __init__(self) -> None:
|
||||
if is_aion:
|
||||
self._aion_config = _config.Aion()
|
||||
|
||||
self.all_listening_modes = ["auto", "manual"]
|
||||
self.all_stt_engines = ["google", "pocketsphinx"]
|
||||
self.all_time_formats = ["12", "24"]
|
||||
self.all_tts_engines = ["pico2wave", "espeak"]
|
||||
self.supported_languages = ["de_DE", "en_US"]
|
||||
|
||||
def get_hotword_file(self) -> str:
|
||||
"""
|
||||
get set hotword file path
|
||||
|
||||
:return: str
|
||||
returns path of the hotword file
|
||||
syntax: <hotword file path>
|
||||
example: "/usr/local/aion-<aion_version>/etc/Aion.pmdl"
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
if is_aion:
|
||||
return self._aion_config.get_hotword_file()
|
||||
else:
|
||||
no_aion()
|
||||
|
||||
def get_language(self) -> str:
|
||||
"""
|
||||
get sett language locale
|
||||
|
||||
:return: str
|
||||
returns language locale
|
||||
syntax: <language locale>
|
||||
example: "en_US"
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
if is_aion:
|
||||
return self._aion_config.get_language()
|
||||
else:
|
||||
no_aion()
|
||||
|
||||
def get_listening_mode(self) -> str:
|
||||
"""
|
||||
get set listening mode
|
||||
|
||||
:return: str
|
||||
returns listening mode
|
||||
syntax: <listening mode>
|
||||
example: "auto"
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
if is_aion:
|
||||
return self._aion_config.get_listening_mode()
|
||||
else:
|
||||
no_aion()
|
||||
|
||||
def get_pid_manipulation_number(self) -> int:
|
||||
"""
|
||||
get set pid manipulation number
|
||||
|
||||
:return: int
|
||||
returns the pid manipulation number
|
||||
syntax: <pid manipulation number>
|
||||
example: 4
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
if is_aion:
|
||||
return int(self._aion_config.get_pid_manipulation_number())
|
||||
else:
|
||||
no_aion()
|
||||
|
||||
def get_stt_engine(self) -> str:
|
||||
"""
|
||||
get set speech-to-text engine
|
||||
|
||||
:return: str
|
||||
returns speech-to-text engine
|
||||
syntax: <speech-to-text engine>
|
||||
example: "google"
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
if is_aion:
|
||||
return self._aion_config.get_stt_engine()
|
||||
else:
|
||||
no_aion()
|
||||
|
||||
def get_time_format(self) -> int:
|
||||
"""
|
||||
get set time format
|
||||
|
||||
:return: str
|
||||
returns time format
|
||||
syntax: <time format>
|
||||
example: 24
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
if is_aion:
|
||||
return int(self._aion_config.get_time_format())
|
||||
else:
|
||||
no_aion()
|
||||
|
||||
def get_tts_engine(self) -> str:
|
||||
"""
|
||||
get set text-to-speech engine
|
||||
|
||||
:return: str
|
||||
returns text-to-speech engine
|
||||
syntax: <text-to-speech engine>
|
||||
example: "espeak"
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
if is_aion:
|
||||
return self._aion_config.get_tts_engine()
|
||||
else:
|
||||
no_aion()
|
||||
|
||||
def set_hotword_file(self, hotword_file: str) -> None:
|
||||
"""
|
||||
sets the hotword file
|
||||
|
||||
:param hotword_file: str
|
||||
location from the new hotword file
|
||||
syntax: <hotword_file>
|
||||
example: "/usr/local/aion-*/etc/Aion.pmdl"
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
if is_aion:
|
||||
self._aion_config.set_hotword_file(hotword_file)
|
||||
else:
|
||||
no_aion()
|
||||
|
||||
def set_language(self, language: str) -> None:
|
||||
"""
|
||||
sets the language locale
|
||||
|
||||
:param language: str
|
||||
new language locale
|
||||
syntax: <language locale>
|
||||
example: "en_US"
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
if is_aion:
|
||||
self._aion_config.set_language(language)
|
||||
else:
|
||||
no_aion()
|
||||
|
||||
def set_listening_mode(self, listening_mode: str) -> None:
|
||||
"""
|
||||
sets the listening mode
|
||||
|
||||
:param listening_mode: str
|
||||
new listening mode
|
||||
syntax: <listening mode>
|
||||
example: "auto"
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
if is_aion:
|
||||
self._aion_config.set_listening_mode(listening_mode)
|
||||
else:
|
||||
no_aion()
|
||||
|
||||
def set_pid_manipulation_number(self, pid_manipulation_number: int) -> None:
|
||||
"""
|
||||
sets the pid manipulation number
|
||||
|
||||
:param pid_manipulation_number: int
|
||||
new pid manipulation number
|
||||
syntax: <pid manipulation number>
|
||||
example: 4
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
if is_aion:
|
||||
self._aion_config.set_pid_manipulation_number(pid_manipulation_number)
|
||||
else:
|
||||
no_aion()
|
||||
|
||||
def set_stt_engine(self, stt_engine: str) -> None:
|
||||
"""
|
||||
sets the spech-to-text engine
|
||||
|
||||
:param stt_engine : str
|
||||
new speech-to-text engine
|
||||
syntax: <speech-to-text engine>
|
||||
example: "google"
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
if is_aion:
|
||||
self._aion_config.set_stt_engine(stt_engine)
|
||||
else:
|
||||
no_aion()
|
||||
|
||||
def set_time_format(self, time_format: str) -> None:
|
||||
"""
|
||||
sets the time format
|
||||
|
||||
:param time_format: str
|
||||
new time format
|
||||
syntax: <time format>
|
||||
example: "24"
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
if is_aion:
|
||||
self._aion_config.set_time_format(time_format)
|
||||
else:
|
||||
no_aion()
|
||||
|
||||
def set_tts_engine(self, tts_engine: str) -> None:
|
||||
"""
|
||||
sets the text-to-speech engine
|
||||
|
||||
:param tts_engine: str
|
||||
new text-to-speech engine
|
||||
syntax: <text-to-speech engine>
|
||||
example: "espeak"
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
if is_aion:
|
||||
self._aion_config.set_tts_engine(tts_engine)
|
||||
else:
|
||||
no_aion()
|
||||
|
||||
|
||||
def add_entry(name: str, text: str = None, attrib: dict = {}, parent_name: str = "config", parent_attrib: dict = {}) -> None:
|
||||
"""
|
||||
adds an entry from the config file
|
||||
|
||||
:param name: str
|
||||
name of the new entry
|
||||
syntax: <name>
|
||||
example: "test_entry"
|
||||
:param text: str, optional
|
||||
text of the new entry
|
||||
syntax: <text>
|
||||
example: "Test"
|
||||
:param attrib: dict, optional
|
||||
attributes of the new entry
|
||||
syntax: {<attribute name>: <attribute value>}
|
||||
example: {"test_attrib", "test"}
|
||||
:param parent_name: str, optional
|
||||
name of the parent entry to which the entry is added
|
||||
syntax: <parent name>
|
||||
example: "test_parent"
|
||||
:param parent_attrib: dict, optional
|
||||
attributes of the parent entry
|
||||
syntax: {<parent attribute name>: <parent attribute value>}
|
||||
example: {"version": "1.0.0"}
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
if is_aion:
|
||||
_config.add_entry(name=name, text=text, attrib=attrib, parent_name=parent_name, parent_attrib=parent_attrib)
|
||||
else:
|
||||
no_aion()
|
||||
|
||||
|
||||
def delete_entry(name: str, parent_name: str = "config", parent_attrib: dict = {}) -> None:
|
||||
"""
|
||||
deletes an entry from the config file
|
||||
|
||||
:param name: str
|
||||
name of the entry to be deleted
|
||||
syntax: <name>
|
||||
example: "test_entry"
|
||||
:param parent_name: str, optional
|
||||
name of the parent entry of the entry to be deleted
|
||||
syntax: <parent name>
|
||||
example: "test_parent"
|
||||
:param parent_attrib: dict, optional
|
||||
attributes of the parent entry from the entry to be searched
|
||||
syntax: {<attribute name>: <attribute value>}
|
||||
example: {"test_attrib", "test"}
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
if is_aion:
|
||||
_config.delete_entry(name=name, parent_name=parent_name, parent_attrib=parent_attrib)
|
||||
else:
|
||||
no_aion()
|
||||
|
||||
|
||||
def get_entry(name: str, parent_name: str = None, parent_attrib: dict = {}) -> None:
|
||||
"""
|
||||
get infos about an entry
|
||||
|
||||
:param name: str
|
||||
name of the entry to be searched
|
||||
syntax: <name>
|
||||
example: "test_entry"
|
||||
:param parent_name: str, optional
|
||||
name of the parent entry of the entry to be deleted
|
||||
syntax: <parent name>
|
||||
example: "test_parent"
|
||||
:param parent_attrib: dict, optional
|
||||
attributes of the parent entry
|
||||
syntax: {<attribute name>: <attribute value>}
|
||||
example: {"test_attrib", "test"}
|
||||
:return: dict
|
||||
returns the infos about the given entry
|
||||
syntax: {"text": <text of entry>, "attrib": <attributes of entry>}
|
||||
e.g.: {"text": "entry text", "attrib": {"version": "1.0.0"}}
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
if is_aion:
|
||||
return _config.get_entry(name=name, parent_name=parent_name, parent_attrib=parent_attrib)
|
||||
else:
|
||||
no_aion()
|
||||
|
||||
|
||||
def update_entry(name: str, text: str = None, attrib: dict = {}, parent_name: str = "config", **extra: str) -> None:
|
||||
"""
|
||||
updates an entry
|
||||
|
||||
:param name: str
|
||||
name of the entry to be updated
|
||||
syntax: <name>
|
||||
example: "test_entry"
|
||||
:param text: str, optional
|
||||
new text of the entry to be updated
|
||||
syntax: <text>
|
||||
example: "new test text"
|
||||
:param attrib: dict, optional
|
||||
new attributes of the entry to be updated
|
||||
syntax: {<attribute name>: <attribute value>}
|
||||
example: {"new_test_attrib", "new_test"}
|
||||
:param parent_name: str, optional
|
||||
parent entry of the entry to be updated
|
||||
syntax: <parent name>
|
||||
example: "test_parent"
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
if is_aion:
|
||||
_config.update_entry(name=name, text=text, attrib=attrib.update(extra), parent_name=parent_name)
|
||||
else:
|
||||
no_aion()
|
171
aionlib/language.py
Normal file
171
aionlib/language.py
Normal file
@ -0,0 +1,171 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
from . import is_aion
|
||||
from ._utils import no_aion
|
||||
|
||||
|
||||
def add_entry(fname: str, package, entry_dict: dict = {}) -> None:
|
||||
"""
|
||||
adds an new entry(s) to from argument 'language_locale' given language
|
||||
|
||||
:param fname: str
|
||||
file name of the file you want to add the entry(s)
|
||||
language locale from the language to which the entry(s) is/are to be added
|
||||
syntax: <language locale>
|
||||
example: "de_DE"
|
||||
:param package: str
|
||||
package name to which the entry belongs
|
||||
syntax: "<package name>"
|
||||
example: "test_package"
|
||||
:param entry_dict: dict, optional
|
||||
all texts for execution of a function
|
||||
syntax: {<entry name>: <text of your entry>}
|
||||
example: {"test_entry": "Test function was executed correctly"}
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
from os.path import isfile
|
||||
|
||||
if isfile(fname) is False:
|
||||
raise FileNotFoundError("the file " + fname + " doesn't exist")
|
||||
|
||||
from ._utils import BaseXMLWriter
|
||||
|
||||
lng_adder = BaseXMLWriter(fname)
|
||||
for entry, text in entry_dict.items():
|
||||
if exist_entry(fname, package, entry) is True:
|
||||
raise IndexError("the entry " + entry + " already exist")
|
||||
lng_adder.add("<root>", package + "." + str(entry), text=str(text))
|
||||
lng_adder.write()
|
||||
|
||||
|
||||
def create_lng_file(language_locale: str, extra_dict: dict = {}, **extra: str) -> None:
|
||||
"""
|
||||
creates a new '.lng' file for given language locale with given entry_dict
|
||||
|
||||
:param language_locale : str
|
||||
language locale of language from which the new file is to be created
|
||||
syntax: <language_locale>
|
||||
example: en_US
|
||||
:param extra_dict: dict, optional
|
||||
package name you want to add specific entries
|
||||
syntax: {<name of the package you want to add entries>: {{<name of the entry>: <text of the entry>}}
|
||||
example: {"test_package": {"test_entry": "This is the text for the test text entry"}}
|
||||
:param extra: kwargs, optional
|
||||
package name you want to add specific entries
|
||||
syntax: <name of the package you want to add entries>={<name of the entry>: <text of the entry>}
|
||||
example: test_package={"test_success": "The test was executed successfully", "text_error": "The test wasn't executed successfully"}
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
from ._utils import BaseXMLBuilder
|
||||
from os import getcwd
|
||||
from os.path import isfile
|
||||
|
||||
if isfile(getcwd() + "/" + language_locale + ".lng"):
|
||||
raise FileExistsError("the language file " + language_locale + ".lng already")
|
||||
|
||||
lng_file = BaseXMLBuilder(language_locale)
|
||||
|
||||
for package, entry_dict in extra_dict.items():
|
||||
for entry_name, entry_text in entry_dict.items():
|
||||
lng_file.create_root_element(language_locale, str(package) + "." + str(entry_name), text=str(entry_text))
|
||||
|
||||
for package, entry_dict in extra.items():
|
||||
for entry_name, entry_text in entry_dict.items():
|
||||
lng_file.create_root_element(language_locale, str(package) + "." + str(entry_name), text=str(entry_text))
|
||||
lng_file.write(language_locale + ".lng")
|
||||
|
||||
|
||||
def delete_entry(fname: str, package: str, entry_list: list = []) -> None:
|
||||
"""
|
||||
deletes entries from '<language_locale>.lng'
|
||||
|
||||
:param fname: str
|
||||
path to file you want to delete entries
|
||||
syntax: <fname>
|
||||
example: "en_US.lng"
|
||||
:param package: str
|
||||
name of the package from which the entries should be deleted
|
||||
syntax: <package name>
|
||||
example: "test"
|
||||
:param entry_list: list, optional
|
||||
name of the entries you want to remove
|
||||
syntax: [<entry name>]
|
||||
example: ["test_entry"]
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
from ._utils import BaseXMLWriter
|
||||
|
||||
lng_writer = BaseXMLWriter(fname)
|
||||
for item in entry_list:
|
||||
lng_writer.remove("language", str(package) + "." + str(item))
|
||||
|
||||
|
||||
def exist_entry(fname: str, package: str, entry: str) -> bool:
|
||||
"""
|
||||
checks if a entry exist
|
||||
|
||||
:param fname: str
|
||||
file from which the entry should be search
|
||||
syntax: <language locale>
|
||||
example: "en_US"
|
||||
:param package: str
|
||||
package name from the entry
|
||||
syntax: <package name>
|
||||
example: "test"
|
||||
:param entry: str
|
||||
entry name of package (entry)
|
||||
syntax: <entry name>
|
||||
example: "test_entry"
|
||||
:return: bool
|
||||
returns True if entry exist / False if not
|
||||
syntax: <boolean>
|
||||
example: False
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
from ._utils import BaseXMLReader
|
||||
|
||||
entry = entry.replace(" ", "_")
|
||||
|
||||
lng_reader = BaseXMLReader(fname)
|
||||
for item in lng_reader.get_infos(["<root>"]).items().index(0):
|
||||
if package + "." + entry in item["childs"]:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def start(skill: str, entry: str, format: dict = {}) -> str:
|
||||
"""
|
||||
returns entry from given arguments
|
||||
|
||||
:param skill: str
|
||||
name of the skill from the entry you want to call
|
||||
syntax: <skill name>
|
||||
example: "test_skill"
|
||||
:param entry: str
|
||||
name of the entry you want to call
|
||||
syntax: <entry>
|
||||
example: "test_func_entry"
|
||||
:param format: dict
|
||||
dictionary to format the string in the '.lng' file
|
||||
syntax: <format>
|
||||
example: {"test", "newtest"}: "This is a test" -> "This is a newtest"
|
||||
:return: str
|
||||
returns the (from 'format' formatted) string from the in '/etc/aion_data/config.xml' setted language locale '.lng' file
|
||||
syntax: <return string>
|
||||
example: "This is a test"
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
if is_aion:
|
||||
from ._utils import import_aion_internal_file as _import_aion_internal_file
|
||||
return _import_aion_internal_file("language").start(skill=skill, entry=entry, format=format)
|
||||
else:
|
||||
no_aion()
|
621
aionlib/logging.py
Normal file
621
aionlib/logging.py
Normal file
@ -0,0 +1,621 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
from . import aion_data_path, is_aion
|
||||
from ._utils import no_aion
|
||||
from time import time as _time
|
||||
|
||||
|
||||
class LogAion:
|
||||
"""
|
||||
class for adding own logs to the aion logger
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
"""
|
||||
set all class variables
|
||||
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
if is_aion:
|
||||
from ._utils import import_aion_internal_file as _import_aion_internal_file
|
||||
self._aion_logger = _import_aion_internal_file("logging").LogAll(aion_data_path + "/logs/aion.log",
|
||||
critical_fname=aion_data_path + "/logs/critical.log",
|
||||
debug_fname=aion_data_path + "/logs/debug.log",
|
||||
error_fname=aion_data_path + "/logs/error.log",
|
||||
info_fname=aion_data_path + "/logs/info.log",
|
||||
warning_fname=aion_data_path + "/logs/warning.log")
|
||||
|
||||
def critical(self, msg: str, lineno: int = None) -> None:
|
||||
"""
|
||||
prints and write given format with 'critical' levelname and in 'msg' given message
|
||||
|
||||
:param msg: str
|
||||
message you want to print and write
|
||||
syntax: <message>
|
||||
example: "critical message"
|
||||
:param lineno: int, optional
|
||||
custom 'lineno' (line number) entry
|
||||
syntax: <lineno>
|
||||
example: 5
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
if is_aion:
|
||||
self._aion_logger.critical(msg=msg, lineno=lineno)
|
||||
else:
|
||||
no_aion()
|
||||
|
||||
def debug(self, msg: str, lineno: int = None) -> None:
|
||||
"""
|
||||
prints and write given format with 'debug' levelname and in 'msg' given message
|
||||
|
||||
:param msg: str
|
||||
message you want to print and write
|
||||
syntax: <message>
|
||||
example: "debug message"
|
||||
:param lineno: int, optional
|
||||
custom 'lineno' (line number) entry
|
||||
syntax: <lineno>
|
||||
example: 5
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
if is_aion:
|
||||
self._aion_logger.debug(msg=msg, lineno=lineno)
|
||||
else:
|
||||
no_aion()
|
||||
|
||||
def error(self, msg: str, lineno: int = None) -> None:
|
||||
"""
|
||||
prints and write given format with 'error' levelname and in 'msg' given message
|
||||
|
||||
:param msg: str
|
||||
message you want to print and write
|
||||
syntax: <message>
|
||||
example: "error message"
|
||||
:param lineno: int, optional
|
||||
custom 'lineno' (line number) entry
|
||||
syntax: <lineno>
|
||||
example: 5
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
if is_aion:
|
||||
self._aion_logger.error(msg=msg, lineno=lineno)
|
||||
else:
|
||||
no_aion()
|
||||
|
||||
def info(self, msg: str, lineno: int = None) -> None:
|
||||
"""
|
||||
prints and write given format with 'info' levelname and in 'msg' given message
|
||||
|
||||
:param msg: str
|
||||
message you want to print and write
|
||||
syntax: <message>
|
||||
example: "info message"
|
||||
:param lineno: int, optional
|
||||
custom 'lineno' (line number) entry
|
||||
syntax: <lineno>
|
||||
example: 5
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
if is_aion:
|
||||
self._aion_logger.info(msg=msg, lineno=lineno)
|
||||
else:
|
||||
no_aion()
|
||||
|
||||
def warning(self, msg: str, lineno: int = None) -> None:
|
||||
"""
|
||||
prints and write given format with 'warning' levelname and in 'msg' given message
|
||||
|
||||
:param msg: str
|
||||
message you want to print and write
|
||||
syntax: <message>
|
||||
example: "warning message"
|
||||
:param lineno: int, optional
|
||||
custom 'lineno' (line number) entry
|
||||
syntax: <lineno>
|
||||
example: 5
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
if is_aion:
|
||||
self._aion_logger.warning(msg=msg, lineno=lineno)
|
||||
else:
|
||||
no_aion()
|
||||
|
||||
|
||||
class LogConsole:
|
||||
"""
|
||||
a simple logger for consoles
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
|
||||
def __init__(self, format: str = "[{runtime}] - {filename}(line: {lineno}) - {levelname}: {message}") -> None:
|
||||
"""
|
||||
:param format : str, optional
|
||||
format of the console output
|
||||
syntax: <format>
|
||||
example: [{runtime}] - {filename}(line: {lineno}) - {levelname}: {message}
|
||||
NOTE: in 'format' you can use the following curly bracktes:
|
||||
year gives the year back
|
||||
month gives the month back
|
||||
day gives the day back
|
||||
hour gives the hour back
|
||||
minute gives the minute back
|
||||
second gives the second back
|
||||
microsecond gives the microsecond back
|
||||
runtime gives the back since the logger has started
|
||||
levelname gives the levelname back
|
||||
filename gives the name of the file from which the logger is called back
|
||||
lineno gives the line number back from which the levelname function was called
|
||||
function gives the function back from which the levelname function was called
|
||||
message gives the in levelname function given message back
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
from datetime import datetime
|
||||
from inspect import getframeinfo, stack
|
||||
|
||||
self.format = format
|
||||
|
||||
self._caller_infos = getframeinfo(stack()[1][0])
|
||||
self._date = datetime.now()
|
||||
self._start_time = _time()
|
||||
|
||||
def _format(self, levelname: str, message: str) -> dict:
|
||||
"""
|
||||
returns a dict with custom entries
|
||||
|
||||
:param levelname: str
|
||||
name of the level
|
||||
syntax: <levelname>
|
||||
example: "INFO"
|
||||
:param message: str
|
||||
message in the dict
|
||||
syntax: <message>
|
||||
example: "Test message"
|
||||
|
||||
:return: dict
|
||||
syntax: {"year": <year>,
|
||||
"month": <month>,
|
||||
"day": <day>,
|
||||
"hour": <hour>,
|
||||
"minute": <minute>,
|
||||
"second": <second>,
|
||||
"microsecond": <microsecond>,
|
||||
"runtime": <runtime>,
|
||||
"levelname": <level name>,
|
||||
"filename": <filename>,
|
||||
"lineno": <line number>,
|
||||
"function": <function>,
|
||||
"message": <message>}
|
||||
example: {"year": 2000,
|
||||
"month": 1,
|
||||
"day": 1,
|
||||
"hour": 00,
|
||||
"minute": 00,
|
||||
"second": 00,
|
||||
"microsecond": 00000,
|
||||
"runtime": "01:23:45",
|
||||
"levelname": "INFO",
|
||||
"filename": "abc.py",
|
||||
"lineno": 123,
|
||||
"function": "test_function",
|
||||
"message": "This is a test message"}
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
return {"year": self._date.year, "month": self._date.month, "day": self._date.day, "hour": self._date.hour, "minute": self._date.minute, "second": self._date.second, "microsecond": self._date.microsecond,
|
||||
"runtime": self._runtime(), "levelname": levelname, "filename": self._caller_infos.filename, "lineno": self._caller_infos.lineno, "function": self._caller_infos.function, "message": message}
|
||||
|
||||
def _runtime(self) -> str:
|
||||
"""
|
||||
returns the runtime
|
||||
|
||||
:return: str
|
||||
returns the runtime
|
||||
syntax: <hour>:<minute>:<day>
|
||||
example: "01:23:45"
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
second = int(_time() - self._start_time)
|
||||
minute = 0
|
||||
hour = 0
|
||||
while (second / 60) >= 1:
|
||||
minute += 1
|
||||
second -= 60
|
||||
|
||||
while (minute / 60) >= 1:
|
||||
hour += 1
|
||||
minute -= 60
|
||||
|
||||
if len(str(second)) == 1:
|
||||
second = "0" + str(second)
|
||||
|
||||
if len(str(minute)) == 1:
|
||||
minute = "0" + str(minute)
|
||||
|
||||
if len(str(hour)) == 1:
|
||||
hour = "0" + str(hour)
|
||||
|
||||
return str(str(hour) + ":" + str(minute) + ":" + str(second))
|
||||
|
||||
def critical(self, msg: str, _format_values: dict = None) -> None:
|
||||
"""
|
||||
prints given format with 'critical' levelname and in 'msg' given message
|
||||
|
||||
:param msg: str
|
||||
message you want to print out
|
||||
syntax: <message>
|
||||
example: "critical message"
|
||||
:param _format_values: dict, optional
|
||||
dictionary with own format values
|
||||
syntax: {<key>: <value>}
|
||||
example: {"mytext": "This is my text"}
|
||||
NOTE: if you use '_format_values' the in function '_format' given format values won't used
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
if _format_values is None:
|
||||
print(self.format.format(**self._format(levelname="CRITICAL", message=msg)))
|
||||
else:
|
||||
print(self.format.format(**_format_values))
|
||||
|
||||
def debug(self, msg: str, _format_values: dict = None) -> None:
|
||||
"""
|
||||
prints given format with 'debug' levelname and in 'msg' given message
|
||||
|
||||
:param msg: str
|
||||
message you want to print out
|
||||
syntax: <message>
|
||||
example: "debug message"
|
||||
:param _format_values: dict, optional
|
||||
dictionary with own format values
|
||||
syntax: {<key>: <value>}
|
||||
example: {"mytext": "This is my text"}
|
||||
NOTE: if you use '_format_values' the in function '_format' given format values won't used
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
if _format_values is None:
|
||||
print(self.format.format(**self._format(levelname="DEBUG", message=msg)))
|
||||
else:
|
||||
print(self.format.format(**_format_values))
|
||||
|
||||
def error(self, msg: str, _format_values: dict = None) -> None:
|
||||
"""
|
||||
prints given format with 'error' levelname and in 'msg' given message
|
||||
|
||||
:param msg: str
|
||||
message you want to print out
|
||||
syntax: <message>
|
||||
example: "error message"
|
||||
:param _format_values: dict, optional
|
||||
dictionary with own format values
|
||||
syntax: {<key>: <value>}
|
||||
example: {"mytext": "This is my text"}
|
||||
NOTE: if you use '_format_values' the in function '_format' given format values won't used
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
if _format_values is None:
|
||||
print(self.format.format(**self._format(levelname="ERROR", message=msg)))
|
||||
else:
|
||||
print(self.format.format(**_format_values))
|
||||
|
||||
def info(self, msg: str, _format_values: dict = None) -> None:
|
||||
"""
|
||||
prints given format with 'info' levelname and in 'msg' given message
|
||||
|
||||
:param msg: str
|
||||
message you want to print out
|
||||
syntax: <message>
|
||||
example: "info message"
|
||||
:param _format_values: dict, optional
|
||||
dictionary with own format values
|
||||
syntax: {<key>: <value>}
|
||||
example: {"mytext": "This is my text"}
|
||||
NOTE: if you use '_format_values' the in function '_format' given format values won't used
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
if _format_values is None:
|
||||
print(self.format.format(**self._format(levelname="INFO", message=msg)))
|
||||
else:
|
||||
print(self.format.format(**_format_values))
|
||||
|
||||
def warning(self, msg: str, _format_values: dict = None) -> None:
|
||||
"""
|
||||
prints given format with 'warning' levelname and in 'msg' given message
|
||||
|
||||
:param msg: str
|
||||
message you want to print out
|
||||
syntax: <message>
|
||||
example: "warning message"
|
||||
:param _format_values: dict, optional
|
||||
dictionary with own format values
|
||||
syntax: {<key>: <value>}
|
||||
example: {"mytext": "This is my text"}
|
||||
NOTE: if you use '_format_values' the in function '_format' given format values won't used
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
|
||||
if _format_values is None:
|
||||
print(self.format.format(**self._format(levelname="WARNING", message=msg)))
|
||||
else:
|
||||
print(self.format.format(**_format_values))
|
||||
|
||||
|
||||
class LogFile:
|
||||
"""
|
||||
a simple logger for files
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
|
||||
def __init__(self, log_fname: str, mode: str = "a", format: str = "[{year}-{month}-{day} {hour}:{minute}:{second}] - {filename}(line: {lineno}) - {levelname}: {message}") -> None:
|
||||
"""
|
||||
:param log_fname: str
|
||||
filename of the file to which the logging messages should be saved
|
||||
syntax: <fname>
|
||||
example: "/home/pi/test.log"
|
||||
:param mode: str, optional
|
||||
mode to write on file
|
||||
syntax: <mode>
|
||||
example: "a"
|
||||
:param format: str, optional
|
||||
format of the output that should be write to file
|
||||
syntax: <format>
|
||||
example: [{runtime}] - {filename}(line: {lineno}) - {levelname}: {message}
|
||||
NOTE: in 'format' you can use the following curly bracktes:
|
||||
year gives the year back
|
||||
month gives the month back
|
||||
day gives the day back
|
||||
hour gives the hour back
|
||||
minute gives the minute back
|
||||
second gives the second back
|
||||
microsecond gives the microsecond back
|
||||
runtime gives the back since the logger has started
|
||||
levelname gives the levelname back
|
||||
filename gives the name of the file from which the logger is called back
|
||||
lineno gives the line number back from which the levelname function was called
|
||||
function gives the function back from which the levelname function was called
|
||||
message gives the in levelname function given message back
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
from datetime import datetime
|
||||
from inspect import getframeinfo, stack
|
||||
|
||||
self.format = format
|
||||
self.log_fname = log_fname
|
||||
self.mode = mode
|
||||
|
||||
self._caller_infos = getframeinfo(stack()[1][0])
|
||||
self._date = datetime.now()
|
||||
self._start_time = _time()
|
||||
|
||||
def _format(self, levelname: str, message: str) -> dict:
|
||||
"""
|
||||
returns a dict with custom entries
|
||||
|
||||
:param levelname: str
|
||||
name of the level
|
||||
syntax: <levelname>
|
||||
example: "INFO"
|
||||
:param message: str
|
||||
message in the dict
|
||||
syntax: <message>
|
||||
example: "Test message"
|
||||
:return: dict
|
||||
syntax: {"year": <year>,
|
||||
"month": <month>,
|
||||
"day": <day>,
|
||||
"hour": <hour>,
|
||||
"minute": <minute>,
|
||||
"second": <second>,
|
||||
"microsecond": <microsecond>,
|
||||
"runtime": <runtime>,
|
||||
"levelname": <level name>,
|
||||
"filename": <filename>,
|
||||
"lineno": <line number>,
|
||||
"function": <function>,
|
||||
"message": <message>}
|
||||
example: {"year": 2000,
|
||||
"month": 1,
|
||||
"day": 1,
|
||||
"hour": 00,
|
||||
"minute": 00,
|
||||
"second": 00,
|
||||
"microsecond": 00000,
|
||||
"runtime": "01:23:45",
|
||||
"levelname": "INFO",
|
||||
"filename": "abc.py",
|
||||
"lineno": 123,
|
||||
"function": "test_function",
|
||||
"message": "This is a test message"}
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
return {"year": self._date.year, "month": self._date.month, "day": self._date.day, "hour": self._date.hour, "minute": self._date.minute, "second": self._date.second, "microsecond": self._date.microsecond,
|
||||
"runtime": self._runtime(), "levelname": levelname, "filename": self._caller_infos.filename, "lineno": self._caller_infos.lineno, "function": self._caller_infos.function, "message": message}
|
||||
|
||||
def _runtime(self) -> str:
|
||||
"""
|
||||
returns the runtime
|
||||
|
||||
:return: str
|
||||
returns the runtime
|
||||
syntax: <hour>:<minute>:<day>
|
||||
example: "01:23:45"
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
second = int(_time() - self._start_time)
|
||||
minute = 0
|
||||
hour = 0
|
||||
while (second / 60) >= 1:
|
||||
minute += 1
|
||||
second -= 60
|
||||
|
||||
while (minute / 60) >= 1:
|
||||
hour += 1
|
||||
minute -= 60
|
||||
|
||||
if len(str(second)) == 1:
|
||||
second = "0" + str(second)
|
||||
|
||||
if len(str(minute)) == 1:
|
||||
minute = "0" + str(minute)
|
||||
|
||||
if len(str(hour)) == 1:
|
||||
hour = "0" + str(hour)
|
||||
|
||||
return str(str(hour) + ":" + str(minute) + ":" + str(second))
|
||||
|
||||
def _write(self, msg: str) -> None:
|
||||
"""
|
||||
writes the given message to the log file
|
||||
|
||||
:param msg: str
|
||||
message that should be write to the file
|
||||
syntax: <message>
|
||||
example: "Test message"
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
with open(self.log_fname, self.mode) as file:
|
||||
file.write(msg + "\n")
|
||||
file.close()
|
||||
|
||||
def critical(self, msg: str, _format_values: dict = None) -> None:
|
||||
"""
|
||||
writes given format with 'critical' levelname and in 'msg' given message to file
|
||||
|
||||
:param msg: str
|
||||
message you want to write to file
|
||||
syntax: <message>
|
||||
example: "critical message"
|
||||
:param _format_values: dict, optional
|
||||
dictionary with own format values
|
||||
syntax: {<key>: <value>}
|
||||
example: {"mytext": "This is my text"}
|
||||
NOTE: if you use '_format_values' the in function '_format' given format values won't used
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
if _format_values is None:
|
||||
self._write(self.format.format(**self._format(levelname="CRITICAL", message=msg)))
|
||||
else:
|
||||
self._write(self.format.format(**_format_values))
|
||||
|
||||
def debug(self, msg: str, _format_values: dict = None) -> None:
|
||||
"""
|
||||
writes given format with 'debug' levelname and in 'msg' given message to file
|
||||
|
||||
:param msg: str
|
||||
message you want to write to file
|
||||
syntax: <message>
|
||||
example: "debug message"
|
||||
:param _format_values: dict, optional
|
||||
dictionary with own format values
|
||||
syntax: {<key>: <value>}
|
||||
example: {"mytext": "This is my text"}
|
||||
NOTE: if you use '_format_values' the in function '_format' given format values won't used
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
if _format_values is None:
|
||||
self._write(self.format.format(**self._format(levelname="DEBUG", message=msg)))
|
||||
else:
|
||||
self._write(self.format.format(**_format_values))
|
||||
|
||||
def error(self, msg: str, _format_values: dict = None) -> None:
|
||||
"""
|
||||
writes given format with 'debug' levelname and in 'msg' given message to file
|
||||
|
||||
:param msg: str
|
||||
message you want to write to file
|
||||
syntax: <message>
|
||||
example: "debug message"
|
||||
:param _format_values: dict, optional
|
||||
dictionary with own format values
|
||||
syntax: {<key>: <value>}
|
||||
example: {"mytext": "This is my text"}
|
||||
NOTE: if you use '_format_values' the in function '_format' given format values won't used
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
if _format_values is None:
|
||||
self._write(self.format.format(**self._format(levelname="ERROR", message=msg)))
|
||||
else:
|
||||
self._write(self.format.format(**_format_values))
|
||||
|
||||
def info(self, msg: str, _format_values: dict = None) -> None:
|
||||
"""
|
||||
writes given format with 'info' levelname and in 'msg' given message to file
|
||||
|
||||
:param msg: str
|
||||
message you want to write to file
|
||||
syntax: <message>
|
||||
example: "info message"
|
||||
:param _format_values: dict, optional
|
||||
dictionary with own format values
|
||||
syntax: {<key>: <value>}
|
||||
example: {"mytext": "This is my text"}
|
||||
NOTE: if you use '_format_values' the in function '_format' given format values won't used
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
if _format_values is None:
|
||||
self._write(self.format.format(**self._format(levelname="INFO", message=msg)))
|
||||
else:
|
||||
self._write(self.format.format(**_format_values))
|
||||
|
||||
def warning(self, msg: str, _format_values: dict = None) -> None:
|
||||
"""
|
||||
writes given format with 'warning' levelname and in 'msg' given message to file
|
||||
|
||||
:param msg: str
|
||||
message you want to write to file
|
||||
syntax: <message>
|
||||
example: "warning message"
|
||||
:param _format_values: dict, optional
|
||||
dictionary with own format values
|
||||
syntax: {<key>: <value>}
|
||||
example: {"mytext": "This is my text"}
|
||||
NOTE: if you use '_format_values' the in function '_format' given format values won't used
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
if _format_values is None:
|
||||
self._write(self.format.format(**self._format(levelname="WARNING", message=msg)))
|
||||
else:
|
||||
self._write(self.format.format(**_format_values))
|
670
aionlib/plugin.py
Normal file
670
aionlib/plugin.py
Normal file
@ -0,0 +1,670 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
from . import aion_data_path as _aion_data_path
|
||||
|
||||
|
||||
RUN_AFTER = "run_after"
|
||||
RUN_BEFORE = "run_after"
|
||||
|
||||
|
||||
run_after_path = _aion_data_path + "/plugins/run_after"
|
||||
run_before_path = _aion_data_path + "/plugins/run_before"
|
||||
|
||||
run_after_file = _aion_data_path + "/plugins/run_after/run_after.xml"
|
||||
run_before_file = _aion_data_path + "/plugins/run_before/run_before.xml"
|
||||
|
||||
|
||||
class RunAfter:
|
||||
"""
|
||||
base class to create custom 'run_after' plugins
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
|
||||
def __init__(self, activate_phrase: str, speech_input: str) -> None:
|
||||
"""
|
||||
makes the variables available for all class functions
|
||||
|
||||
:param activate_phrase: str
|
||||
activate phrase from which this class was called
|
||||
syntax: <activate phrase>
|
||||
example: "start plugin test"
|
||||
:param speech_input: str
|
||||
input that the user has spoken in
|
||||
syntax: <speech input>
|
||||
example: "start plugin test"
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
self.activate_phrase = activate_phrase
|
||||
self.speech_input = speech_input
|
||||
|
||||
def main(self) -> None:
|
||||
"""
|
||||
gets called if the class get called from the 'run_after_plugin' plugin of the 'Skill' class
|
||||
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class RunBefore:
|
||||
"""
|
||||
base class to create custom 'run_before' plugins
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
|
||||
def __init__(self, activate_phrase: str, speech_input: str) -> None:
|
||||
"""
|
||||
makes the variables available for all class functions
|
||||
|
||||
:param activate_phrase: str
|
||||
activate phrase from which this class was called
|
||||
syntax: <activate phrase>
|
||||
example: "start plugin test"
|
||||
:param speech_input: str
|
||||
input that the user has spoken in
|
||||
syntax: <speech input>
|
||||
example: "start plugin test"
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
self.activate_phrase = activate_phrase
|
||||
self.speech_input = speech_input
|
||||
|
||||
def main(self) -> None:
|
||||
"""
|
||||
gets called if the class get called from the 'run_before_plugin' function of the 'Skill' class
|
||||
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def create_run_after_plugin_file(author: str,
|
||||
plugin_name: str,
|
||||
main_file: str,
|
||||
skill: str,
|
||||
plugin_methods: dict,
|
||||
version: str,
|
||||
additional_directories: list = [],
|
||||
description: str = "",
|
||||
language_locales: list = [],
|
||||
language_dict: dict = {},
|
||||
license: str = "",
|
||||
required_python3_packages: list = []) -> None:
|
||||
"""
|
||||
creates a file from which a 'run_after' plugin can be installed
|
||||
|
||||
:param author: str
|
||||
name of the author from the plugin
|
||||
syntax: <author name>
|
||||
example: "blueShard"
|
||||
:param main_file: str
|
||||
file name of file where all plugin methods are defined
|
||||
syntax: <file name>
|
||||
example: "test.py"
|
||||
NOTE: the file must be in the same directory as the file from which 'create_run_after_plugin_file' is being executed
|
||||
:param plugin_name: str
|
||||
root name of the plugin you create
|
||||
syntax: <plugin name>
|
||||
example: "text_plugin"
|
||||
:param skill: str
|
||||
name of the skill you want to add the 'run_before' plugin
|
||||
syntax: <skill name>
|
||||
example: "Play"
|
||||
NOTE: be case-sensitive!
|
||||
:param plugin_methods: dict
|
||||
dictionary of plugin pseudonym with plugin method you want to add to given 'skill'
|
||||
syntax: {"<plugin pseudonym>": <plugin methods>}
|
||||
example: ["test_plugin_run_test_2": "TestPlugin"]
|
||||
NOTE: be case-sensitive!
|
||||
NOTE2: the plugins pseudonyms are only pseudonyms for the given methods
|
||||
NOTE3: you can't remove individual plugins via the 'aion' command line command
|
||||
:param version: str
|
||||
version (number) of your plugin
|
||||
syntax: <version>
|
||||
example: "1.0.0"
|
||||
:param additional_directories: list, optional
|
||||
list of additional directories your main file needs for execution
|
||||
syntax: [<additional directories>]
|
||||
example: ["test_directory"]
|
||||
NOTE: the directories must be in the same directory as the file from which 'create_run_after_plugin_file' is being executed
|
||||
:param description: str, optional
|
||||
description of your plugin
|
||||
syntax: <description>
|
||||
example: "A simple plugin to test the method 'create_run_after_plugin_file'"
|
||||
:param language_locales: list
|
||||
list of language locales for which the 'language_dict' should be stored
|
||||
syntax: [<language locale>]
|
||||
example: ["en_US"]
|
||||
:param language_dict: dict, optional
|
||||
dictionary of messages which are saved in (from argument 'language_locales' given) '.lng' files
|
||||
syntax: {<entry>, <text>}
|
||||
example: {"test_entry": "The test was successful"}
|
||||
NOTE: the method name should be included in the entry for legibility
|
||||
NOTE2: for more infos about language ('.lng') files, see file 'language.py'
|
||||
:param license: str, optional
|
||||
license of the plugin
|
||||
syntax: <license>
|
||||
example: "MPL-2.0"
|
||||
:param required_python3_packages: list, optional
|
||||
list of python3 packages your plugin needs for correct execution
|
||||
syntax: [<python3 package>]
|
||||
example: ["aionlib"]
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
_create_befater_plugin_file("run_after",
|
||||
author,
|
||||
plugin_name,
|
||||
main_file,
|
||||
skill,
|
||||
plugin_methods,
|
||||
version,
|
||||
additional_directories,
|
||||
description,
|
||||
language_locales,
|
||||
language_dict,
|
||||
license,
|
||||
required_python3_packages)
|
||||
|
||||
|
||||
def create_run_before_plugin_file(author: str,
|
||||
plugin_name: str,
|
||||
main_file: str,
|
||||
skill: str,
|
||||
plugin_methods: dict,
|
||||
version: str,
|
||||
additional_directories: list = [],
|
||||
description: str = "",
|
||||
language_locales: list = [],
|
||||
language_dict: dict = {},
|
||||
license: str = "",
|
||||
required_python3_packages: list = []) -> None:
|
||||
"""
|
||||
creates a file from which a 'run_before' plugin can be installed
|
||||
|
||||
:param author: str
|
||||
name of the author from the plugin
|
||||
syntax: <author name>
|
||||
example: "blueShard"
|
||||
:param main_file: str
|
||||
file name of file where all plugin methods are defined
|
||||
syntax: <file name>
|
||||
example: "test.py"
|
||||
NOTE: the file must be in the same directory as the file from which 'create_run_before_plugin_file' is being executed
|
||||
:param plugin_name: str
|
||||
root name of the plugins you create
|
||||
syntax: <plugin name>
|
||||
example: "text_plugin"
|
||||
:param skill: str
|
||||
name of the skill you want to add the 'run_before' plugin
|
||||
syntax: <skill name>
|
||||
example: "Play"
|
||||
NOTE: be case-sensitive!
|
||||
:param plugin_methods: dict
|
||||
dictionary of plugin pseudonym with plugin method you want to add to given 'skill'
|
||||
syntax: {"<plugin pseudonyms>": <plugin methods>}
|
||||
example: ["test_plugin_run_test_2": "TestPlugin"]
|
||||
NOTE: be case-sensitive!
|
||||
NOTE2: the plugins pseudonyms are only pseudonyms for the given methods
|
||||
NOTE3: you can't remove individual plugins via the 'aion' command line command
|
||||
:param plugin_name: str
|
||||
name of the plugin you create
|
||||
syntax: <plugin name>
|
||||
example: "text_plugin"
|
||||
:param version: str
|
||||
version (number) of your plugin
|
||||
syntax: <version>
|
||||
example: "1.0.0"
|
||||
:param additional_directories: list, optional
|
||||
list of additional directories your main file needs for execution
|
||||
syntax: [<additional directories>]
|
||||
example: ["test_directory"]
|
||||
NOTE: the directories must be in the same directory as the file from which 'create_run_before_plugin_file' is being executed
|
||||
:param description: str, optional
|
||||
description of your plugin
|
||||
syntax: <description>
|
||||
example: "A simple plugin to test the method 'create_run_after_plugin_file'"
|
||||
:param language_locales: list
|
||||
list of language locales for which the 'language_dict' should be stored
|
||||
syntax: [<language locale>]
|
||||
example: ["en_US"]
|
||||
:param language_dict: dict, optional
|
||||
dictionary of messages which are saved in (from argument 'language_locales' given) '.lng' files
|
||||
syntax: {<entry>, <text>}
|
||||
example: {"test_entry": "The test was successful"}
|
||||
NOTE: the method name should be included in the entry for legibility
|
||||
NOTE2: for more infos about language ('.lng') files, see file 'language.py'
|
||||
:param license: str, optional
|
||||
license of the plugin
|
||||
syntax: <license>
|
||||
example: "MPL-2.0"
|
||||
:param required_python3_packages: list, optional
|
||||
list of python3 packages your plugin needs for correct execution
|
||||
syntax: [<python3 package>]
|
||||
example: ["aionlib"]
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
_create_befater_plugin_file("run_before",
|
||||
author,
|
||||
plugin_name,
|
||||
main_file,
|
||||
skill,
|
||||
plugin_methods,
|
||||
version,
|
||||
additional_directories,
|
||||
description,
|
||||
language_locales,
|
||||
language_dict,
|
||||
license,
|
||||
required_python3_packages)
|
||||
|
||||
|
||||
def create_plugin_package(dir_name: str) -> None:
|
||||
"""
|
||||
creates a stand alone file ('.plugin') from given directory
|
||||
|
||||
:param dir_name : str
|
||||
directory name of the directory from which you want to create a '.plugin' file
|
||||
syntax: <directory name>
|
||||
example: "/home/pi/test/"
|
||||
:return: None
|
||||
|
||||
:note: 'plugin.aion' file must be in the given directory (see 'create_run_after_plugin_file' / 'create_run_before_plugin_file' to create a 'plugin.aion' file)
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
from os import listdir, mkdir, rename
|
||||
from os.path import isdir
|
||||
from random import sample
|
||||
from shutil import make_archive, rmtree
|
||||
|
||||
if isdir(dir_name) is False:
|
||||
raise NotADirectoryError("couldn't find the directory '" + dir_name + "'")
|
||||
|
||||
name = ""
|
||||
file_num = 0
|
||||
for file in listdir(dir_name):
|
||||
if file.endswith(".aion"):
|
||||
file_num += 1
|
||||
name = "".join(file.split(".aion")[0])
|
||||
if file_num == 0:
|
||||
raise FileNotFoundError("couldn't find .aion file in " + dir_name + ". To create one use the 'create_plugin_file' function in aionlib.skill")
|
||||
elif file_num > 1:
|
||||
raise FileExistsError("expected one .aion file in " + dir_name + ", got " + str(file_num))
|
||||
|
||||
plugin_dir_name = "plugin_" + name + "".join([str(num) for num in sample(range(1, 10), 5)])
|
||||
mkdir(plugin_dir_name)
|
||||
|
||||
make_archive(name + ".plugin", "zip", plugin_dir_name)
|
||||
rename(plugin_dir_name + ".plugin.zip", plugin_dir_name + ".plugin")
|
||||
|
||||
rmtree(plugin_dir_name)
|
||||
|
||||
|
||||
def get_all_run_after_plugins() -> dict:
|
||||
"""
|
||||
get all installed 'run_after' plugins + infos
|
||||
|
||||
:return: dict
|
||||
returns dict of all plugins + infos
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
from . import is_aion
|
||||
from .utils import is_dict_in_dict
|
||||
from ._utils import no_aion, BaseXMLReader
|
||||
|
||||
run_after = {}
|
||||
|
||||
if is_aion:
|
||||
for value in BaseXMLReader(run_after_file).get_infos("<all>").values():
|
||||
for child in value:
|
||||
attrib = child["attrib"]
|
||||
parent_tag = child["parent"]["tag"]
|
||||
parent_attrib = child["parent"]["attrib"]
|
||||
if is_dict_in_dict({"type": "skill"}, parent_attrib):
|
||||
try:
|
||||
run_after[parent_tag][child["tag"]] = {"method": attrib["method"], "root_plugin": attrib["root_plugin"]}
|
||||
except KeyError:
|
||||
run_after[parent_tag] = {}
|
||||
else:
|
||||
for skill in run_after.values():
|
||||
for plugin in skill:
|
||||
if plugin == parent_tag:
|
||||
run_after[skill][plugin][child["tag"]] = child["text"]
|
||||
break
|
||||
else:
|
||||
no_aion()
|
||||
|
||||
return run_after
|
||||
|
||||
|
||||
def get_all_run_before_plugins() -> dict:
|
||||
"""
|
||||
get all installed 'run_before' plugins + infos
|
||||
|
||||
:return: dict
|
||||
returns dict of all plugins + infos
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
from . import is_aion
|
||||
from .utils import is_dict_in_dict
|
||||
from ._utils import no_aion, BaseXMLReader
|
||||
|
||||
run_before = {}
|
||||
|
||||
if is_aion:
|
||||
for value in BaseXMLReader(run_before_file).get_infos("<all>").values():
|
||||
for child in value:
|
||||
attrib = child["attrib"]
|
||||
parent_tag = child["parent"]["tag"]
|
||||
parent_attrib = child["parent"]["attrib"]
|
||||
if is_dict_in_dict({"type": "skill"}, parent_attrib):
|
||||
try:
|
||||
run_before[parent_tag][child["tag"]] = {"method": attrib["method"], "root_plugin": attrib["root_plugin"]}
|
||||
except KeyError:
|
||||
run_before[parent_tag] = {}
|
||||
else:
|
||||
for skill in run_before.values():
|
||||
for plugin in skill:
|
||||
if plugin == parent_tag:
|
||||
run_before[skill][plugin][child["tag"]] = child["text"]
|
||||
break
|
||||
else:
|
||||
no_aion()
|
||||
|
||||
return run_before
|
||||
|
||||
|
||||
def get_run_after_plugin_infos(plugin_name: str) -> dict:
|
||||
"""
|
||||
returns infos about an given 'run_after' plugin
|
||||
|
||||
:param plugin_name: str
|
||||
the name of the 'run_after' plugin
|
||||
syntax: <plugin name>
|
||||
example: "test_plugin"
|
||||
:return: dict
|
||||
returns a dictionary with infos of the 'run_after' plugin
|
||||
syntax: {"author": <author>,
|
||||
"main_file": <main file>,
|
||||
"plugin_root_name": <plugin root name>
|
||||
"plugin_name": <plugin name>,
|
||||
"plugin_method": <plugin method>
|
||||
"version": <version>,
|
||||
"additional_directories": [<additional directories>],
|
||||
"description": <description>,
|
||||
"language_locales": [<language locales>],
|
||||
"language_dict": {<entry>: <text>}
|
||||
"license": <license>,
|
||||
"required_python3_packages": [<python3 packages>]}
|
||||
example: {"author": "blueShard",
|
||||
"main_file": "test.py",
|
||||
"plugin_root_name:": "test_plugin"
|
||||
"plugin_name": "test_plugin_run_after",
|
||||
"plugin_method": "test_plugin_method"
|
||||
"version": "1.0.0",
|
||||
"additional_directories": ["test_directory"],
|
||||
"description": "A simple plugin to test the method 'get_run_after_plugin_infos",
|
||||
"language_locales": ["en_US"],
|
||||
"language_dict": {"test_method": "The test was successful"},
|
||||
"license": "MPL-2.0",
|
||||
"required_python3_packages": ["aionlib"]}
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
for skill in get_all_run_after_plugins().values():
|
||||
for plugin, infos in skill.values():
|
||||
if plugin == plugin_name:
|
||||
return infos
|
||||
|
||||
|
||||
def get_run_before_plugin_infos(plugin_name: str) -> dict:
|
||||
"""
|
||||
returns infos about an given 'run_before' plugin
|
||||
|
||||
:param plugin_name: str
|
||||
the name of the 'run_after' plugin
|
||||
syntax: <plugin name>
|
||||
example: "test_plugin"
|
||||
:return: dict
|
||||
returns a dictionary with infos of the 'run_after' plugin
|
||||
syntax: {"author": <author>,
|
||||
"main_file": <main file>,
|
||||
"plugin_root_name": <plugin root name>
|
||||
"plugin_name": <plugin name>,
|
||||
"plugin_method": <plugin method>
|
||||
"version": <version>,
|
||||
"additional_directories": [<additional directories>],
|
||||
"description": <description>,
|
||||
"language_locales": [<language locales>],
|
||||
"language_dict": {<entry>: <text>}
|
||||
"license": <license>,
|
||||
"required_python3_packages": [<python3 packages>]}
|
||||
example: {"author": "blueShard",
|
||||
"main_file": "test.py",
|
||||
"plugin_root_name:": "test_plugin"
|
||||
"plugin_name": "test_plugin_run_before",
|
||||
"plugin_method": "test_plugin_method"
|
||||
"version": "1.0.0",
|
||||
"additional_directories": ["test_directory"],
|
||||
"description": "A simple plugin to test the method 'get_run_before_plugin_infos",
|
||||
"language_locales": ["en_US"],
|
||||
"language_dict": {"test_method": "The test was successful"},
|
||||
"license": "MPL-2.0",
|
||||
"required_python3_packages": ["aionlib"]}
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
for skill in get_all_run_before_plugins().values():
|
||||
for plugin, infos in skill.values():
|
||||
if plugin == plugin_name:
|
||||
return infos
|
||||
|
||||
|
||||
def _create_befater_plugin_file(type: (RUN_AFTER, RUN_BEFORE),
|
||||
author: str,
|
||||
plugin_name: str,
|
||||
main_file: str,
|
||||
skill: str,
|
||||
plugin_methods: dict,
|
||||
version: str,
|
||||
additional_directories: list = [],
|
||||
description: str = "",
|
||||
language_locales: list = [],
|
||||
language_dict: dict = {},
|
||||
license: str = "",
|
||||
required_python3_packages: list = []) -> None:
|
||||
"""
|
||||
creates a file from which a plugin can be installed
|
||||
|
||||
:param type: (RUN_AFTER, RUN_BEFORE)
|
||||
type of the plugin
|
||||
syntax: <plugin type>
|
||||
example: RUN_AFTER
|
||||
:param author: str
|
||||
name of the author from the plugin
|
||||
syntax: <author name>
|
||||
example: "blueShard"
|
||||
:param main_file: str
|
||||
file name of file where all plugin methods are defined
|
||||
syntax: <file name>
|
||||
example: "test.py"
|
||||
NOTE: the file must be in the same directory as the file from which 'create_run_after_plugin_file' is being executed
|
||||
:param plugin_name: str
|
||||
root name of the plugin you create
|
||||
syntax: <plugin name>
|
||||
example: "text_plugin"
|
||||
:param skill: str
|
||||
name of the skill you want to add the 'run_before' plugin
|
||||
syntax: <skill name>
|
||||
example: "Play"
|
||||
NOTE: be case-sensitive!
|
||||
:param plugin_methods: dict
|
||||
dictionary of plugin pseudonym with plugin method you want to add to given 'skill'
|
||||
syntax: {"<plugin pseudonym>": <plugin methods>}
|
||||
example: ["test_plugin_run_test_2": "TestPlugin"]
|
||||
NOTE: be case-sensitive!
|
||||
NOTE2: the plugins pseudonyms are only pseudonyms for the given methods
|
||||
NOTE3: you can't remove individual plugins via the 'aion' command line command
|
||||
:param version: str
|
||||
version (number) of your plugin
|
||||
syntax: <version>
|
||||
example: "1.0.0"
|
||||
:param additional_directories: list, optional
|
||||
list of additional directories your main file needs for execution
|
||||
syntax: [<additional directories>]
|
||||
example: ["test_directory"]
|
||||
NOTE: the directories must be in the same directory as the file from which 'create_run_after_plugin_file' is being executed
|
||||
:param description: str, optional
|
||||
description of your plugin
|
||||
syntax: <description>
|
||||
example: "A simple plugin to test the method 'create_run_after_plugin_file'"
|
||||
:param language_locales: list
|
||||
list of language locales for which the 'language_dict' should be stored
|
||||
syntax: [<language locale>]
|
||||
example: ["en_US"]
|
||||
:param language_dict: dict, optional
|
||||
dictionary of messages which are saved in (from argument 'language_locales' given) '.lng' files
|
||||
syntax: {<entry>, <text>}
|
||||
example: {"test_entry": "The test was successful"}
|
||||
NOTE: the method name should be included in the entry for legibility
|
||||
NOTE2: for more infos about language ('.lng') files, see file 'language.py'
|
||||
:param license: str, optional
|
||||
license of the plugin
|
||||
syntax: <license>
|
||||
example: "MPL-2.0"
|
||||
:param required_python3_packages: list, optional
|
||||
list of python3 packages your plugin needs for correct execution
|
||||
syntax: [<python3 package>]
|
||||
example: ["aionlib"]
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
from os import getcwd, listdir
|
||||
|
||||
write_dict = {}
|
||||
|
||||
if isinstance(author, str) is False:
|
||||
raise TypeError("argument 'author' must be str, got " + type(author).__name__)
|
||||
write_dict["author"] = author
|
||||
|
||||
if isinstance(main_file, str) is False:
|
||||
raise TypeError("argument 'main_file' must be str, got " + type(author).__name__)
|
||||
if main_file not in listdir(getcwd()):
|
||||
raise FileNotFoundError("couldn't find the file " + main_file + " in current directory")
|
||||
if main_file[:-3] == plugin_name is False:
|
||||
raise NameError("the file name from " + main_file + " must be same as the argument 'name' (" + plugin_name + ")")
|
||||
if main_file not in listdir(getcwd()):
|
||||
raise FileNotFoundError("couldn't find the file '" + main_file + "' in current directory")
|
||||
write_dict["main_file"] = main_file
|
||||
|
||||
if isinstance(plugin_name, str) is False:
|
||||
raise TypeError("argument 'plugin_name' must be str, got " + type(plugin_name).__name__)
|
||||
write_dict["plugin_name"] = plugin_name
|
||||
|
||||
if isinstance(skill, str) is False:
|
||||
raise TypeError("argument 'plugin_name' must be dict, got " + type(plugin_methods).__name__)
|
||||
write_dict["skill"] = skill
|
||||
|
||||
if isinstance(plugin_methods, dict) is False:
|
||||
raise TypeError("argument 'plugin_name' must be dict, got " + type(plugin_methods).__name__)
|
||||
write_dict["plugin_methods"] = plugin_methods
|
||||
|
||||
if isinstance(version, str) is False:
|
||||
raise TypeError("argument 'version' must be str, got " + type(version).__name__)
|
||||
write_dict["version"] = version
|
||||
|
||||
# ----- #
|
||||
|
||||
if isinstance(additional_directories, (list, tuple)) is False:
|
||||
raise TypeError("argument 'additional_directories' must be list or tuple, got " + type(additional_directories).__name__)
|
||||
for directory in additional_directories:
|
||||
if directory not in listdir(getcwd()):
|
||||
raise NotADirectoryError("couldn't find the directory " + directory + " in current directory")
|
||||
write_dict["additional_directories"] = additional_directories
|
||||
|
||||
if isinstance(description, str) is False:
|
||||
raise TypeError("argument 'description' must be str, got " + type(description).__name__)
|
||||
write_dict["description"] = description
|
||||
|
||||
if isinstance(language_locales, (list, tuple)) is False:
|
||||
raise TypeError("argument 'language_locales' must be list or tuple, got " + type(language_locales).__name__)
|
||||
write_dict["language_locales"] = language_locales
|
||||
|
||||
if isinstance(language_dict, dict) is False:
|
||||
raise TypeError("argument 'language_success' must be dict, got " + type(language_dict).__name__)
|
||||
for key in language_dict.keys():
|
||||
tmp_string = ""
|
||||
for char in key:
|
||||
if char == " ":
|
||||
char = "_"
|
||||
if char.lower() not in "abcdefghijklmnopqrstuvwxyz_":
|
||||
raise ValueError("letter " + str(char) + " in " + str(key) + " must be in 'ABCDEFGHIJLMNOPQRSTUVWXYZabcdefghijklmopqrstuvwxyz_'")
|
||||
tmp_string = tmp_string + char
|
||||
language_dict[tmp_string] = language_dict.pop(key)
|
||||
write_dict["language_dict"] = language_dict
|
||||
|
||||
if isinstance(license, str) is False:
|
||||
raise TypeError("argument 'license' must be str, got " + type(license).__name__)
|
||||
write_dict["license"] = license
|
||||
|
||||
if isinstance(required_python3_packages, (list, tuple)) is False:
|
||||
raise TypeError("argument 'required_python3_packages' must be list or tuple, got " + type(required_python3_packages).__name__)
|
||||
write_dict["required_python3_packages"] = required_python3_packages
|
||||
|
||||
# ----- #
|
||||
|
||||
with open("plugin.aion", "w") as file:
|
||||
file.write("#type: " + type.lower() + "_plugin\n")
|
||||
for key, value in write_dict.items():
|
||||
file.write(key + " = " + str(value) + "\n")
|
||||
file.close()
|
||||
|
||||
|
||||
def _run_befater_plugin(type: str, fname: str, plugin_name: str, activate_phrase: str, speech_input: str) -> None:
|
||||
"""
|
||||
runs a plugin
|
||||
|
||||
:param type: (RUN_AFTER, RUN_BEFORE)
|
||||
type of the plugin
|
||||
syntax: <plugin type>
|
||||
example: RUN_AFTER
|
||||
:param fname: str
|
||||
file path of the plugin file
|
||||
syntax: <filename>
|
||||
example: "/home/pi/test.py"
|
||||
:param plugin_name: str
|
||||
name of the plugin
|
||||
syntax: <plugin name>
|
||||
example: "TestPlugin"
|
||||
:param activate_phrase: str
|
||||
activate phrase, which calls the skill class to which the plugin belongs
|
||||
syntax: <activate phrase>
|
||||
example: "Start test plugin"
|
||||
:param speech_input: str
|
||||
speech input, which calls the skill class to which the plugin belongs
|
||||
syntax: <speech input>
|
||||
example: "Start test plugin"
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
from sys import path
|
||||
path.insert(1, _aion_data_path + "/" + type.lower())
|
||||
exec("__import__('" + fname + "')." + plugin_name + "(" + activate_phrase + ", " + speech_input + ").main()")
|
374
aionlib/skill.py
Normal file
374
aionlib/skill.py
Normal file
@ -0,0 +1,374 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
from . import aion_data_path as _aion_data_path
|
||||
|
||||
|
||||
skills_path = _aion_data_path + "/skills"
|
||||
skills_file = skills_path + "/skills.xml"
|
||||
|
||||
|
||||
class Skill:
|
||||
"""
|
||||
base class for use custom skills
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
|
||||
def __init__(self, activate_phrase: str, speech_input: str, run_after_plugins: dict, run_before_plugins: dict) -> None:
|
||||
"""
|
||||
:param activate_phrase: str
|
||||
activate phrase that called this class
|
||||
syntax: "<activate phrase>"
|
||||
example: "test"
|
||||
:param speech_input: str
|
||||
complete spoken words
|
||||
syntax: "<speech input>"
|
||||
example: "Start the test"
|
||||
:param run_after_plugins: dict
|
||||
all run after plugins
|
||||
:param run_before_plugins: dict
|
||||
all run before plugins
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
self.activate_phrase = activate_phrase
|
||||
self.activate_phrase_list = activate_phrase.split("__and__")
|
||||
self.speech_input = speech_input
|
||||
|
||||
try:
|
||||
self.run_after_plugins = run_after_plugins[self.__class__.__name__]
|
||||
except KeyError:
|
||||
self.run_after_plugins = {}
|
||||
try:
|
||||
self.run_before_plugins = run_before_plugins[self.__class__.__name__]
|
||||
except KeyError:
|
||||
self.run_before_plugins = {}
|
||||
|
||||
def main(self) -> None:
|
||||
"""
|
||||
gets called if user says the defined activate_phrase
|
||||
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
pass
|
||||
|
||||
def run_after(self) -> None:
|
||||
"""
|
||||
gets called after the 'main' function was executed
|
||||
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
pass
|
||||
|
||||
def run_before(self) -> None:
|
||||
"""
|
||||
gets called before the 'main' function was executed
|
||||
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
pass
|
||||
|
||||
def start_run_after_plugin(self, plugin_name: str) -> None:
|
||||
"""
|
||||
calls a 'run_after' plugin (all plugins are in at the root of 'run_after_plugins' dict)
|
||||
|
||||
:param plugin_name: str
|
||||
name of the plugin that should called (all plugins are in at the root of 'run_after_plugins' dict)
|
||||
syntax: "<plugin name>"
|
||||
example: "ExampleClass
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
try:
|
||||
from .plugin import _run_befater_plugin, RUN_AFTER
|
||||
except ImportError:
|
||||
from plugin import _run_befater_plugin, RUN_AFTER
|
||||
|
||||
if plugin_name in self.run_after_plugins:
|
||||
_run_befater_plugin(RUN_AFTER, plugin_name, self.run_after_plugins[plugin_name]["method"], self.activate_phrase, self.speech_input)
|
||||
|
||||
def start_run_before_plugin(self, plugin_name: str) -> None:
|
||||
"""
|
||||
calls a 'run_before' plugin (all plugins are in at the root of 'run_before_plugins' dict)
|
||||
|
||||
:param plugin_name: str
|
||||
name of the plugin that should called (all plugins are in at the root of 'run_before_plugins' dict)
|
||||
syntax: <plugin name>
|
||||
example: "ExampleClass"
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
try:
|
||||
from .plugin import _run_befater_plugin, RUN_BEFORE
|
||||
except ImportError:
|
||||
from plugin import _run_befater_plugin, RUN_BEFORE
|
||||
|
||||
if plugin_name in self.run_before_plugins:
|
||||
_run_befater_plugin(RUN_BEFORE, plugin_name, self.run_before_plugins[plugin_name]["method"], self.activate_phrase, self.speech_input)
|
||||
|
||||
def speech_output(self, speech_output: str) -> None:
|
||||
"""
|
||||
plays a output of an artificial voice from the given words
|
||||
|
||||
:param speech_output: str
|
||||
the words to be said
|
||||
syntax: <speech output words>
|
||||
example: "This is an test"
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
try:
|
||||
from . import speech_output as _speech_output
|
||||
except ImportError:
|
||||
from .__init__ import speech_output as _speech_output
|
||||
|
||||
_speech_output(speech_output)
|
||||
|
||||
|
||||
def create_skill_file(activate_phrases: dict,
|
||||
author: str,
|
||||
language_locales: list,
|
||||
main_file: str,
|
||||
skill_name: str,
|
||||
version: str,
|
||||
additional_directories: list = [],
|
||||
description: str = "",
|
||||
language_dict: dict = {},
|
||||
license: str = "",
|
||||
required_python3_packages: list = []) -> None:
|
||||
"""
|
||||
creates a file from which a skill can be installed
|
||||
|
||||
:param activate_phrases: dict
|
||||
defines a word or a sentence from which a method is called
|
||||
syntax: {<activate phrase>: <method that should get called after the activate phrase was said>}
|
||||
example: {"start test": "MyTestMethod"}
|
||||
NOTE: in key 'activate_phrase' you can use the '__and__' statement. This checks if the words before and after '__and__' are in the sentence that the user has spoken in
|
||||
:param author: str
|
||||
name of the author from the skill
|
||||
syntax: <author name>
|
||||
example: "blueShard"
|
||||
:param language_locales: list
|
||||
list of language locales for which the skill is available
|
||||
syntax: [<language locale>]
|
||||
example: ["en_US"]
|
||||
:param main_file: str
|
||||
file name of file where all methods for the activate_phrases are defined
|
||||
syntax: <file name>
|
||||
example: "test.py"
|
||||
NOTE: the file must be in the same directory as the file from which 'create_skill_file' is being executed
|
||||
:param skill_name: str
|
||||
name of the skill you create
|
||||
syntax: <skill name>
|
||||
example: "text_skill"
|
||||
:param version: str
|
||||
version (number) of your skill
|
||||
syntax: <version>
|
||||
example: "1.0.0"
|
||||
|
||||
:param additional_directories: list, optional
|
||||
list of additional directories your main file needs for execution
|
||||
syntax: [<additional directories>]
|
||||
example: ["test_directory"]
|
||||
NOTE: the directories must be in the same directory as the file from which 'create_skill_file' is being executed
|
||||
:param description: str, optional
|
||||
description of your skill
|
||||
syntax: <description>
|
||||
example: "A simple skill to test the method 'create_skill_file'"
|
||||
:param language_dict: dict, optional
|
||||
dictionary of messages which are saved in (from argument 'language_locales' given) '.lng' files
|
||||
syntax: {<entry>, <text>}
|
||||
example: {"test_entry": "The test was successful"}
|
||||
NOTE: the method name should be included in the entry for legibility
|
||||
NOTE2: for more infos about language ('.lng') files, see file 'language.py'
|
||||
:param license: str, optional
|
||||
license of the skill
|
||||
syntax: <license>
|
||||
example: "MPL-2.0"
|
||||
:param required_python3_packages: list, optional
|
||||
list of python3 packages your package needs for correct execution
|
||||
syntax: [<python3 package>]
|
||||
example: ["aionlib"]
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
|
||||
from os import getcwd, listdir
|
||||
|
||||
write_dict = {}
|
||||
|
||||
if isinstance(author, str) is False:
|
||||
raise TypeError("argument 'author' must be str, got " + type(author).__name__)
|
||||
write_dict["author"] = author
|
||||
|
||||
if isinstance(language_locales, (list, tuple)) is False:
|
||||
raise TypeError("argument 'language_locales' must be list or tuple, got " + type(language_locales).__name__)
|
||||
write_dict["language_locales"] = language_locales
|
||||
|
||||
if isinstance(main_file, str) is False:
|
||||
raise TypeError("argument 'main_file' must be str, got " + type(author).__name__)
|
||||
if main_file not in listdir(getcwd()):
|
||||
raise FileNotFoundError("couldn't find the file " + main_file + " in current directory")
|
||||
if main_file[:-3] == skill_name is False:
|
||||
raise NameError("the file name from " + main_file + " must be same as the argument 'name' (" + skill_name + ")")
|
||||
if main_file not in listdir(getcwd()):
|
||||
raise FileNotFoundError("couldn't find the file '" + main_file + "' in current directory")
|
||||
write_dict["main_file"] = main_file
|
||||
|
||||
if isinstance(skill_name, str) is False:
|
||||
raise TypeError("argument 'skill_name' must be str, got " + type(skill_name).__name__)
|
||||
write_dict["pskill_name"] = skill_name
|
||||
|
||||
if isinstance(version, str) is False:
|
||||
raise TypeError("argument 'version' must be str, got " + type(version).__name__)
|
||||
write_dict["version"] = version
|
||||
|
||||
# ----- #
|
||||
|
||||
if isinstance(additional_directories, (list, tuple)) is False:
|
||||
raise TypeError("argument 'additional_directories' must be list or tuple, got " + type(additional_directories).__name__)
|
||||
for directory in additional_directories:
|
||||
if directory not in listdir(getcwd()):
|
||||
raise NotADirectoryError("couldn't find the directory " + directory + " in current directory")
|
||||
write_dict["additional_directories"] = additional_directories
|
||||
|
||||
if isinstance(description, str) is False:
|
||||
raise TypeError("argument 'description' must be str, got " + type(description).__name__)
|
||||
write_dict["description"] = description
|
||||
|
||||
if isinstance(language_dict, dict) is False:
|
||||
raise TypeError("argument 'language_success' must be dict, got " + type(language_dict).__name__)
|
||||
for key in language_dict.keys():
|
||||
tmp_string = ""
|
||||
for char in key:
|
||||
if char == " ":
|
||||
char = "_"
|
||||
if char.lower() not in "abcdefghijklmnopqrstuvwxyz_":
|
||||
raise ValueError("letter " + str(char) + " in " + str(key) + " must be in 'ABCDEFGHIJLMNOPQRSTUVWXYZabcdefghijklmopqrstuvwxyz_'")
|
||||
tmp_string = tmp_string + char
|
||||
language_dict[tmp_string] = language_dict.pop(key)
|
||||
write_dict["language_dict"] = language_dict
|
||||
|
||||
if isinstance(license, str) is False:
|
||||
raise TypeError("argument 'license' must be str, got " + type(license).__name__)
|
||||
write_dict["license"] = license
|
||||
|
||||
if isinstance(required_python3_packages, (list, tuple)) is False:
|
||||
raise TypeError("argument 'required_python3_packages' must be list or tuple, got " + type(required_python3_packages).__name__)
|
||||
write_dict["required_python3_packages"] = required_python3_packages
|
||||
|
||||
# ----- #
|
||||
|
||||
if isinstance(activate_phrases, dict) is False:
|
||||
raise TypeError("argument 'activate_phrases' must be dict, got " + type(activate_phrases).__name__)
|
||||
for item in activate_phrases:
|
||||
tmp_string = ""
|
||||
|
||||
for char in item:
|
||||
if char == " ":
|
||||
char = "_"
|
||||
if char.lower() not in "abcdefghijklmnopqrstuvwxyz-_":
|
||||
raise ValueError("letter " + str(char) + " in " + str(item) + " must be in 'ABCDEFGHIJLMNOPQRSTUVWXYZabcdefghijklmopqrstuvwxyz-_'")
|
||||
tmp_string = tmp_string + char
|
||||
activate_phrases[tmp_string] = activate_phrases.pop(item)
|
||||
write_dict["activate_phrases"] = activate_phrases
|
||||
|
||||
# ----- #
|
||||
|
||||
with open("skill.aion", "w") as file:
|
||||
file.write("#type: skill\n")
|
||||
for key, value in write_dict.items():
|
||||
file.write(key + " = " + str(value) + "\n")
|
||||
file.close()
|
||||
|
||||
|
||||
def get_all_skills() -> list:
|
||||
"""
|
||||
returns all installed skills
|
||||
|
||||
:return: list
|
||||
returns list of all installed skills
|
||||
syntax: [<skill>]
|
||||
example: ["skills"]
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
from . import is_aion
|
||||
from ._utils import no_aion, BaseXMLReader
|
||||
|
||||
if is_aion:
|
||||
return BaseXMLReader(skills_file).get_infos("<root>").items().index(0)[0]["childs"]
|
||||
else:
|
||||
no_aion()
|
||||
return []
|
||||
|
||||
|
||||
def get_skill_infos(skill_name: str) -> dict:
|
||||
"""
|
||||
returns infos about an given skill
|
||||
|
||||
:param skill_name: str
|
||||
name of the skill you want to get infos about
|
||||
syntax: <skill name>
|
||||
example: "test_skill"
|
||||
:return: dict
|
||||
returns a dictionary with infos of the skill
|
||||
syntax: {"activate_phrases": {<activate phrases>},
|
||||
"author": <author>,
|
||||
"language_locales": [<language locales>],
|
||||
"main_file": <main file>,
|
||||
"skill_name": <skill name>,
|
||||
"version": <version>,
|
||||
"additional_directories": [<additional directories>],
|
||||
"description": <description>,
|
||||
"language_dict": {<entry>: <text>}
|
||||
"license": <license>,
|
||||
"required_python3_packages": [<python3 packages>]}
|
||||
example: {"activate_phrases": {"start test": "test_method_start"}},
|
||||
"author": "blueShard",
|
||||
"language_locales": ["en_US"],
|
||||
"main_file": "test.py",
|
||||
"skill_name": "text_skill",
|
||||
"version": "1.0.0",
|
||||
"additional_directories": ["test_directory"],
|
||||
"description": "A simple skill to test the function 'get_skill_infos",
|
||||
"language_dict": {"test_func": "The test was successful"},
|
||||
"license": "MPL-2.0",
|
||||
"required_python3_packages": ["aionlib"]}
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
from . import is_aion
|
||||
from ._utils import no_aion, BaseXMLReader
|
||||
|
||||
if is_aion:
|
||||
from ast import literal_eval
|
||||
skill_reader = BaseXMLReader(skills_file)
|
||||
return_dict = {"skill_name": skill_name}
|
||||
for value_list in skill_reader.get_infos("<all>").values():
|
||||
for skill in value_list:
|
||||
try:
|
||||
if skill["parent"]["tag"] == skill_name:
|
||||
try:
|
||||
return_dict[skill["tag"]] = literal_eval(skill["text"])
|
||||
except (EOFError, SyntaxError, ValueError):
|
||||
return_dict[skill["tag"]] = skill["text"]
|
||||
except KeyError:
|
||||
pass
|
||||
return return_dict
|
||||
|
||||
else:
|
||||
no_aion()
|
||||
return {}
|
550
aionlib/utils.py
Normal file
550
aionlib/utils.py
Normal file
@ -0,0 +1,550 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
|
||||
def download_youtube_audio(url: str, path: str, output_format: str = "mp3") -> None:
|
||||
"""
|
||||
downloads youtube audio by url
|
||||
|
||||
:param url: str
|
||||
the url from which the audio should be downloaded
|
||||
syntax: <url>
|
||||
example: "https://youtu.be/MAlSjtxy5ak"
|
||||
:param path: str
|
||||
the path where the downloaded audio should be saved
|
||||
syntax: <path>
|
||||
example: "/home/pi/{title}"
|
||||
NOTE: in your path you can use the following things:
|
||||
"author" channel name of the creator
|
||||
"category" category of the video
|
||||
"dislikes" number of dislikes on the video
|
||||
"duration" duration time of the video (HH:MM:SS)
|
||||
"likes" number of likes on the video
|
||||
"title" title of the video
|
||||
"views" number of views on the video
|
||||
:param output_format: str, optional
|
||||
output format of the audio
|
||||
syntax: <output format>
|
||||
example: "mp3"
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
from . import is_aion
|
||||
from ._utils import no_aion
|
||||
if is_aion:
|
||||
from os import system
|
||||
from os.path import isdir, isfile
|
||||
from pafy import new
|
||||
from urllib.request import urlopen
|
||||
|
||||
source = new(url)
|
||||
|
||||
source_url = source.getbestaudio().url
|
||||
source_extension = source.getbestaudio().extension
|
||||
|
||||
if isfile(path + "." + source_extension):
|
||||
raise FileExistsError(path + " must be an non existing file")
|
||||
elif isdir(path):
|
||||
raise IsADirectoryError("path must be path to file, not path to directory")
|
||||
|
||||
path = path.format({"author": source.author, "category": source.category, "dislikes": source.dislikes, "duration": source.duration, "likes": source.likes, "title": source.title, "views": source.viewcount})
|
||||
with open(path + "." + source_extension, "wb") as file:
|
||||
file.write(bytes(urlopen(source_url).read()))
|
||||
file.close()
|
||||
|
||||
system("ffmpeg -i " + path + "." + source_extension + " " + path + "." + output_format)
|
||||
else:
|
||||
no_aion()
|
||||
|
||||
|
||||
def download_youtube_video(url: str, path: str, output_format: str = "mp4") -> None:
|
||||
"""
|
||||
downloads youtube video by url
|
||||
|
||||
:param url: str
|
||||
the url from which the video should be downloaded
|
||||
syntax: <url>
|
||||
example: "https://youtu.be/MAlSjtxy5ak"
|
||||
:param path: str
|
||||
the path where the downloaded video should be saved
|
||||
syntax: <path>
|
||||
example: "/home/pi/{title}"
|
||||
NOTE: in your path you can use the following things:
|
||||
"author" channel name of the creator
|
||||
"category" category of the video
|
||||
"dislikes" number of dislikes on the video
|
||||
"duration" duration time of the video (HH:MM:SS)
|
||||
"likes" number of likes on the video
|
||||
"title" title of the video
|
||||
"views" number of views on the video
|
||||
:param output_format: str, optional
|
||||
output format of the video
|
||||
syntax: <output format>
|
||||
example: "mp4"
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
from . import is_aion
|
||||
from ._utils import no_aion
|
||||
if is_aion:
|
||||
from os import system
|
||||
from os.path import isdir, isfile
|
||||
from pafy import new
|
||||
from urllib.request import urlopen
|
||||
|
||||
source = new(url)
|
||||
|
||||
source_url = source.getbestvideo().url
|
||||
source_extension = source.getbestvideo().extension
|
||||
|
||||
if isfile(path + "." + source_extension):
|
||||
raise FileExistsError(path + " must be an not existing file")
|
||||
elif isdir(path):
|
||||
raise IsADirectoryError("path must be path to file, not path to directory")
|
||||
|
||||
path = path.format({"author": source.author, "category": source.category, "dislikes": source.dislikes, "duration": source.duration, "likes": source.likes, "title": source.title, "views": source.viewcount})
|
||||
with open(path + "." + source_extension, "wb") as file:
|
||||
file.write(bytes(urlopen(source_url).read()))
|
||||
file.close()
|
||||
|
||||
system("ffmpeg -i " + path + "." + source_extension + " " + path + "." + output_format)
|
||||
else:
|
||||
no_aion()
|
||||
|
||||
|
||||
def get_full_directory_data(directory: str) -> list:
|
||||
"""
|
||||
returns list of all files and directories of given directory back (subdirectories with subfiles, subsubdirectories with subsubfiles, ... included)
|
||||
|
||||
:param directory: str
|
||||
path of directory from which you want to get the data
|
||||
syntax: <directory path>
|
||||
example: "/home/pi"
|
||||
|
||||
:return: list
|
||||
list of all files and directories (subdirectories with subfiles, subsubdirectories with subsubfiles, ... included)
|
||||
syntax: [<path>]
|
||||
example: ["/home/pi/test", "/home/pi/test/test.py"]
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
from os import walk
|
||||
from os.path import join
|
||||
|
||||
data = []
|
||||
for path, subdirs, files in walk(directory):
|
||||
for name in files:
|
||||
data.append(join(path, name))
|
||||
return data
|
||||
|
||||
|
||||
def get_full_youtube_audio_url(search_element: str) -> str:
|
||||
"""
|
||||
search youtube for the search element and gives the first youtube url back
|
||||
|
||||
:param search_element: str
|
||||
the element you want to search
|
||||
syntax: <search element>
|
||||
example: "Every programming tutorial"
|
||||
:return: str
|
||||
the youtube url from the search element
|
||||
syntax: <url>
|
||||
example: "https://youtu.be/MAlSjtxy5ak"
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
import urllib.parse, urllib.request
|
||||
from pafy import new
|
||||
from re import findall
|
||||
search_query = urllib.parse.urlencode({"search_query": search_element})
|
||||
for i in range(10): # sometimes the video url's cannot be found
|
||||
try:
|
||||
html_content = urllib.request.urlopen("https://www.youtube.com/results?" + search_query)
|
||||
search_results = findall(r'href=\"\/watch\?v=(.{11})', html_content.read().decode())
|
||||
return new(str("https://www.youtube.com/watch?v=" + search_results[0])).getbestaudio().url
|
||||
except IndexError:
|
||||
pass
|
||||
|
||||
|
||||
def get_full_youtube_video_url(search_element: str) -> str:
|
||||
"""
|
||||
search youtube for the search element and gives the first youtube url back
|
||||
|
||||
:param search_element: str
|
||||
the element you want to search
|
||||
syntax: <search element>
|
||||
example: "Every programming tutorial"
|
||||
:return: str
|
||||
the youtube url from the search element
|
||||
syntax: <url>
|
||||
example: "https://youtu.be/MAlSjtxy5ak"
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
import urllib.parse, urllib.request
|
||||
from pafy import new
|
||||
from re import findall
|
||||
search_query = urllib.parse.urlencode({"search_query": search_element})
|
||||
for i in range(10): # sometimes the video url's cannot be found
|
||||
try:
|
||||
html_content = urllib.request.urlopen("https://www.youtube.com/results?" + search_query)
|
||||
search_results = findall(r'href=\"\/watch\?v=(.{11})', html_content.read().decode())
|
||||
return new(str("https://www.youtube.com/watch?v=" + search_results[0])).getbestvideo().url
|
||||
except IndexError:
|
||||
pass
|
||||
|
||||
|
||||
def get_line_number(fname: str, search_element: str, full_line: bool = True, strip: bool = True) -> int:
|
||||
"""
|
||||
returns the line number of an element in a file
|
||||
|
||||
:param fname: str
|
||||
name of the file you want to search for the element
|
||||
syntax: <file name>
|
||||
example: "test_file"
|
||||
:param search_element: str
|
||||
element you want to get the line number of
|
||||
syntax: <search element>
|
||||
example: "test_search_element"
|
||||
:param full_line: bool
|
||||
sets if the 'search_element' should be the FULL line (True) or if the 'search_element' should be IN the line (False)
|
||||
syntax: <boolean>
|
||||
example: False
|
||||
:param strip: bool
|
||||
sets if the line of the should be striped before search the 'search_element' in it
|
||||
syntax: <boolean>
|
||||
example: False
|
||||
:return: int
|
||||
returns the line number of the 'search_element'
|
||||
syntax: <line number>
|
||||
example: 69
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
from os.path import isfile
|
||||
if isfile(fname) is False:
|
||||
raise FileNotFoundError(fname + " don't exist")
|
||||
line_number = -1
|
||||
if full_line and strip:
|
||||
for line in open(fname):
|
||||
line_number = line_number + 1
|
||||
if line.strip() == search_element:
|
||||
return line_number
|
||||
elif full_line and strip is False:
|
||||
for line in open(fname):
|
||||
line_number = line_number + 1
|
||||
if line == search_element:
|
||||
return line_number
|
||||
elif full_line is False and strip:
|
||||
for line in open(fname):
|
||||
line_number = line_number + 1
|
||||
if search_element in line.strip():
|
||||
return line_number
|
||||
else:
|
||||
for line in open(fname):
|
||||
line_number = line_number + 1
|
||||
if search_element in line:
|
||||
return line_number
|
||||
|
||||
raise EOFError("couldn't get line number of " + search_element)
|
||||
|
||||
|
||||
def get_youtube_url(search_element: str) -> str:
|
||||
"""
|
||||
search youtube for the search element and gives the first youtube url back
|
||||
|
||||
:param search_element: str
|
||||
the element you want to search
|
||||
syntax: <search element>
|
||||
example: "Every programming tutorial"
|
||||
:return: str
|
||||
the youtube url from the search element
|
||||
syntax: <url>
|
||||
example: "https://youtu.be/MAlSjtxy5ak"
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
import re, urllib.parse, urllib.request
|
||||
search_query = urllib.parse.urlencode({"search_query": search_element})
|
||||
html_content = urllib.request.urlopen("https://www.youtube.com/results?search_query=" + search_query)
|
||||
search_results = re.findall(r'href=\"\/watch\?v=(.{11})', html_content.read().decode())
|
||||
return str("https://www.youtube.com/watch?v=" + search_results[0])
|
||||
|
||||
|
||||
def is_dict_in_dict(dict1: dict, dict2: dict) -> bool:
|
||||
"""
|
||||
checks if dict key-value pairs exist in another dict
|
||||
|
||||
:param dict1: dict
|
||||
dictionary you want to check if it is included in another dictionary
|
||||
syntax: {"key": "value"}
|
||||
example: {"a": "b"}
|
||||
:param dict2: dict
|
||||
dictionary you want to see if there is another dictionary in it
|
||||
syntax: {"key": "value"}
|
||||
example: {"a": "b", "c": "d"}
|
||||
:return: boolean
|
||||
returns if 'dict1' is in 'dict2'
|
||||
syntax: <boolean>
|
||||
example: True
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
for key, value in dict1.items():
|
||||
if key in dict2:
|
||||
if dict2[key] == value:
|
||||
pass
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def is_element_in_file(fname: str, element: str) -> bool:
|
||||
"""
|
||||
checks if an element is in a file
|
||||
|
||||
:param fname: str
|
||||
file name of file
|
||||
syntax: <file name>
|
||||
example: "/home/pi/test.py"
|
||||
:param element: str
|
||||
element you want to check if in file
|
||||
syntax: <element>
|
||||
example: "test"
|
||||
:return: bool
|
||||
returns True or False is element is in file
|
||||
syntax: <boolean>
|
||||
example: True
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
is_in_file = False
|
||||
for line in open(fname, "r"):
|
||||
if element in line:
|
||||
is_in_file = True
|
||||
break
|
||||
return is_in_file
|
||||
|
||||
|
||||
def is_internet_connected() -> bool:
|
||||
"""
|
||||
checks if the internet is connected
|
||||
|
||||
:return: bool
|
||||
returns True or False if internet is connected
|
||||
syntax: <boolean>
|
||||
example: True
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
import socket
|
||||
try:
|
||||
socket.gethostbyname("google.com")
|
||||
internet = True
|
||||
except OSError:
|
||||
internet = False
|
||||
except:
|
||||
internet = False
|
||||
print("An unexpected error appeard")
|
||||
return internet
|
||||
|
||||
|
||||
def is_root() -> bool:
|
||||
"""
|
||||
checks if the function from which this function is called run as root
|
||||
|
||||
:return: bool
|
||||
returns True or False if the function from which this function is called run as root
|
||||
syntax: <boolean>
|
||||
example: True
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
from os import geteuid
|
||||
if geteuid() == 0:
|
||||
return True
|
||||
elif geteuid() == 1000:
|
||||
return False
|
||||
|
||||
|
||||
def remove_brackets(string: str) -> str:
|
||||
"""
|
||||
removes all brackets and the text which is between the brackets
|
||||
|
||||
:param string: str
|
||||
string from which you want to remove the brackets
|
||||
syntax: <string>
|
||||
example: "Hello, this is(wedcwerfwe) an [sdvsfvv] random text{ervweg}"
|
||||
:return: str
|
||||
string without brackets and the text between them
|
||||
syntax: <string without brackets>
|
||||
example: "Hello, this is an random text"
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
finished_string = ""
|
||||
square_brackets = 0
|
||||
parentheses = 0
|
||||
for brackets in string:
|
||||
if brackets == "[":
|
||||
square_brackets += 1
|
||||
elif brackets == "(":
|
||||
parentheses += 1
|
||||
elif brackets == "]" and square_brackets > 0:
|
||||
square_brackets -= 1
|
||||
elif brackets == ")" and parentheses > 0:
|
||||
parentheses -= 1
|
||||
elif square_brackets == 0 and parentheses == 0:
|
||||
finished_string += brackets
|
||||
return finished_string
|
||||
|
||||
|
||||
def remove_space(string: str, space: str = " ") -> str:
|
||||
"""
|
||||
removes all the space from string which is equal or higher than from argument 'space' given space
|
||||
|
||||
:param string: str
|
||||
string from which you want to remove space
|
||||
syntax: <string>
|
||||
example: "This string has to much space"
|
||||
:param space: str, optional
|
||||
space size from which you want to start to remove
|
||||
syntax: <space>
|
||||
example: " "
|
||||
NOTE: '" "' will be replaced with '" "'
|
||||
:return: str
|
||||
returns the string without the given space and higher
|
||||
syntax: <string>
|
||||
example: "This string has to much space"
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
while True:
|
||||
if space in string:
|
||||
string = string.replace(space, "")
|
||||
space = space + " "
|
||||
if len(space) >= len(string):
|
||||
break
|
||||
|
||||
string = string.strip()
|
||||
return string
|
||||
|
||||
|
||||
def remove_string_characters(string: str, characters_to_remove: (list, tuple)) -> str:
|
||||
"""
|
||||
removes in argument 'characters_to_remove' given characters from given string
|
||||
|
||||
:param string: str
|
||||
string from which you want to remove the characters
|
||||
syntax: <string>
|
||||
example: "This string hello has its to much word me"
|
||||
:param characters_to_remove: list
|
||||
list of characters you want to remove from string
|
||||
syntax: [<character>]
|
||||
example: ["hello", "its", "me"]
|
||||
:return: str
|
||||
returns string without in given characters to remove
|
||||
syntax: <string>
|
||||
example: "This string has to much word"
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
for char in characters_to_remove:
|
||||
if char in string:
|
||||
string = string.replace(char, "")
|
||||
return string
|
||||
|
||||
|
||||
def remove_string_sequence(string: str, start: str, end: str, include: bool = False) -> str:
|
||||
"""
|
||||
removes all characters from a string between the given 'start' and 'end' element
|
||||
|
||||
:param string: str
|
||||
the string from which the sequence should be removed from
|
||||
syntax: "<string>"
|
||||
example: "Test lol random words string"
|
||||
:param start: str
|
||||
start character
|
||||
syntax: "<start character>"
|
||||
example: "lol"
|
||||
:param end: str
|
||||
end character
|
||||
syntax: "<end character>"
|
||||
example: "words"
|
||||
:param include: bool
|
||||
'True' if the given start and end character should be included in the return string, False if not
|
||||
syntax: <boolean>
|
||||
example: False
|
||||
:return: str
|
||||
string without the sequence between 'start' and 'end'
|
||||
syntax: "<string>"
|
||||
example: "Test string"
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
if include:
|
||||
return string.replace(string[string.find(start) - len(start):string.find(end)], "")
|
||||
return string.replace(string[string.find(start):string.find(end) + len(end)], "")
|
||||
|
||||
|
||||
def replace_line(fname: str, line_number: int, new_line: str) -> None:
|
||||
"""
|
||||
replaces a line in a file
|
||||
|
||||
:param fname: str
|
||||
filename from which you want to replace the line
|
||||
syntax: <filename>
|
||||
example: "/home/pi/test.txt"
|
||||
:param line_number: int
|
||||
line number of line you want to replace
|
||||
syntax: <line number>
|
||||
example: 5
|
||||
:param new_line: str
|
||||
line content with which the line should be replaced
|
||||
syntax: <new line>
|
||||
example: "This is the new line"
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
from os.path import isfile
|
||||
|
||||
line_number = int(line_number)
|
||||
if isfile(fname) is False:
|
||||
raise FileNotFoundError(fname + " don't exist")
|
||||
lines = open(fname).readlines()
|
||||
lines[line_number] = new_line + "\n"
|
||||
with open(fname, "w") as file:
|
||||
file.writelines(lines)
|
||||
file.close()
|
||||
|
||||
|
||||
def vlc(url_or_file_path: str, video: bool = False) -> None:
|
||||
"""
|
||||
plays audio from url or file path
|
||||
|
||||
:param url_or_file_path: str
|
||||
the url or the path of the file you want to play
|
||||
syntax: <url or path>
|
||||
example: "https://youtu.be/MAlSjtxy5ak"
|
||||
:param video: bool, optional
|
||||
sets True or False if video should be played (if the file had one)
|
||||
syntax: <boolean>
|
||||
example: False
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
from os import system
|
||||
|
||||
if isinstance(video, bool) is False:
|
||||
raise TypeError("expected " + str(bool.__name__) + " for video, got " + str(type(video).__name__))
|
||||
if video is True:
|
||||
system("cvlc --play-and-exit " + url_or_file_path)
|
||||
else:
|
||||
system("cvlc --play-and-exit --no-video " + url_or_file_path)
|
195
aionlib/variable.py
Normal file
195
aionlib/variable.py
Normal file
@ -0,0 +1,195 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
from . import is_linux
|
||||
|
||||
|
||||
_aion_variable_file = "/tmp/aion39ewefv90erfte25"
|
||||
|
||||
_default_variables = {"IS_AION_RUNNING": False}
|
||||
|
||||
IS_AION_RUNNING = "IS_AION_RUNNING"
|
||||
|
||||
|
||||
class Variable:
|
||||
"""
|
||||
base class for aion variables
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
"""
|
||||
set all class variables
|
||||
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
from . import is_linux
|
||||
from os.path import isfile as _isfile
|
||||
|
||||
self._user_variables = {}
|
||||
|
||||
if _isfile(_aion_variable_file) and is_linux is False:
|
||||
self._aion_open_variable_file = open(_aion_variable_file, "rw")
|
||||
else:
|
||||
self._aion_open_variable_file = None
|
||||
|
||||
def add_variable(self, variable_name, value):
|
||||
"""
|
||||
adds a variable
|
||||
|
||||
:param variable_name: str
|
||||
name of the variable you want to add
|
||||
syntax: <variable name>
|
||||
example: "test_variable"
|
||||
:param value: str
|
||||
value of the variable
|
||||
syntax: <value>
|
||||
example: "test_value"
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
if self._aion_open_variable_file is not None:
|
||||
file = open(_aion_variable_file, "a")
|
||||
file.write(variable_name + "=" + value)
|
||||
self._aion_open_variable_file = open(_aion_variable_file, "rw")
|
||||
self._user_variables[variable_name] = value
|
||||
|
||||
def close(self):
|
||||
"""
|
||||
remove the file with the saved variables
|
||||
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
from os import remove
|
||||
|
||||
if self._aion_open_variable_file is not None:
|
||||
remove(_aion_variable_file)
|
||||
self._aion_open_variable_file = None
|
||||
|
||||
def get_value(self, variable_name):
|
||||
"""
|
||||
get the value of an variable
|
||||
|
||||
:param variable_name: str
|
||||
name of the variable you want to get the value
|
||||
syntax: <variable name>
|
||||
example: "test_variable"
|
||||
:return: str
|
||||
return the value of the variable
|
||||
syntax: <value>
|
||||
example: <text_variable_value>
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
if self._aion_open_variable_file is not None:
|
||||
for value in self._aion_open_variable_file:
|
||||
if value.strip().startswith("#"):
|
||||
continue
|
||||
elif value.split("=")[0].strip() == variable_name:
|
||||
return value.split("=")[1].strip()
|
||||
raise KeyError("the variable " + variable_name + " doesn't exists")
|
||||
else:
|
||||
try:
|
||||
return _default_variables[variable_name]
|
||||
except KeyError:
|
||||
if variable_name in self._user_variables:
|
||||
return self._user_variables[variable_name]
|
||||
raise KeyError("the variable " + variable_name + " doesn't exists")
|
||||
|
||||
def inititalize_variables(self, additional_variables={}):
|
||||
"""
|
||||
creates a new file for the variables to store
|
||||
|
||||
:param additional_variables: dict, optional
|
||||
variables that should be added ('add_variable' could be used instead)
|
||||
syntax: {"key": "value"}
|
||||
example: {"test": "True"}
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
if is_linux:
|
||||
self._aion_open_variable_file = open(_aion_variable_file, "w+")
|
||||
write_list = [variable + "=" + str(value) for variable, value in _default_variables.items()]
|
||||
write_list = write_list + [str(additional_variable) + "=" + str(additional_value) for additional_variable, additional_value in additional_variables.items()]
|
||||
write_list = write_list + [str(user_variable) + "=" + str(user_value) for user_variable, user_value in self._user_variables]
|
||||
self._aion_open_variable_file.writelines(write_list)
|
||||
self._aion_open_variable_file = open(_aion_variable_file, "w+")
|
||||
|
||||
def remove_variable(self, variable_name):
|
||||
"""
|
||||
removes a variable
|
||||
|
||||
:param variable_name: str
|
||||
name of the variable
|
||||
syntax: <variable name>
|
||||
example: "test_variable"
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
try:
|
||||
from .utils import remove_space, replace_line
|
||||
except ImportError:
|
||||
from utils import remove_space, replace_line
|
||||
|
||||
found = False
|
||||
|
||||
if variable_name in self._user_variables:
|
||||
del self._user_variables[variable_name]
|
||||
found = True
|
||||
|
||||
if self._aion_open_variable_file is not None:
|
||||
line_number = -1
|
||||
for line in self._aion_open_variable_file:
|
||||
line_number = line_number + 1
|
||||
if remove_space(line, "").split("=")[0] == variable_name:
|
||||
replace_line(_aion_variable_file, line_number, "")
|
||||
self._aion_open_variable_file = open(_aion_variable_file, "rw")
|
||||
return
|
||||
|
||||
if found is False:
|
||||
raise KeyError("the variable " + variable_name + " doesn't exists")
|
||||
|
||||
def set_value(self, variable_name, value):
|
||||
"""
|
||||
set a new value to a variable
|
||||
|
||||
:param variable_name: str
|
||||
name of the variable you want to change the value
|
||||
syntax: <variable name>
|
||||
example: "test_variable"
|
||||
:param value: str
|
||||
new value
|
||||
syntax: <new value>
|
||||
example: "new_test_value"
|
||||
:return: None
|
||||
|
||||
:since: 0.1.0
|
||||
"""
|
||||
try:
|
||||
from .utils import remove_space, replace_line
|
||||
except ImportError:
|
||||
from utils import remove_space, replace_line
|
||||
|
||||
found = False
|
||||
|
||||
if variable_name in self._user_variables:
|
||||
self._user_variables[variable_name] = value
|
||||
found = True
|
||||
|
||||
line_number = -1
|
||||
for line in self._aion_open_variable_file:
|
||||
line_number = line_number + 1
|
||||
if remove_space(line, "").split("=")[0] == variable_name:
|
||||
replace_line(_aion_variable_file, line_number, variable_name + "=" + value)
|
||||
self._aion_open_variable_file = open(_aion_variable_file, "rw")
|
||||
return
|
||||
|
||||
if found is False:
|
||||
raise KeyError("the variable " + variable_name + " doesn't exists")
|
21
setup.py
Normal file
21
setup.py
Normal file
@ -0,0 +1,21 @@
|
||||
from setuptools import find_packages, setup
|
||||
|
||||
|
||||
setup(name="aionlib",
|
||||
version="0.1.0",
|
||||
author="blueShard",
|
||||
description="Library support for the 'aion' project",
|
||||
license="MPL-2.0",
|
||||
classifiers=[
|
||||
"Development Status :: 4 - Beta",
|
||||
"Environment :: Console",
|
||||
"License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)",
|
||||
"Operating System :: Unix",
|
||||
"Programming Language :: Python :: 3.6",
|
||||
"Programming Language :: Python :: 3.7",
|
||||
"Programming Language :: Python :: 3.8",
|
||||
"Programming Language :: Python :: 3.9",
|
||||
"Topic :: Home Automation"],
|
||||
python_requires=">=3.6.*",
|
||||
install_requires=["colorama"],
|
||||
packages=find_packages())
|
Loading…
x
Reference in New Issue
Block a user