Enhanced complex concepts handling

This commit is contained in:
2020-01-11 08:03:35 +01:00
parent a62c1f0f13
commit 40416ac337
24 changed files with 1647 additions and 961 deletions
+28 -20
View File
@@ -108,26 +108,34 @@ def test_that_the_source_is_correctly_set():
assert created_concept.metadata.definition == "hello a"
def test_that_the_ast_is_correctly_initialized():
context = get_context()
def_concept_return_value = get_concept(
name="hello a",
definition=get_concept_definition("hello a", Sequence(StrMatch("hello"), StrMatch("a"))),
where="isinstance(a, str )",
pre="a is not None",
body="print('hello' + a)")
evaluated = AddConceptEvaluator().eval(context, def_concept_return_value)
assert evaluated.status
assert context.sheerka.isinstance(evaluated.body, BuiltinConcepts.NEW_CONCEPT)
created_concept = evaluated.body.body
assert ConceptParts.WHERE in created_concept.cached_asts
assert ConceptParts.PRE in created_concept.cached_asts
assert ConceptParts.BODY in created_concept.cached_asts
assert ConceptParts.POST not in created_concept.cached_asts
# def test_that_the_ast_is_correctly_initialized():
# """
# When I parse the definition of a concept, I evaluate the metadata (like the body)
# I wanted to keep in cache these evaluation for further utilisation but I have
# a serialization issue.
# So I had to comment concept.add_codes(def_concept_node.get_asts()) around line 85
# So this test is now irrelevant
# :return:
# """
# context = get_context()
# def_concept_return_value = get_concept(
# name="hello a",
# definition=get_concept_definition("hello a", Sequence(StrMatch("hello"), StrMatch("a"))),
# where="isinstance(a, str )",
# pre="a is not None",
# body="print('hello' + a)")
#
# evaluated = AddConceptEvaluator().eval(context, def_concept_return_value)
#
# assert evaluated.status
# assert context.sheerka.isinstance(evaluated.body, BuiltinConcepts.NEW_CONCEPT)
#
# created_concept = evaluated.body.body
#
# assert ConceptParts.WHERE in created_concept.cached_asts
# assert ConceptParts.PRE in created_concept.cached_asts
# assert ConceptParts.BODY in created_concept.cached_asts
# assert ConceptParts.POST not in created_concept.cached_asts
def test_that_the_new_concept_is_correctly_saved():
+3 -3
View File
@@ -108,12 +108,12 @@ def test_i_can_use_the_result_of_regex_parsing_to_parse_a_text():
res = concept_parser.parse(context, "twenty two")
assert res.status
assert res.value.body == [(bar, 0, 2, "twenty two")]
assert res.value.body == [("bar", 0, 2, "twenty two")]
res = concept_parser.parse(context, "thirty one")
assert res.status
assert res.value.body == [(bar, 0, 2, "thirty one")]
assert res.value.body == [("bar", 0, 2, "thirty one")]
res = concept_parser.parse(context, "twenty")
assert res.status
assert res.value.body == [(foo, 0, 0, "twenty")]
assert res.value.body == [("foo", 0, 0, "twenty")]
+128 -128
View File
@@ -1,128 +1,128 @@
import pytest
from core.builtin_concepts import ReturnValueConcept, ParserResultConcept
from core.concept import Concept
from core.sheerka import Sheerka, ExecutionContext
from evaluators.BaseEvaluator import BaseEvaluator
from evaluators.ConceptComposerEvaluator import ConceptComposerEvaluator
from parsers.BaseParser import BaseParser
from parsers.ConceptLexerParser import ConceptNode, ConceptLexerParser, Sequence
from sdp.sheerkaDataProvider import Event
concept_lexer_name = ConceptLexerParser().name
def get_context():
sheerka = Sheerka(skip_builtins_in_db=True)
sheerka.initialize("mem://")
return ExecutionContext("test", Event(), sheerka)
def get_return_values(context, grammar, expression):
parser = ConceptLexerParser()
parser.initialize(context, grammar)
ret_val = parser.parse(context, expression)
assert not ret_val.status
return [ret_val]
def init(concepts, grammar, expression):
context = get_context()
for c in concepts:
context.sheerka.add_in_cache(c)
return_values = get_return_values(context, grammar, expression)
return context, return_values
@pytest.mark.parametrize("return_values, expected", [
([
ReturnValueConcept(BaseParser.PREFIX + "some_name", False, "in error"),
ReturnValueConcept(concept_lexer_name, False, ParserResultConcept(value=[ConceptNode(Concept(), 0, 0)])),
ReturnValueConcept("not a parser", True, "some value"),
], True),
([
ReturnValueConcept(concept_lexer_name, False, ParserResultConcept(value=[ConceptNode(Concept(), 0, 0)])),
], True),
([
ReturnValueConcept(BaseParser.PREFIX + "some_name", True, "not in error"),
ReturnValueConcept(concept_lexer_name, False, ParserResultConcept(value=[ConceptNode(Concept(), 0, 0)])),
], False),
([
ReturnValueConcept(BaseParser.PREFIX + "some_name", False, "in error"),
ReturnValueConcept(concept_lexer_name, True, ParserResultConcept(value=[ConceptNode(Concept(), 0, 0)])),
], False),
([
ReturnValueConcept(BaseParser.PREFIX + "some_name", False, "in error"),
ReturnValueConcept(concept_lexer_name, False, "some value"),
], False),
([
ReturnValueConcept(BaseParser.PREFIX + "some_name", False, "in error"),
ReturnValueConcept(concept_lexer_name, False, ParserResultConcept(value=["not a concept"])),
], False),
([
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", False, "evaluator in error"),
ReturnValueConcept(concept_lexer_name, False, ParserResultConcept(value=[ConceptNode(Concept(), 0, 0)])),
ReturnValueConcept("not a parser", True, "some value"),
], False),
([
ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, "evaluator"),
ReturnValueConcept(concept_lexer_name, False, ParserResultConcept(value=[ConceptNode(Concept(), 0, 0)])),
ReturnValueConcept("not a parser", True, "some value"),
], False),
])
def test_i_can_match(return_values, expected):
context = get_context()
assert ConceptComposerEvaluator().matches(context, return_values) == expected
def test_i_can_eval_simple_concepts():
foo = Concept("foo", body="'foo'")
bar = Concept("bar", body="'bar'")
grammar = {}
context, return_values = init([foo, bar], grammar, "bar foo")
composer = ConceptComposerEvaluator()
assert composer.matches(context, return_values)
ret_val = composer.eval(context, return_values)
assert ret_val.status
assert ret_val.who == composer.name
assert ret_val.value == [Concept("bar", body="bar").init_key(), Concept("foo", body="foo").init_key()]
assert ret_val.value[0].metadata.is_evaluated
assert ret_val.value[1].metadata.is_evaluated
assert ret_val.parents == [return_values[0]]
def test_i_can_eval_simple_concepts_when_some_are_bnf():
foo = Concept("foo", body="'foo'")
bar = Concept("bar", body="'bar'")
grammar = {foo: "foo"}
context, return_values = init([foo, bar], grammar, "bar foo")
composer = ConceptComposerEvaluator()
assert composer.matches(context, return_values)
ret_val = composer.eval(context, return_values)
assert ret_val.status
assert ret_val.who == composer.name
assert ret_val.value == [Concept("bar", body="bar").init_key(), Concept("foo", body="foo").init_key()]
assert ret_val.value[0].metadata.is_evaluated
assert ret_val.value[1].metadata.is_evaluated
assert ret_val.parents == [return_values[0]]
def test_i_can_eval_simple_concept_and_text():
foo = Concept("foo", body="'foo'")
grammar = {}
context, return_values = init([foo], grammar, "'bar' foo")
composer = ConceptComposerEvaluator()
assert composer.matches(context, return_values)
ret_val = composer.eval(context, return_values)
assert ret_val.status
assert ret_val.who == composer.name
assert ret_val.value == "bar foo"
assert ret_val.parents == [return_values[0]]
# import pytest
#
# from core.builtin_concepts import ReturnValueConcept, ParserResultConcept
# from core.concept import Concept
# from core.sheerka import Sheerka, ExecutionContext
# from evaluators.BaseEvaluator import BaseEvaluator
# from evaluators.ConceptComposerEvaluator import ConceptComposerEvaluator
# from parsers.BaseParser import BaseParser
# from parsers.ConceptLexerParser import ConceptNode, ConceptLexerParser, Sequence
# from sdp.sheerkaDataProvider import Event
#
# concept_lexer_name = ConceptLexerParser().name
#
#
# def get_context():
# sheerka = Sheerka(skip_builtins_in_db=True)
# sheerka.initialize("mem://")
# return ExecutionContext("test", Event(), sheerka)
#
#
# def get_return_values(context, grammar, expression):
# parser = ConceptLexerParser()
# parser.initialize(context, grammar)
#
# ret_val = parser.parse(context, expression)
# assert not ret_val.status
# return [ret_val]
#
#
# def init(concepts, grammar, expression):
# context = get_context()
# for c in concepts:
# context.sheerka.add_in_cache(c)
# return_values = get_return_values(context, grammar, expression)
#
# return context, return_values
#
#
# @pytest.mark.parametrize("return_values, expected", [
# ([
# ReturnValueConcept(BaseParser.PREFIX + "some_name", False, "in error"),
# ReturnValueConcept(concept_lexer_name, False, ParserResultConcept(value=[ConceptNode(Concept(), 0, 0)])),
# ReturnValueConcept("not a parser", True, "some value"),
# ], True),
# ([
# ReturnValueConcept(concept_lexer_name, False, ParserResultConcept(value=[ConceptNode(Concept(), 0, 0)])),
# ], True),
# ([
# ReturnValueConcept(BaseParser.PREFIX + "some_name", True, "not in error"),
# ReturnValueConcept(concept_lexer_name, False, ParserResultConcept(value=[ConceptNode(Concept(), 0, 0)])),
# ], False),
# ([
# ReturnValueConcept(BaseParser.PREFIX + "some_name", False, "in error"),
# ReturnValueConcept(concept_lexer_name, True, ParserResultConcept(value=[ConceptNode(Concept(), 0, 0)])),
# ], False),
# ([
# ReturnValueConcept(BaseParser.PREFIX + "some_name", False, "in error"),
# ReturnValueConcept(concept_lexer_name, False, "some value"),
# ], False),
# ([
# ReturnValueConcept(BaseParser.PREFIX + "some_name", False, "in error"),
# ReturnValueConcept(concept_lexer_name, False, ParserResultConcept(value=["not a concept"])),
# ], False),
# ([
# ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", False, "evaluator in error"),
# ReturnValueConcept(concept_lexer_name, False, ParserResultConcept(value=[ConceptNode(Concept(), 0, 0)])),
# ReturnValueConcept("not a parser", True, "some value"),
# ], False),
# ([
# ReturnValueConcept(BaseEvaluator.PREFIX + "some_name", True, "evaluator"),
# ReturnValueConcept(concept_lexer_name, False, ParserResultConcept(value=[ConceptNode(Concept(), 0, 0)])),
# ReturnValueConcept("not a parser", True, "some value"),
# ], False),
# ])
# def test_i_can_match(return_values, expected):
# context = get_context()
# assert ConceptComposerEvaluator().matches(context, return_values) == expected
#
#
# def test_i_can_eval_simple_concepts():
# foo = Concept("foo", body="'foo'")
# bar = Concept("bar", body="'bar'")
# grammar = {}
# context, return_values = init([foo, bar], grammar, "bar foo")
#
# composer = ConceptComposerEvaluator()
# assert composer.matches(context, return_values)
#
# ret_val = composer.eval(context, return_values)
# assert ret_val.status
# assert ret_val.who == composer.name
# assert ret_val.value == [Concept("bar", body="bar").init_key(), Concept("foo", body="foo").init_key()]
# assert ret_val.value[0].metadata.is_evaluated
# assert ret_val.value[1].metadata.is_evaluated
# assert ret_val.parents == [return_values[0]]
#
#
# def test_i_can_eval_simple_concepts_when_some_are_bnf():
# foo = Concept("foo", body="'foo'")
# bar = Concept("bar", body="'bar'")
# grammar = {foo: "foo"}
# context, return_values = init([foo, bar], grammar, "bar foo")
#
# composer = ConceptComposerEvaluator()
# assert composer.matches(context, return_values)
#
# ret_val = composer.eval(context, return_values)
# assert ret_val.status
# assert ret_val.who == composer.name
# assert ret_val.value == [Concept("bar", body="bar").init_key(), Concept("foo", body="foo").init_key()]
# assert ret_val.value[0].metadata.is_evaluated
# assert ret_val.value[1].metadata.is_evaluated
# assert ret_val.parents == [return_values[0]]
#
#
# def test_i_can_eval_simple_concept_and_text():
# foo = Concept("foo", body="'foo'")
# grammar = {}
# context, return_values = init([foo], grammar, "'bar' foo")
#
# composer = ConceptComposerEvaluator()
# assert composer.matches(context, return_values)
#
# ret_val = composer.eval(context, return_values)
# assert ret_val.status
# assert ret_val.who == composer.name
# assert ret_val.value == "bar foo"
# assert ret_val.parents == [return_values[0]]
File diff suppressed because it is too large Load Diff
+12 -160
View File
@@ -1,6 +1,6 @@
import pytest
from core.builtin_concepts import ReturnValueConcept, ParserResultConcept
from core.builtin_concepts import ReturnValueConcept, ParserResultConcept, BuiltinConcepts
from core.concept import Concept
from core.sheerka import Sheerka, ExecutionContext
from evaluators.ConceptNodeEvaluator import ConceptNodeEvaluator
@@ -15,7 +15,7 @@ def get_context():
return ExecutionContext("test", Event(), sheerka)
def get_return_value(context, grammar, expression):
def from_parsing(context, grammar, expression):
parser = ConceptLexerParser()
parser.initialize(context, grammar)
@@ -31,7 +31,7 @@ def init(concept, grammar, text):
context.sheerka.add_in_cache(c)
else:
context.sheerka.add_in_cache(concept)
ret_val = get_return_value(context, grammar, text)
ret_val = from_parsing(context, grammar, text)
node = ret_val.value.value[0]
return context, node
@@ -56,172 +56,24 @@ def test_i_can_match(ret_val, expected):
assert ConceptNodeEvaluator().matches(context, ret_val) == expected
def test_parser_result_of_concept_is_returned_when_list_of_one_concept_node():
def test_concept_is_returned_when_only_one_in_the_list():
foo = Concept("foo")
context = get_context()
context.sheerka.add_in_cache(foo)
evaluator = ConceptNodeEvaluator()
ret_val = get_return_value(context, {foo: StrMatch("foo")}, "foo")
ret_val = from_parsing(context, {foo: StrMatch("foo")}, "foo")
result = evaluator.eval(context, ret_val)
wrapper = result.body
return_value = result.body.body
assert result.who == evaluator.name
assert result.status
assert result.value == ParserResultConcept(
evaluator,
"foo",
Concept("foo", body="'foo'").init_key(),
None)
assert context.sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
assert wrapper.parser == evaluator
assert wrapper.source == "foo"
assert return_value == Concept("foo", body="foo").init_key()
assert return_value.metadata.is_evaluated
assert result.parents == [ret_val]
def test_concept_property_is_correctly_updated_for_str_match():
foo = Concept("foo")
grammar = {foo: StrMatch("foo", rule_name="variable")}
context, node = init(foo, grammar, "foo")
updated = ConceptNodeEvaluator().finalize_concept(context.sheerka, node.concept, node.underlying)
assert "variable" in updated.props
assert updated.props["variable"].value == "'foo'"
assert updated.body == "'foo'"
def test_concept_property_is_correctly_updated_for_sequence():
foo = Concept("foo")
grammar = {foo: Sequence("one", "two", rule_name="variable")}
context, node = init(foo, grammar, "one two")
updated = ConceptNodeEvaluator().finalize_concept(
context.sheerka,
context.sheerka.new(node.concept.key),
node.underlying)
assert "variable" in updated.props
assert updated.props["variable"].value == "'one two'"
assert updated.body == "'one two'"
def test_concept_property_is_updated_for_str_in_sequence():
foo = Concept("foo")
grammar = {foo: Sequence(StrMatch("one", rule_name="s1"), StrMatch("two", rule_name="s2"), rule_name="variable")}
context, node = init(foo, grammar, "one two")
updated = ConceptNodeEvaluator().finalize_concept(
context.sheerka,
context.sheerka.new(node.concept.key),
node.underlying)
assert updated.props["variable"].value == "'one two'"
assert updated.props["s1"].value == "'one'"
assert updated.props["s2"].value == "'two'"
assert updated.body == "'one two'"
def test_concept_property_is_correctly_updated_for_optional():
foo = Concept("foo")
grammar = {foo: Sequence("one", Optional("two", rule_name="o"), rule_name="variable")}
context, node = init(foo, grammar, "one two")
updated = ConceptNodeEvaluator().finalize_concept(
context.sheerka,
context.sheerka.new(node.concept.key),
node.underlying)
assert "variable" in updated.props
assert updated.props["variable"].value == "'one two'"
assert updated.props["o"].value == "'two'"
assert updated.body == "'one two'"
def test_concept_property_is_correctly_updated_for_zero_or_more():
foo = Concept("foo")
grammar = {foo: ZeroOrMore("one", rule_name="variable")}
context, node = init(foo, grammar, "one one one")
updated = ConceptNodeEvaluator().finalize_concept(
context.sheerka,
context.sheerka.new(node.concept.key),
node.underlying)
assert "variable" in updated.props
assert updated.props["variable"].value == "'one one one'"
assert updated.body == "'one one one'"
def test_concept_property_is_correctly_updated_when_list_of_properties():
foo = Concept("foo")
grammar = {foo: Sequence(StrMatch("one", rule_name="s"), StrMatch("two", rule_name="s"), rule_name="variable")}
context, node = init(foo, grammar, "one two")
updated = ConceptNodeEvaluator().finalize_concept(
context.sheerka,
context.sheerka.new(node.concept.key),
node.underlying)
assert updated.props["variable"].value == "'one two'"
assert updated.props["s"].value == ["'one'", "'two'"]
assert updated.body == "'one two'"
def test_concept_property_is_correctly_updated_when_another_concept():
foo = Concept("foo")
bar = Concept("bar")
grammar = {
foo: Sequence("one", "two", rule_name="var"),
bar: Sequence(foo, "three", "four", rule_name="var")}
context, node = init([foo, bar], grammar, "one two three four")
updated = ConceptNodeEvaluator().finalize_concept(
context.sheerka,
context.sheerka.new(node.concept.key),
node.underlying)
assert updated.body == "foo 'three four'"
assert updated.props["var"].value == "foo 'three four'"
assert updated.props["foo"].value == Concept("foo", body="'one two'").set_prop("var", "'one two'").init_key()
def test_concept_property_is_correctly_updated_when_concept_recursion_using_optional():
number = Concept("number")
add = Concept("add")
grammar = {
number: OrderedChoice("one", "two"),
add: Sequence(number, Optional(Sequence(OrderedChoice("plus", "minus", rule_name="op"), add)))
}
context, node = init([number, add], grammar, "one plus two")
updated = ConceptNodeEvaluator().finalize_concept(
context.sheerka,
context.sheerka.new(node.concept.key),
node.underlying)
assert updated.props["number"].value == Concept("number", body="'one'").init_key()
assert updated.props["op"].value == "'plus'"
expected_add = Concept("add", body="number"). \
set_prop("number", Concept("number", body="'two'").init_key()). \
init_key()
assert updated.props["add"].value == expected_add
def test_concept_property_is_correctly_updated_when_concept_recursion_using_zero_or_more():
number = Concept("number")
add = Concept("add")
grammar = {
number: OrderedChoice("one", "two", 'three'),
add: Sequence(number, ZeroOrMore(Sequence(OrderedChoice("plus", "minus", rule_name="op"), number)))
}
context, node = init([number, add], grammar, "one plus two minus three")
updated = ConceptNodeEvaluator().finalize_concept(
context.sheerka,
context.sheerka.new(node.concept.key),
node.underlying,
init_empty_body=True)
assert updated.props["number"].value == [Concept("number", body="'one'").init_key(),
Concept("number", body="'two'").init_key(),
Concept("number", body="'three'").init_key()]
assert updated.props["op"].value == ["'plus'", "'minus'"]
+160
View File
@@ -0,0 +1,160 @@
from core.builtin_concepts import ParserResultConcept, BuiltinConcepts
from core.concept import Concept
from core.sheerka import Sheerka, ExecutionContext
from parsers.ConceptLexerParser import ConceptLexerParser, ConceptNode, Sequence, UnrecognizedTokensNode
from parsers.MultipleConceptsParser import MultipleConceptsParser
from sdp.sheerkaDataProvider import Event
def get_context():
sheerka = Sheerka(skip_builtins_in_db=True)
sheerka.initialize("mem://")
return ExecutionContext("test", Event(), sheerka)
def get_return_value(context, grammar, expression):
parser = ConceptLexerParser()
parser.initialize(context, grammar)
ret_val = parser.parse(context, expression)
assert not ret_val.status
return ret_val
def init(concepts, grammar, expression):
context = get_context()
for c in concepts:
context.sheerka.create_new_concept(context, c)
return_value = get_return_value(context, grammar, expression)
return context, return_value
def test_not_interested_if_not_parser_result():
context = get_context()
text = "not parser result"
res = MultipleConceptsParser().parse(context, text)
assert res is None
def test_not_interested_if_not_from_concept_lexer_parser():
context = get_context()
text = ParserResultConcept(parser="not concept lexer", value="some value")
res = MultipleConceptsParser().parse(context, text)
assert res is None
def test_i_can_parse_exact_concepts():
foo = Concept("foo", body="'foo'")
bar = Concept("bar", body="'bar'")
baz = Concept("baz", body="'baz'")
grammar = {}
context, return_value = init([foo, bar, baz], grammar, "bar foo baz")
parser = MultipleConceptsParser()
ret_val = parser.parse(context, return_value.body)
assert ret_val.status
assert ret_val.who == parser.name
assert context.sheerka.isinstance(ret_val.value, BuiltinConcepts.PARSER_RESULT)
assert ret_val.value.value == [
ConceptNode(bar, 0, 0, source="bar"),
ConceptNode(foo, 2, 2, source="foo"),
ConceptNode(baz, 4, 4, source="baz")]
assert ret_val.value.source == "bar foo baz"
def test_i_can_parse_when_ending_with_bnf():
foo = Concept("foo", body="'foo'")
bar = Concept("bar", body="'bar'")
grammar = {foo: Sequence("foo1", "foo2", "foo3")}
context, return_value = init([foo, bar], grammar, "bar foo1 foo2 foo3")
parser = MultipleConceptsParser()
ret_val = parser.parse(context, return_value.body)
assert ret_val.status
assert ret_val.who == parser.name
assert context.sheerka.isinstance(ret_val.value, BuiltinConcepts.PARSER_RESULT)
assert ret_val.value.value == [("bar", 0, 0, "bar"), ("foo", 2, 6, "foo1 foo2 foo3")]
assert ret_val.value.source == "bar foo1 foo2 foo3"
def test_i_can_parse_when_starting_with_bnf():
foo = Concept("foo", body="'foo'")
bar = Concept("bar", body="'bar'")
grammar = {foo: Sequence("foo1", "foo2", "foo3")}
context, return_value = init([foo, bar], grammar, "foo1 foo2 foo3 bar")
parser = MultipleConceptsParser()
ret_val = parser.parse(context, return_value.body)
assert ret_val.status
assert ret_val.who == parser.name
assert context.sheerka.isinstance(ret_val.value, BuiltinConcepts.PARSER_RESULT)
assert ret_val.value.value == [("foo", 0, 4, "foo1 foo2 foo3"), ("bar", 6, 6, "bar")]
assert ret_val.value.source == "foo1 foo2 foo3 bar"
def test_i_can_parse_when_concept_are_mixed():
foo = Concept("foo")
bar = Concept("bar")
baz = Concept("baz")
grammar = {foo: Sequence("foo1", "foo2", "foo3")}
context, return_value = init([foo, bar, baz], grammar, "baz foo1 foo2 foo3 bar")
parser = MultipleConceptsParser()
ret_val = parser.parse(context, return_value.body)
assert ret_val.status
assert ret_val.who == parser.name
assert context.sheerka.isinstance(ret_val.value, BuiltinConcepts.PARSER_RESULT)
assert ret_val.value.value == [
("baz", 0, 0, "baz"),
("foo", 2, 6, "foo1 foo2 foo3"),
("bar", 8, 8, "bar")]
assert ret_val.value.source == "baz foo1 foo2 foo3 bar"
def test_i_can_parse_when_multiple_concept_are_matching():
foo = Concept("foo")
bar = Concept("bar", body="bar1")
baz = Concept("bar", body="bar2")
grammar = {foo: "foo"}
context, return_value = init([foo, bar, baz], grammar, "foo bar")
parser = MultipleConceptsParser()
ret_val = parser.parse(context, return_value.body)
assert len(ret_val) == 2
assert ret_val[0].status
assert ret_val[0].value.value == [("foo", 0, 0, "foo"), ("bar", 2, 2, "bar")]
assert ret_val[0].value.source == "foo bar"
assert ret_val[0].value.value[1].concept.body == "bar1"
assert ret_val[1].status
assert ret_val[1].value.value == [("foo", 0, 0, "foo"), ("bar", 2, 2, "bar")]
assert ret_val[1].value.source == "foo bar"
assert ret_val[1].value.value[1].concept.body == "bar2"
def test_i_cannot_parse_when_unrecognized_token():
twenty_two = Concept("twenty two")
one = Concept("one")
grammar = {twenty_two: Sequence("twenty", "two")}
context, return_value = init([twenty_two, one], grammar, "twenty two + one")
parser = MultipleConceptsParser()
ret_val = parser.parse(context, return_value.body)
assert not ret_val.status
assert ret_val.who == parser.name
assert context.sheerka.isinstance(ret_val.value, BuiltinConcepts.PARSER_RESULT)
assert ret_val.value.value == [
("twenty two", 0, 2, "twenty two"),
(3, 5, " + "),
("one", 6, 6, "one")
]
assert ret_val.value.source == "twenty two + one"
+23
View File
@@ -126,3 +126,26 @@ def test_i_can_eval_concept_token():
assert not evaluated.status
assert evaluated.body.body.args[0] == "'int' object has no attribute 'name'"
@pytest.mark.parametrize("text, concept_key, concept_id, use_concept", [
("__C__key__C__", "key", None, False),
("__C__key__id__C__", "key", "id", False),
("__C__USE_CONCEPT__key__id__C__", "key", "id", True),
("__C__USE_CONCEPT__key__id__C__", "key", "id", True),
])
def test_i_can_resolve_name(text, concept_key, concept_id, use_concept):
context = get_context()
assert PythonEvaluator().resolve_name(context, text) == (concept_key, concept_id, use_concept)
@pytest.mark.parametrize("text", [
"__C__",
"__C__key",
"__C__key____",
"__C____",
"__C__USE_CONCEPT__",
])
def test_i_cannot_resolve_name(text):
context = get_context()
assert PythonEvaluator().resolve_name(context, text) is None
+1 -1
View File
@@ -86,4 +86,4 @@ def test_i_can_parse_a_concept():
assert res
assert res.value.value == PythonNode(
"c:concept_name: + 1",
ast.parse("__C__concept_name__C__+1", mode="eval"))
ast.parse("__C__USE_CONCEPT__concept_name__C__+1", mode="eval"))
+142
View File
@@ -0,0 +1,142 @@
import ast
import pytest
from core.builtin_concepts import ParserResultConcept, BuiltinConcepts, ReturnValueConcept
from core.concept import Concept
from core.sheerka import Sheerka, ExecutionContext
from core.tokenizer import Token, TokenKind, Tokenizer
from parsers.ConceptLexerParser import ConceptNode, UnrecognizedTokensNode
from parsers.PythonParser import PythonNode, PythonErrorNode
from parsers.PythonWithConceptsParser import PythonWithConceptsParser
from sdp.sheerkaDataProvider import Event
def get_context():
sheerka = Sheerka(skip_builtins_in_db=True)
sheerka.initialize("mem://")
return ExecutionContext("test", Event(), sheerka)
def get_ret_from(*args):
result = []
index = 0
for item in args:
if isinstance(item, Concept):
tokens = [Token(TokenKind.IDENTIFIER, item.name, 0, 0, 0)]
result.append(ConceptNode(item, index, index, tokens, item.name))
index += 1
else:
tokens = list(Tokenizer(item))
result.append(UnrecognizedTokensNode(index, index + len(tokens) - 1, tokens))
index += len(tokens)
return ReturnValueConcept("who", False, ParserResultConcept(parser="name", value=result))
def to_str_ast(expression):
return PythonNode.get_dump(ast.parse(expression, mode="eval"))
@pytest.mark.parametrize("text", [
"not parser result",
ParserResultConcept(value="not a list"),
ParserResultConcept(value=[]),
ParserResultConcept(value=["not a Node"]),
])
def test_not_interested(text):
context = get_context()
res = PythonWithConceptsParser().parse(context, text)
assert res is None
def test_i_can_parse_concepts_and_python():
context = get_context()
foo = Concept("foo")
input_return_value = get_ret_from(foo, " + 1")
parser = PythonWithConceptsParser()
result = parser.parse(context, input_return_value.body)
wrapper = result.value
return_value = result.value.value
assert result.status
assert result.who == parser.name
assert context.sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
assert wrapper.source == "foo + 1"
assert isinstance(return_value, PythonNode)
assert return_value.source == "foo + 1"
assert return_value.get_dump(return_value.ast_) == to_str_ast("__C__foo__C__ + 1")
assert return_value.concepts["__C__foo__C__"] == foo
def test_i_can_parse_concepts_and_python_when_concept_is_known():
context = get_context()
foo = Concept("foo")
foo = context.sheerka.create_new_concept(context, foo).body.body
input_return_value = get_ret_from(foo, " + 1")
parser = PythonWithConceptsParser()
result = parser.parse(context, input_return_value.body)
wrapper = result.value
return_value = result.value.value
assert result.status
assert result.who == parser.name
assert context.sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
assert wrapper.source == "foo + 1"
assert isinstance(return_value, PythonNode)
assert return_value.source == "foo + 1"
assert return_value.get_dump(return_value.ast_) == to_str_ast("__C__foo__1001__C__ + 1")
assert return_value.concepts["__C__foo__1001__C__"] == foo
def test_i_can_parse_when_concept_name_has_invalid_characters():
context = get_context()
foo = Concept("foo et > (,")
foo = context.sheerka.create_new_concept(context, foo).body.body
input_return_value = get_ret_from(foo, " + 1")
parser = PythonWithConceptsParser()
result = parser.parse(context, input_return_value.body)
return_value = result.value.value
assert result.status
assert return_value.concepts["__C__foo0et000000__1001__C__"] == foo
def test_python_ids_mappings_are_correct_when_concepts_with_the_same_name():
context = get_context()
foo1 = Concept("foo")
foo2 = Concept("foo")
foo3 = context.sheerka.create_new_concept(context, Concept("foo", body="foo3")).body.body
foo4 = context.sheerka.create_new_concept(context, Concept("foo", body="foo4")).body.body
input_return_value = get_ret_from(foo1, "+", foo2, "+", foo3, "+", foo4)
parser = PythonWithConceptsParser()
result = parser.parse(context, input_return_value.body)
return_value = result.value.value
assert result.status
assert return_value.concepts["__C__foo__C__"] == foo1
assert return_value.concepts["__C__foo_1__C__"] == foo2
assert return_value.concepts["__C__foo__1001__C__"] == foo3
assert return_value.concepts["__C__foo__1002__C__"] == foo4
def test_i_cannot_parse_if_syntax_error():
context = get_context()
foo = Concept("foo")
foo = context.sheerka.create_new_concept(context, foo).body.body
input_return_value = get_ret_from(foo, " + ")
parser = PythonWithConceptsParser()
result = parser.parse(context, input_return_value.body)
wrapper = result.value
return_value = result.value.value
assert not result.status
assert context.sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
assert isinstance(return_value[0], PythonErrorNode)
+48 -1
View File
@@ -144,7 +144,7 @@ def test_i_can_get_a_builtin_concept_by_their_enum_or_the_string():
assert sheerka.get(str(key)) is not None
def test_i_can_get_new_concept():
def test_i_can_get_a_newly_created_concept():
sheerka = get_sheerka()
concept = get_default_concept()
@@ -324,6 +324,21 @@ def test_i_can_instantiate_a_concept():
assert new.props["b"].value == "value"
def test_i_can_instantiate_with_the_name_and_the_id():
sheerka = get_sheerka()
sheerka.create_new_concept(get_context(sheerka), Concept("foo", body="foo1"))
sheerka.create_new_concept(get_context(sheerka), Concept("foo", body="foo2"))
concepts = sheerka.new("foo")
assert len(concepts) == 2
foo1 = sheerka.new(("foo", "1001"))
assert foo1.body == "foo1"
foo2 = sheerka.new(("foo", "1002"))
assert foo2.body == "foo2"
def test_instances_are_different_when_asking_for_new():
sheerka = get_sheerka()
concept = get_default_concept()
@@ -357,6 +372,38 @@ def test_i_cannot_instantiate_an_unknown_concept():
assert new.body == "fake_concept"
def test_i_cannot_instantiate_with_invalid_id():
sheerka = get_sheerka()
sheerka.create_new_concept(get_context(sheerka), Concept("foo", body="foo1"))
sheerka.create_new_concept(get_context(sheerka), Concept("foo", body="foo2"))
new = sheerka.new(("foo", "invalid_id"))
assert sheerka.isinstance(new, BuiltinConcepts.UNKNOWN_CONCEPT)
assert new.body == "foo"
def test_i_cannot_instantiate_with_invalid_key():
sheerka = get_sheerka()
sheerka.create_new_concept(get_context(sheerka), Concept("foo", body="foo1"))
sheerka.create_new_concept(get_context(sheerka), Concept("foo", body="foo2"))
new = sheerka.new(("invalid_key", "1001"))
assert sheerka.isinstance(new, BuiltinConcepts.UNKNOWN_CONCEPT)
assert new.body == "invalid_key"
def test_concept_id_is_irrelevant_when_only_one_concept():
sheerka = get_sheerka()
sheerka.create_new_concept(get_context(sheerka), Concept("foo", body="foo1"))
new = sheerka.new(("foo", "invalid_id"))
assert sheerka.isinstance(new, "foo")
assert new.body == "foo1"
def test_i_cannot_instantiate_when_properties_are_not_recognized():
sheerka = get_sheerka()
concept = get_default_concept()
+42
View File
@@ -401,6 +401,48 @@ def test_i_can_eval_bnf_definitions_from_separate_instances():
assert res[0].value.props["a"] == Property("a", sheerka.new(concept_a.key, body="one two").init_key())
def test_i_can_eval_a_mix_with_bnf_and_python():
sheerka = get_sheerka()
sheerka.evaluate_user_input("def concept one as 1")
sheerka.evaluate_user_input("def concept twenties from bnf 'twenty' one as 20 + one")
res = sheerka.evaluate_user_input("twenty one + 1")
assert len(res) == 1
assert res[0].status
assert res[0].body == 22
def test_i_can_eval_a_mix_with_bnf_and_python_when_rule_name():
sheerka = get_sheerka()
sheerka.evaluate_user_input("def concept one as 1")
sheerka.evaluate_user_input("def concept two as 2")
sheerka.evaluate_user_input("def concept twenties from bnf 'twenty' (one|two)=unit as 20 + unit")
assert sheerka.evaluate_user_input("eval twenty one")[0].body == 21
res = sheerka.evaluate_user_input("twenty one + 1")
assert len(res) == 1
assert res[0].status
assert res[0].body == 22
def test_i_can_eval_a_more_complicated_mix_with_bnf_and_python():
sheerka = get_sheerka()
sheerka.evaluate_user_input("def concept one as 1")
sheerka.evaluate_user_input("def concept two as 2")
sheerka.evaluate_user_input("def concept twenties from bnf 'twenty' (one|two)=unit as 20 + unit")
assert sheerka.evaluate_user_input("eval twenty one")[0].body == 21
res = sheerka.evaluate_user_input("twenty one + twenty two")
assert len(res) == 1
assert res[0].status
assert res[0].body == 43
def test_i_can_say_that_a_concept_isa_another_concept():
sheerka = get_sheerka()
sheerka.evaluate_user_input("def concept foo")