Skip to content

Commit

Permalink
refs #38, #39, dictation-toolbox#385: add more validators
Browse files Browse the repository at this point in the history
  • Loading branch information
synkarius committed Oct 15, 2019
1 parent 661c90c commit e96b1e8
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 7 deletions.
20 changes: 14 additions & 6 deletions castervoice/lib/ctrl/mgr/grammar_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
from dragonfly import Grammar

from castervoice.lib import printer
from castervoice.lib.const import CCRType
from castervoice.lib.ctrl.mgr.errors.not_a_module import NotAModuleError
from castervoice.lib.ctrl.mgr.loading.load.content_type import ContentType
from castervoice.lib.ctrl.mgr.managed_rule import ManagedRule
Expand All @@ -25,7 +24,8 @@ def __init__(self, config,
ccr_toggle,
smrc,
t_runner,
companion_config):
companion_config,
combo_validator):
"""
Holds both the current merged ccr rules and the most recently instantiated/validated
copies of all ccr and non-ccr rules.
Expand All @@ -44,7 +44,8 @@ def __init__(self, config,
:param hooks_runner: runs all hooks at different events
:param smrc: grants limited access to other parts of framework to selfmod rules- don't keep reference
:param t_runner: a reference is kept to it so can instantly activate its activation rule
:param companion_config a config which controls which rules can be enabled/disabled instantly by other rules
:param companion_config: a config which controls which rules can be enabled/disabled instantly by other rules
:param combo_validator: validates all (ccr/non-ccr) rule+detail combinations
"""
self._config = config
self._merger = merger
Expand All @@ -59,6 +60,7 @@ def __init__(self, config,
self._ccr_toggle = ccr_toggle
self._transformers_runner = t_runner
self._companion_config = companion_config
self._combo_validator = combo_validator

# rules: (class name : ManagedRule}
self._managed_rules = {}
Expand Down Expand Up @@ -237,21 +239,26 @@ def _get_invalidation(self, rule_class, details):
'''validate details configuration before anything else'''
details_invalidation = self._details_validator.validate_details(details)
if details_invalidation is not None:
return class_name + " rejected due to detail validation errors: " + details_invalidation
return "{} rejected due to detail validation errors: {}".format(class_name, details_invalidation)

'''attempt to instantiate the rule'''
test_instance = None
try:
test_instance = rule_class()
except: # ignore warnings on this line-- it's supposed to be broad
traceback.print_exc()
return class_name + " rejected due to instantiation errors"
return "{} rejected due to instantiation errors".format(class_name)

'''if ccr, validate the rule'''
if details.declared_ccrtype is not None:
error = self._ccr_rules_validator.validate_rule(test_instance, details.declared_ccrtype)
if error is not None:
return class_name + " rejected due to rule validation errors: " + error
return "{} rejected due to rule validation errors: {}".format(class_name, error)

'''do combo validations'''
combo_invalidation = self._combo_validator.validate(test_instance, details)
if combo_invalidation is not None:
return "{} rejected due to rule/details combination errors: {}".format(class_name, combo_invalidation)

return None

Expand All @@ -264,6 +271,7 @@ def load_activation_grammars(self):
rules = [self._activator.construct_activation_rule(),
self._hooks_runner.construct_activation_rule(),
self._transformers_runner.construct_activation_rule()]
rules = [rule for rule in rules if len(rule[0].mapping) > 0] # there might not be *any* transformers/hooks
if hasattr(self._reload_observable, "get_loadable"):
rules.append(self._reload_observable.get_loadable())

Expand Down
Empty file.
11 changes: 11 additions & 0 deletions castervoice/lib/ctrl/mgr/validation/combo/base_combo_validator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from castervoice.lib.ctrl.mgr.errors.base_class_error import DontUseBaseClassError


class BaseComboValidator(object):
"""
Identifies and rejects invalid rules; has access to their
RuleDetails objects.
"""

def validate(self, rule, details):
raise DontUseBaseClassError(self)
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
class ComboValidationDelegator(object):

def __init__(self, *validator_delegates):
self._validator_delegates = validator_delegates

def validate(self, rule, details):
invalidations = []
for delegate in self._validator_delegates:
invalidation = delegate.validate(rule, details)
if invalidation is not None:
invalidations.append(invalidation)
return None if len(invalidations) == 0 else ", ".join(invalidations)
26 changes: 26 additions & 0 deletions castervoice/lib/ctrl/mgr/validation/combo/non_empty_validator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from castervoice.lib.ctrl.mgr.validation.combo.base_combo_validator import BaseComboValidator
from castervoice.lib.merge.selfmod.selfmodrule import BaseSelfModifyingRule


class RuleNonEmptyValidator(BaseComboValidator):
"""
Any static rule should have at least one command to start.
Some selfmod rules don't have any rules the first time they
are instantiated, but then immediately fill in and "reboot"
themselves.
SikuliRule is not a selfmod rule, but it kind of works like
one, so it is also exempted.
"""

def validate(self, rule, details):
invalidations = []
if len(rule.mapping) == 0 and not self._rule_is_exempt(rule):
invalidations.append("rules must have at least one command")
return None if len(invalidations) == 0 else ", ".join(invalidations)

def _rule_is_exempt(self, rule):
selfmod = isinstance(rule, BaseSelfModifyingRule)
sikuli = rule.__class__.__name__ == "SikuliRule"
return selfmod or sikuli
15 changes: 15 additions & 0 deletions castervoice/lib/ctrl/mgr/validation/combo/rule_family_validator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from dragonfly import MappingRule

from castervoice.lib.ctrl.mgr.validation.combo.base_combo_validator import BaseComboValidator
from castervoice.lib.merge.mergerule import MergeRule


class RuleFamilyValidator(BaseComboValidator):

def validate(self, rule, details):
invalidations = []
if isinstance(rule, MappingRule) and details.declared_ccrtype is not None:
invalidations.append("MappingRules must not have a ccrtype")
if isinstance(rule, MergeRule) and details.declared_ccrtype is None:
invalidations.append("MergeRules must have a ccrtype")
return None if len(invalidations) == 0 else ", ".join(invalidations)
10 changes: 9 additions & 1 deletion castervoice/lib/ctrl/nexus.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
from castervoice.lib.ctrl.mgr.loading.reload.timer_reload_observable import TimerReloadObservable
from castervoice.lib.ctrl.mgr.rule_maker.mapping_rule_maker import MappingRuleMaker
from castervoice.lib.ctrl.mgr.rules_config import RulesConfig
from castervoice.lib.ctrl.mgr.validation.combo.combo_validation_delegator import ComboValidationDelegator
from castervoice.lib.ctrl.mgr.validation.combo.non_empty_validator import RuleNonEmptyValidator
from castervoice.lib.ctrl.mgr.validation.combo.rule_family_validator import RuleFamilyValidator
from castervoice.lib.merge.ccrmerging2.compatibility.detail_compat_checker import DetailCompatibilityChecker
from castervoice.lib.merge.ccrmerging2.hooks.hooks_config import HooksConfig
from castervoice.lib.merge.ccrmerging2.hooks.hooks_runner import HooksRunner
Expand Down Expand Up @@ -120,6 +123,10 @@ def _create_grammar_manager(merger, content_loader, hooks_runner, rule_config, s
AppCCRDetailsValidator(),
NonCCRDetailsValidator()
)
combo_validator = ComboValidationDelegator(
RuleFamilyValidator(),
RuleNonEmptyValidator()
)

observable = TimerReloadObservable(5)
if settings.SETTINGS["miscellaneous"]["reload_trigger"] == "manual":
Expand All @@ -144,7 +151,8 @@ def _create_grammar_manager(merger, content_loader, hooks_runner, rule_config, s
ccr_toggle,
smrc,
transformers_runner,
companion_config)
companion_config,
combo_validator)
return gm

@staticmethod
Expand Down

0 comments on commit e96b1e8

Please sign in to comment.