54e5681c5a
Fixed #110 : SheerkaDebugManager: add list_debug_settings Fixed #111 : SheerkaDebugManager: Implement ListDebugLogger Fixed #112 : SyaNodeParser: rewrite this parser Fixed #113 : Sheerka.: Add enable_parser_caching to disable parsers caching Fixed #114 : SyaNodeParser : Implement fast cache to resolve unrecognized tokens requests Fixed #115 : BnfNodeParser : Implement fast cache to resolve unrecognized tokens requests Fixed #116 : SequenceNodeParser : Implement fast cache to resolve unrecognized tokens requests Fixed #117 : ResolveMultiplePluralAmbiguityEvaluator: Resolve Multiple plural ambiguity
298 lines
12 KiB
Python
298 lines
12 KiB
Python
import os
|
|
import time
|
|
from os import path
|
|
|
|
from core.builtin_concepts_ids import BuiltinConcepts, BuiltinContainers
|
|
from core.builtin_helpers import ensure_concept_or_rule
|
|
from core.concept import Concept
|
|
from core.global_symbols import SHEERKA_BACKUP_FOLDER
|
|
from core.sheerka.services.SheerkaExecute import SheerkaExecute
|
|
from core.sheerka.services.SheerkaHistoryManager import SheerkaHistoryManager
|
|
from core.sheerka.services.SheerkaMemory import SheerkaMemory
|
|
from core.sheerka.services.sheerka_service import BaseService
|
|
|
|
CONCEPTS_FILE_FULL = "full.sb" # .sb for sheerka backup
|
|
CONCEPTS_FILE_TO_USE = CONCEPTS_FILE_FULL
|
|
|
|
|
|
class SheerkaAdmin(BaseService):
|
|
NAME = "Admin"
|
|
|
|
def __init__(self, sheerka):
|
|
super().__init__(sheerka)
|
|
|
|
def initialize(self):
|
|
self.sheerka.bind_service_method(self.NAME, self.caches_names, False)
|
|
self.sheerka.bind_service_method(self.NAME, self.cache, False)
|
|
self.sheerka.bind_service_method(self.NAME, self.restore, True)
|
|
self.sheerka.bind_service_method(self.NAME, self.concepts, False)
|
|
self.sheerka.bind_service_method(self.NAME, self.builtins, False)
|
|
self.sheerka.bind_service_method(self.NAME, self.desc, False)
|
|
self.sheerka.bind_service_method(self.NAME, self.desc_evaluators, False)
|
|
self.sheerka.bind_service_method(self.NAME, self.desc_parsers, False)
|
|
self.sheerka.bind_service_method(self.NAME, self.extended_isinstance, False)
|
|
self.sheerka.bind_service_method(self.NAME, self.is_container, False)
|
|
self.sheerka.bind_service_method(self.NAME, self.format_rules, False)
|
|
self.sheerka.bind_service_method(self.NAME, self.exec_rules, False)
|
|
self.sheerka.bind_service_method(self.NAME, self.admin_push_ontology, True, as_name="push_ontology")
|
|
self.sheerka.bind_service_method(self.NAME, self.admin_pop_ontology, True, as_name="pop_ontology")
|
|
self.sheerka.bind_service_method(self.NAME, self.ontologies, False)
|
|
self.sheerka.bind_service_method(self.NAME, self.in_memory, False)
|
|
self.sheerka.bind_service_method(self.NAME, self.admin_history, False, as_name="history")
|
|
self.sheerka.bind_service_method(self.NAME, self.sdp, False)
|
|
self.sheerka.bind_service_method(self.NAME, self.set_sheerka, True)
|
|
|
|
def caches_names(self):
|
|
"""
|
|
Returns the name of all the caches
|
|
:return:
|
|
"""
|
|
return self.sheerka.new(BuiltinConcepts.TO_LIST, body=self.sheerka.om.current_cache_manager().caches.keys())
|
|
|
|
def cache(self, name, *keys):
|
|
"""
|
|
Returns the content of a cache
|
|
:param name:
|
|
:param keys: look for a specific key. May ask to sdp if the key is not in cache
|
|
:return:
|
|
"""
|
|
if name not in self.sheerka.om.current_cache_manager().caches:
|
|
return self.sheerka.new(BuiltinConcepts.NOT_FOUND, body={"cache": name})
|
|
|
|
if not keys:
|
|
return self.sheerka.om.current_cache_manager().caches[name].cache.copy()
|
|
|
|
return {key: self.sheerka.om.get(name, key) for key in keys}
|
|
|
|
def sdp(self, name=None):
|
|
if name:
|
|
for ontology in self.sheerka.om.ontologies:
|
|
if ontology.name == name:
|
|
return ontology.cache_manager.sdp
|
|
|
|
return self.sheerka.err(self.sheerka.new(BuiltinConcepts.NOT_FOUND, {"sdp_name", name}))
|
|
|
|
return self.sheerka.om.current_sdp()
|
|
|
|
def restore(self, backup_file=CONCEPTS_FILE_TO_USE):
|
|
"""
|
|
Restore the state with all previous valid concept definitions
|
|
:return:
|
|
"""
|
|
|
|
def restore_from_file(file_name):
|
|
_nb_lines, _nb_instructions, _nb_lines_in_error = 0, 0, 0
|
|
_min_time, _max_time = None, None
|
|
file_path = path.join(backup_folder, file_name)
|
|
if not path.exists(file_path):
|
|
print(f"\u001b[31mFile '{file_path}' is not found !\u001b[0m")
|
|
return 0, 0, 1
|
|
|
|
with open(file_path, "r") as f:
|
|
for line in f.readlines():
|
|
_nb_lines += 1
|
|
line = line.strip()
|
|
|
|
if line.startswith("#import "):
|
|
to_import = line[8:] + ".sb"
|
|
print(f" ==== Importing {to_import} ==== ")
|
|
res = restore_from_file(to_import)
|
|
_nb_lines += res[0]
|
|
_nb_instructions += res[1]
|
|
_nb_lines_in_error += res[2]
|
|
if _min_time is None or res[3] < _min_time:
|
|
_min_time = res[3]
|
|
if _max_time is None or res[4] > _max_time:
|
|
_max_time = res[4]
|
|
continue
|
|
|
|
if line == "" or line.startswith("#"):
|
|
continue
|
|
|
|
print(line)
|
|
_nb_instructions += 1
|
|
stop_watch = time.time_ns()
|
|
res = self.sheerka.evaluate_user_input(line)
|
|
user_input_elapsed = time.time_ns() - stop_watch
|
|
|
|
if _min_time is None or user_input_elapsed < _min_time:
|
|
_min_time = user_input_elapsed
|
|
if _max_time is None or user_input_elapsed > _max_time:
|
|
_max_time = user_input_elapsed
|
|
|
|
if len(res) > 1 or not res[0].status:
|
|
_nb_lines_in_error += 1
|
|
print("\u001b[31mError detected !\u001b[0m")
|
|
|
|
return _nb_lines, _nb_instructions, _nb_lines_in_error, _min_time, _max_time
|
|
|
|
backup_folder = os.getenv(SHEERKA_BACKUP_FOLDER)
|
|
if backup_folder is None:
|
|
return self.sheerka.ret(self.NAME, False, self.sheerka.err(SHEERKA_BACKUP_FOLDER + " is not defined"))
|
|
|
|
if not backup_file.endswith(".sb"):
|
|
backup_file = backup_file + ".sb"
|
|
|
|
try:
|
|
start = time.time_ns()
|
|
self.sheerka.during_restore = True
|
|
self.sheerka.save_execution_context = False
|
|
enable_process_return_values_previous_value = self.sheerka.enable_process_return_values
|
|
self.sheerka.enable_process_return_values = False
|
|
self.sheerka.add_to_context(BuiltinConcepts.EVAL_GLOBAL_TRUTH_REQUESTED)
|
|
|
|
nb_lines, nb_instructions, nb_lines_in_error, min_time, max_time = restore_from_file(backup_file)
|
|
|
|
self.sheerka.remove_fom_context(BuiltinConcepts.EVAL_GLOBAL_TRUTH_REQUESTED)
|
|
self.sheerka.enable_process_return_values = enable_process_return_values_previous_value
|
|
self.sheerka.save_execution_context = True
|
|
self.sheerka.during_restore = False
|
|
stop = time.time_ns()
|
|
|
|
nano_sec = stop - start
|
|
dt = nano_sec / 1e6
|
|
elapsed = f"{dt:.3f} ms" if dt < 1000 else f"{dt / 1000:.3f} s"
|
|
min_str = f"{min_time / 1e6:.3f} ms"
|
|
max_str = f"{max_time / 1e6:.3f} ms"
|
|
mean_time = dt / nb_lines
|
|
mean_str = f"{mean_time:.3f} ms" if mean_time < 1000 else f"{mean_time / 1000:.3f} s"
|
|
|
|
print(f"Imported {nb_lines} line(s) in {elapsed}. min={min_str}, max={max_str}, mean={mean_str}")
|
|
print(f"{nb_instructions} instruction(s).")
|
|
if nb_lines_in_error > 0:
|
|
print(f"\u001b[31m{nb_lines_in_error} errors(s) found.\u001b[0m")
|
|
else:
|
|
print(f"No error.")
|
|
except IOError as e:
|
|
raise e
|
|
|
|
def concepts(self):
|
|
concepts = sorted(self.sheerka.om.list(self.sheerka.CONCEPTS_BY_ID_ENTRY), key=lambda item: int(item.id))
|
|
return self.sheerka.new(BuiltinConcepts.TO_LIST, body=concepts)
|
|
|
|
def builtins(self):
|
|
builtins = sorted(self.sheerka.sheerka_methods.values(), key=lambda builtin_method: builtin_method.name)
|
|
return self.sheerka.new(BuiltinConcepts.TO_LIST, body=builtins)
|
|
|
|
def desc_evaluators(self):
|
|
evaluators = {k: sorted(v[0].items(), reverse=True)
|
|
for k, v in self.sheerka.services[SheerkaExecute.NAME].grouped_evaluators_cache.items()}
|
|
return self.sheerka.new(BuiltinConcepts.TO_DICT, body=evaluators)
|
|
|
|
def desc_parsers(self):
|
|
res = {}
|
|
for k, v in self.sheerka.services[SheerkaExecute.NAME].grouped_parsers_cache.items():
|
|
parsers = {k1: [p.__name__ for p in v1] for k1, v1 in v[0].items()}
|
|
sorted_parsers = sorted(parsers.items(), reverse=True)
|
|
res[k] = sorted_parsers
|
|
return self.sheerka.new(BuiltinConcepts.TO_DICT, body=res)
|
|
|
|
def desc(self, *items):
|
|
if len(items) == 1 and isinstance(items[0], str):
|
|
name = items[0].strip().lower()
|
|
if name == "parsers":
|
|
return self.desc_parsers()
|
|
elif name == "evaluators":
|
|
return self.desc_evaluators()
|
|
|
|
ensure_concept_or_rule(*items)
|
|
res = []
|
|
for item in items:
|
|
if isinstance(item, Concept):
|
|
bag = {
|
|
"id": item.id,
|
|
"name": item.name,
|
|
"key": item.key,
|
|
"definition": item.get_metadata().definition,
|
|
"type": item.get_metadata().definition_type,
|
|
"hash": item.get_definition_hash(),
|
|
"body": item.get_metadata().body,
|
|
"where": item.get_metadata().where,
|
|
"pre": item.get_metadata().pre,
|
|
"post": item.get_metadata().post,
|
|
"ret": item.get_metadata().ret,
|
|
"vars": item.get_metadata().variables,
|
|
"props": item.get_metadata().props,
|
|
}
|
|
else:
|
|
bag = {
|
|
"id": item.id,
|
|
"name": item.metadata.name,
|
|
"type": item.metadata.action_type,
|
|
"predicate": item.metadata.predicate,
|
|
"action": item.metadata.action,
|
|
"priority": item.priority,
|
|
"compiled": item.metadata.is_compiled,
|
|
"enabled": item.metadata.is_enabled,
|
|
}
|
|
res.append(self.sheerka.new(BuiltinConcepts.TO_DICT, body=bag))
|
|
|
|
return res[0] if len(res) == 1 else self.sheerka.new(BuiltinConcepts.TO_LIST, body=res)
|
|
|
|
def format_rules(self):
|
|
return self.sheerka.new(BuiltinConcepts.TO_LIST, items=self.sheerka.get_format_rules())
|
|
|
|
def exec_rules(self):
|
|
return self.sheerka.new(BuiltinConcepts.TO_LIST, items=self.sheerka.get_exec_rules())
|
|
|
|
def extended_isinstance(self, a, b):
|
|
"""
|
|
switch between sheerka.isinstance and builtin.isinstance
|
|
:param a:
|
|
:param b:
|
|
:return:
|
|
"""
|
|
|
|
if isinstance(b, (type, tuple)):
|
|
return isinstance(a, b)
|
|
|
|
return self.sheerka.isinstance(a, b)
|
|
|
|
@staticmethod
|
|
def is_container(obj):
|
|
"""
|
|
A container concept is a builtin concept that embed a result
|
|
:param obj:
|
|
:return:
|
|
"""
|
|
if not isinstance(obj, Concept):
|
|
return False
|
|
|
|
return obj.key in BuiltinContainers
|
|
|
|
def admin_push_ontology(self, context, name):
|
|
return self.sheerka.push_ontology(context, name, False)
|
|
|
|
def admin_pop_ontology(self, context):
|
|
return self.sheerka.pop_ontology(context)
|
|
|
|
def ontologies(self):
|
|
ontologies = self.sheerka.om.ontologies_names
|
|
return self.sheerka.new(BuiltinConcepts.TO_LIST, body=ontologies)
|
|
|
|
def in_memory(self):
|
|
"""
|
|
Returns the list of all obj in memory
|
|
"""
|
|
res = {}
|
|
for k, obj in self.sheerka.om.get_all(SheerkaMemory.OBJECTS_ENTRY).items():
|
|
if isinstance(obj, list):
|
|
obj = obj[-1]
|
|
res[k] = obj.obj
|
|
|
|
return self.sheerka.ret(self.NAME, True, self.sheerka.new(BuiltinConcepts.TO_DICT, body=res))
|
|
|
|
def admin_history(self, depth=10, start=0):
|
|
history = self.sheerka.services[SheerkaHistoryManager.NAME].history(depth, start)
|
|
return self.sheerka.new(BuiltinConcepts.TO_LIST, body=history)
|
|
|
|
def set_sheerka(self, context, key, value, service=None):
|
|
"""
|
|
@param context:
|
|
@param key:
|
|
@param value:
|
|
@param service:
|
|
@return:
|
|
"""
|
|
return self.sheerka.record_var(context, service or self.sheerka.name, key, value)
|