394 lines
16 KiB
Python
394 lines
16 KiB
Python
#!/usr/bin/env python
|
|
# -*- coding: utf-8 -*-
|
|
|
|
from re import compile as RECompile
|
|
from json import loads as json_decode
|
|
|
|
if "MemWeb" not in globals():
|
|
class MemWeb:pass
|
|
|
|
class Anonymous(MemWeb.Abstracts.Common):
|
|
|
|
re_key = RECompile(r'^[a-z0-9_]+$')
|
|
re_command = RECompile(r'^([^ ]+)(.+)?$')
|
|
re_parameters = RECompile(r' +(\-{1,2})?("(([^\\"]+|\\")*)"|\'(([^\\\']+|\\\')*)\'|([^= ]+))( *=( *("(([^\\"]+|\\")*)"|\'(([^\\\']+|\\\')*)\'|([^ ]+)))?)?')
|
|
|
|
def __set_basic_data(self):
|
|
self.__default_overwrite = self.settings(("commands_overwrite", "overwrite"))
|
|
self.__show_add_ok = self.settings(("terminal_show_add_ok_message", "show_ok_message"))
|
|
self.__show_add_error = self.settings(("terminal_show_add_error_message", "show_error_message"))
|
|
self.__show_add_exception = self.settings(("terminal_show_add_exception_message", "show_exception_message"))
|
|
|
|
def __init__(self, mem_web, inputs = None):
|
|
super().__init__(mem_web, "terminal")
|
|
|
|
self._print("info", "mem_web_terminal_building")
|
|
|
|
self.__commands = []
|
|
self.__thread = None
|
|
|
|
self.__set_basic_data()
|
|
|
|
self._print("ok", "mem_web_terminal_built")
|
|
|
|
def _start(self, end):
|
|
if self.__started:return
|
|
|
|
self.__set_basic_data()
|
|
for key in ("default_commands_files", "commands_files", "commands"):
|
|
self.add(self.settings(key), True)
|
|
|
|
help_command = self.get_command("help")
|
|
|
|
if help_command:
|
|
help_command["synonyms"] += ["?"]
|
|
|
|
(self.__thread, error) = self.mem_web.threads.add(self.__execute, {
|
|
"bucle" : True,
|
|
"start_now" : True,
|
|
"key" : "terminal"
|
|
})
|
|
|
|
end(0)
|
|
|
|
def _close(self, end):
|
|
if not self.__started:return
|
|
|
|
self.mem_web.threads.remove(self.__thread)
|
|
|
|
end(0)
|
|
|
|
def __execute(self, thread):
|
|
|
|
(key, inputs) = self.re_command.match(input()).groups()
|
|
|
|
for command in self.__commands:
|
|
if key in command["synonyms"]:
|
|
|
|
parameters = []
|
|
attributes = {}
|
|
special = []
|
|
|
|
if inputs:
|
|
|
|
def callback(matches):
|
|
|
|
_type = len(matches.group(1) or "")
|
|
base = matches.group(3) or matches.group(5) or matches.group(7)
|
|
value = matches.group(11) or matches.group(13) or matches.group(15)
|
|
|
|
if _type:
|
|
special.append((_type, base, value))
|
|
if value != None:
|
|
attributes[base] = value
|
|
else:
|
|
parameters.append(base)
|
|
|
|
self.re_parameters.sub(callback, inputs)
|
|
|
|
if len(special):
|
|
for _type, name, parameter in special:
|
|
|
|
ok = False
|
|
|
|
for subcommand in self.__commands:
|
|
if subcommand["special"] and name in subcommand["synonyms"]:
|
|
subcommand["special"](key, command, _type, name, parameter)
|
|
ok = True
|
|
break
|
|
|
|
not ok and self._print("warn", "mem_web_terminal_special_unknown", {
|
|
"type" : _type,
|
|
"name" : name,
|
|
"parameter" : parameter,
|
|
"key" : key,
|
|
"real_key" : command["synonyms"][0]
|
|
})
|
|
|
|
else:
|
|
command["method"](parameters, attributes)
|
|
return
|
|
|
|
self._print("warn", "mem_web_terminal_command_unknown", {
|
|
"key" : key
|
|
})
|
|
|
|
def key_exists(self, key):
|
|
|
|
key = key.lower()
|
|
|
|
for i, command in enumerate(self.__commands):
|
|
if key in command["synonyms"]:
|
|
return i
|
|
return None
|
|
|
|
def __get_method(self, data, key):
|
|
if key not in data:
|
|
return None
|
|
|
|
method = globals()
|
|
|
|
if "root" in data:
|
|
method = data["root"]
|
|
elif data[key][0] == "mem_web":
|
|
method = self.mem_web
|
|
data[key] = data[key][1:]
|
|
|
|
for i, key in enumerate(data[key]):
|
|
try:
|
|
if not i and isinstance(method, dict):
|
|
if key in method:
|
|
method = method[key]
|
|
continue
|
|
elif hasattr(method, key):
|
|
method = getattr(method, key)
|
|
continue
|
|
except:
|
|
pass
|
|
method = None
|
|
break
|
|
|
|
return method
|
|
|
|
def add(self, inputs, overwrite = None, show_errors = None):
|
|
if isinstance(inputs, (list, tuple)):
|
|
for subset in inputs:
|
|
self.add(subset, overwrite, show_errors)
|
|
elif isinstance(inputs, dict):
|
|
|
|
has_show_errors = isinstance(show_errors, bool)
|
|
|
|
if not isinstance(overwrite, bool):
|
|
overwrite = self.__default_overwrite
|
|
|
|
for key, data in inputs.items():
|
|
|
|
error = (
|
|
((
|
|
1 << 0 if key == None else
|
|
1 << 1 if not isinstance(key, str) else
|
|
1 << 2 if not key else
|
|
0) << 0) |
|
|
((
|
|
1 << 0 if data == None else
|
|
1 << 1 if not isinstance(data, dict) else
|
|
(
|
|
((
|
|
0 if "synonyms" not in data else
|
|
1 << 1 if data["synonyms"] == None else
|
|
1 << 2 if not isinstance(data["synonyms"], (str, list, tuple)) else
|
|
0) << 0) |
|
|
((
|
|
1 << 0 if "method" not in data else
|
|
1 << 1 if data["method"] == None else
|
|
1 << 2 if not isinstance(data["method"], (str, list, tuple)) else
|
|
0) << 3) |
|
|
((
|
|
0 if "root" not in data else
|
|
1 << 1 if data["root"] == None else
|
|
1 << 2 if MemWeb.is_object(data["root"]) or MemWeb.is_class(data["root"]) else
|
|
0) << 6) |
|
|
((
|
|
0 if "parameters" not in data else
|
|
1 << 1 if data["parameters"] == None else
|
|
1 << 2 if not isinstance(data["parameters"], (str, list, tuple)) else
|
|
0) << 9) |
|
|
((
|
|
0 if "special" not in data else
|
|
1 << 1 if data["special"] == None else
|
|
1 << 2 if not isinstance(data["special"], (str, list, tuple)) else
|
|
0) << 12) |
|
|
0) << 2) << 3) |
|
|
0) << 1
|
|
|
|
if not error:
|
|
|
|
key_i = self.key_exists(key)
|
|
|
|
if "synonyms" not in data:
|
|
data["synonyms"] = []
|
|
elif isinstance(data["synonyms"], str):
|
|
data["synonyms"] = (data["synonyms"],)
|
|
elif isinstance(data["synonyms"], tuple):
|
|
data["synonyms"] = list(data["synonyms"])
|
|
data["synonyms"] = [subkey.lower() for subkey in [key] + data["synonyms"]]
|
|
|
|
for subkey in ("method", "special"):
|
|
if subkey in data and isinstance(data[subkey], str):
|
|
data[subkey] = data[subkey].split(".")
|
|
|
|
data["parameters"] = [subkey.lower() for subkey in (
|
|
tuple() if "parameters" not in data else
|
|
(data["parameters"],) if isinstance(data["parameters"], str) else
|
|
data["parameters"])]
|
|
|
|
if not overwrite and key_i != None:
|
|
error |= 1 << 21
|
|
for i, subkey in enumerate(("synonyms", "method", "special", "parameters")):
|
|
if subkey in data:
|
|
error |= (MemWeb.reduce([(
|
|
1 << 0 if key == None else
|
|
1 << 1 if not isinstance(key, str) else
|
|
1 << 2 if not key else
|
|
1 << 3 if not self.re_key.match(key) else
|
|
0) for key in data[subkey]], lambda a, b, *_: a | b, 0)[0]) << (22 + i * 4)
|
|
|
|
if not error:
|
|
|
|
for i, subkey in enumerate(("method", "special")):
|
|
if subkey in data:
|
|
|
|
processed_key = subkey + "_processed"
|
|
data[processed_key] = self.__get_method(data, subkey)
|
|
|
|
error |= (
|
|
(0 if i else 1 << 0) if data[processed_key] == None else
|
|
1 << 1 if not callable(data[processed_key]) else
|
|
0) << (38 + i * 2)
|
|
|
|
if not error:
|
|
if key_i == None:
|
|
key_i = len(self.__commands)
|
|
self.__commands.append(None)
|
|
self.__commands[key_i] = {
|
|
"i" : key_i,
|
|
"method" : data["method_processed"],
|
|
"raw_method" : data["method"],
|
|
"synonyms" : data["synonyms"],
|
|
"parameters" : data["parameters"],
|
|
"special" : data["special_processed"] if "special" in data else None
|
|
}
|
|
|
|
self.validate(
|
|
error,
|
|
(
|
|
"exception",
|
|
"key_null",
|
|
"key_not_string",
|
|
"key_empty",
|
|
"data_null",
|
|
"data_not_dictionary",
|
|
"synonyms_not_data",
|
|
"synonyms_null",
|
|
"synonyms_bad_type",
|
|
"method_not_data",
|
|
"method_null",
|
|
"method_bad_type",
|
|
"root_not_data",
|
|
"root_null",
|
|
"root_not_object_class",
|
|
"parameters_not_data",
|
|
"parameters_null",
|
|
"parameters_bad_type",
|
|
"special_not_data",
|
|
"special_null",
|
|
"special_bad_type",
|
|
"command_key_exists",
|
|
"some_synonym_null",
|
|
"some_synonym_not_string",
|
|
"some_synonym_empty",
|
|
"some_synonym_bad_characters",
|
|
"some_method_key_null",
|
|
"some_method_key_not_string",
|
|
"some_method_key_empty",
|
|
"some_method_key_bad_characters",
|
|
"some_special_key_null",
|
|
"some_special_key_not_string",
|
|
"some_special_key_empty",
|
|
"some_special_key_bad_characters",
|
|
"some_parameter_key_null",
|
|
"some_parameter_key_not_string",
|
|
"some_parameter_key_empty",
|
|
"some_parameter_key_bad_characters",
|
|
"method_null",
|
|
"method_not_function",
|
|
"special_null",
|
|
"special_not_function"
|
|
),
|
|
{
|
|
"key" : key,
|
|
"action" : data["method"] if "method" in data else None
|
|
},
|
|
(show_errors if has_show_errors else self.__show_add_error) and "mem_web_terminal_add_error",
|
|
(show_errors if has_show_errors else True) and self.__show_add_ok and "mem_web_terminal_add_ok"
|
|
)
|
|
|
|
elif isinstance(inputs, str):
|
|
if MemWeb.re_json.match(inputs.strip()):
|
|
try:
|
|
self.add(json_decode(inputs), overwrite, show_errors)
|
|
except Exception as exception:
|
|
self.exception(exception, self.__show_add_exception and "mem_web_terminal_add_exception")
|
|
else:
|
|
|
|
json = self.mem_web.load_file(inputs)[0]
|
|
|
|
if json and MemWeb.re_json.match(json.strip()):
|
|
try:
|
|
self.add(json_decode(json), overwrite, show_errors)
|
|
except Exception as exception:
|
|
self.exception(exception, self.__show_add_exception and "mem_web_terminal_add_exception")
|
|
|
|
def _echo(self, parameters, attributes):
|
|
print(" ".join(parameters))
|
|
|
|
def _close_application(self, *_):
|
|
self.mem_web.close()
|
|
|
|
def get_command(self, keys):
|
|
|
|
keys = MemWeb.get_keys(keys)
|
|
|
|
if len(keys):
|
|
for command in self.__commands:
|
|
for key in keys:
|
|
if key in command["synonyms"]:
|
|
return command
|
|
return None
|
|
|
|
def _help(self, *_):
|
|
self._print("help", "mem_web_terminal_help", {
|
|
"commands" : "".join(["\n - " + command["synonyms"][0] + (
|
|
" (" + ", ".join(command["synonyms"][1:]) + ")" if len(command["synonyms"]) > 1 else ""
|
|
) for command in self.__commands]) + "\n",
|
|
"help_key" : (self.get_command("help") or {"synonyms" : [None]})["synonyms"][0]
|
|
})
|
|
|
|
def _help_special(self, key, command, _type, name, parameter):
|
|
if parameter:
|
|
if parameter in command["parameters"]:
|
|
self._print("help", (
|
|
"mem_web_help_" + command["synonyms"][0] + "_" + parameter,
|
|
"mem_web_help_" + command["synonyms"][0] + "_parameter",
|
|
"help_" + command["synonyms"][0] + "_" + parameter,
|
|
"help_" + command["synonyms"][0] + "_parameter"
|
|
), {
|
|
"special_type" : _type,
|
|
"real_key" : command["synonyms"][0],
|
|
"key" : key,
|
|
"synonyms" : ", ".join(command["synonyms"][1:]),
|
|
"parameter" : parameter
|
|
})
|
|
else:
|
|
self._print("warn", "mem_web_terminal_command_unknown_parameter", {
|
|
"special_type" : _type,
|
|
"real_key" : command["synonyms"][0],
|
|
"key" : key,
|
|
"synonyms" : ", ".join(command["synonyms"][1:]),
|
|
"parameter" : parameter,
|
|
"parameters" : "".join(["\n - " + subkey for subkey in command["parameters"]]) + "\n"
|
|
})
|
|
else:
|
|
self._print("help", (
|
|
"mem_web_help_" + command["synonyms"][0],
|
|
"help_" + command["synonyms"][0]
|
|
), {
|
|
"special_type" : _type,
|
|
"real_key" : command["synonyms"][0],
|
|
"key" : key,
|
|
"synonyms" : ", ".join(command["synonyms"][1:]),
|
|
"parameters" : "".join(["\n - " + subkey for subkey in command["parameters"]]) + "\n"
|
|
})
|
|
|
|
MemWeb.Terminal = Anonymous
|
|
del globals()["Anonymous"] |