Refactored sheerka class: splitted to use sub handlers. Refactored unit tests to use classes.
This commit is contained in:
@@ -0,0 +1,203 @@
|
||||
import logging
|
||||
import time
|
||||
|
||||
from core.builtin_concepts import BuiltinConcepts
|
||||
from core.concept import Concept
|
||||
from sdp.sheerkaDataProvider import Event
|
||||
|
||||
DEBUG_TAB_SIZE = 4
|
||||
|
||||
|
||||
class ExecutionContext:
|
||||
"""
|
||||
To keep track of the execution of a request
|
||||
"""
|
||||
|
||||
ids = {}
|
||||
|
||||
@staticmethod
|
||||
def get_id(event_digest):
|
||||
if event_digest in ExecutionContext.ids:
|
||||
ExecutionContext.ids[event_digest] += 1
|
||||
else:
|
||||
ExecutionContext.ids[event_digest] = 0
|
||||
return ExecutionContext.ids[event_digest]
|
||||
|
||||
def __init__(self,
|
||||
who,
|
||||
event: Event,
|
||||
sheerka,
|
||||
desc: str = None,
|
||||
**kwargs):
|
||||
|
||||
self._parent = None
|
||||
self._id = ExecutionContext.get_id(event.get_digest())
|
||||
self._tab = ""
|
||||
self._bag = {} # other variables
|
||||
self._start = 0
|
||||
self._stop = 0
|
||||
|
||||
self.who = who # who is asking
|
||||
self.event = event # what was the (original) trigger
|
||||
self.sheerka = sheerka # sheerka
|
||||
self.desc = desc # human description of what is going on
|
||||
self.children = []
|
||||
self.preprocess = None
|
||||
|
||||
self.inputs = {} # what was the parameters of the execution context
|
||||
self.values = {} # what was produced by the execution context
|
||||
|
||||
self.obj = kwargs.pop("obj", None)
|
||||
self.concepts = kwargs.pop("concepts", {})
|
||||
# update the other elements
|
||||
for k, v in kwargs.items():
|
||||
self._bag[k] = v
|
||||
|
||||
@property
|
||||
def elapsed(self):
|
||||
if self._start == 0:
|
||||
return 0
|
||||
|
||||
return (self._stop if self._stop > 0 else time.time_ns()) - self._start
|
||||
|
||||
@property
|
||||
def elapsed_str(self):
|
||||
nano_sec = self.elapsed
|
||||
dt = nano_sec / 1e6
|
||||
return f"{dt} ms" if dt < 1000 else f"{dt / 1000} s"
|
||||
|
||||
@property
|
||||
def id(self):
|
||||
return self._id
|
||||
|
||||
def __getattr__(self, item):
|
||||
if item in self._bag:
|
||||
return self._bag[item]
|
||||
|
||||
raise AttributeError(f"'ExecutionContext' object has no attribute '{item}'")
|
||||
|
||||
def __enter__(self):
|
||||
self._start = time.time_ns()
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc_val, exc_tb):
|
||||
self._stop = time.time_ns()
|
||||
|
||||
def __repr__(self):
|
||||
msg = f"ExecutionContext(who={self.who}, id={self._id}"
|
||||
if self.desc:
|
||||
msg += f", desc='{self.desc}'"
|
||||
msg += ")"
|
||||
return msg
|
||||
|
||||
def add_preprocess(self, name, **kwargs):
|
||||
preprocess = self.sheerka.new(BuiltinConcepts.EVALUATOR_PRE_PROCESS)
|
||||
preprocess.set_prop("name", name)
|
||||
for k, v in kwargs.items():
|
||||
preprocess.set_prop(k, v)
|
||||
|
||||
if not self.preprocess:
|
||||
self.preprocess = set()
|
||||
self.preprocess.add(preprocess)
|
||||
return self
|
||||
|
||||
def add_inputs(self, **kwargs):
|
||||
for k, v in kwargs.items():
|
||||
self.inputs[k] = v
|
||||
return self
|
||||
|
||||
def add_values(self, **kwargs):
|
||||
for k, v in kwargs.items():
|
||||
self.values[k] = v
|
||||
return self
|
||||
|
||||
def get_concept(self, key):
|
||||
# search in obj
|
||||
if isinstance(self.obj, Concept):
|
||||
if self.obj.key == key:
|
||||
return self.obj
|
||||
for prop in self.obj.props:
|
||||
if prop == key:
|
||||
value = self.obj.props[prop].value
|
||||
if isinstance(value, Concept):
|
||||
return value
|
||||
|
||||
# search in concepts
|
||||
if self.concepts:
|
||||
for k, c in self.concepts.items():
|
||||
if k == key:
|
||||
return c
|
||||
|
||||
return self.sheerka.get(key)
|
||||
|
||||
def new_concept(self, key, **kwargs):
|
||||
# search in obj
|
||||
if self.obj:
|
||||
if self.obj.key == key:
|
||||
return self.sheerka.new_from_template(self.obj, key, **kwargs)
|
||||
for prop in self.obj.props:
|
||||
if prop == key:
|
||||
value = self.obj.props[prop].value
|
||||
if isinstance(value, Concept):
|
||||
return self.sheerka.new_from_template(value, key, **kwargs)
|
||||
else:
|
||||
return value
|
||||
|
||||
if self.concepts:
|
||||
for k, c in self.concepts.items():
|
||||
if k == key:
|
||||
return self.sheerka.new_from_template(c, key, **kwargs)
|
||||
|
||||
return self.sheerka.new(key, **kwargs)
|
||||
|
||||
def push(self, who=None, desc=None, **kwargs):
|
||||
who = who or self.who
|
||||
_kwargs = {"obj": self.obj, "concepts": self.concepts}
|
||||
_kwargs.update(self._bag)
|
||||
_kwargs.update(kwargs)
|
||||
new = ExecutionContext(
|
||||
who,
|
||||
self.event,
|
||||
self.sheerka,
|
||||
desc,
|
||||
**_kwargs,
|
||||
)
|
||||
new._parent = self
|
||||
new._tab = self._tab + " " * DEBUG_TAB_SIZE
|
||||
new.preprocess = self.preprocess
|
||||
|
||||
self.children.append(new)
|
||||
return new
|
||||
|
||||
def log_new(self, logger):
|
||||
logger.debug(f"[{self._id:2}]" + self._tab + str(self))
|
||||
|
||||
def log(self, logger, message, who=None):
|
||||
logger.debug(f"[{self._id:2}]" + self._tab + (f"[{who}] " if who else "") + str(message))
|
||||
|
||||
def log_error(self, logger, message, who=None):
|
||||
logger.exception(f"[{self._id:2}]" + self._tab + (f"[{who}] " if who else "") + str(message))
|
||||
|
||||
def log_result(self, logger, return_values):
|
||||
if not logger.isEnabledFor(logging.DEBUG):
|
||||
return
|
||||
|
||||
if len(return_values) == 0:
|
||||
logger.debug(self._tab + "No return value")
|
||||
|
||||
for r in return_values:
|
||||
to_str = self.return_value_to_str(r)
|
||||
logger.debug(f"[{self._id:2}]" + self._tab + "-> " + to_str)
|
||||
|
||||
def to_dict(self):
|
||||
from core.sheerka_transform import SheerkaTransform
|
||||
st = SheerkaTransform(self.sheerka)
|
||||
return st.to_dict(self)
|
||||
|
||||
@staticmethod
|
||||
def return_value_to_str(r):
|
||||
value = str(r.value)
|
||||
if len(value) > 50:
|
||||
value = value[:47] + "..."
|
||||
to_str = f"ReturnValue(who={r.who}, status={r.status}, value={value})"
|
||||
return to_str
|
||||
Reference in New Issue
Block a user