Added parsers and Evaluators auto discovery
This commit is contained in:
+40
-13
@@ -65,17 +65,8 @@ class Sheerka(Concept):
|
|||||||
self.sdp.set_key(self.USER_CONCEPTS_KEYS, 1000)
|
self.sdp.set_key(self.USER_CONCEPTS_KEYS, 1000)
|
||||||
|
|
||||||
self.initialize_builtin_concepts()
|
self.initialize_builtin_concepts()
|
||||||
|
self.initialize_builtin_parsers()
|
||||||
self.parsers.append(core.utils.get_class("parsers.DefaultParser.DefaultParser"))
|
self.initialize_builtin_evaluators()
|
||||||
self.parsers.append(core.utils.get_class("parsers.PythonParser.PythonParser"))
|
|
||||||
self.parsers.append(core.utils.get_class("parsers.ExactConceptParser.ExactConceptParser"))
|
|
||||||
|
|
||||||
self.evaluators.append(core.utils.new_object("evaluators.ParsersEvaluator.ParsersEvaluator"))
|
|
||||||
self.evaluators.append(core.utils.new_object("evaluators.AddConceptEvaluator.AddConceptEvaluator"))
|
|
||||||
self.evaluators.append(core.utils.new_object("evaluators.PythonEvaluator.PythonEvaluator"))
|
|
||||||
self.evaluators.append(core.utils.new_object("evaluators.ConceptEvaluator.ConceptEvaluator"))
|
|
||||||
self.evaluators.append(
|
|
||||||
core.utils.new_object("evaluators.DuplicateConceptEvaluator.DuplicateConceptEvaluator"))
|
|
||||||
|
|
||||||
except IOError as e:
|
except IOError as e:
|
||||||
return ReturnValueConcept(self, False, self.get(BuiltinConcepts.ERROR), e)
|
return ReturnValueConcept(self, False, self.get(BuiltinConcepts.ERROR), e)
|
||||||
@@ -123,6 +114,28 @@ class Sheerka(Concept):
|
|||||||
|
|
||||||
self.add_in_cache(concept)
|
self.add_in_cache(concept)
|
||||||
|
|
||||||
|
def initialize_builtin_parsers(self):
|
||||||
|
"""
|
||||||
|
Init the parsers
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
for parser in core.utils.get_sub_classes("parsers", "parsers.BaseParser.BaseParser"):
|
||||||
|
log.debug(f"Adding builtin parser '{parser.__name__}'")
|
||||||
|
self.parsers.append(parser)
|
||||||
|
|
||||||
|
def initialize_builtin_evaluators(self):
|
||||||
|
"""
|
||||||
|
Init the evaluators
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
for evaluator in core.utils.get_sub_classes("evaluators", "evaluators.BaseEvaluator.OneReturnValueEvaluator"):
|
||||||
|
log.debug(f"Adding builtin evaluator '{evaluator.__name__}'")
|
||||||
|
self.evaluators.append(evaluator)
|
||||||
|
|
||||||
|
for evaluator in core.utils.get_sub_classes("evaluators", "evaluators.BaseEvaluator.AllReturnValuesEvaluator"):
|
||||||
|
log.debug(f"Adding builtin evaluator '{evaluator.__name__}'")
|
||||||
|
self.evaluators.append(evaluator)
|
||||||
|
|
||||||
def init_logging(self):
|
def init_logging(self):
|
||||||
if self.debug:
|
if self.debug:
|
||||||
log_format = "%(asctime)s %(name)s [%(levelname)s] %(message)s"
|
log_format = "%(asctime)s %(name)s [%(levelname)s] %(message)s"
|
||||||
@@ -197,17 +210,18 @@ class Sheerka(Concept):
|
|||||||
def process(self, context, return_values, contextual_concepts=None):
|
def process(self, context, return_values, contextual_concepts=None):
|
||||||
log.debug("Evaluating parsing result.")
|
log.debug("Evaluating parsing result.")
|
||||||
|
|
||||||
# init
|
# return_values must be a list
|
||||||
if not isinstance(return_values, list):
|
if not isinstance(return_values, list):
|
||||||
return_values = [return_values]
|
return_values = [return_values]
|
||||||
|
|
||||||
|
# adds contextual concepts
|
||||||
if contextual_concepts:
|
if contextual_concepts:
|
||||||
return_values.extend(contextual_concepts)
|
return_values.extend(contextual_concepts)
|
||||||
|
|
||||||
# group the evaluators by priority and sort them
|
# group the evaluators by priority and sort them
|
||||||
# The first one to be applied will be the one with the highest priority
|
# The first one to be applied will be the one with the highest priority
|
||||||
grouped_evaluators = {}
|
grouped_evaluators = {}
|
||||||
for item in self.evaluators:
|
for item in [e() for e in self.evaluators]:
|
||||||
grouped_evaluators.setdefault(item.priority, []).append(item)
|
grouped_evaluators.setdefault(item.priority, []).append(item)
|
||||||
sorted_priorities = sorted(grouped_evaluators.keys(), reverse=True)
|
sorted_priorities = sorted(grouped_evaluators.keys(), reverse=True)
|
||||||
|
|
||||||
@@ -428,6 +442,19 @@ class Sheerka(Concept):
|
|||||||
|
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_builtin_parsers():
|
||||||
|
res = []
|
||||||
|
# modules = core.utils.get_module("parsers")
|
||||||
|
# for m in modules:
|
||||||
|
base_class = core.utils.get_class("parsers.BaseParser.BaseParser")
|
||||||
|
|
||||||
|
for c in core.utils.get_classes_recursive("parsers"):
|
||||||
|
#if issubclass(c, base_class) and c != base_class:
|
||||||
|
res.append(c)
|
||||||
|
|
||||||
|
return res
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def test():
|
def test():
|
||||||
return "I have access to Sheerka !"
|
return "I have access to Sheerka !"
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
|
import importlib
|
||||||
import inspect
|
import inspect
|
||||||
|
import pkgutil
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
|
||||||
@@ -38,6 +40,7 @@ def get_class(qname):
|
|||||||
m = getattr(m, comp)
|
m = getattr(m, comp)
|
||||||
return m
|
return m
|
||||||
|
|
||||||
|
|
||||||
def get_module(qname):
|
def get_module(qname):
|
||||||
"""
|
"""
|
||||||
Loads a module from its full qualified name
|
Loads a module from its full qualified name
|
||||||
@@ -77,6 +80,11 @@ def get_full_qualified_name(obj):
|
|||||||
|
|
||||||
|
|
||||||
def get_classes(module_name):
|
def get_classes(module_name):
|
||||||
|
"""
|
||||||
|
Gets all classes, for a given module_name
|
||||||
|
:param module_name: name of the module
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
mod = get_module(module_name)
|
mod = get_module(module_name)
|
||||||
for name in dir(mod):
|
for name in dir(mod):
|
||||||
obj = getattr(mod, name)
|
obj = getattr(mod, name)
|
||||||
@@ -84,6 +92,30 @@ def get_classes(module_name):
|
|||||||
yield obj
|
yield obj
|
||||||
|
|
||||||
|
|
||||||
|
def get_classes_from_package(package_name):
|
||||||
|
"""
|
||||||
|
Gets all classes, for a given package
|
||||||
|
:param package_name: name of the package
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
pkg = __import__(package_name)
|
||||||
|
prefix = pkg.__name__ + "."
|
||||||
|
for importer, modname, ispkg in pkgutil.iter_modules(pkg.__path__, prefix):
|
||||||
|
for c in get_classes(modname):
|
||||||
|
yield c
|
||||||
|
|
||||||
|
|
||||||
|
def get_sub_classes(package_name, base_class_name):
|
||||||
|
|
||||||
|
pkg = __import__(package_name)
|
||||||
|
prefix = pkg.__name__ + "."
|
||||||
|
for (module_loader, name, ispkg) in pkgutil.iter_modules(pkg.__path__, prefix):
|
||||||
|
importlib.import_module(name)
|
||||||
|
|
||||||
|
base_class = get_class(base_class_name)
|
||||||
|
return base_class.__subclasses__()
|
||||||
|
|
||||||
|
|
||||||
def remove_from_list(lst, to_remove):
|
def remove_from_list(lst, to_remove):
|
||||||
"""
|
"""
|
||||||
Removes elements from a list if they exist
|
Removes elements from a list if they exist
|
||||||
|
|||||||
@@ -20,3 +20,39 @@ def test_i_can_get_classes():
|
|||||||
assert len(classes) > 2
|
assert len(classes) > 2
|
||||||
assert error_concept in classes
|
assert error_concept in classes
|
||||||
assert return_value_concept in classes
|
assert return_value_concept in classes
|
||||||
|
|
||||||
|
|
||||||
|
def test_i_can_get_base_classes():
|
||||||
|
classes = list(core.utils.get_classes_from_package("parsers"))
|
||||||
|
|
||||||
|
# example of classes that should be in the result
|
||||||
|
base_parser = core.utils.get_class("parsers.BaseParser.BaseParser")
|
||||||
|
default_parser = core.utils.get_class("parsers.DefaultParser.DefaultParser")
|
||||||
|
exact_concept_parser = core.utils.get_class("parsers.ExactConceptParser.ExactConceptParser")
|
||||||
|
python_parser = core.utils.get_class("parsers.PythonParser.PythonParser")
|
||||||
|
node = core.utils.get_class("parsers.BaseParser.Node")
|
||||||
|
def_concept_node = core.utils.get_class("parsers.DefaultParser.DefConceptNode")
|
||||||
|
python_node = core.utils.get_class("parsers.PythonParser.PythonNode")
|
||||||
|
|
||||||
|
assert base_parser in classes
|
||||||
|
assert default_parser in classes
|
||||||
|
assert exact_concept_parser in classes
|
||||||
|
assert python_parser in classes
|
||||||
|
assert node in classes
|
||||||
|
assert def_concept_node in classes
|
||||||
|
assert python_node in classes
|
||||||
|
|
||||||
|
|
||||||
|
def test_i_can_get_sub_classes():
|
||||||
|
sub_classes = core.utils.get_sub_classes("parsers", "parsers.BaseParser.BaseParser")
|
||||||
|
|
||||||
|
# example of classes that should be (or not) in the result
|
||||||
|
base_parser = core.utils.get_class("parsers.BaseParser.BaseParser")
|
||||||
|
default_parser = core.utils.get_class("parsers.DefaultParser.DefaultParser")
|
||||||
|
exact_concept_parser = core.utils.get_class("parsers.ExactConceptParser.ExactConceptParser")
|
||||||
|
python_parser = core.utils.get_class("parsers.PythonParser.PythonParser")
|
||||||
|
|
||||||
|
assert base_parser not in sub_classes
|
||||||
|
assert default_parser in sub_classes
|
||||||
|
assert exact_concept_parser in sub_classes
|
||||||
|
assert python_parser in sub_classes
|
||||||
|
|||||||
Reference in New Issue
Block a user