Skip to content

Commit

Permalink
fix: Rules are composable (#14)
Browse files Browse the repository at this point in the history
Store input validation rules as an array of rules
and append new rules rather than overwriting existing rules
  • Loading branch information
gadenbuie authored Jan 9, 2025
1 parent 757c7cd commit 1da0ad9
Showing 1 changed file with 48 additions and 40 deletions.
88 changes: 48 additions & 40 deletions shiny_validate/validator.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def __init__(
self.__session = require_active_session(get_current_session())
self.__priority: int = priority
self.__condition = reactive.Value(None)
self.__rules: reactive.Value[dict[str, Rule]] = reactive.Value({})
self.__rules: reactive.Value[dict[str, list[Rule]]] = reactive.Value({})

self.__enabled: bool = False
self.__observer_handle: Optional[reactive.Effect] = None
Expand Down Expand Up @@ -82,10 +82,17 @@ def add_rule(self, inputId: str, rule: Callable):
if not callable(rule):
raise ValueError("`rule` argument must be a function")

new_rule = Rule(rule, label, session=get_current_session())

with reactive.isolate():
new_rules = self.__rules.get()
new_rules[inputId] = Rule(rule, label, session=get_current_session())
self.__rules.set(new_rules)
rules = self.__rules.get()
if inputId in rules.keys():
rules[inputId].append(new_rule)
else:
rules[inputId] = [new_rule]

self.__rules.unset()
self.__rules.set(rules)

def enable(self):
if self.__is_child:
Expand Down Expand Up @@ -140,46 +147,47 @@ def __validate_impl(self):
dependency_results = {**dependency_results, **child_results}

results = {}
for name, rule in self.__rules().items():
fullname = rule.session.ns(name)

try:
result = rule.rule(rule.session.input[name]())
except Exception as e:
result = "An unexpected error occurred during input validation: " + str(
e
)
for name, rules in self.__rules().items():
fullname = rules[0].session.ns(name)
results[fullname] = None

for rule in rules:
try:
result = rule.rule(rule.session.input[name]())
except Exception as e:
result = "An unexpected error occurred during input validation: " + str(
e
)

result_is_html = isinstance(result, (str, bytes))
if result_is_html:
result = str(result)
result_is_html = isinstance(result, (str, bytes))
if result_is_html:
result = str(result)

is_valid_result = (
result is None
or (isinstance(result, str))
or result == SkipValidation()
)

if not is_valid_result:
raise ValueError(
"Result of '"
+ name
+ "' validation was not a single-character vector (actual class: "
+ str(type(result))
+ ")"
is_valid_result = (
result is None
or (isinstance(result, str))
or result == SkipValidation()
)

if result is None:
if fullname not in results:
results[fullname] = None
elif result == SkipValidation():
results[fullname] = True
else:
results[fullname] = {
"type": "error",
"message": result,
"is_html": result_is_html,
}
if not is_valid_result:
raise ValueError(
"Result of '"
+ name
+ "' validation was not a single-character vector (actual class: "
+ str(type(result))
+ ")"
)

if result is not None:
if result == SkipValidation():
results[fullname] = True
else:
results[fullname] = {
"type": "error",
"message": result,
"is_html": result_is_html,
}
break

for key in results:
if results[key] is True:
Expand Down

0 comments on commit 1da0ad9

Please sign in to comment.