Restarting the project.

Fixing unit tests. Continuing SyaParser
This commit is contained in:
2026-04-12 09:40:04 +02:00
parent 3be854d34c
commit 078d8e5df6
15 changed files with 2351 additions and 1290 deletions
+71 -71
View File
@@ -12,103 +12,103 @@ DEFAULT_ONTOLOGY_NAME = "current_test_"
@pytest.fixture(scope="session")
def sheerka():
from core.Sheerka import Sheerka
sheerka = Sheerka()
sheerka.initialize("mem://")
return sheerka
from core.Sheerka import Sheerka
sheerka = Sheerka()
sheerka.initialize("mem://")
return sheerka
@pytest.fixture(scope="module", autouse=True)
def on_new_module(sheerka, request):
"""
For each new module, make sure to create a new ontology
Remove it at the end of the module
:param sheerka:
:type sheerka:
:param request:
:type request:
:return:
:rtype:
"""
from core.Event import Event
from core.ExecutionContext import ExecutionContext, ContextActions
module_name = request.module.__name__.split(".")[-1]
context = ExecutionContext("test",
Event(message=f"Executing module {module_name}"),
sheerka,
ContextActions.TESTING,
None)
ontology = sheerka.om.push_ontology(module_name)
yield
sheerka.om.revert_ontology(context, ontology)
"""
For each new module, make sure to create a new ontology
Remove it at the end of the module
:param sheerka:
:type sheerka:
:param request:
:type request:
:return:
:rtype:
"""
from core.Event import Event
from core.ExecutionContext import ExecutionContext, ContextActions
module_name = request.module.__name__.split(".")[-1]
context = ExecutionContext("test",
Event(message=f"Executing module {module_name}"),
sheerka,
ContextActions.TESTING,
None)
ontology = sheerka.om.push_ontology(module_name)
yield
sheerka.om.revert_ontology(context, ontology)
@pytest.fixture(scope="function")
def context(sheerka):
from core.Event import Event
from core.ExecutionContext import ExecutionContext, ContextActions
return ExecutionContext("test",
Event(message=""),
sheerka,
ContextActions.TESTING,
None)
from core.Event import Event
from core.ExecutionContext import ExecutionContext, ContextActions
return ExecutionContext("test",
Event(message=""),
sheerka,
ContextActions.TESTING,
None)
@pytest.fixture()
def next_id():
return GetNextId()
return GetNextId()
@pytest.fixture()
def user():
return User(username="johan doe", email="johan.doe@sheerka.com", firstname="johan", lastname="doe")
return User(username="johan doe", email="johan.doe@sheerka.com", firstname="johan", lastname="doe")
class TestUsingFileBasedSheerka:
@pytest.fixture(scope="class")
def sheerka(self):
sheerka = Sheerka()
sheerka.initialize()
return sheerka
@pytest.fixture(scope="class")
def sheerka(self):
sheerka = Sheerka()
sheerka.initialize()
return sheerka
class NewOntology:
"""
For some test who may need to declare the same concepts across the tests
"""
from core.ExecutionContext import ExecutionContext
def __init__(self, context: ExecutionContext, name=None):
self.sheerka = context.sheerka
self.context = context
self.name = name
self.ontology = None
if self.name is None:
self.name = inspect.stack()[1][3]
def __enter__(self):
self.ontology = self.sheerka.om.push_ontology(self.name)
return self.ontology
def __exit__(self, exc_type, exc_val, exc_tb):
self.sheerka.om.revert_ontology(self.context, self.ontology)
return False
"""
For some test who may need to declare the same concepts across the tests
"""
from core.ExecutionContext import ExecutionContext
def __init__(self, context: ExecutionContext, name=None):
self.sheerka = context.sheerka
self.context = context
self.name = name
self.ontology = None
if self.name is None:
self.name = inspect.stack()[1][3]
def __enter__(self):
self.ontology = self.sheerka.om.push_ontology(self.name)
return self.ontology
def __exit__(self, exc_type, exc_val, exc_tb):
self.sheerka.om.revert_ontology(self.context, self.ontology)
return False
def simple_token_compare(a, b):
return a.type == b.type and a.value == b.value
return a.type == b.type and a.value == b.value
@contextmanager
def comparable_tokens():
eq = Token.__eq__
ne = Token.__ne__
setattr(Token, "__eq__", simple_token_compare)
setattr(Token, "__ne__", lambda a, b: not simple_token_compare(a, b))
yield
setattr(Token, "__eq__", eq)
setattr(Token, "__ne__", ne)
eq = Token.__eq__
ne = Token.__ne__
setattr(Token, "__eq__", simple_token_compare)
setattr(Token, "__ne__", lambda a, b: not simple_token_compare(a, b))
yield
setattr(Token, "__eq__", eq)
setattr(Token, "__ne__", ne)
+356 -393
View File
@@ -20,12 +20,12 @@ ATTR_MAP = {
class GetNextId:
def __init__(self):
self.seq = 1000
def next(self):
self.seq += 1
return self.seq
def __init__(self):
self.seq = 1000
def next(self):
self.seq += 1
return self.seq
def get_concept(name=None, body=None,
@@ -47,126 +47,126 @@ def get_concept(name=None, body=None,
autouse=False,
sequence=None,
init_parameters=True) -> Concept:
"""
Create a Concept objet
Caution : 'id' and 'key' are not initialized
"""
Create a Concept objet
Caution : 'id' and 'key' are not initialized
:param name:
:type name:
:param body:
:type body:
:param id:
:type id:
:param key:
:type key:
:param where:
:type where:
:param pre:
:type pre:
:param post:
:type post:
:param ret:
:type ret:
:param definition:
:type definition:
:param definition_type:
:type definition_type:
:param desc:
:type desc:
:param props:
:type props:
:param variables:
:type variables:
:param parameters:
:type parameters:
:param bound_body:
:type bound_body:
:param is_builtin:
:type is_builtin:
:param is_unique:
:type is_unique:
:param autouse:
:type autouse:
:param sequence:
:type sequence:
:return:
:rtype:
"""
metadata = get_metadata(
name, body,
id,
key,
where,
pre,
post,
ret,
definition,
definition_type,
desc,
props,
variables,
parameters,
bound_body,
is_builtin,
is_unique,
autouse
)
if sequence:
metadata.auto_init(sequence)
else:
metadata.digest = ConceptManager.compute_metadata_digest(metadata)
metadata.all_attrs = ConceptManager.compute_all_attrs(metadata.variables)
if init_parameters and metadata.variables:
metadata.parameters = [v[0] if isinstance(v, tuple) else v for v in metadata.variables]
return Concept(metadata)
:param name:
:type name:
:param body:
:type body:
:param id:
:type id:
:param key:
:type key:
:param where:
:type where:
:param pre:
:type pre:
:param post:
:type post:
:param ret:
:type ret:
:param definition:
:type definition:
:param definition_type:
:type definition_type:
:param desc:
:type desc:
:param props:
:type props:
:param variables:
:type variables:
:param parameters:
:type parameters:
:param bound_body:
:type bound_body:
:param is_builtin:
:type is_builtin:
:param is_unique:
:type is_unique:
:param autouse:
:type autouse:
:param sequence:
:type sequence:
:return:
:rtype:
"""
metadata = get_metadata(
name, body,
id,
key,
where,
pre,
post,
ret,
definition,
definition_type,
desc,
props,
variables,
parameters,
bound_body,
is_builtin,
is_unique,
autouse
)
if sequence:
metadata.auto_init(sequence)
else:
metadata.digest = ConceptManager.compute_metadata_digest(metadata)
metadata.all_attrs = ConceptManager.compute_all_attrs(metadata.variables)
if init_parameters and metadata.variables:
metadata.parameters = [v[0] if isinstance(v, tuple) else v for v in metadata.variables]
return Concept(metadata)
def get_evaluated_concept(blueprint: Concept | ConceptMetadata, **kwargs):
"""
Returns a concept where value are already initialized
:param blueprint:
:type blueprint:
:param kwargs:
:type kwargs:
:return:
:rtype:
"""
def _isfloat(num):
try:
float(num)
return True
except ValueError:
return False
res = Concept(blueprint.get_metadata())
for attr in ATTR_MAP:
source_code = getattr(res.get_metadata(), attr)
if source_code == "" or source_code is None:
value = NotInit
elif source_code[0] in ("'", '"'):
value = source_code[1:-1]
elif source_code in ("True", "False"):
value = source_code == "True"
elif source_code.isdecimal():
value = int(source_code)
elif _isfloat(source_code):
value = float(source_code)
else:
raise Exception(f"Cannot manage {attr=}, {source_code=}")
setattr(res, ATTR_MAP[attr], value)
# force values
for k, v in kwargs.items():
res.set_value(ATTR_MAP.get(k, k), v)
res.get_runtime_info().is_evaluated = True
return res
"""
Returns a concept where value are already initialized
:param blueprint:
:type blueprint:
:param kwargs:
:type kwargs:
:return:
:rtype:
"""
def _isfloat(num):
try:
float(num)
return True
except ValueError:
return False
res = Concept(blueprint.get_metadata())
for attr in ATTR_MAP:
source_code = getattr(res.get_metadata(), attr)
if source_code == "" or source_code is None:
value = NotInit
elif source_code[0] in ("'", '"'):
value = source_code[1:-1]
elif source_code in ("True", "False"):
value = source_code == "True"
elif source_code.isdecimal():
value = int(source_code)
elif _isfloat(source_code):
value = float(source_code)
else:
raise Exception(f"Cannot manage {attr=}, {source_code=}")
setattr(res, ATTR_MAP[attr], value)
# force values
for k, v in kwargs.items():
res.set_value(ATTR_MAP.get(k, k), v)
res.get_runtime_info().is_evaluated = True
return res
def get_metadata(name=None, body=None,
@@ -188,68 +188,68 @@ def get_metadata(name=None, body=None,
autouse=False,
digest=None,
all_attrs=None):
new_variables = []
if variables:
for v in variables:
if isinstance(v, tuple):
new_variables.append(v)
else:
new_variables.append((v, NotInit))
return ConceptMetadata(
id,
name,
key,
is_builtin,
is_unique,
body,
where,
pre,
post,
ret,
definition,
definition_type,
desc,
autouse,
bound_body,
props or {},
tuple(new_variables),
parameters or [],
digest,
all_attrs,
)
new_variables = []
if variables:
for v in variables:
if isinstance(v, tuple):
new_variables.append(v)
else:
new_variables.append((v, NotInit))
return ConceptMetadata(
id,
name,
key,
is_builtin,
is_unique,
body,
where,
pre,
post,
ret,
definition,
definition_type,
desc,
autouse,
bound_body,
props or {},
tuple(new_variables),
parameters or [],
digest,
all_attrs,
)
def metadata_auto_init(self: ConceptMetadata, sequence) -> ConceptMetadata:
"""
Helper function for the unit tests.
This method will be added to the `ConceptMetadata` to ease the writing of the unit tests
It properly initializes the ConceptMetadata
:param self:
:type self:
:param sequence:
:type sequence:
:return:
:rtype:
"""
if not self.id:
self.id = str(sequence.next())
if not self.key:
self.key = ConceptManager.create_concept_key(self.name, self.definition, self.variables)
if not self.is_unique:
self.is_unique = False
if not self.is_builtin:
self.is_builtin = False
if not self.definition_type:
self.definition_type = DefinitionType.DEFAULT
if not self.all_attrs:
self.all_attrs = ConceptManager.compute_all_attrs(self.variables)
if not self.digest:
self.digest = ConceptManager.compute_metadata_digest(self)
# Note that I do not automatically update the digest as I don't want to make unnecessary computations
return self
"""
Helper function for the unit tests.
This method will be added to the `ConceptMetadata` to ease the writing of the unit tests
It properly initializes the ConceptMetadata
:param self:
:type self:
:param sequence:
:type sequence:
:return:
:rtype:
"""
if not self.id:
self.id = str(sequence.next())
if not self.key:
self.key = ConceptManager.create_concept_key(self.name, self.definition, self.variables)
if not self.is_unique:
self.is_unique = False
if not self.is_builtin:
self.is_builtin = False
if not self.definition_type:
self.definition_type = DefinitionType.DEFAULT
if not self.all_attrs:
self.all_attrs = ConceptManager.compute_all_attrs(self.variables)
if not self.digest:
self.digest = ConceptManager.compute_metadata_digest(self)
# Note that I do not automatically update the digest as I don't want to make unnecessary computations
return self
def metadata_clone(self: ConceptMetadata, name=None, body=None,
@@ -270,75 +270,75 @@ def metadata_clone(self: ConceptMetadata, name=None, body=None,
autouse=None,
digest=None,
all_attrs=None) -> ConceptMetadata:
"""
Helper function for the unit tests.
This method will be added to the `ConceptMetadata` to ease the writing of the unit tests
It clones a ConceptMetadata, but can override some attributes if requested
:param self:
:type self:
:param name:
:type name:
:param body:
:type body:
:param key:
:type key:
:param where:
:type where:
:param pre:
:type pre:
:param post:
:type post:
:param ret:
:type ret:
:param definition:
:type definition:
:param definition_type:
:type definition_type:
:param desc:
:type desc:
:param props:
:type props:
:param variables:
:type variables:
:param parameters:
:type parameters:
:param bound_body:
:type bound_body:
:param is_builtin:
:type is_builtin:
:param is_unique:
:type is_unique:
:param autouse:
:type autouse:
:param digest:
:type digest:
:param all_attrs:
:type all_attrs:
:return:
:rtype:
"""
return ConceptMetadata(
id=self.id,
name=self.name if name is None else name,
body=self.body if body is None else body,
key=self.key if key is None else key,
where=self.where if where is None else where,
pre=self.pre if pre is None else pre,
post=self.post if post is None else post,
ret=self.ret if ret is None else ret,
definition=self.definition if definition is None else definition,
definition_type=self.definition_type if definition_type is None else definition_type,
desc=self.desc if desc is None else desc,
props=self.props if props is None else props,
variables=self.variables if variables is None else variables,
parameters=self.parameters if parameters is None else parameters,
bound_body=self.bound_body if bound_body is None else bound_body,
is_builtin=self.is_builtin if is_builtin is None else is_builtin,
is_unique=self.is_unique if is_unique is None else is_unique,
autouse=self.autouse if autouse is None else autouse,
digest=self.digest if digest is None else digest,
all_attrs=self.all_attrs if all_attrs is None else all_attrs,
)
"""
Helper function for the unit tests.
This method will be added to the `ConceptMetadata` to ease the writing of the unit tests
It clones a ConceptMetadata, but can override some attributes if requested
:param self:
:type self:
:param name:
:type name:
:param body:
:type body:
:param key:
:type key:
:param where:
:type where:
:param pre:
:type pre:
:param post:
:type post:
:param ret:
:type ret:
:param definition:
:type definition:
:param definition_type:
:type definition_type:
:param desc:
:type desc:
:param props:
:type props:
:param variables:
:type variables:
:param parameters:
:type parameters:
:param bound_body:
:type bound_body:
:param is_builtin:
:type is_builtin:
:param is_unique:
:type is_unique:
:param autouse:
:type autouse:
:param digest:
:type digest:
:param all_attrs:
:type all_attrs:
:return:
:rtype:
"""
return ConceptMetadata(
id=self.id,
name=self.name if name is None else name,
body=self.body if body is None else body,
key=self.key if key is None else key,
where=self.where if where is None else where,
pre=self.pre if pre is None else pre,
post=self.post if post is None else post,
ret=self.ret if ret is None else ret,
definition=self.definition if definition is None else definition,
definition_type=self.definition_type if definition_type is None else definition_type,
desc=self.desc if desc is None else desc,
props=self.props if props is None else props,
variables=self.variables if variables is None else variables,
parameters=self.parameters if parameters is None else parameters,
bound_body=self.bound_body if bound_body is None else bound_body,
is_builtin=self.is_builtin if is_builtin is None else is_builtin,
is_unique=self.is_unique if is_unique is None else is_unique,
autouse=self.autouse if autouse is None else autouse,
digest=self.digest if digest is None else digest,
all_attrs=self.all_attrs if all_attrs is None else all_attrs,
)
# Helpers functions for unit tests
@@ -347,175 +347,138 @@ setattr(ConceptMetadata, 'clone', metadata_clone)
def get_metadatas(*args, **kwargs):
as_metadatas = [arg if isinstance(arg, ConceptMetadata) else get_metadata(arg) for arg in args]
next_id = kwargs.get("next_id", None)
if next_id:
for metadata in as_metadatas:
metadata_auto_init(metadata, next_id)
return as_metadatas
as_metadatas = [arg if isinstance(arg, ConceptMetadata) else get_metadata(arg) for arg in args]
next_id = kwargs.get("next_id", None)
if next_id:
for metadata in as_metadatas:
metadata_auto_init(metadata, next_id)
return as_metadatas
def get_concepts(context: ExecutionContext, *concepts, **kwargs) -> list[Concept]:
"""
Simple and quick way to get initialize concepts for a test
:param context:
:param concepts: Concepts to create
:param kwargs: named parameters to tweak the creation of the concepts
use_sheerka : Adds the new concepts to Sheerka. If not simply creates concepts that do not affect Sheerka
sequence : Sequence Manager, to give a correct id to the created concepts
:return: the concepts
"""
res = []
use_sheerka = kwargs.pop("use_sheerka", False)
sequence = kwargs.pop("sequence", None)
for c in concepts:
if use_sheerka:
c = define_new_concept(context, c)
elif isinstance(c, str):
c = get_concept(c)
if sequence:
c.get_metadata().auto_init(sequence)
res.append(c)
return res
"""
Simple and quick way to get initialize concepts for a test
:param context:
:param concepts: Concepts to create
:param kwargs: named parameters to tweak the creation of the concepts
use_sheerka : Adds the new concepts to Sheerka. If not simply creates concepts that do not affect Sheerka
sequence : Sequence Manager, to give a correct id to the created concepts
:return: the concepts
"""
res = []
use_sheerka = kwargs.pop("use_sheerka", False)
sequence = kwargs.pop("sequence", None)
for c in concepts:
if use_sheerka:
c = define_new_concept(context, c)
elif isinstance(c, str):
c = get_concept(c)
if sequence:
c.get_metadata().auto_init(sequence)
res.append(c)
return res
def get_evaluated_concepts(context, *concepts, use_sheerka=False) -> list[Concept]:
if use_sheerka:
return [context.sheerka.evaluate_concept(context, Concept(c.get_metadata())) for c in concepts]
else:
return [get_evaluated_concept(concept) for concept in concepts]
if use_sheerka:
return [context.sheerka.evaluate_concept(context, Concept(c.get_metadata())) for c in concepts]
else:
return [get_evaluated_concept(concept) for concept in concepts]
def define_new_concept(context: ExecutionContext, c: str | Concept | ConceptMetadata) -> Concept:
sheerka = context.sheerka
if isinstance(c, str):
retval = sheerka.define_new_concept(context, c)
else:
metadata = c.get_metadata()
retval = sheerka.define_new_concept(context,
metadata.name,
metadata.is_builtin,
metadata.is_unique,
metadata.body,
metadata.where,
metadata.pre,
metadata.post,
metadata.ret,
metadata.definition,
metadata.definition_type,
metadata.autouse,
metadata.bound_body,
metadata.desc,
metadata.props,
metadata.variables,
metadata.parameters)
assert retval.status
concept = sheerka.newi(retval.value.metadata.id)
return concept
sheerka = context.sheerka
if isinstance(c, str):
retval = sheerka.define_new_concept(context, c)
else:
metadata = c.get_metadata()
retval = sheerka.define_new_concept(context,
metadata.name,
metadata.is_builtin,
metadata.is_unique,
metadata.body,
metadata.where,
metadata.pre,
metadata.post,
metadata.ret,
metadata.definition,
metadata.definition_type,
metadata.autouse,
metadata.bound_body,
metadata.desc,
metadata.props,
metadata.variables,
metadata.parameters)
assert retval.status
concept = sheerka.newi(retval.value.metadata.id)
return concept
def get_file_content(file_name):
with open(file_name) as f:
return f.read()
with open(file_name) as f:
return f.read()
def get_parser_input(text):
pi = ParserInput(text)
assert pi.init()
return pi
pi = ParserInput(text)
assert pi.init()
return pi
def get_from(*args, **kwargs):
"""
Convert the input to fix the positions
:param args:
:type args:
:return:
:rtype:
"""
cache = {} # I keep the name in cache to avoid having to remind it everytime
pos = 0
res = []
for item in args:
start = pos
if isinstance(item, MetadataToken):
if item.metadata.name:
cache[item.metadata.id] = item.metadata.name
tokens = list(Tokenizer(cache[item.metadata.id], yield_eof=False))
pos += len(tokens)
resolution_method = kwargs.get("resolution_method", item.resolution_method)
parser = kwargs.get("parser", item.parser)
res.append(MetadataToken(item.metadata, start, pos - 1, resolution_method, parser))
elif isinstance(item, UnrecognizedToken):
tokens = list(Tokenizer(item.buffer, yield_eof=False))
pos += len(tokens)
res.append(UnrecognizedToken(item.buffer, start, pos - 1))
return res
"""
Convert the input to fix the positions
:param args:
:type args:
:return:
:rtype:
"""
cache = {} # I keep the name in cache to avoid having to remind it everytime
pos = 0
res = []
for item in args:
start = pos
if isinstance(item, MetadataToken):
if item.metadata.name:
cache[item.metadata.id] = item.metadata.name
tokens = list(Tokenizer(cache[item.metadata.id], yield_eof=False))
pos += len(tokens)
resolution_method = kwargs.get("resolution_method", item.resolution_method)
parser = kwargs.get("parser", item.parser)
res.append(MetadataToken(item.metadata, start, pos - 1, resolution_method, parser))
elif isinstance(item, UnrecognizedToken):
tokens = list(Tokenizer(item.buffer, yield_eof=False))
pos += len(tokens)
res.append(UnrecognizedToken(item.buffer, start, pos - 1))
return res
def _rv(value, who="Test"):
return ReturnValue(who=who, status=True, value=value)
return ReturnValue(who=who, status=True, value=value)
def _rvc(concept_name, who="Test"):
next_id = GetNextId()
concept = get_concept(concept_name, sequence=next_id)
return ReturnValue(who=who, status=True, value=concept)
next_id = GetNextId()
concept = get_concept(concept_name, sequence=next_id)
return ReturnValue(who=who, status=True, value=concept)
def _rvf(value, who="Test"):
"""
Return Value False
:param value:
:type value:
:return:
:rtype:
"""
return ReturnValue(who=who, status=False, value=value)
"""
Return Value False
:param value:
:type value:
:return:
:rtype:
"""
return ReturnValue(who=who, status=False, value=value)
def _ut(buffer, start=0, end=-1):
"""
helper to UnrecognizedToken
:param buffer:
:type buffer:
:param start:
:type start:
:param end:
:type end:
:return:
:rtype:
"""
return UnrecognizedToken(buffer, start, end)
def _mt(concept_id,
start=0,
end=-1,
resolution_method: Literal["name", "key", "id"] = "id",
parser="simple",
**kwargs):
"""
helper to MetadataToken
:param concept_id:
:type concept_id:
:param start:
:type start:
:param end:
:type end:
:return:
:rtype:
"""
name, _id = unstr_concept(concept_id)
variables = [(k, v) for k, v in kwargs.items()] if kwargs else None
metadata = get_metadata(id=concept_id, variables=variables) if _id is None \
else get_metadata(id=_id, name=name, variables=variables)
return MetadataToken(metadata, start, end, resolution_method, parser)
-62
View File
@@ -1,62 +0,0 @@
import logging
from multiprocessing import Process
from time import sleep
import uvicorn
from fastapi import FastAPI
class MockServer:
""" Core application to test. """
def __init__(self, endpoints: list[dict]):
"""
:param endpoints:
:type endpoints: list of {path: '', response:''}
"""
self.api = FastAPI()
def raise_exception(ex):
raise ex
# register endpoints
for endpoint in endpoints:
method = endpoint["method"] if "method" in endpoint else "get"
if method == "post":
if "exception" in endpoint:
self.api.post(endpoint["path"])(lambda: raise_exception(endpoint["exception"]))
else:
self.api.post(endpoint["path"])(lambda: endpoint["response"])
else:
self.api.get(endpoint["path"])(lambda: endpoint["response"])
# register shutdown
self.api.on_event("shutdown")(self.close)
# create the process
self.proc = Process(target=uvicorn.run,
args=(self.api,),
kwargs={
"host": "127.0.0.1",
"port": 5000,
"log_level": "info"},
daemon=True)
async def close(self):
""" Gracefull shutdown. """
logging.warning("Shutting down the app.")
def start_server(self):
self.proc.start()
sleep(0.1)
def stop_server(self):
self.proc.terminate()
def __enter__(self):
self.start_server()
return self
def __exit__(self, exc_type, exc_val, exc_tb):
self.stop_server()
+105
View File
@@ -0,0 +1,105 @@
from typing import Literal
from common.utils import str_concept, unstr_concept
from helpers import get_metadata
from parsers.state_machine import MetadataToken, UnrecognizedToken
class MetadataTokenForTest(MetadataToken):
def __repr__(self):
res = f"(MetadataTokenForTest metadata={str_concept(self.metadata, drop_name=True)}"
if self.start is not None:
res += f", start={self.start}"
if self.end is not None:
res += f", end={self.end}"
if self.resolution_method is not None:
res += f", method={self.resolution_method}"
if self.parser is not None:
res += f", origin={self.parser}"
res += ")"
return res
def __eq__(self, other):
if not isinstance(other, MetadataToken):
return False
if self.metadata.id != other.metadata.id:
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
if self.parser is not None and self.parser != other.parser:
return False
if self.resolution_method is not None and self.resolution_method != other.resolution_method:
return False
return True
def _ut(buffer, start=0, end=-1):
"""
helper to UnrecognizedToken
:param buffer:
:type buffer:
:param start:
:type start:
:param end:
:type end:
:return:
:rtype:
"""
return UnrecognizedToken(buffer, start, end)
def _mt(concept_id,
start=0,
end=-1,
resolution_method: Literal["name", "key", "id"] = "key",
parser="simple",
**kwargs):
"""
helper to MetadataToken
:param concept_id:
:type concept_id:
:param start:
:type start:
:param end:
:type end:
:return:
:rtype:
"""
name, _id = unstr_concept(concept_id)
variables = [(k, v) for k, v in kwargs.items()] if kwargs else None
metadata = get_metadata(id=concept_id, variables=variables) if _id is None \
else get_metadata(id=_id, name=name, variables=variables)
return MetadataTokenForTest(metadata, start, end, resolution_method, parser)
def _mtsya(concept_id,
start=0,
end=None,
resolution_method: Literal["name", "key", "id"] = "key",
parser="sya",
**kwargs):
"""
helper to MetadataToken
:param concept_id:
:type concept_id:
:param start:
:type start:
:param end:
:type end:
:return:
:rtype:
"""
name, _id = unstr_concept(concept_id)
variables = [(k, v) for k, v in kwargs.items()] if kwargs else None
metadata = get_metadata(id=concept_id, variables=variables) if _id is None \
else get_metadata(id=_id, name=name, variables=variables)
return MetadataTokenForTest(metadata, start, end, resolution_method, parser)
+142 -141
View File
@@ -3,148 +3,149 @@ import pytest
from base import BaseTest
from conftest import NewOntology
from evaluators.base_evaluator import MultipleChoices
from helpers import _mt, _ut, get_concepts, get_from, get_metadata, get_parser_input
from helpers import get_concepts, get_from, get_metadata, get_parser_input
from parsers.SimpleConceptsParser import SimpleConceptsParser
from tests.parsers.conftest import _mt, _ut
class TestSimpleConceptsParser(BaseTest):
@pytest.fixture()
def parser(self):
return SimpleConceptsParser()
@pytest.mark.parametrize("text, expected", [
("I am a new concept", [_mt("1003", 0, 8)]),
("xxx yyy I am a new concept", [_ut("xxx yyy ", 0, 3), _mt("1003", 4, 12)]),
("I am a new concept xxx yyy", [_mt("1003", 0, 8), _ut(" xxx yyy", 9, 12)]),
("xxx I am a new concept yyy", [_ut("xxx ", 0, 1), _mt("1003", 2, 10), _ut(" yyy", 11, 12)]),
("c:#1003:", [_mt("1003", 0, 0)]),
("xxx c:#1003: yyy", [_ut("xxx ", 0, 1), _mt("1003", 2, 2), _ut(" yyy", 3, 4)]),
("xxx c:I am: yyy", [_ut("xxx ", 0, 1), _mt("1002", 2, 2), _ut(" yyy", 3, 4)]),
(" I am a new concept", [_ut(" ", 0, 0), _mt("1003", 1, 9)])
])
def test_i_can_recognize_a_concept(self, context, parser, text, expected):
with NewOntology(context, "test_i_can_recognize_a_concept"):
get_concepts(context, "I", "I am", "I am a new concept", use_sheerka=True)
pi = get_parser_input(text)
error_sink = []
res = parser.parse(context, pi, error_sink)
assert res == MultipleChoices([expected])
assert not error_sink
@pytest.mark.parametrize("text, expected", [
("foo", [_mt("1001", 0, 0)]),
("I am a new concept", [_mt("1001", 0, 8)])
])
def test_i_can_recognize_a_concept_by_its_name_and_its_definition(self, context, parser, text, expected):
with NewOntology(context, "test_i_can_recognize_a_concept_by_its_name_and_its_definition"):
get_concepts(context, get_metadata(name="foo", definition="I am a new concept"), use_sheerka=True)
pi = get_parser_input(text)
error_sink = []
res = parser.parse(context, pi, error_sink)
assert res == MultipleChoices([expected])
assert not error_sink
@pytest.mark.parametrize("text, expected", [
("long concept name", [_mt("1001", 0, 4)]),
("I am a new concept", [_mt("1001", 0, 8)])
])
def test_i_can_recognize_a_concept_by_its_name_when_long_name(self, context, parser, text, expected):
with NewOntology(context, "test_i_can_recognize_a_concept_by_its_name_when_long_name"):
get_concepts(context, get_metadata(name="long concept name", definition="I am a new concept"),
use_sheerka=True)
pi = get_parser_input(text)
error_sink = []
res = parser.parse(context, pi, error_sink)
assert res == MultipleChoices([expected])
assert not error_sink
def test_i_can_parse_a_sequence_of_concept(self, context, parser):
with NewOntology(context, "test_i_can_parse_a_sequence_of_concept"):
get_concepts(context, "foo bar", "baz", "qux", use_sheerka=True)
pi = get_parser_input("foo bar baz foo, qux")
error_sink = []
res = parser.parse(context, pi, error_sink)
expected = [_mt("1001", 0, 2),
_ut(" ", 3, 3),
_mt("1002", 4, 4),
_ut(" foo, ", 5, 8),
_mt("1003", 9, 9)]
assert res == MultipleChoices([expected])
assert not error_sink
def test_i_can_detect_multiple_choices(self, context, parser):
with NewOntology(context, "test_i_can_detect_multiple_choices"):
get_concepts(context, "foo bar", "bar baz", use_sheerka=True)
pi = get_parser_input("foo bar baz")
error_sink = []
res = parser.parse(context, pi, error_sink)
expected1 = [_mt("1001", 0, 2), _ut(" baz", 3, 4)]
expected2 = [_ut("foo ", 0, 1), _mt("1002", 2, 4)]
assert res == MultipleChoices([expected1, expected2])
assert not error_sink
def test_i_can_detect_multiple_choices_2(self, context, parser):
with NewOntology(context, "test_i_can_detect_multiple_choices_2"):
get_concepts(context, "one two", "one", "two", use_sheerka=True)
pi = get_parser_input("one two")
error_sink = []
res = parser.parse(context, pi, error_sink)
expected1 = [_mt("1001", 0, 2)]
expected2 = [_mt("1002", 0, 0), _ut(" ", 1, 1), _mt("1003", 2, 2)]
assert res == MultipleChoices([expected1, expected2])
assert not error_sink
def test_i_can_detect_multiple_choices_3(self, context, parser):
with NewOntology(context, "test_i_can_detect_multiple_choices_2"):
get_concepts(context, "one two", "one", "two", use_sheerka=True)
pi = get_parser_input("one two xxx one two")
error_sink = []
res = parser.parse(context, pi, error_sink)
e1 = get_from(_mt("c:one two#1001:"), _ut(" xxx "), _mt("c:#1001:"))
e2 = get_from(_mt("c:one#1002:"), _ut(" "), _mt("c:two#1003:"), _ut(" xxx "), _mt("c:one two#1001:"))
e3 = get_from(_mt("c:one two#1001:"), _ut(" xxx "), _mt("c:one#1002:"), _ut(" "), _mt("c:two#1003:"))
e4 = get_from(_mt("c:one#1002:"), _ut(" "), _mt("c:two#1003:"), _ut(" xxx "), _mt("c:#1002:"), _ut(" "),
_mt("c:#1003:"))
assert res == MultipleChoices([e1, e2, e3, e4])
assert not error_sink
def test_nothing_is_return_is_no_concept_is_recognized(self, context, parser):
pi = get_parser_input("one two three")
error_sink = []
res = parser.parse(context, pi, error_sink)
assert res == MultipleChoices([])
def test_i_can_manage_attribute_reference(self, context, parser):
with NewOntology(context, "test_i_can_detect_multiple_choices_2"):
get_concepts(context, "foo", "i am a concept", use_sheerka=True)
pi = get_parser_input("foo.attribute")
error_sink = []
res = parser.parse(context, pi, error_sink)
expected = [_mt("1001", 0, 0), _ut(".attribute", 1, 2)]
assert res == MultipleChoices([expected])
pi = get_parser_input("i am a concept.attribute")
res = parser.parse(context, pi, error_sink)
expected = [_mt("1002", 0, 6), _ut(".attribute", 7, 8)]
assert res == MultipleChoices([expected])
@pytest.fixture()
def parser(self):
return SimpleConceptsParser()
@pytest.mark.parametrize("text, expected", [
("I am a new concept", [_mt("1003", 0, 8)]),
("xxx yyy I am a new concept", [_ut("xxx yyy ", 0, 3), _mt("1003", 4, 12)]),
("I am a new concept xxx yyy", [_mt("1003", 0, 8), _ut(" xxx yyy", 9, 12)]),
("xxx I am a new concept yyy", [_ut("xxx ", 0, 1), _mt("1003", 2, 10), _ut(" yyy", 11, 12)]),
("c:#1003:", [_mt("1003", 0, 0, resolution_method="id")]),
("xxx c:#1003: yyy", [_ut("xxx ", 0, 1), _mt("1003", 2, 2, resolution_method="id"), _ut(" yyy", 3, 4)]),
("xxx c:I am: yyy", [_ut("xxx ", 0, 1), _mt("1002", 2, 2, resolution_method="name"), _ut(" yyy", 3, 4)]),
(" I am a new concept", [_ut(" ", 0, 0), _mt("1003", 1, 9)])
])
def test_i_can_recognize_a_concept(self, context, parser, text, expected):
with NewOntology(context, "test_i_can_recognize_a_concept"):
get_concepts(context, "I", "I am", "I am a new concept", use_sheerka=True)
pi = get_parser_input(text)
error_sink = []
res = parser.parse(context, pi, error_sink)
assert res == MultipleChoices([expected])
assert not error_sink
@pytest.mark.parametrize("text, expected", [
("foo", [_mt("1001", 0, 0, resolution_method="name")]),
("I am a new concept", [_mt("1001", 0, 8)])
])
def test_i_can_recognize_a_concept_by_its_name_and_its_definition(self, context, parser, text, expected):
with NewOntology(context, "test_i_can_recognize_a_concept_by_its_name_and_its_definition"):
get_concepts(context, get_metadata(name="foo", definition="I am a new concept"), use_sheerka=True)
pi = get_parser_input(text)
error_sink = []
res = parser.parse(context, pi, error_sink)
assert res == MultipleChoices([expected])
assert not error_sink
@pytest.mark.parametrize("text, expected", [
("long concept name", [_mt("1001", 0, 4, resolution_method="name")]),
("I am a new concept", [_mt("1001", 0, 8)])
])
def test_i_can_recognize_a_concept_by_its_name_when_long_name(self, context, parser, text, expected):
with NewOntology(context, "test_i_can_recognize_a_concept_by_its_name_when_long_name"):
get_concepts(context, get_metadata(name="long concept name", definition="I am a new concept"),
use_sheerka=True)
pi = get_parser_input(text)
error_sink = []
res = parser.parse(context, pi, error_sink)
assert res == MultipleChoices([expected])
assert not error_sink
def test_i_can_parse_a_sequence_of_concept(self, context, parser):
with NewOntology(context, "test_i_can_parse_a_sequence_of_concept"):
get_concepts(context, "foo bar", "baz", "qux", use_sheerka=True)
pi = get_parser_input("foo bar baz foo, qux")
error_sink = []
res = parser.parse(context, pi, error_sink)
expected = [_mt("1001", 0, 2),
_ut(" ", 3, 3),
_mt("1002", 4, 4),
_ut(" foo, ", 5, 8),
_mt("1003", 9, 9)]
assert res == MultipleChoices([expected])
assert not error_sink
def test_i_can_detect_multiple_choices(self, context, parser):
with NewOntology(context, "test_i_can_detect_multiple_choices"):
get_concepts(context, "foo bar", "bar baz", use_sheerka=True)
pi = get_parser_input("foo bar baz")
error_sink = []
res = parser.parse(context, pi, error_sink)
expected1 = [_mt("1001", 0, 2), _ut(" baz", 3, 4)]
expected2 = [_ut("foo ", 0, 1), _mt("1002", 2, 4)]
assert res == MultipleChoices([expected1, expected2])
assert not error_sink
def test_i_can_detect_multiple_choices_2(self, context, parser):
with NewOntology(context, "test_i_can_detect_multiple_choices_2"):
get_concepts(context, "one two", "one", "two", use_sheerka=True)
pi = get_parser_input("one two")
error_sink = []
res = parser.parse(context, pi, error_sink)
expected1 = [_mt("1001", 0, 2)]
expected2 = [_mt("1002", 0, 0), _ut(" ", 1, 1), _mt("1003", 2, 2)]
assert res == MultipleChoices([expected1, expected2])
assert not error_sink
def test_i_can_detect_multiple_choices_3(self, context, parser):
with NewOntology(context, "test_i_can_detect_multiple_choices_2"):
get_concepts(context, "one two", "one", "two", use_sheerka=True)
pi = get_parser_input("one two xxx one two")
error_sink = []
res = parser.parse(context, pi, error_sink)
e1 = get_from(_mt("c:one two#1001:"), _ut(" xxx "), _mt("c:#1001:"))
e2 = get_from(_mt("c:one#1002:"), _ut(" "), _mt("c:two#1003:"), _ut(" xxx "), _mt("c:one two#1001:"))
e3 = get_from(_mt("c:one two#1001:"), _ut(" xxx "), _mt("c:one#1002:"), _ut(" "), _mt("c:two#1003:"))
e4 = get_from(_mt("c:one#1002:"), _ut(" "), _mt("c:two#1003:"), _ut(" xxx "), _mt("c:#1002:"), _ut(" "),
_mt("c:#1003:"))
assert res == MultipleChoices([e1, e2, e3, e4])
assert not error_sink
def test_nothing_is_return_is_no_concept_is_recognized(self, context, parser):
pi = get_parser_input("one two three")
error_sink = []
res = parser.parse(context, pi, error_sink)
assert res == MultipleChoices([])
def test_i_can_manage_attribute_reference(self, context, parser):
with NewOntology(context, "test_i_can_detect_multiple_choices_2"):
get_concepts(context, "foo", "i am a concept", use_sheerka=True)
pi = get_parser_input("foo.attribute")
error_sink = []
res = parser.parse(context, pi, error_sink)
expected = [_mt("1001", 0, 0), _ut(".attribute", 1, 2)]
assert res == MultipleChoices([expected])
pi = get_parser_input("i am a concept.attribute")
res = parser.parse(context, pi, error_sink)
expected = [_mt("1002", 0, 6), _ut(".attribute", 7, 8)]
assert res == MultipleChoices([expected])
+84 -83
View File
@@ -3,91 +3,92 @@ import pytest
from base import BaseTest
from conftest import NewOntology, comparable_tokens
from evaluators.base_evaluator import MultipleChoices
from helpers import _mt, get_concept, get_concepts, get_parser_input
from helpers import get_concept, get_concepts, get_parser_input
from parsers.SyaConceptsParser import SyaConceptsParser
from parsers.tokenizer import Tokenizer
from tests.parsers.conftest import _mtsya
class TestSyaConceptsParser(BaseTest):
@pytest.fixture()
def parser(self):
return SyaConceptsParser()
@pytest.mark.parametrize("concept_key, expected_list", [
["a long token name", [("a long token name", 0)]],
["__var__0 __var__1 __var__2", [("", 3)]],
["__var__0 __var__1 prefixed", [(" prefixed", 2)]],
["suffixed __var__0 __var__1", [("suffixed ", 0), ["", 2]]],
["__var__0 __var__1 infixed __var__0 __var__1", [(" infixed ", 2), ["", 2]]],
["if __var__0 __var__1 then __var__2 end", [("if ", 0), (" then ", 2), (" end", 1)]]
])
def test_i_can_initialize_expected_parameters(self, parser, concept_key, expected_list):
resolved_expected_list = [(list(Tokenizer(source, yield_eof=False)), nb) for source, nb in expected_list]
actual = parser._get_expected_tokens(concept_key)
with comparable_tokens():
assert actual == resolved_expected_list
@pytest.mark.parametrize("concept", [
get_concept("a plus b", variables=["a", "b"]),
get_concept("add a b", variables=["a", "b"]),
get_concept("a b add", variables=["a", "b"]),
])
def test_i_can_parse_a_simple_case(self, context, parser, concept):
with NewOntology(context, "test_i_can_parse_a_simple_case"):
get_concepts(context, concept, use_sheerka=True)
pi = get_parser_input("1 plus 2")
error_sink = []
res = parser.parse(context, pi, error_sink)
expected = [_mt("1001", a="1 ", b=" 2")]
assert res == MultipleChoices([expected])
assert not error_sink
def test_i_can_parse_long_names_concept(self, context, parser):
with NewOntology(context, "test_i_can_parse_a_simple_case"):
get_concepts(context, get_concept("a long named concept b", variables=["a", "b"]), use_sheerka=True)
pi = get_parser_input("1 long named concept 2")
error_sink = []
res = parser.parse(context, pi, error_sink)
expected = [_mt("1001", a="1 ", b=" 2")]
assert res == MultipleChoices([expected])
assert not error_sink
def test_i_can_parse_sequence(self, context, parser):
with NewOntology(context, "test_i_can_parse_sequence"):
get_concepts(context, get_concept("a plus b", variables=["a", "b"]), use_sheerka=True)
pi = get_parser_input("1 plus 2 3 plus 7")
error_sink = []
res = parser.parse(context, pi, error_sink)
expected = [[_mt("1001", a="1 ", b=" 2")], [_mt("1001", a=" 3 ", b=" 7")]]
assert res == MultipleChoices(expected)
assert not error_sink
def test_not_enough_parameters(self, context, parser):
with NewOntology(context, "test_not_enough_parameters"):
get_concepts(context, get_concept("a plus b", variables=["a", "b"]), use_sheerka=True)
pi = get_parser_input("1 plus 2 3 plus 7")
error_sink = []
res = parser.parse(context, pi, error_sink)
expected = [[_mt("1001", a="1 ", b=" 2")], [_mt("1001", a=" 3 ", b=" 7")]]
assert res == MultipleChoices(expected)
assert not error_sink
def test_i_can_detect_when_name_does_not_match(self, context, parser):
with NewOntology(context, "test_i_can_detect_when_name_does_not_match"):
get_concepts(context, get_concept("a long named concept b", variables=["a", "b"]), use_sheerka=True)
pi = get_parser_input("1 long named mismatch 2")
error_sink = []
res = parser.parse(context, pi, error_sink)
assert error_sink
@pytest.fixture()
def parser(self):
return SyaConceptsParser()
@pytest.mark.parametrize("concept_key, expected_list", [
["a long token name", [("a long token name", 0)]],
["__var__0 __var__1 __var__2", [("", 3)]],
["__var__0 __var__1 prefixed", [(" prefixed", 2)]],
["suffixed __var__0 __var__1", [("suffixed ", 0), ["", 2]]],
["__var__0 __var__1 infixed __var__0 __var__1", [(" infixed ", 2), ["", 2]]],
["if __var__0 __var__1 then __var__2 end", [("if ", 0), (" then ", 2), (" end", 1)]]
])
def test_i_can_initialize_expected_parameters(self, parser, concept_key, expected_list):
resolved_expected_list = [(list(Tokenizer(source, yield_eof=False)), nb) for source, nb in expected_list]
actual = parser._get_expected_tokens(concept_key)
with comparable_tokens():
assert actual == resolved_expected_list
@pytest.mark.parametrize("concept, _input", [
(get_concept("a plus b", variables=["a", "b"]), "1 plus 2"),
(get_concept("add a b", variables=["a", "b"]), "add 1 2"),
(get_concept("a b add", variables=["a", "b"]), "1 2 add")
])
def test_i_can_parse_a_simple_case(self, context, parser, concept, _input):
with NewOntology(context, "test_i_can_parse_a_simple_case"):
get_concepts(context, concept, use_sheerka=True)
pi = get_parser_input(_input)
error_sink = []
res = parser.parse(context, pi, error_sink)
expected = [_mtsya("1001", a="1 ", b=" 2")]
assert res == MultipleChoices([expected])
assert not error_sink
def test_i_can_parse_long_names_concept(self, context, parser):
with NewOntology(context, "test_i_can_parse_a_simple_case"):
get_concepts(context, get_concept("a long named concept b", variables=["a", "b"]), use_sheerka=True)
pi = get_parser_input("1 long named concept 2")
error_sink = []
res = parser.parse(context, pi, error_sink)
expected = [_mtsya("1001", a="1 ", b=" 2")]
assert res == MultipleChoices([expected])
assert not error_sink
def test_i_can_parse_sequence(self, context, parser):
with NewOntology(context, "test_i_can_parse_sequence"):
get_concepts(context, get_concept("a plus b", variables=["a", "b"]), use_sheerka=True)
pi = get_parser_input("1 plus 2 3 plus 7")
error_sink = []
res = parser.parse(context, pi, error_sink)
expected = [[_mtsya("1001", a="1 ", b=" 2")], [_mtsya("1001", a=" 3 ", b=" 7")]]
assert res == MultipleChoices(expected)
assert not error_sink
def test_not_enough_parameters(self, context, parser):
with NewOntology(context, "test_not_enough_parameters"):
get_concepts(context, get_concept("a plus b", variables=["a", "b"]), use_sheerka=True)
pi = get_parser_input("1 plus ")
error_sink = []
res = parser.parse(context, pi, error_sink)
expected = [[_mtsya("1001", a="1 ", b=" 2")], [_mtsya("1001", a=" 3 ", b=" 7")]]
assert res == MultipleChoices(expected)
assert not error_sink
def test_i_can_detect_when_name_does_not_match(self, context, parser):
with NewOntology(context, "test_i_can_detect_when_name_does_not_match"):
get_concepts(context, get_concept("a long named concept b", variables=["a", "b"]), use_sheerka=True)
pi = get_parser_input("1 long named mismatch 2")
error_sink = []
res = parser.parse(context, pi, error_sink)
assert error_sink
+20 -20
View File
@@ -1,11 +1,11 @@
from unittest.mock import MagicMock, patch
from fastapi import HTTPException
from starlette import status
from client import SheerkaClient, parse_arguments
from mockserver import MockServer
# @pytest.mark.skip("too long")
class TestSheerkaClient:
def test_i_can_start_with_a_default_hostname(self):
parsed = parse_arguments([])
@@ -41,7 +41,11 @@ class TestSheerkaClient:
assert res.message == "Connection refused."
def test_i_can_manage_when_resource_is_not_found(self):
with MockServer([]):
mock_response = MagicMock()
mock_response.__bool__ = MagicMock(return_value=False)
mock_response.text = '{"detail":"Not Found"}'
with patch("requests.get", return_value=mock_response):
client = SheerkaClient("http://localhost", 5000)
res = client.check_url()
@@ -49,29 +53,25 @@ class TestSheerkaClient:
assert res.message == '{"detail":"Not Found"}'
def test_i_can_connect_to_a_server(self):
with MockServer([{
"path": "/",
"response": "Hello world"
}]):
mock_response = MagicMock()
mock_response.__bool__ = MagicMock(return_value=True)
mock_response.text = '"Hello world"'
with patch("requests.get", return_value=mock_response):
client = SheerkaClient("http://localhost", 5000)
res = client.check_url()
assert res.status
assert res.message == '"Hello world"'
def test_i_can_manage_when_authentication_fails(self):
with MockServer([{
"path": "/",
"response": "Hello world"
}, {
"method": "post",
"path": "/token",
"exception": HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Incorrect username or password",
headers={"WWW-Authenticate": "Bearer"},
)
}]):
mock_response = MagicMock()
mock_response.__bool__ = MagicMock(return_value=False)
mock_response.json.return_value = {"detail": "Incorrect username or password"}
with patch("requests.post", return_value=mock_response):
client = SheerkaClient("http://localhost", 5000)
res = client.connect("username", "wrong_password")
assert not res.status
assert res.message == 'Incorrect username or password'
assert res.message == "Incorrect username or password"
+226 -225
View File
@@ -2,279 +2,280 @@ import pytest
from common.global_symbols import NotInit
from core.concept import Concept, ConceptDefaultProps, ConceptMetadata, DefinitionType
from helpers import GetNextId, _mt, _ut, get_concept, get_concepts, get_evaluated_concept, get_from, get_metadata, \
get_metadatas
from helpers import GetNextId, get_concept, get_concepts, get_evaluated_concept, get_from, get_metadata, \
get_metadatas
from tests.parsers.conftest import _mt, _ut
def test_i_can_get_default_value_when_get_metadata():
metadata = get_metadata()
assert metadata.id is None
assert metadata.name is None
assert metadata.name is None
assert metadata.body is None
assert metadata.id is None
assert metadata.key is None
assert metadata.where is None
assert metadata.pre is None
assert metadata.post is None
assert metadata.ret is None
assert metadata.definition is None
assert metadata.definition_type == DefinitionType.DEFAULT
assert metadata.desc is None
assert metadata.props == {}
assert metadata.variables == tuple()
assert metadata.parameters == []
assert metadata.bound_body is None
assert metadata.is_builtin is False
assert metadata.is_unique is False
assert metadata.autouse is False
metadata = get_metadata()
assert metadata.id is None
assert metadata.name is None
assert metadata.name is None
assert metadata.body is None
assert metadata.id is None
assert metadata.key is None
assert metadata.where is None
assert metadata.pre is None
assert metadata.post is None
assert metadata.ret is None
assert metadata.definition is None
assert metadata.definition_type == DefinitionType.DEFAULT
assert metadata.desc is None
assert metadata.props == {}
assert metadata.variables == tuple()
assert metadata.parameters == []
assert metadata.bound_body is None
assert metadata.is_builtin is False
assert metadata.is_unique is False
assert metadata.autouse is False
def test_i_can_use_shortcut_to_declare_variables():
metadata = get_metadata(variables=(("var1", NotInit), ("var2", "value")))
assert metadata.variables == (("var1", NotInit), ("var2", "value")) # default behaviour
metadata = get_metadata(variables=[("var1", NotInit), ("var2", "value")])
assert metadata.variables == (("var1", NotInit), ("var2", "value")) # lists are transformed into tuples
metadata = get_metadata(variables=["var1", "var2"])
assert metadata.variables == (("var1", NotInit), ("var2", NotInit)) # expanded
metadata = get_metadata(variables=(("var1", NotInit), ("var2", "value")))
assert metadata.variables == (("var1", NotInit), ("var2", "value")) # default behaviour
metadata = get_metadata(variables=[("var1", NotInit), ("var2", "value")])
assert metadata.variables == (("var1", NotInit), ("var2", "value")) # lists are transformed into tuples
metadata = get_metadata(variables=["var1", "var2"])
assert metadata.variables == (("var1", NotInit), ("var2", NotInit)) # expanded
def test_i_can_clone():
metadata = ConceptMetadata(
"id",
"name",
"key",
True,
True,
"body",
"where",
"pre",
"post",
"ret",
"definition",
DefinitionType.BNF,
"desc",
True,
"bound_body",
{"prop": "value"},
(("variable", "value"),),
("p1",),
"digest",
("all_attr",),
)
clone = metadata.clone()
for attr, value in vars(metadata).items():
clone_value = getattr(clone, attr)
assert clone_value == value
metadata = ConceptMetadata(
"id",
"name",
"key",
True,
True,
"body",
"where",
"pre",
"post",
"ret",
"definition",
DefinitionType.BNF,
"desc",
True,
"bound_body",
{"prop": "value"},
(("variable", "value"),),
("p1",),
"digest",
("all_attr",),
)
clone = metadata.clone()
for attr, value in vars(metadata).items():
clone_value = getattr(clone, attr)
assert clone_value == value
def test_i_can_override_values_when_i_clone_metadata():
metadata = get_metadata()
assert metadata.clone(name="new_name").name == "new_name"
assert metadata.clone(body="new_body").body == "new_body"
assert metadata.clone(key="new_key").key == "new_key"
assert metadata.clone(where="new_where").where == "new_where"
assert metadata.clone(pre="new_pre").pre == "new_pre"
assert metadata.clone(post="new_post").post == "new_post"
assert metadata.clone(ret="new_ret").ret == "new_ret"
assert metadata.clone(definition="new_definition").definition == "new_definition"
assert metadata.clone(definition_type="new_definition_type").definition_type == "new_definition_type"
assert metadata.clone(desc="new_desc").desc == "new_desc"
assert metadata.clone(props="new_props").props == "new_props"
assert metadata.clone(variables="new_variables").variables == "new_variables"
assert metadata.clone(parameters="new_parameters").parameters == "new_parameters"
assert metadata.clone(bound_body="new_bound_body").bound_body == "new_bound_body"
assert metadata.clone(is_builtin="new_is_builtin").is_builtin == "new_is_builtin"
assert metadata.clone(is_unique="new_is_unique").is_unique == "new_is_unique"
assert metadata.clone(autouse="new_autouse").autouse == "new_autouse"
assert metadata.clone(digest="new_digest").digest == "new_digest"
assert metadata.clone(all_attrs="new_all_attrs").all_attrs == "new_all_attrs"
metadata = get_metadata()
assert metadata.clone(name="new_name").name == "new_name"
assert metadata.clone(body="new_body").body == "new_body"
assert metadata.clone(key="new_key").key == "new_key"
assert metadata.clone(where="new_where").where == "new_where"
assert metadata.clone(pre="new_pre").pre == "new_pre"
assert metadata.clone(post="new_post").post == "new_post"
assert metadata.clone(ret="new_ret").ret == "new_ret"
assert metadata.clone(definition="new_definition").definition == "new_definition"
assert metadata.clone(definition_type="new_definition_type").definition_type == "new_definition_type"
assert metadata.clone(desc="new_desc").desc == "new_desc"
assert metadata.clone(props="new_props").props == "new_props"
assert metadata.clone(variables="new_variables").variables == "new_variables"
assert metadata.clone(parameters="new_parameters").parameters == "new_parameters"
assert metadata.clone(bound_body="new_bound_body").bound_body == "new_bound_body"
assert metadata.clone(is_builtin="new_is_builtin").is_builtin == "new_is_builtin"
assert metadata.clone(is_unique="new_is_unique").is_unique == "new_is_unique"
assert metadata.clone(autouse="new_autouse").autouse == "new_autouse"
assert metadata.clone(digest="new_digest").digest == "new_digest"
assert metadata.clone(all_attrs="new_all_attrs").all_attrs == "new_all_attrs"
def test_i_cannot_change_the_id_when_cloning():
with pytest.raises(TypeError):
metadata = get_metadata()
metadata.clone(id="new_id")
with pytest.raises(TypeError):
metadata = get_metadata()
metadata.clone(id="new_id")
def test_i_can_auto_init():
next_id = GetNextId()
metadata = get_metadata("a plus b", body="a + b", variables=["a", "b"]).auto_init(next_id)
assert metadata.name == "a plus b"
assert metadata.id == "1001"
assert metadata.key == "__var__0 plus __var__1"
assert metadata.all_attrs == ('#where#', '#pre#', '#post#', '#body#', '#ret#', 'a', 'b')
assert metadata.is_unique is False
assert metadata.is_builtin is False
assert metadata.definition_type is DefinitionType.DEFAULT
assert metadata.digest == '9e058bc1261d1e2c785889147066ce89960fd6844db5bb6f1d1d809a8eb790b7'
next_id = GetNextId()
metadata = get_metadata("a plus b", body="a + b", variables=["a", "b"]).auto_init(next_id)
assert metadata.name == "a plus b"
assert metadata.id == "1001"
assert metadata.key == "__var__0 plus __var__1"
assert metadata.all_attrs == ('#where#', '#pre#', '#post#', '#body#', '#ret#', 'a', 'b')
assert metadata.is_unique is False
assert metadata.is_builtin is False
assert metadata.definition_type is DefinitionType.DEFAULT
assert metadata.digest == '9e058bc1261d1e2c785889147066ce89960fd6844db5bb6f1d1d809a8eb790b7'
def test_sequences_are_incremented_when_multiples_call():
next_id = GetNextId()
assert get_metadata("foo").auto_init(next_id).id == "1001"
assert get_metadata("bar").auto_init(next_id).id == "1002"
next_id = GetNextId()
assert get_metadata("foo").auto_init(next_id).id == "1001"
assert get_metadata("bar").auto_init(next_id).id == "1002"
def test_i_can_get_multiple_metadatas():
res = get_metadatas("foo", get_metadata("bar", body="body"))
assert len(res) == 2
metadata = res[0]
assert isinstance(metadata, ConceptMetadata)
assert metadata.name == "foo"
assert metadata.body is None
assert metadata.key is None
assert metadata.id is None
metadata = res[1]
assert isinstance(metadata, ConceptMetadata)
assert metadata.name == "bar"
assert metadata.body == "body"
assert metadata.key is None
assert metadata.id is None
res = get_metadatas("foo", get_metadata("bar", body="body"))
assert len(res) == 2
metadata = res[0]
assert isinstance(metadata, ConceptMetadata)
assert metadata.name == "foo"
assert metadata.body is None
assert metadata.key is None
assert metadata.id is None
metadata = res[1]
assert isinstance(metadata, ConceptMetadata)
assert metadata.name == "bar"
assert metadata.body == "body"
assert metadata.key is None
assert metadata.id is None
def test_i_can_get_multiple_already_initialized_metadatas():
res = get_metadatas("foo", get_metadata("bar", body="body"), next_id=GetNextId())
assert len(res) == 2
metadata = res[0]
assert isinstance(metadata, ConceptMetadata)
assert metadata.name == "foo"
assert metadata.body is None
assert metadata.key == "foo"
assert metadata.id == "1001"
metadata = res[1]
assert isinstance(metadata, ConceptMetadata)
assert metadata.name == "bar"
assert metadata.body == "body"
assert metadata.key == "bar"
assert metadata.id == "1002"
res = get_metadatas("foo", get_metadata("bar", body="body"), next_id=GetNextId())
assert len(res) == 2
metadata = res[0]
assert isinstance(metadata, ConceptMetadata)
assert metadata.name == "foo"
assert metadata.body is None
assert metadata.key == "foo"
assert metadata.id == "1001"
metadata = res[1]
assert isinstance(metadata, ConceptMetadata)
assert metadata.name == "bar"
assert metadata.body == "body"
assert metadata.key == "bar"
assert metadata.id == "1002"
def test_i_can_get_a_concept():
foo = get_concept("foo", variables=("var1",))
assert isinstance(foo, Concept)
assert foo.name == "foo"
assert foo.key is None
assert foo.id is None
assert foo.all_attrs() == ('#where#', '#pre#', '#post#', '#body#', '#ret#', 'var1')
foo = get_concept("foo", variables=("var1",))
assert isinstance(foo, Concept)
assert foo.name == "foo"
assert foo.key is None
assert foo.id is None
assert foo.all_attrs() == ('#where#', '#pre#', '#post#', '#body#', '#ret#', 'var1')
def test_i_can_request_basic_initialization_when_getting_a_concept():
next_id = GetNextId()
foo = get_concept("foo", variables=("var1",), sequence=next_id)
assert foo.name == "foo"
assert foo.key == "foo"
assert foo.id == "1001"
assert foo.all_attrs() == ('#where#', '#pre#', '#post#', '#body#', '#ret#', 'var1')
next_id = GetNextId()
foo = get_concept("foo", variables=("var1",), sequence=next_id)
assert foo.name == "foo"
assert foo.key == "foo"
assert foo.id == "1001"
assert foo.all_attrs() == ('#where#', '#pre#', '#post#', '#body#', '#ret#', 'var1')
def test_i_can_get_multiple_concepts(context):
next_id = GetNextId()
foo, bar, baz = get_concepts(context,
"foo",
"bar",
get_concept("baz", definition="baz var1", variables=("var1",)),
sequence=next_id)
assert foo.name == "foo"
assert foo.id == "1001"
assert foo.key == "foo"
assert bar.name == "bar"
assert bar.id == "1002"
assert bar.key == "bar"
assert baz.name == "baz"
assert baz.id == "1003"
assert baz.key == "baz __var__0"
next_id = GetNextId()
foo, bar, baz = get_concepts(context,
"foo",
"bar",
get_concept("baz", definition="baz var1", variables=("var1",)),
sequence=next_id)
assert foo.name == "foo"
assert foo.id == "1001"
assert foo.key == "foo"
assert bar.name == "bar"
assert bar.id == "1002"
assert bar.key == "bar"
assert baz.name == "baz"
assert baz.id == "1003"
assert baz.key == "baz __var__0"
def test_i_can_get_multiple_concepts_using_sheerka(sheerka, context):
foo, bar, baz = get_concepts(context,
"foo",
"bar",
get_concept("baz", definition="baz var1", variables=("var1",)),
use_sheerka=True)
assert foo.name == "foo"
assert foo.id == "1001"
assert foo.key == "foo"
assert bar.name == "bar"
assert bar.id == "1002"
assert bar.key == "bar"
assert baz.name == "baz"
assert baz.id == "1003"
assert baz.key == "baz __var__0"
assert baz.get_value("var1") is NotInit
# the concepts are defined in Sheerka, so we can instantiate them
baz2 = sheerka.newn("baz", var1="value for var1")
assert baz2.name == "baz"
assert baz2.id == "1003"
assert baz2.key == "baz __var__0"
assert baz2.get_value("var1") == "value for var1"
foo, bar, baz = get_concepts(context,
"foo",
"bar",
get_concept("baz", definition="baz var1", variables=("var1",)),
use_sheerka=True)
assert foo.name == "foo"
assert foo.id == "1001"
assert foo.key == "foo"
assert bar.name == "bar"
assert bar.id == "1002"
assert bar.key == "bar"
assert baz.name == "baz"
assert baz.id == "1003"
assert baz.key == "baz __var__0"
assert baz.get_value("var1") is NotInit
# the concepts are defined in Sheerka, so we can instantiate them
baz2 = sheerka.newn("baz", var1="value for var1")
assert baz2.name == "baz"
assert baz2.id == "1003"
assert baz2.key == "baz __var__0"
assert baz2.get_value("var1") == "value for var1"
def test_i_can_get_multiple_concepts_when_same_name(sheerka, context):
one_str, one_int = get_concepts(context,
get_metadata("one", body="'one'"),
get_metadata("one", body="1"),
use_sheerka=True)
assert sheerka.isinstance(one_str, "one")
assert sheerka.isinstance(one_int, "one")
one_str, one_int = get_concepts(context,
get_metadata("one", body="'one'"),
get_metadata("one", body="1"),
use_sheerka=True)
assert sheerka.isinstance(one_str, "one")
assert sheerka.isinstance(one_int, "one")
def test_i_can_create_test_concept():
concept = get_concept("one", body="'one'")
test_concept = get_evaluated_concept(concept, body='hello', a="value for a")
assert test_concept.get_metadata() == concept.get_metadata()
assert test_concept.get_value(ConceptDefaultProps.BODY) == "hello"
assert test_concept.get_value("a") == "value for a"
concept = get_concept("one", body="'one'")
test_concept = get_evaluated_concept(concept, body='hello', a="value for a")
assert test_concept.get_metadata() == concept.get_metadata()
assert test_concept.get_value(ConceptDefaultProps.BODY) == "hello"
assert test_concept.get_value("a") == "value for a"
def test_i_can_dummy_evaluate_concept():
concept = get_concept("one", body="'one'", where="True", pre="False", ret="1", post="1.0")
evaluated = get_evaluated_concept(concept)
assert evaluated.get_value(ConceptDefaultProps.WHERE) is True
assert evaluated.get_value(ConceptDefaultProps.PRE) is False
assert evaluated.get_value(ConceptDefaultProps.BODY) == "one"
assert evaluated.get_value(ConceptDefaultProps.RET) == 1
assert evaluated.get_value(ConceptDefaultProps.POST) == 1.0
concept = get_concept("one", body='"one"', ret="'a value'")
evaluated = get_evaluated_concept(concept, ret='forced value')
assert evaluated.get_value(ConceptDefaultProps.WHERE) == NotInit
assert evaluated.get_value(ConceptDefaultProps.PRE) == NotInit
assert evaluated.get_value(ConceptDefaultProps.BODY) == "one"
assert evaluated.get_value(ConceptDefaultProps.RET) == "forced value"
assert evaluated.get_value(ConceptDefaultProps.POST) == NotInit
concept = get_concept("one", body="'one'", where="True", pre="False", ret="1", post="1.0")
evaluated = get_evaluated_concept(concept)
assert evaluated.get_value(ConceptDefaultProps.WHERE) is True
assert evaluated.get_value(ConceptDefaultProps.PRE) is False
assert evaluated.get_value(ConceptDefaultProps.BODY) == "one"
assert evaluated.get_value(ConceptDefaultProps.RET) == 1
assert evaluated.get_value(ConceptDefaultProps.POST) == 1.0
concept = get_concept("one", body='"one"', ret="'a value'")
evaluated = get_evaluated_concept(concept, ret='forced value')
assert evaluated.get_value(ConceptDefaultProps.WHERE) == NotInit
assert evaluated.get_value(ConceptDefaultProps.PRE) == NotInit
assert evaluated.get_value(ConceptDefaultProps.BODY) == "one"
assert evaluated.get_value(ConceptDefaultProps.RET) == "forced value"
assert evaluated.get_value(ConceptDefaultProps.POST) == NotInit
def test_i_can_get_from():
res = get_from(_mt("c:i am a concept#1001:"))
assert res == [_mt("1001", 0, 6)]
res = get_from(_ut("some unrecognized stuff"))
assert res == [_ut("some unrecognized stuff", 0, 4)]
res = get_from(_mt("c:i am a concept#1001:"), _ut("some unrecognized stuff"))
assert res == [_mt("1001", 0, 6), _ut("some unrecognized stuff", 7, 11)]
res = get_from(_mt("c:i am a concept#1001:"), _ut("some unrecognized stuff"), parser="other")
assert res == [_mt("1001", 0, 6, parser="other"), _ut("some unrecognized stuff", 7, 11)]
res = get_from(_mt("c:i am a concept#1001:"), _mt("c:#1001:"))
assert res == [_mt("1001", 0, 6), _mt("1001", 7, 13)]
res = get_from(_mt("c:i am a concept#1001:"))
assert res == [_mt("1001", 0, 6)]
res = get_from(_ut("some unrecognized stuff"))
assert res == [_ut("some unrecognized stuff", 0, 4)]
res = get_from(_mt("c:i am a concept#1001:"), _ut("some unrecognized stuff"))
assert res == [_mt("1001", 0, 6), _ut("some unrecognized stuff", 7, 11)]
res = get_from(_mt("c:i am a concept#1001:"), _ut("some unrecognized stuff"), parser="other")
assert res == [_mt("1001", 0, 6, parser="other"), _ut("some unrecognized stuff", 7, 11)]
res = get_from(_mt("c:i am a concept#1001:"), _mt("c:#1001:"))
assert res == [_mt("1001", 0, 6), _mt("1001", 7, 13)]