First implementation of Debugger for SyaNodeParser
This commit is contained in:
@@ -7,59 +7,59 @@ class TestSheerkaAdmin(TestUsingMemoryBasedSheerka):
|
||||
def test_i_can_get_last_ret(self):
|
||||
pass
|
||||
|
||||
def test_i_can_get_last_error_ret(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
|
||||
# nothing in history
|
||||
last_error_ret = sheerka.last_error_ret(context)
|
||||
assert sheerka.isinstance(last_error_ret, BuiltinConcepts.RETURN_VALUE)
|
||||
assert not last_error_ret.status
|
||||
assert sheerka.isinstance(last_error_ret.body, BuiltinConcepts.NOT_FOUND)
|
||||
|
||||
# only success in history
|
||||
r_success = sheerka.ret("Test", True, "success")
|
||||
sheerka.last_return_values.append([r_success])
|
||||
last_error_ret = sheerka.last_error_ret(context)
|
||||
assert sheerka.isinstance(last_error_ret, BuiltinConcepts.RETURN_VALUE)
|
||||
assert not last_error_ret.status
|
||||
assert sheerka.isinstance(last_error_ret.body, BuiltinConcepts.NOT_FOUND)
|
||||
|
||||
# at least on error
|
||||
r_failure = sheerka.ret("Test", False, "failure")
|
||||
sheerka.last_return_values.append([r_failure])
|
||||
assert sheerka.last_error_ret(context) == r_failure
|
||||
|
||||
# add another success and make sure we get the same error
|
||||
sheerka.last_return_values.append([r_success])
|
||||
assert sheerka.last_error_ret(context) == r_failure
|
||||
|
||||
# and I only get the last failure
|
||||
r_failure2 = sheerka.ret("Test", False, "another failure")
|
||||
sheerka.last_return_values.append([r_failure2])
|
||||
assert sheerka.last_error_ret(context) == r_failure2
|
||||
|
||||
# but I still can get the previous error
|
||||
assert sheerka.last_error_ret(context, -2) == r_failure
|
||||
|
||||
def test_i_can_get_last_error_ret_when_only_one_ret_has_failed(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
|
||||
r_success = sheerka.ret("Test", True, "success")
|
||||
r_failure = sheerka.ret("Test", False, "False1")
|
||||
|
||||
sheerka.last_return_values.append([r_success, r_failure])
|
||||
assert sheerka.last_error_ret(context) == r_failure
|
||||
|
||||
def test_i_cannot_get_last_error_ret_when_too_many_errors(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
|
||||
r1 = sheerka.ret("Test", True, "success")
|
||||
r2 = sheerka.ret("Test", False, "False1")
|
||||
r3 = sheerka.ret("Test", False, "False2")
|
||||
|
||||
sheerka.last_return_values.append([r1, r2, r3])
|
||||
last_error_ret = sheerka.last_error_ret(context)
|
||||
assert sheerka.isinstance(last_error_ret, BuiltinConcepts.RETURN_VALUE)
|
||||
assert not last_error_ret.status
|
||||
assert sheerka.isinstance(last_error_ret.body, BuiltinConcepts.TOO_MANY_ERRORS)
|
||||
assert last_error_ret.body.body == [r2, r3]
|
||||
# def test_i_can_get_last_error_ret(self):
|
||||
# sheerka, context = self.init_concepts()
|
||||
#
|
||||
# # nothing in history
|
||||
# last_error_ret = sheerka.last_error_ret(context)
|
||||
# assert sheerka.isinstance(last_error_ret, BuiltinConcepts.RETURN_VALUE)
|
||||
# assert not last_error_ret.status
|
||||
# assert sheerka.isinstance(last_error_ret.body, BuiltinConcepts.NOT_FOUND)
|
||||
#
|
||||
# # only success in history
|
||||
# r_success = sheerka.ret("Test", True, "success")
|
||||
# sheerka.last_return_values.append([r_success])
|
||||
# last_error_ret = sheerka.last_error_ret(context)
|
||||
# assert sheerka.isinstance(last_error_ret, BuiltinConcepts.RETURN_VALUE)
|
||||
# assert not last_error_ret.status
|
||||
# assert sheerka.isinstance(last_error_ret.body, BuiltinConcepts.NOT_FOUND)
|
||||
#
|
||||
# # at least on error
|
||||
# r_failure = sheerka.ret("Test", False, "failure")
|
||||
# sheerka.last_return_values.append([r_failure])
|
||||
# assert sheerka.last_error_ret(context) == r_failure
|
||||
#
|
||||
# # add another success and make sure we get the same error
|
||||
# sheerka.last_return_values.append([r_success])
|
||||
# assert sheerka.last_error_ret(context) == r_failure
|
||||
#
|
||||
# # and I only get the last failure
|
||||
# r_failure2 = sheerka.ret("Test", False, "another failure")
|
||||
# sheerka.last_return_values.append([r_failure2])
|
||||
# assert sheerka.last_error_ret(context) == r_failure2
|
||||
#
|
||||
# # but I still can get the previous error
|
||||
# assert sheerka.last_error_ret(context, -2) == r_failure
|
||||
#
|
||||
# def test_i_can_get_last_error_ret_when_only_one_ret_has_failed(self):
|
||||
# sheerka, context = self.init_concepts()
|
||||
#
|
||||
# r_success = sheerka.ret("Test", True, "success")
|
||||
# r_failure = sheerka.ret("Test", False, "False1")
|
||||
#
|
||||
# sheerka.last_return_values.append([r_success, r_failure])
|
||||
# assert sheerka.last_error_ret(context) == r_failure
|
||||
#
|
||||
# def test_i_cannot_get_last_error_ret_when_too_many_errors(self):
|
||||
# sheerka, context = self.init_concepts()
|
||||
#
|
||||
# r1 = sheerka.ret("Test", True, "success")
|
||||
# r2 = sheerka.ret("Test", False, "False1")
|
||||
# r3 = sheerka.ret("Test", False, "False2")
|
||||
#
|
||||
# sheerka.last_return_values.append([r1, r2, r3])
|
||||
# last_error_ret = sheerka.last_error_ret(context)
|
||||
# assert sheerka.isinstance(last_error_ret, BuiltinConcepts.RETURN_VALUE)
|
||||
# assert not last_error_ret.status
|
||||
# assert sheerka.isinstance(last_error_ret.body, BuiltinConcepts.TOO_MANY_ERRORS)
|
||||
# assert last_error_ret.body.body == [r2, r3]
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import pytest
|
||||
from core.builtin_concepts import BuiltinConcepts
|
||||
from core.concept import Concept
|
||||
from core.global_symbols import CONCEPT_PRECEDENCE_MODIFIED, CONCEPT_COMPARISON_CONTEXT, RULE_PRECEDENCE_MODIFIED, \
|
||||
from core.global_symbols import EVENT_CONCEPT_PRECEDENCE_MODIFIED, CONCEPT_COMPARISON_CONTEXT, EVENT_RULE_PRECEDENCE_MODIFIED, \
|
||||
RULE_COMPARISON_CONTEXT
|
||||
from core.sheerka.services.SheerkaComparisonManager import SheerkaComparisonManager, ComparisonObj
|
||||
|
||||
@@ -446,7 +446,7 @@ class TestSheerkaGreaterThanManager(TestUsingMemoryBasedSheerka):
|
||||
nonlocal event_received
|
||||
event_received = True
|
||||
|
||||
sheerka.subscribe(CONCEPT_PRECEDENCE_MODIFIED, receive_event)
|
||||
sheerka.subscribe(EVENT_CONCEPT_PRECEDENCE_MODIFIED, receive_event)
|
||||
|
||||
sheerka.set_is_greater_than(context, foo, one, two)
|
||||
assert not event_received
|
||||
@@ -471,7 +471,7 @@ class TestSheerkaGreaterThanManager(TestUsingMemoryBasedSheerka):
|
||||
nonlocal event_received
|
||||
event_received = True
|
||||
|
||||
sheerka.subscribe(RULE_PRECEDENCE_MODIFIED, receive_event)
|
||||
sheerka.subscribe(EVENT_RULE_PRECEDENCE_MODIFIED, receive_event)
|
||||
|
||||
sheerka.set_is_greater_than(context, foo, r1, r2)
|
||||
assert not event_received
|
||||
|
||||
@@ -1,12 +1,23 @@
|
||||
import pytest
|
||||
from core.builtin_concepts import BuiltinConcepts
|
||||
from core.concept import Concept, NotInit
|
||||
from core.sheerka.ExecutionContext import ExecutionContext
|
||||
from core.sheerka.services.SheerkaDebugManager import SheerkaDebugManager, DebugItem
|
||||
from core.sheerka.services.SheerkaDebugManager import SheerkaDebugManager, DebugItem, ConceptDebugObj
|
||||
from parsers.PythonParser import PythonNode
|
||||
from sdp.sheerkaDataProvider import Event
|
||||
|
||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||
|
||||
|
||||
class DummyObj:
|
||||
def __init__(self, a, b):
|
||||
self.a = a
|
||||
self.b = b
|
||||
|
||||
def __repr__(self):
|
||||
return f"DummyObj(a={self.a}, b={self.b})"
|
||||
|
||||
|
||||
class TestSheerkaDebugManager(TestUsingMemoryBasedSheerka):
|
||||
|
||||
def test_i_can_activate_debug(self):
|
||||
@@ -478,12 +489,85 @@ class TestSheerkaDebugManager(TestUsingMemoryBasedSheerka):
|
||||
assert len(service.debug_rules_settings) == 0
|
||||
assert len(service.debug_concepts_settings) == 0
|
||||
|
||||
@pytest.mark.parametrize("settings, expected", [
|
||||
({"service": "my_service", "item": "var_name"}, {"var_name"}),
|
||||
({"method": "my_method", "item": "var_name"}, {"var_name"}),
|
||||
({"debug_id": 0, "item": "var_name"}, {"var_name"}),
|
||||
({"service": "my_service", "item": "*"}, {"*"}),
|
||||
({"method": "my_method", "item": "*"}, {"*"}),
|
||||
({"debug_id": 0, "item": "*"}, {"*"}),
|
||||
({"service": "my_service"}, set()),
|
||||
({"method": "my_method"}, set()),
|
||||
({"debug_id": 0}, set()),
|
||||
])
|
||||
def test_i_can_get_enabled_items(self, settings, expected):
|
||||
sheerka, context = self.init_concepts()
|
||||
service = sheerka.services[SheerkaDebugManager.NAME]
|
||||
service.set_debug(context, True)
|
||||
|
||||
service.add_or_update_debug_item(context, "vars", **settings)
|
||||
|
||||
assert service.get_enabled_items("vars", context, "my_service", "my_method", 0) == expected
|
||||
|
||||
def test_i_can_get_enabled_items_for_context(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
another_context = context.push(BuiltinConcepts.TESTING, None)
|
||||
service = sheerka.services[SheerkaDebugManager.NAME]
|
||||
service.set_debug(context, True)
|
||||
|
||||
service.add_or_update_debug_item(context, "rules", context_id=context.id, item="item", enabled=True)
|
||||
|
||||
assert service.get_enabled_items("rules", context, "my_service", "my_method", 10) == {"item"}
|
||||
assert service.get_enabled_items("rules", another_context, "my_service", "my_method", 10) == set()
|
||||
|
||||
def test_i_can_get_enabled_items_for_sub_context(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
sub_context = context.push(BuiltinConcepts.TESTING, None)
|
||||
another_context = self.get_context(sheerka)
|
||||
service = sheerka.services[SheerkaDebugManager.NAME]
|
||||
service.set_debug(context, True)
|
||||
|
||||
service.add_or_update_debug_item(context, "rules", context_id=context.id, item="item", context_children=True)
|
||||
|
||||
assert service.get_enabled_items("rules", context, "my_service", "my_method", 10) == {"item"}
|
||||
assert service.get_enabled_items("rules", sub_context, "my_service", "my_method", 10) == {"item"}
|
||||
assert service.get_enabled_items("rules", another_context, "my_service", "my_method", 10) == set()
|
||||
|
||||
def test_i_can_get_all_enabled_items(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
service = sheerka.services[SheerkaDebugManager.NAME]
|
||||
service.set_debug(context, True)
|
||||
|
||||
service.add_or_update_debug_item(context, "vars", service="s1", item="v11")
|
||||
service.add_or_update_debug_item(context, "vars", service="s2", item="v21")
|
||||
service.add_or_update_debug_item(context, "vars", method="m1", item="v12")
|
||||
service.add_or_update_debug_item(context, "vars", method="m2", item="v22")
|
||||
service.add_or_update_debug_item(context, "vars", debug_id=1, item="v13")
|
||||
service.add_or_update_debug_item(context, "vars", debug_id=2, item="v23")
|
||||
service.add_or_update_debug_item(context, "vars", service="s1", method="m1", item="v111")
|
||||
|
||||
assert service.get_enabled_items("vars", context, "s1", "m1", 1) == {"v11", "v12", "v13", "v111"}
|
||||
|
||||
def test_i_can_manage_duplicates_when_get_enabled_items(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
service = sheerka.services[SheerkaDebugManager.NAME]
|
||||
service.set_debug(context, True)
|
||||
|
||||
service.add_or_update_debug_item(context, "vars", service="s1", item="var_name")
|
||||
service.add_or_update_debug_item(context, "vars", method="m1", item="*")
|
||||
service.add_or_update_debug_item(context, "vars", debug_id=1, item="var_name")
|
||||
service.add_or_update_debug_item(context, "vars", service="s1", method="m1", item="*")
|
||||
|
||||
assert service.get_enabled_items("vars", context, "s1", "m1", 1) == {"var_name", "*"}
|
||||
|
||||
@pytest.mark.parametrize("args, kwargs, expected", [
|
||||
(["my_service.my_method.my_var"], {}, ("my_var", "my_service", "my_method", None, False, None, True)),
|
||||
(["*.*.my_var"], {}, ("my_var", None, None, None, False, None, True)),
|
||||
(["my_service"], {}, (None, "my_service", None, None, False, None, True)),
|
||||
(["my_service.my_method"], {}, (None, "my_service", "my_method", None, False, None, True)),
|
||||
(["*.*.*"], {}, ("*", None, None, None, False, None, True)),
|
||||
(["*.*.*.*.*"], {}, ("*.*.*", None, None, None, False, None, True)),
|
||||
(["s.m.var.in.multi.parts"], {}, ("var.in.multi.parts", "s", "m", None, False, None, True)),
|
||||
([1], {}, ("1", None, None, None, False, None, True)),
|
||||
(["", 1], {}, (None, None, None, 1, False, None, True)),
|
||||
([None, 1], {}, (None, None, None, 1, False, None, True)),
|
||||
@@ -566,3 +650,265 @@ class TestSheerkaDebugManager(TestUsingMemoryBasedSheerka):
|
||||
DebugItem('1', None, None, None, False, None, False, True)]
|
||||
assert another_service.debug_concepts_settings == [
|
||||
DebugItem('1001', None, None, None, False, None, False, True)]
|
||||
|
||||
def test_i_can_inspect_concept_all_attributes(self):
|
||||
sheerka, context, foo = self.init_concepts("foo")
|
||||
foo.values() # freeze known attributes
|
||||
foo.set_value("new_var", "var_value")
|
||||
|
||||
res = sheerka.inspect(context, foo)
|
||||
assert res.body == {"#type#": "Concept",
|
||||
"id": foo.id,
|
||||
"name": foo.name,
|
||||
"key": foo.key,
|
||||
"value.new_var": "'var_value'"}
|
||||
|
||||
def test_i_can_inspect_concept_specified_attributes(self):
|
||||
sheerka, context, foo = self.init_concepts("foo")
|
||||
foo.values() # freeze known attributes
|
||||
foo.set_value("new_var", "var_value")
|
||||
|
||||
res = sheerka.inspect(context, foo, "id", "value.new_var")
|
||||
assert res.body == {"id": foo.id, "value.new_var": "'var_value'"}
|
||||
|
||||
def test_i_can_inspect_concept_specified_attributes_using_short_name(self):
|
||||
sheerka, context, foo, bar = self.init_concepts(Concept("foo").def_var("var_name", "default_value"), "bar")
|
||||
foo.set_value("var_name", "var_value")
|
||||
foo.get_compiled()["var_name"] = bar
|
||||
|
||||
res = sheerka.inspect(context, foo, "id", "var_name")
|
||||
assert res.body == {"id": foo.id,
|
||||
"meta.var_name": "'default_value'",
|
||||
"compiled.var_name": bar,
|
||||
"value.var_name": "'var_value'"}
|
||||
|
||||
def test_i_can_inspect_object_all_attributes(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
python_node = PythonNode("one + 1").init_ast()
|
||||
|
||||
res = sheerka.inspect(context, python_node)
|
||||
assert set(res.body.keys()) == {"#type#", 'ast_', 'ast_str', 'compiled', 'objects', 'source'}
|
||||
|
||||
def test_i_can_inspect_object_specified_attributes(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
python_node = PythonNode("one + 1").init_ast()
|
||||
|
||||
res = sheerka.inspect(context, python_node, "#type#", "source", "ast_str")
|
||||
assert res.body == {
|
||||
"#type#": "PythonNode",
|
||||
'ast_str': "Expression(body=BinOp(left=Name(id='one'), op=Add(), right=Constant(value=1)))",
|
||||
'source': 'one + 1'}
|
||||
|
||||
def test_i_can_inspect_object_with_as_bag_all_attributes(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
|
||||
res = sheerka.inspect(context, context)
|
||||
assert res.body == {'#type#': 'ExecutionContext',
|
||||
'_children': [],
|
||||
'action': '__TESTING',
|
||||
'concepts': None,
|
||||
'context': None,
|
||||
'desc': None,
|
||||
'digest': 'xxx',
|
||||
'elapsed': 0,
|
||||
'elapsed_str': '0.0 ms',
|
||||
'id': context.id,
|
||||
'inputs': {},
|
||||
'obj': None,
|
||||
'status': None,
|
||||
'values': {},
|
||||
'who': 'test'}
|
||||
|
||||
def test_i_can_inspect_object_with_as_bag_specified_attributes(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
|
||||
res = sheerka.inspect(context, context, "who", "_children")
|
||||
assert res.body == {'_children': [],
|
||||
'who': 'test'}
|
||||
|
||||
def test_i_can_inspect_object_with_concept(self):
|
||||
sheerka, context, foo = self.init_concepts("foo")
|
||||
foo.values() # freeze known attributes
|
||||
sheerka.set_attr(foo, "new_var", "var_value")
|
||||
|
||||
dummy = DummyObj(foo, "value")
|
||||
res = sheerka.inspect(context, dummy)
|
||||
assert res.body == {'#type#': 'DummyObj', 'a': foo, 'b': 'value'}
|
||||
|
||||
def test_i_can_inspect_object_with_concept_when_as_bag(self):
|
||||
sheerka, context, foo = self.init_concepts("foo")
|
||||
foo.values() # freeze known attributes
|
||||
sheerka.set_attr(foo, "new_var", "var_value")
|
||||
|
||||
dummy = DummyObj(foo, "value")
|
||||
res = sheerka.inspect(context, dummy, as_bag=True)
|
||||
assert res.body == {'#type#': 'DummyObj',
|
||||
'a': {'#type#': 'Concept',
|
||||
'id': '1001',
|
||||
'key': 'foo',
|
||||
'name': 'foo',
|
||||
'value.new_var': "'var_value'"},
|
||||
'b': 'value'}
|
||||
|
||||
def test_i_can_inspect_object_with_concept_when_values(self):
|
||||
sheerka, context, foo = self.init_concepts("foo")
|
||||
foo.values() # freeze known attributes
|
||||
sheerka.set_attr(foo, "new_var", "var_value")
|
||||
|
||||
dummy = DummyObj(foo, "value")
|
||||
res = sheerka.inspect(context, dummy, values=True)
|
||||
assert res.body == {'#type#': 'DummyObj', 'a': ConceptDebugObj(foo), 'b': 'value'}
|
||||
|
||||
def test_i_can_inspect_concept_with_concept(self):
|
||||
sheerka, context, foo, bar = self.init_concepts(Concept("foo").def_var("var_name"), "bar")
|
||||
foo.set_value("var_name", bar)
|
||||
|
||||
res = sheerka.inspect(context, foo)
|
||||
assert res.body == {'#type#': 'Concept',
|
||||
'id': '1001',
|
||||
'key': 'foo',
|
||||
'name': 'foo',
|
||||
'value.var_name': bar}
|
||||
|
||||
def test_i_can_inspect_concept_with_concept_when_as_bag(self):
|
||||
sheerka, context, foo, bar = self.init_concepts(Concept("foo").def_var("var_name"), "bar")
|
||||
foo.set_value("var_name", bar)
|
||||
|
||||
res = sheerka.inspect(context, foo, as_bag=True)
|
||||
assert res.body == {'#type#': 'Concept',
|
||||
'id': '1001',
|
||||
'key': 'foo',
|
||||
'name': 'foo',
|
||||
'value.var_name': {'#type#': 'Concept',
|
||||
'id': '1002',
|
||||
'key': 'bar',
|
||||
'name': 'bar'}}
|
||||
|
||||
def test_i_can_inspect_concept_with_concept_when_values(self):
|
||||
sheerka, context, foo, bar = self.init_concepts(Concept("foo").def_var("var_name"), "bar")
|
||||
foo.set_value("var_name", bar)
|
||||
|
||||
res = sheerka.inspect(context, foo, values=True)
|
||||
assert res.body == {'#type#': 'Concept',
|
||||
'id': '1001',
|
||||
'key': 'foo',
|
||||
'name': 'foo',
|
||||
'value.var_name': ConceptDebugObj(bar)}
|
||||
|
||||
def test_i_can_inspect_execution_context_item(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
ExecutionContext.ids.clear()
|
||||
|
||||
sheerka.evaluate_user_input("def concept one as 1")
|
||||
results = list(sheerka.get_last_results(context).body)
|
||||
user_input_ret_val = results[0].inputs["user_input"]
|
||||
return_values = results[0].values["return_values"]
|
||||
|
||||
res = sheerka.inspect(context, 0)
|
||||
assert res.body == {'inputs': {'user_input': user_input_ret_val},
|
||||
'values.return_values': return_values}
|
||||
|
||||
def test_i_can_inspect_execution_context_values(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
ExecutionContext.ids.clear()
|
||||
|
||||
sheerka.evaluate_user_input("def concept one as 1")
|
||||
results = list(sheerka.get_last_results(context).body)
|
||||
user_input_ret_val = results[0].inputs["user_input"]
|
||||
return_values = results[0].values["return_values"]
|
||||
|
||||
res = sheerka.inspect(context, 0, values=True)
|
||||
|
||||
assert res.body == {'inputs': {'user_input': user_input_ret_val},
|
||||
'values.return_values': [ConceptDebugObj(return_values[0].body.body)]}
|
||||
|
||||
def test_i_can_inspect_when_a_property_does_not_exist(self):
|
||||
sheerka, context, foo = self.init_concepts("foo")
|
||||
foo.values() # freeze known attributes
|
||||
sheerka.set_attr(foo, "new_var", "var_value")
|
||||
|
||||
dummy = DummyObj(foo, "value")
|
||||
res = sheerka.inspect(context, dummy, "#type#", "fake", "a", "b")
|
||||
assert res.body == {'#type#': 'DummyObj',
|
||||
'fake': "** Not Found **",
|
||||
'a': foo,
|
||||
'b': 'value'}
|
||||
|
||||
def test_i_can_inspect_when_properties_are_specified_several_times(self):
|
||||
sheerka, context, foo = self.init_concepts("foo")
|
||||
foo.values() # freeze known attributes
|
||||
sheerka.set_attr(foo, "new_var", "var_value")
|
||||
|
||||
dummy = DummyObj(foo, "value")
|
||||
res = sheerka.inspect(context, dummy, "#type#", "a", "b", "a")
|
||||
assert res.body == {'#type#': 'DummyObj',
|
||||
'a': foo,
|
||||
'b': 'value'}
|
||||
|
||||
def test_i_cannot_inspect_execution_context_item_if_no_last_item(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
|
||||
res = sheerka.inspect(context, 0)
|
||||
|
||||
assert res.body == {'#type#': 'NotFound',
|
||||
'id': '70',
|
||||
'key': '__NOT_FOUND',
|
||||
'name': '__NOT_FOUND',
|
||||
'body': 'no digest'}
|
||||
|
||||
def test_i_can_inspect_values(self):
|
||||
sheerka, context, table, how, little = self.init_concepts(
|
||||
"table",
|
||||
Concept("how is x").def_var("x"),
|
||||
Concept("little x").def_var("x"),
|
||||
create_new=True
|
||||
)
|
||||
|
||||
return_values = sheerka.evaluate_user_input("how is little table")
|
||||
|
||||
res = sheerka.inspect(context, return_values[0], values=True)
|
||||
concept_debug_obj = ConceptDebugObj(return_values[0].body)
|
||||
assert res.body == {
|
||||
'body': concept_debug_obj,
|
||||
'#type#': 'ReturnValueConcept',
|
||||
'id': '43',
|
||||
'key': '__RETURN_VALUE',
|
||||
'message': None,
|
||||
'name': '__RETURN_VALUE',
|
||||
'parents': [concept_debug_obj],
|
||||
'status': True,
|
||||
'value': concept_debug_obj,
|
||||
'who': 'evaluators.OneSuccess'}
|
||||
|
||||
# I also can print it using bag
|
||||
res = sheerka.inspect(context, return_values[0], '#type#', "who", "status", "value", values=True, as_bag=True)
|
||||
assert res.body == {'#type#': 'ReturnValueConcept',
|
||||
'who': 'evaluators.OneSuccess',
|
||||
'status': True,
|
||||
'value': {'#type#': 'Concept',
|
||||
'compiled.x': {'#type#': 'Concept',
|
||||
'compiled.x': {'#type#': 'Concept',
|
||||
'id': '1001',
|
||||
'key': 'table',
|
||||
'name': 'table'},
|
||||
'id': '1003',
|
||||
'key': 'little __var__0',
|
||||
'meta.x': "'table'",
|
||||
'name': 'little x'},
|
||||
'id': '1002',
|
||||
'key': 'how is __var__0',
|
||||
'meta.x': "'little table'",
|
||||
'name': 'how is x'}}
|
||||
|
||||
def test_i_can_display_meta_and_compile_attributes_using_concept_debug_obj(self):
|
||||
foo = Concept("foo", id=1001, key="foo_key").def_var("x", "x_meta").def_var("y", "y_meta")
|
||||
foo.get_compiled()["x"] = Concept("bar", id=1002).def_var("a", "a_meta").set_value("a", "a_value")
|
||||
foo.set_value("x", "x_value")
|
||||
foo.set_value("y", NotInit)
|
||||
|
||||
foo.values() # freeze attributes
|
||||
|
||||
foo.set_value("z", "extra_value")
|
||||
|
||||
assert str(ConceptDebugObj(foo)) == \
|
||||
"(:foo|1001:meta.x='x_meta', meta.y='y_meta', compiled.x=(:bar|1002:meta.a='a_meta', value.a='a_value'), value.x='x_value', value.z='extra_value')"
|
||||
|
||||
@@ -85,7 +85,7 @@ class TestSheerkaMemory(TestUsingMemoryBasedSheerka):
|
||||
foo = Concept("foo")
|
||||
sheerka.add_to_memory(context, "a", foo)
|
||||
|
||||
assert service.objects.copy() == {"a": MemoryObject(context.event.get_digest(), foo)}
|
||||
assert service.memory_objects.copy() == {"a": MemoryObject(context.event.get_digest(), foo)}
|
||||
assert id(sheerka.get_from_memory(context, "a").obj) == id(foo)
|
||||
|
||||
def test_i_can_use_memory_to_get_the_list_of_all_objects(self):
|
||||
@@ -134,6 +134,11 @@ class TestSheerkaMemory(TestUsingMemoryBasedSheerka):
|
||||
|
||||
assert sheerka.memory(context, "item") == bar
|
||||
|
||||
def test_object_are_not_added_in_memory_during_the_initialisation(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
|
||||
assert len(sheerka.memory(context)) == 0
|
||||
|
||||
|
||||
class TestSheerkaMemoryUsingFileBase(TestUsingFileBasedSheerka):
|
||||
def test_i_can_record_memory_objects(self):
|
||||
|
||||
@@ -2,7 +2,7 @@ import ast
|
||||
|
||||
import pytest
|
||||
from core.builtin_concepts import BuiltinConcepts
|
||||
from core.concept import Concept
|
||||
from core.concept import Concept, CMV
|
||||
from core.global_symbols import RULE_COMPARISON_CONTEXT
|
||||
from core.rule import Rule
|
||||
from core.sheerka.services.SheerkaRuleManager import SheerkaRuleManager, FormatRuleParser, \
|
||||
@@ -227,8 +227,8 @@ class TestSheerkaRuleManager(TestUsingMemoryBasedSheerka):
|
||||
assert res[0].concept == expected
|
||||
|
||||
@pytest.mark.parametrize("text, expected_variables", [
|
||||
("a cat is an animal", ["cat", "animal"]),
|
||||
("a cat is an b", ["a", "animal"]),
|
||||
("a cat is an animal", ["a cat", "animal"]),
|
||||
("a cat is an b", ["a cat", "b"]),
|
||||
])
|
||||
def test_i_can_compile_predicate_when_sya_node_parser(self, text, expected_variables):
|
||||
sheerka, context, *concepts = self.init_concepts(
|
||||
@@ -238,7 +238,7 @@ class TestSheerkaRuleManager(TestUsingMemoryBasedSheerka):
|
||||
create_new=True
|
||||
)
|
||||
service = sheerka.services[SheerkaRuleManager.NAME]
|
||||
expected = concepts[0]
|
||||
expected = CMV(concepts[0], x=expected_variables[0], y=expected_variables[1])
|
||||
|
||||
res = service.compile_when(context, "test", text)
|
||||
|
||||
@@ -281,14 +281,14 @@ class TestSheerkaRuleManager(TestUsingMemoryBasedSheerka):
|
||||
assert isinstance(res[0], RulePredicate)
|
||||
assert res[0].evaluator == CONCEPT_EVALUATOR_NAME
|
||||
assert sheerka.isinstance(res[0].predicate, BuiltinConcepts.RETURN_VALUE)
|
||||
assert sheerka.objvalue(res[0].predicate)[0].concept == concepts[0]
|
||||
assert res[0].concept == concepts[0]
|
||||
assert sheerka.objvalue(res[0].predicate)[0].concept == CMV(concepts[0], x="a", y="b")
|
||||
assert res[0].concept == CMV(concepts[0], x="a", y="b")
|
||||
|
||||
assert isinstance(res[1], RulePredicate)
|
||||
assert res[1].evaluator == CONCEPT_EVALUATOR_NAME
|
||||
assert sheerka.isinstance(res[1].predicate, BuiltinConcepts.RETURN_VALUE)
|
||||
assert sheerka.objvalue(res[1].predicate)[0].concept == concepts[1]
|
||||
assert res[1].concept == concepts[1]
|
||||
assert sheerka.objvalue(res[1].predicate)[0].concept == CMV(concepts[1], x="a", y="b")
|
||||
assert res[1].concept == CMV(concepts[1], x="a", y="b")
|
||||
|
||||
# @pytest.mark.skip
|
||||
# @pytest.mark.parametrize("text, expected", [
|
||||
|
||||
@@ -14,10 +14,8 @@ class TestSheerkaResultManager(TestUsingMemoryBasedSheerka):
|
||||
|
||||
@classmethod
|
||||
def setup_class(cls):
|
||||
sheerka = cls().get_sheerka()
|
||||
sheerka = cls().get_sheerka(cache_only=False)
|
||||
sheerka.save_execution_context = True
|
||||
sheerka.evaluate_user_input("def concept one as 1")
|
||||
cls.io_cache = sheerka.sdp.io.cache.copy()
|
||||
|
||||
@classmethod
|
||||
def teardown_class(cls):
|
||||
@@ -26,21 +24,73 @@ class TestSheerkaResultManager(TestUsingMemoryBasedSheerka):
|
||||
|
||||
def init_test(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
sheerka.sdp.io.cache = self.io_cache.copy()
|
||||
return sheerka, context
|
||||
service = sheerka.services[SheerkaResultConcept.NAME]
|
||||
|
||||
def test_i_can_get_the_result_by_digest(self):
|
||||
sheerka, context = self.init_test()
|
||||
return sheerka, context, service
|
||||
|
||||
digest = sheerka.get_last_execution().event.get_digest()
|
||||
def test_i_can_record_execution_contexts(self):
|
||||
sheerka, context, service = self.init_test()
|
||||
|
||||
sheerka.evaluate_user_input("foo")
|
||||
|
||||
executions_contexts_in_cache = service.executions_contexts_cache.copy()
|
||||
assert len(executions_contexts_in_cache) == 1
|
||||
event_id = list(executions_contexts_in_cache.keys())[0]
|
||||
execution_context = list(executions_contexts_in_cache.values())[0]
|
||||
|
||||
assert execution_context.desc == "Evaluating 'foo'"
|
||||
|
||||
executions_contexts_in_db = sheerka.sdp.load_result(event_id)
|
||||
assert executions_contexts_in_db is not None
|
||||
assert executions_contexts_in_db.desc == "Evaluating 'foo'"
|
||||
|
||||
assert service.last_execution is not None
|
||||
assert service.last_execution.desc == "Evaluating 'foo'"
|
||||
|
||||
def test_i_can_get_the_result_by_digest_using_cache(self):
|
||||
sheerka, context, service = self.init_test()
|
||||
sheerka.evaluate_user_input("def concept one as 1")
|
||||
|
||||
digest = service.last_execution.event.get_digest()
|
||||
|
||||
res = sheerka.get_results_by_digest(context, digest)
|
||||
|
||||
# we get the result
|
||||
assert sheerka.isinstance(res, BuiltinConcepts.EXPLANATION)
|
||||
assert res.command == "def concept one as 1"
|
||||
assert res.digest == digest
|
||||
assert isinstance(res.body, types.GeneratorType)
|
||||
|
||||
# the digest is correctly recorded
|
||||
assert sheerka.load_var(SheerkaResultConcept.NAME, "digest") == digest
|
||||
|
||||
previous_results = list(res.body)
|
||||
|
||||
# Second test,
|
||||
# I can get the result from the recorded digest
|
||||
res = sheerka.get_results(context)
|
||||
assert sheerka.isinstance(res, BuiltinConcepts.EXPLANATION)
|
||||
assert res.command == "def concept one as 1"
|
||||
assert res.digest == digest
|
||||
assert isinstance(res.body, types.GeneratorType)
|
||||
|
||||
assert list(res.body) == previous_results
|
||||
|
||||
def test_i_can_get_result_by_digest_using_db(self):
|
||||
sheerka, context, service = self.init_test()
|
||||
sheerka.evaluate_user_input("def concept one as 1")
|
||||
digest = service.last_execution.event.get_digest()
|
||||
service.reset()
|
||||
|
||||
res = sheerka.get_results_by_digest(context, digest)
|
||||
|
||||
# we get the result
|
||||
assert sheerka.isinstance(res, BuiltinConcepts.EXPLANATION)
|
||||
assert res.command == "def concept one as 1"
|
||||
assert res.digest == digest
|
||||
assert isinstance(res.body, types.GeneratorType)
|
||||
|
||||
# the digest is correctly recorded
|
||||
assert sheerka.load_var(SheerkaResultConcept.NAME, "digest") == digest
|
||||
|
||||
previous_results = list(res.body)
|
||||
@@ -67,9 +117,10 @@ class TestSheerkaResultManager(TestUsingMemoryBasedSheerka):
|
||||
assert sheerka.get_results(context) is None
|
||||
|
||||
def test_i_can_get_the_result_by_command_name(self):
|
||||
sheerka, context = self.init_test()
|
||||
sheerka, context, service = self.init_test()
|
||||
sheerka.evaluate_user_input("def concept one as 1")
|
||||
|
||||
digest = sheerka.get_last_execution().event.get_digest()
|
||||
digest = service.last_execution.event.get_digest()
|
||||
sheerka.evaluate_user_input("one") # another command
|
||||
|
||||
res = sheerka.get_results_by_command(context, "def concept")
|
||||
@@ -78,8 +129,18 @@ class TestSheerkaResultManager(TestUsingMemoryBasedSheerka):
|
||||
assert res.digest == digest
|
||||
assert isinstance(res.body, types.GeneratorType)
|
||||
|
||||
def test_i_can_get_the_result_by_command_name_using_db(self):
|
||||
sheerka, context, service = self.init_test()
|
||||
sheerka.evaluate_user_input("def concept one as 1")
|
||||
sheerka.evaluate_user_input("one") # another command
|
||||
service.reset()
|
||||
|
||||
res = sheerka.get_results_by_command(context, "def concept")
|
||||
assert res.command == "def concept one as 1"
|
||||
|
||||
def test_i_can_get_the_result_by_command_when_not_in_the_same_page_size(self):
|
||||
sheerka, context = self.init_test()
|
||||
sheerka, context, service = self.init_test()
|
||||
sheerka.evaluate_user_input("def concept one as 1")
|
||||
|
||||
sheerka.evaluate_user_input("one")
|
||||
sheerka.evaluate_user_input("one")
|
||||
@@ -98,7 +159,8 @@ class TestSheerkaResultManager(TestUsingMemoryBasedSheerka):
|
||||
assert res.body == {'command': 'def concept'}
|
||||
|
||||
def test_i_cannot_get_result_from_command_if_the_command_does_not_exists_multiple_pages(self):
|
||||
sheerka, context = self.init_test()
|
||||
sheerka, context, service = self.init_test()
|
||||
sheerka.evaluate_user_input("def concept one as 1")
|
||||
|
||||
sheerka.evaluate_user_input("one")
|
||||
sheerka.evaluate_user_input("one")
|
||||
@@ -110,7 +172,8 @@ class TestSheerkaResultManager(TestUsingMemoryBasedSheerka):
|
||||
assert res.body == {'command': 'fake command'}
|
||||
|
||||
def test_i_can_get_last_results(self):
|
||||
sheerka, context = self.init_test()
|
||||
sheerka, context, service = self.init_test()
|
||||
sheerka.evaluate_user_input("def concept one as 1")
|
||||
|
||||
sheerka.evaluate_user_input("one")
|
||||
|
||||
@@ -118,6 +181,16 @@ class TestSheerkaResultManager(TestUsingMemoryBasedSheerka):
|
||||
assert sheerka.isinstance(res, BuiltinConcepts.EXPLANATION)
|
||||
assert res.command == "one"
|
||||
|
||||
def test_i_can_get_last_results_using_db(self):
|
||||
sheerka, context, service = self.init_test()
|
||||
sheerka.evaluate_user_input("def concept one as 1")
|
||||
sheerka.evaluate_user_input("one")
|
||||
service.reset()
|
||||
|
||||
res = sheerka.get_last_results(context)
|
||||
assert sheerka.isinstance(res, BuiltinConcepts.EXPLANATION)
|
||||
assert res.command == "one"
|
||||
|
||||
def test_i_can_get_last_results_when_event_with_no_result(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
|
||||
@@ -154,7 +227,8 @@ class TestSheerkaResultManager(TestUsingMemoryBasedSheerka):
|
||||
{"desc": "Evaluating 'def concept one as 1'", "id": 0}
|
||||
])
|
||||
def test_i_can_get_last_results_using_kwarg(self, kwargs):
|
||||
sheerka, context = self.init_test()
|
||||
sheerka, context, service = self.init_test()
|
||||
sheerka.evaluate_user_input("def concept one as 1")
|
||||
ExecutionContext.ids.clear()
|
||||
|
||||
res = sheerka.get_last_results(context, **kwargs)
|
||||
@@ -170,7 +244,8 @@ class TestSheerkaResultManager(TestUsingMemoryBasedSheerka):
|
||||
("'def concept one as 1' in desc and id == 0", {"desc": "Evaluating 'def concept one as 1'", "id": 0})
|
||||
])
|
||||
def test_i_can_get_last_results_using_filter(self, predicate, expected):
|
||||
sheerka, context = self.init_test()
|
||||
sheerka, context, service = self.init_test()
|
||||
sheerka.evaluate_user_input("def concept one as 1")
|
||||
ExecutionContext.ids.clear()
|
||||
|
||||
res = sheerka.get_last_results(context, filter=predicate)
|
||||
@@ -186,7 +261,8 @@ class TestSheerkaResultManager(TestUsingMemoryBasedSheerka):
|
||||
("'def concept one as 1' in desc and id == 0", {"desc": "Evaluating 'def concept one as 1'", "id": 0})
|
||||
])
|
||||
def test_i_can_get_last_results_using_the_first_argument_to_filter(self, predicate, expected):
|
||||
sheerka, context = self.init_test()
|
||||
sheerka, context, service = self.init_test()
|
||||
sheerka.evaluate_user_input("def concept one as 1")
|
||||
ExecutionContext.ids.clear()
|
||||
|
||||
res = sheerka.get_last_results(context, predicate)
|
||||
@@ -202,7 +278,8 @@ class TestSheerkaResultManager(TestUsingMemoryBasedSheerka):
|
||||
{"desc": "Evaluating 'def concept one as 1'", "id": 0}
|
||||
])
|
||||
def test_i_can_get_results_using_kwarg(self, kwargs):
|
||||
sheerka, context = self.init_test()
|
||||
sheerka, context, service = self.init_test()
|
||||
sheerka.evaluate_user_input("def concept one as 1")
|
||||
ExecutionContext.ids.clear()
|
||||
sheerka.get_last_results(context)
|
||||
|
||||
@@ -219,7 +296,8 @@ class TestSheerkaResultManager(TestUsingMemoryBasedSheerka):
|
||||
("'def concept one as 1' in desc and id == 0", {"desc": "Evaluating 'def concept one as 1'", "id": 0})
|
||||
])
|
||||
def test_i_can_get_results_using_filter(self, predicate, expected):
|
||||
sheerka, context = self.init_test()
|
||||
sheerka, context, service = self.init_test()
|
||||
sheerka.evaluate_user_input("def concept one as 1")
|
||||
ExecutionContext.ids.clear()
|
||||
sheerka.get_last_results(context)
|
||||
|
||||
@@ -236,7 +314,8 @@ class TestSheerkaResultManager(TestUsingMemoryBasedSheerka):
|
||||
("'def concept one as 1' in desc and id == 0", {"desc": "Evaluating 'def concept one as 1'", "id": 0})
|
||||
])
|
||||
def test_i_can_get_results_using_the_first_argument_to_filter(self, predicate, expected):
|
||||
sheerka, context = self.init_test()
|
||||
sheerka, context, service = self.init_test()
|
||||
sheerka.evaluate_user_input("def concept one as 1")
|
||||
ExecutionContext.ids.clear()
|
||||
sheerka.get_last_results(context)
|
||||
|
||||
@@ -251,3 +330,35 @@ class TestSheerkaResultManager(TestUsingMemoryBasedSheerka):
|
||||
predicate = {"filter": "a b c"}
|
||||
with pytest.raises(SyntaxError):
|
||||
SheerkaResultConcept.get_predicate(**predicate)
|
||||
|
||||
def test_i_can_get_last_return_value(self):
|
||||
sheerka, context, service = self.init_test()
|
||||
|
||||
sheerka.evaluate_user_input("def concept one as 1")
|
||||
ret = sheerka.last_ret(context)
|
||||
assert sheerka.isinstance(ret[0].body, BuiltinConcepts.NEW_CONCEPT)
|
||||
|
||||
sheerka.evaluate_user_input("eval one")
|
||||
ret = sheerka.last_ret(context)
|
||||
assert ret[0].body == 1
|
||||
|
||||
def test_i_can_track_new_concept(self):
|
||||
sheerka, context, service = self.init_test()
|
||||
|
||||
res = sheerka.evaluate_user_input("def concept one as 1")
|
||||
new_concept = res[0].body.body
|
||||
|
||||
assert sheerka.last_created_concept(context) == new_concept
|
||||
assert service.last_created_concept_id == new_concept.id
|
||||
|
||||
def test_last_created_concept_is_recorded(self):
|
||||
sheerka, context, service = self.init_test()
|
||||
res = sheerka.evaluate_user_input("def concept one as 1")
|
||||
new_concept = res[0].body.body
|
||||
service.reset()
|
||||
|
||||
service.initialize_deferred(context, False)
|
||||
|
||||
assert service.last_created_concept_id == new_concept.id
|
||||
assert sheerka.last_created_concept(context) == new_concept
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ from dataclasses import dataclass
|
||||
|
||||
import core.utils
|
||||
import pytest
|
||||
from core.builtin_concepts import BuiltinConcepts
|
||||
from core.concept import Concept
|
||||
from core.tokenizer import Token, TokenKind, Tokenizer, Keywords
|
||||
|
||||
@@ -338,3 +339,81 @@ def test_i_can_get_text_from_tokens(text, expected_text):
|
||||
def test_i_can_get_text_from_tokens_with_custom_switcher(text, custom, expected_text):
|
||||
tokens = list(Tokenizer(text))
|
||||
assert core.utils.get_text_from_tokens(tokens, custom) == expected_text
|
||||
|
||||
|
||||
def test_i_can_deep_copy_a_concept():
|
||||
def check_are_the_same(actual, expected):
|
||||
assert id(actual) != id(expected)
|
||||
|
||||
for k, v in vars(expected.get_metadata()).items():
|
||||
assert getattr(actual.get_metadata(), k) == v
|
||||
|
||||
# test the values
|
||||
for k, v in expected.values().items():
|
||||
assert getattr(actual, k) == v
|
||||
|
||||
concept1 = Concept(name="concept1_name",
|
||||
is_builtin=True,
|
||||
is_unique=True,
|
||||
key="concept1_key",
|
||||
body="concept1_body",
|
||||
where='concept1_where',
|
||||
pre="concept1_pre",
|
||||
post="concept1_post",
|
||||
ret="concept1_ret",
|
||||
definition="concept1_definition",
|
||||
definition_type="concept1_definition_type",
|
||||
desc="concept1_desc",
|
||||
id="concept1_ids",
|
||||
props="concept1_props",
|
||||
variables=[],
|
||||
bound_body=None)
|
||||
|
||||
concept2 = Concept(name="concept2_name",
|
||||
is_builtin=True,
|
||||
is_unique=True,
|
||||
key="concept2_key",
|
||||
body="concept2_body",
|
||||
where='concept2_where',
|
||||
pre="concept2_pre",
|
||||
post="concept2_post",
|
||||
ret="concept2_ret",
|
||||
definition="concept2_definition",
|
||||
definition_type="concept2_definition_type",
|
||||
desc="concept2_desc",
|
||||
id="concept2_ids",
|
||||
props={"prop_name": concept1},
|
||||
variables=[("var1", "default_value1"), ("var2", "default_value2")],
|
||||
bound_body="var1")
|
||||
|
||||
concept = Concept(name="my_name",
|
||||
is_builtin=True,
|
||||
is_unique=True,
|
||||
key="my_key",
|
||||
body="my_body",
|
||||
where='my_where',
|
||||
pre="my_pre",
|
||||
post="my_post",
|
||||
ret="my_ret",
|
||||
definition="my_definition",
|
||||
definition_type="my_definition_type",
|
||||
desc="my_desc",
|
||||
id="my_ids",
|
||||
props={
|
||||
BuiltinConcepts.ISA: {concept1, concept2},
|
||||
"prop2": ["value1, value2"],
|
||||
"prop3": {"a": 1, "b": 2},
|
||||
"prop4": "a simple value"},
|
||||
variables=[("var1", "default_value1"), ("var2", "default_value2")])
|
||||
concept.set_value("var1", "string_value")
|
||||
concept.set_value("var2", 10)
|
||||
concept.set_value("var3", concept1)
|
||||
|
||||
copied = core.utils.sheerka_deepcopy(concept)
|
||||
|
||||
check_are_the_same(copied, concept)
|
||||
|
||||
copied_props = sorted(list(copied.get_prop(BuiltinConcepts.ISA)), key=lambda o: o.id)
|
||||
concept_props = sorted(list(concept.get_prop(BuiltinConcepts.ISA)), key=lambda o: o.id)
|
||||
for copied_prop, concept_prop in zip(copied_props, concept_props):
|
||||
check_are_the_same(copied_prop, concept_prop)
|
||||
|
||||
Reference in New Issue
Block a user