Fixed #32 : concept groups are not correctly updated

Fixed #35 : Refactor test helper class (CNC, CC, CIO)
Fixed #36 : Concept values are not used when declared with variable expression
Fixed #37 : Objects in memory lose their values are restart
Fixed #38 : func(a=b, c) (which is not allowed) raise an exception
This commit is contained in:
2021-03-05 11:16:19 +01:00
parent 646c428edb
commit 05577012f3
38 changed files with 1942 additions and 1463 deletions
+842 -31
View File
@@ -1,13 +1,16 @@
import ast
from dataclasses import dataclass
from typing import Union
from core.builtin_concepts import ReturnValueConcept
from core.builtin_helpers import CreateObjectIdentifiers
from core.concept import CC, Concept, ConceptParts, DoNotResolve, CIO, CMV
from core.concept import Concept, ConceptParts, DoNotResolve, AllConceptParts
from core.rule import Rule
from core.tokenizer import Tokenizer, TokenKind, Token
from core.utils import get_text_from_tokens, tokens_index
from parsers.BaseNodeParser import scnode, utnode, cnode, SCWC, CNC, short_cnode, CN, UTN, \
SCN, RN, UnrecognizedTokensNode, SourceCodeNode
from core.utils import get_text_from_tokens, tokens_index, str_concept
from parsers.BaseNodeParser import UnrecognizedTokensNode, SourceCodeNode, RuleNode, ConceptNode, \
SourceCodeWithConceptNode
from parsers.FunctionParser import FunctionNode
from parsers.PythonParser import PythonNode
from parsers.SyaNodeParser import SyaConceptParserHelper
from parsers.expressions import NameExprNode, AndNode, OrNode, NotNode, VariableNode, ComparisonNode, ComparisonType
@@ -115,6 +118,825 @@ class NIN: # for NOT INT
source = None
class CC:
"""
Concept class for test purpose
CC means concept for compiled (or concept with compiled)
It matches a concept if the compiles are equals
"""
# The only properties that are testes are concept_key and compiled
# The other properties (concept, source, start and end)
# are used in tests/parsers/parsers_utils.py to help creating helper objects
def __init__(self, concept, source=None, exclude_body=False, **kwargs):
self.concept_key = concept.key if isinstance(concept, Concept) else concept
self.compiled = kwargs
self.concept = concept if isinstance(concept, Concept) else None
self.source = source # to use when the key is different from the sub str to search when filling start and stop
self.start = None # for debug purpose, indicate where the concept starts
self.end = None # for debug purpose, indicate where the concept ends
self.exclude_body = exclude_body
if "body" in self.compiled:
self.compiled[ConceptParts.BODY] = self.compiled["body"]
del self.compiled["body"]
def __eq__(self, other):
if id(self) == id(other):
return True
if isinstance(other, Concept):
if other.key != self.concept_key:
return False
if self.exclude_body:
to_compare = {k: v for k, v in other.get_compiled().items() if k != ConceptParts.BODY}
else:
to_compare = other.get_compiled()
if self.compiled == to_compare:
return True
else:
return False
if not isinstance(other, CC):
return False
if self.concept_key != other.concept_key:
return False
return self.compiled == other.compiled
def __hash__(self):
if self.concept:
return hash(self.concept)
return hash(self.concept_key)
def __repr__(self):
if self.concept:
txt = f"CC(concept='{self.concept}'"
else:
txt = f"CC(concept_key='{self.concept_key}'"
for k, v in self.compiled.items():
txt += f", {k}='{v}'"
return txt + ")"
def fix_pos(self, node):
start = node.start if hasattr(node, "start") else \
node[0] if isinstance(node, tuple) else None
end = node.end if hasattr(node, "end") else \
node[1] if isinstance(node, tuple) else None
if start is not None:
if self.start is None or start < self.start:
self.start = start
if end is not None:
if self.end is None or end > self.end:
self.end = end
return self
def transform_real_obj(self, other, to_compare_delegate):
"""
Transform other into CNC, to ease the comparison
:param other:
:param to_compare_delegate:
:return:
"""
if isinstance(other, CC):
return other
if isinstance(other, Concept):
if self.exclude_body:
compiled = {k: v for k, v in other.get_compiled().items() if k != ConceptParts.BODY}
else:
compiled = other.get_compiled()
self_compile_to_use = self.compiled or compiled
compiled = to_compare_delegate(self_compile_to_use, compiled, to_compare_delegate)
return CC(other,
self.source,
self.exclude_body,
**compiled)
raise NotImplementedError(f"CC, {other=}")
class CB:
"""
Concept with body only
Test class that tests only the body of the concept
"""
def __init__(self, concept: Union[str, Concept], body: object):
self.concept_key = concept.key if isinstance(concept, Concept) else concept
self.concept = concept if isinstance(concept, Concept) else None
self.body = body
def __eq__(self, other):
if not isinstance(other, CB):
return False
return self.concept_key == other.concept_key and self.body == other.body
def __hash__(self):
return hash((self.concept, self.body))
def __repr__(self):
concept_debug = f"concept={self.concept}" if self.concept else f"concept_key={self.concept_key}"
return f"CB({concept_debug}, body='{self.body}')"
def transform_real_obj(self, other, get_test_obj_delegate):
if isinstance(other, CB):
return other
if isinstance(other, Concept):
concept = other.key if not self.concept else other
if isinstance(other.body, Concept):
body = get_test_obj_delegate(other.body, self.body, get_test_obj_delegate)
else:
body = other.body
return CB(concept, body)
raise NotImplementedError(f"CB, {other=}")
class CV:
"""
Concept with all values
Test class that tests all the values (not the metadata, so not the properties) of a concept
"""
def __init__(self, concept, **kwargs):
self.concept_key = concept.key if isinstance(concept, Concept) else concept
self.concept = concept if isinstance(concept, Concept) else None
self.values = {}
for k, v in kwargs.items():
if f"#{k}#" in AllConceptParts:
self.values[f"#{k}#"] = v
else:
self.values[k] = v
def __eq__(self, other):
if not isinstance(other, CV):
return False
return self.concept_key == other.concept_key and self.values == other.values
def __hash__(self):
return hash((self.concept_key, self.values))
def __repr__(self):
concept_debug = f"concept={self.concept}" if self.concept else f"concept_key={self.concept_key}"
return f"CV({concept_debug}, values={self.values})"
def transform_real_obj(self, other, get_test_obj_delegate):
if isinstance(other, CV):
return other
if isinstance(other, Concept):
concept = other.key if not self.concept else other
values = get_test_obj_delegate(other.values(), self.values, get_test_obj_delegate)
return CV(concept, **values)
raise NotImplementedError(f"CV, {other=}")
class CMV:
"""
Concept with metadata variables
CMV stands for Concept Metadata Variables
Test class that only compare the key and the metadata variables
"""
def __init__(self, concept, **kwargs):
self.concept_key = concept.key if isinstance(concept, Concept) else concept
self.concept = concept if isinstance(concept, Concept) else None
self.variables = kwargs
def __eq__(self, other):
if id(self) == id(other):
return True
if not isinstance(other, CMV):
return False
if self.concept_key != other.concept_key:
return False
return self.variables == other.variables
def __hash__(self):
if self.concept:
return hash(self.concept)
return hash(self.concept_key)
def __repr__(self):
if self.concept:
txt = f"CMV(concept='{self.concept}'"
else:
txt = f"CMV(concept_key='{self.concept_key}'"
for k, v in self.variables.items():
txt += f", {k}='{v}'"
return txt + ")"
def transform_real_obj(self, other, get_test_obj_delegate):
if isinstance(other, CMV):
return other
if isinstance(other, Concept):
concept = other.key if not self.concept else other
variables = {name: value for name, value in other.get_metadata().variables}
return CMV(concept, **variables)
raise NotImplementedError(f"CMV, {other=}")
class CIO:
"""
Concept id only
only test the id
"""
def __init__(self, concept, source=None):
if isinstance(concept, str):
self.concept_name = concept
self.concept_id = None
self.concept = None
elif isinstance(concept, Concept):
self.concept_id = concept.id
self.concept = concept
self.source = source
self.start = None
self.end = None
def set_concept(self, concept):
self.concept = concept
self.concept_id = concept.id
def __eq__(self, other):
if id(self) == id(other):
return True
if not isinstance(other, CIO):
return False
return self.concept_id == other.concept_id
def __hash__(self):
return hash(self.concept_id)
def __repr__(self):
return f"CIO(concept='{self.concept}')" if self.concept else f"CIO(name='{self.concept_name}')"
def transform_real_obj(self, other, get_test_obj_delegate):
if isinstance(other, CIO):
return other
if isinstance(other, Concept):
return CIO(other)
raise NotImplementedError(f"CIO, {other=}")
class HelperWithPos:
def __init__(self, start=None, end=None):
self.start = start
self.end = end
self.start_is_fixed = start is not None
self.end_is_fixed = end is not None
def fix_pos(self, node):
if not self.start_is_fixed:
start = node.start if hasattr(node, "start") else \
node[0] if isinstance(node, tuple) else None
if start is not None and (self.start is None or start < self.start):
self.start = start
if not self.end_is_fixed:
end = node.end if hasattr(node, "end") else \
node[1] if isinstance(node, tuple) else None
if end is not None and (self.end is None or end > self.end):
self.end = end
return self
class SCN(HelperWithPos):
"""
SourceCodeNode tester class
It matches with SourceCodeNode but with less constraints
SCN == SourceCodeNode if source, start, end (start and end are not validated when None)
"""
def __init__(self, source, start=None, end=None):
super().__init__(start, end)
self.source = source
def __eq__(self, other):
if id(self) == id(other):
return True
if isinstance(other, SourceCodeNode):
if self.source != other.source:
return False
if self.start is not None and self.start != other.start:
return False
if self.end is not None and self.end != other.end:
return False
return True
if not isinstance(other, SCN):
return False
return self.source == other.source and \
self.start == other.start and \
self.end == other.end
def __hash__(self):
return hash((self.source, self.start, self.end))
def __repr__(self):
txt = f"SCN(source='{self.source}'"
if self.start is not None:
txt += f", start={self.start}"
if self.end is not None:
txt += f", end={self.end}"
return txt + ")"
def transform_real_obj(self, other, to_compare_delegate):
"""
Transform other into CNC, to ease the comparison
:param other:
:param to_compare_delegate:
:return:
"""
if isinstance(other, SCN):
return other
if isinstance(other, SourceCodeNode):
return SCN(other.source,
other.start if self.start is not None else None,
other.end if self.end is not None else None)
raise NotImplementedError(f"SCN, {other=}")
class SCWC(HelperWithPos):
"""
SourceNodeWithConcept tester class
It matches with a SourceNodeWithConcept
but it's easier to instantiate during the tests
"""
def __init__(self, first, last, *args):
super().__init__(None, None)
self.first = first
self.last = last
self.content = list(args)
def __eq__(self, other):
if id(self) == id(other):
return True
if isinstance(other, SourceCodeWithConceptNode):
if self.first != other.first:
return False
if self.last != other.last:
return False
if len(self.content) != len(other.nodes):
return False
for self_node, other_node in zip(self.content, other.nodes):
if self_node != other_node:
return False
# at last
return True
if not isinstance(other, SCWC):
return False
return (self.start == other.start and
self.end == other.end and
self.first == other.first and
self.last == other.last and
self.content == other.content)
def __repr__(self):
txt = "SCWC("
if self.start is not None:
txt += f"start={self.start}"
if self.end is not None:
txt += f", end={self.end}"
for item in [self.first, self.last, *self.content]:
txt += f", {item}"
return txt + ")"
def transform_real_obj(self, other, get_test_obj_delegate):
"""
Transform other into CNC, to ease the comparison
:param other:
:param get_test_obj_delegate:
:return:
"""
if isinstance(other, SCWC):
return other
if isinstance(other, SourceCodeWithConceptNode):
first = get_test_obj_delegate(other.first, self.first)
last = get_test_obj_delegate(other.last, self.last)
content = [get_test_obj_delegate(r, t) for r, t in zip(other.nodes, self.content)]
res = SCWC(first, last, *content)
res.start = other.start
res.end = other.end
return res
raise NotImplementedError(f"SCWC, {other=}")
@property
def source(self):
"""
this code is a copy and paste from SourceCodeWithConceptNode.pseudo_fix_source
TODO: create a common function or whatever...
:return:
"""
source = self.first.source if hasattr(self.first, "source") else self.first
for n in self.content:
source += " "
if hasattr(n, "source"):
source += n.source
elif hasattr(n, "concept"):
source += str(n.concept)
else:
source += " unknown"
source += self.last.source if hasattr(self.last, "source") else self.last
return source
class CN(HelperWithPos):
"""
ConceptNode tester class
It matches with ConceptNode but with less constraints
CN == ConceptNode if concept key, start, end and source are the same
"""
def __init__(self, concept, source=None, start=None, end=None):
"""
:param concept: Concept or concept_key (only the key is used anyway)
:param start:
:param end:
:param source:
"""
super().__init__(start, end)
self.concept_key = concept.key if isinstance(concept, Concept) else concept
self.source = source
self.concept = concept if isinstance(concept, Concept) else None
def fix_source(self, str_tokens):
self.source = "".join(str_tokens)
return self
def __eq__(self, other):
if id(self) == id(other):
return True
if not isinstance(other, CN):
return False
return self.concept_key == other.concept_key and \
self.start == other.start and \
self.end == other.end and \
self.source == other.source
def __hash__(self):
return hash((self.concept_key, self.start, self.end, self.source))
def __repr__(self):
if self.concept:
txt = f"CN(concept='{self.concept}'"
else:
txt = f"CN(concept_key='{self.concept_key}'"
txt += f", source='{self.source}'"
if self.start is not None:
txt += f", start={self.start}"
if self.end is not None:
txt += f", end={self.end}"
return txt + ")"
def transform_real_obj(self, other, get_test_obj_delegate):
"""
Transform other into CNC, to ease the comparison
:param other:
:param get_test_obj_delegate:
:return:
"""
if isinstance(other, CN):
return other
if isinstance(other, ConceptNode):
return CN(other.concept,
other.source if self.source is not None else None,
other.start if self.start is not None else None,
other.end if self.end is not None else None)
raise NotImplementedError(f"CN, {other=}")
class CNC(CN):
"""
ConceptNode for Compiled tester class
It matches with ConceptNode
But focuses on the 'compiled' property of the concept
CNC == ConceptNode if CNC.get_compiled() == ConceptNode.concept.get_compiled()
"""
def __init__(self, concept_key, source=None, start=None, end=None, exclude_body=False, **kwargs):
super().__init__(concept_key, source, start, end)
self.compiled = kwargs
self.exclude_body = exclude_body
if "body" in self.compiled:
self.compiled[ConceptParts.BODY] = self.compiled["body"]
del self.compiled["body"]
def __eq__(self, other):
if id(self) == id(other):
return True
if not isinstance(other, CNC):
return False
return self.concept_key == other.concept_key and \
self.start == other.start and \
self.end == other.end and \
self.source == other.source and \
self.compiled == other.compiled
def __repr__(self):
if self.concept:
txt = f"CNC(concept='{self.concept}'"
else:
txt = f"CNC(concept_key='{self.concept_key}'"
txt += f", source='{self.source}'"
if self.start is not None:
txt += f", start={self.start}"
if self.end is not None:
txt += f", end={self.end}"
for k, v in self.compiled.items():
txt += f", {k}='{v}'"
return txt + ")"
def transform_real_obj(self, other, get_test_obj_delegate):
"""
Transform other into CNC, to ease the comparison
:param other:
:param get_test_obj_delegate:
:return:
"""
if isinstance(other, CNC):
return other
if isinstance(other, ConceptNode):
if self.exclude_body:
compiled = {k: v for k, v in other.concept.get_compiled().items() if k != ConceptParts.BODY}
else:
compiled = other.concept.get_compiled()
self_compile_to_use = self.compiled or compiled
compiled = get_test_obj_delegate(self_compile_to_use, compiled, get_test_obj_delegate)
return CNC(other.concept,
other.source if self.source is not None else None,
other.start if self.start is not None else None,
other.end if self.end is not None else None,
self.exclude_body,
**compiled)
raise NotImplementedError(f"CNC, {other=}")
class UTN(HelperWithPos):
"""
Tester class for UnrecognizedTokenNode
compare the source, and start, end if defined
"""
def __init__(self, source, start=None, end=None):
"""
:param source:
:param start:
:param end:
"""
super().__init__(start, end)
self.source = source
def __eq__(self, other):
if id(self) == id(other):
return True
if isinstance(other, UnrecognizedTokensNode):
return self.start == other.start and \
self.end == other.end and \
self.source == other.source
if not isinstance(other, UTN):
return False
return self.start == other.start and \
self.end == other.end and \
self.source == other.source
def __hash__(self):
return hash((self.source, self.start, self.end))
def __repr__(self):
txt = f"UTN(source='{self.source}'"
if self.start is not None:
txt += f", start={self.start}"
if self.end is not None:
txt += f", end={self.end}"
return txt + ")"
def transform_real_obj(self, other, get_test_obj_delegate):
"""
Transform other into CNC, to ease the comparison
:param other:
:param get_test_obj_delegate:
:return:
"""
if isinstance(other, UTN):
return other
if isinstance(other, UnrecognizedTokensNode):
return UTN(other.source,
other.start,
other.end)
raise NotImplementedError(f"UTN, {other=}")
class RN(HelperWithPos):
"""
Helper class to test RuleNode
"""
def __init__(self, rule, source=None, start=None, end=None):
"""
:param source:
:param start:
:param end:
"""
super().__init__(start, end)
self.rule_id = rule.id if isinstance(rule, Rule) else rule
self.source = source or str_concept((None, self.rule_id), prefix="r:") if self.rule_id else None
self.rule = rule if isinstance(rule, Rule) else None
def __eq__(self, other):
if id(self) == id(other):
return True
if not isinstance(other, RN):
return False
return self.rule_id == other.rule_id and \
self.start == other.start and \
self.end == other.end and \
self.source == other.source
def __hash__(self):
return hash((self.rule_id, self.start, self.end, self.source))
def __repr__(self):
if self.rule:
txt = f"RN(rule='{self.rule}'"
else:
txt = f"RN(rule_id='{self.rule_id}'"
txt += f", source='{self.source}'"
if self.start is not None:
txt += f", start={self.start}"
if self.end is not None:
txt += f", end={self.end}"
return txt + ")"
def transform_real_obj(self, other, get_test_obj_delegate):
"""
Transform other into CNC, to ease the comparison
:param other:
:param get_test_obj_delegate:
:return:
"""
if isinstance(other, RN):
return other
if isinstance(other, RuleNode):
return RN(other.rule,
other.source if self.source is not None else None,
other.start if self.start is not None else None,
other.end if self.end is not None else None)
raise NotImplementedError(f"RN, {other=}")
class FN:
"""
Test class only
It matches with FunctionNode but with less constraints
Thereby,
FN("first", "last", ["param1," ...]) can be compared to
FunctionNode(NameExprNode("first"), NameExprNode("second"), [FunctionParameter(NamesNodes("param1"), NamesNodes(", ")])
Note that FunctionParameter can easily be defined with a single string
* "param" -> FunctionParameter(NameExprNode("param"), None)
* "param, " -> FunctionParameter(NameExprNode("param"), NameExprNode(", "))
For more complicated situations, you can use a tuple (value, sep) to define the value part and the separator part
"""
def __init__(self, first, last, parameters):
self.first = first
self.last = last
self.parameters = []
for param in parameters:
if isinstance(param, tuple):
self.parameters.append(param)
elif isinstance(param, str) and (pos := param.find(",")) != -1:
self.parameters.append((param[:pos], param[pos:]))
else:
self.parameters.append((param, None))
def __repr__(self):
res = self.first
for param in self.parameters:
if param[1]:
res += f"{param[0]}{param[1]} "
else:
res += f"{param[0]}"
return res + self.last
def __eq__(self, other):
if id(self) == id(other):
return True
if isinstance(other, FN):
return self.first == other.first and self.last == other.last and self.parameters == other.parameters
# if isinstance(other, FunctionNode):
# if self.first != other.first.value or self.last != other.last.value:
# return False
# if len(self.parameters) != len(other.parameters):
# return False
# for self_parameter, other_parameter in zip(self.parameters, other.parameters):
# value = other_parameter.value.value if isinstance(self_parameter[0], str) else other_parameter.value
# sep = other_parameter.separator.value if other_parameter.separator else None
# if self_parameter[0] != value or self_parameter[1] != sep:
# return False
#
# return True
return False
def __hash__(self):
return hash((self.first, self.last, self.parameters))
def transform_real_obj(self, other, get_test_obj_delegate):
if isinstance(other, FN):
return other
if isinstance(other, FunctionNode):
params = []
for self_parameter, other_parameter in zip(self.parameters, other.parameters):
if isinstance(self_parameter[0], str):
value = other_parameter.value.value
else:
value = get_test_obj_delegate(other_parameter.value, self_parameter[0])
sep = other_parameter.separator.value if other_parameter.separator else None
params.append((value, sep))
return FN(other.first.value, other.last.value, params)
raise NotImplementedError(f"FN, {other=}")
comparison_type_mapping = {
"EQ": ComparisonType.EQUALS,
"NEQ": ComparisonType.NOT_EQUAlS,
@@ -260,7 +1082,7 @@ def get_node(
if isinstance(sub_expr, ReturnValueConcept):
return sub_expr
if isinstance(sub_expr, (scnode, utnode, DoNotResolve)):
if isinstance(sub_expr, DoNotResolve):
return sub_expr
if isinstance(sub_expr, CIO):
@@ -272,18 +1094,6 @@ def get_node(
sub_expr.end = node.end
return sub_expr
if isinstance(sub_expr, cnode):
# for cnode, map the concept key to the one from concepts_maps if needed
if sub_expr.concept_key.startswith("#"):
return cnode(
concepts_map[sub_expr.concept_key[1:]].key,
sub_expr.start,
sub_expr.end,
sub_expr.source
)
else:
return sub_expr
if isinstance(sub_expr, SCWC):
sub_expr.first = get_node(concepts_map, expression_as_tokens, sub_expr.first, sya=sya)
sub_expr.last = get_node(concepts_map, expression_as_tokens, sub_expr.last, sya=sya)
@@ -342,10 +1152,6 @@ def get_node(
sub_expr.fix_pos(node)
return sub_expr
if isinstance(sub_expr, short_cnode):
return get_node(concepts_map, expression_as_tokens, sub_expr.source,
concept_key=sub_expr.concept_key, skip=skip, is_bnf=True, sya=sya)
if isinstance(sub_expr, tuple):
return get_node(concepts_map, expression_as_tokens, sub_expr[0],
concept_key=concept_key, skip=sub_expr[1], is_bnf=is_bnf, sya=sya)
@@ -364,11 +1170,11 @@ def get_node(
if sya and len(concept_found.get_metadata().variables) > 0 and not is_bnf:
return SyaConceptParserHelper(concept_found, start, start + length - 1)
elif init_empty_body:
node = CNC(concept_found, start, start + length - 1, source=sub_expr, exclude_body=exclude_body)
node = CNC(concept_found, sub_expr, start, start + length - 1, exclude_body=exclude_body)
init_body(node, concept_found, sub_expr)
return node
else:
return CN(concept_found, start, start + length - 1, source=sub_expr)
return CN(concept_found, sub_expr, start, start + length - 1)
else:
# else an UnrecognizedTokensNode
return UTN(sub_expr, start, start + length - 1)
@@ -489,27 +1295,32 @@ def get_rete_conditions(*conditions_as_string):
return AndConditions(res)
def get_test_obj(test_obj, real_obj, to_compare_delegate=None):
def get_test_obj(real_obj, test_obj, get_test_obj_delegate=None):
"""
From a production object (Concept, ConceptNode, ....)
Create a test object (CNC, CC ...) that can be used to validate the unit tests
:param test_obj:
:param real_obj:
:param to_compare_delegate:
:param get_test_obj_delegate:
:return:
"""
if isinstance(test_obj, list):
if len(test_obj) != len(real_obj):
raise Exception(f"Not the same size ! {test_obj=}, {real_obj=}")
return [get_test_obj(t, r) for t, r in zip(test_obj, real_obj)]
raise Exception(f"Not the same size ! {real_obj=}, {test_obj=}")
return [get_test_obj(r, t) for r, t in zip(real_obj, test_obj)]
if isinstance(test_obj, dict):
if len(test_obj) != len(real_obj):
raise Exception(f"Not the same size ! {test_obj=}, {real_obj=}")
raise Exception(f"Not the same size ! {real_obj=}, {test_obj=}")
return {k: get_test_obj(v, real_obj[k]) for k, v in test_obj.items()}
return {k: get_test_obj(real_obj[k], v) for k, v in test_obj.items()}
if not hasattr(test_obj, "to_compare"):
if not hasattr(test_obj, "transform_real_obj"):
return real_obj
return test_obj.to_compare(real_obj, get_test_obj)
return test_obj.transform_real_obj(real_obj, get_test_obj)
def compare_with_test_object(actual, expected):
to_compare = get_test_obj(actual, expected)
assert to_compare == expected
+148 -142
View File
@@ -4,11 +4,11 @@ import pytest
import tests.parsers.parsers_utils
from core.builtin_concepts import BuiltinConcepts
from core.concept import Concept, ConceptParts, DoNotResolve, CC, DEFINITION_TYPE_BNF
from core.concept import Concept, ConceptParts, DoNotResolve, DEFINITION_TYPE_BNF
from core.global_symbols import NotInit
from core.sheerka.services.SheerkaConceptManager import SheerkaConceptManager
from core.sheerka.services.SheerkaExecute import ParserInput
from parsers.BaseNodeParser import CNC, UTN, CN, NoMatchingTokenError, SCN
from parsers.BaseNodeParser import NoMatchingTokenError
from parsers.BnfDefinitionParser import BnfDefinitionParser
from parsers.BnfNodeParser import StrMatch, TerminalNode, NonTerminalNode, Sequence, OrderedChoice, \
Optional, ZeroOrMore, OneOrMore, ConceptExpression, UnOrderedChoice, BnfNodeParser, RegExMatch, \
@@ -16,6 +16,7 @@ from parsers.BnfNodeParser import StrMatch, TerminalNode, NonTerminalNode, Seque
from tests.BaseTest import BaseTest
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
from tests.evaluators.EvaluatorTestsUtils import python_ret_val
from tests.parsers.parsers_utils import CNC, CN, UTN, CC, SCN, get_test_obj, compare_with_test_object
cmap = {
"one": Concept("one"),
@@ -210,7 +211,7 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
assert len(bnf_parsers_helpers) == len(expected_array)
for parser_helper, expected_sequence in zip(bnf_parsers_helpers, expected_array):
to_compare = tests.parsers.parsers_utils.get_test_obj(expected_sequence, parser_helper.sequence)
to_compare = tests.parsers.parsers_utils.get_test_obj(parser_helper.sequence, expected_sequence)
# assert parser_helper.sequence == expected_sequence
assert to_compare == expected_sequence
@@ -305,7 +306,7 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
self.validate_get_concepts_sequences(my_map, text, expected)
@pytest.mark.parametrize("text, expected", [
("one two three", [CNC("foo", source="one two three")]),
("one two three", [CNC("foo", "one two three")]),
("one two", []),
("one two four", []),
])
@@ -345,7 +346,8 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
parser.reset_parser(context, ParserInput(text))
bnf_parsers_helpers = parser.get_concepts_sequences(context)
assert bnf_parsers_helpers[0].sequence == expected_array
transformed = get_test_obj(bnf_parsers_helpers[0].sequence, expected_array)
assert transformed == expected_array
assert not bnf_parsers_helpers[0].has_unrecognized
# but I cannot parse
@@ -362,8 +364,8 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
text = "one two three one two"
expected = [
CNC("foo", source="one two three"),
CNC("bar", source="one two", start=6, end=8)]
CNC("foo", "one two three"),
CNC("bar", "one two", 6, 8)]
self.validate_get_concepts_sequences(my_map, text, expected)
@@ -406,8 +408,8 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
self.validate_get_concepts_sequences(my_map, text, expected)
@pytest.mark.parametrize("text, expected", [
("ok thirty one", [CNC("foo", source="ok thirty one")]),
("ok twenty one", [CNC("foo", source="ok twenty one")]),
("ok thirty one", [CNC("foo", "ok thirty one")]),
("ok twenty one", [CNC("foo", "ok twenty one")]),
("ok one", []),
])
def test_i_can_mix_sequence_and_ordered(self, text, expected):
@@ -421,7 +423,7 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
self.validate_get_concepts_sequences(my_map, text, expected)
@pytest.mark.parametrize("text, expected", [
("twenty one", [CNC("foo", source="twenty one")]),
("twenty one", [CNC("foo", "twenty one")]),
("twenty three", []), # three does not exist
("twenty four", []), # four exists but should not be seen
])
@@ -435,8 +437,8 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
self.validate_get_concepts_sequences(my_map, text, expected)
@pytest.mark.parametrize("text, expected", [
("twenty thirty", [CNC("foo", source="twenty thirty")]),
("one", [CNC("foo", source="one")]),
("twenty thirty", [CNC("foo", "twenty thirty")]),
("one", [CNC("foo", "one")]),
])
def test_i_can_mix_ordered_choices_and_sequences(self, text, expected):
my_map = {
@@ -448,8 +450,8 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
self.validate_get_concepts_sequences(my_map, text, expected)
@pytest.mark.parametrize("text, expected", [
("one", [CNC("foo", source="one")]),
("one two", [CNC("foo", source="one two")]),
("one", [CNC("foo", "one")]),
("one two", [CNC("foo", "one two")]),
("three", []),
])
@@ -463,7 +465,7 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
self.validate_get_concepts_sequences(my_map, text, expected)
@pytest.mark.parametrize("text, expected", [
("one", [CNC("foo", source="one")]),
("one", [CNC("foo", "one")]),
("", []),
("two", []),
])
@@ -475,8 +477,8 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
self.validate_get_concepts_sequences(my_map, text, expected)
@pytest.mark.parametrize("text, expected", [
("twenty one", [CNC("foo", source="twenty one")]),
("one", [CNC("foo", source="one")]),
("twenty one", [CNC("foo", "twenty one")]),
("one", [CNC("foo", "one")]),
])
def test_i_can_match_sequence_starting_with_optional(self, text, expected):
my_map = {
@@ -489,8 +491,8 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
self.validate_get_concepts_sequences(my_map, text, expected)
@pytest.mark.parametrize("text, expected", [
("one two three", [CNC("foo", source="one two three")]),
("one two", [CNC("foo", source="one two")]),
("one two three", [CNC("foo", "one two three")]),
("one two", [CNC("foo", "one two")]),
])
def test_i_can_match_sequence_ending_with_optional(self, text, expected):
my_map = {
@@ -504,8 +506,8 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
self.validate_get_concepts_sequences(my_map, text, expected)
@pytest.mark.parametrize("text, expected", [
("one two three", [CNC("foo", source="one two three")]),
("one three", [CNC("foo", source="one three")]),
("one two three", [CNC("foo", "one two three")]),
("one three", [CNC("foo", "one three")]),
])
def test_i_can_match_sequence_with_optional_in_between(self, text, expected):
my_map = {
@@ -521,8 +523,8 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
@pytest.mark.parametrize("text, expected", [
("", []),
("two", []),
("one", [CNC("foo", source="one")]),
("one one", [CNC("foo", source="one one")]),
("one", [CNC("foo", "one")]),
("one one", [CNC("foo", "one one")]),
])
def test_i_can_match_zero_or_more(self, text, expected):
my_map = {
@@ -532,9 +534,9 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
self.validate_get_concepts_sequences(my_map, text, expected)
@pytest.mark.parametrize("text, expected", [
("two", [CNC("foo", source="two")]),
("one two", [CNC("foo", source="one two")]),
("one one two", [CNC("foo", source="one one two")]),
("two", [CNC("foo", "two")]),
("one two", [CNC("foo", "one two")]),
("one one two", [CNC("foo", "one one two")]),
])
def test_i_can_match_sequence_and_zero_or_more(self, text, expected):
my_map = {
@@ -548,7 +550,7 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
self.validate_get_concepts_sequences(my_map, text, expected)
@pytest.mark.parametrize("text, expected", [
("one, one , one", [CNC("foo", source="one, one , one")]),
("one, one , one", [CNC("foo", "one, one , one")]),
])
def test_i_can_match_zero_or_more_with_separator(self, text, expected):
my_map = {
@@ -564,14 +566,14 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
}
text = "one one one"
expected = [CNC("foo", source=text)]
expected = [CNC("foo", text)]
self.validate_get_concepts_sequences(my_map, text, expected)
@pytest.mark.parametrize("text, expected", [
("", []),
("two", []),
("one", [CNC("foo", source="one")]),
("one one one", [CNC("foo", source="one one one")]),
("one", [CNC("foo", "one")]),
("one one one", [CNC("foo", "one one one")]),
])
def test_i_can_match_one_or_more(self, text, expected):
my_map = {
@@ -582,8 +584,8 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
@pytest.mark.parametrize("text, expected", [
("two", []),
("one two", [CNC("foo", source="one two")]),
("one one two", [CNC("foo", source="one one two")]),
("one two", [CNC("foo", "one two")]),
("one one two", [CNC("foo", "one one two")]),
])
def test_i_can_match_sequence_one_and_or_more(self, text, expected):
my_map = {
@@ -597,7 +599,7 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
self.validate_get_concepts_sequences(my_map, text, expected)
@pytest.mark.parametrize("text, expected", [
("one, one , one", [CNC("foo", source="one, one , one")]),
("one, one , one", [CNC("foo", "one, one , one")]),
])
def test_i_can_match_one_or_more_with_separator(self, text, expected):
my_map = {
@@ -613,18 +615,18 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
}
text = "one one one"
expected = [CNC("foo", source=text)]
expected = [CNC("foo", text)]
self.validate_get_concepts_sequences(my_map, text, expected)
@pytest.mark.parametrize("text, expected", [
("one two", [
[CNC("foo", source="one two")],
[CNC("bar", source="one two")]]),
[CNC("foo", "one two")],
[CNC("bar", "one two")]]),
("one two one two", [
[CNC("bar", source="one two"), CNC("bar", source="one two")],
[CNC("foo", source="one two"), CNC("bar", source="one two")],
[CNC("bar", source="one two"), CNC("foo", source="one two")],
[CNC("foo", source="one two"), CNC("foo", source="one two")]]),
[CNC("bar", "one two"), CNC("bar", "one two")],
[CNC("foo", "one two"), CNC("bar", "one two")],
[CNC("bar", "one two"), CNC("foo", "one two")],
[CNC("foo", "one two"), CNC("foo", "one two")]]),
])
def test_i_can_have_multiple_results(self, text, expected):
my_map = {
@@ -635,7 +637,7 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
}
text = "one two"
expected = [[CNC("foo", source=text)], [CNC("bar", source=text)]]
expected = [[CNC("foo", text)], [CNC("bar", text)]]
self.validate_get_concepts_sequences(my_map, text, expected, multiple_result=True)
def test_i_can_refer_to_other_concepts(self):
@@ -646,8 +648,8 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
text = "one two"
expected = [
[CNC("foo", source=text)],
[CN("bar", source=text)] # Do not check the compiled part
[CNC("foo", text)],
[CN("bar", text)] # Do not check the compiled part
]
sequences = self.validate_get_concepts_sequences(my_map, text, expected, multiple_result=True)
@@ -672,8 +674,8 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
text = "one two"
expected = [
[CNC("foo", source=text)],
[CN("bar", source=text)] # Do not check the compiled part
[CNC("foo", text)],
[CN("bar", text)] # Do not check the compiled part
]
sequences = self.validate_get_concepts_sequences(my_map, text, expected, multiple_result=True)
@@ -698,9 +700,9 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
text = "one two"
expected = [
[CNC("foo", source=text)],
[CN("bar", source=text)], # Do not check the compiled part
[CN("baz", source=text)], # Do not check the compiled part
[CNC("foo", text)],
[CN("bar", text)], # Do not check the compiled part
[CN("baz", text)], # Do not check the compiled part
]
sequences = self.validate_get_concepts_sequences(my_map, text, expected, multiple_result=True)
@@ -769,7 +771,7 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
text = "twenty two"
expected = [CNC("twenties",
source="twenty two",
"twenty two",
twenty=CC("twenty", body=DoNotResolve("twenty")),
number=CC("number", source="two", body=DoNotResolve("two"))
)]
@@ -842,7 +844,7 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
}
text = "twenty one"
expected = [CN("foo", source="twenty one")]
expected = [CN("foo", "twenty one")]
sequences = self.validate_get_concepts_sequences(my_map, text, expected)
concept_foo = sequences[0].concept
assert concept_foo.get_compiled() == {
@@ -869,8 +871,9 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
# explicit validations of the compiled
concept_foo = sequences[0].concept
assert concept_foo.body == NotInit
assert concept_foo.get_compiled() == {'number': CC(my_map["number"], body=my_map["two"], two=my_map["two"]),
ConceptParts.BODY: DoNotResolve(value='twenty two')}
compare_with_test_object(concept_foo.get_compiled(), {
'number': CC(my_map["number"], body=my_map["two"], two=my_map["two"]),
ConceptParts.BODY: DoNotResolve(value='twenty two')})
text = "twenty one"
expected = [CN("foo", source="twenty one")]
@@ -879,14 +882,15 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
# explicit validations of the compiled
concept_foo = sequences[0].concept
assert concept_foo.body == NotInit
assert concept_foo.get_compiled() == {'number': CC(my_map["number"], body=my_map["one"], one=my_map["one"]),
ConceptParts.BODY: DoNotResolve(value='twenty one')}
compare_with_test_object(concept_foo.get_compiled(), {
'number': CC(my_map["number"], body=my_map["one"], one=my_map["one"]),
ConceptParts.BODY: DoNotResolve(value='twenty one')})
@pytest.mark.parametrize("expr, expected", [
("one 'car'", [CNC("foo", source="one 'car'", x=python_ret_val("'car'"))]), # python
("one bar", [CNC("foo", source="one bar", x=CC("bar"))]), # simple concept
("one super car", [CNC("foo", source="one super car", x=CC("super car"))]), # long concept
("one shoe", [CNC("foo", source="one shoe", x=CC("thing", source="shoe", body=DoNotResolve("shoe")))]), # bnf
("one 'car'", [CNC("foo", "one 'car'", x=python_ret_val("'car'"))]), # python
("one bar", [CNC("foo", "one bar", x=CC("bar"))]), # simple concept
("one super car", [CNC("foo", "one super car", x=CC("super car"))]), # long concept
("one shoe", [CNC("foo", "one shoe", x=CC("thing", source="shoe", body=DoNotResolve("shoe")))]), # bnf
])
def test_i_can_match_variable_when_ending_with_one_variable(self, expr, expected):
my_map = {
@@ -910,8 +914,8 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
expr = "one bar plus baz"
expected = [
[CNC("foo", source="one bar", x=CC("bar")), UTN(" plus "), CN("baz")],
[CNC("foo", source="one bar plus baz", x=CC("plus", source="bar plus baz", x="bar", y="baz"))],
[CNC("foo", "one bar", x=CC("bar")), UTN(" plus "), CN("baz")],
[CNC("foo", "one bar plus baz", x=CC("plus", source="bar plus baz", x="bar", y="baz"))],
]
self.validate_get_concepts_sequences(my_map, expr, expected, multiple_result=True)
@@ -925,8 +929,8 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
expr = "one pretty big"
expected = [
[CNC("foo", source="one pretty big", x=CC("pretty big"))],
[CNC("foo", source="one pretty big", x=CC("pbig", source="pretty big"))]
[CNC("foo", "one pretty big", x=CC("pretty big"))],
[CNC("foo", "one pretty big", x=CC("pbig", source="pretty big"))]
]
self.validate_get_concepts_sequences(my_map, expr, expected, multiple_result=True)
@@ -940,16 +944,16 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
expr = "one pretty big"
expected = [
[CNC("foo", source="one pretty big", x=CC("pretty"), y=CC("big"))],
[CNC("foo", source="one pretty big", x=CC("pretty2", source="pretty"), y=CC("big"))]
[CNC("foo", "one pretty big", x=CC("pretty"), y=CC("big"))],
[CNC("foo", "one pretty big", x=CC("pretty2", source="pretty"), y=CC("big"))]
]
self.validate_get_concepts_sequences(my_map, expr, expected, multiple_result=True)
@pytest.mark.parametrize("expr, expected", [
("'my' shoe", [CNC("foo", source="'my' shoe", x=python_ret_val("'my' "))]), # python
("one shoe", [CNC("foo", source="one shoe", x=CC("one"))]), # concept
("my little shoe", [CNC("foo", source="my little shoe", x=CC("my little"))]), # long concept
("black shoe", [CNC("foo", source="black shoe", x=CC("color", source="black", body=DoNotResolve('black')))]),
("'my' shoe", [CNC("foo", "'my' shoe", x=python_ret_val("'my' "))]), # python
("one shoe", [CNC("foo", "one shoe", x=CC("one"))]), # concept
("my little shoe", [CNC("foo", "my little shoe", x=CC("my little"))]), # long concept
("black shoe", [CNC("foo", "black shoe", x=CC("color", source="black", body=DoNotResolve('black')))]),
])
def test_i_can_match_variable_when_starting_with_one_variable(self, expr, expected):
my_map = {
@@ -972,9 +976,9 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
expr = "tiny but beautiful shoe"
expected_res = [
CNC("foo",
source="tiny but beautiful shoe",
"tiny but beautiful shoe",
x=CC("but", source="tiny but beautiful", x="tiny", y="beautiful"))]
unwanted_res = [CN("tiny"), UTN(" but "), CNC("foo", source="beautiful shoe", x=CC("beautiful"))]
unwanted_res = [CN("tiny"), UTN(" but "), CNC("foo", "beautiful shoe", x=CC("beautiful"))]
self.validate_get_concepts_sequences(my_map, expr, [unwanted_res, expected_res], multiple_result=True)
def test_i_can_match_variable_when_starting_with_multiple_variables(self):
@@ -992,7 +996,7 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
unwanted_res = [CN("one"), SCN(" 'one' "), ("one", 1), UTN(" plus "), CN("two")]
expected_res = [CNC("foo",
source="one 'one' one plus two shoe",
"one 'one' one plus two shoe",
x=CC("one"),
y=python_ret_val(" 'one' "),
z=CC("plus", source="one plus two", x="one", y="two"))]
@@ -1009,18 +1013,18 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
"one": Concept("one")
}
text = "one foo bar baz"
expected = [CNC("foo", source="one foo bar baz", x=CC("one"))]
expected = [CNC("foo", "one foo bar baz", x=CC("one"))]
self.validate_get_concepts_sequences(my_map, text, expected)
@pytest.mark.parametrize("expr, expected", [
("one 'pretty' shoe", [CNC("foo", source="one 'pretty' shoe", x=python_ret_val("'pretty' "))]), # python
("one little shoe", [CNC("foo", source="one little shoe", x=CC("little"))]), # concept
("one very big shoe", [CNC("foo", source="one very big shoe", x=CC("very big"))]), # long concept
("one 'pretty' shoe", [CNC("foo", "one 'pretty' shoe", x=python_ret_val("'pretty' "))]), # python
("one little shoe", [CNC("foo", "one little shoe", x=CC("little"))]), # concept
("one very big shoe", [CNC("foo", "one very big shoe", x=CC("very big"))]), # long concept
("one black shoe",
[CNC("foo", source="one black shoe", x=CC("color", source="black", body=DoNotResolve('black')))]),
[CNC("foo", "one black shoe", x=CC("color", source="black", body=DoNotResolve('black')))]),
("one tiny but beautiful shoe",
[CNC("foo",
source="one tiny but beautiful shoe",
"one tiny but beautiful shoe",
x=CC("but", source="tiny but beautiful", x="tiny", y="beautiful "))]),
])
def test_i_can_match_variable_in_between(self, expr, expected):
@@ -1043,8 +1047,8 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
expr = "one pretty big shoe"
expected = [
[CNC("foo", source="one pretty big shoe", x=CC("pretty big"))],
[CNC("foo", source="one pretty big shoe", x=CC("pbig", source="pretty big"))]
[CNC("foo", "one pretty big shoe", x=CC("pretty big"))],
[CNC("foo", "one pretty big shoe", x=CC("pbig", source="pretty big"))]
]
self.validate_get_concepts_sequences(my_map, expr, expected, multiple_result=True)
@@ -1055,7 +1059,7 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
"shoe": Concept("shoe")
}
text = "onyx shoe"
expected = [CNC("foo", source="onyx shoe", x=CC("shoe"))]
expected = [CNC("foo", "onyx shoe", x=CC("shoe"))]
self.validate_get_concepts_sequences(my_map, text, expected)
def test_i_can_match_variable_and_regex(self):
@@ -1065,7 +1069,7 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
"one": Concept("one")
}
text = "one onyx"
expected = [CNC("foo", source="one onyx", x=CC("one"))]
expected = [CNC("foo", "one onyx", x=CC("one"))]
self.validate_get_concepts_sequences(my_map, text, expected)
def test_i_can_reuse_the_same_variable(self):
@@ -1083,12 +1087,12 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
# same variable appears only once in the compiled variables
text = "one equals one"
expected = [CNC("foo", source="one equals one", x=CC("one"))]
expected = [CNC("foo", "one equals one", x=CC("one"))]
expected_sequence = compute_expected_array(my_map, text, expected)
parser.reset_parser(context, ParserInput(text))
bnf_parsers_helpers = parser.get_concepts_sequences(context)
to_compare = tests.parsers.parsers_utils.get_test_obj(expected_sequence, bnf_parsers_helpers[0].sequence)
to_compare = tests.parsers.parsers_utils.get_test_obj(bnf_parsers_helpers[0].sequence, expected_sequence)
assert to_compare == expected
def test_i_cannot_match_variable_when_variables_discrepancy(self):
@@ -1314,9 +1318,9 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
ConceptExpression(my_map["one"], rule_name="one"))
@pytest.mark.parametrize("expr, text, expected", [
(ZeroOrMore(StrMatch("one"), sep=","), "one,", [CNC("foo", source="one"), UTN(",")]),
(StrMatch("one"), "one two", [CNC("foo", source="one"), UTN(" two")]),
(StrMatch("one"), "two one", [UTN("two "), CNC("foo", source="one")]),
(ZeroOrMore(StrMatch("one"), sep=","), "one,", [CNC("foo", "one"), UTN(",")]),
(StrMatch("one"), "one two", [CNC("foo", "one"), UTN(" two")]),
(StrMatch("one"), "two one", [UTN("two "), CNC("foo", "one")]),
])
def test_i_can_recognize_unknown_concepts(self, expr, text, expected):
my_map = {
@@ -1332,7 +1336,7 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
}
text = "one three"
expected = [UTN("one "), CNC("three", source="three")]
expected = [UTN("one "), CNC("three", "three")]
self.validate_get_concepts_sequences(my_map, text, expected)
def test_i_can_remove_duplicates(self):
@@ -1350,12 +1354,12 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
assert len(sequence) == 1
@pytest.mark.parametrize("parser_input, expected_status, expected", [
("baz", True, [CNC("bnf baz", source="baz")]), # the bnf one is chosen
("foo bar", True, [CNC("foo then bar", source="foo bar", foo="foo", bar="bar")]),
("bar", True, [CNC("foo or bar", source="bar", bar="bar", body="bar")]),
("one plus two", True, [CNC("plus", source="one plus two", one="one", two="two")]),
("twenty one", True, [CNC("t1", source="twenty one", unit="one")]),
("one 'car'", True, [CNC("one thing", source="one 'car'", x=python_ret_val("'car'"), one="one")])
("baz", True, [CNC("bnf baz", "baz")]), # the bnf one is chosen
("foo bar", True, [CNC("foo then bar", "foo bar", foo="foo", bar="bar")]),
("bar", True, [CNC("foo or bar", "bar", bar="bar", body="bar")]),
("one plus two", True, [CNC("plus", "one plus two", one="one", two="two")]),
("twenty one", True, [CNC("t1", "twenty one", unit="one")]),
("one 'car'", True, [CNC("one thing", "one 'car'", x=python_ret_val("'car'"), one="one")])
])
def test_i_can_parse_simple_expressions(self, parser_input, expected_status, expected):
sheerka, context, parser = self.init_parser(init_from_sheerka=True)
@@ -1367,7 +1371,7 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
assert res.status == expected_status
assert sheerka.isinstance(parser_result, BuiltinConcepts.PARSER_RESULT)
assert concepts_nodes == expected_array
compare_with_test_object(concepts_nodes, expected_array)
def test_i_can_parse_when_multiple_times_the_same_variable(self):
sheerka, context, parser = self.init_parser(init_from_sheerka=True)
@@ -1382,7 +1386,7 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
assert res.status
assert sheerka.isinstance(parser_result, BuiltinConcepts.PARSER_RESULT)
assert concepts_nodes == expected_array
compare_with_test_object(concepts_nodes, expected_array)
def test_i_can_test_when_expression_references_other_expressions(self):
sheerka, context, parser = self.init_parser(init_from_sheerka=True)
@@ -1402,7 +1406,7 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
assert res.status
assert sheerka.isinstance(parser_result, BuiltinConcepts.PARSER_RESULT)
assert concepts_nodes == expected_array
compare_with_test_object(concepts_nodes, expected_array)
def test_i_can_parse_bnf_concept_mixed_with_isa_concepts(self):
sheerka, context, parser = self.init_parser(init_from_sheerka=True)
@@ -1428,7 +1432,7 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
assert res.status
assert sheerka.isinstance(parser_result, BuiltinConcepts.PARSER_RESULT)
assert concepts_nodes == expected_array
compare_with_test_object(concepts_nodes, expected_array)
def test_i_can_parse_bnf_concept_mixed_with_isa_concepts_2(self):
# this time, three is a number, and also part of three_four, even if it is not relevant in t3
@@ -1450,7 +1454,7 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
assert res.status
assert sheerka.isinstance(parser_result, BuiltinConcepts.PARSER_RESULT)
assert concepts_nodes == expected_array
compare_with_test_object(concepts_nodes, expected_array)
def test_i_can_parse_when_starting_by_isa_concept(self):
"""
@@ -1476,7 +1480,7 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
assert res.status
assert sheerka.isinstance(parser_result, BuiltinConcepts.PARSER_RESULT)
assert concepts_nodes == expected_array
compare_with_test_object(concepts_nodes, expected_array)
def test_i_can_parse_fifty_one_thousand(self):
"""
@@ -1515,10 +1519,10 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
res = parser.parse(context, ParserInput(text))
assert res[0].status
assert res[0].value.value == expected_thousands
compare_with_test_object(res[0].value.value, expected_thousands)
assert res[1].status
assert res[1].value.value == expected_fifties
compare_with_test_object(res[1].value.value, expected_fifties)
def test_i_can_parse_one_hundred_thousand(self):
sheerka, context, parser = self.init_parser(init_from_sheerka=True)
@@ -1565,7 +1569,7 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
assert res.status
assert sheerka.isinstance(parser_result, BuiltinConcepts.PARSER_RESULT)
assert concepts_nodes == expected_array
compare_with_test_object(concepts_nodes, expected_array)
def test_i_can_parse_bnf_concept_mixed_with_isa_after_restart(self):
sheerka, context, parser = self.init_parser(init_from_sheerka=True)
@@ -1589,7 +1593,7 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
assert res.status
assert sheerka.isinstance(parser_result, BuiltinConcepts.PARSER_RESULT)
assert concepts_nodes == expected_array
compare_with_test_object(concepts_nodes, expected_array)
text = "forty one"
expected = CNC("forties",
@@ -1607,13 +1611,13 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
assert res.status
assert sheerka.isinstance(parser_result, BuiltinConcepts.PARSER_RESULT)
assert concepts_nodes == expected_array
compare_with_test_object(concepts_nodes, expected_array)
def test_i_can_parse_when_keyword(self):
sheerka, context, parser = self.init_parser(init_from_sheerka=True)
parser_input = "def one"
expected = [CNC("def number", source="def one", number="one")]
expected = [CNC("def number", "def one", number="one")]
res = parser.parse(context, ParserInput(parser_input))
expected_array = compute_expected_array(cmap, parser_input, expected)
@@ -1624,7 +1628,7 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
assert res.status
assert sheerka.isinstance(parser_result, BuiltinConcepts.PARSER_RESULT)
assert concepts_nodes == expected_array
compare_with_test_object(concepts_nodes, expected_array)
def test_i_can_parse_filter(self):
sheerka, context, parser = self.init_parser(init_from_sheerka=True)
@@ -1639,7 +1643,7 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
assert res.status
assert sheerka.isinstance(parser_result, BuiltinConcepts.PARSER_RESULT)
assert concepts_nodes == expected_array
compare_with_test_object(concepts_nodes, expected_array)
def test_i_can_parse_descent_grammar(self):
my_map = {
@@ -1662,17 +1666,17 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
assert res.status
assert sheerka.isinstance(parser_result, BuiltinConcepts.PARSER_RESULT)
assert concepts_nodes == [CNC(expr,
term=[CC(term,
body=CC(factor, body=DoNotResolve("1")),
factor=CC(factor, body=DoNotResolve("1"))),
CC(term,
body=DoNotResolve("2 * 3"),
factor=[
CC(factor, body=DoNotResolve("2")),
CC(factor, body=DoNotResolve("3")),
])],
body=DoNotResolve("1 + 2 * 3"))]
compare_with_test_object(concepts_nodes, [CNC(expr,
term=[CC(term,
body=CC(factor, body=DoNotResolve("1")),
factor=CC(factor, body=DoNotResolve("1"))),
CC(term,
body=DoNotResolve("2 * 3"),
factor=[
CC(factor, body=DoNotResolve("2")),
CC(factor, body=DoNotResolve("3")),
])],
body=DoNotResolve("1 + 2 * 3"))])
def test_i_can_parse_recursive_descent_grammar(self):
my_map = {
@@ -1698,25 +1702,27 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
# concepts_nodes = res.value.value is too complicated to be validated
assert res.status
assert sheerka.isinstance(parser_result, BuiltinConcepts.PARSER_RESULT)
assert concepts_nodes == [CNC(expr,
term=CC(term,
body=CC(factor, body=DoNotResolve("1")),
factor=CC(factor, body=DoNotResolve("1"))),
expr=CC(expr,
body=CC(term,
body=DoNotResolve("2 * 3"),
factor=CC(factor, body=DoNotResolve("2")),
compare_with_test_object(concepts_nodes, [CNC(expr,
term=CC(term,
body=CC(factor, body=DoNotResolve("3")),
factor=CC(factor, body=DoNotResolve("3")))),
term=CC(term,
body=DoNotResolve("2 * 3"),
factor=CC(factor, body=DoNotResolve("2")),
term=CC(term,
body=CC(factor, body=DoNotResolve("3")),
factor=CC(factor, body=DoNotResolve("3"))))),
body=CC(factor, body=DoNotResolve("1")),
factor=CC(factor, body=DoNotResolve("1"))),
expr=CC(expr,
body=CC(term,
body=DoNotResolve("2 * 3"),
factor=CC(factor, body=DoNotResolve("2")),
term=CC(term,
body=CC(factor, body=DoNotResolve("3")),
factor=CC(factor,
body=DoNotResolve("3")))),
term=CC(term,
body=DoNotResolve("2 * 3"),
factor=CC(factor, body=DoNotResolve("2")),
term=CC(term,
body=CC(factor, body=DoNotResolve("3")),
factor=CC(factor,
body=DoNotResolve("3"))))),
body=DoNotResolve("1 + 2 * 3"))]
body=DoNotResolve("1 + 2 * 3"))])
def test_i_can_parse_simple_recursive_grammar(self):
my_map = {
@@ -1752,14 +1758,14 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
text = "thirty one"
res = parser.parse(context, ParserInput(text))
assert res.status
assert res.value.value == compute_expected_array(cmap, text, [CN("thirties", source=text)])
compare_with_test_object(res.value.value, compute_expected_array(cmap, text, [CN("thirties", text)]))
# add a layer, I still can parse the text
sheerka.push_ontology(context, "new layer")
parser = BnfNodeParser(sheerka=sheerka)
res = parser.parse(context, ParserInput(text))
assert res.status
assert res.value.value == compute_expected_array(cmap, text, [CN("thirties", source=text)])
compare_with_test_object(res.value.value, compute_expected_array(cmap, text, [CN("thirties", text)]))
def test_i_do_not_eat_unwanted_tokens_at_the_beginning_when_concept_with_variable(self):
my_map = {
@@ -1772,9 +1778,9 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
text = "two one shoe"
res = parser.parse(context, ParserInput(text))
assert res.status
assert res.value.value == compute_expected_array(my_map, text, [
compare_with_test_object(res.value.value, compute_expected_array(my_map, text, [
CN("two"),
CNC("foo", source="one shoe", x=CC("one"))])
CNC("foo", "one shoe", x=CC("one"))]))
def test_i_do_not_eat_unwanted_tokens_at_the_end_when_concept_with_variable(self):
my_map = {
@@ -1787,9 +1793,9 @@ class TestBnfNodeParser(TestUsingMemoryBasedSheerka):
text = "one bar baz"
res = parser.parse(context, ParserInput(text))
assert res.status
assert res.value.value == compute_expected_array(my_map, text, [
CNC("foo", source="one bar", x=CC("bar")),
CN("baz")])
compare_with_test_object(res.value.value, compute_expected_array(my_map, text, [
CNC("foo", "one bar", x=CC("bar")),
CN("baz")]))
@pytest.mark.parametrize("parsing_expression, expected", [
(RegExMatch("a"), [RegExDef("a")]),
+4 -4
View File
@@ -4,13 +4,13 @@ from core.builtin_concepts import BuiltinConcepts
from core.concept import Concept, DEFINITION_TYPE_BNF
from core.sheerka.services.SheerkaExecute import ParserInput
from core.tokenizer import Tokenizer, TokenKind, LexerError
from parsers.BaseNodeParser import cnode
from parsers.BaseParser import UnexpectedTokenParsingError, UnexpectedEofParsingError
from parsers.BnfDefinitionParser import BnfDefinitionParser
from parsers.BnfNodeParser import BnfNodeParser, RegExMatch, VariableExpression
from parsers.BnfNodeParser import StrMatch, Optional, ZeroOrMore, OrderedChoice, Sequence, \
OneOrMore, ConceptExpression
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
from tests.parsers.parsers_utils import CN, compare_with_test_object
class ClassWithName:
@@ -226,15 +226,15 @@ class TestBnfParser(TestUsingMemoryBasedSheerka):
res = bnf_parser.parse(context, ParserInput("twenty two"))
assert res.status
assert res.value.body == [cnode("bar", 0, 2, "twenty two")]
compare_with_test_object(res.value.body, [CN("bar", "twenty two", 0, 2)])
res = bnf_parser.parse(context, ParserInput("thirty one"))
assert res.status
assert res.value.body == [cnode("bar", 0, 2, "thirty one")]
compare_with_test_object(res.value.body, [CN("bar", "thirty one", 0, 2)])
res = bnf_parser.parse(context, ParserInput("twenty"))
assert res.status
assert res.value.body == [cnode("foo", 0, 0, "twenty")]
compare_with_test_object(res.value.body, [CN("foo", "twenty", 0, 0)])
def test_i_cannot_parse_when_too_many_concepts(self):
sheerka, context, regex_parser, foo1, foo2 = self.init_parser(
+8 -13
View File
@@ -4,11 +4,10 @@ from dataclasses import dataclass
import pytest
from core.builtin_concepts import ParserResultConcept, BuiltinConcepts, ReturnValueConcept
from core.concept import DEFINITION_TYPE_BNF, DEFINITION_TYPE_DEF, Concept, CV
from core.concept import DEFINITION_TYPE_BNF, DEFINITION_TYPE_DEF, Concept
from core.global_symbols import NotInit
from core.sheerka.services.SheerkaExecute import ParserInput
from core.tokenizer import Keywords, Tokenizer, LexerError
from parsers.BaseNodeParser import SCWC
from parsers.BaseParser import UnexpectedEofParsingError
from parsers.BnfDefinitionParser import BnfDefinitionParser
from parsers.BnfNodeParser import OrderedChoice, ConceptExpression, StrMatch, Sequence, RegExMatch, OneOrMore, \
@@ -18,7 +17,7 @@ from parsers.DefConceptParser import UnexpectedTokenParsingError, DefConceptNode
from parsers.FunctionParser import FunctionParser
from parsers.PythonParser import PythonParser, PythonNode
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
from tests.parsers.parsers_utils import compute_expected_array
from tests.parsers.parsers_utils import compute_expected_array, SCWC, CV, compare_with_test_object
def get_def_concept(name, where=None, pre=None, post=None, body=None, definition=None, bnf_def=None, ret=None):
@@ -265,7 +264,6 @@ class TestDefConceptParser(TestUsingMemoryBasedSheerka):
text = """def concept a mult b
where a,b
pre isinstance(a, int) and isinstance(b, int)
post isinstance(res, a)
as res = a * b
ret a if isinstance(a, Concept) else self
"""
@@ -276,7 +274,6 @@ ret a if isinstance(a, Concept) else self
name="a mult b",
where="a,b\n",
pre="isinstance(a, int) and isinstance(b, int)\n",
post=FN("isinstance(res, a)\n", "isinstance(", ")", ["res", ", ", "a"]),
body=PN("res = a * b\n", "exec"),
ret="a if isinstance(a, Concept) else self\n"
)
@@ -542,29 +539,27 @@ from give me the date !
text = "def concept foo x y where x is a y"
res = parser.parse(context, ParserInput(text))
expected_body = self.pretval(CV(concepts[0], pre=True), source="x is a y", who="parsers.DefConcept",
parser="parsers.ExactConcept")
expected = get_def_concept("foo x y", where=expected_body)
node = res.value.value
assert res.status
assert res.who == parser.name
assert res.value.source == text
assert isinstance(res.value, ParserResultConcept)
assert node == expected
assert isinstance(node, DefConceptNode)
assert sheerka.isinstance(node.where, BuiltinConcepts.RETURN_VALUE)
compare_with_test_object(node.where.body.body, CV(concepts[0], pre=True))
text = "def concept foo x y pre x is a y"
res = parser.parse(context, ParserInput(text))
expected_body = self.pretval(CV(concepts[0], pre=True), source="x is a y", who="parsers.DefConcept",
parser="parsers.ExactConcept")
expected = get_def_concept("foo x y", pre=expected_body)
node = res.value.value
assert res.status
assert res.who == parser.name
assert res.value.source == text
assert isinstance(res.value, ParserResultConcept)
assert node == expected
assert isinstance(node, DefConceptNode)
assert sheerka.isinstance(node.pre, BuiltinConcepts.RETURN_VALUE)
compare_with_test_object(node.pre.body.body, CV(concepts[0], pre=True))
def test_i_can_parse_bnf_concept_with_regex(self):
sheerka, context, parser, number = self.init_parser("number")
+8 -7
View File
@@ -1,9 +1,10 @@
from core.builtin_concepts import BuiltinConcepts
from core.concept import Concept, CMV
from core.concept import Concept
from core.sheerka.services.SheerkaExecute import ParserInput
from parsers.ExactConceptParser import ExactConceptParser
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
from tests.parsers.parsers_utils import CMV, compare_with_test_object
def variable_def(concept, prop_name):
@@ -97,7 +98,7 @@ class TestExactConceptParser(TestUsingMemoryBasedSheerka):
assert results[0].status
concept_found = results[0].value.value
assert concept_found == CMV(concept, a="10", b="5")
compare_with_test_object(concept_found, CMV(concept, a="10", b="5"))
assert concept_found.get_metadata().need_validation
assert not concept_found.get_metadata().is_evaluated
@@ -113,7 +114,7 @@ class TestExactConceptParser(TestUsingMemoryBasedSheerka):
assert results[0].status
concept_found = results[0].value.value
assert concept_found == CMV(concept, a="10", b="5")
compare_with_test_object(concept_found, CMV(concept, a="10", b="5"))
assert concept_found.get_metadata().need_validation
def test_i_can_parse_concept_when_defined_using_from_def(self):
@@ -127,7 +128,7 @@ class TestExactConceptParser(TestUsingMemoryBasedSheerka):
assert len(results) == 1
assert results[0].status
assert concept_found == CMV(plus, a="10", b="5")
compare_with_test_object(concept_found, CMV(plus, a="10", b="5"))
assert concept_found.get_metadata().need_validation
assert not concept_found.get_metadata().is_evaluated
@@ -157,7 +158,7 @@ class TestExactConceptParser(TestUsingMemoryBasedSheerka):
assert len(results) == 1
assert results[0].status
assert concept_found == CMV(plus, a="c:one:", b="c:two:")
compare_with_test_object(concept_found, CMV(plus, a="c:one:", b="c:two:"))
assert concept_found.get_metadata().need_validation
assert not concept_found.get_metadata().is_evaluated
@@ -173,7 +174,7 @@ class TestExactConceptParser(TestUsingMemoryBasedSheerka):
assert len(results) == 1
assert results[0].status
assert concept_found == CMV(isa, c="z")
compare_with_test_object(concept_found, CMV(isa, c="z"))
assert concept_found.get_metadata().need_validation
assert not concept_found.get_metadata().is_evaluated
@@ -183,7 +184,7 @@ class TestExactConceptParser(TestUsingMemoryBasedSheerka):
assert len(results) == 1
assert results[0].status
assert concept_found == CMV(def_concept, a="z")
compare_with_test_object(concept_found, CMV(def_concept, a="z"))
assert concept_found.get_metadata().need_validation
assert not concept_found.get_metadata().is_evaluated
+12 -13
View File
@@ -3,11 +3,10 @@ import ast
import pytest
from core.builtin_concepts import BuiltinConcepts, ReturnValueConcept
from core.concept import Concept, CMV, DoNotResolve, CC
from core.concept import Concept, DoNotResolve
from core.rule import Rule
from core.sheerka.services.SheerkaExecute import ParserInput
from core.tokenizer import TokenKind
from parsers.BaseNodeParser import CNC
from parsers.BaseParser import UnexpectedEofParsingError, UnexpectedTokenParsingError
from parsers.ExpressionParser import ExpressionParser, LeftPartNotFoundError, ParenthesisMismatchError
from parsers.PythonParser import PythonNode
@@ -15,7 +14,7 @@ from parsers.expressions import TrueifyVisitor, IsAQuestionVisitor, AndNode
from sheerkarete.network import ReteNetwork
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
from tests.parsers.parsers_utils import compute_expected_array, resolve_test_concept, EXPR, OR, AND, NOT, \
get_expr_node_from_test_node, get_rete_conditions
get_expr_node_from_test_node, get_rete_conditions, CMV, CNC, CC, compare_with_test_object
class TestExpressionParser(TestUsingMemoryBasedSheerka):
@@ -215,9 +214,9 @@ class TestExpressionParser(TestUsingMemoryBasedSheerka):
("foo", "foo"),
("one two", "one two"),
("foo is a bar", CMV("is a", x='foo', y='bar')),
("one two is a bar", [CNC("is a", source="one two is a bar", x="one two", y="bar")]),
("one two is a bar", [CNC("is a", "one two is a bar", x="one two", y="bar")]),
("foo is an foo bar",
[CNC("is an", source="foo is an foo bar", x=DoNotResolve(value='foo'), exclude_body=True)]),
[CNC("is an", "foo is an foo bar", x=DoNotResolve(value='foo'), exclude_body=True)]),
])
def test_i_can_get_compiled_expr_from_simple_concepts_expressions(self, expression, expected):
concepts_map = {
@@ -238,10 +237,10 @@ class TestExpressionParser(TestUsingMemoryBasedSheerka):
if isinstance(expected, list):
expected_nodes = compute_expected_array(concepts_map, expression, expected)
assert ret.body.body == expected_nodes
compare_with_test_object(ret.body.body, expected_nodes)
else:
expected_concept = resolve_test_concept(concepts_map, expected)
assert ret.body.body == expected_concept
compare_with_test_object(ret.body.body, expected_concept)
@pytest.mark.parametrize("expression", [
"a == 5",
@@ -338,11 +337,11 @@ class TestExpressionParser(TestUsingMemoryBasedSheerka):
ret = return_values[0]
python_node = ret.body.body
assert python_node == expected_python_node
assert python_node.objects == {
compare_with_test_object(python_node.objects, {
"__C__00var0000is0a000var001__1005__C__": CC(is_a, x=cat, y=pet),
"__C__00var0000is0an0y__1006__C__": CC(is_an, exclude_body=True, x=DoNotResolve("bird"), animal=animal),
"__C__00var0000is0a000var001__1005_1__C__": CMV(is_a, x="dog", y="pet"),
}
})
def test_i_can_get_compiled_expr_from_mix(self):
sheerka, context, animal, cat, dog, pet, is_a, is_an = self.init_test().with_concepts(
@@ -369,11 +368,11 @@ class TestExpressionParser(TestUsingMemoryBasedSheerka):
python_node = ret.body.body
assert python_node == expected_python_node
assert python_node.objects == {
compare_with_test_object(python_node.objects, {
"__C__00var0000is0a000var001__1005__C__": CC(is_a, x=cat, y=pet),
"__C__00var0000is0an0y__1006__C__": CC(is_an, exclude_body=True, x=DoNotResolve("bird"), animal=animal),
"__C__00var0000is0a000var001__1005_1__C__": CMV(is_a, x="dog", y="pet"),
}
})
def test_i_can_get_compiled_expr_when_multiple_choices(self):
sheerka, context, *concepts = self.init_test().with_concepts(
@@ -390,10 +389,10 @@ class TestExpressionParser(TestUsingMemoryBasedSheerka):
assert len(return_values) == 2
ret = return_values[0]
assert sheerka.objvalue(ret)[0].concept == CMV(concepts[0], x="a", y="b")
compare_with_test_object(sheerka.objvalue(ret)[0].concept, CMV(concepts[0], x="a", y="b"))
ret = return_values[1]
assert sheerka.objvalue(ret)[0].concept == CMV(concepts[1], x="a", y="b")
compare_with_test_object(sheerka.objvalue(ret)[0].concept, CMV(concepts[1], x="a", y="b"))
def test_i_can_get_compiled_expr_from_mix_when_multiple_choices(self):
sheerka, context, *concepts = self.init_test().with_concepts(
+47 -59
View File
@@ -3,10 +3,10 @@ import pytest
from core.builtin_concepts import BuiltinConcepts
from core.concept import Concept
from core.sheerka.services.SheerkaExecute import ParserInput
from parsers.BaseNodeParser import SCN, SCWC, CN, UTN, CNC, RN
from parsers.FunctionParser import FunctionParser, FN
from parsers.FunctionParser import FunctionParser
from parsers.PythonParser import PythonErrorNode
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
from tests.parsers.parsers_utils import compute_expected_array
from tests.parsers.parsers_utils import compute_expected_array, SCN, SCWC, CN, UTN, CNC, RN, FN, get_test_obj
cmap = {
"one": Concept("one"),
@@ -80,60 +80,73 @@ class TestFunctionParser(TestUsingMemoryBasedSheerka):
parser.parser_input.next_token()
res = parser.parse_function()
assert res == expected
transformed_res = get_test_obj(res, expected)
assert transformed_res == expected
def test_i_can_parse_function_when_rule(self):
sheerka, context, parser = self.init_parser()
expected = FN("func(", ")", ["r:|1:"])
parser.reset_parser(context, ParserInput("func(r:|1:)"))
parser.parser_input.next_token()
res = parser.parse_function()
assert res == FN("func(", ")", ["r:|1:"])
transformed_res = get_test_obj(res, expected)
assert transformed_res == expected
@pytest.mark.parametrize("text, expected", [
("func()", SCN("func()")),
(" func()", SCN("func()")),
("func(one)", SCWC("func(", ")", CN("one"))),
("func(one, unknown, two)", SCWC("func(", ")", CN("one"), ", ", UTN("unknown"), (", ", 1), CN("two"))),
("func(one, twenty two)", SCWC("func(", ")", "one", ", ", CN("twenties", source="twenty two"))),
("func(one, twenty two)", SCWC("func(", ")", "one", ", ", CN("twenties", "twenty two"))),
("func(one plus two, three)", SCWC("func(", ")", CNC("plus", a="one", b="two"), ", ", UTN("three"))),
("func(func1(one), two)", SCWC("func(", (")", 1), SCWC("func1(", ")", "one"), ", ", "two"))
])
def test_i_can_parse(self, text, expected):
sheerka, context, parser = self.init_parser()
resolved_expected = compute_expected_array(cmap, text, [expected])[0]
res = parser.parse(context, ParserInput(text))
parser_result = res.body
expression = res.body.body
assert res.status
assert sheerka.isinstance(parser_result, BuiltinConcepts.PARSER_RESULT)
assert expression == resolved_expected
transformed_expression = get_test_obj(expression, resolved_expected)
assert transformed_expression == resolved_expected
assert expression.python_node is not None
assert expression.return_value is not None
def test_i_can_parse_when_multiple_results_when_requested(self):
# the previous output was
# [
# SCWC("func(", ")", "one", ", ", "twenty ", "two"),
# SCWC("func(", ")", "one", ", ", CN("twenties", "twenty two"))
# ]
# But the first one is now filtered out, as it's not a valid python function call
sheerka, context, parser = self.init_parser()
parser.longest_concepts_only = False
text = "func(one, twenty two)"
expected = [SCWC("func(", ")", "one", ", ", "twenty ", "two"),
SCWC("func(", ")", "one", ", ", CN("twenties", source="twenty two"))]
all_resolved_expected = compute_expected_array(cmap, text, expected)
expected = [SCWC("func(", ")", "one", ", ", CN("twenties", "twenty two"))]
resolved_expected = compute_expected_array(cmap, text, expected)
results = parser.parse(context, ParserInput(text))
assert len(results) == 2
for res, resolved_expected in zip(results, all_resolved_expected):
parser_result = res.body
expressions = res.body.body
res = results[0]
assert not res.status
assert sheerka.isinstance(res.body, BuiltinConcepts.ERROR)
assert len(res.body.body) == 1
assert (res.body.body[0], PythonErrorNode)
assert sheerka.isinstance(parser_result, BuiltinConcepts.PARSER_RESULT)
assert expressions == resolved_expected
res = results[1]
parser_result = res.body
expressions = res.body.body
assert sheerka.isinstance(parser_result, BuiltinConcepts.PARSER_RESULT)
transformed_expressions = get_test_obj(expressions, resolved_expected[0])
assert transformed_expressions == resolved_expected[0]
def test_i_can_parse_when_the_parameter_is_not_a_concept(self):
"""
@@ -144,10 +157,15 @@ class TestFunctionParser(TestUsingMemoryBasedSheerka):
text = "func(unknown_concept)"
res = parser.parse(context, ParserInput(text))
expected = [SCWC("func(", ")", "unknown_concept")]
resolved_expected = compute_expected_array(cmap, text, expected)
assert res.status
parsed = res.body.body
transformed_parsed = get_test_obj([parsed], resolved_expected)
assert transformed_parsed == resolved_expected
def test_i_cannot_parse_when_the_concept_is_not_found(self):
def test_i_can_parse_when_the_concept_is_not_found(self):
"""
We do not check yet if it's a valid concept
If you find a cheap way to do so, simply remove this test
@@ -169,37 +187,24 @@ class TestFunctionParser(TestUsingMemoryBasedSheerka):
res = parser.parse(context, ParserInput(text))
parser_result = res.body
expression = res.body.body
transformed_expression = get_test_obj(expression, resolved_expected)
assert res.status
assert sheerka.isinstance(parser_result, BuiltinConcepts.PARSER_RESULT)
assert expression == resolved_expected
assert transformed_expression == resolved_expected
assert expression.python_node is not None
assert expression.return_value is not None
# def test_i_cannot_parse_when_rule_not_found(self):
# sheerka, context, parser = self.init_parser()
# text = "func(r:|fake:)"
# expected = SCWC("func(", ")", RN("fake"))
# resolved_expected = compute_expected_array(cmap, text, [expected])[0]
#
# res = parser.parse(context, ParserInput(text))
# parser_result = res.body
# expression = res.body.body
#
# assert not res.status
# assert sheerka.isinstance(parser_result, BuiltinConcepts.PARSER_RESULT)
# assert expression == resolved_expected
# assert expression.python_node is not None
# assert expression.return_value is not None
@pytest.mark.parametrize("text, expected_error_type", [
("one", BuiltinConcepts.NOT_FOR_ME),
("$*!", BuiltinConcepts.NOT_FOR_ME),
("func(", BuiltinConcepts.ERROR),
("func(one", BuiltinConcepts.ERROR),
("func(one, two, ", BuiltinConcepts.ERROR),
("func(one) and func(two)", BuiltinConcepts.ERROR),
("one func(one)", BuiltinConcepts.NOT_FOR_ME),
("one", BuiltinConcepts.NOT_FOR_ME), # no function found
("$*!", BuiltinConcepts.NOT_FOR_ME), # no function found
("func(", BuiltinConcepts.ERROR), # function found, but incomplete
("func(one", BuiltinConcepts.ERROR), # function found, but incomplete
("func(one, two, ", BuiltinConcepts.ERROR), # function found, but incomplete
("func(one) and func(two)", BuiltinConcepts.ERROR), # to many function
("one func(one)", BuiltinConcepts.NOT_FOR_ME), # function not found ! (as it is not the first)
("func(a=b, c)", BuiltinConcepts.ERROR), # function found, but cannot be parsed
("func(one two)", BuiltinConcepts.ERROR), # function found, but cannot be parsed
])
def test_i_cannot_parse(self, text, expected_error_type):
sheerka, context, parser = self.init_parser()
@@ -209,23 +214,6 @@ class TestFunctionParser(TestUsingMemoryBasedSheerka):
assert not res.status
assert sheerka.isinstance(res.body, expected_error_type)
@pytest.mark.parametrize("text, expected", [
("func(one two)", SCWC("func(", ")", "one", "two")),
])
def test_i_can_detect_none_function(self, text, expected):
sheerka, context, parser = self.init_parser()
resolved_expected = compute_expected_array(cmap, text, [expected])[0]
res = parser.parse(context, ParserInput(text))
parser_result = res.body
expression = res.body.body
assert not res.status
assert sheerka.isinstance(parser_result, BuiltinConcepts.PARSER_RESULT)
assert expression == resolved_expected
assert expression.python_node is None
assert expression.return_value is None
@pytest.mark.parametrize("sequence, expected", [
(None, None),
([["a"]], [["a"]]),
+15 -9
View File
@@ -7,7 +7,8 @@ from core.concept import Concept
from core.rule import Rule
from core.sheerka.services.SheerkaExecute import ParserInput
from core.tokenizer import Token, TokenKind, Tokenizer
from parsers.BaseNodeParser import ConceptNode, UnrecognizedTokensNode, RuleNode, SourceCodeNode
from core.var_ref import VariableRef
from parsers.BaseNodeParser import ConceptNode, UnrecognizedTokensNode, RuleNode, VariableNode
from parsers.PythonParser import PythonNode
from parsers.PythonWithConceptsParser import PythonWithConceptsParser
from parsers.UnrecognizedNodeParser import UnrecognizedNodeParser
@@ -29,8 +30,12 @@ def ret_val(*args):
tokens = [Token(TokenKind.RULE, (None, item.id), 0, 0, 0)]
result.append(RuleNode(item, index, index, tokens, f"r:|{item.id}:"))
index += 1
elif isinstance(item, VariableRef):
tokens = list(Tokenizer(item.prop, yield_eof=False))
result.append(VariableNode(item.obj, item.prop, index, index + len(tokens) - 1, tokens, f"{item.prop}"))
index += len(tokens)
else:
tokens = list(Tokenizer(item))
tokens = list(Tokenizer(item, yield_eof=False))
result.append(UnrecognizedTokensNode(index, index + len(tokens) - 1, tokens))
index += len(tokens)
@@ -58,10 +63,10 @@ class TestPythonWithConceptsParser(TestUsingMemoryBasedSheerka):
else:
assert res is None
def test_i_can_parse_concepts_and_python(self):
def test_i_can_parse_concepts_python_and_variable_ref(self):
context = self.get_context()
foo = Concept("foo")
input_return_value = ret_val(foo, " + 1")
input_return_value = ret_val(foo, " + 1 + ", VariableRef(foo, "var_name"))
parser = PythonWithConceptsParser()
result = parser.parse(context, input_return_value.body)
@@ -71,12 +76,13 @@ class TestPythonWithConceptsParser(TestUsingMemoryBasedSheerka):
assert result.status
assert result.who == parser.name
assert context.sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
assert wrapper.source == "foo + 1"
assert wrapper.source == "foo + 1 + var_name"
assert isinstance(return_value, PythonNode)
assert return_value.source == "__C__foo__C__ + 1"
assert return_value.original_source == "foo + 1"
assert return_value.get_dump(return_value.ast_) == to_str_ast("__C__foo__C__ + 1")
assert return_value.objects["__C__foo__C__"] == foo
assert return_value.source == "__C__foo__C__ + 1 + __V__foo__var_name__V__"
assert return_value.original_source == "foo + 1 + var_name"
assert return_value.get_dump(return_value.ast_) == to_str_ast("__C__foo__C__ + 1 + __V__foo__var_name__V__")
assert return_value.objects == {"__C__foo__C__": foo,
"__V__foo__var_name__V__": VariableRef(foo, "var_name")}
def test_i_can_parse_concepts_and_python_when_concept_is_known(self):
context = self.get_context()
+25 -23
View File
@@ -1,12 +1,12 @@
import pytest
from core.builtin_concepts import BuiltinConcepts
from core.concept import Concept, DEFINITION_TYPE_DEF
from core.sheerka.services.SheerkaExecute import ParserInput
from parsers.SequenceNodeParser import SequenceNodeParser
from parsers.BaseNodeParser import cnode, utnode, CNC, SCN, CN
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
from tests.parsers.parsers_utils import compute_expected_array
from tests.parsers.parsers_utils import compute_expected_array, CN, CNC, SCN, get_test_obj, compare_with_test_object, \
UTN
class TestAtomsParser(TestUsingMemoryBasedSheerka):
@@ -40,8 +40,8 @@ class TestAtomsParser(TestUsingMemoryBasedSheerka):
(" foo ", ["foo"]),
("foo bar", ["foo", "bar"]),
("foo bar twenties", ["foo", "bar", "twenties"]),
("a plus b", [CN("plus", 0, 4)]),
("mult", [CN("mult", 0, 0, "mult")]),
("a plus b", [CN("plus", None, 0, 4)]),
("mult", [CN("mult", "mult", 0, 0)]),
])
def test_i_can_parse_simple_sequences(self, text, expected):
concepts_map = {
@@ -62,7 +62,7 @@ class TestAtomsParser(TestUsingMemoryBasedSheerka):
expected_array = compute_expected_array(concepts_map, text, expected)
assert sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
assert lexer_nodes == expected_array
compare_with_test_object(lexer_nodes, expected_array)
@pytest.mark.parametrize("text, expected", [
("foo bar", ["foo bar"]),
@@ -85,7 +85,7 @@ class TestAtomsParser(TestUsingMemoryBasedSheerka):
expected_array = compute_expected_array(concepts_map, text, expected)
assert sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
assert lexer_nodes == expected_array
compare_with_test_object(lexer_nodes, expected_array)
@pytest.mark.parametrize("text, expected_status, expected", [
("foo bar suffixed one", False, ["foo bar", " suffixed ", "one"]),
@@ -123,12 +123,12 @@ class TestAtomsParser(TestUsingMemoryBasedSheerka):
expected_array = compute_expected_array(concepts_map, text, expected)
assert sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
assert lexer_nodes == expected_array
compare_with_test_object(lexer_nodes, expected_array)
@pytest.mark.parametrize("text, expected_status, expected", [
(" one two ", True, [cnode("one", 1, 1, "one"), cnode("two", 3, 3, "two")]),
(" one x$!# ", False, [cnode("one", 1, 1, "one"), utnode(2, 7, " x$!# ")]),
(" foo bar x$!# ", False, [cnode("foo bar", 1, 3, "foo bar"), utnode(4, 9, " x$!# ")]),
(" one two ", True, [CN("one", "one", 1, 1), CN("two", "two", 3, 3)]),
(" one x$!# ", False, [CN("one", "one", 1, 1), UTN(" x$!# ", 2, 7)]),
(" foo bar x$!# ", False, [CN("foo bar", "foo bar", 1, 3), UTN(" x$!# ", 4, 9)]),
])
def test_i_can_parse_when_surrounded_by_spaces(self, text, expected_status, expected):
concepts_map = {
@@ -150,7 +150,7 @@ class TestAtomsParser(TestUsingMemoryBasedSheerka):
expected_array = compute_expected_array(concepts_map, text, expected)
assert sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
assert lexer_nodes == expected_array
compare_with_test_object(lexer_nodes, expected_array)
@pytest.mark.parametrize("text, expected", [
("one two", [["one", "two"], ["one two"]])
@@ -173,7 +173,7 @@ class TestAtomsParser(TestUsingMemoryBasedSheerka):
assert res.status
expected_array = compute_expected_array(concepts_map, text, expected[i])
assert sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
assert lexer_nodes == expected_array
compare_with_test_object(lexer_nodes, expected_array)
def test_i_can_parse_multiple_concepts_when_long_names_and_unrecognized(self):
concepts_map = {
@@ -204,7 +204,7 @@ class TestAtomsParser(TestUsingMemoryBasedSheerka):
assert res.status == expected[0]
expected_array = compute_expected_array(concepts_map, text, expected[1])
assert sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
assert lexer_nodes == expected_array
compare_with_test_object(lexer_nodes, expected_array)
def test_i_can_parse_concepts_with_isa(self):
concepts_map = {
@@ -218,7 +218,7 @@ class TestAtomsParser(TestUsingMemoryBasedSheerka):
res = parser.parse(context, ParserInput("one"))
lexer_nodes = res.body.body
expected_array = compute_expected_array(concepts_map, "one", ["one"])
assert lexer_nodes == expected_array
compare_with_test_object(lexer_nodes, expected_array)
def test_i_can_parse_concepts_with_keyword(self):
concepts_map = {
@@ -231,12 +231,12 @@ class TestAtomsParser(TestUsingMemoryBasedSheerka):
res = parser.parse(context, ParserInput("a special concept"))
lexer_nodes = res.body.body
expected_array = compute_expected_array(concepts_map, "a special concept", ["a special concept"])
assert lexer_nodes == expected_array
compare_with_test_object(lexer_nodes, expected_array)
res = parser.parse(context, ParserInput("isa"))
lexer_nodes = res.body.body
expected_array = compute_expected_array(concepts_map, "isa", ["isa"])
assert lexer_nodes == expected_array
compare_with_test_object(lexer_nodes, expected_array)
def test_i_can_parse_concepts_when_sub_tokens(self):
concepts_map = {
@@ -256,7 +256,7 @@ class TestAtomsParser(TestUsingMemoryBasedSheerka):
expected_array = compute_expected_array(concepts_map, text, expected)
assert sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
assert lexer_nodes == expected_array
compare_with_test_object(lexer_nodes, expected_array)
@pytest.mark.parametrize("text", [
"foo",
@@ -283,8 +283,8 @@ class TestAtomsParser(TestUsingMemoryBasedSheerka):
@pytest.mark.parametrize("text, expected", [
("hello foo bar",
[
(True, [CNC("hello1", source="hello foo ", a="foo "), "bar"]),
(True, [CNC("hello2", source="hello foo ", b="foo "), "bar"]),
(True, [CNC("hello1", "hello foo ", a="foo "), "bar"]),
(True, [CNC("hello2", "hello foo ", b="foo "), "bar"]),
]),
])
def test_i_can_parse_when_unrecognized_yield_multiple_values(self, text, expected):
@@ -304,9 +304,10 @@ class TestAtomsParser(TestUsingMemoryBasedSheerka):
lexer_nodes = res.body.body
assert res.status == expected[0]
expected_array = compute_expected_array(concepts_map, text, expected[1])
assert sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
assert lexer_nodes == expected_array
expected_array = compute_expected_array(concepts_map, text, expected[1])
transformed_nodes = get_test_obj(lexer_nodes, expected_array)
assert transformed_nodes == expected_array
@pytest.mark.parametrize("text, expected", [
("1 + twenty one", [SCN("1 + twenty "), "one"]),
@@ -326,7 +327,8 @@ class TestAtomsParser(TestUsingMemoryBasedSheerka):
expected_array = compute_expected_array(concepts_map, text, expected)
assert sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
assert lexer_nodes == expected_array
transformed_nodes = get_test_obj(lexer_nodes, expected_array)
assert transformed_nodes == expected_array
@pytest.mark.parametrize("text, expected_is_evaluated", [
("foo", False),
+129 -123
View File
@@ -2,18 +2,19 @@ import pytest
import tests.parsers.parsers_utils
from core.builtin_concepts import BuiltinConcepts
from core.concept import Concept, CIO, CMV
from core.concept import Concept
from core.global_symbols import CONCEPT_COMPARISON_CONTEXT
from core.sheerka.services.SheerkaExecute import ParserInput
from core.tokenizer import Tokenizer
from core.utils import NextIdManager
from parsers.BaseNodeParser import utnode, cnode, short_cnode, UnrecognizedTokensNode, \
SCWC, CNC, UTN, SCN, CN
from parsers.BaseNodeParser import UnrecognizedTokensNode
from parsers.PythonParser import PythonNode
from parsers.SyaNodeParser import SyaNodeParser, SyaConceptParserHelper, SyaAssociativity, \
NoneAssociativeSequenceError, TooManyParametersFoundError, InFixToPostFix, ParenthesisMismatchError
from tests.TestUsingFileBasedSheerka import TestUsingFileBasedSheerka
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
from tests.parsers.parsers_utils import UTN, SCWC, CNC, SCN, CIO, CN, compute_debug_array, CMV, get_test_obj, \
compare_with_test_object
def compute_expected_array(concepts_map, expression, expected):
@@ -102,6 +103,16 @@ class TestSyaNodeParser(TestUsingMemoryBasedSheerka):
parser.init_from_concepts(context, concepts, sya=sya_def_to_use)
return sheerka, context, parser
@staticmethod
def compare_results(res, expected_sequences, concept_map, expression, validate_errors=True):
assert len(res) == len(expected_sequences)
for res_i, expected in zip(res, expected_sequences):
if validate_errors:
assert len(res_i.errors) == 0
expected_array = compute_expected_array(concept_map, expression, expected)
res_i_as_test_obj = get_test_obj(res_i.out, expected_array)
assert res_i_as_test_obj == expected_array
@pytest.mark.parametrize("expression, expected_sequences", [
("one plus two", [["one", "two", "plus"]]),
("1 + 1 plus two", [["1 + 1", "two", "plus"]]),
@@ -110,7 +121,7 @@ class TestSyaNodeParser(TestUsingMemoryBasedSheerka):
["one + two", "three", "plus"]]),
("twenty one plus two", [
["twenty ", "one", "two", "plus"],
[short_cnode("twenties", "twenty one"), "two", "plus"]
[CN("twenties", "twenty one"), "two", "plus"]
]),
("x$!# plus two", [["x$!#", "two", "plus"]]),
@@ -122,7 +133,7 @@ class TestSyaNodeParser(TestUsingMemoryBasedSheerka):
]),
("twenty one plus 1 + 1", [
["twenty ", "one", "1 + 1", "plus"],
[cnode("twenties", 0, 2, "twenty one"), "1 + 1", "plus"]
[CN("twenties", "twenty one", 0, 2), "1 + 1", "plus"]
]),
("x$!# plus 1 + 1", [["x$!#", "1 + 1", "plus"]]),
@@ -142,9 +153,9 @@ class TestSyaNodeParser(TestUsingMemoryBasedSheerka):
]),
("twenty one plus two + three", [
["twenty ", "one", "two", "plus", " + ", "three"],
[cnode("twenties", 0, 2, "twenty one"), "two", "plus", " + ", "three"],
[CN("twenties", "twenty one", 0, 2), "two", "plus", " + ", "three"],
["twenty ", "one", "two + three", "plus"],
[cnode("twenties", 0, 2, "twenty one"), "two + three", "plus"],
[CN("twenties", "twenty one", 0, 2), "two + three", "plus"],
]),
("x$!# plus two + three", [
["x$!#", "two", "plus", " + ", "three"],
@@ -153,28 +164,28 @@ class TestSyaNodeParser(TestUsingMemoryBasedSheerka):
("one plus twenty two", [
["one", "twenty ", "plus", "two"],
["one", cnode("twenties", 4, 6, "twenty two"), "plus"],
["one", CN("twenties", "twenty two", 4, 6), "plus"],
]),
("1 + 1 plus twenty one", [
["1 + 1", "twenty ", "plus", "one"],
["1 + 1", cnode("twenties", 8, 10, "twenty one"), "plus"],
["1 + 1", CN("twenties", "twenty one", 8, 10), "plus"],
]),
("one + two plus twenty one", [
["one", " + ", "two", "twenty ", "plus", ("one", 1)],
["one + two", "twenty ", "plus", ("one", 1)],
["one", " + ", "two", cnode("twenties", 8, 10, "twenty one"), "plus"],
["one + two", cnode("twenties", 8, 10, "twenty one"), "plus"],
["one", " + ", "two", CN("twenties", "twenty one", 8, 10), "plus"],
["one + two", CN("twenties", "twenty one", 8, 10), "plus"],
]),
("twenty one plus twenty two",
[
["twenty ", "one", ("twenty ", 1), "plus", "two"],
[cnode("twenties", 0, 2, "twenty one"), ("twenty ", 1), "plus", "two"],
["twenty ", "one", cnode("twenties", 6, 8, "twenty two"), "plus"],
[cnode("twenties", 0, 2, "twenty one"), cnode("twenties", 6, 8, "twenty two"), "plus"],
[CN("twenties", "twenty one", 0, 2), ("twenty ", 1), "plus", "two"],
["twenty ", "one", CN("twenties", "twenty two", 6, 8), "plus"],
[CN("twenties", "twenty one", 0, 2), CN("twenties", "twenty two", 6, 8), "plus"],
]),
("x$!# plus twenty two", [
["x$!#", "twenty ", "plus", "two"],
["x$!#", cnode("twenties", 7, 9, "twenty two"), "plus"]
["x$!#", CN("twenties", "twenty two", 7, 9), "plus"]
]),
("one plus z$!#", [["one", "z$!#", "plus"]]),
@@ -185,7 +196,7 @@ class TestSyaNodeParser(TestUsingMemoryBasedSheerka):
]),
("twenty one plus z$!#", [
["twenty ", "one", "z$!#", "plus"],
[cnode("twenties", 0, 2, "twenty one"), "z$!#", "plus"],
[CN("twenties", "twenty one", 0, 2), "z$!#", "plus"],
]),
("x$!# plus z$!#", [["x$!#", "z$!#", "plus"]]),
])
@@ -194,17 +205,13 @@ class TestSyaNodeParser(TestUsingMemoryBasedSheerka):
res = parser.infix_to_postfix(context, ParserInput(expression))
assert len(res) == len(expected_sequences)
for res_i, expected in zip(res, expected_sequences):
assert len(res_i.errors) == 0
expected_array = compute_expected_array(cmap, expression, expected)
assert res_i.out == expected_array
self.compare_results(res, expected_sequences, cmap, expression)
@pytest.mark.parametrize("expression, expected_sequences", [
("one plus plus plus 1 + 1", [["one", "1 + 1", "plus plus plus"]]),
("x$!# another long name infix twenty two", [
["x$!#", "twenty ", "another long name infix", "two"],
["x$!#", cnode("twenties", 13, 15, "twenty two"), "another long name infix"],
["x$!#", CN("twenties", "twenty two", 13, 15), "another long name infix"],
]),
])
def test_i_can_post_fix_infix_concepts_with_long_name(self, expression, expected_sequences):
@@ -220,11 +227,7 @@ class TestSyaNodeParser(TestUsingMemoryBasedSheerka):
res = parser.infix_to_postfix(context, ParserInput(expression))
assert len(res) == len(expected_sequences)
for res_i, expected in zip(res, expected_sequences):
assert len(res_i.errors) == 0
expected_array = compute_expected_array(concepts_map, expression, expected)
assert res_i.out == expected_array
self.compare_results(res, expected_sequences, concepts_map, expression)
@pytest.mark.parametrize("expression, expected_sequences", [
("one prefixed", [["one", "prefixed"]]),
@@ -235,7 +238,7 @@ class TestSyaNodeParser(TestUsingMemoryBasedSheerka):
]),
("twenty one prefixed", [
["twenty ", "one", "prefixed"],
[cnode("twenties", 0, 2, "twenty one"), "prefixed"],
[CN("twenties", "twenty one", 0, 2), "prefixed"],
]),
("x$!# prefixed", [["x$!#", "prefixed"]]),
])
@@ -244,11 +247,7 @@ class TestSyaNodeParser(TestUsingMemoryBasedSheerka):
res = parser.infix_to_postfix(context, ParserInput(expression))
assert len(res) == len(expected_sequences)
for res_i, expected in zip(res, expected_sequences):
assert len(res_i.errors) == 0
expected_array = compute_expected_array(cmap, expression, expected)
assert res_i.out == expected_array
self.compare_results(res, expected_sequences, cmap, expression)
@pytest.mark.parametrize("expression, expected_sequences", [
("one prefixed prefixed", [["one", "prefixed prefixed"]]),
@@ -259,7 +258,7 @@ class TestSyaNodeParser(TestUsingMemoryBasedSheerka):
]),
("twenty one prefixed prefixed", [
["twenty ", "one", "prefixed prefixed"],
[cnode("twenties", 0, 2, "twenty one"), "prefixed prefixed"],
[CN("twenties", "twenty one", 0, 2), "prefixed prefixed"],
]),
("x$!# prefixed prefixed", [["x$!#", "prefixed prefixed"]]),
@@ -271,7 +270,7 @@ class TestSyaNodeParser(TestUsingMemoryBasedSheerka):
]),
("twenty one long name prefixed", [
["twenty ", "one", "long name prefixed"],
[cnode("twenties", 0, 2, "twenty one"), "long name prefixed"],
[CN("twenties", "twenty one", 0, 2), "long name prefixed"],
]),
("x$!# long name prefixed", [["x$!#", "long name prefixed"]]),
])
@@ -287,11 +286,7 @@ class TestSyaNodeParser(TestUsingMemoryBasedSheerka):
res = parser.infix_to_postfix(context, ParserInput(expression))
assert len(res) == len(expected_sequences)
for res_i, expected in zip(res, expected_sequences):
assert len(res_i.errors) == 0
expected_array = compute_expected_array(concepts_map, expression, expected)
assert res_i.out == expected_array
self.compare_results(res, expected_sequences, concepts_map, expression)
@pytest.mark.parametrize("expression, expected_sequences", [
("suffixed one", [["one", "suffixed"]]),
@@ -302,7 +297,7 @@ class TestSyaNodeParser(TestUsingMemoryBasedSheerka):
]),
("suffixed twenty one", [
["twenty ", "suffixed", "one"],
[cnode("twenties", 2, 4, "twenty one"), "suffixed"],
[CN("twenties", "twenty one", 2, 4), "suffixed"],
]),
("suffixed x$!#", [["x$!#", "suffixed"]]),
])
@@ -311,11 +306,7 @@ class TestSyaNodeParser(TestUsingMemoryBasedSheerka):
res = parser.infix_to_postfix(context, ParserInput(expression))
assert len(res) == len(expected_sequences)
for res_i, expected in zip(res, expected_sequences):
assert len(res_i.errors) == 0
expected_array = compute_expected_array(cmap, expression, expected)
assert res_i.out == expected_array
self.compare_results(res, expected_sequences, cmap, expression)
@pytest.mark.parametrize("expression, expected", [
("suffixed suffixed one", ["one", "suffixed suffixed"]),
@@ -333,8 +324,10 @@ class TestSyaNodeParser(TestUsingMemoryBasedSheerka):
res = parser.infix_to_postfix(context, ParserInput(expression))
expected_array = compute_expected_array(concepts_map, expression, expected)
assert len(res) == 1
assert res[0].out == expected_array
transformed_out = get_test_obj(res[0].out, expected_array)
assert transformed_out == expected_array
@pytest.mark.parametrize("expression, expected_sequences", [
("one ? two : three", [["one", "two", "three", "?"]]),
@@ -342,14 +335,14 @@ class TestSyaNodeParser(TestUsingMemoryBasedSheerka):
("1+1 ? one + two : twenty one", [
["1+1", "one", " + ", "two"], # error is detected so the parsing has stopped
["1+1", "one + two", "twenty ", "?", ("one", 1)],
["1+1", "one + two", short_cnode("twenties", "twenty one"), "?"],
["1+1", "one + two", CN("twenties", "twenty one"), "?"],
]),
("x$!# ? y$!# : z$!#", [["x$!#", "y$!#", "z$!#", "?"]]),
("if one then two else three end", [["one", "two", "three", "if"]]),
("if 1+1 then x$!# else twenty one end", [
["1+1", "x$!#", "twenty ", "one"], # an error is detected
["1+1", "x$!#", short_cnode("twenties", "twenty one"), "if"],
["1+1", "x$!#", CN("twenties", "twenty one"), "if"],
]),
("if x$!# then one + two else z$!# end", [
["x$!#", "one", " + ", "two"], # error is detected so the parsing has stopped
@@ -373,24 +366,20 @@ class TestSyaNodeParser(TestUsingMemoryBasedSheerka):
res = parser.infix_to_postfix(context, ParserInput(expression))
assert len(res) == len(expected_sequences)
for res_i, expected in zip(res, expected_sequences):
# assert len(res_i.errors) == 0 # Do not validate errors
expected_array = compute_expected_array(cmap, expression, expected)
assert res_i.out == expected_array
self.compare_results(res, expected_sequences, cmap, expression, validate_errors=False)
@pytest.mark.parametrize("expression, expected_sequences", [
("one ? ? two : : three", [["one", "two", "three", "? ?"]]),
("1+1 ? ? one + two : : twenty one", [
["1+1", "one", " + ", "two"], # error
["1+1", "one + two", "twenty ", "? ?", ("one", 1)],
["1+1", "one + two", short_cnode("twenties", "twenty one"), "? ?"],
["1+1", "one + two", CN("twenties", "twenty one"), "? ?"],
]),
("if if one then then two else else three end end ", [["one", "two", "three", "if if"]]),
("if if 1+1 then then x$!# else else twenty one end end ", [
["1+1", "x$!#", "twenty ", "one"], # error
["1+1", "x$!#", short_cnode("twenties", "twenty one"), "if if"]]),
["1+1", "x$!#", CN("twenties", "twenty one"), "if if"]]),
])
def test_i_can_post_fix_ternary_concept_with_long_names(self, expression, expected_sequences):
concepts_map = {
@@ -405,11 +394,7 @@ class TestSyaNodeParser(TestUsingMemoryBasedSheerka):
res = parser.infix_to_postfix(context, ParserInput(expression))
assert len(res) == len(expected_sequences)
for res_i, expected in zip(res, expected_sequences):
# assert len(res_i.errors) == 0 # Do not validate errors
expected_array = compute_expected_array(concepts_map, expression, expected)
assert res_i.out == expected_array
self.compare_results(res, expected_sequences, concepts_map, expression, validate_errors=False)
@pytest.mark.parametrize("expression, expected", [
("foo bar baz", ["baz", "bar", "foo"]),
@@ -428,7 +413,8 @@ class TestSyaNodeParser(TestUsingMemoryBasedSheerka):
expected_array = compute_expected_array(concepts_map, expression, expected)
assert len(res) == 1
assert res[0].out == expected_array
transformed_out = get_test_obj(res[0].out, expected_array)
assert transformed_out == expected_array
@pytest.mark.parametrize("expression, expected", [
("baz bar foo", ["baz", "bar", "foo"]),
@@ -451,7 +437,8 @@ class TestSyaNodeParser(TestUsingMemoryBasedSheerka):
expected_array = compute_expected_array(concepts_map, expression, expected)
assert len(res) == 1
assert res[0].out == expected_array
transformed_out = get_test_obj(res[0].out, expected_array)
assert transformed_out == expected_array
@pytest.mark.parametrize("expression, expected", [
("one plus two mult three", ["one", "two", "three", "mult", "plus"]),
@@ -466,7 +453,8 @@ class TestSyaNodeParser(TestUsingMemoryBasedSheerka):
expected_array = compute_expected_array(cmap, expression, expected)
assert len(res) == 1
assert res[0].out == expected_array
transformed_out = get_test_obj(res[0].out, expected_array)
assert transformed_out == expected_array
def test_i_can_post_fix_unary_with_precedence(self):
concepts_map = {
@@ -487,7 +475,8 @@ class TestSyaNodeParser(TestUsingMemoryBasedSheerka):
expected_array = compute_expected_array(concepts_map, expression, expected)
assert len(res) == 1
assert res[0].out == expected_array
transformed_out = get_test_obj(res[0].out, expected_array)
assert transformed_out == expected_array
# change the precedence
sya_def = {
@@ -502,7 +491,8 @@ class TestSyaNodeParser(TestUsingMemoryBasedSheerka):
expected_array = compute_expected_array(concepts_map, expression, expected)
assert len(res) == 1
assert res[0].out == expected_array
transformed_out = get_test_obj(res[0].out, expected_array)
assert transformed_out == expected_array
def test_i_can_post_fix_right_associated_binary(self):
concepts_map = {
@@ -524,7 +514,8 @@ class TestSyaNodeParser(TestUsingMemoryBasedSheerka):
expected_array = compute_expected_array(concepts_map, expression, expected)
assert len(res) == 1
assert res[0].out == expected_array
transformed_out = get_test_obj(res[0].out, expected_array)
assert transformed_out == expected_array
def test_i_can_post_fix_left_associated_binary(self):
concepts_map = {
@@ -546,7 +537,8 @@ class TestSyaNodeParser(TestUsingMemoryBasedSheerka):
expected_array = compute_expected_array(concepts_map, expression, expected)
assert len(res) == 1
assert res[0].out == expected_array
transformed_out = get_test_obj(res[0].out, expected_array)
assert transformed_out == expected_array
@pytest.mark.parametrize("expression, expected", [
("x$!# ? y$!# : z$!# ? two : three", ["x$!#", "y$!#", "z$!#", "two", "three", ("?", 1), "?"]),
@@ -572,8 +564,10 @@ class TestSyaNodeParser(TestUsingMemoryBasedSheerka):
res = parser.infix_to_postfix(context, ParserInput(expression))
expected_array = compute_expected_array(concepts_map, expression, expected)
assert len(res) == 1
assert res[0].out == expected_array
transformed_out = get_test_obj(res[0].out, expected_array)
assert transformed_out == expected_array
@pytest.mark.parametrize("expression, expected", [
("x$!# ? y$!# : z$!# ? two : three", ["x$!#", "y$!#", "z$!#", "?", "two", "three", ("?", 1)]),
@@ -599,8 +593,10 @@ class TestSyaNodeParser(TestUsingMemoryBasedSheerka):
res = parser.infix_to_postfix(context, ParserInput(expression))
expected_array = compute_expected_array(concepts_map, expression, expected)
assert len(res) == 1
assert res[0].out == expected_array
transformed_out = get_test_obj(res[0].out, expected_array)
assert transformed_out == expected_array
def test_i_can_post_fix_when_multiple_concepts_are_found(self):
concepts_map = {
@@ -617,11 +613,7 @@ class TestSyaNodeParser(TestUsingMemoryBasedSheerka):
["baz", "foo bar"]
]
assert len(res) == len(expected_sequences)
for res_i, expected in zip(res, expected_sequences):
assert len(res_i.errors) == 0
expected_array = compute_expected_array(concepts_map, expression, expected)
assert res_i.out == expected_array
self.compare_results(res, expected_sequences, concepts_map, expression)
@pytest.mark.parametrize("expression, expected", [
# ("function(one plus three) minus two",
@@ -667,7 +659,8 @@ class TestSyaNodeParser(TestUsingMemoryBasedSheerka):
expected_array = compute_expected_array(cmap, expression, expected)
assert len(res) == 1
assert res[0].out == expected_array
transformed_out = get_test_obj(res[0].out, expected_array)
assert transformed_out == expected_array
@pytest.mark.parametrize("expression, expected_sequences", [
# composition
@@ -681,20 +674,18 @@ class TestSyaNodeParser(TestUsingMemoryBasedSheerka):
[[SCWC("function(", ")", CNC("prefixed", a=CIO("twenties", source="twenty two")))]]),
("function(if one then twenty two else three end)",
[[SCWC("function(", ")", CNC("if", a="one", b=CIO("twenties", source="twenty two"), c="three", end=16))]]),
("func1(func2(one two) three)",
[[SCWC("func1(", (")", 1), SCWC("func2(", ")", "one", "two"), "three")]]),
("twenty two(suffixed one)", [
["twenty ", SCWC("two(", ")", CNC("suffixed", a="one"))],
[CN("twenties", source="twenty two"), "one", "suffixed"],
[CN("twenties", "twenty two"), "one", "suffixed"],
]),
("twenty two(one prefixed)", [
["twenty ", SCWC("two(", ")", CNC("prefixed", a="one"))],
[CN("twenties", source="twenty two"), "one", "prefixed"],
[CN("twenties", "twenty two"), "one", "prefixed"],
]),
("f1(one plus two mult three) plus f2(suffixed x$!# prefixed)", [
[SCWC("f1(", ")", CN("plus", source="one plus two mult three")),
SCWC("f2(", (")", 1), CN("suffixed", source="suffixed x$!# prefixed")),
("f1(one plus two mult three) plus f2(suffixed xxx prefixed)", [
[SCWC("f1(", ")", CN("plus", "one plus two mult three")),
SCWC("f2(", (")", 1), CN("suffixed", "suffixed xxx prefixed")),
("plus", 1)]
]),
@@ -706,8 +697,8 @@ class TestSyaNodeParser(TestUsingMemoryBasedSheerka):
[SCWC("f1(", ")", "one"), SCWC("f2(", (")", 1), "two"), SCWC("f3(", (")", 2), "three"), "if"]]),
# Sequence
("if one then two else three end function(x$!#)", [
["one", "two", "three", "if", UTN(" ", start=13, end=13), SCWC("function(", ")", "x$!#")]]),
("if one then two else three end function(xxx)", [
["one", "two", "three", "if", UTN(" ", start=13, end=13), SCWC("function(", ")", "xxx")]]),
("one prefixed function(two)", [["one", "prefixed", UTN(" ", start=3, end=3), SCWC("function(", ")", "two")]]),
("suffixed one function(two)", [["one", "suffixed", UTN(" ", start=3, end=3), SCWC("function(", ")", "two")]]),
("func(one, two, three)", [[SCWC("func(", ")", "one", ", ", "two", (", ", 1), "three")]]),
@@ -717,10 +708,7 @@ class TestSyaNodeParser(TestUsingMemoryBasedSheerka):
res = parser.infix_to_postfix(context, ParserInput(expression))
assert len(res) == len(expected_sequences)
for res_i, expected in zip(res, expected_sequences):
expected_array = compute_expected_array(cmap, expression, expected)
assert res_i.out == expected_array
self.compare_results(res, expected_sequences, cmap, expression)
@pytest.mark.parametrize("expression, expected", [
("(", ("(", 0)),
@@ -800,7 +788,8 @@ class TestSyaNodeParser(TestUsingMemoryBasedSheerka):
expected_array = compute_expected_array(cmap, expression, expected)
assert len(res) == 1
assert res[0].out == expected_array
transformed_out = get_test_obj(res[0].out, expected_array)
assert transformed_out == expected_array
@pytest.mark.parametrize("expression", [
"one ? two : three",
@@ -818,7 +807,8 @@ class TestSyaNodeParser(TestUsingMemoryBasedSheerka):
expected_array = compute_expected_array(cmap, expression, expected)
assert len(res) == 1
assert res[0].out == expected_array
transformed_out = get_test_obj(res[0].out, expected_array)
assert transformed_out == expected_array
def test_the_more_concepts_the_more_results(self):
concepts_map = {
@@ -837,7 +827,7 @@ class TestSyaNodeParser(TestUsingMemoryBasedSheerka):
expression = "a plus plus equals b"
res = parser.infix_to_postfix(context, ParserInput(expression))
expected_array = tests.parsers.parsers_utils.compute_debug_array(res)
expected_array = compute_debug_array(res)
assert len(expected_array) == len([
["T(a)", "C(a plus b)", "C(a plus b)", "T(equals)", "T(b)"],
["T(a)", "C(a plus b)", "C(a plus plus)", "T(equals)", "T(b)"],
@@ -861,14 +851,17 @@ class TestSyaNodeParser(TestUsingMemoryBasedSheerka):
sheerka, context, parser = self.init_parser(concepts_map, None)
res = parser.infix_to_postfix(context, ParserInput("one ? ? two '::' three"))
assert len(res) == 1
assert res[0].out == [
cnode("one", start=0, end=0, source="one"),
cnode("two", start=6, end=6, source="two"),
cnode("three", start=10, end=10, source="three"),
expected_array = [
CN("one", start=0, end=0, source="one"),
CN("two", start=6, end=6, source="two"),
CN("three", start=10, end=10, source="three"),
SyaConceptParserHelper(concepts_map["ternary"], 2),
]
assert len(res) == 1
transformed_out = get_test_obj(res[0].out, expected_array)
assert transformed_out == expected_array
def test_i_cannot_chain_non_associative(self):
concepts_map = {
"less than": Concept("a less than b").def_var("a").def_var("b"),
@@ -897,10 +890,12 @@ class TestSyaNodeParser(TestUsingMemoryBasedSheerka):
expression = "suffixed twenties"
res = parser.infix_to_postfix(context, ParserInput(expression))
expected = [cnode("twenties", 2, 2, "twenties"), "suffixed"]
expected = [CN("twenties", "twenties", 2, 2), "suffixed"]
expected_array = compute_expected_array(cmap, expression, expected)
assert len(res) == 1
assert res[0].out == expected_array
transformed_out = get_test_obj(res[0].out, expected_array)
assert transformed_out == expected_array
@pytest.mark.parametrize("expression, expected_debugs", [
("one", [[" 0:one => PUSH_UNREC"]]),
@@ -999,12 +994,12 @@ class TestSyaNodeParser(TestUsingMemoryBasedSheerka):
assert res.status
assert context.sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
assert lexer_nodes == [CN(cmap["plus"], 0, 8, source=text)]
compare_with_test_object(lexer_nodes, [CN(cmap["plus"], text, 0, 8)])
# check the compiled
expected_concept = lexer_nodes[0].concept
assert expected_concept.get_compiled()["a"] == cmap["one"]
assert expected_concept.get_compiled()["b"] == CMV(cmap["mult"], a="two", b="three")
compare_with_test_object(expected_concept.get_compiled()["b"], CMV(cmap["mult"], a="two", b="three"))
assert expected_concept.get_compiled()["b"].get_compiled()["a"] == cmap["two"]
assert expected_concept.get_compiled()["b"].get_compiled()["b"] == cmap["three"]
@@ -1023,7 +1018,7 @@ class TestSyaNodeParser(TestUsingMemoryBasedSheerka):
assert res.status
assert context.sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
assert lexer_nodes == [CN(cmap["suffixed"], 0, 6, source=text)]
compare_with_test_object(lexer_nodes, [CN(cmap["suffixed"], text, 0, 6)])
# check the compiled
expected_concept = lexer_nodes[0].concept
@@ -1051,7 +1046,7 @@ class TestSyaNodeParser(TestUsingMemoryBasedSheerka):
lexer_nodes = res[1].body.body
assert context.sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
assert lexer_nodes == [CN(cmap["suffixed"], 0, 4, source=text)]
compare_with_test_object(lexer_nodes, [CN(cmap["suffixed"], text, 0, 4)])
# check the compiled
expected_concept = lexer_nodes[0].concept
@@ -1071,9 +1066,9 @@ class TestSyaNodeParser(TestUsingMemoryBasedSheerka):
assert res.status
assert context.sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
assert lexer_nodes == [
CN(cmap["plus"], 0, 9, source="one plus 1 + 1 "),
CN(cmap["suffixed"], 10, 12, source="suffixed two")]
compare_with_test_object(lexer_nodes, [
CN(cmap["plus"], "one plus 1 + 1 ", 0, 9),
CN(cmap["suffixed"], "suffixed two", 10, 12)])
# check the compiled
concept_plus_a = lexer_nodes[0].concept.get_compiled()["a"]
@@ -1105,7 +1100,9 @@ class TestSyaNodeParser(TestUsingMemoryBasedSheerka):
expected_array = compute_expected_array(cmap, text, expected_result)
assert res.status == expected_status
assert context.sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
assert lexer_nodes == expected_array
transformed_nodes = get_test_obj(lexer_nodes, expected_array)
assert transformed_nodes == expected_array
@pytest.mark.parametrize("text", [
"function(suffixed one)",
@@ -1166,11 +1163,15 @@ class TestSyaNodeParser(TestUsingMemoryBasedSheerka):
expected_array = compute_expected_array(cmap, text, expected_result)
assert not res.status
assert context.sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
assert lexer_nodes == expected_array
transformed_nodes = get_test_obj(lexer_nodes, expected_array)
assert transformed_nodes == expected_array
# assert lexer_nodes == expected_array
@pytest.mark.parametrize("text, expected_result", [
("a plus b", [CN("plus", source="a plus b")]),
("suffixed a plus b", [CN("suffixed", source="suffixed a plus b")]),
("a plus b", [CN("plus", "a plus b")]),
("suffixed a plus b", [CN("suffixed", "suffixed a plus b")]),
])
def test_i_can_almost_parse_concept_definition(self, text, expected_result):
"""
@@ -1190,7 +1191,9 @@ class TestSyaNodeParser(TestUsingMemoryBasedSheerka):
expected_array = compute_expected_array(cmap, text, expected_result)
assert not res.status
assert context.sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
assert lexer_nodes == expected_array
transformed_nodes = get_test_obj(lexer_nodes, expected_array)
assert transformed_nodes == expected_array
# assert lexer_nodes == expected_array
@pytest.mark.parametrize("text, expected_concept, expected_unrecognized", [
("x$!# prefixed", "prefixed", ["a"]),
@@ -1209,15 +1212,18 @@ class TestSyaNodeParser(TestUsingMemoryBasedSheerka):
assert not res.status
assert context.sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
assert lexer_nodes == [CN(cmap[expected_concept], 0, expected_end, source=text)]
expected_array = [CN(cmap[expected_concept], text, 0, expected_end)]
transformed_nodes = get_test_obj(lexer_nodes, expected_array)
assert transformed_nodes == expected_array
# assert lexer_nodes == [CN(cmap[expected_concept], text, 0, expected_end)]
concept_found = lexer_nodes[0].concept
for unrecognized in expected_unrecognized:
assert isinstance(concept_found.get_compiled()[unrecognized], UnrecognizedTokensNode)
@pytest.mark.parametrize("text, expected", [
("x$!# suffixed one", [utnode(0, 4, "x$!# "), cnode("suffixed __var__0", 5, 7, "suffixed one")]),
("one prefixed x$!#", [cnode("__var__0 prefixed", 0, 2, "one prefixed"), utnode(3, 7, " x$!#")]),
("x$!# suffixed one", [UTN("x$!# ", 0, 4), CN("suffixed __var__0", "suffixed one", 5, 7)]),
("one prefixed x$!#", [CN("__var__0 prefixed", "one prefixed", 0, 2), UTN(" x$!#", 3, 7)]),
])
def test_i_cannot_parse_when_part_of_the_sequence_is_not_recognized(self, text, expected):
sheerka, context, parser = self.init_parser()
@@ -1228,7 +1234,7 @@ class TestSyaNodeParser(TestUsingMemoryBasedSheerka):
assert not res.status
assert context.sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
assert lexer_nodes == expected
compare_with_test_object(lexer_nodes, expected)
def test_i_cannot_parse_function_using_short_name(self):
concepts_map = {
@@ -1301,15 +1307,15 @@ class TestSyaNodeParser(TestUsingMemoryBasedSheerka):
assert len(actual) == 1
assert actual[0].to_out == resolved_to_out
compare_with_test_object(actual[0].to_out, resolved_to_out)
actual[0].function.fix_source()
assert actual[0].function == resolved_function_name[0]
compare_with_test_object(actual[0].function, resolved_function_name[0])
@pytest.mark.parametrize("expression, expected_list", [
("twenty two function(", [(["twenty ", "two", UTN(" ", 3, 3)], "function("),
([CN("twenties", source="twenty two"), UTN(" ", 3, 3)], "function(")]),
([CN("twenties", "twenty two"), UTN(" ", 3, 3)], "function(")]),
("twenty two(", [(["twenty "], "two("),
([CN("twenties", source="twenty two")], None)]),
([CN("twenties", "twenty two")], None)]),
])
def test_i_can_get_functions_names_from_unrecognized_when_multiple_results(self, expression, expected_list):
sheerka, context, parser = self.init_parser()
@@ -1326,11 +1332,11 @@ class TestSyaNodeParser(TestUsingMemoryBasedSheerka):
for actual, expected in zip(actual_list, expected_list):
resolved_to_out = compute_expected_array(cmap, expression, expected[0])
assert actual.to_out == resolved_to_out
compare_with_test_object(actual.to_out, resolved_to_out)
if actual.function:
actual.function.fix_source()
resolved_function_name = compute_expected_array(cmap, expression, [expected[1]])
assert actual.function == resolved_function_name[0]
compare_with_test_object(actual.function, resolved_function_name[0])
else:
assert actual.function is None
@@ -1344,7 +1350,7 @@ class TestSyaNodeParser(TestUsingMemoryBasedSheerka):
assert res.status
assert context.sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
assert lexer_nodes == [CN(cmap["suffixed"], 0, 6, source=text)]
compare_with_test_object(lexer_nodes, [CN(cmap["suffixed"], text, 0, 6)])
# add an ontology layer and make sure will still can parse
sheerka.push_ontology(context, "new ontology")
@@ -1356,7 +1362,7 @@ class TestSyaNodeParser(TestUsingMemoryBasedSheerka):
assert res.status
assert context.sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
assert lexer_nodes == [CN(cmap["suffixed"], 0, 6, source=text)]
compare_with_test_object(lexer_nodes, [CN(cmap["suffixed"], text, 0, 6)])
class TestFileBaseSyaNodeParser(TestUsingFileBasedSheerka):
+33 -33
View File
@@ -1,14 +1,14 @@
from core.builtin_concepts import ParserResultConcept, BuiltinConcepts
from core.concept import Concept, CC
from core.concept import Concept
from core.tokenizer import Tokenizer, TokenKind
from parsers.BaseNodeParser import ConceptNode, UnrecognizedTokensNode, scnode, cnode, \
utnode, CN, CNC, UTN, SourceCodeWithConceptNode, SCWC, SourceCodeNode
from parsers.BaseNodeParser import ConceptNode, UnrecognizedTokensNode, SourceCodeWithConceptNode, SourceCodeNode
from parsers.BnfNodeParser import BnfNodeParser
from parsers.SequenceNodeParser import SequenceNodeParser
from parsers.SyaNodeParser import SyaNodeParser
from parsers.UnrecognizedNodeParser import UnrecognizedNodeParser
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
from tests.parsers.parsers_utils import compute_expected_array, get_node
from tests.parsers.parsers_utils import compute_expected_array, get_node, CC, UTN, CNC, CN, SCWC, \
compare_with_test_object, SCN
def get_input_nodes_from(my_concepts_map, full_expr, *args):
@@ -19,10 +19,10 @@ def get_input_nodes_from(my_concepts_map, full_expr, *args):
concept.get_compiled()[k] = _get_real_node(v)
return concept
if isinstance(n, (utnode, UTN)):
if isinstance(n, UTN):
return UnrecognizedTokensNode(n.start, n.end, full_expr_as_tokens[n.start: n.end + 1])
if isinstance(n, (CNC, CN, cnode)):
if isinstance(n, (CNC, CN)):
concept = n.concept if hasattr(n, "concept") and n.concept else \
Concept().update_from(my_concepts_map[n.concept_key])
tokens = full_expr_as_tokens[n.start: n.end + 1]
@@ -116,7 +116,7 @@ class TestUnrecognizedNodeParser(TestUsingMemoryBasedSheerka):
a=" one ",
b=" two three ",
c=" twenty one ",
d=utnode(12, 18, " 1 + 2 "),
d=UTN(" 1 + 2 ", 12, 18),
e=" one plus two mult three"))[0]
res = UnrecognizedNodeParser().validate_concept_node(context, node)
@@ -130,13 +130,14 @@ class TestUnrecognizedNodeParser(TestUsingMemoryBasedSheerka):
assert sheerka.isinstance(concept.get_compiled()["a"][0], BuiltinConcepts.RETURN_VALUE)
assert concept.get_compiled()["a"][0].status
assert concept.get_compiled()["a"][0].who == "parsers." + SequenceNodeParser.NAME
assert concept.get_compiled()["a"][0].body.body == [cnode("one", 1, 1, "one")]
compare_with_test_object(concept.get_compiled()["a"][0].body.body, [CN("one", "one", 1, 1)])
assert len(concept.get_compiled()["b"]) == 1
assert sheerka.isinstance(concept.get_compiled()["b"][0], BuiltinConcepts.RETURN_VALUE)
assert concept.get_compiled()["b"][0].status
assert concept.get_compiled()["b"][0].who == "parsers." + SequenceNodeParser.NAME
assert concept.get_compiled()["b"][0].body.body == [cnode("two", 1, 1, "two"), cnode("three", 3, 3, "three")]
compare_with_test_object(concept.get_compiled()["b"][0].body.body,
[CN("two", "two", 1, 1), CN("three", "three", 3, 3)])
assert len(concept.get_compiled()["c"]) == 1
assert sheerka.isinstance(concept.get_compiled()["c"][0], BuiltinConcepts.RETURN_VALUE)
@@ -145,8 +146,8 @@ class TestUnrecognizedNodeParser(TestUsingMemoryBasedSheerka):
expected_nodes = compute_expected_array(
concepts_map,
" twenty one ",
[CNC("twenties", source="twenty one", unit="one")])
assert concept.get_compiled()["c"][0].body.body == expected_nodes
[CNC("twenties", "twenty one", unit="one")])
compare_with_test_object(concept.get_compiled()["c"][0].body.body, expected_nodes)
assert len(concept.get_compiled()["d"]) == 1
assert sheerka.isinstance(concept.get_compiled()["d"][0], BuiltinConcepts.RETURN_VALUE)
@@ -164,7 +165,7 @@ class TestUnrecognizedNodeParser(TestUsingMemoryBasedSheerka):
[CNC("plus", a="one", b=CC("mult", a="two", b="three"))],
exclude_body=True)
assert concept.get_compiled()["e"][0].body.body == expected_nodes
compare_with_test_object(concept.get_compiled()["e"][0].body.body, expected_nodes)
# # sanity check, I can evaluate the concept
# evaluated = sheerka.evaluate_concept(self.get_context(sheerka, eval_body=True), concept)
@@ -204,8 +205,8 @@ class TestUnrecognizedNodeParser(TestUsingMemoryBasedSheerka):
expected_nodes = compute_expected_array(
concepts_map,
" twenty two",
[CNC("twenties", source="twenty two", unit="two")])
assert res.body.concept.get_compiled()["b"].get_compiled()["b"][0].body.body == expected_nodes
[CNC("twenties", "twenty two", unit="two")])
compare_with_test_object(res.body.concept.get_compiled()["b"].get_compiled()["b"][0].body.body, expected_nodes)
def test_i_can_validate_and_evaluate_a_concept_node_with_python(self):
sheerka, context, parser = self.init_parser()
@@ -281,7 +282,7 @@ class TestUnrecognizedNodeParser(TestUsingMemoryBasedSheerka):
assert sheerka.isinstance(parser_result, BuiltinConcepts.PARSER_RESULT)
assert parser_result.source == expression
assert len(actual_nodes) == 1
assert actual_nodes[0] == scnode(0, 4, expression)
compare_with_test_object(actual_nodes[0], SCN(expression, 0, 4))
def test_i_cannot_parse_unrecognized_python_that_looks_like_concept(self):
sheerka, context, parser = self.init_parser()
@@ -319,7 +320,7 @@ class TestUnrecognizedNodeParser(TestUsingMemoryBasedSheerka):
expected_array = compute_expected_array(
concepts_map,
expression, [CNC("twenties", source=expression, unit="one")])
assert actual_nodes == expected_array
compare_with_test_object(actual_nodes, expected_array)
def test_i_can_parse_unrecognized_sya_concept_node(self):
sheerka, context, parser = self.init_parser()
@@ -343,7 +344,7 @@ class TestUnrecognizedNodeParser(TestUsingMemoryBasedSheerka):
a="one",
b=CC("mult", source="two mult three", a="two", b="three"))],
exclude_body=True)
assert actual_nodes == expected_array
compare_with_test_object(actual_nodes, expected_array)
def test_i_can_parse_unrecognized_source_code_with_concept_node(self):
sheerka, context, parser = self.init_parser()
@@ -388,8 +389,8 @@ class TestUnrecognizedNodeParser(TestUsingMemoryBasedSheerka):
expression = "hello get_user_name(twenty one)"
tmp_node = CNC("hello_sya",
source="hello get_user_name(twenty one)",
a=SCWC("get_user_name(", ")", CNC("twenties", source="twenty one", unit="one")))
"hello get_user_name(twenty one)",
a=SCWC("get_user_name(", ")", CNC("twenties", "twenty one", unit="one")))
nodes = get_input_nodes_from(concepts_map, expression, tmp_node)
parser_input = ParserResultConcept("parsers.xxx", source=expression, value=nodes)
@@ -404,9 +405,9 @@ class TestUnrecognizedNodeParser(TestUsingMemoryBasedSheerka):
expected_array = compute_expected_array(
concepts_map,
expression, [CN("hello_sya", source="hello get_user_name(twenty one)")],
expression, [CN("hello_sya", "hello get_user_name(twenty one)")],
exclude_body=True)
assert actual_nodes == expected_array
compare_with_test_object(actual_nodes, expected_array)
assert isinstance(actual_nodes[0].concept.get_compiled()["a"], list)
assert sheerka.isinstance(actual_nodes[0].concept.get_compiled()["a"][0], BuiltinConcepts.RETURN_VALUE)
@@ -416,7 +417,7 @@ class TestUnrecognizedNodeParser(TestUsingMemoryBasedSheerka):
expression = "one plus two three"
sequence = get_input_nodes_from(concepts_map, expression,
CNC("plus", a="one", b="two"),
utnode(5, 6, " three"))
UTN(" three", 5, 6))
parser_input = ParserResultConcept("parsers.xxx", source="one plus two three", value=sequence)
res = parser.parse(context, parser_input)
@@ -429,7 +430,7 @@ class TestUnrecognizedNodeParser(TestUsingMemoryBasedSheerka):
expression, [
CNC("plus", a="one", b="two"),
CN("three", start=6, end=6)])
assert actual_nodes == expected_array
compare_with_test_object(actual_nodes, expected_array)
def test_i_can_parse_when_multiple_atom_and_sya(self):
sheerka, context, parser = self.init_parser()
@@ -445,19 +446,18 @@ class TestUnrecognizedNodeParser(TestUsingMemoryBasedSheerka):
actual_nodes0 = res[0].body.body
expected_0 = compute_expected_array(concepts_map, expression, [
CN("two", 0, 0),
CN("two", start=0, end=0),
CN("hello_atom", source="hello one", start=2, end=4),
CN("three", 6, 6)])
assert actual_nodes0 == expected_0
CN("three", start=6, end=6)])
compare_with_test_object(actual_nodes0, expected_0)
actual_nodes1 = res[1].body.body
expected_1 = compute_expected_array(concepts_map, expression, [
CN("two", 0, 0),
CNC("hello_sya", source="hello one", start=2, end=4, a="one"),
CN("three", 6, 6)],
CN("two", start=0, end=0),
CNC("hello_sya", "hello one", start=2, end=4, a="one"),
CN("three", start=6, end=6)],
exclude_body=True)
assert actual_nodes1 == expected_1
compare_with_test_object(actual_nodes1, expected_1)
def test_i_can_parse_when_multiple_sya_concepts(self):
sheerka, context, parser = self.init_parser()
@@ -474,12 +474,12 @@ class TestUnrecognizedNodeParser(TestUsingMemoryBasedSheerka):
actual_nodes0 = res[0].body.body
expected_0 = compute_expected_array(concepts_map, expression, [
CNC("greetings_a", source="greetings two", start=0, end=2, a="two")], exclude_body=True)
assert actual_nodes0 == expected_0
compare_with_test_object(actual_nodes0, expected_0)
actual_nodes1 = res[1].body.body
expected_1 = compute_expected_array(concepts_map, expression, [
CNC("greetings_b", source="greetings two", start=0, end=2, b="two")], exclude_body=True)
assert actual_nodes1 == expected_1
compare_with_test_object(actual_nodes1, expected_1)
def test_i_cannot_parse_when_some_unrecognized_remain(self):
sheerka, context, parser = self.init_parser()
+120 -15
View File
@@ -1,10 +1,13 @@
from core.concept import Concept, ConceptParts, CC
from core.concept import Concept, ConceptParts
from core.global_symbols import NotInit
from core.rule import Rule, ACTION_TYPE_EXEC
from core.sheerka.services.SheerkaExecute import ParserInput
from parsers.BaseNodeParser import CNC
from parsers.BaseNodeParser import RuleNode
from parsers.BnfNodeParser import BnfNodeParser
from parsers.FunctionParser import FunctionParser
from parsers.SyaNodeParser import SyaNodeParser
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
from tests.parsers.parsers_utils import get_test_obj
from tests.parsers.parsers_utils import get_test_obj, CNC, CC, CN, SCN, SCWC, UTN, RN, CB
class TestParsersUtils(TestUsingMemoryBasedSheerka):
@@ -20,12 +23,12 @@ class TestParsersUtils(TestUsingMemoryBasedSheerka):
cnode = parser.parse(context, ParserInput("one plus two")).body.body[0]
# compare all attributes
cnc_res = get_test_obj(CNC(concept_key="key", start=0, end=1, source="", exclude_body=False), cnode)
cnc_res = get_test_obj(cnode, CNC(concept_key="key", start=0, end=1, source="", exclude_body=False))
assert isinstance(cnc_res, CNC)
assert cnc_res == CNC("__var__0 plus __var__1", 0, 4, "one plus two", False, **cnode.concept.get_compiled())
assert cnc_res == CNC("__var__0 plus __var__1", "one plus two", 0, 4, False, **cnode.concept.get_compiled())
# I can discard start, end and source
cnc_res = get_test_obj(CNC(concept_key="key"), cnode)
cnc_res = get_test_obj(cnode, CNC(concept_key="key"))
assert isinstance(cnc_res, CNC)
assert cnc_res == CNC("__var__0 plus __var__1", None, None, None, False, **cnode.concept.get_compiled())
@@ -40,12 +43,12 @@ class TestParsersUtils(TestUsingMemoryBasedSheerka):
cnode = parser.parse(context, ParserInput("twenty one")).body.body[0]
# compare all attributes
cnc_res = get_test_obj(CNC(concept_key="key", start=0, end=1, source="", exclude_body=False), cnode)
cnc_res = get_test_obj(cnode, CNC(concept_key="key", start=0, end=1, source="", exclude_body=False))
assert isinstance(cnc_res, CNC)
assert cnc_res == CNC("twenties", 0, 2, "twenty one", False, **cnode.concept.get_compiled())
assert cnc_res == CNC("twenties", "twenty one", 0, 2, False, **cnode.concept.get_compiled())
# I can exclude body
cnc_res = get_test_obj(CNC(concept_key="key", exclude_body=True), cnode)
cnc_res = get_test_obj(cnode, CNC(concept_key="key", exclude_body=True))
expected_compiled = {k: v for k, v in cnode.concept.get_compiled().items()}
del expected_compiled[ConceptParts.BODY]
assert isinstance(cnc_res, CNC)
@@ -61,13 +64,13 @@ class TestParsersUtils(TestUsingMemoryBasedSheerka):
parser = SyaNodeParser().init_from_concepts(context, [one, two, plus])
cnode = parser.parse(context, ParserInput("one plus two")).body.body[0]
res = get_test_obj([CNC("key1"), CNC("key", 0, 1, "")], [cnode, cnode])
res = get_test_obj([cnode, cnode], [CNC("key1"), CNC("key", 0, 1, "")])
assert len(res) == 2
assert isinstance(res[0], CNC)
assert res[0] == CNC("__var__0 plus __var__1", None, None, None, False, **cnode.concept.get_compiled())
assert isinstance(res[1], CNC)
assert res[1] == CNC("__var__0 plus __var__1", 0, 4, "one plus two", False, **cnode.concept.get_compiled())
assert res[1] == CNC("__var__0 plus __var__1", "one plus two", 0, 4, False, **cnode.concept.get_compiled())
def test_i_can_get_test_obj_when_dict(self):
sheerka, context, one, two, plus = self.init_concepts(
@@ -79,12 +82,12 @@ class TestParsersUtils(TestUsingMemoryBasedSheerka):
parser = SyaNodeParser().init_from_concepts(context, [one, two, plus])
cnode = parser.parse(context, ParserInput("one plus two")).body.body[0]
res = get_test_obj({"key1": CNC("key1"), "key2": CNC("key", 0, 1, "")}, {"key1": cnode, "key2": cnode})
res = get_test_obj({"key1": cnode, "key2": cnode}, {"key1": CNC("key1"), "key2": CNC("key", 0, 1, "")})
assert len(res) == 2
assert isinstance(res["key1"], CNC)
assert res["key1"] == CNC("__var__0 plus __var__1", None, None, None, False, **cnode.concept.get_compiled())
assert isinstance(res["key2"], CNC)
assert res["key2"] == CNC("__var__0 plus __var__1", 0, 4, "one plus two", False, **cnode.concept.get_compiled())
assert res["key2"] == CNC("__var__0 plus __var__1", "one plus two", 0, 4, False, **cnode.concept.get_compiled())
def test_i_can_get_test_obj_when_CC(self):
sheerka, context, one, two, plus = self.init_concepts(
@@ -97,13 +100,115 @@ class TestParsersUtils(TestUsingMemoryBasedSheerka):
cc = parser.parse(context, ParserInput("twenty one")).body.body[0].concept
# compare all attributes
cc_res = get_test_obj(CC(concept="key", source="", exclude_body=False), cc)
cc_res = get_test_obj(cc, CC(concept="key", source="", exclude_body=False))
assert isinstance(cc_res, CC)
assert cc_res == CC("twenties", "twenty one", False, **cc.get_compiled())
# I can exclude body
cnc_res = get_test_obj(CC(concept="key", exclude_body=True), cc)
cnc_res = get_test_obj(cc, CC(concept="key", exclude_body=True))
expected_compiled = {k: v for k, v in cc.get_compiled().items()}
del expected_compiled[ConceptParts.BODY]
assert isinstance(cnc_res, CC)
assert cnc_res == CC("twenties", "twenty one", True, **expected_compiled)
def test_i_can_get_test_obj_when_CN(self):
sheerka, context, one, two, plus = self.init_concepts(
"one",
"two",
Concept("a plus b").def_var("a").def_var("b")
)
parser = SyaNodeParser().init_from_concepts(context, [one, two, plus])
cnode = parser.parse(context, ParserInput("one plus two")).body.body[0]
cn_res = get_test_obj(cnode, CN(concept="key", start=0, end=1, source=""))
assert isinstance(cn_res, CN)
assert cn_res == CN(plus, "one plus two", 0, 4)
# I can discard start, end and source
cnc_res = get_test_obj(cnode, CN(concept="key"))
assert isinstance(cnc_res, CN)
assert cnc_res == CN(plus, None, None, None)
def test_i_can_get_test_obj_when_SCN(self):
sheerka, context = self.init_test().unpack()
parser = FunctionParser()
scn = parser.parse(context, ParserInput("test()")).body.body
scn_res = get_test_obj(scn, SCN("", start=0, end=1))
assert isinstance(scn_res, SCN)
assert scn_res == SCN("test()", 0, 2)
# I can discard start and end
scn_res = get_test_obj(scn, SCN(""))
assert isinstance(scn_res, SCN)
assert scn_res == SCN("test()", None, None)
def test_i_can_get_test_obj_when_SCWC(self):
sheerka, context = self.init_test().unpack()
parser = FunctionParser()
scwc = parser.parse(context, ParserInput("test(param1, test2())")).body.body
scwc_res = get_test_obj(scwc, SCWC(UTN(""), UTN(""), UTN(""), UTN(""), SCN("", 0, 0)))
assert isinstance(scwc_res, SCWC)
expected = SCWC(UTN("test(", 0, 1),
UTN(")", 8, 8),
UTN("param1", 2, 2),
UTN(", ", 3, 4),
SCN("test2()", 5, 7))
expected.start = 0
expected.end = 8
assert scwc_res == expected
assert isinstance(scwc_res.first, UTN)
assert isinstance(scwc_res.last, UTN)
assert isinstance(scwc_res.content[0], UTN)
assert isinstance(scwc_res.content[1], UTN)
assert isinstance(scwc_res.content[2], SCN)
def test_i_can_get_test_obj_when_RN(self):
rule = Rule(ACTION_TYPE_EXEC, "test_rule", "True", "True")
rn = RuleNode(rule, 1, 1, source="r:|xxx:")
rn_res = get_test_obj(rn, RN("", "", 0, 1))
assert isinstance(rn_res, RN)
assert rn_res == RN(rule, rn.source, rn.start, rn.end)
# I can discard start and end
rn_res = get_test_obj(rn, RN("", None, None, None))
assert isinstance(rn_res, RN)
assert rn_res == RN(rule, None, None, None)
def test_i_can_get_test_obj_when_CB(self):
a = Concept("a", key="a", body="10").auto_init()
b = Concept("b", key="b", body=a).auto_init()
c = Concept("c", key="c")
other_c = Concept("c", key="c", body="i don't care")
# i can test when no body
res = get_test_obj(c, CB("", ""))
assert isinstance(res, CB)
assert res == CB("c", NotInit)
# i can test with a concept instead of a key
res = get_test_obj(c, CB(Concept(), ""))
assert isinstance(res, CB)
assert res == CB(other_c, NotInit) # don't care if it's not the real 'c', only test key and body
# # i can test when the body is a concept
res = get_test_obj(b, CB("", ""))
assert isinstance(res, CB)
assert res == CB("b", a)
# i can go into recursion when body is a concept
res = get_test_obj(b, CB("", CB("", "")))
assert isinstance(res, CB)
assert res == CB("b", CB("a", "10"))
# I can try to go into recursion when there nothing to found
res = get_test_obj(c, CB("", CB("", "")))
assert isinstance(res, CB)
assert res == CB("c", NotInit)