@@ -1,2 +1,181 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import time
|
||||
|
||||
from core.Event import Event
|
||||
|
||||
|
||||
class ExecutionContextActions:
|
||||
TESTING = "Testing"
|
||||
INIT_SHEERKA = "Init Sheerka"
|
||||
EVALUATE_USER_INPUT = "Evaluate user input"
|
||||
EVALUATING_STEP = "Evaluating step"
|
||||
EVALUATING_ITERATION = "Evaluating iteration"
|
||||
BEFORE_PARSING = "Before parsing"
|
||||
PARSING = "Parsing"
|
||||
AFTER_PARSING = "After parsing"
|
||||
BEFORE_EVALUATION = "Before evaluation"
|
||||
EVALUATION = "Evaluation"
|
||||
AFTER_EVALUATION = "After Evaluation"
|
||||
|
||||
|
||||
class ContextHint:
|
||||
REDUCE_CONCEPTS = "Reduce Concepts" # to tell the process to only keep the meaningful results
|
||||
|
||||
|
||||
ids = {} # keep track of the next execution context id, for a given event id
|
||||
|
||||
|
||||
def get_next_id(event_digest):
|
||||
"""
|
||||
For a given event, give the next id
|
||||
:param event_digest:
|
||||
:type event_digest:
|
||||
:return:
|
||||
:rtype:
|
||||
"""
|
||||
if event_digest in ids:
|
||||
ids[event_digest] += 1
|
||||
else:
|
||||
ids[event_digest] = 0
|
||||
return ids[event_digest]
|
||||
|
||||
|
||||
class ExecutionContext:
|
||||
pass
|
||||
"""
|
||||
To keep track of the execution of a request
|
||||
Note that the protected hints are working correctly only if the hint is added BEFORE the creation of the child
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
who: str,
|
||||
event: Event,
|
||||
sheerka,
|
||||
action: ExecutionContextActions,
|
||||
action_context: object,
|
||||
desc: str = None,
|
||||
logger=None,
|
||||
global_hints=None,
|
||||
protected_hints=None,
|
||||
parent: ExecutionContext = None):
|
||||
self._id = get_next_id(event.get_digest())
|
||||
self._parent = parent
|
||||
self._children = []
|
||||
self._start = 0 # when the execution starts (to measure elapsed time)
|
||||
self._stop = 0 # when the execution stops (to measure elapses time)
|
||||
self._logger = logger
|
||||
|
||||
self.who = who # who is asking
|
||||
self.event = event # what was the (original) trigger
|
||||
self.sheerka = sheerka # sheerka
|
||||
self.action = action
|
||||
self.action_context = action_context
|
||||
self.desc = desc # human description of what is going on
|
||||
|
||||
self.private_hints = set()
|
||||
self.protected_hints = set() if protected_hints is None else protected_hints.copy()
|
||||
self.global_hints = set() if global_hints is None else global_hints
|
||||
|
||||
self.inputs = {} # what were the parameters of the execution context
|
||||
self.values = {} # what was produced by the execution context
|
||||
|
||||
def __repr__(self):
|
||||
msg = f"ExecutionContext(who={self.who}, id={self._id}, action={self.action}, context={self.action_context}"
|
||||
if self.desc:
|
||||
msg += f", desc='{self.desc}'"
|
||||
msg += ")"
|
||||
return msg
|
||||
|
||||
def __eq__(self, other):
|
||||
if id(self) == id(other):
|
||||
return True
|
||||
|
||||
if not isinstance(other, ExecutionContext):
|
||||
return False
|
||||
|
||||
return self.long_id == other.long_id
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self.long_id)
|
||||
|
||||
@property
|
||||
def long_id(self):
|
||||
return f"{self.event.get_digest()}:{self._id}"
|
||||
|
||||
@property
|
||||
def id(self):
|
||||
return self._id
|
||||
|
||||
@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"
|
||||
|
||||
def add_inputs(self, **kwargs):
|
||||
"""
|
||||
When entering stacking an ExecutionContext, list of variable that are worth to trace
|
||||
:param kwargs:
|
||||
:type kwargs:
|
||||
:return:
|
||||
:rtype:
|
||||
"""
|
||||
self.inputs.update(kwargs)
|
||||
return self
|
||||
|
||||
def add_values(self, **kwargs):
|
||||
"""
|
||||
When popping from an ExecutionContext, list of variable that are worth to trace
|
||||
:param kwargs:
|
||||
:type kwargs:
|
||||
:return:
|
||||
:rtype:
|
||||
"""
|
||||
self.values.update(kwargs)
|
||||
return self
|
||||
|
||||
def push(self,
|
||||
who: str,
|
||||
action: ExecutionContextActions,
|
||||
action_context: object,
|
||||
desc: str = None,
|
||||
logger=None):
|
||||
child = ExecutionContext(
|
||||
who,
|
||||
self.event,
|
||||
self.sheerka,
|
||||
action,
|
||||
action_context,
|
||||
desc,
|
||||
logger or self._logger,
|
||||
self.global_hints,
|
||||
self.protected_hints,
|
||||
self
|
||||
)
|
||||
self._children.append(child)
|
||||
return child
|
||||
|
||||
def get_children(self, level=-1):
|
||||
"""
|
||||
recursively look for children
|
||||
:return:
|
||||
:rtype:
|
||||
"""
|
||||
for child in self._children:
|
||||
yield child
|
||||
if level != 1:
|
||||
yield from child.get_children(level - 1)
|
||||
|
||||
def __enter__(self):
|
||||
self._start = time.time_ns()
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc_val, exc_tb):
|
||||
self._stop = time.time_ns()
|
||||
|
||||
Reference in New Issue
Block a user