From 87f232b52790329f3bf624877e545e09f32f844f Mon Sep 17 00:00:00 2001 From: Kodjo Sossouvi Date: Tue, 18 Feb 2020 16:31:55 +0100 Subject: [PATCH] Logger is now an attribute of the execution context --- src/core/builtin_helpers.py | 15 ++-- src/core/sheerka/ExecutionContext.py | 45 ++++++++--- .../Services/SheerkaCreateNewConcept.py | 7 +- src/core/sheerka/Services/SheerkaDump.py | 5 ++ .../Services/SheerkaEvaluateConcept.py | 34 ++++----- src/core/sheerka/Services/SheerkaExecute.py | 24 +++--- .../sheerka/Services/SheerkaModifyConcept.py | 3 +- .../sheerka/Services/SheerkaSetsManager.py | 47 +++++------- src/core/sheerka/Sheerka.py | 63 ++++++++-------- src/core/sheerka_logger.py | 27 +++++-- src/evaluators/AddConceptEvaluator.py | 6 +- src/evaluators/AddConceptInSetEvaluator.py | 10 +-- src/evaluators/ConceptEvaluator.py | 6 +- src/evaluators/EvalEvaluator.py | 4 +- src/evaluators/LexerNodeEvaluator.py | 2 +- src/evaluators/MutipleSameSuccessEvaluator.py | 4 +- src/evaluators/OneErrorEvaluator.py | 4 +- src/evaluators/OneSuccessEvaluator.py | 4 +- src/evaluators/PythonEvaluator.py | 74 ++++--------------- src/evaluators/TooManySuccessEvaluator.py | 9 +-- src/parsers/BaseParser.py | 16 +++- src/parsers/ConceptLexerParser.py | 3 +- src/parsers/ConceptsWithConceptsParser.py | 2 - src/parsers/DefaultParser.py | 7 +- src/parsers/ExactConceptParser.py | 9 +-- tests/core/test_SheerkaEvaluateConcept.py | 2 +- .../test_AddConceptInSetEvaluator.py | 24 +++--- 27 files changed, 213 insertions(+), 243 deletions(-) diff --git a/src/core/builtin_helpers.py b/src/core/builtin_helpers.py index a6ee448..8054720 100644 --- a/src/core/builtin_helpers.py +++ b/src/core/builtin_helpers.py @@ -32,13 +32,12 @@ def is_same_success(sheerka, return_values): return True -def expect_one(context, return_values, logger=None): +def expect_one(context, return_values): """ Checks if there is at least one success return value If there is more than one, check if it's the same value :param context: :param return_values: - :param logger: :return: """ @@ -75,10 +74,10 @@ def expect_one(context, return_values, logger=None): successful_results[0].value, parents=return_values) else: - if logger and logger.isEnabledFor(logging.DEBUG): - context.log(logger, f"Too many successful results found by expect_one()", context.who) + if context.logger and context.logger.isEnabledFor(logging.DEBUG): + context.log(f"Too many successful results found by expect_one()", context.who) for s in successful_results: - context.log(logger, f"-> {s}", context.who) + context.log(f"-> {s}", context.who) return sheerka.ret( context.who, False, @@ -86,10 +85,10 @@ def expect_one(context, return_values, logger=None): parents=return_values) # only errors, i cannot help you - if logger and logger.isEnabledFor(logging.DEBUG): - context.log(logger, f"Too many errors found by expect_one()", context.who) + if context.logger and context.logger.isEnabledFor(logging.DEBUG): + context.log(f"Too many errors found by expect_one()", context.who) for s in successful_results: - context.log(logger, f"-> {s}", context.who) + context.log(f"-> {s}", context.who) if len(return_values) == 1: return sheerka.ret( diff --git a/src/core/sheerka/ExecutionContext.py b/src/core/sheerka/ExecutionContext.py index bb74d6c..c83d145 100644 --- a/src/core/sheerka/ExecutionContext.py +++ b/src/core/sheerka/ExecutionContext.py @@ -3,8 +3,8 @@ import time from core.builtin_concepts import BuiltinConcepts from core.concept import Concept +from core.sheerka_logger import get_logger from sdp.sheerkaDataProvider import Event -from sheerkapickle.SheerkaPickler import SheerkaPickler DEBUG_TAB_SIZE = 4 @@ -21,6 +21,8 @@ PROPERTIES_TO_SERIALIZE = ("_id", "concepts") + + class ExecutionContext: """ To keep track of the execution of a request @@ -41,6 +43,7 @@ class ExecutionContext: event: Event, sheerka, desc: str = None, + logger=None, **kwargs): self._parent = None @@ -56,6 +59,7 @@ class ExecutionContext: self.desc = desc # human description of what is going on self.children = [] self.preprocess = None + self.logger = logger self.inputs = {} # what was the parameters of the execution context self.values = {} # what was produced by the execution context @@ -66,6 +70,9 @@ class ExecutionContext: for k, v in kwargs.items(): self._bag[k] = v + self.stat_log = get_logger("stats") + self.show_stats = False + @property def elapsed(self): if self._start == 0: @@ -91,10 +98,13 @@ class ExecutionContext: def __enter__(self): self._start = time.time_ns() + self.log_new() return self def __exit__(self, exc_type, exc_val, exc_tb): self._stop = time.time_ns() + if self.show_stats: + self.stat_log.debug(f"[{self._id:2}]" + self._tab + "Execution time: " + self.elapsed_str) def __repr__(self): msg = f"ExecutionContext(who={self.who}, id={self._id}" @@ -103,6 +113,11 @@ class ExecutionContext: msg += ")" return msg + def __str__(self): + msg = self.desc or "New Context" + msg += f", who={self.who}, id={self.id}" + return msg + def __eq__(self, other): if id(self) == id(other): return True @@ -183,8 +198,9 @@ class ExecutionContext: return self.sheerka.new(key, **kwargs) - def push(self, who=None, desc=None, **kwargs): + def push(self, who=None, desc=None, logger=None, **kwargs): who = who or self.who + logger = logger or self.logger _kwargs = {"obj": self.obj, "concepts": self.concepts} _kwargs.update(self._bag) _kwargs.update(kwargs) @@ -193,6 +209,7 @@ class ExecutionContext: self.event, self.sheerka, desc, + logger, **_kwargs, ) new._parent = self @@ -202,25 +219,29 @@ class ExecutionContext: self.children.append(new) return new - def log_new(self, logger): - logger.debug(f"[{self._id:2}]" + self._tab + str(self)) + def log_new(self): + if self.logger and not self.logger.disabled: + self.logger.debug(f"[{self._id:2}]" + self._tab + str(self)) + self.show_stats = True - def log(self, logger, message, who=None): - logger.debug(f"[{self._id:2}]" + self._tab + (f"[{who}] " if who else "") + str(message)) + def log(self, message, who=None): + if self.logger and not self.logger.disabled: + self.logger.debug(f"[{self._id:2}]" + self._tab + (f"[{who}] " if who else "") + str(message)) - def log_error(self, logger, message, who=None): - logger.exception(f"[{self._id:2}]" + self._tab + (f"[{who}] " if who else "") + str(message)) + def log_error(self, message, who=None): + if self.logger and not self.logger.disabled: + self.logger.exception(f"[{self._id:2}]" + self._tab + (f"[{who}] " if who else "") + str(message)) - def log_result(self, logger, return_values): - if not logger.isEnabledFor(logging.DEBUG): + def log_result(self, return_values): + if not self.logger or not self.logger.isEnabledFor(logging.DEBUG): return if len(return_values) == 0: - logger.debug(self._tab + "No return value") + self.logger.debug(self._tab + "No return value") for r in return_values: to_str = self.return_value_to_str(r) - logger.debug(f"[{self._id:2}]" + self._tab + "-> " + to_str) + self.logger.debug(f"[{self._id:2}]" + self._tab + "-> " + to_str) def get_parent(self): return self._parent diff --git a/src/core/sheerka/Services/SheerkaCreateNewConcept.py b/src/core/sheerka/Services/SheerkaCreateNewConcept.py index ea5102b..eb9e148 100644 --- a/src/core/sheerka/Services/SheerkaCreateNewConcept.py +++ b/src/core/sheerka/Services/SheerkaCreateNewConcept.py @@ -14,7 +14,7 @@ class SheerkaCreateNewConcept: self.sheerka = sheerka self.logger_name = self.create_new_concept.__name__ - def create_new_concept(self, context, concept: Concept, logger=None): + def create_new_concept(self, context, concept: Concept): """ Adds a new concept to the system :param context: @@ -23,8 +23,6 @@ class SheerkaCreateNewConcept: :return: digest of the new concept """ - logger = logger or self.sheerka.log - concept.init_key() concepts_definitions = None init_ret_value = None @@ -52,7 +50,6 @@ class SheerkaCreateNewConcept: concept_lexer_parser = self.sheerka.parsers[CONCEPT_LEXER_PARSER_CLASS]() with context.push(self.sheerka.name, desc=f"Initializing concept definition for {concept}") as sub_context: sub_context.concepts[concept.key] = concept # the concept is not in the real cache yet - sub_context.log_new(logger) init_ret_value = concept_lexer_parser.initialize(sub_context, concepts_definitions) sub_context.add_values(return_values=init_ret_value) if not init_ret_value.status: @@ -83,7 +80,7 @@ class SheerkaCreateNewConcept: use_ref=True) self.sheerka.concepts_definitions_cache = None # invalidate cache except SheerkaDataProviderDuplicateKeyError as error: - context.log_error(logger, "Failed to create a new concept.", who=self.logger_name) + context.log_error("Failed to create a new concept.", who=self.logger_name) return self.sheerka.ret( self.logger_name, False, diff --git a/src/core/sheerka/Services/SheerkaDump.py b/src/core/sheerka/Services/SheerkaDump.py index d404265..11454d7 100644 --- a/src/core/sheerka/Services/SheerkaDump.py +++ b/src/core/sheerka/Services/SheerkaDump.py @@ -58,6 +58,11 @@ class SheerkaDump: self.sheerka.log.info(f"body : {c.metadata.body}") if eval: self.sheerka.log.info(f"value : {value}") + for p in c.props: + self.sheerka.log.info(f"{p}: {c.get_prop(p)}") + else: + self.sheerka.log.info("No property") + self.sheerka.log.info(f"digest : {c.get_digest()}") if self.sheerka.isaset(context, c): diff --git a/src/core/sheerka/Services/SheerkaEvaluateConcept.py b/src/core/sheerka/Services/SheerkaEvaluateConcept.py index 5b0cde7..bf59a55 100644 --- a/src/core/sheerka/Services/SheerkaEvaluateConcept.py +++ b/src/core/sheerka/Services/SheerkaEvaluateConcept.py @@ -62,7 +62,7 @@ class SheerkaEvaluateConcept: False, self.sheerka.new(BuiltinConcepts.CHICKEN_AND_EGG, body=concepts_found)) - def initialize_concept_asts(self, context, concept: Concept, logger=None): + def initialize_concept_asts(self, context, concept: Concept): """ Updates the codes of the newly created concept Basically, it runs the parsers on all parts @@ -84,11 +84,10 @@ class SheerkaEvaluateConcept: concept.compiled[part_key] = DoNotResolve(source) else: with context.push(desc=f"Initializing compiled for {part_key}") as sub_context: - sub_context.log_new(logger) sub_context.add_inputs(source=source) to_parse = self.sheerka.ret(context.who, True, self.sheerka.new(BuiltinConcepts.USER_INPUT, body=source)) - res = self.sheerka.execute(sub_context, to_parse, steps, logger) + res = self.sheerka.execute(sub_context, to_parse, steps) concept.compiled[part_key] = res sub_context.add_values(return_values=res) @@ -103,7 +102,6 @@ class SheerkaEvaluateConcept: concept.compiled[prop] = DoNotResolve(default_value) else: with context.push(desc=f"Initializing AST for property {prop}") as sub_context: - sub_context.log_new(logger) sub_context.add_inputs(source=default_value) to_parse = self.sheerka.ret(context.who, True, self.sheerka.new(BuiltinConcepts.USER_INPUT, body=default_value)) @@ -120,7 +118,7 @@ class SheerkaEvaluateConcept: else: self.sheerka.cache_by_key[concept.key].compiled = concept.compiled - def resolve(self, context, to_resolve, current_prop, current_concept, logger): + def resolve(self, context, to_resolve, current_prop, current_concept): if isinstance(to_resolve, DoNotResolve): return to_resolve.value @@ -128,20 +126,18 @@ class SheerkaEvaluateConcept: if self.infinite_recursion_detected(context, current_concept): with context.push(desc="Infinite recursion detected", obj=current_concept) as sub_context: # I create a sub context in order to log what happened - sub_context.log_new(logger) ret_val = self.manage_infinite_recursion(context) sub_context.add_values(return_values=ret_val) return ret_val.body desc = f"Evaluating {current_prop} (concept={current_concept})" - context.log(logger, desc, self.logger_name) + context.log(desc, self.logger_name) with context.push(desc=desc, obj=current_concept) as sub_context: - sub_context.log_new(logger) # when it's a concept, evaluate it if isinstance(to_resolve, Concept) and \ not context.sheerka.isinstance(to_resolve, BuiltinConcepts.RETURN_VALUE): - evaluated = self.evaluate_concept(sub_context, to_resolve, logger) + evaluated = self.evaluate_concept(sub_context, to_resolve) sub_context.add_values(return_values=evaluated) if evaluated.key == to_resolve.key: return evaluated @@ -151,7 +147,7 @@ class SheerkaEvaluateConcept: # otherwise, execute all return values to find out what is the value else: use_copy = [r for r in to_resolve] if hasattr(to_resolve, "__iter__") else to_resolve - r = self.sheerka.execute(sub_context, use_copy, CONCEPT_EVALUATION_STEPS, logger) + r = self.sheerka.execute(sub_context, use_copy, CONCEPT_EVALUATION_STEPS) one_r = core.builtin_helpers.expect_one(context, r) sub_context.add_values(return_values=one_r) if one_r.status: @@ -165,7 +161,7 @@ class SheerkaEvaluateConcept: concept=current_concept, property_name=current_prop) - def resolve_list(self, context, list_to_resolve, current_prop, current_concept, logger): + def resolve_list(self, context, list_to_resolve, current_prop, current_concept): """When dealing with a list, there are two possibilities""" # It may be a list of ReturnValueConcept to execute (always the case for metadata) # or a list of single values (may be the case for properties) @@ -174,7 +170,7 @@ class SheerkaEvaluateConcept: return [] if self.sheerka.isinstance(list_to_resolve[0], BuiltinConcepts.RETURN_VALUE): - return self.resolve(context, list_to_resolve, current_prop, current_concept, logger) + return self.resolve(context, list_to_resolve, current_prop, current_concept) res = [] for to_resolve in list_to_resolve: @@ -185,14 +181,14 @@ class SheerkaEvaluateConcept: concept=current_concept, property_name=current_prop) - r = self.resolve(context, to_resolve, current_prop, current_concept, logger) + r = self.resolve(context, to_resolve, current_prop, current_concept) if self.sheerka.isinstance(r, BuiltinConcepts.CONCEPT_EVAL_ERROR): return r res.append(r) return res - def evaluate_concept(self, context, concept: Concept, logger=None): + def evaluate_concept(self, context, concept: Concept): """ Evaluation a concept It means that if the where clause is True, will evaluate the body @@ -202,8 +198,6 @@ class SheerkaEvaluateConcept: :return: value of the evaluation or error """ - logger = logger or self.sheerka.log - if concept.metadata.is_evaluated: return concept @@ -211,7 +205,7 @@ class SheerkaEvaluateConcept: # TODO : Validate the PRE condition # - self.initialize_concept_asts(context, concept, logger) + self.initialize_concept_asts(context, concept) # to make sure of the order, it don't use ConceptParts.get_parts() # props must be evaluated first, body must be evaluated before where @@ -224,10 +218,10 @@ class SheerkaEvaluateConcept: if isinstance(prop_ast, list): # Do not send the current concept for the properties - resolved = self.resolve_list(context, prop_ast, prop_name, None, logger) + resolved = self.resolve_list(context, prop_ast, prop_name, None) else: # Do not send the current concept for the properties - resolved = self.resolve(context, prop_ast, prop_name, None, logger) + resolved = self.resolve(context, prop_ast, prop_name, None) if isinstance(resolved, Concept) and not context.sheerka.is_success(resolved): resolved.set_prop("concept", concept) # since current concept was not sent return resolved @@ -243,7 +237,7 @@ class SheerkaEvaluateConcept: if part_key in concept.compiled and concept.compiled[part_key] is not None: metadata_ast = concept.compiled[part_key] - resolved = self.resolve(context, metadata_ast, part_key, concept, logger) + resolved = self.resolve(context, metadata_ast, part_key, concept) if isinstance(resolved, Concept) and not context.sheerka.is_success(resolved): return resolved else: diff --git a/src/core/sheerka/Services/SheerkaExecute.py b/src/core/sheerka/Services/SheerkaExecute.py index 2027614..1d2edcb 100644 --- a/src/core/sheerka/Services/SheerkaExecute.py +++ b/src/core/sheerka/Services/SheerkaExecute.py @@ -10,7 +10,7 @@ class SheerkaExecute: def __init__(self, sheerka): self.sheerka = sheerka - def call_parsers(self, execution_context, return_values, logger=None): + def call_parsers(self, execution_context, return_values): # return_values must be a list if not isinstance(return_values, list): @@ -35,8 +35,6 @@ class SheerkaExecute: instantiated_parsers = [parser(sheerka=self.sheerka) for parser in self.sheerka.parsers.values()] grouped_parsers = {} for parser in [p for p in instantiated_parsers if p.enabled]: - if logger: - parser.log = logger grouped_parsers.setdefault(parser.priority, []).append(parser) sorted_priorities = sorted(grouped_parsers.keys(), reverse=True) @@ -56,9 +54,9 @@ class SheerkaExecute: # if self.sheerka.log.isEnabledFor(logging.DEBUG): # debug_text = "'" + to_parse + "'" if isinstance(to_parse, str) \ # else "'" + BaseParser.get_text_from_tokens(to_parse) + "' as tokens" - # execution_context.log(logger or self.sheerka.log, f"Parsing {debug_text}") + # execution_context.log(f"Parsing {debug_text}") - with execution_context.push(desc=f"Parsing using {parser.name}") as sub_context: + with execution_context.push(desc=f"Parsing using {parser.name}", logger=parser.verbose_log) as sub_context: sub_context.add_inputs(to_parse=to_parse) res = parser.parse(sub_context, to_parse) if res is not None: @@ -92,7 +90,7 @@ class SheerkaExecute: result = core.utils.remove_list_from_list(result, user_inputs) return result - def call_evaluators(self, execution_context, return_values, process_step, evaluation_context=None, logger=None): + def call_evaluators(self, execution_context, return_values, process_step, evaluation_context=None): # return_values must be a list if not isinstance(return_values, list): @@ -122,8 +120,6 @@ class SheerkaExecute: instantiated_evaluators = self._preprocess_evaluators(execution_context, instantiated_evaluators) for evaluator in [e for e in instantiated_evaluators if e.enabled and process_step in e.steps]: - if logger: - evaluator.log = logger grouped_evaluators.setdefault(evaluator.priority, []).append(evaluator) # order the groups by priority, the higher first @@ -145,7 +141,7 @@ class SheerkaExecute: evaluator = self._preprocess_evaluators(execution_context, evaluator.__class__()) # fresh copy sub_context_desc = f"Evaluating using {evaluator.name} ({priority=})" - with iteration_context.push(desc=sub_context_desc) as sub_context: + with iteration_context.push(desc=sub_context_desc, logger=evaluator.verbose_log) as sub_context: sub_context.add_inputs(return_values=original_items) # process evaluators that work on one simple return value at the time @@ -206,28 +202,26 @@ class SheerkaExecute: return_values = core.utils.remove_list_from_list(return_values, evaluation_return_values) return return_values - def execute(self, execution_context, return_values, execution_steps, logger=None): + def execute(self, execution_context, return_values, execution_steps): """ Executes process for all initial contexts :param execution_context: :param return_values: :param execution_steps: - :param logger: logger to use (if not directly called by sheerka) :return: """ for step in execution_steps: copy = return_values[:] if hasattr(return_values, "__iter__") else [return_values] with execution_context.push(step=step, iteration=0, desc=f"{step=}") as sub_context: - sub_context.log(logger or self.sheerka.log, f"{step=}, context='{sub_context}'") if step == BuiltinConcepts.PARSING: - return_values = self.call_parsers(sub_context, return_values, logger) + return_values = self.call_parsers(sub_context, return_values) else: - return_values = self.call_evaluators(sub_context, return_values, step, None, logger) + return_values = self.call_evaluators(sub_context, return_values, step, None) if copy != return_values: - sub_context.log_result(logger or self.sheerka.log, return_values) + sub_context.log_result(return_values) sub_context.add_values(return_values=return_values) diff --git a/src/core/sheerka/Services/SheerkaModifyConcept.py b/src/core/sheerka/Services/SheerkaModifyConcept.py index d6dcbb9..227cdbb 100644 --- a/src/core/sheerka/Services/SheerkaModifyConcept.py +++ b/src/core/sheerka/Services/SheerkaModifyConcept.py @@ -6,8 +6,7 @@ class SheerkaModifyConcept: self.sheerka = sheerka self.logger_name = self.modify_concept.__name__ - def modify_concept(self, context, concept, logger=None): - logger = logger or self.sheerka.log + def modify_concept(self, context, concept): self.sheerka.sdp.modify(context.event.get_digest(), self.sheerka.CONCEPTS_ENTRY, concept.key, concept) diff --git a/src/core/sheerka/Services/SheerkaSetsManager.py b/src/core/sheerka/Services/SheerkaSetsManager.py index 9ecd020..88b24ed 100644 --- a/src/core/sheerka/Services/SheerkaSetsManager.py +++ b/src/core/sheerka/Services/SheerkaSetsManager.py @@ -11,42 +11,38 @@ class SheerkaSetsManager: self.sheerka = sheerka self.logger_name = self.add_concept_to_set.__name__ - def set_isa(self, context, concept, concept_set, logger=None): + def set_isa(self, context, concept, concept_set): """ Defines that concept a is b is another concept :param context: :param concept: :param concept_set: - :param logger: :return: """ - logger = logger or self.sheerka.log - context.log(logger, f"Setting that concept {concept} is a {concept_set}", who=self.logger_name) + context.log(f"Setting that concept {concept} is a {concept_set}", who=self.logger_name) isa = [] if BuiltinConcepts.ISA not in concept.props else concept.get_prop(BuiltinConcepts.ISA) if concept_set not in isa: isa.append(concept_set) concept.set_prop(BuiltinConcepts.ISA, isa) - res = self.sheerka.modify_concept(context, concept, logger) + res = self.sheerka.modify_concept(context, concept) if not res.status: return res - return self.add_concept_to_set(context, concept, concept_set, logger) + return self.add_concept_to_set(context, concept, concept_set) - def add_concept_to_set(self, context, concept, concept_set, logger=None): + def add_concept_to_set(self, context, concept, concept_set): """ Add an entry in sdp to tell that concept isa concept_set :param context: :param concept: :param concept_set: - :param logger: :return: """ - logger = logger or self.sheerka.log - context.log(logger, f"Adding concept {concept} to set {concept_set}", who=self.logger_name) + context.log(f"Adding concept {concept} to set {concept_set}", who=self.logger_name) assert concept.id assert concept_set.id @@ -61,14 +57,13 @@ class SheerkaSetsManager: else: return self.sheerka.ret(self.logger_name, True, self.sheerka.new(BuiltinConcepts.SUCCESS)) except Exception as error: - context.log_error(logger, "Failed to add to set.", who=self.logger_name) + context.log_error("Failed to add to set.", who=self.logger_name) return self.sheerka.ret(self.logger_name, False, ErrorConcept(error), error.args[0]) - def add_concepts_to_set(self, context, concepts, concept_set, logger=None): + def add_concepts_to_set(self, context, concepts, concept_set): """Adding multiple concepts at the same time""" - logger = logger or self.sheerka.log - context.log(logger, f"Adding concepts {concepts} to set {concept_set}", who=self.logger_name) + context.log(f"Adding concepts {concepts} to set {concept_set}", who=self.logger_name) previous = self.sheerka.sdp.get_safe(GROUP_PREFIX + concept_set.id) new_ids = [c.id for c in concepts] if previous is None else previous + [c.id for c in concepts] @@ -76,21 +71,18 @@ class SheerkaSetsManager: self.sheerka.sdp.set(context.event.get_digest(), GROUP_PREFIX + concept_set.id, new_ids) return self.sheerka.ret(self.logger_name, True, self.sheerka.new(BuiltinConcepts.SUCCESS)) except Exception as error: - context.log_error(logger, "Failed to add to set.", who=self.logger_name) + context.log_error("Failed to add to set.", who=self.logger_name) return self.sheerka.ret(self.logger_name, False, ErrorConcept(error), error.args[0]) - def get_set_elements(self, context, concept, logger=None): + def get_set_elements(self, context, concept): """ Concept is supposed to be a set Returns all elements if the set :param context: :param concept: - :param logger: :return: """ - logger = logger or self.sheerka.log - # noinspection PyShadowingNames def _get_set_elements(context, concept, sub_concept): if not (isinstance(sub_concept, Concept) and sub_concept.id): @@ -105,13 +97,13 @@ class SheerkaSetsManager: else: # This methods sucks, but I don't have enough tools (like proper AST manipulation functions) # to do it properly now. It will be enhanced later - concepts = self._get_concepts(context, ids, True, logger) + concepts = self._get_concepts(context, ids, True) globals_ = {"xx__concepts__xx": concepts, "sheerka": self.sheerka} locals_ = {} exec(new_condition, globals_, locals_) return locals_["result"] else: - return self._get_concepts(context, ids, False, logger) + return self._get_concepts(context, ids, False) # it may be a concept that references a set if not sub_concept.metadata.is_evaluated: @@ -160,30 +152,27 @@ class SheerkaSetsManager: return False - def isaset(self, context, concept, logger=None): + def isaset(self, context, concept): """ True if exists All_ in sdp or if concept references to a concept that has all_ :param context: :param concept: - :param logger: :return: """ """""" - logger = logger or self.sheerka.log - if not (isinstance(concept, Concept) and concept.id): return None # it may be a concept that references a set if not concept.metadata.is_evaluated: with context.push(desc=f"Evaluating concept {concept}") as sub_context: - evaluated = self.sheerka.evaluate_concept(sub_context, concept, logger) + evaluated = self.sheerka.evaluate_concept(sub_context, concept) if evaluated.key != concept.key: return False if concept.body: - return self.isaset(context, concept.body, logger) + return self.isaset(context, concept.body) res = self.sheerka.sdp.get_safe(GROUP_PREFIX + concept.id) return res is not None @@ -211,7 +200,7 @@ for x in xx__concepts__xx: """ return expression - def _get_concepts(self, context, ids, evaluate, logger): + def _get_concepts(self, context, ids, evaluate): """ Gets concepts from a list of concepts ids :param ids: @@ -229,7 +218,7 @@ for x in xx__concepts__xx: with context.push(desc=f"Evaluating concepts of a set") as sub_context: for element_id in ids: concept = self.sheerka.get_by_id(element_id) - evaluated = self.sheerka.evaluate_concept(context, concept, logger) + evaluated = self.sheerka.evaluate_concept(context, concept) result.append(evaluated) return result diff --git a/src/core/sheerka/Sheerka.py b/src/core/sheerka/Sheerka.py index 8a07342..7b1e5bd 100644 --- a/src/core/sheerka/Sheerka.py +++ b/src/core/sheerka/Sheerka.py @@ -40,6 +40,7 @@ class Sheerka(Concept): def __init__(self, skip_builtins_in_db=False, debug=False, loggers=None): self.init_logging(debug, loggers) + self.loggers = loggers super().__init__(BuiltinConcepts.SHEERKA, True, True, BuiltinConcepts.SHEERKA) self.log.debug("Starting Sheerka.") @@ -110,17 +111,18 @@ class Sheerka(Concept): event = Event("Initializing Sheerka.", user=self.name) self.sdp.save_event(event) - exec_context = ExecutionContext(self.key, event, self) + with ExecutionContext(self.key, event, self, "Initializing Sheerka.", self.init_log) as exec_context: - self.initialize_builtin_concepts() - self.initialize_builtin_parsers() - self.initialize_builtin_evaluators() - self.initialize_concepts_definitions(exec_context) - res = ReturnValueConcept(self, True, self) + self.initialize_builtin_concepts() + self.initialize_builtin_parsers() + self.initialize_builtin_evaluators() + self.initialize_concepts_definitions(exec_context) + res = ReturnValueConcept(self, True, self) - exec_context.add_values(return_values=res) - if not self.skip_builtins_in_db: - self.sdp.save_result(exec_context) + exec_context.add_values(return_values=res) + if not self.skip_builtins_in_db: + self.sdp.save_result(exec_context) + self.init_log.debug(f"Sheerka successfully initialized") except IOError as e: res = ReturnValueConcept(self, False, self.get(BuiltinConcepts.ERROR), e) @@ -191,8 +193,7 @@ class Sheerka(Concept): self.evaluators.append(evaluator) def initialize_concepts_definitions(self, execution_context): - self.init_log.debug("Initializing concepts definitions") - # definitions = self.sdp.get_safe(self.CONCEPTS_DEFINITIONS_ENTRY, load_origin=False) + self.init_log.debug("Initializing concepts grammars.") definitions = self.get_concepts_definitions(execution_context) if definitions is None: @@ -234,7 +235,7 @@ class Sheerka(Concept): evt_digest = self.sdp.save_event(event) self.log.debug(f"{evt_digest=}") - with ExecutionContext(self.key, event, self, f"Evaluating '{text}'") as execution_context: + with ExecutionContext(self.key, event, self, f"Evaluating '{text}'", self.log) as execution_context: user_input = self.ret(self.name, True, self.new(BuiltinConcepts.USER_INPUT, body=text, user_name=user_name)) reduce_requested = self.ret(self.name, True, self.new(BuiltinConcepts.REDUCE_REQUESTED)) @@ -261,7 +262,7 @@ class Sheerka(Concept): return ret - def execute(self, execution_context, return_values, execution_steps, logger=None): + def execute(self, execution_context, return_values, execution_steps): """ Executes process for all initial contexts :param execution_context: @@ -270,7 +271,7 @@ class Sheerka(Concept): :param logger: logger to use (if not directly called by sheerka) :return: """ - return self.execute_handler.execute(execution_context, return_values, execution_steps, logger) + return self.execute_handler.execute(execution_context, return_values, execution_steps) def set_id_if_needed(self, obj: Concept, is_builtin: bool): """ @@ -287,7 +288,7 @@ class Sheerka(Concept): obj.metadata.id = self.sdp.get_next_key(entry) self.log.debug(f"Setting id '{obj.metadata.id}' to concept '{obj.metadata.name}'.") - def create_new_concept(self, context, concept: Concept, logger=None): + def create_new_concept(self, context, concept: Concept): """ Adds a new concept to the system :param context: @@ -296,12 +297,12 @@ class Sheerka(Concept): :return: digest of the new concept """ - return self.create_new_concept_handler.create_new_concept(context, concept, logger) + return self.create_new_concept_handler.create_new_concept(context, concept) - def modify_concept(self, context, concept: Concept, logger): - return self.modify_concept_handler.modify_concept(context, concept, logger) + def modify_concept(self, context, concept: Concept): + return self.modify_concept_handler.modify_concept(context, concept) - def add_concept_to_set(self, context, concept, concept_set, logger=None): + def add_concept_to_set(self, context, concept, concept_set): """ Add an entry in sdp to tell that concept isa concept_set :param context: @@ -310,9 +311,9 @@ class Sheerka(Concept): :param logger: :return: """ - return self.sets_handler.add_concept_to_set(context, concept, concept_set, logger) + return self.sets_handler.add_concept_to_set(context, concept, concept_set) - def set_isa(self, context, concept, concept_set, logger=None): + def set_isa(self, context, concept, concept_set): """ :param context: @@ -321,7 +322,7 @@ class Sheerka(Concept): :param logger: :return: """ - return self.sets_handler.set_isa(context, concept, concept_set, logger) + return self.sets_handler.set_isa(context, concept, concept_set) def get_set_elements(self, context, concept): """ @@ -334,7 +335,7 @@ class Sheerka(Concept): return self.sets_handler.get_set_elements(context, concept) - def evaluate_concept(self, context, concept: Concept, logger=None): + def evaluate_concept(self, context, concept: Concept): """ Evaluation a concept It means that if the where clause is True, will evaluate the body @@ -343,7 +344,7 @@ class Sheerka(Concept): :param logger: :return: value of the evaluation or error """ - return self.evaluate_concept_handler.evaluate_concept(context, concept, logger) + return self.evaluate_concept_handler.evaluate_concept(context, concept) def add_in_cache(self, concept: Concept): """ @@ -424,18 +425,20 @@ class Sheerka(Concept): return result def get_concepts_definitions(self, context): + if self.concepts_definitions_cache: return self.concepts_definitions_cache - encoded = self.sdp.get_safe( + encoded_bnf = self.sdp.get_safe( self.CONCEPTS_DEFINITIONS_ENTRY, load_origin=False) or {} self.concepts_definitions_cache = {} bnf_parser = self.parsers[BNF_PARSER_CLASS]() - for k, v in encoded.items(): + for k, v in encoded_bnf.items(): key, id_ = core.utils.unstr_concept(k) concept = self.new((key, id_)) + context.log(f"Parsing BNF definition for {concept}", context.who) rule_result = bnf_parser.parse(context, v) if rule_result.status: self.concepts_definitions_cache[concept] = rule_result.value.value @@ -681,10 +684,12 @@ class Sheerka(Concept): @staticmethod def init_logging(debug, loggers): - core.sheerka_logger.set_enabled(loggers) + core.sheerka_logger.init_config(loggers) if debug: - # log_format = "%(asctime)s %(name)s [%(levelname)s] %(message)s" - log_format = "%(asctime)s [%(levelname)s] %(message)s" + log_format = "%(asctime)s" + if "show-name" in loggers: + log_format += " %(name)s" + log_format += " [%(levelname)s] %(message)s" log_level = logging.DEBUG else: log_format = "%(message)s" diff --git a/src/core/sheerka_logger.py b/src/core/sheerka_logger.py index 9f87a99..c05773c 100644 --- a/src/core/sheerka_logger.py +++ b/src/core/sheerka_logger.py @@ -2,21 +2,32 @@ import logging import sys enabled = [] -disabled = ["init", "sdp", "parsers", "evaluators", "verbose"] +disabled = ["init", "sdp", "parsers", "evaluators", "verbose", "stats"] console_handler = logging.StreamHandler(sys.stdout) all_loggers = {} - -def set_enabled(to_enable): - if to_enable is None: +def init_config(loggers): + if loggers is None: return - if not hasattr(to_enable, "__iter__"): - to_enable = [to_enable] + if not hasattr(loggers, "__iter__"): + loggers = [loggers] - enabled.extend(to_enable) + if "all" in loggers: + disabled.clear() + + for logger in loggers: + if logger == "all": + continue + + if logger.startswith("-"): + disabled.append(logger[1:]) + elif logger.startswith("+"): + enabled.append(logger[1:]) + else: + enabled.append(logger) def to_discard(logger_class): @@ -40,7 +51,7 @@ def get_logger(logger_name): all_loggers[logger_name] = logger for d in disabled: - if logger_name.startswith(d + ".") and to_discard(d): + if (logger_name == d or logger_name.startswith(d + ".")) and to_discard(d): logger.disabled = True for e in enabled: diff --git a/src/evaluators/AddConceptEvaluator.py b/src/evaluators/AddConceptEvaluator.py index dd4fa8a..7b20d00 100644 --- a/src/evaluators/AddConceptEvaluator.py +++ b/src/evaluators/AddConceptEvaluator.py @@ -47,7 +47,7 @@ class AddConceptEvaluator(OneReturnValueEvaluator): isinstance(return_value.value.value, DefConceptNode) def eval(self, context, return_value): - context.log(self.log, "Adding a new concept", self.name) + context.log("Adding a new concept", self.name) def_concept_node = return_value.value.value sheerka = context.sheerka @@ -86,10 +86,10 @@ class AddConceptEvaluator(OneReturnValueEvaluator): sheerka.is_success(def_concept_node.definition): concept.bnf = def_concept_node.definition.value.value - ret = sheerka.create_new_concept(context, concept, self.verbose_log) + ret = sheerka.create_new_concept(context, concept) if not ret.status: error_cause = sheerka.value(ret.body) - context.log(self.log, f"Failed to add concept '{concept.name}'. Reason: {error_cause}", self.name) + context.log(f"Failed to add concept '{concept.name}'. Reason: {error_cause}", self.name) return sheerka.ret(self.name, ret.status, ret.value, parents=[return_value]) @staticmethod diff --git a/src/evaluators/AddConceptInSetEvaluator.py b/src/evaluators/AddConceptInSetEvaluator.py index ccdcf95..9e6186e 100644 --- a/src/evaluators/AddConceptInSetEvaluator.py +++ b/src/evaluators/AddConceptInSetEvaluator.py @@ -34,14 +34,14 @@ class AddConceptInSetEvaluator(OneReturnValueEvaluator): sheerka.new(BuiltinConcepts.USER_INPUT, body=name_node.tokens, user_name="N/A")) with context.push(desc=f"Recognizing '{name_node}'") as sub_context: - r = sheerka.execute(sub_context, ret_val, ALL_STEPS, self.verbose_log) + r = sheerka.execute(sub_context, ret_val, ALL_STEPS) one_r = core.builtin_helpers.expect_one(context, r) sub_context.add_values(return_values=one_r) return one_r isa_node = return_value.value.value sheerka = context.sheerka - context.log(self.log, f"Adding a concept {isa_node.concept} to set {isa_node.set}", self.name) + context.log(f"Adding concept '{isa_node.concept}' to set '{isa_node.set}'", self.name) # Try to recognize the concept res = _resolve(isa_node.concept) @@ -62,11 +62,11 @@ class AddConceptInSetEvaluator(OneReturnValueEvaluator): parents=[return_value]) concept_set = res.value - res = sheerka.add_concept_to_set(context, concept, concept_set, self.verbose_log) + res = sheerka.set_isa(context, concept, concept_set) if not res.status: - context.log(self.log, f"Failed. Reason: {sheerka.value(res.body)}.", self.name) + context.log(f"Failed. Reason: {sheerka.value(res.body)}.", self.name) else: - context.log(self.log, f"Concept added.", self.name) + context.log(f"Concept added.", self.name) return sheerka.ret( self.name, diff --git a/src/evaluators/ConceptEvaluator.py b/src/evaluators/ConceptEvaluator.py index ed5158c..be0eccd 100644 --- a/src/evaluators/ConceptEvaluator.py +++ b/src/evaluators/ConceptEvaluator.py @@ -24,7 +24,7 @@ class ConceptEvaluator(OneReturnValueEvaluator): def eval(self, context, return_value): sheerka = context.sheerka concept = return_value.value.value - context.log(self.verbose_log, f"Evaluating concept {concept}.", self.name) + context.log(f"Evaluating concept {concept}.", self.name) # If the concept that is requested is in the context(at least its name), drop the call. # Why ? @@ -32,11 +32,11 @@ class ConceptEvaluator(OneReturnValueEvaluator): # The body should be 'property_a', and not a concept called 'a' if context.obj and concept.name in context.obj.props: value = context.obj.props[concept.name].value - context.log(self.verbose_log, f"{concept.name} is a property. Returning value '{value}'.", self.name) + context.log(f"{concept.name} is a property. Returning value '{value}'.", self.name) return sheerka.ret(self.name, True, value, parents=[return_value]) - evaluated = sheerka.evaluate_concept(context, concept, self.verbose_log) + evaluated = sheerka.evaluate_concept(context, concept) if evaluated.key != concept.key: # evaluated.key != concept.key means that we have transformed the concept diff --git a/src/evaluators/EvalEvaluator.py b/src/evaluators/EvalEvaluator.py index 541501e..06a92d1 100644 --- a/src/evaluators/EvalEvaluator.py +++ b/src/evaluators/EvalEvaluator.py @@ -29,10 +29,10 @@ class EvalEvaluator(AllReturnValuesEvaluator): for ret_val in return_values: if ret_val.status and isinstance(ret_val.body, Concept) and ret_val.body.body: - context.log(self.verbose_log, f"Evaluating {ret_val.body}", who=self) + context.log(f"Evaluating {ret_val.body}", who=self) result.append(sheerka.ret(self.name, True, ret_val.body.body, parents=[ret_val, self.eval_requested])) elif ret_val.status and sheerka.isaset(context, ret_val.body): - context.log(self.verbose_log, f"Evaluating set {ret_val.body}", who=self) + context.log(f"Evaluating set {ret_val.body}", who=self) result.append(sheerka.ret( self.name, True, diff --git a/src/evaluators/LexerNodeEvaluator.py b/src/evaluators/LexerNodeEvaluator.py index 15c1e41..3589ca6 100644 --- a/src/evaluators/LexerNodeEvaluator.py +++ b/src/evaluators/LexerNodeEvaluator.py @@ -44,7 +44,7 @@ class LexerNodeEvaluator(OneReturnValueEvaluator): if not hasattr(nodes, "__iter__"): nodes = [nodes] - context.log(self.verbose_log, f"{nodes=}", self.name) + context.log(f"{nodes=}", self.name) for node in nodes: if isinstance(node, SourceCodeNode): diff --git a/src/evaluators/MutipleSameSuccessEvaluator.py b/src/evaluators/MutipleSameSuccessEvaluator.py index 358743b..ad1cc24 100644 --- a/src/evaluators/MutipleSameSuccessEvaluator.py +++ b/src/evaluators/MutipleSameSuccessEvaluator.py @@ -45,9 +45,9 @@ class MultipleSameSuccessEvaluator(AllReturnValuesEvaluator): def eval(self, context, return_values): sheerka = context.sheerka - context.log(self.verbose_log, f"{len(self.success)} successful return value(s)", who=self) + context.log(f"{len(self.success)} successful return value(s)", who=self) for s in self.success: - context.log(self.verbose_log, f"{s}", who=self) + context.log(f"{s}", who=self) if not core.builtin_helpers.is_same_success(sheerka, self.success): return None diff --git a/src/evaluators/OneErrorEvaluator.py b/src/evaluators/OneErrorEvaluator.py index 5c7354a..faa3ef1 100644 --- a/src/evaluators/OneErrorEvaluator.py +++ b/src/evaluators/OneErrorEvaluator.py @@ -35,8 +35,8 @@ class OneErrorEvaluator(AllReturnValuesEvaluator): return to_process and nb_evaluators_in_error == 1 def eval(self, context, return_values): - context.log(self.verbose_log, f"1 return value in error, {len(self.eaten)} item(s) eaten", who=self) - context.log(self.verbose_log, f"{self.return_value_in_error}", who=self) + context.log(f"1 return value in error, {len(self.eaten)} item(s) eaten", who=self) + context.log(f"{self.return_value_in_error}", who=self) sheerka = context.sheerka return sheerka.ret(self.name, False, self.return_value_in_error.value, parents=self.eaten) diff --git a/src/evaluators/OneSuccessEvaluator.py b/src/evaluators/OneSuccessEvaluator.py index c834008..53f33bb 100644 --- a/src/evaluators/OneSuccessEvaluator.py +++ b/src/evaluators/OneSuccessEvaluator.py @@ -37,8 +37,8 @@ class OneSuccessEvaluator(AllReturnValuesEvaluator): return to_process and nb_successful_evaluators == 1 def eval(self, context, return_values): - context.log(self.verbose_log, f"1 successful return value, {len(self.eaten)} item(s) eaten", who=self) - context.log(self.verbose_log, f"{self.successful_return_value}", who=self) + context.log(f"1 successful return value, {len(self.eaten)} item(s) eaten", who=self) + context.log(f"{self.successful_return_value}", who=self) sheerka = context.sheerka return sheerka.ret(self.name, True, self.successful_return_value.value, parents=self.eaten) diff --git a/src/evaluators/PythonEvaluator.py b/src/evaluators/PythonEvaluator.py index 7c705ad..72f2b11 100644 --- a/src/evaluators/PythonEvaluator.py +++ b/src/evaluators/PythonEvaluator.py @@ -31,35 +31,35 @@ class PythonEvaluator(OneReturnValueEvaluator): sheerka = context.sheerka node = return_value.value.value try: - context.log(self.verbose_log, f"Evaluating python node {node}.", self.name) + context.log(f"Evaluating python node {node}.", self.name) # Do not evaluate if the ast refers to a concept (leave it to ConceptEvaluator) if isinstance(node.ast_, ast.Expression) and isinstance(node.ast_.body, ast.Name): c = context.sheerka.get(node.ast_.body.id) if not context.sheerka.isinstance(c, BuiltinConcepts.UNKNOWN_CONCEPT): - context.log(self.verbose_log, "It's a simple concept. Not for me.", self.name) + context.log("It's a simple concept. Not for me.", self.name) not_for_me = context.sheerka.new(BuiltinConcepts.NOT_FOR_ME, body=node) return sheerka.ret(self.name, False, not_for_me, parents=[return_value]) # get locals my_globals = self.get_globals(context, node) my_locals = {} - context.log(self.verbose_log, f"globals={my_globals}", self.name) + context.log(f"globals={my_globals}", self.name) # eval if isinstance(node.ast_, ast.Expression): - context.log(self.verbose_log, "Evaluating using 'eval'.", self.name) + context.log("Evaluating using 'eval'.", self.name) compiled = compile(node.ast_, "", "eval") evaluated = eval(compiled, my_globals, my_locals) else: - context.log(self.verbose_log, "Evaluating using 'exec'.", self.name) + context.log("Evaluating using 'exec'.", self.name) evaluated = self.exec_with_return(node.ast_, my_globals, my_locals) - context.log(self.verbose_log, f"{evaluated=}", self.name) + context.log(f"{evaluated=}", self.name) return sheerka.ret(self.name, True, evaluated, parents=[return_value]) except Exception as error: - context.log_error(self.verbose_log, error, self.name) + context.log_error(error, self.name) error = sheerka.new(BuiltinConcepts.ERROR, body=error) return sheerka.ret(self.name, False, error, parents=[return_value]) @@ -74,8 +74,7 @@ class PythonEvaluator(OneReturnValueEvaluator): "Concept": core.concept.Concept } if context.obj: - context.log(self.verbose_log, - f"Concept '{context.obj}' is in context. Adding it and its properties to locals.", self.name) + context.log(f"Concept '{context.obj}' is in context. Adding it and its properties to locals.", self.name) for prop_name, prop_value in context.obj.props.items(): if isinstance(prop_value.value, Concept): @@ -90,10 +89,10 @@ class PythonEvaluator(OneReturnValueEvaluator): unreferenced_names_visitor.visit(node_concept) for name in unreferenced_names_visitor.names: - context.log(self.verbose_log, f"Resolving '{name}'.", self.name) + context.log(f"Resolving '{name}'.", self.name) if name in node.concepts: - context.log(self.verbose_log, f"Using value from node.", self.name) + context.log(f"Using value from node.", self.name) concept = node.concepts[name] return_concept = False @@ -101,20 +100,19 @@ class PythonEvaluator(OneReturnValueEvaluator): c_key, c_id, return_concept = self.resolve_name(name) if c_key in my_locals: - context.log(self.verbose_log, f"Using value from property.", self.name) + context.log(f"Using value from property.", self.name) continue - context.log(self.verbose_log, f"Instantiating new concept with {c_key=}, {c_id=}.", self.name) + context.log(f"Instantiating new concept with {c_key=}, {c_id=}.", self.name) new = context.sheerka.new concept = new((None, c_id)) if c_id else new(c_key) if context.sheerka.isinstance(concept, BuiltinConcepts.UNKNOWN_CONCEPT): - context.log(self.verbose_log, f"({c_key=}, {c_id=}) is not a concept. Skipping.", self.name) + context.log(f"({c_key=}, {c_id=}) is not a concept. Skipping.", self.name) continue - context.log(self.verbose_log, f"Evaluating '{concept}'", self.name) + context.log(f"Evaluating '{concept}'", self.name) with context.push(self.name, desc=f"Evaluating '{concept}'", obj=concept) as sub_context: - sub_context.log_new(self.verbose_log) - evaluated = context.sheerka.evaluate_concept(sub_context, concept, self.verbose_log) + evaluated = context.sheerka.evaluate_concept(sub_context, concept) sub_context.add_values(return_values=evaluated) if evaluated.key == concept.key: @@ -141,47 +139,7 @@ class PythonEvaluator(OneReturnValueEvaluator): return key, id_, use_concept else: return to_resolve, None, False - # - # if not to_resolve.startswith("__C__"): - # return to_resolve, None, False - # - # context.log(self.verbose_log, f"Resolving name '{to_resolve}'.", self.name) - # - # if len(to_resolve) >= 18 and to_resolve[:18] == "__C__USE_CONCEPT__": - # use_concept = True - # index = 18 - # else: - # use_concept = False - # index = 5 - # - # try: - # next_index = to_resolve.index("__", index) - # if next_index == index: - # context.log(self.verbose_log, f"Error: no key between '__'.", self.name) - # return None - # concept_key = to_resolve[index: next_index] - # except ValueError: - # context.log(self.verbose_log, f"Error: Missing trailing '__'.", self.name) - # return None - # - # if next_index == len(to_resolve) - 5: - # context.log(self.verbose_log, f"Recognized concept '{concept_key}'", self.name) - # return concept_key, None, use_concept - # - # index = next_index + 2 - # try: - # next_index = to_resolve.index("__", index) - # if next_index == index: - # context.log(self.verbose_log, f"Error: no id between '__'.", self.name) - # return None - # - # concept_id = to_resolve[index: next_index] - # except ValueError: - # context.log(self.verbose_log, f"Recognized concept '{concept_key}'.", self.name) - # return concept_key, None, use_concept - # - # context.log(self.verbose_log, f"Recognized concept '{concept_key}' (id='{concept_id}').", self.name) - # return concept_key, concept_id, use_concept + @staticmethod def expr_to_expression(expr): diff --git a/src/evaluators/TooManySuccessEvaluator.py b/src/evaluators/TooManySuccessEvaluator.py index b255e67..b4c235a 100644 --- a/src/evaluators/TooManySuccessEvaluator.py +++ b/src/evaluators/TooManySuccessEvaluator.py @@ -41,14 +41,13 @@ class TooManySuccessEvaluator(AllReturnValuesEvaluator): sheerka = context.sheerka if self.verbose_log.isEnabledFor(logging.DEBUG): for s in self.success: - context.log(self.verbose_log, s, self.name) - context.log(self.verbose_log, f"value={sheerka.value(s.value)}", self.name) + context.log(s, self.name) + context.log(f"value={sheerka.value(s.value)}", self.name) if not core.builtin_helpers.is_same_success(sheerka, self.success): - context.log(self.verbose_log, - f"Values are different. Raising {BuiltinConcepts.TOO_MANY_SUCCESS}.", self.name) + context.log(f"Values are different. Raising {BuiltinConcepts.TOO_MANY_SUCCESS}.", self.name) too_many_success = sheerka.new(BuiltinConcepts.TOO_MANY_SUCCESS, body=self.success) return sheerka.ret(self.name, False, too_many_success, parents=self.eaten) - context.log(self.verbose_log, f"Values are the same. Nothing to do.", self.name) + context.log(f"Values are the same. Nothing to do.", self.name) return None diff --git a/src/parsers/BaseParser.py b/src/parsers/BaseParser.py index 76df3d1..877d0ab 100644 --- a/src/parsers/BaseParser.py +++ b/src/parsers/BaseParser.py @@ -100,20 +100,28 @@ class BaseParser: if ret.status: value = context.return_value_to_str(ret) - context.log(self.log, f"Recognized '{source}' as {value}", self.name) + context.log(f"Recognized '{source}' as {value}", self.name) else: - context.log(self.log, f"Failed to recognize '{source}'", self.name) + context.log(f"Failed to recognize '{source}'", self.name) def log_multiple_results(self, context, source, list_of_ret): if not self.log.isEnabledFor(logging.DEBUG): return - context.log(self.log, f"Recognized '{source}' as multiple concepts", self.name) + context.log(f"Recognized '{source}' as multiple concepts", self.name) for r in list_of_ret: value = context.return_value_to_str(r) - context.log(self.log, f" Recognized '{value}'", self.name) + context.log(f" Recognized '{value}'", self.name) def get_return_value_body(self, sheerka, source, tree, try_parse): + """ + All parsers must return their result in a standard way + :param sheerka: + :param source: + :param tree: + :param try_parse: + :return: + """ if len(self.error_sink) == 1 and isinstance(self.error_sink[0], Concept): return self.error_sink[0] diff --git a/src/parsers/ConceptLexerParser.py b/src/parsers/ConceptLexerParser.py index ffe5df1..32db674 100644 --- a/src/parsers/ConceptLexerParser.py +++ b/src/parsers/ConceptLexerParser.py @@ -665,8 +665,9 @@ class ConceptLexerParser(BaseParser): self.sheerka = context.sheerka concepts_to_resolve = set() - # ## Gets the grammars for concept, concept_def in concepts_definitions.items(): + # ## Gets the grammars + context.log(f"Resolving grammar for '{concept}'", context.who) concept.init_key() # make sure that the key is initialized grammar = self.get_model(concept_def, concepts_to_resolve) self.concepts_grammars[concept] = grammar diff --git a/src/parsers/ConceptsWithConceptsParser.py b/src/parsers/ConceptsWithConceptsParser.py index 38a8a5a..7d8a3c6 100644 --- a/src/parsers/ConceptsWithConceptsParser.py +++ b/src/parsers/ConceptsWithConceptsParser.py @@ -56,7 +56,6 @@ class ConceptsWithConceptsParser(BaseParser): prop_name = list(concept.props.keys())[index] concept.compiled[prop_name] = node.concept context.log( - self.verbose_log, f"Setting property '{prop_name}='{node.concept}'.", self.name) index += 1 @@ -66,7 +65,6 @@ class ConceptsWithConceptsParser(BaseParser): value = sheerka.new(BuiltinConcepts.PARSER_RESULT, parser=self, source=node.source, body=node.node) concept.compiled[prop_name] = [context.sheerka.ret(self.name, True, value)] context.log( - self.verbose_log, f"Setting property '{prop_name}'='Python({node.source})'.", self.name) index += 1 diff --git a/src/parsers/DefaultParser.py b/src/parsers/DefaultParser.py index b09e367..7bac427 100644 --- a/src/parsers/DefaultParser.py +++ b/src/parsers/DefaultParser.py @@ -230,7 +230,7 @@ class DefaultParser(BaseParser): token = self.get_token() if token.value == Keywords.DEF: self.next_token() - self.context.log(self.verbose_log, "Keyword DEF found.", self.name) + self.context.log("Keyword DEF found.", self.name) return self.parse_def_concept(token) else: return self.parse_isa_concept() @@ -411,14 +411,13 @@ class DefaultParser(BaseParser): # ask the other parsers if they recognize the tokens with self.context.push(self.name, desc=f"Parsing {keyword}") as sub_context: - sub_context.log_new(self.verbose_log) to_parse = self.sheerka.ret( sub_context.who, True, self.sheerka.new(BuiltinConcepts.USER_INPUT, body=tokens)) steps = [BuiltinConcepts.PARSING] - parsed = self.sheerka.execute(sub_context, to_parse, steps, self.verbose_log) - parsing_result = core.builtin_helpers.expect_one(sub_context, parsed, self.verbose_log) + parsed = self.sheerka.execute(sub_context, to_parse, steps) + parsing_result = core.builtin_helpers.expect_one(sub_context, parsed) sub_context.add_values(return_values=parsing_result) if not parsing_result.status: diff --git a/src/parsers/ExactConceptParser.py b/src/parsers/ExactConceptParser.py index e1e4f53..f1cd108 100644 --- a/src/parsers/ExactConceptParser.py +++ b/src/parsers/ExactConceptParser.py @@ -24,17 +24,17 @@ class ExactConceptParser(BaseParser): :return: """ - context.log(self.verbose_log, f"Parsing '{text}'", self.name) + context.log(f"Parsing '{text}'", self.name) res = [] sheerka = context.sheerka try: words = self.get_words(text) except LexerError as e: - context.log(self.verbose_log, f"Error found in tokenizer {e}", self.name) + context.log(f"Error found in tokenizer {e}", self.name) return sheerka.ret(self.name, False, sheerka.new(BuiltinConcepts.ERROR, body=e)) if len(words) > self.MAX_WORDS_SIZE: - context.log(self.verbose_log, f"Max words reached. Stopping.", self.name) + context.log(f"Max words reached. Stopping.", self.name) return sheerka.ret(self.name, False, sheerka.new(BuiltinConcepts.CONCEPT_TOO_LONG, body=text)) recognized = False @@ -50,7 +50,7 @@ class ExactConceptParser(BaseParser): concepts = result if isinstance(result, list) else [result] for concept in concepts: - context.log(self.verbose_log, f"Recognized concept {concept}.", self.name) + context.log(f"Recognized concept {concept}.", self.name) # update the properties if needed for i, token in enumerate(combination): if token.startswith(VARIABLE_PREFIX): @@ -59,7 +59,6 @@ class ExactConceptParser(BaseParser): if self.verbose_log.isEnabledFor(logging.DEBUG): prop_name = list(concept.props.keys())[index] context.log( - self.verbose_log, f"Added property {index}: {prop_name}='{words[i]}'.", self.name) diff --git a/tests/core/test_SheerkaEvaluateConcept.py b/tests/core/test_SheerkaEvaluateConcept.py index 7d480fb..9d1b54b 100644 --- a/tests/core/test_SheerkaEvaluateConcept.py +++ b/tests/core/test_SheerkaEvaluateConcept.py @@ -302,7 +302,7 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka): sheerka.add_in_cache(Concept(name="a", body="'concept_a'")) sheerka.add_in_cache(Concept(name="b", body="'concept_b'")) - concept = Concept("foo", body="a + b").def_prop("a", "'prop_a'") + concept = Concept("foo", body="a + b").def_prop("a", "'prop_a'").init_key() evaluated = sheerka.evaluate_concept(self.get_context(sheerka), concept) assert evaluated.key == concept.key assert evaluated.body == 'prop_aconcept_b' diff --git a/tests/evaluators/test_AddConceptInSetEvaluator.py b/tests/evaluators/test_AddConceptInSetEvaluator.py index b6ebbc2..9b0d0e0 100644 --- a/tests/evaluators/test_AddConceptInSetEvaluator.py +++ b/tests/evaluators/test_AddConceptInSetEvaluator.py @@ -15,7 +15,7 @@ def get_ret_val(concept_name, concept_set_name): return ReturnValueConcept("some_name", True, ParserResultConcept(value=IsaConceptNode([], n1, n2))) -class TestAssConceptInSetEvaluator(TestUsingMemoryBasedSheerka): +class TestAddConceptInSetEvaluator(TestUsingMemoryBasedSheerka): @pytest.mark.parametrize("ret_val, expected", [ (ReturnValueConcept("some_name", True, ParserResultConcept(value=IsaConceptNode([]))), True), @@ -53,12 +53,10 @@ class TestAssConceptInSetEvaluator(TestUsingMemoryBasedSheerka): def test_i_can_add_concept_to_a_set_of_concept(self): context = self.get_context() foo = Concept("foo") - context.sheerka.set_id_if_needed(foo, False) - context.sheerka.add_in_cache(foo) + context.sheerka.create_new_concept(context, foo) bar = Concept("bar") - context.sheerka.set_id_if_needed(bar, False) - context.sheerka.add_in_cache(bar) + context.sheerka.create_new_concept(context, bar) ret_val = get_ret_val("foo", "bar") res = AddConceptInSetEvaluator().eval(context, ret_val) @@ -69,12 +67,10 @@ class TestAssConceptInSetEvaluator(TestUsingMemoryBasedSheerka): def test_i_can_add_concept_with_a_body_to_a_set_of_concept(self): context = self.get_context() foo = Concept("foo", body="1") - context.sheerka.set_id_if_needed(foo, False) - context.sheerka.add_in_cache(foo) + context.sheerka.create_new_concept(context, foo) bar = Concept("bar") - context.sheerka.set_id_if_needed(bar, False) - context.sheerka.add_in_cache(bar) + context.sheerka.create_new_concept(context, bar) ret_val = get_ret_val("foo", "bar") res = AddConceptInSetEvaluator().eval(context, ret_val) @@ -85,12 +81,10 @@ class TestAssConceptInSetEvaluator(TestUsingMemoryBasedSheerka): def test_i_cannot_add_the_same_concept_twice(self): context = self.get_context() foo = Concept("foo") - context.sheerka.set_id_if_needed(foo, False) - context.sheerka.add_in_cache(foo) + context.sheerka.create_new_concept(context, foo) bar = Concept("bar") - context.sheerka.set_id_if_needed(bar, False) - context.sheerka.add_in_cache(bar) + context.sheerka.create_new_concept(context, bar) ret_val = get_ret_val("foo", "bar") AddConceptInSetEvaluator().eval(context, ret_val) @@ -98,5 +92,5 @@ class TestAssConceptInSetEvaluator(TestUsingMemoryBasedSheerka): assert not res.status assert context.sheerka.isinstance(res.value, BuiltinConcepts.CONCEPT_ALREADY_IN_SET) - assert res.value.concept == foo - assert res.value.concept_set == bar + assert res.value.concept.key == foo.key + assert res.value.concept_set.key == bar.key