Working on #98 : Persist attribute value when global_truth is set to true

This commit is contained in:
2021-08-03 11:26:57 +02:00
parent e69745adc8
commit c798c2c570
22 changed files with 496 additions and 106 deletions
+9 -10
View File
@@ -13,7 +13,7 @@ PROPERTIES_FOR_DIGEST = ("name", "key",
"definition", "definition_type",
"is_builtin", "is_unique",
"where", "pre", "post", "body", "ret",
"desc", "props", "variables")
"desc", "props", "variables", "parameters")
PROPERTIES_TO_SERIALIZE = PROPERTIES_FOR_DIGEST + tuple(["id"])
PROPERTIES_FOR_NEW = ("where", "pre", "post", "body", "desc")
VARIABLE_PREFIX = "__var__"
@@ -73,6 +73,7 @@ class ConceptMetadata:
id: str # unique identifier for a concept. The id will never be modified (but the key can)
props: dict # hashmap of properties, values
variables: list # list of concept variables(tuple), with their default values
parameters: list # list of variables that are part of the name of the concept
full_serialization: bool = False # If True, the full object will be serialized, rather than just the diff
all_attributes: List[str] = None # list of instance attributes
@@ -163,7 +164,8 @@ class Concept:
desc,
id,
props or {},
variables or []
variables or [],
[]
)
self._metadata = metadata
@@ -241,8 +243,8 @@ class Concept:
# It's just to control what I put in the default value of properties
# You can allow more type if it's REALLY needed.
# - str are for standard definition
# - list of concepts is used by ISA
assert default_value is None or isinstance(default_value, str)
# - Concept when properly set
assert default_value is None or isinstance(default_value, (str, Concept))
self._metadata.variables.append((var_name, default_value))
@@ -330,7 +332,6 @@ class Concept:
if token.value in variables:
key += VARIABLE_PREFIX + str(variables.index(token.value))
else:
# value = token.value[1:-1] if token.type == TokenKind.STRING else token.value
key += token.value.value if token.type == TokenKind.KEYWORD else token.value
first = False
@@ -421,6 +422,8 @@ class Concept:
self.def_var(name, value)
elif prop == "props":
self._metadata.props = core.utils.sheerka_deepcopy(other.get_metadata().props)
elif prop == "parameters":
self._metadata.parameters = other.get_metadata().parameters.copy()
else:
setattr(self._metadata, prop, getattr(other.get_metadata(), prop))
@@ -522,11 +525,7 @@ class Concept:
return NotInit
def values(self):
try:
values = {k: getattr(self, k) for k in get_concept_attrs(self)}
except AttributeError as err:
print(f"{err}, {self=}")
raise err
values = {k: getattr(self, k) if hasattr(self, k) else NotInit for k in get_concept_attrs(self)}
for prop_name in AllConceptParts:
try:
+10 -2
View File
@@ -21,6 +21,9 @@ from sdp.sheerkaDataProvider import Event
BASE_NODE_PARSER_CLASS = "parsers.BaseNodeParser.BaseNodeParser"
EXIT_COMMANDS = ("quit", "exit", "bye")
CONTEXT_HINT_COMMANDS = (("global_truth(", "global_truth"),
("question(", "question"),
("eval", "eval"))
EXECUTE_STEPS = [
BuiltinConcepts.BEFORE_PARSING,
BuiltinConcepts.PARSING,
@@ -493,7 +496,7 @@ class Sheerka(Concept):
c.get_hints().recognized_by = rec_by
c.get_hints().is_instance = is_inst
if is_eval is None:
c.get_hints().is_evaluated = len(c.get_metadata().variables) > 0
c.get_hints().is_evaluated = len(c.get_metadata().parameters) > 0
else:
c.get_hints().is_evaluated = is_eval
return c
@@ -581,7 +584,12 @@ class Sheerka(Concept):
# otherwise, create another instance
concept = self.builtin_cache[key]() if key in self.builtin_cache else Concept()
concept.update_from(template, update_value=False)
# concept.freeze_definition_hash()
# set the default values is needed
for var_name, var_value in concept.get_metadata().variables:
if isinstance(var_value, Concept):
concept.set_value(var_name, var_value)
# Note that the concept is not considered as evaluated. The body may need to be computed
if len(kwargs) == 0:
return concept
@@ -295,7 +295,7 @@ class SheerkaConceptManager(BaseService):
# 'props' : {<key>: <value>} of properties to add/update,
# 'variables': {<key>: <value>} of variables to add/update,
# }
# if the <key> already exists, the entry is updated, otherwise a new value is created
# for variables, if the <key> already exists, the entry is updated, otherwise a new value is created
# for props, if the <key> already exists, a new entry is added to the set
#
# to_remove = {
@@ -391,9 +391,10 @@ class SheerkaConceptManager(BaseService):
sheerka.publish(context, EVENT_CONCEPT_DELETED, concept)
return sheerka.ret(self.NAME, True, sheerka.new(BuiltinConcepts.SUCCESS))
def set_attr(self, concept, attribute, value):
def set_attr(self, context, concept, attribute, value):
"""
Modifies an attribute of a concept (concept.values)
:param context:
:param concept:
:param attribute:
:param value:
@@ -402,8 +403,16 @@ class SheerkaConceptManager(BaseService):
ensure_concept(concept)
attr = attribute.str_id if isinstance(attribute, Concept) else attribute
old_value = concept.get_value(attr)
if (old_value := concept.get_value(attr)) is not NotInit:
if context.in_context(BuiltinConcepts.EVAL_GLOBAL_TRUTH_REQUESTED):
old_value = self.sheerka.get_by_id(concept.id).get_value(attr)
else:
old_value = concept.get_value(attr)
# Caution, creating a list when a set_attr is called for the second time is not always
# what is expected
if old_value is not NotInit:
if old_value == value:
return self.sheerka.ret(self.NAME, True, self.sheerka.new(BuiltinConcepts.SUCCESS))
@@ -413,6 +422,13 @@ class SheerkaConceptManager(BaseService):
else:
value = [old_value, value]
if context.in_context(BuiltinConcepts.EVAL_GLOBAL_TRUTH_REQUESTED):
to_add = {"variables": {attr: value}}
res = self.sheerka.modify_concept(context, concept, to_add, modify_source=True)
concept.set_value(attr, value)
return res
else:
concept.set_value(attr, value)
return self.sheerka.ret(self.NAME, True, self.sheerka.new(BuiltinConcepts.SUCCESS))
@@ -857,6 +873,7 @@ class SheerkaConceptManager(BaseService):
concept.set_bnf(None)
ensure_bnf(context, concept)
self.recompute_concept_parameters(context, concept)
concept.init_key()
return
@@ -1252,3 +1269,27 @@ class SheerkaConceptManager(BaseService):
# update the compiled regex
self.compiled_concepts_by_regex.clear()
self.compiled_concepts_by_regex.extend(compiled_by_first_regex)
@staticmethod
def recompute_concept_parameters(context, concept):
concept.get_metadata().parameters.clear()
if concept.get_metadata().definition_type == DEFINITION_TYPE_DEF:
tokens = list(Tokenizer(concept.get_metadata().definition, yield_eof=False))
else:
tokens = list(Tokenizer(concept.get_metadata().name, yield_eof=False))
# all variables that appear in the name are concept parameters
if len(tokens) > 0:
variables = [p[0] for p in concept.get_metadata().variables]
for token in [t for t in tokens if t.value in variables]:
concept.get_metadata().parameters.append(token.value)
# for bnf concept, use the visitor to extract parameters
if concept.get_bnf():
from evaluators.DefConceptEvaluator import ConceptOrRuleVariableVisitor, ParameterVariable
visitor = ConceptOrRuleVariableVisitor(context)
visitor.visit(concept.get_bnf())
for variable in [v for v in visitor.variables if isinstance(v, ParameterVariable)]:
if variable.name not in concept.get_metadata().parameters:
concept.get_metadata().parameters.append(variable.name)
@@ -432,9 +432,12 @@ class SheerkaEvaluateConcept(BaseService):
if default_value is None:
continue
if not isinstance(default_value, str):
raise Exception("Invalid concept init. variable metadata must be a string")
if not isinstance(default_value, (str, Concept)):
raise Exception("Invalid concept init. variable metadata must be a string (or a concept)")
if isinstance(default_value, Concept):
concept.get_compiled()[var_name] = default_value.copy()
else:
concept.get_compiled()[var_name] = self.get_asts(context,
self.NAME,
default_value,
@@ -740,8 +743,6 @@ class SheerkaEvaluateConcept(BaseService):
# TODO : Validate the POST condition
#
concept.init_key() # Necessary for old unit tests. To remove someday
if ConceptParts.BODY in all_metadata_to_eval and not failed_to_evaluate_body:
concept.get_hints().is_evaluated = True
+56 -8
View File
@@ -74,27 +74,63 @@ class CertainVariable(ConceptEvaluatorVariable):
return hash(("PossibleVariable", self.name))
@dataclass(eq=True, frozen=True)
class ParameterVariable(ConceptEvaluatorVariable):
"""
A parameter variable (for BNF concepts) are variables that are mandatory for the resolution of the concept
example:
def concept plus from bnf number=n1 plus number=n2 # n1 and n2 are parameters
def concept plus from bnf number plus number # number is a parameter
def concept inc from bnf (one|two)=n1 plus 1 # n1 is a parameter
def concept inc from bnf (one|two) plus 1 # (one|two) is a parameter (but with no associated variable name)
"""
is_a_variable: bool # True is the parameter has an associated variable name
def __hash__(self):
return hash(("ParameterVariable", self.name, self.is_a_variable))
class ConceptOrRuleVariableVisitor(ParsingExpressionVisitor):
"""
Gets the concepts referenced by BNF
If a rule_name is given, it will also be considered as a potential property
"""
def __init__(self):
def __init__(self, context):
super().__init__()
self.context = context
self.variables = []
self.counter = 1
def _get_parameter_name(self, node, prefix):
if not node.rule_name:
name = f"{prefix}{self.counter}"
self.counter += 1
is_a_variable = False
else:
name = node.rule_name
is_a_variable = True
return name, is_a_variable
def visit_ConceptExpression(self, node):
if node.rule_name:
self.variables.append(CertainVariable(node.rule_name))
elif isinstance(node.concept, Concept):
self.variables.append(CertainVariable(node.concept.name))
if isinstance(node.concept, Concept):
if self.context.sheerka.isaset(self.context, node.concept):
parameter_name, is_a_variable = self._get_parameter_name(node, "__ConceptExpression__")
self.variables.append(ParameterVariable(parameter_name, is_a_variable))
else:
self.variables.append(CertainVariable(node.concept))
self.variables.append(CertainVariable(node.rule_name or node.concept.name))
else:
self.variables.append(CertainVariable(node.rule_name or node.concept))
def visit_VariableExpression(self, node):
self.variables.append(MandatoryVariable(node.rule_name))
def visit_OrderedChoice(self, node):
parameter_name, is_a_variable = self._get_parameter_name(node, "__OrderedChoice__")
self.variables.append(ParameterVariable(parameter_name, is_a_variable))
self.visit_children(node)
def visit_all(self, node):
if node.rule_name:
self.variables.append(CertainVariable(node.rule_name))
@@ -127,7 +163,8 @@ class DefConceptEvaluator(OneReturnValueEvaluator):
# validate the node
variables_found = set()
mandatory_variables = set() # these variable MUST have a match in the name (if the name is not None)
certain_variables = []
parameter_variables = [] # BNF variables known as concept parameter. Use a list to keep the order
certain_variables = [] # names that we know for sure that there are variables
skip_variables_resolution = False
concept = Concept(str(def_concept_node.name))
@@ -164,6 +201,12 @@ class DefConceptEvaluator(OneReturnValueEvaluator):
# try to find what can be a property
for p in self.get_variables(context, part_ret_val, name_to_use):
if isinstance(p, ParameterVariable):
parameter_variables.append(p.name)
if p.is_a_variable:
variables_found.add(p.name)
certain_variables.append(p.name)
else:
variables_found.add(p.name)
if isinstance(p, MandatoryVariable):
mandatory_variables.add(p.name)
@@ -174,6 +217,7 @@ class DefConceptEvaluator(OneReturnValueEvaluator):
for name_part in [name_part for name_part in name_to_use if str(name_part).isalnum()]:
if name_part in variables_found:
concept.def_var(name_part, None)
concept.get_metadata().parameters.append(name_part)
# check that all mandatory variables are defined in the name
# KSI: 2021-02-17
@@ -190,6 +234,10 @@ class DefConceptEvaluator(OneReturnValueEvaluator):
if p not in concept.values():
concept.def_var(p, None)
for p in parameter_variables:
if p not in concept.get_metadata().parameters:
concept.get_metadata().parameters.append(p)
# initialize the key
key_source = def_concept_node.definition.tokens if \
def_concept_node.definition_type == DEFINITION_TYPE_DEF else \
@@ -251,7 +299,7 @@ class DefConceptEvaluator(OneReturnValueEvaluator):
# case of BNF
#
if isinstance(ret_value.value, ParserResultConcept) and isinstance(ret_value.value.value, ParsingExpression):
visitor = ConceptOrRuleVariableVisitor()
visitor = ConceptOrRuleVariableVisitor(context)
visitor.visit(ret_value.value.value)
debugger.debug_var("names", visitor.variables, hint="from BNF")
return visitor.variables
+2 -2
View File
@@ -11,10 +11,10 @@ class BnfDefinitionParser(BaseParser):
"""
Parser used to transform literal into ParsingExpression
example :
a | b, c -> Sequence(OrderedChoice(a, b) ,c)
a | b c -> Sequence(OrderedChoice(a, b), c)
'|' (pipe) is used for OrderedChoice
',' (comma) is used for Sequence
' ' space is used for Sequence
'?' (question mark) is used for Optional
'*' (star) is used for ZeroOrMore
'+' (plus) is used for OneOrMore
+3
View File
@@ -1165,6 +1165,9 @@ class ParsingExpressionVisitor:
if hasattr(self, "visit_all"):
self.visit_all(parsing_expression)
self.visit_children(parsing_expression)
def visit_children(self, parsing_expression):
for node in self.get_nodes(parsing_expression):
if isinstance(node, Concept):
res = self.visit(ConceptExpression(node.key or node.name))
+1 -1
View File
@@ -231,7 +231,7 @@ class SequenceNodeParser(BaseNodeParser):
:param concept:
:return:
"""
return len(concept.get_metadata().variables) == 0 \
return len(concept.get_metadata().parameters) == 0 \
and concept.get_metadata().definition_type != DEFINITION_TYPE_BNF
def get_concepts(self, token, to_keep, custom=None, to_map=None, strip_quotes=False):
+13 -6
View File
@@ -199,7 +199,7 @@ class SyaConceptParserHelper:
self.expected = temp
self.eat_token(first_keyword_found) # remove the first token
self.tokens.append(first_keyword_found)
self.tokens.append(first_keyword_found) # and add it to the list of tokens eaten
def is_matched(self):
return len(self.expected) == 0
@@ -554,7 +554,7 @@ class InFixToPostFix:
def nb_expected_parameters(expected):
"""
Count the number of successive variables that are expected
Count the number of successive variables that are still expected
:param expected:
:return:
"""
@@ -1228,10 +1228,10 @@ class SyaNodeParser(BaseNodeParser):
:param concept:
:return:
"""
# We only concepts that has parameter (refuse atoms)
# We only considers concepts that has parameter variables (refuse atoms)
# Bnf definitions are not supposed to be managed by this parser either
return len(
concept.get_metadata().variables) > 0 and concept.get_metadata().definition_type != DEFINITION_TYPE_BNF
return (concept.get_metadata().definition_type != DEFINITION_TYPE_BNF and
len(concept.get_metadata().parameters) > 0)
def infix_to_postfix(self, context, parser_input: ParserInput):
"""
@@ -1368,6 +1368,14 @@ class SyaNodeParser(BaseNodeParser):
concept = sheerka.new_from_template(item.concept, item.concept.key)
concept_metadata = []
for param_index in reversed(range(len(concept.get_metadata().variables))):
param_name = concept.get_metadata().variables[param_index][0]
if param_name not in concept.get_metadata().parameters:
# This is not a real concept parameter, but a concept variable
# just copy its default value
concept_metadata.append(concept.get_metadata().variables[param_index])
continue
inner_item = self.postfix_to_item(sheerka, postfixed)
if inner_item.start < start:
start = inner_item.start
@@ -1376,7 +1384,6 @@ class SyaNodeParser(BaseNodeParser):
has_unrecognized |= isinstance(inner_item, (UnrecognizedTokensNode, SourceCodeWithConceptNode)) or \
hasattr(inner_item, "has_unrecognized") and inner_item.has_unrecognized
param_name = concept.get_metadata().variables[param_index][0]
param_value = inner_item.concept if hasattr(inner_item, "concept") else \
[inner_item.return_value] if isinstance(inner_item, SourceCodeNode) else \
inner_item
+6 -2
View File
@@ -7,7 +7,7 @@ from dataclasses import dataclass
from prompt_toolkit.completion import Completer, Completion
from core.concept import Concept
from core.sheerka.Sheerka import EXIT_COMMANDS
from core.sheerka.Sheerka import EXIT_COMMANDS, CONTEXT_HINT_COMMANDS
from core.sheerka.services.SheerkaConceptManager import SheerkaConceptManager
from core.sheerka.services.SheerkaFunctionsParametersHistory import SheerkaFunctionsParametersHistory
from core.tokenizer import Tokenizer, TokenKind, LexerError
@@ -154,6 +154,9 @@ class SheerkaPromptCompleter(Completer):
"builtin",
["context"]))
for name, display in CONTEXT_HINT_COMMANDS:
self.builtins.append(CompletionDesc(name, display, "context"))
self.exit_commands = [CompletionDesc(c, c, "command") for c in EXIT_COMMANDS]
self.globals = {k: v.method for k, v in self.sheerka.sheerka_methods.items()}
@@ -313,11 +316,12 @@ class SheerkaPromptCompleter(Completer):
function_name = name + "("
signature = inspect.signature(function)
params_count = len([p for p in signature.parameters if p not in skip_params])
if params_count == 0:
function_name += ")"
return CompletionDesc(function_name, name, meta_display)
@staticmethod
def inside_function(text, pos):
bracket_count = 0
+8
View File
@@ -6,6 +6,7 @@ from core.concept import Concept, DEFINITION_TYPE_BNF, DEFINITION_TYPE_DEF, free
from core.rule import Rule, ACTION_TYPE_PRINT, ACTION_TYPE_EXEC
from core.sheerka.ExecutionContext import ExecutionContext
from core.sheerka.Sheerka import Sheerka
from core.sheerka.services.SheerkaConceptManager import SheerkaConceptManager
from core.sheerka.services.SheerkaRuleManager import SheerkaRuleManager
from parsers.BnfDefinitionParser import BnfDefinitionParser
from parsers.BnfNodeParser import StrMatch
@@ -47,6 +48,7 @@ class InitTestHelper:
raise Exception(f"Error in bnf definition '{c.get_metadata().definition}'",
self.sheerka.get_errors(self.context, res))
self._update_concept_parameters(c)
if create_new:
self.sheerka.create_new_concept(self.context, c)
else:
@@ -99,6 +101,12 @@ class InitTestHelper:
return self
def _update_concept_parameters(self, concept):
if concept.get_metadata().parameters:
return
SheerkaConceptManager.recompute_concept_parameters(self.context, concept)
class BaseTest:
def get_sheerka(self, **kwargs) -> Sheerka:
+113 -25
View File
@@ -4,7 +4,7 @@ from cache.CacheManager import ConceptNotFound
from core.builtin_concepts import BuiltinConcepts
from core.builtin_helpers import ensure_bnf
from core.concept import PROPERTIES_TO_SERIALIZE, Concept, DEFINITION_TYPE_DEF, get_concept_attrs, \
DEFINITION_TYPE_BNF
DEFINITION_TYPE_BNF, ConceptParts
from core.global_symbols import NotInit, NotFound, SyaAssociativity, CONCEPT_COMPARISON_CONTEXT
from core.sheerka.services.SheerkaConceptManager import SheerkaConceptManager, NoModificationFound, ForbiddenAttribute, \
UnknownAttribute, CannotRemoveMeta, ValueNotFound, ConceptIsReferenced, NoFirstTokenError
@@ -494,13 +494,13 @@ class TestSheerkaConceptManager(TestUsingMemoryBasedSheerka):
to_add = {"meta": {"name": "b bar c d"},
"variables": {"c": None, "d": None}}
to_remove = {"variables": ["a"]}
res = sheerka.modify_concept(context, foo, to_add, to_remove)
res = sheerka.modify_concept(context, foo, to_add)
new_concept = res.body.body
assert res.status
assert new_concept.key == "__var__0 bar __var__1 __var__2"
assert new_concept.key == "__var__1 bar __var__2 __var__3"
assert new_concept.get_metadata().parameters == ["b", "c", "d"]
assert new_concept.get_metadata().variables == [("a", None), ("b", None), ("c", None), ("d", None)]
def test_key_is_modified_when_modifying_the_definition(self):
sheerka, context, foo = self.init_concepts(
@@ -790,13 +790,101 @@ class TestSheerkaConceptManager(TestUsingMemoryBasedSheerka):
prop = Concept("property")
bar = Concept("bar")
res = sheerka.set_attr(foo, prop, bar)
res = sheerka.set_attr(context, foo, prop, bar)
assert res.status
assert sheerka.isinstance(res.body, BuiltinConcepts.SUCCESS)
assert sheerka.get_attr(foo, prop) == bar
def test_i_setting_twice_the_same_property_creates_a_list(self):
def test_i_can_get_and_set_attribute_when_global_truth_is_set(self):
sheerka, context, foo, adjective, color, red, brightness, dark = self.init_test(cache_only=False).with_concepts(
"foo",
"adjective",
"color",
"red",
"brightness",
"dark",
create_new=True).unpack()
service = sheerka.services[SheerkaConceptManager.NAME]
global_truth_context = self.get_context(sheerka, global_truth=True)
color_instance = sheerka.new("color", body=sheerka.new("red"))
sheerka.set_attr(context, color_instance, brightness, sheerka.new("dark"))
sheerka.set_isa(context, color_instance, sheerka.new(adjective))
adjective_instance = sheerka.new("adjective")
adjective_instance.set_value(ConceptParts.BODY, color_instance)
foo_instance = sheerka.new("foo")
res = sheerka.set_attr(global_truth_context, foo_instance, sheerka.new("adjective"), adjective_instance)
assert res.status
assert sheerka.isinstance(res.body, BuiltinConcepts.NEW_CONCEPT)
# foo.adjective is modified
resolved_adjective = sheerka.get_attr(foo_instance, sheerka.new("adjective"))
assert sheerka.isinstance(resolved_adjective, "adjective")
resolved_color = resolved_adjective.body
assert sheerka.isinstance(resolved_color, "color")
assert sheerka.isa(resolved_color, adjective)
assert sheerka.get_attr(resolved_color, brightness) == dark
assert resolved_color.body == red
# foo default variable value is modified
adjective_from_default_var = foo_instance.get_metadata().variables[0][1]
assert sheerka.isinstance(adjective_from_default_var, "adjective")
color_from_default_var = resolved_adjective.body
assert sheerka.isinstance(color_from_default_var, "color")
assert sheerka.isa(color_from_default_var, adjective)
assert sheerka.get_attr(color_from_default_var, brightness) == dark
assert color_from_default_var.body == red
# new instance are update
new_instance = sheerka.new("foo")
resolved_adjective = sheerka.get_attr(new_instance, sheerka.new("adjective"))
assert sheerka.isinstance(resolved_adjective, "adjective")
resolved_color = resolved_adjective.body
assert sheerka.isinstance(resolved_color, "color")
assert sheerka.isa(resolved_color, adjective)
assert sheerka.get_attr(resolved_color, brightness) == dark
assert resolved_color.body == red
# No need to check the default variable value since the attribute is updated
# make sure it's persisted in DB
sheerka.om.commit(context)
from_db = sheerka.om.current_sdp().get(service.CONCEPTS_BY_ID_ENTRY, foo.id)
# concepts values are never persisted in DB.
# only check the default value of the variable
adjective_from_default_var = from_db.get_metadata().variables[0][1]
assert sheerka.isinstance(adjective_from_default_var, "adjective")
color_from_default_var = resolved_adjective.body
assert sheerka.isinstance(color_from_default_var, "color")
assert sheerka.isa(color_from_default_var, adjective)
assert sheerka.get_attr(color_from_default_var, brightness) == dark
assert color_from_default_var.body == red
# check that we can access the values
assert foo_instance.values() == {'c:adjective|1002:': adjective_instance}
assert new_instance.values() == {'c:adjective|1002:': adjective_instance}
assert from_db.values() == {'c:adjective|1002:': NotInit}
assert foo.values() == {'c:adjective|1002:': NotInit}
def test_i_can_set_attr_twice_is_the_second_time_global_truth_is_true(self):
sheerka, context, foo, prop, value = self.init_test(cache_only=False).with_concepts(
"foo",
"prop",
"value",
create_new=True).unpack()
global_truth_context = self.get_context(sheerka, global_truth=True)
foo_instance = sheerka.new("foo")
sheerka.set_attr(context, foo_instance, prop, value)
sheerka.set_attr(global_truth_context, foo_instance, prop, value)
new_instance = sheerka.new("foo")
assert sheerka.get_attr(new_instance, prop) == value
def test_setting_twice_the_same_property_creates_a_list(self):
sheerka, context = self.init_concepts()
foo = Concept("foo")
prop = Concept("property")
@@ -804,22 +892,22 @@ class TestSheerkaConceptManager(TestUsingMemoryBasedSheerka):
baz = Concept("baz")
qux = Concept("qux")
res = sheerka.set_attr(foo, prop, bar)
res = sheerka.set_attr(context, foo, prop, bar)
assert res.status
assert sheerka.isinstance(res.body, BuiltinConcepts.SUCCESS)
assert sheerka.get_attr(foo, prop) == bar
res = sheerka.set_attr(foo, prop, bar) # again, same value as no effect
res = sheerka.set_attr(context, foo, prop, bar) # again, same value as no effect
assert res.status
assert sheerka.isinstance(res.body, BuiltinConcepts.SUCCESS)
assert sheerka.get_attr(foo, prop) == bar
res = sheerka.set_attr(foo, prop, baz)
res = sheerka.set_attr(context, foo, prop, baz)
assert res.status
assert sheerka.isinstance(res.body, BuiltinConcepts.SUCCESS)
assert sheerka.get_attr(foo, prop) == [bar, baz]
res = sheerka.set_attr(foo, prop, qux)
res = sheerka.set_attr(context, foo, prop, qux)
assert res.status
assert sheerka.isinstance(res.body, BuiltinConcepts.SUCCESS)
assert sheerka.get_attr(foo, prop) == [bar, baz, qux]
@@ -1241,7 +1329,7 @@ class TestSheerkaConceptManager(TestUsingMemoryBasedSheerka):
prop = Concept("property")
bar = Concept("bar")
sheerka.set_attr(foo, prop, bar)
sheerka.set_attr(context, foo, prop, bar)
assert sheerka.smart_get_attr(foo, prop) == bar
def test_i_can_smart_get_attr_when_simple_isa(self):
@@ -1256,7 +1344,7 @@ class TestSheerkaConceptManager(TestUsingMemoryBasedSheerka):
color_instance = sheerka.new(color, body=red)
adjective_instance = sheerka.new(adjective, body=color_instance)
table_instance = sheerka.new(table)
sheerka.set_attr(table_instance, adjective, adjective_instance)
sheerka.set_attr(context, table_instance, adjective, adjective_instance)
assert sheerka.smart_get_attr(table_instance, color) == color_instance
assert sheerka.objvalue(sheerka.smart_get_attr(table_instance, color)) == red
@@ -1276,7 +1364,7 @@ class TestSheerkaConceptManager(TestUsingMemoryBasedSheerka):
color_instance = sheerka.new(color, body=reddish_instance)
adjective_instance = sheerka.new(adjective, body=color_instance)
table_instance = sheerka.new(table)
sheerka.set_attr(table_instance, adjective, adjective_instance)
sheerka.set_attr(context, table_instance, adjective, adjective_instance)
assert sheerka.smart_get_attr(table_instance, reddish_instance) == reddish_instance
assert sheerka.objvalue(sheerka.smart_get_attr(table_instance, color)) == red
@@ -1296,12 +1384,12 @@ class TestSheerkaConceptManager(TestUsingMemoryBasedSheerka):
# add red color
red_color_instance = sheerka.new(color, body=red)
red_adjective_instance = sheerka.new(adjective, body=red_color_instance)
sheerka.set_attr(table_instance, adjective, red_adjective_instance)
sheerka.set_attr(context, table_instance, adjective, red_adjective_instance)
# add blue color
blue_color_instance = sheerka.new(color, body=blue)
blue_adjective_instance = sheerka.new(adjective, body=blue_color_instance)
sheerka.set_attr(table_instance, adjective, blue_adjective_instance)
sheerka.set_attr(context, table_instance, adjective, blue_adjective_instance)
res = sheerka.smart_get_attr(table_instance, color)
assert res == [red_color_instance, blue_color_instance]
@@ -1317,7 +1405,7 @@ class TestSheerkaConceptManager(TestUsingMemoryBasedSheerka):
color_instance = sheerka.new(color, body=red)
table_instance = sheerka.new(table)
sheerka.set_attr(table_instance, color, color_instance)
sheerka.set_attr(context, table_instance, color, color_instance)
assert sheerka.smart_get_attr(table_instance, adjective) == color_instance
@@ -1336,9 +1424,9 @@ class TestSheerkaConceptManager(TestUsingMemoryBasedSheerka):
table_instance = sheerka.new(table)
color_instance = sheerka.new(color, body=red)
sheerka.set_attr(table_instance, color, color_instance)
sheerka.set_attr(context, table_instance, color, color_instance)
size_instance = sheerka.new(size, body=large)
sheerka.set_attr(table_instance, size, size_instance)
sheerka.set_attr(context, table_instance, size, size_instance)
assert sheerka.smart_get_attr(table_instance, adjective) == [color_instance, size_instance]
@@ -1355,8 +1443,8 @@ class TestSheerkaConceptManager(TestUsingMemoryBasedSheerka):
color_instance = sheerka.new(color, body=red)
adjective_instance = sheerka.new(adjective, body=color_instance)
table_instance = sheerka.new(table)
sheerka.set_attr(table_instance, adjective, adjective_instance)
sheerka.set_attr(table_instance, color, blue) # set direct color value
sheerka.set_attr(context, table_instance, adjective, adjective_instance)
sheerka.set_attr(context, table_instance, color, blue) # set direct color value
assert sheerka.smart_get_attr(table_instance, color) == blue
@@ -1372,8 +1460,8 @@ class TestSheerkaConceptManager(TestUsingMemoryBasedSheerka):
color_instance = sheerka.new(color, body=red)
table_instance = sheerka.new(table)
sheerka.set_attr(table_instance, color, color_instance)
sheerka.set_attr(table_instance, adjective, blue) # set direct color value
sheerka.set_attr(context, table_instance, color, color_instance)
sheerka.set_attr(context, table_instance, adjective, blue) # set direct color value
assert sheerka.smart_get_attr(table_instance, adjective) == blue
@@ -1397,7 +1485,7 @@ class TestSheerkaConceptManager(TestUsingMemoryBasedSheerka):
color_instance = sheerka.new(color, body=red)
adjective_instance = sheerka.new(adjective, body=color_instance)
table_instance = sheerka.new(table)
sheerka.set_attr(table_instance, adjective, adjective_instance)
sheerka.set_attr(context, table_instance, adjective, adjective_instance)
res = sheerka.smart_get_attr(table_instance, color)
assert sheerka.isinstance(res, BuiltinConcepts.NOT_FOUND)
@@ -1417,7 +1505,7 @@ class TestSheerkaConceptManager(TestUsingMemoryBasedSheerka):
table_instance = sheerka.new(table)
color_instance = sheerka.new(color, body=red)
adjective_instance = sheerka.new(adjective, body=color_instance)
sheerka.set_attr(table_instance, adjective, adjective_instance)
sheerka.set_attr(context, table_instance, adjective, adjective_instance)
res = sheerka.smart_get_attr(table_instance, size)
assert sheerka.isinstance(res, BuiltinConcepts.NOT_FOUND)
+5 -5
View File
@@ -533,7 +533,7 @@ class TestSheerkaDebugManager(TestUsingMemoryBasedSheerka):
def test_i_can_inspect_object_with_concept(self):
sheerka, context, foo = self.init_concepts("foo")
foo.values() # freeze known attributes
sheerka.set_attr(foo, "new_var", "var_value")
sheerka.set_attr(context, foo, "new_var", "var_value")
dummy = DummyObj(foo, "value")
res = sheerka.inspect(context, dummy)
@@ -542,7 +542,7 @@ class TestSheerkaDebugManager(TestUsingMemoryBasedSheerka):
def test_i_can_inspect_object_with_concept_when_as_bag(self):
sheerka, context, foo = self.init_concepts("foo")
foo.values() # freeze known attributes
sheerka.set_attr(foo, "new_var", "var_value")
sheerka.set_attr(context, foo, "new_var", "var_value")
dummy = DummyObj(foo, "value")
res = sheerka.inspect(context, dummy, as_bag=True)
@@ -557,7 +557,7 @@ class TestSheerkaDebugManager(TestUsingMemoryBasedSheerka):
def test_i_can_inspect_object_with_concept_when_values(self):
sheerka, context, foo = self.init_concepts("foo")
foo.values() # freeze known attributes
sheerka.set_attr(foo, "new_var", "var_value")
sheerka.set_attr(context, foo, "new_var", "var_value")
dummy = DummyObj(foo, "value")
res = sheerka.inspect(context, dummy, values=True)
@@ -629,7 +629,7 @@ class TestSheerkaDebugManager(TestUsingMemoryBasedSheerka):
def test_i_can_inspect_when_a_property_does_not_exist(self):
sheerka, context, foo = self.init_concepts("foo")
foo.values() # freeze known attributes
sheerka.set_attr(foo, "new_var", "var_value")
sheerka.set_attr(context, foo, "new_var", "var_value")
dummy = DummyObj(foo, "value")
res = sheerka.inspect(context, dummy, "#type#", "fake", "a", "b")
@@ -641,7 +641,7 @@ class TestSheerkaDebugManager(TestUsingMemoryBasedSheerka):
def test_i_can_inspect_when_properties_are_specified_several_times(self):
sheerka, context, foo = self.init_concepts("foo")
foo.values() # freeze known attributes
sheerka.set_attr(foo, "new_var", "var_value")
sheerka.set_attr(context, foo, "new_var", "var_value")
dummy = DummyObj(foo, "value")
res = sheerka.inspect(context, dummy, "#type#", "a", "b", "a")
+1 -9
View File
@@ -314,7 +314,7 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
def test_i_can_evaluate_when_variable_asts_is_a_list(self):
sheerka = self.get_sheerka()
foo = Concept("foo", body="1")
foo = Concept("foo", body="1").init_key()
concept = Concept("to_eval").def_var("prop")
concept.get_compiled()["prop"] = [foo, DoNotResolve("1")]
@@ -467,14 +467,6 @@ class TestSheerkaEvaluateConcept(TestUsingMemoryBasedSheerka):
evaluated = sheerka.evaluate_concept(self.get_context(sheerka, True), concept)
assert sheerka.isinstance(evaluated, BuiltinConcepts.CONCEPT_EVAL_ERROR)
def test_key_is_initialized_by_evaluation(self):
sheerka = self.get_sheerka()
concept = Concept("foo")
evaluated = sheerka.evaluate_concept(self.get_context(sheerka, True), concept)
assert evaluated.key == concept.init_key().key
@pytest.mark.parametrize("where_clause, expected, expected_prop, expected_body", [
("True", True, None, NotInit),
("False", False, ConceptParts.WHERE, NotInit),
+1 -1
View File
@@ -253,7 +253,7 @@ class TestSheerkaMemory(TestUsingMemoryBasedSheerka):
instantiated_foo = sheerka.new(foo, x="value1")
instantiated_one = ensure_evaluated(context, sheerka.new(inner_value))
instantiated_value = sheerka.new(value, x=instantiated_one)
sheerka.set_attr(instantiated_foo, prop, instantiated_value)
sheerka.set_attr(context, instantiated_foo, prop, instantiated_value)
sheerka.add_to_memory(context, "foo", instantiated_foo)
sheerka.om.commit(context)
+38 -5
View File
@@ -64,10 +64,10 @@ def test_i_can_serialize():
:return:
"""
concept = Concept(
name="concept_name",
name="concept_name a",
is_builtin=True,
is_unique=True,
key="concept_key",
key=None,
body="definition of the body",
where="definition of the where",
pre="definition of the pre",
@@ -78,6 +78,8 @@ def test_i_can_serialize():
desc="this this the desc",
id="123456"
).def_var("a", "10").def_var("b", None)
concept.get_metadata().parameters = ["a"]
concept.init_key()
to_dict = concept.to_dict()
assert to_dict == {
@@ -88,14 +90,15 @@ def test_i_can_serialize():
'id': '123456',
'is_builtin': True,
'is_unique': True,
'key': 'concept_key',
'name': 'concept_name',
'key': 'concept_name __var__0',
'name': 'concept_name a',
'post': 'definition of the post',
'pre': 'definition of the pre',
'ret': "concept to return",
'props': {},
'variables': [('a', "10"), ('b', None)],
'where': 'definition of the where'
'where': 'definition of the where',
'parameters': ['a'],
}
@@ -302,3 +305,33 @@ def test_i_can_manage_instance_attributes():
assert foo.values() == {"x": "value for x", "y": "value for y"}
assert foo.get_all_attributes() == ["x", "y"]
assert ALL_ATTRIBUTES == {"foo_id": ["x"]}
def test_i_can_init_key_and_compute_parameters():
concept = Concept("foo x").def_var("x").init_key()
assert concept.key == "foo __var__0"
concept = Concept("foo").def_var("x").init_key()
assert concept.key == "foo"
concept = Concept("foo a b").def_var("a").def_var("b").init_key()
assert concept.key == "foo __var__0 __var__1"
concept = Concept("foo a b").def_var("b").def_var("a").init_key()
assert concept.key == "foo __var__1 __var__0"
concept = Concept("foo a b").def_var("a").init_key()
assert concept.key == "foo __var__0 b"
concept = Concept("foo a b").def_var("b").init_key()
assert concept.key == "foo a __var__0"
concept = Concept("foo a").def_var("a").def_var("b").init_key()
assert concept.key == "foo __var__0"
concept = Concept("foo b").def_var("a").def_var("b").init_key()
assert concept.key == "foo __var__1"
concept = Concept("plus", definition_type=DEFINITION_TYPE_DEF, definition="a plus b").def_var("a").def_var("b")
concept.init_key()
assert concept.key == "__var__0 plus __var__1"
@@ -38,7 +38,6 @@ class TestAddConceptEvaluator(TestUsingMemoryBasedSheerka):
assert result.value.get_value(ConceptParts.POST) == 4
assert result.value.get_value("a") == 5
assert result.value.get_value("b") == 6
assert result.value.key == "foo"
assert result.parents == [item]
def test_body_is_returned_when_defined_and_requested(self):
+84 -2
View File
@@ -7,7 +7,7 @@ from core.concept import VARIABLE_PREFIX, Concept, DEFINITION_TYPE_BNF, DEFINITI
from core.sheerka.services.SheerkaConceptManager import NoFirstTokenError
from core.sheerka.services.SheerkaExecute import ParserInput
from core.tokenizer import Tokenizer
from evaluators.DefConceptEvaluator import DefConceptEvaluator, PossibleVariable, CertainVariable
from evaluators.DefConceptEvaluator import DefConceptEvaluator, PossibleVariable, CertainVariable, ParameterVariable
from parsers.BaseParser import BaseParser
from parsers.BnfDefinitionParser import BnfDefinitionParser
from parsers.BnfNodeParser import Sequence, StrMatch, ZeroOrMore, ConceptExpression, VariableExpression
@@ -200,7 +200,7 @@ class TestDefConceptEvaluator(TestUsingMemoryBasedSheerka):
def_ret_val = DefConceptParser().parse(context, ParserInput(text))
concept_definition = def_ret_val.value.body.definition
expected = [CertainVariable("unit"), CertainVariable("one"), CertainVariable("two")]
expected = [ParameterVariable("unit", True), CertainVariable("one"), CertainVariable("two")]
assert DefConceptEvaluator.get_variables(context, concept_definition, []) == expected
def test_i_can_recognize_variables_when_referencing_other_concepts(self):
@@ -326,6 +326,84 @@ class TestDefConceptEvaluator(TestUsingMemoryBasedSheerka):
assert evaluated.body.body.key == "foo2 __var__0"
assert evaluated.body.body.get_metadata().variables == [("x", None)]
def test_i_can_eval_when_bnf_with_implicit_variables_from_named_ordered_choice(self):
sheerka, context, one, two = self.init_concepts("one", "two", create_new=True)
text = "def concept plus from bnf (one|two)=n1 'plus' (one|two)=n2 as n1 + n2"
def_ret_val = DefConceptParser().parse(context, ParserInput(text))
evaluated = DefConceptEvaluator().eval(context, def_ret_val)
assert evaluated.status
assert context.sheerka.isinstance(evaluated.body, BuiltinConcepts.NEW_CONCEPT)
created_concept = evaluated.body.body
assert created_concept.get_metadata().name == "plus"
assert created_concept.get_metadata().key == "plus"
assert created_concept.get_metadata().definition == "(one|two)=n1 'plus' (one|two)=n2"
assert created_concept.get_metadata().definition_type == "bnf"
assert created_concept.get_metadata().variables == [('n1', None), ('one', None), ('two', None), ('n2', None)]
assert created_concept.get_metadata().parameters == ['n1', 'n2']
def test_i_can_eval_when_bnf_with_implicit_variables_from_unamed_ordered_choice(self):
sheerka, context, one, two, three = self.init_concepts("one", "two", "three", create_new=True)
text = "def concept choice from bnf (one|two) 'or' (two|three) 'or' (two|three)=c3"
def_ret_val = DefConceptParser().parse(context, ParserInput(text))
evaluated = DefConceptEvaluator().eval(context, def_ret_val)
assert evaluated.status
assert context.sheerka.isinstance(evaluated.body, BuiltinConcepts.NEW_CONCEPT)
created_concept = evaluated.body.body
assert created_concept.get_metadata().name == "choice"
assert created_concept.get_metadata().key == "choice"
assert created_concept.get_metadata().definition == "(one|two) 'or' (two|three) 'or' (two|three)=c3"
assert created_concept.get_metadata().definition_type == "bnf"
assert created_concept.get_metadata().variables == [('one', None), ('two', None), ('three', None), ('c3', None)]
assert created_concept.get_metadata().parameters == ['__OrderedChoice__1', '__OrderedChoice__2', "c3"]
def test_i_can_eval_when_bnf_with_implicit_variables_from_unordered_choice(self):
# as it's not possible to directly defined UnorderedChoice, we test isa concept
sheerka, context, one, two, number = self.init_concepts("one", "two", "number", create_new=True)
global_truth_context = self.get_context(global_truth=True)
sheerka.set_isa(global_truth_context, one, number)
sheerka.set_isa(global_truth_context, two, number)
text = "def concept plus from bnf number=n1 'plus' number=n2 as n1 + n2"
def_ret_val = DefConceptParser().parse(context, ParserInput(text))
evaluated = DefConceptEvaluator().eval(context, def_ret_val)
assert evaluated.status
assert context.sheerka.isinstance(evaluated.body, BuiltinConcepts.NEW_CONCEPT)
created_concept = evaluated.body.body
assert created_concept.get_metadata().name == "plus"
assert created_concept.get_metadata().key == "plus"
assert created_concept.get_metadata().definition == "number=n1 'plus' number=n2"
assert created_concept.get_metadata().definition_type == "bnf"
assert created_concept.get_metadata().variables == [('n1', None), ('n2', None)]
assert created_concept.get_metadata().parameters == ['n1', 'n2']
def test_i_can_eval_when_bnf_with_implicit_variables_from_unamed_unordered_choice(self):
# as it's not possible to directly defined UnorderedChoice, we test isa concept
sheerka, context, one, two, number = self.init_concepts("one", "two", "number", create_new=True)
global_truth_context = self.get_context(global_truth=True)
sheerka.set_isa(global_truth_context, one, number)
sheerka.set_isa(global_truth_context, two, number)
text = "def concept plus from bnf number 'plus' number as number[0] + number[1]"
def_ret_val = DefConceptParser().parse(context, ParserInput(text))
evaluated = DefConceptEvaluator().eval(context, def_ret_val)
assert evaluated.status
assert context.sheerka.isinstance(evaluated.body, BuiltinConcepts.NEW_CONCEPT)
created_concept = evaluated.body.body
assert created_concept.get_metadata().name == "plus"
assert created_concept.get_metadata().key == "plus"
assert created_concept.get_metadata().definition == "number 'plus' number"
assert created_concept.get_metadata().definition_type == "bnf"
assert created_concept.get_metadata().variables == [('number', None)]
assert created_concept.get_metadata().parameters == ['number']
def test_i_can_eval_when_bnf_concept_with_regex(self):
context = self.get_context()
def_ret_val = DefConceptParser().parse(context, ParserInput("def concept hello a from bnf r'[a-z]+'=a 'hello'"))
@@ -339,6 +417,8 @@ class TestDefConceptEvaluator(TestUsingMemoryBasedSheerka):
assert created_concept.get_metadata().key == "hello __var__0"
assert created_concept.get_metadata().definition == "r'[a-z]+'=a 'hello'"
assert created_concept.get_metadata().definition_type == "bnf"
assert created_concept.get_metadata().variables == [('a', None)]
assert created_concept.get_metadata().parameters == ['a']
def test_i_can_eval_when_bnf_concept_with_variable(self):
context = self.get_context()
@@ -355,6 +435,8 @@ class TestDefConceptEvaluator(TestUsingMemoryBasedSheerka):
assert created_concept.get_metadata().definition_type == "bnf"
assert created_concept.get_metadata().variables == [("x", None)]
assert created_concept._bnf == Sequence(StrMatch("hello"), VariableExpression("x"))
assert created_concept.get_metadata().variables == [('x', None)]
assert created_concept.get_metadata().parameters == ['x']
def test_i_can_eval_when_auto_eval_is_true(self):
sheerka, context = self.init_test().unpack()
+19 -2
View File
@@ -94,6 +94,7 @@ as:
expected.get_metadata().id = "1001"
expected.get_metadata().desc = None
expected.get_metadata().variables = [("a", None), ("b", None)]
expected.get_metadata().parameters = ["a", "b"]
expected.init_key()
sheerka = self.get_sheerka(cache_only=False)
@@ -134,6 +135,7 @@ as:
res = sheerka.evaluate_user_input("def concept a xx b as a plus b")
expected = Concept(name="a xx b", body="a plus b").def_var("a").def_var("b").init_key()
expected.get_metadata().id = "1001"
expected.get_metadata().parameters = ["a", "b"]
assert len(res) == 1
assert res[0].status
@@ -1392,17 +1394,32 @@ as:
"set_isa(color, adjective)",
"def concept what is the x of y pre is_question() as smart_get_attr(y, x)",
"def concept qualify x from bnf adjective x as set_attr(x, c:adjective:, adjective) ret x",
"eval a red short",
]
sheerka = self.init_scenario(init, global_truth=True)
res = sheerka.evaluate_user_input("eval a red short")
res = sheerka.evaluate_user_input("what is the color of the short ?")
assert len(res) == 1
assert res[0].status
assert res[0].value == "red"
res = sheerka.evaluate_user_input("eval a blue short")
sheerka.evaluate_user_input("eval a blue short")
res = sheerka.evaluate_user_input("what is the color of the short ?")
assert len(res) == 1
assert res[0].status
assert res[0].value == "blue"
def test_i_can_access_a_concept_after_a_global_set_attr(self):
init = [
"def concept foo",
"def concept color",
"def concept red",
"global_truth(set_attr(foo, color, red))"
]
sheerka = self.init_scenario(init)
res = sheerka.evaluate_user_input("inspect(foo)")
assert len(res) == 1
assert res[0].status
+4 -4
View File
@@ -32,7 +32,7 @@ name : foo
key : foo
definition: None
type : None
hash : 16f7fbb8bc509b8c652edaf3d0c0457d15a37f0a862fbe03fa357b0c77249c46
hash : 632c9ac7f3a08777918aeee4bb53712caedc634a863ae39a641f69055ae2e238
body : 1
where : None
pre : None
@@ -45,7 +45,7 @@ name : foo
key : foo
definition: None
type : None
hash : 7036cd5ffa9294d2e1dc9bf9c9bbe2783ace5cf7f423bfce9b28c8d33c0d1d0c
hash : 23a1a8bc5966982471aa19b8452e22d414a55d704431866e198570913d47fd7d
body : 2
where : None
pre : None
@@ -71,7 +71,7 @@ name : foo
key : foo
definition: None
type : None
hash : 16f7fbb8bc509b8c652edaf3d0c0457d15a37f0a862fbe03fa357b0c77249c46
hash : 632c9ac7f3a08777918aeee4bb53712caedc634a863ae39a641f69055ae2e238
body : 1
where : None
pre : None
@@ -84,7 +84,7 @@ name : foo
key : foo
definition: None
type : None
hash : e8dd1af1b6bc0eca0fb4a87a6fabb16655caa4b7a6ea9dbbd1f887757e6caf89
hash : 60e442c59940a2616a3783d2e34f428f4a5ae456a88539bba9a5e87cf77060a6
body : 2
where : True
pre : None
+21 -1
View File
@@ -5,7 +5,7 @@ from core.concept import Concept, DEFINITION_TYPE_DEF
from core.sheerka.services.SheerkaExecute import ParserInput
from parsers.SequenceNodeParser import SequenceNodeParser
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
from tests.parsers.parsers_utils import compute_expected_array, CN, CNC, SCN, get_test_obj, compare_with_test_object, \
from tests.parsers.parsers_utils import compute_expected_array, CN, SCN, get_test_obj, compare_with_test_object, \
UTN
@@ -275,6 +275,26 @@ class TestSequenceNodeParser(TestUsingMemoryBasedSheerka):
assert concept_found.get_hints().is_evaluated
assert not concept_found.get_hints().is_instance
def test_i_can_parse_when_variable_is_not_a_parameter(self):
concepts_map = {
"foo": Concept("foo").def_var("a"), # 'a' is not a parameter (but a property like its color for ex)
}
text, expected = "foo", ["foo"]
sheerka, context, parser = self.init_parser(concepts_map, create_new=True, use_sheerka=True)
res = parser.parse(context, ParserInput(text))
wrapper = res.body
lexer_nodes = res.body.body
assert res.status
expected_array = compute_expected_array(concepts_map, text, expected)
assert sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
compare_with_test_object(lexer_nodes, expected_array)
assert not lexer_nodes[0].concept.get_hints().is_evaluated
assert lexer_nodes[0].concept.get_hints().use_copy
assert lexer_nodes[0].concept.get_hints().is_instance
@pytest.mark.parametrize("text", [
"foo",
f"foo one",
+40
View File
@@ -1114,6 +1114,33 @@ class TestSyaNodeParser(TestUsingMemoryBasedSheerka):
# check metadata
assert expected_concept.get_metadata().variables == [("a", "twenty one")]
def test_i_can_parse_when_all_variables_are_not_parameters(self):
my_map = {
"foo": Concept("foo a").def_var("a", "'default_a'").def_var("b", "'default_b'"), # 'b' is not a parameter
"bar": Concept("bar b").def_var("a", "'default_a'").def_var("b", "'default_b'"), # 'a' is not a parameter
"baz": Concept("baz")
}
sheerka, context, parser = self.init_parser(my_map)
text = "foo baz"
res = parser.parse(context, ParserInput(text))
assert res.status
assert len(res.body.body) == 1
expected_concept = res.body.body[0].concept
assert sheerka.isinstance(expected_concept.get_compiled()["a"], "baz")
assert "b" not in expected_concept.get_compiled()
assert expected_concept.get_metadata().variables == [("a", "baz"), ("b", "'default_b'")]
text = "bar baz"
res = parser.parse(context, ParserInput(text))
assert res.status
assert len(res.body.body) == 1
expected_concept = res.body.body[0].concept
assert sheerka.isinstance(expected_concept.get_compiled()["b"], "baz")
assert "a" not in expected_concept.get_compiled()
assert expected_concept.get_metadata().variables == [("a", "'default_a'"), ("b", "baz")]
def test_i_can_parse_sequences(self):
sheerka, context, parser = self.init_parser()
@@ -1335,6 +1362,19 @@ class TestSyaNodeParser(TestUsingMemoryBasedSheerka):
assert not res.status
assert sheerka.isinstance(res.body, BuiltinConcepts.IS_EMPTY)
def test_i_cannot_parse_concept_when_variable_is_not_a_parameter(self):
my_map = {
"foo": Concept("foo").def_var("a") # 'a' is not a parameter (but a property like its color for ex)
}
sheerka, context, parser = self.init_parser(my_map)
text = "foo"
res = parser.parse(context, ParserInput(text))
assert not res.status
assert sheerka.isinstance(res.body, BuiltinConcepts.NOT_FOR_ME)
assert res.body.body == text
@pytest.mark.parametrize("expression, expected", [
("function(", ([], "function(")),
("before the function(", (["before the "], "function(")),