mirror of
https://github.com/Tautulli/Tautulli.git
synced 2025-07-12 08:16:06 -07:00
Remove the use of eval for evaluating custom notification logic
This commit is contained in:
parent
d4e5a750e0
commit
161e6f70d0
2 changed files with 43 additions and 5 deletions
|
@ -814,6 +814,7 @@ def parse_condition_logic_string(s, num_cond=0):
|
||||||
bool_next = False
|
bool_next = False
|
||||||
open_bracket_next = True
|
open_bracket_next = True
|
||||||
close_bracket_next = False
|
close_bracket_next = False
|
||||||
|
nest_and = False
|
||||||
|
|
||||||
for i, x in enumerate(tokens):
|
for i, x in enumerate(tokens):
|
||||||
if open_bracket_next and x == '(':
|
if open_bracket_next and x == '(':
|
||||||
|
@ -823,6 +824,7 @@ def parse_condition_logic_string(s, num_cond=0):
|
||||||
bool_next = False
|
bool_next = False
|
||||||
open_bracket_next = True
|
open_bracket_next = True
|
||||||
close_bracket_next = False
|
close_bracket_next = False
|
||||||
|
nest_and = False
|
||||||
|
|
||||||
elif close_bracket_next and x == ')':
|
elif close_bracket_next and x == ')':
|
||||||
stack.pop()
|
stack.pop()
|
||||||
|
@ -832,6 +834,7 @@ def parse_condition_logic_string(s, num_cond=0):
|
||||||
bool_next = True
|
bool_next = True
|
||||||
open_bracket_next = False
|
open_bracket_next = False
|
||||||
close_bracket_next = True
|
close_bracket_next = True
|
||||||
|
nest_and = False
|
||||||
|
|
||||||
elif cond_next and re.match(conditions_pattern, x):
|
elif cond_next and re.match(conditions_pattern, x):
|
||||||
try:
|
try:
|
||||||
|
@ -840,18 +843,33 @@ def parse_condition_logic_string(s, num_cond=0):
|
||||||
raise ValueError('invalid condition logic')
|
raise ValueError('invalid condition logic')
|
||||||
if not 0 < num <= num_cond:
|
if not 0 < num <= num_cond:
|
||||||
raise ValueError('invalid condition number in condition logic')
|
raise ValueError('invalid condition number in condition logic')
|
||||||
stack[-1].append(x)
|
stack[-1].append(num)
|
||||||
|
if nest_and:
|
||||||
|
stack.pop()
|
||||||
cond_next = False
|
cond_next = False
|
||||||
bool_next = True
|
bool_next = True
|
||||||
open_bracket_next = False
|
open_bracket_next = False
|
||||||
close_bracket_next = True
|
close_bracket_next = True
|
||||||
|
nest_and = False
|
||||||
|
|
||||||
elif bool_next and x in ('and', 'or') and i < len(tokens)-1:
|
elif bool_next and x == 'and' and i < len(tokens)-1:
|
||||||
|
stack[-1].append([])
|
||||||
|
stack.append(stack[-1][-1])
|
||||||
|
stack[-1].append(stack[-2].pop(-2))
|
||||||
stack[-1].append(x)
|
stack[-1].append(x)
|
||||||
cond_next = True
|
cond_next = True
|
||||||
bool_next = False
|
bool_next = False
|
||||||
open_bracket_next = True
|
open_bracket_next = True
|
||||||
close_bracket_next = False
|
close_bracket_next = False
|
||||||
|
nest_and = True
|
||||||
|
|
||||||
|
elif bool_next and x == 'or' and i < len(tokens)-1:
|
||||||
|
stack[-1].append(x)
|
||||||
|
cond_next = True
|
||||||
|
bool_next = False
|
||||||
|
open_bracket_next = True
|
||||||
|
close_bracket_next = False
|
||||||
|
nest_and = False
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise ValueError('invalid condition logic')
|
raise ValueError('invalid condition logic')
|
||||||
|
@ -867,3 +885,24 @@ def nested_list_to_string(l):
|
||||||
l[i] = nested_list_to_string(x)
|
l[i] = nested_list_to_string(x)
|
||||||
s = '(' + ' '.join(l) + ')'
|
s = '(' + ' '.join(l) + ')'
|
||||||
return s
|
return s
|
||||||
|
|
||||||
|
def eval_logic_groups_to_bool(logic_groups, eval_conds):
|
||||||
|
first_cond = logic_groups[0]
|
||||||
|
|
||||||
|
if isinstance(first_cond, list):
|
||||||
|
result = eval_logic_groups_to_bool(first_cond, eval_conds)
|
||||||
|
else:
|
||||||
|
result = eval_conds[first_cond]
|
||||||
|
|
||||||
|
for op, cond in zip(logic_groups[1::2], logic_groups[2::2]):
|
||||||
|
if isinstance(cond, list):
|
||||||
|
eval_cond = eval_logic_groups_to_bool(cond, eval_conds)
|
||||||
|
else:
|
||||||
|
eval_cond = eval_conds[cond]
|
||||||
|
|
||||||
|
if op == 'and':
|
||||||
|
result = result and eval_cond
|
||||||
|
elif op == 'or':
|
||||||
|
result = result or eval_cond
|
||||||
|
|
||||||
|
return result
|
|
@ -205,7 +205,6 @@ def notify_custom_conditions(notifier_id=None, parameters=None):
|
||||||
try:
|
try:
|
||||||
# Parse and validate the custom conditions logic
|
# Parse and validate the custom conditions logic
|
||||||
logic_groups = helpers.parse_condition_logic_string(custom_conditions_logic, len(custom_conditions))
|
logic_groups = helpers.parse_condition_logic_string(custom_conditions_logic, len(custom_conditions))
|
||||||
logic_string = helpers.nested_list_to_string(logic_groups)
|
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
logger.error(u"PlexPy NotificationHandler :: Unable to parse custom condition logic '%s': %s."
|
logger.error(u"PlexPy NotificationHandler :: Unable to parse custom condition logic '%s': %s."
|
||||||
% (custom_conditions_logic, e))
|
% (custom_conditions_logic, e))
|
||||||
|
@ -291,7 +290,7 @@ def notify_custom_conditions(notifier_id=None, parameters=None):
|
||||||
|
|
||||||
# Format and evaluate the logic string
|
# Format and evaluate the logic string
|
||||||
try:
|
try:
|
||||||
evaluated_logic = bool(eval(logic_string.format(*evaluated_conditions)))
|
evaluated_logic = helpers.eval_logic_groups_to_bool(logic_groups, evaluated_conditions)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(u"PlexPy NotificationHandler :: Unable to evaluate custom condition logic: %s." % e)
|
logger.error(u"PlexPy NotificationHandler :: Unable to evaluate custom condition logic: %s." % e)
|
||||||
return False
|
return False
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue