Added basic implentation for where

This commit is contained in:
2020-02-05 18:47:20 +01:00
parent a5a721094b
commit afc1e22949
35 changed files with 864 additions and 320 deletions
@@ -45,7 +45,7 @@ class SheerkaCreateNewConcept:
# add the BNF if known
if concept.bnf:
concepts_definitions = self.sheerka.get_concept_definition()
concepts_definitions = self.sheerka.get_concepts_definitions(context)
concepts_definitions[concept] = concept.bnf
# check if it's a valid BNF or whether it breaks the known rules
@@ -61,22 +61,26 @@ class SheerkaCreateNewConcept:
# save the new concept in sdp
try:
# TODO : needs to make these calls atomic (or at least one single call)
# save the new concept
self.sheerka.sdp.add(
context.event.get_digest(),
self.sheerka.CONCEPTS_ENTRY,
concept,
use_ref=True)
# save it by id
self.sheerka.sdp.add(
context.event.get_digest(),
self.sheerka.CONCEPTS_BY_ID_ENTRY,
{concept.id: concept.get_digest()},
is_ref=True)
# update the definition table
if concepts_definitions is not None:
self.sheerka.sdp.set(
context.event.get_digest(),
self.sheerka.CONCEPTS_DEFINITIONS_ENTRY,
concepts_definitions,
concept_lexer_parser.encode_grammar(init_ret_value.body),
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)
return self.sheerka.ret(
@@ -94,6 +98,3 @@ class SheerkaCreateNewConcept:
# process the return in needed
ret = self.sheerka.ret(self.logger_name, True, self.sheerka.new(BuiltinConcepts.NEW_CONCEPT, body=concept))
return ret
+14
View File
@@ -1,5 +1,14 @@
from core.builtin_concepts import BuiltinConcepts
from core.concept import Concept
from sdp.sheerkaDataProvider import SheerkaDataProvider
import pprint
import os
def get_pp():
rows, columns = os.popen('stty size', 'r').read().split()
pp = pprint.PrettyPrinter(width=columns, compact=True)
return pp
class SheerkaDump:
@@ -71,3 +80,8 @@ class SheerkaDump:
break
page_count += 1
def dump_state(self):
snapshot = self.sheerka.sdp.get_snapshot(SheerkaDataProvider.HeadFile)
state = self.sheerka.sdp.load_state(snapshot)
self.sheerka.log.info(get_pp().pformat(state.data))
@@ -147,9 +147,6 @@ class SheerkaEvaluateConcept:
if concept.metadata.is_evaluated:
return concept
# WHERE condition should already be validated by the parser.
# It's a mandatory condition for the concept before it can be recognized
#
# TODO : Validate the PRE condition
#
@@ -157,8 +154,8 @@ class SheerkaEvaluateConcept:
self.initialize_concept_asts(context, concept, logger)
# to make sure of the order, it don't use ConceptParts.get_parts()
# props must be evaluated first
all_metadata_to_eval = ["props", "where", "pre", "post", "body"]
# props must be evaluated first, body must be evaluated before where
all_metadata_to_eval = ["pre", "post", "props", "body", "where"]
for metadata_to_eval in all_metadata_to_eval:
if metadata_to_eval == "props":
@@ -186,6 +183,12 @@ class SheerkaEvaluateConcept:
else:
concept.values[part_key] = resolved
# validate where clause
if concept.metadata.where is not None:
where_value = concept.values[ConceptParts.WHERE]
if not (where_value is None or self.sheerka.value(where_value) is True):
return self.sheerka.new(BuiltinConcepts.WHERE_CLAUSE_FAILED, body=concept)
#
# TODO : Validate the POST condition
#
@@ -19,7 +19,7 @@ class History:
return msg
def __repr__(self):
return f"event={self.event!r}, status={self.status}, result={self.result}"
return f"History(event={self.event!r}, status={self.status}, result={self.result})"
def __eq__(self, other):
if id(self) == id(other):
@@ -38,6 +38,21 @@ class SheerkaSetsManager:
context.log_error(logger, "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):
"""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)
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]
try:
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)
return self.sheerka.ret(self.logger_name, False, ErrorConcept(error), error.args[0])
def get_set_elements(self, concept):
"""
Concept is supposed to be a set
+26 -9
View File
@@ -22,6 +22,7 @@ import logging
# BuiltinConcepts.AFTER_EVALUATION]
CONCEPT_LEXER_PARSER_CLASS = "parsers.ConceptLexerParser.ConceptLexerParser"
BNF_PARSER_CLASS = "parsers.BnfParser.BnfParser"
CONCEPTS_FILE = "_concepts.txt"
@@ -52,7 +53,7 @@ class Sheerka(Concept):
# cache for concept definitions,
# Primarily used for unit test that does not have access to sdp
self.concepts_definition_cache = {}
self.concepts_definitions_cache = {}
#
# cache for concepts grammars
@@ -187,7 +188,8 @@ class Sheerka(Concept):
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)
# definitions = self.sdp.get_safe(self.CONCEPTS_DEFINITIONS_ENTRY, load_origin=False)
definitions = self.get_concepts_definitions(execution_context)
if definitions is None:
self.init_log.debug("No BNF defined")
@@ -389,14 +391,26 @@ class Sheerka(Concept):
return result or self._get_unknown(('id', concept_id))
def get_concept_definition(self):
if self.concepts_definition_cache:
return self.concepts_definition_cache
def get_concepts_definitions(self, context):
if self.concepts_definitions_cache:
return self.concepts_definitions_cache
self.concepts_definition_cache = self.sdp.get_safe(
encoded = self.sdp.get_safe(
self.CONCEPTS_DEFINITIONS_ENTRY,
load_origin=False) or {}
return self.concepts_definition_cache
self.concepts_definitions_cache = {}
bnf_parser = self.parsers[BNF_PARSER_CLASS]()
for k, v in encoded.items():
key, id_ = core.utils.unstr_concept(k)
concept = self.new((key, id_))
rule_result = bnf_parser.parse(context, v)
if rule_result.status:
self.concepts_definitions_cache[concept] = rule_result.value.value
else:
self.log.error(f"Failed to load bnf rule for concept {key}")
return self.concepts_definitions_cache
def new(self, concept_key, **kwargs):
"""
@@ -411,7 +425,7 @@ class Sheerka(Concept):
else:
concept_id = None
template = self.get(concept_key, concept_id)
template = self.get_by_id(concept_id) if not concept_key else self.get(concept_key, concept_id)
# manage concept not found
if self.isinstance(template, BuiltinConcepts.UNKNOWN_CONCEPT) and \
@@ -579,7 +593,10 @@ class Sheerka(Concept):
self.during_restore = True
with open(CONCEPTS_FILE, "r") as f:
for line in f.readlines():
self.log.info(line.strip())
line = line.strip()
if line == "" or line.startswith("#"):
continue
self.log.info(line)
self.evaluate_user_input(line)
self.during_restore = False
except IOError: