standardised event construction and validation a bit more

This commit is contained in:
PatchOfScotland
2023-02-02 17:41:18 +01:00
parent 636d70f4e8
commit 64aaf46196
13 changed files with 243 additions and 97 deletions

View File

@ -9,7 +9,7 @@ import os
import shutil import shutil
from datetime import datetime from datetime import datetime
from typing import Any from typing import Any, Tuple
from core.correctness.vars import JOB_TYPE_PYTHON, PYTHON_FUNC, JOB_STATUS, \ from core.correctness.vars import JOB_TYPE_PYTHON, PYTHON_FUNC, JOB_STATUS, \
STATUS_RUNNING, JOB_START_TIME, PYTHON_EXECUTION_BASE, JOB_ID, META_FILE, \ STATUS_RUNNING, JOB_START_TIME, PYTHON_EXECUTION_BASE, JOB_ID, META_FILE, \
@ -25,16 +25,16 @@ class LocalPythonConductor(BaseConductor):
def __init__(self)->None: def __init__(self)->None:
super().__init__() super().__init__()
def valid_execute_criteria(self, job:dict[str,Any])->bool: def valid_execute_criteria(self, job:dict[str,Any])->Tuple[bool,str]:
"""Function to determine given an job defintion, if this conductor can """Function to determine given an job defintion, if this conductor can
process it or not. This conductor will accept any Python job type""" process it or not. This conductor will accept any Python job type"""
try: try:
valid_job(job) valid_job(job)
if job[JOB_TYPE] == JOB_TYPE_PYTHON: if job[JOB_TYPE] == JOB_TYPE_PYTHON:
return True return True, ""
except: except Exception as e:
pass pass
return False return False, str(e)
def execute(self, job:dict[str,Any])->None: def execute(self, job:dict[str,Any])->None:
valid_job(job) valid_job(job)

View File

@ -12,7 +12,8 @@ from typing import Any, _SpecialForm, Union, Tuple, get_origin, get_args
from core.correctness.vars import VALID_PATH_CHARS, get_not_imp_msg, \ from core.correctness.vars import VALID_PATH_CHARS, get_not_imp_msg, \
EVENT_TYPE, EVENT_PATH, JOB_EVENT, JOB_TYPE, JOB_ID, JOB_PATTERN, \ EVENT_TYPE, EVENT_PATH, JOB_EVENT, JOB_TYPE, JOB_ID, JOB_PATTERN, \
JOB_RECIPE, JOB_RULE, JOB_STATUS, JOB_CREATE_TIME, EVENT_RULE JOB_RECIPE, JOB_RULE, JOB_STATUS, JOB_CREATE_TIME, EVENT_RULE, \
WATCHDOG_BASE
# Required keys in event dict # Required keys in event dict
EVENT_KEYS = { EVENT_KEYS = {
@ -23,6 +24,11 @@ EVENT_KEYS = {
EVENT_RULE: Any EVENT_RULE: Any
} }
WATCHDOG_EVENT_KEYS = {
WATCHDOG_BASE: str,
**EVENT_KEYS
}
# Required keys in job dict # Required keys in job dict
JOB_KEYS = { JOB_KEYS = {
JOB_TYPE: str, JOB_TYPE: str,
@ -254,3 +260,6 @@ def valid_event(event:dict[str,Any])->None:
def valid_job(job:dict[str,Any])->None: def valid_job(job:dict[str,Any])->None:
"""Check that a given dict expresses a meow job.""" """Check that a given dict expresses a meow job."""
valid_meow_dict(job, "Job", JOB_KEYS) valid_meow_dict(job, "Job", JOB_KEYS)
def valid_watchdog_event(event:dict[str,Any])->None:
valid_meow_dict(event, "Watchdog event", WATCHDOG_EVENT_KEYS)

View File

@ -20,7 +20,8 @@ from core.correctness.vars import CHAR_LOWERCASE, CHAR_UPPERCASE, \
VALID_CHANNELS, HASH_BUFFER_SIZE, SHA256, DEBUG_WARNING, DEBUG_INFO, \ VALID_CHANNELS, HASH_BUFFER_SIZE, SHA256, DEBUG_WARNING, DEBUG_INFO, \
EVENT_TYPE, EVENT_PATH, JOB_EVENT, JOB_TYPE, JOB_ID, JOB_PATTERN, \ EVENT_TYPE, EVENT_PATH, JOB_EVENT, JOB_TYPE, JOB_ID, JOB_PATTERN, \
JOB_RECIPE, JOB_RULE, EVENT_RULE, JOB_STATUS, STATUS_QUEUED, \ JOB_RECIPE, JOB_RULE, EVENT_RULE, JOB_STATUS, STATUS_QUEUED, \
JOB_CREATE_TIME, JOB_REQUIREMENTS JOB_CREATE_TIME, JOB_REQUIREMENTS, WATCHDOG_BASE, WATCHDOG_HASH, \
EVENT_TYPE_WATCHDOG, JOB_TYPE_PYTHON
# mig trigger keyword replacements # mig trigger keyword replacements
KEYWORD_PATH = "{PATH}" KEYWORD_PATH = "{PATH}"
@ -283,16 +284,45 @@ def replace_keywords(old_dict:dict[str,str], job_id:str, src_path:str,
return new_dict return new_dict
def create_event(event_type:str, path:str, rule:Any, source:dict[Any,Any]={} def create_event(event_type:str, path:str, rule:Any, extras:dict[Any,Any]={}
)->dict[Any,Any]: )->dict[Any,Any]:
return { return {
**source, **extras,
EVENT_PATH: path, EVENT_PATH: path,
EVENT_TYPE: event_type, EVENT_TYPE: event_type,
EVENT_RULE: rule EVENT_RULE: rule
} }
def create_job(job_type:str, event:dict[str,Any], source:dict[Any,Any]={} def create_watchdog_event(path:str, rule:Any, base:str, hash:str,
extras:dict[Any,Any]={})->dict[Any,Any]:
return create_event(
EVENT_TYPE_WATCHDOG,
path,
rule,
extras={
**extras,
**{
WATCHDOG_HASH: hash,
WATCHDOG_BASE: base
}
}
)
def create_fake_watchdog_event(path:str, rule:Any, base:str,
extras:dict[Any,Any]={})->dict[Any,Any]:
return create_event(
EVENT_TYPE_WATCHDOG,
path,
rule,
extras={
**extras,
**{
WATCHDOG_BASE: base
}
}
)
def create_job(job_type:str, event:dict[str,Any], extras:dict[Any,Any]={}
)->dict[Any,Any]: )->dict[Any,Any]:
job_dict = { job_dict = {
#TODO compress event? #TODO compress event?
@ -307,4 +337,4 @@ def create_job(job_type:str, event:dict[str,Any], source:dict[Any,Any]={}
JOB_REQUIREMENTS: event[EVENT_RULE].recipe.requirements JOB_REQUIREMENTS: event[EVENT_RULE].recipe.requirements
} }
return {**source, **job_dict} return {**extras, **job_dict}

View File

@ -11,7 +11,7 @@ import inspect
import sys import sys
from copy import deepcopy from copy import deepcopy
from typing import Any, Union from typing import Any, Union, Tuple
from core.correctness.vars import VALID_RECIPE_NAME_CHARS, \ from core.correctness.vars import VALID_RECIPE_NAME_CHARS, \
VALID_PATTERN_NAME_CHARS, VALID_RULE_NAME_CHARS, VALID_CHANNELS, \ VALID_PATTERN_NAME_CHARS, VALID_RULE_NAME_CHARS, VALID_CHANNELS, \
@ -323,8 +323,7 @@ class BaseHandler:
raise TypeError(msg) raise TypeError(msg)
return object.__new__(cls) return object.__new__(cls)
# TODO also implement something like me from conductor def valid_handle_criteria(self, event:dict[str,Any])->Tuple[bool,str]:
def valid_handle_criteria(self, event:dict[str,Any])->bool:
"""Function to determine given an event defintion, if this handler can """Function to determine given an event defintion, if this handler can
process it or not. Must be implemented by any child process.""" process it or not. Must be implemented by any child process."""
pass pass
@ -350,7 +349,7 @@ class BaseConductor:
raise TypeError(msg) raise TypeError(msg)
return object.__new__(cls) return object.__new__(cls)
def valid_execute_criteria(self, job:dict[str,Any])->bool: def valid_execute_criteria(self, job:dict[str,Any])->Tuple[bool,str]:
"""Function to determine given an job defintion, if this conductor can """Function to determine given an job defintion, if this conductor can
process it or not. Must be implemented by any child process.""" process it or not. Must be implemented by any child process."""
pass pass

View File

@ -10,13 +10,12 @@ import os
import sys import sys
import threading import threading
from inspect import signature
from multiprocessing import Pipe from multiprocessing import Pipe
from random import randrange from random import randrange
from typing import Any, Union from typing import Any, Union
from core.correctness.vars import DEBUG_WARNING, DEBUG_INFO, EVENT_TYPE, \ from core.correctness.vars import DEBUG_WARNING, DEBUG_INFO, EVENT_TYPE, \
VALID_CHANNELS, JOB_TYPE, JOB_ID, META_FILE VALID_CHANNELS, JOB_ID, META_FILE
from core.correctness.validation import setup_debugging, check_type, \ from core.correctness.validation import setup_debugging, check_type, \
valid_list valid_list
from core.functionality import print_debug, wait, read_yaml from core.functionality import print_debug, wait, read_yaml
@ -104,7 +103,7 @@ class MeowRunner:
valid_handlers = [] valid_handlers = []
for handler in self.handlers: for handler in self.handlers:
try: try:
valid = handler.valid_handle_criteria(event) valid, _ = handler.valid_handle_criteria(event)
if valid: if valid:
valid_handlers.append(handler) valid_handlers.append(handler)
except Exception as e: except Exception as e:
@ -155,7 +154,8 @@ class MeowRunner:
valid_conductors = [] valid_conductors = []
for conductor in self.conductors: for conductor in self.conductors:
try: try:
valid = conductor.valid_execute_criteria(job) valid, _ = \
conductor.valid_execute_criteria(job)
if valid: if valid:
valid_conductors.append(conductor) valid_conductors.append(conductor)
except Exception as e: except Exception as e:

View File

@ -25,7 +25,8 @@ from core.correctness.vars import VALID_RECIPE_NAME_CHARS, \
VALID_VARIABLE_NAME_CHARS, FILE_EVENTS, FILE_CREATE_EVENT, \ VALID_VARIABLE_NAME_CHARS, FILE_EVENTS, FILE_CREATE_EVENT, \
FILE_MODIFY_EVENT, FILE_MOVED_EVENT, DEBUG_INFO, EVENT_TYPE_WATCHDOG, \ FILE_MODIFY_EVENT, FILE_MOVED_EVENT, DEBUG_INFO, EVENT_TYPE_WATCHDOG, \
WATCHDOG_BASE, FILE_RETROACTIVE_EVENT, WATCHDOG_HASH, SHA256 WATCHDOG_BASE, FILE_RETROACTIVE_EVENT, WATCHDOG_HASH, SHA256
from core.functionality import print_debug, create_event, get_file_hash from core.functionality import print_debug, create_watchdog_event, \
get_file_hash, create_fake_watchdog_event
from core.meow import BasePattern, BaseMonitor, BaseRule, BaseRecipe, \ from core.meow import BasePattern, BaseMonitor, BaseRule, BaseRecipe, \
create_rule create_rule
@ -236,17 +237,11 @@ class WatchdogMonitor(BaseMonitor):
# If matched, the create a watchdog event # If matched, the create a watchdog event
if direct_hit or recursive_hit: if direct_hit or recursive_hit:
meow_event = create_event( meow_event = create_watchdog_event(
EVENT_TYPE_WATCHDOG,
event.src_path, event.src_path,
rule, rule,
{ self.base_dir,
WATCHDOG_BASE: self.base_dir, get_file_hash(event.src_path, SHA256)
WATCHDOG_HASH: get_file_hash(
event.src_path,
SHA256
)
}
) )
print_debug(self._print_target, self.debug_level, print_debug(self._print_target, self.debug_level,
f"Event at {src_path} of type {event_type} hit rule " f"Event at {src_path} of type {event_type} hit rule "
@ -534,11 +529,10 @@ class WatchdogMonitor(BaseMonitor):
# For each file create a fake event. # For each file create a fake event.
for globble in globbed: for globble in globbed:
meow_event = create_event( meow_event = create_fake_watchdog_event(
EVENT_TYPE_WATCHDOG,
globble, globble,
rule, rule,
{ WATCHDOG_BASE: self.base_dir } self.base_dir
) )
print_debug(self._print_target, self.debug_level, print_debug(self._print_target, self.debug_level,
f"Retroactive event for file at at {globble} hit rule " f"Retroactive event for file at at {globble} hit rule "

View File

@ -10,7 +10,7 @@ import itertools
import nbformat import nbformat
import sys import sys
from typing import Any from typing import Any, Tuple
from core.correctness.validation import check_type, valid_string, \ from core.correctness.validation import check_type, valid_string, \
valid_dict, valid_path, valid_existing_dir_path, setup_debugging, \ valid_dict, valid_path, valid_existing_dir_path, setup_debugging, \
@ -123,7 +123,7 @@ class PapermillHandler(BaseHandler):
yaml_dict[value[0]] = value[1] yaml_dict[value[0]] = value[1]
self.setup_job(event, yaml_dict) self.setup_job(event, yaml_dict)
def valid_handle_criteria(self, event:dict[str,Any])->bool: def valid_handle_criteria(self, event:dict[str,Any])->Tuple[bool,str]:
"""Function to determine given an event defintion, if this handler can """Function to determine given an event defintion, if this handler can
process it or not. This handler accepts events from watchdog with process it or not. This handler accepts events from watchdog with
jupyter notebook recipes.""" jupyter notebook recipes."""
@ -131,10 +131,10 @@ class PapermillHandler(BaseHandler):
valid_event(event) valid_event(event)
if type(event[EVENT_RULE].recipe) == JupyterNotebookRecipe \ if type(event[EVENT_RULE].recipe) == JupyterNotebookRecipe \
and event[EVENT_TYPE] == EVENT_TYPE_WATCHDOG: and event[EVENT_TYPE] == EVENT_TYPE_WATCHDOG:
return True return True, ""
except: except Exception as e:
pass pass
return False return False, str(e)
def _is_valid_handler_base(self, handler_base)->None: def _is_valid_handler_base(self, handler_base)->None:
@ -153,7 +153,7 @@ class PapermillHandler(BaseHandler):
meow_job = create_job( meow_job = create_job(
JOB_TYPE_PYTHON, JOB_TYPE_PYTHON,
event, event,
{ extras={
JOB_PARAMETERS:yaml_dict, JOB_PARAMETERS:yaml_dict,
JOB_HASH: event[WATCHDOG_HASH], JOB_HASH: event[WATCHDOG_HASH],
PYTHON_FUNC:job_func, PYTHON_FUNC:job_func,

View File

@ -10,7 +10,7 @@ import itertools
import nbformat import nbformat
import sys import sys
from typing import Any from typing import Any, Tuple
from core.correctness.validation import check_type, valid_string, \ from core.correctness.validation import check_type, valid_string, \
valid_dict, valid_event, valid_existing_dir_path, setup_debugging valid_dict, valid_event, valid_existing_dir_path, setup_debugging
@ -114,7 +114,7 @@ class PythonHandler(BaseHandler):
yaml_dict[value[0]] = value[1] yaml_dict[value[0]] = value[1]
self.setup_job(event, yaml_dict) self.setup_job(event, yaml_dict)
def valid_handle_criteria(self, event:dict[str,Any])->bool: def valid_handle_criteria(self, event:dict[str,Any])->Tuple[bool,str]:
"""Function to determine given an event defintion, if this handler can """Function to determine given an event defintion, if this handler can
process it or not. This handler accepts events from watchdog with process it or not. This handler accepts events from watchdog with
Python recipes""" Python recipes"""
@ -122,10 +122,10 @@ class PythonHandler(BaseHandler):
valid_event(event) valid_event(event)
if event[EVENT_TYPE] == EVENT_TYPE_WATCHDOG \ if event[EVENT_TYPE] == EVENT_TYPE_WATCHDOG \
and type(event[EVENT_RULE].recipe) == PythonRecipe: and type(event[EVENT_RULE].recipe) == PythonRecipe:
return True return True, ""
except: except Exception as e:
pass pass
return False return False, str(e)
def _is_valid_handler_base(self, handler_base)->None: def _is_valid_handler_base(self, handler_base)->None:
"""Validation check for 'handler_base' variable from main """Validation check for 'handler_base' variable from main
@ -143,7 +143,7 @@ class PythonHandler(BaseHandler):
meow_job = create_job( meow_job = create_job(
JOB_TYPE_PYTHON, JOB_TYPE_PYTHON,
event, event,
{ extras={
JOB_PARAMETERS:yaml_dict, JOB_PARAMETERS:yaml_dict,
JOB_HASH: event[WATCHDOG_HASH], JOB_HASH: event[WATCHDOG_HASH],
PYTHON_FUNC:job_func, PYTHON_FUNC:job_func,

View File

@ -6,8 +6,8 @@ from core.correctness.vars import JOB_TYPE_PYTHON, SHA256, EVENT_TYPE_WATCHDOG,
WATCHDOG_BASE, EVENT_RULE, WATCHDOG_HASH, JOB_PARAMETERS, JOB_HASH, \ WATCHDOG_BASE, EVENT_RULE, WATCHDOG_HASH, JOB_PARAMETERS, JOB_HASH, \
PYTHON_FUNC, PYTHON_OUTPUT_DIR, PYTHON_EXECUTION_BASE, JOB_ID, META_FILE, \ PYTHON_FUNC, PYTHON_OUTPUT_DIR, PYTHON_EXECUTION_BASE, JOB_ID, META_FILE, \
BASE_FILE, PARAMS_FILE, JOB_FILE, RESULT_FILE BASE_FILE, PARAMS_FILE, JOB_FILE, RESULT_FILE
from core.functionality import get_file_hash, create_event, create_job, \ from core.functionality import get_file_hash, create_watchdog_event, \
make_dir, write_yaml, write_notebook create_job, make_dir, write_yaml, write_notebook
from core.meow import create_rule from core.meow import create_rule
from conductors import LocalPythonConductor from conductors import LocalPythonConductor
from patterns import FileEventPattern from patterns import FileEventPattern
@ -69,17 +69,13 @@ class MeowTests(unittest.TestCase):
job_dict = create_job( job_dict = create_job(
JOB_TYPE_PYTHON, JOB_TYPE_PYTHON,
create_event( create_watchdog_event(
EVENT_TYPE_WATCHDOG,
file_path, file_path,
rule, rule,
{ TEST_MONITOR_BASE,
WATCHDOG_BASE: TEST_MONITOR_BASE, file_hash
EVENT_RULE: rule,
WATCHDOG_HASH: file_hash
}
), ),
{ extras={
JOB_PARAMETERS:params_dict, JOB_PARAMETERS:params_dict,
JOB_HASH: file_hash, JOB_HASH: file_hash,
PYTHON_FUNC:job_func, PYTHON_FUNC:job_func,
@ -146,17 +142,13 @@ class MeowTests(unittest.TestCase):
bad_job_dict = create_job( bad_job_dict = create_job(
JOB_TYPE_PYTHON, JOB_TYPE_PYTHON,
create_event( create_watchdog_event(
EVENT_TYPE_WATCHDOG,
file_path, file_path,
rule, rule,
{ TEST_MONITOR_BASE,
WATCHDOG_BASE: TEST_MONITOR_BASE, file_hash
EVENT_RULE: rule,
WATCHDOG_HASH: file_hash
}
), ),
{ extras={
JOB_PARAMETERS:params_dict, JOB_PARAMETERS:params_dict,
JOB_HASH: file_hash, JOB_HASH: file_hash,
PYTHON_FUNC:job_func, PYTHON_FUNC:job_func,
@ -178,17 +170,13 @@ class MeowTests(unittest.TestCase):
# Ensure execution can continue after one failed job # Ensure execution can continue after one failed job
good_job_dict = create_job( good_job_dict = create_job(
JOB_TYPE_PYTHON, JOB_TYPE_PYTHON,
create_event( create_watchdog_event(
EVENT_TYPE_WATCHDOG,
file_path, file_path,
rule, rule,
{ TEST_MONITOR_BASE,
WATCHDOG_BASE: TEST_MONITOR_BASE, file_hash
EVENT_RULE: rule,
WATCHDOG_HASH: file_hash
}
), ),
{ extras={
JOB_PARAMETERS:params_dict, JOB_PARAMETERS:params_dict,
JOB_HASH: file_hash, JOB_HASH: file_hash,
PYTHON_FUNC:job_func, PYTHON_FUNC:job_func,
@ -249,17 +237,13 @@ class MeowTests(unittest.TestCase):
job_dict = create_job( job_dict = create_job(
JOB_TYPE_PYTHON, JOB_TYPE_PYTHON,
create_event( create_watchdog_event(
EVENT_TYPE_WATCHDOG,
file_path, file_path,
rule, rule,
{ TEST_MONITOR_BASE,
WATCHDOG_BASE: TEST_MONITOR_BASE, file_hash
EVENT_RULE: rule,
WATCHDOG_HASH: file_hash
}
), ),
{ extras={
JOB_PARAMETERS:{ JOB_PARAMETERS:{
"extra":"extra", "extra":"extra",
"infile":file_path, "infile":file_path,

View File

@ -16,6 +16,7 @@ from core.correctness.vars import CHAR_LOWERCASE, CHAR_UPPERCASE, \
from core.functionality import generate_id, wait, get_file_hash, rmtree, \ from core.functionality import generate_id, wait, get_file_hash, rmtree, \
make_dir, parameterize_jupyter_notebook, create_event, create_job, \ make_dir, parameterize_jupyter_notebook, create_event, create_job, \
replace_keywords, write_yaml, write_notebook, read_yaml, read_notebook, \ replace_keywords, write_yaml, write_notebook, read_yaml, read_notebook, \
create_watchdog_event, create_fake_watchdog_event, \
KEYWORD_PATH, KEYWORD_REL_PATH, KEYWORD_DIR, KEYWORD_REL_DIR, \ KEYWORD_PATH, KEYWORD_REL_PATH, KEYWORD_DIR, KEYWORD_REL_DIR, \
KEYWORD_FILENAME, KEYWORD_PREFIX, KEYWORD_BASE, KEYWORD_EXTENSION, \ KEYWORD_FILENAME, KEYWORD_PREFIX, KEYWORD_BASE, KEYWORD_EXTENSION, \
KEYWORD_JOB KEYWORD_JOB
@ -266,7 +267,7 @@ class CorrectnessTests(unittest.TestCase):
self.assertEqual(event[EVENT_PATH], "path") self.assertEqual(event[EVENT_PATH], "path")
self.assertEqual(event[EVENT_RULE], rule) self.assertEqual(event[EVENT_RULE], rule)
event2 = create_event("test2", "path2", rule, {"a":1}) event2 = create_event("test2", "path2", rule, extras={"a":1})
self.assertEqual(type(event2), dict) self.assertEqual(type(event2), dict)
self.assertTrue(EVENT_TYPE in event2.keys()) self.assertTrue(EVENT_TYPE in event2.keys())
@ -298,7 +299,7 @@ class CorrectnessTests(unittest.TestCase):
EVENT_TYPE_WATCHDOG, EVENT_TYPE_WATCHDOG,
"file_path", "file_path",
rule, rule,
{ extras={
WATCHDOG_BASE: TEST_MONITOR_BASE, WATCHDOG_BASE: TEST_MONITOR_BASE,
EVENT_RULE: rule, EVENT_RULE: rule,
WATCHDOG_HASH: "file_hash" WATCHDOG_HASH: "file_hash"
@ -308,7 +309,7 @@ class CorrectnessTests(unittest.TestCase):
job_dict = create_job( job_dict = create_job(
JOB_TYPE_PYTHON, JOB_TYPE_PYTHON,
event, event,
{ extras={
JOB_PARAMETERS:{ JOB_PARAMETERS:{
"extra":"extra", "extra":"extra",
"infile":"file_path", "infile":"file_path",
@ -560,3 +561,101 @@ class CorrectnessTests(unittest.TestCase):
self.assertFalse(os.path.exists(os.path.join(TEST_MONITOR_BASE, "A"))) self.assertFalse(os.path.exists(os.path.join(TEST_MONITOR_BASE, "A")))
self.assertFalse(os.path.exists( self.assertFalse(os.path.exists(
os.path.join(TEST_MONITOR_BASE, "A", "B"))) os.path.join(TEST_MONITOR_BASE, "A", "B")))
def testCreateWatchdogEvent(self)->None:
pattern = FileEventPattern(
"pattern",
"file_path",
"recipe_one",
"infile",
parameters={
"extra":"A line from a test Pattern",
"outfile":"result_path"
})
recipe = JupyterNotebookRecipe(
"recipe_one", APPENDING_NOTEBOOK)
rule = create_rule(pattern, recipe)
with self.assertRaises(TypeError):
event = create_watchdog_event("path", rule)
event = create_watchdog_event("path", rule, "base", "hash")
self.assertEqual(type(event), dict)
self.assertEqual(len(event.keys()), 5)
self.assertTrue(EVENT_TYPE in event.keys())
self.assertTrue(EVENT_PATH in event.keys())
self.assertTrue(EVENT_RULE in event.keys())
self.assertTrue(WATCHDOG_BASE in event.keys())
self.assertTrue(WATCHDOG_HASH in event.keys())
self.assertEqual(event[EVENT_TYPE], EVENT_TYPE_WATCHDOG)
self.assertEqual(event[EVENT_PATH], "path")
self.assertEqual(event[EVENT_RULE], rule)
self.assertEqual(event[WATCHDOG_BASE], "base")
self.assertEqual(event[WATCHDOG_HASH], "hash")
event = create_watchdog_event(
"path2", rule, "base", "hash", extras={"a":1}
)
self.assertEqual(type(event), dict)
self.assertTrue(EVENT_TYPE in event.keys())
self.assertTrue(EVENT_PATH in event.keys())
self.assertTrue(EVENT_RULE in event.keys())
self.assertTrue(WATCHDOG_BASE in event.keys())
self.assertTrue(WATCHDOG_HASH in event.keys())
self.assertEqual(len(event.keys()), 6)
self.assertEqual(event[EVENT_TYPE], EVENT_TYPE_WATCHDOG)
self.assertEqual(event[EVENT_PATH], "path2")
self.assertEqual(event[EVENT_RULE], rule)
self.assertEqual(event["a"], 1)
self.assertEqual(event[WATCHDOG_BASE], "base")
self.assertEqual(event[WATCHDOG_HASH], "hash")
def testCreateFakeWatchdogEvent(self)->None:
pattern = FileEventPattern(
"pattern",
"file_path",
"recipe_one",
"infile",
parameters={
"extra":"A line from a test Pattern",
"outfile":"result_path"
})
recipe = JupyterNotebookRecipe(
"recipe_one", APPENDING_NOTEBOOK)
rule = create_rule(pattern, recipe)
with self.assertRaises(TypeError):
event = create_fake_watchdog_event("path", rule)
event = create_fake_watchdog_event("path", rule, "base")
self.assertEqual(type(event), dict)
self.assertEqual(len(event.keys()), 4)
self.assertTrue(EVENT_TYPE in event.keys())
self.assertTrue(EVENT_PATH in event.keys())
self.assertTrue(EVENT_RULE in event.keys())
self.assertTrue(WATCHDOG_BASE in event.keys())
self.assertEqual(event[EVENT_TYPE], EVENT_TYPE_WATCHDOG)
self.assertEqual(event[EVENT_PATH], "path")
self.assertEqual(event[EVENT_RULE], rule)
self.assertEqual(event[WATCHDOG_BASE], "base")
event = create_fake_watchdog_event(
"path2", rule, "base", extras={"a":1}
)
self.assertEqual(type(event), dict)
self.assertTrue(EVENT_TYPE in event.keys())
self.assertTrue(EVENT_PATH in event.keys())
self.assertTrue(EVENT_RULE in event.keys())
self.assertTrue(WATCHDOG_BASE in event.keys())
self.assertEqual(len(event.keys()), 5)
self.assertEqual(event[EVENT_TYPE], EVENT_TYPE_WATCHDOG)
self.assertEqual(event[EVENT_PATH], "path2")
self.assertEqual(event[EVENT_RULE], rule)
self.assertEqual(event["a"], 1)
self.assertEqual(event[WATCHDOG_BASE], "base")

View File

@ -1,7 +1,7 @@
import unittest import unittest
from typing import Any, Union from typing import Any, Union, Tuple
from core.meow import BasePattern, BaseRecipe, BaseRule, BaseMonitor, \ from core.meow import BasePattern, BaseRecipe, BaseRule, BaseMonitor, \
BaseHandler, BaseConductor, create_rules, create_rule BaseHandler, BaseConductor, create_rules, create_rule
@ -198,7 +198,8 @@ class MeowTests(unittest.TestCase):
pass pass
def _is_valid_inputs(self, inputs:Any)->None: def _is_valid_inputs(self, inputs:Any)->None:
pass pass
def valid_handle_criteria(self, event:dict[str,Any])->bool: def valid_handle_criteria(self, event:dict[str,Any]
)->Tuple[bool,str]:
pass pass
FullTestHandler() FullTestHandler()
@ -218,7 +219,8 @@ class MeowTests(unittest.TestCase):
def execute(self, job:dict[str,Any])->None: def execute(self, job:dict[str,Any])->None:
pass pass
def valid_execute_criteria(self, job:dict[str,Any])->bool: def valid_execute_criteria(self, job:dict[str,Any]
)->Tuple[bool,str]:
pass pass
FullTestConductor() FullTestConductor()

View File

@ -11,8 +11,8 @@ from core.correctness.vars import EVENT_TYPE, WATCHDOG_BASE, EVENT_RULE, \
PYTHON_OUTPUT_DIR, PYTHON_EXECUTION_BASE, META_FILE, BASE_FILE, \ PYTHON_OUTPUT_DIR, PYTHON_EXECUTION_BASE, META_FILE, BASE_FILE, \
PARAMS_FILE, JOB_FILE, RESULT_FILE PARAMS_FILE, JOB_FILE, RESULT_FILE
from core.correctness.validation import valid_job from core.correctness.validation import valid_job
from core.functionality import get_file_hash, create_job, create_event, \ from core.functionality import get_file_hash, create_job, \
make_dir, write_yaml, write_notebook, read_yaml create_watchdog_event, make_dir, write_yaml, write_notebook, read_yaml
from core.meow import create_rules, create_rule from core.meow import create_rules, create_rule
from patterns.file_event_pattern import FileEventPattern, SWEEP_START, \ from patterns.file_event_pattern import FileEventPattern, SWEEP_START, \
SWEEP_STOP, SWEEP_JUMP SWEEP_STOP, SWEEP_JUMP
@ -351,17 +351,13 @@ class JupyterNotebookTests(unittest.TestCase):
job_dict = create_job( job_dict = create_job(
JOB_TYPE_PYTHON, JOB_TYPE_PYTHON,
create_event( create_watchdog_event(
EVENT_TYPE_WATCHDOG,
file_path, file_path,
rule, rule,
{ TEST_MONITOR_BASE,
WATCHDOG_BASE: TEST_MONITOR_BASE, file_hash
EVENT_RULE: rule,
WATCHDOG_HASH: file_hash
}
), ),
{ extras={
JOB_PARAMETERS:params_dict, JOB_PARAMETERS:params_dict,
JOB_HASH: file_hash, JOB_HASH: file_hash,
PYTHON_FUNC:job_func, PYTHON_FUNC:job_func,

View File

@ -9,10 +9,11 @@ from typing import Any, Union
from core.correctness.validation import check_type, check_implementation, \ from core.correctness.validation import check_type, check_implementation, \
valid_string, valid_dict, valid_list, valid_existing_file_path, \ valid_string, valid_dict, valid_list, valid_existing_file_path, \
valid_existing_dir_path, valid_non_existing_path, valid_event, valid_job, \ valid_existing_dir_path, valid_non_existing_path, valid_event, valid_job, \
setup_debugging setup_debugging, valid_watchdog_event
from core.correctness.vars import VALID_NAME_CHARS, SHA256, EVENT_TYPE, \ from core.correctness.vars import VALID_NAME_CHARS, SHA256, EVENT_TYPE, \
EVENT_PATH, JOB_TYPE, JOB_EVENT, JOB_ID, JOB_PATTERN, JOB_RECIPE, \ EVENT_PATH, JOB_TYPE, JOB_EVENT, JOB_ID, JOB_PATTERN, JOB_RECIPE, \
JOB_RULE, JOB_STATUS, JOB_CREATE_TIME, EVENT_RULE JOB_RULE, JOB_STATUS, JOB_CREATE_TIME, EVENT_RULE, WATCHDOG_BASE, \
WATCHDOG_HASH
from core.functionality import make_dir from core.functionality import make_dir
from shared import setup, teardown, TEST_MONITOR_BASE from shared import setup, teardown, TEST_MONITOR_BASE
@ -303,4 +304,36 @@ class CorrectnessTests(unittest.TestCase):
with self.assertRaises(TypeError): with self.assertRaises(TypeError):
setup_debugging(stream, "1") setup_debugging(stream, "1")
#TODO test watchdog event dict #Test watchdog event dict
def testWatchdogEventValidation(self)->None:
valid_watchdog_event({
EVENT_TYPE: "test",
EVENT_PATH: "path",
EVENT_RULE: "rule",
WATCHDOG_HASH: "hash",
WATCHDOG_BASE: "base"
})
with self.assertRaises(KeyError):
valid_watchdog_event({
EVENT_TYPE: "test",
EVENT_PATH: "path",
EVENT_RULE: "rule"
})
with self.assertRaises(KeyError):
valid_watchdog_event({
EVENT_TYPE: "anything",
EVENT_PATH: "path",
EVENT_RULE: "rule",
"a": 1
})
with self.assertRaises(KeyError):
valid_event({EVENT_TYPE: "test"})
with self.assertRaises(KeyError):
valid_event({"EVENT_TYPE": "test"})
with self.assertRaises(KeyError):
valid_event({})