added interaction for monitor state updating
This commit is contained in:
85
core/meow.py
85
core/meow.py
@ -130,14 +130,29 @@ class BaseRule:
|
|||||||
|
|
||||||
|
|
||||||
class BaseMonitor:
|
class BaseMonitor:
|
||||||
rules: dict[str, BaseRule]
|
_patterns: dict[str, BasePattern]
|
||||||
|
_recipes: dict[str, BaseRecipe]
|
||||||
|
_rules: dict[str, BaseRule]
|
||||||
to_runner: VALID_CHANNELS
|
to_runner: VALID_CHANNELS
|
||||||
def __init__(self, rules:dict[str,BaseRule])->None:
|
def __init__(self, patterns:dict[str,BasePattern], recipes:dict[str,BaseRecipe])->None:
|
||||||
check_implementation(type(self).start, BaseMonitor)
|
check_implementation(type(self).start, BaseMonitor)
|
||||||
check_implementation(type(self).stop, BaseMonitor)
|
check_implementation(type(self).stop, BaseMonitor)
|
||||||
check_implementation(type(self)._is_valid_rules, BaseMonitor)
|
check_implementation(type(self)._is_valid_patterns, BaseMonitor)
|
||||||
self._is_valid_rules(rules)
|
self._is_valid_patterns(patterns)
|
||||||
self.rules = rules
|
check_implementation(type(self)._is_valid_recipes, BaseMonitor)
|
||||||
|
self._is_valid_recipes(recipes)
|
||||||
|
check_implementation(type(self).add_pattern, BaseMonitor)
|
||||||
|
check_implementation(type(self).update_pattern, BaseMonitor)
|
||||||
|
check_implementation(type(self).remove_pattern, BaseMonitor)
|
||||||
|
check_implementation(type(self).get_patterns, BaseMonitor)
|
||||||
|
check_implementation(type(self).add_recipe, BaseMonitor)
|
||||||
|
check_implementation(type(self).update_recipe, BaseMonitor)
|
||||||
|
check_implementation(type(self).remove_recipe, BaseMonitor)
|
||||||
|
check_implementation(type(self).get_recipes, BaseMonitor)
|
||||||
|
check_implementation(type(self).get_rules, BaseMonitor)
|
||||||
|
self._patterns = patterns
|
||||||
|
self._recipes = recipes
|
||||||
|
self._rules = create_rules(patterns, recipes)
|
||||||
|
|
||||||
def __new__(cls, *args, **kwargs):
|
def __new__(cls, *args, **kwargs):
|
||||||
if cls is BaseMonitor:
|
if cls is BaseMonitor:
|
||||||
@ -145,7 +160,10 @@ class BaseMonitor:
|
|||||||
raise TypeError(msg)
|
raise TypeError(msg)
|
||||||
return object.__new__(cls)
|
return object.__new__(cls)
|
||||||
|
|
||||||
def _is_valid_rules(self, rules:dict[str,BaseRule])->None:
|
def _is_valid_patterns(self, patterns:dict[str,BasePattern])->None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def _is_valid_recipes(self, recipes:dict[str,BaseRecipe])->None:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def start(self)->None:
|
def start(self)->None:
|
||||||
@ -154,6 +172,33 @@ class BaseMonitor:
|
|||||||
def stop(self)->None:
|
def stop(self)->None:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def add_pattern(self, pattern:BasePattern)->None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def update_pattern(self, pattern:BasePattern)->None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def remove_pattern(self, pattern:Union[str,BasePattern])->None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def get_patterns(self)->None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def add_recipe(self, recipe:BaseRecipe)->None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def update_recipe(self, recipe:BaseRecipe)->None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def remove_recipe(self, recipe:Union[str,BaseRecipe])->None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def get_recipes(self)->None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def get_rules(self)->None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class BaseHandler:
|
class BaseHandler:
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
@ -172,7 +217,6 @@ class BaseHandler:
|
|||||||
def handle(self, event:Any)->None:
|
def handle(self, event:Any)->None:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def create_rules(patterns:Union[dict[str,BasePattern],list[BasePattern]],
|
def create_rules(patterns:Union[dict[str,BasePattern],list[BasePattern]],
|
||||||
recipes:Union[dict[str,BaseRecipe],list[BaseRecipe]],
|
recipes:Union[dict[str,BaseRecipe],list[BaseRecipe]],
|
||||||
new_rules:list[BaseRule]=[])->dict[str,BaseRule]:
|
new_rules:list[BaseRule]=[])->dict[str,BaseRule]:
|
||||||
@ -204,22 +248,31 @@ def create_rules(patterns:Union[dict[str,BasePattern],list[BasePattern]],
|
|||||||
"Recipe dictionaries must be keyed with the name of the "
|
"Recipe dictionaries must be keyed with the name of the "
|
||||||
"Recipe.")
|
"Recipe.")
|
||||||
|
|
||||||
|
generated_rules = {}
|
||||||
|
for pattern in patterns.values():
|
||||||
|
if pattern.recipe in recipes:
|
||||||
|
rule = create_rule(pattern, recipes[pattern.recipe])
|
||||||
|
generated_rules[rule.name] = rule
|
||||||
|
return generated_rules
|
||||||
|
|
||||||
|
def create_rule(pattern:BasePattern, recipe:BaseRecipe,
|
||||||
|
new_rules:list[BaseRule]=[])->BaseRule:
|
||||||
|
check_type(pattern, BasePattern)
|
||||||
|
check_type(recipe, BaseRecipe)
|
||||||
|
valid_list(new_rules, BaseRule, min_length=0)
|
||||||
|
|
||||||
# Imported here to avoid circular imports at top of file
|
# Imported here to avoid circular imports at top of file
|
||||||
import rules
|
import rules
|
||||||
rules = {}
|
|
||||||
all_rules ={(r.pattern_type, r.recipe_type):r for r in [r[1] \
|
all_rules ={(r.pattern_type, r.recipe_type):r for r in [r[1] \
|
||||||
for r in inspect.getmembers(sys.modules["rules"], inspect.isclass) \
|
for r in inspect.getmembers(sys.modules["rules"], inspect.isclass) \
|
||||||
if (issubclass(r[1], BaseRule))]}
|
if (issubclass(r[1], BaseRule))]}
|
||||||
|
|
||||||
for pattern in patterns.values():
|
key = (type(pattern).__name__, type(recipe).__name__)
|
||||||
if pattern.recipe in recipes:
|
|
||||||
key = (type(pattern).__name__,
|
|
||||||
type(recipes[pattern.recipe]).__name__)
|
|
||||||
if (key) in all_rules:
|
if (key) in all_rules:
|
||||||
rule = all_rules[key](
|
return all_rules[key](
|
||||||
generate_id(prefix="Rule_"),
|
generate_id(prefix="Rule_"),
|
||||||
pattern,
|
pattern,
|
||||||
recipes[pattern.recipe]
|
recipe
|
||||||
)
|
)
|
||||||
rules[rule.name] = rule
|
raise TypeError(f"No valid rule for Pattern '{pattern}' and Recipe "
|
||||||
return rules
|
f"'{recipe}' could be found.")
|
||||||
|
@ -4,10 +4,11 @@ import threading
|
|||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
from copy import deepcopy
|
||||||
from fnmatch import translate
|
from fnmatch import translate
|
||||||
from re import match
|
from re import match
|
||||||
from time import time, sleep
|
from time import time, sleep
|
||||||
from typing import Any
|
from typing import Any, Union
|
||||||
from watchdog.observers import Observer
|
from watchdog.observers import Observer
|
||||||
from watchdog.events import PatternMatchingEventHandler
|
from watchdog.events import PatternMatchingEventHandler
|
||||||
|
|
||||||
@ -19,7 +20,8 @@ from core.correctness.vars import VALID_RECIPE_NAME_CHARS, \
|
|||||||
FILE_MODIFY_EVENT, FILE_MOVED_EVENT, DEBUG_INFO, WATCHDOG_TYPE, \
|
FILE_MODIFY_EVENT, FILE_MOVED_EVENT, DEBUG_INFO, WATCHDOG_TYPE, \
|
||||||
WATCHDOG_SRC, WATCHDOG_RULE, WATCHDOG_BASE, FILE_RETROACTIVE_EVENT
|
WATCHDOG_SRC, WATCHDOG_RULE, WATCHDOG_BASE, FILE_RETROACTIVE_EVENT
|
||||||
from core.functionality import print_debug, create_event
|
from core.functionality import print_debug, create_event
|
||||||
from core.meow import BasePattern, BaseMonitor, BaseRule
|
from core.meow import BasePattern, BaseMonitor, BaseRule, BaseRecipe, \
|
||||||
|
create_rule
|
||||||
|
|
||||||
_DEFAULT_MASK = [
|
_DEFAULT_MASK = [
|
||||||
FILE_CREATE_EVENT,
|
FILE_CREATE_EVENT,
|
||||||
@ -124,16 +126,20 @@ class WatchdogMonitor(BaseMonitor):
|
|||||||
base_dir:str
|
base_dir:str
|
||||||
debug_level:int
|
debug_level:int
|
||||||
_print_target:Any
|
_print_target:Any
|
||||||
|
_patterns_lock:threading.Lock
|
||||||
|
_recipes_lock:threading.Lock
|
||||||
_rules_lock:threading.Lock
|
_rules_lock:threading.Lock
|
||||||
|
|
||||||
def __init__(self, base_dir:str, rules:dict[str, BaseRule],
|
def __init__(self, base_dir:str, patterns:dict[str,FileEventPattern],
|
||||||
autostart=False, settletime:int=1, print:Any=sys.stdout,
|
recipes:dict[str,BaseRecipe], autostart=False, settletime:int=1,
|
||||||
logging:int=0)->None:
|
print:Any=sys.stdout, logging:int=0)->None:
|
||||||
super().__init__(rules)
|
super().__init__(patterns, recipes)
|
||||||
self._is_valid_base_dir(base_dir)
|
self._is_valid_base_dir(base_dir)
|
||||||
self.base_dir = base_dir
|
self.base_dir = base_dir
|
||||||
check_type(settletime, int)
|
check_type(settletime, int)
|
||||||
self._print_target, self.debug_level = setup_debugging(print, logging)
|
self._print_target, self.debug_level = setup_debugging(print, logging)
|
||||||
|
self._patterns_lock = threading.Lock()
|
||||||
|
self._recipes_lock = threading.Lock()
|
||||||
self._rules_lock = threading.Lock()
|
self._rules_lock = threading.Lock()
|
||||||
self.event_handler = WatchdogEventHandler(self, settletime=settletime)
|
self.event_handler = WatchdogEventHandler(self, settletime=settletime)
|
||||||
self.monitor = Observer()
|
self.monitor = Observer()
|
||||||
@ -170,7 +176,7 @@ class WatchdogMonitor(BaseMonitor):
|
|||||||
|
|
||||||
self._rules_lock.acquire()
|
self._rules_lock.acquire()
|
||||||
try:
|
try:
|
||||||
for rule in self.rules.values():
|
for rule in self._rules.values():
|
||||||
|
|
||||||
if event_type not in rule.pattern.event_mask:
|
if event_type not in rule.pattern.event_mask:
|
||||||
continue
|
continue
|
||||||
@ -199,19 +205,210 @@ class WatchdogMonitor(BaseMonitor):
|
|||||||
|
|
||||||
self._rules_lock.release()
|
self._rules_lock.release()
|
||||||
|
|
||||||
|
def add_pattern(self, pattern: FileEventPattern) -> None:
|
||||||
|
check_type(pattern, FileEventPattern)
|
||||||
|
self._patterns_lock.acquire()
|
||||||
|
try:
|
||||||
|
if pattern.name in self._patterns:
|
||||||
|
raise KeyError(f"An entry for Pattern '{pattern.name}' already "
|
||||||
|
"exists. Do you intend to update instead?")
|
||||||
|
self._patterns[pattern.name] = pattern
|
||||||
|
except Exception as e:
|
||||||
|
self._patterns_lock.release()
|
||||||
|
raise Exception(e)
|
||||||
|
self._patterns_lock.release()
|
||||||
|
|
||||||
|
self._identify_new_rules(new_pattern=pattern)
|
||||||
|
|
||||||
|
def update_pattern(self, pattern: FileEventPattern) -> None:
|
||||||
|
check_type(pattern, FileEventPattern)
|
||||||
|
self.remove_pattern(pattern.name)
|
||||||
|
self.add_pattern(pattern)
|
||||||
|
|
||||||
|
def remove_pattern(self, pattern: Union[str, FileEventPattern]) -> None:
|
||||||
|
check_type(pattern, str, alt_types=[FileEventPattern])
|
||||||
|
lookup_key = pattern
|
||||||
|
if type(lookup_key) is FileEventPattern:
|
||||||
|
lookup_key = pattern.name
|
||||||
|
self._patterns_lock.acquire()
|
||||||
|
try:
|
||||||
|
if lookup_key not in self._patterns:
|
||||||
|
raise KeyError(f"Cannot remote Pattern '{lookup_key}' as it "
|
||||||
|
"does not already exist")
|
||||||
|
self._patterns.pop(lookup_key)
|
||||||
|
except Exception as e:
|
||||||
|
self._patterns_lock.release()
|
||||||
|
raise Exception(e)
|
||||||
|
self._patterns_lock.release()
|
||||||
|
|
||||||
|
self._identify_lost_rules(lost_pattern=pattern.name)
|
||||||
|
|
||||||
|
def get_patterns(self) -> None:
|
||||||
|
to_return = {}
|
||||||
|
self._patterns_lock.acquire()
|
||||||
|
try:
|
||||||
|
to_return = deepcopy(self._patterns)
|
||||||
|
except Exception as e:
|
||||||
|
self._patterns_lock.release()
|
||||||
|
raise Exception(e)
|
||||||
|
self._patterns_lock.release()
|
||||||
|
return to_return
|
||||||
|
|
||||||
|
def add_recipe(self, recipe: BaseRecipe) -> None:
|
||||||
|
check_type(recipe, BaseRecipe)
|
||||||
|
self._recipes_lock.acquire()
|
||||||
|
try:
|
||||||
|
if recipe.name in self._recipes:
|
||||||
|
raise KeyError(f"An entry for Recipe '{recipe.name}' already "
|
||||||
|
"exists. Do you intend to update instead?")
|
||||||
|
self._recipes[recipe.name] = recipe
|
||||||
|
except Exception as e:
|
||||||
|
self._recipes_lock.release()
|
||||||
|
raise Exception(e)
|
||||||
|
self._recipes_lock.release()
|
||||||
|
|
||||||
|
self._identify_new_rules(new_recipe=recipe)
|
||||||
|
|
||||||
|
def update_recipe(self, recipe: BaseRecipe) -> None:
|
||||||
|
check_type(recipe, BaseRecipe)
|
||||||
|
self.remove_recipe(recipe.name)
|
||||||
|
self.add_recipe(recipe)
|
||||||
|
|
||||||
|
def remove_recipe(self, recipe: Union[str, BaseRecipe]) -> None:
|
||||||
|
check_type(recipe, str, alt_types=[BaseRecipe])
|
||||||
|
lookup_key = recipe
|
||||||
|
if type(lookup_key) is BaseRecipe:
|
||||||
|
lookup_key = recipe.name
|
||||||
|
self._recipes_lock.acquire()
|
||||||
|
try:
|
||||||
|
if lookup_key not in self._recipes:
|
||||||
|
raise KeyError(f"Cannot remote Recipe '{lookup_key}' as it "
|
||||||
|
"does not already exist")
|
||||||
|
self._recipes.pop(lookup_key)
|
||||||
|
except Exception as e:
|
||||||
|
self._recipes_lock.release()
|
||||||
|
raise Exception(e)
|
||||||
|
self._recipes_lock.release()
|
||||||
|
|
||||||
|
self._identify_lost_rules(lost_recipe=recipe.name)
|
||||||
|
|
||||||
|
def get_recipes(self) -> None:
|
||||||
|
to_return = {}
|
||||||
|
self._recipes_lock.acquire()
|
||||||
|
try:
|
||||||
|
to_return = deepcopy(self._recipes)
|
||||||
|
except Exception as e:
|
||||||
|
self._recipes_lock.release()
|
||||||
|
raise Exception(e)
|
||||||
|
self._recipes_lock.release()
|
||||||
|
return to_return
|
||||||
|
|
||||||
|
def get_rules(self) -> None:
|
||||||
|
to_return = {}
|
||||||
|
self._rules_lock.acquire()
|
||||||
|
try:
|
||||||
|
to_return = deepcopy(self._rules)
|
||||||
|
except Exception as e:
|
||||||
|
self._rules_lock.release()
|
||||||
|
raise Exception(e)
|
||||||
|
self._rules_lock.release()
|
||||||
|
return to_return
|
||||||
|
|
||||||
|
def _identify_new_rules(self, new_pattern:FileEventPattern=None,
|
||||||
|
new_recipe:BaseRecipe=None)->None:
|
||||||
|
|
||||||
|
if new_pattern:
|
||||||
|
self._patterns_lock.acquire()
|
||||||
|
self._recipes_lock.acquire()
|
||||||
|
try:
|
||||||
|
if new_pattern.name not in self._patterns:
|
||||||
|
self._patterns_lock.release()
|
||||||
|
self._recipes_lock.release()
|
||||||
|
return
|
||||||
|
if new_pattern.recipe in self._recipes:
|
||||||
|
self._create_new_rule(
|
||||||
|
new_pattern,
|
||||||
|
self._recipes[new_pattern.recipe],
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
self._patterns_lock.release()
|
||||||
|
self._recipes_lock.release()
|
||||||
|
raise Exception(e)
|
||||||
|
self._patterns_lock.release()
|
||||||
|
self._recipes_lock.release()
|
||||||
|
|
||||||
|
if new_recipe:
|
||||||
|
self._patterns_lock.acquire()
|
||||||
|
self._patterns_lock.acquire()
|
||||||
|
try:
|
||||||
|
if new_recipe.name not in self._recipes:
|
||||||
|
self._patterns_lock.release()
|
||||||
|
self._recipes_lock.release()
|
||||||
|
return
|
||||||
|
for pattern in self._patterns.values():
|
||||||
|
if pattern.recipe == new_recipe.name:
|
||||||
|
self._create_new_rule(
|
||||||
|
pattern,
|
||||||
|
new_recipe,
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
self._patterns_lock.release()
|
||||||
|
self._recipes_lock.release()
|
||||||
|
raise Exception(e)
|
||||||
|
self._patterns_lock.release()
|
||||||
|
self._recipes_lock.release()
|
||||||
|
|
||||||
|
def _identify_lost_rules(self, lost_pattern:str, lost_recipe:str)->None:
|
||||||
|
to_delete = []
|
||||||
|
self._rules_lock.acquire()
|
||||||
|
try:
|
||||||
|
for name, rule in self._rules.items():
|
||||||
|
if lost_pattern and rule.pattern.name == lost_pattern:
|
||||||
|
to_delete.append(name)
|
||||||
|
if lost_recipe and rule.recipe.name == lost_recipe:
|
||||||
|
to_delete.append(name)
|
||||||
|
for delete in to_delete:
|
||||||
|
if delete in self._rules.keys():
|
||||||
|
self._rules.pop(delete)
|
||||||
|
except Exception as e:
|
||||||
|
self._rules_lock.release()
|
||||||
|
raise Exception(e)
|
||||||
|
self._rules_lock.release()
|
||||||
|
|
||||||
|
def _create_new_rule(self, pattern:FileEventPattern, recipe:BaseRecipe)->None:
|
||||||
|
rule = create_rule(pattern, recipe)
|
||||||
|
self._rules_lock.acquire()
|
||||||
|
try:
|
||||||
|
if rule.name in self._rules:
|
||||||
|
raise KeyError("Cannot create Rule with name of "
|
||||||
|
f"'{rule.name}' as already in use")
|
||||||
|
self._rules[rule.name] = rule
|
||||||
|
except Exception as e:
|
||||||
|
self._rules_lock.release()
|
||||||
|
raise Exception(e)
|
||||||
|
self._rules_lock.release()
|
||||||
|
|
||||||
|
self._apply_retroactive_rule(rule)
|
||||||
|
|
||||||
def _is_valid_base_dir(self, base_dir:str)->None:
|
def _is_valid_base_dir(self, base_dir:str)->None:
|
||||||
valid_existing_dir_path(base_dir)
|
valid_existing_dir_path(base_dir)
|
||||||
|
|
||||||
def _is_valid_rules(self, rules:dict[str, BaseRule])->None:
|
def _is_valid_patterns(self, patterns:dict[str,FileEventPattern])->None:
|
||||||
valid_dict(rules, str, BaseRule, min_length=0, strict=False)
|
valid_dict(patterns, str, FileEventPattern, min_length=0, strict=False)
|
||||||
|
|
||||||
|
def _is_valid_recipes(self, recipes:dict[str,BaseRecipe])->None:
|
||||||
|
valid_dict(recipes, str, BaseRecipe, min_length=0, strict=False)
|
||||||
|
|
||||||
def _apply_retroactive_rules(self)->None:
|
def _apply_retroactive_rules(self)->None:
|
||||||
for rule in self.rules.values():
|
for rule in self._rules.values():
|
||||||
self._apply_retroactive_rule(rule)
|
self._apply_retroactive_rule(rule)
|
||||||
|
|
||||||
def _apply_retroactive_rule(self, rule:BaseRule)->None:
|
def _apply_retroactive_rule(self, rule:BaseRule)->None:
|
||||||
self._rules_lock.acquire()
|
self._rules_lock.acquire()
|
||||||
try:
|
try:
|
||||||
|
if rule.name not in self._rules:
|
||||||
|
self._rules_lock.release()
|
||||||
|
return
|
||||||
if FILE_RETROACTIVE_EVENT in rule.pattern.event_mask:
|
if FILE_RETROACTIVE_EVENT in rule.pattern.event_mask:
|
||||||
|
|
||||||
testing_path = os.path.join(self.base_dir, rule.pattern.triggering_path)
|
testing_path = os.path.join(self.base_dir, rule.pattern.triggering_path)
|
||||||
|
@ -4,7 +4,7 @@ import os
|
|||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from multiprocessing import Pipe
|
from multiprocessing import Pipe
|
||||||
from typing import Any
|
from typing import Any, Union
|
||||||
|
|
||||||
from core.correctness.vars import TEST_HANDLER_BASE, TEST_JOB_OUTPUT, \
|
from core.correctness.vars import TEST_HANDLER_BASE, TEST_JOB_OUTPUT, \
|
||||||
TEST_MONITOR_BASE, BAREBONES_NOTEBOOK, WATCHDOG_BASE, WATCHDOG_RULE, \
|
TEST_MONITOR_BASE, BAREBONES_NOTEBOOK, WATCHDOG_BASE, WATCHDOG_RULE, \
|
||||||
@ -131,24 +131,42 @@ class MeowTests(unittest.TestCase):
|
|||||||
|
|
||||||
def testBaseMonitor(self)->None:
|
def testBaseMonitor(self)->None:
|
||||||
with self.assertRaises(TypeError):
|
with self.assertRaises(TypeError):
|
||||||
BaseMonitor("")
|
BaseMonitor({}, {})
|
||||||
|
|
||||||
class TestMonitor(BaseMonitor):
|
class TestMonitor(BaseMonitor):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
with self.assertRaises(NotImplementedError):
|
with self.assertRaises(NotImplementedError):
|
||||||
TestMonitor("")
|
TestMonitor({}, {})
|
||||||
|
|
||||||
class FullTestMonitor(BaseMonitor):
|
class FullTestMonitor(BaseMonitor):
|
||||||
def start(self):
|
def start(self):
|
||||||
pass
|
pass
|
||||||
def stop(self):
|
def stop(self):
|
||||||
pass
|
pass
|
||||||
def _is_valid_to_runner(self, to_runner:Any)->None:
|
def _is_valid_patterns(self, patterns:dict[str,BasePattern])->None:
|
||||||
pass
|
pass
|
||||||
def _is_valid_rules(self, rules:Any)->None:
|
def _is_valid_recipes(self, recipes:dict[str,BaseRecipe])->None:
|
||||||
pass
|
pass
|
||||||
FullTestMonitor("")
|
def add_pattern(self, pattern:BasePattern)->None:
|
||||||
|
pass
|
||||||
|
def update_pattern(self, pattern:BasePattern)->None:
|
||||||
|
pass
|
||||||
|
def remove_pattern(self, pattern:Union[str,BasePattern])->None:
|
||||||
|
pass
|
||||||
|
def get_patterns(self)->None:
|
||||||
|
pass
|
||||||
|
def add_recipe(self, recipe:BaseRecipe)->None:
|
||||||
|
pass
|
||||||
|
def update_recipe(self, recipe:BaseRecipe)->None:
|
||||||
|
pass
|
||||||
|
def remove_recipe(self, recipe:Union[str,BaseRecipe])->None:
|
||||||
|
pass
|
||||||
|
def get_recipes(self)->None:
|
||||||
|
pass
|
||||||
|
def get_rules(self)->None:
|
||||||
|
pass
|
||||||
|
FullTestMonitor({}, {})
|
||||||
|
|
||||||
def testMonitoring(self)->None:
|
def testMonitoring(self)->None:
|
||||||
pattern_one = FileEventPattern(
|
pattern_one = FileEventPattern(
|
||||||
@ -163,20 +181,21 @@ class MeowTests(unittest.TestCase):
|
|||||||
recipes = {
|
recipes = {
|
||||||
recipe.name: recipe,
|
recipe.name: recipe,
|
||||||
}
|
}
|
||||||
rules = create_rules(patterns, recipes)
|
|
||||||
|
|
||||||
rule = rules[list(rules.keys())[0]]
|
|
||||||
|
|
||||||
monitor_debug_stream = io.StringIO("")
|
monitor_debug_stream = io.StringIO("")
|
||||||
|
|
||||||
wm = WatchdogMonitor(
|
wm = WatchdogMonitor(
|
||||||
TEST_MONITOR_BASE,
|
TEST_MONITOR_BASE,
|
||||||
rules,
|
patterns,
|
||||||
|
recipes,
|
||||||
print=monitor_debug_stream,
|
print=monitor_debug_stream,
|
||||||
logging=3,
|
logging=3,
|
||||||
settletime=1
|
settletime=1
|
||||||
)
|
)
|
||||||
|
|
||||||
|
rules = wm.get_rules()
|
||||||
|
rule = rules[list(rules.keys())[0]]
|
||||||
|
|
||||||
from_monitor_reader, from_monitor_writer = Pipe()
|
from_monitor_reader, from_monitor_writer = Pipe()
|
||||||
wm.to_runner = from_monitor_writer
|
wm.to_runner = from_monitor_writer
|
||||||
|
|
||||||
@ -225,9 +244,6 @@ class MeowTests(unittest.TestCase):
|
|||||||
recipes = {
|
recipes = {
|
||||||
recipe.name: recipe,
|
recipe.name: recipe,
|
||||||
}
|
}
|
||||||
rules = create_rules(patterns, recipes)
|
|
||||||
|
|
||||||
rule = rules[list(rules.keys())[0]]
|
|
||||||
|
|
||||||
start_dir = os.path.join(TEST_MONITOR_BASE, "start")
|
start_dir = os.path.join(TEST_MONITOR_BASE, "start")
|
||||||
make_dir(start_dir)
|
make_dir(start_dir)
|
||||||
@ -241,12 +257,16 @@ class MeowTests(unittest.TestCase):
|
|||||||
|
|
||||||
wm = WatchdogMonitor(
|
wm = WatchdogMonitor(
|
||||||
TEST_MONITOR_BASE,
|
TEST_MONITOR_BASE,
|
||||||
rules,
|
patterns,
|
||||||
|
recipes,
|
||||||
print=monitor_debug_stream,
|
print=monitor_debug_stream,
|
||||||
logging=3,
|
logging=3,
|
||||||
settletime=1
|
settletime=1
|
||||||
)
|
)
|
||||||
|
|
||||||
|
rules = wm.get_rules()
|
||||||
|
rule = rules[list(rules.keys())[0]]
|
||||||
|
|
||||||
from_monitor_reader, from_monitor_writer = Pipe()
|
from_monitor_reader, from_monitor_writer = Pipe()
|
||||||
wm.to_runner = from_monitor_writer
|
wm.to_runner = from_monitor_writer
|
||||||
|
|
||||||
|
@ -147,7 +147,7 @@ class CorrectnessTests(unittest.TestCase):
|
|||||||
|
|
||||||
def testWatchdogMonitorMinimum(self)->None:
|
def testWatchdogMonitorMinimum(self)->None:
|
||||||
from_monitor = Pipe()
|
from_monitor = Pipe()
|
||||||
WatchdogMonitor(TEST_MONITOR_BASE, {}, from_monitor[1])
|
WatchdogMonitor(TEST_MONITOR_BASE, {}, {}, from_monitor[1])
|
||||||
|
|
||||||
def testWatchdogMonitorEventIdentificaion(self)->None:
|
def testWatchdogMonitorEventIdentificaion(self)->None:
|
||||||
from_monitor_reader, from_monitor_writer = Pipe()
|
from_monitor_reader, from_monitor_writer = Pipe()
|
||||||
@ -163,11 +163,12 @@ class CorrectnessTests(unittest.TestCase):
|
|||||||
recipes = {
|
recipes = {
|
||||||
recipe.name: recipe,
|
recipe.name: recipe,
|
||||||
}
|
}
|
||||||
rules = create_rules(patterns, recipes)
|
|
||||||
|
|
||||||
wm = WatchdogMonitor(TEST_MONITOR_BASE, rules)
|
wm = WatchdogMonitor(TEST_MONITOR_BASE, patterns, recipes)
|
||||||
wm.to_runner = from_monitor_writer
|
wm.to_runner = from_monitor_writer
|
||||||
|
|
||||||
|
rules = wm.get_rules()
|
||||||
|
|
||||||
self.assertEqual(len(rules), 1)
|
self.assertEqual(len(rules), 1)
|
||||||
rule = rules[list(rules.keys())[0]]
|
rule = rules[list(rules.keys())[0]]
|
||||||
|
|
||||||
|
@ -44,7 +44,6 @@ class MeowTests(unittest.TestCase):
|
|||||||
recipes = {
|
recipes = {
|
||||||
recipe.name: recipe,
|
recipe.name: recipe,
|
||||||
}
|
}
|
||||||
rules = create_rules(patterns, recipes)
|
|
||||||
|
|
||||||
monitor_debug_stream = io.StringIO("")
|
monitor_debug_stream = io.StringIO("")
|
||||||
handler_debug_stream = io.StringIO("")
|
handler_debug_stream = io.StringIO("")
|
||||||
@ -52,7 +51,8 @@ class MeowTests(unittest.TestCase):
|
|||||||
runner = MeowRunner(
|
runner = MeowRunner(
|
||||||
WatchdogMonitor(
|
WatchdogMonitor(
|
||||||
TEST_MONITOR_BASE,
|
TEST_MONITOR_BASE,
|
||||||
rules,
|
patterns,
|
||||||
|
recipes,
|
||||||
print=monitor_debug_stream,
|
print=monitor_debug_stream,
|
||||||
logging=3,
|
logging=3,
|
||||||
settletime=1
|
settletime=1
|
||||||
@ -142,7 +142,8 @@ class MeowTests(unittest.TestCase):
|
|||||||
runner = MeowRunner(
|
runner = MeowRunner(
|
||||||
WatchdogMonitor(
|
WatchdogMonitor(
|
||||||
TEST_MONITOR_BASE,
|
TEST_MONITOR_BASE,
|
||||||
rules,
|
patterns,
|
||||||
|
recipes,
|
||||||
print=monitor_debug_stream,
|
print=monitor_debug_stream,
|
||||||
logging=3,
|
logging=3,
|
||||||
settletime=1
|
settletime=1
|
||||||
|
Reference in New Issue
Block a user