From e3193bc874e45c9a6761d54da0f74fda5975d443 Mon Sep 17 00:00:00 2001 From: rajeswari1301 Date: Tue, 26 May 2026 12:42:12 -0500 Subject: [PATCH 1/3] Implement PythonBool validator for mandatory, initial, scan for variables --- src/dayamlchecker/yaml_structure.py | 21 +++++- tests/test_yaml_structure.py | 110 ++++++++++++++++++++++++++++ 2 files changed, 128 insertions(+), 3 deletions(-) diff --git a/src/dayamlchecker/yaml_structure.py b/src/dayamlchecker/yaml_structure.py index a85baac..f296948 100644 --- a/src/dayamlchecker/yaml_structure.py +++ b/src/dayamlchecker/yaml_structure.py @@ -203,7 +203,22 @@ class PythonBool: def __init__(self, x): self.errors = [] - pass + if isinstance(x, bool): + return + #number like 10 or 0 - not valid, even though Python treats them as truthy/falsy + if isinstance(x, (int, float)): + self.errors = [(f"expected True, False, or a Python expression, got number: {x}", 1)] + return + #must be a string at this point + if not isinstance(x, str): + self.errors = [(f"expected True, False, or a Python expression, got: {type(x).__name__}", 1)] + return + #try parsing it as a Python expression - covers things like "user_age > 18" + try: + ast.parse(x) + except SyntaxError as ex: + msg = ex.msg or str(ex) + self.errors = [(f"expected True, False, or a valid Python expression, got: {x!r} (Python syntax error: {msg})", 1)] class JavascriptText: @@ -751,10 +766,10 @@ def _variable_candidates(self, var_expr): "default language": {}, "default validation messages": {}, "machine learning storage": {}, - "scan for variables": {}, + "scan for variables": {"type": PythonBool}, "if": {}, "sets": {}, - "initial": {}, + "initial": {"type": PythonBool}, "event": {}, "comment": {}, "generic object": {"type": DAPythonVar}, diff --git a/tests/test_yaml_structure.py b/tests/test_yaml_structure.py index 0a9922a..11165f5 100644 --- a/tests/test_yaml_structure.py +++ b/tests/test_yaml_structure.py @@ -1732,6 +1732,116 @@ def test_show_hide_nesting_depth_two_no_warning(self): f"Did not expect nesting warning, got: {errs}", ) + def test_mandatory_number_errors(self): + """Error: mandatory with a number should be flagged""" + invalid = """ +mandatory: 10 +question: | + Hello +field: user_name +""" + errs = find_errors_from_string(invalid, input_file="") + self.assertTrue( + any("got number: 10" in e.err_str for e in errs), + f"Expected mandatory number error, got: {errs}", + ) + + def test_mandatory_bool_true_valid(self): + """Valid: mandatory: True should pass""" + valid = """ +mandatory: True +question: | + Hello +field: user_name +""" + errs = find_errors_from_string(valid, input_file="") + self.assertFalse( + any("expected True, False" in e.err_str for e in errs), + f"Did not expect mandatory error for True, got: {errs}", + ) + + def test_mandatory_bool_false_valid(self): + """Valid: mandatory: False should pass""" + valid = """ +mandatory: False +question: | + Hello +field: user_name +""" + errs = find_errors_from_string(valid, input_file="") + self.assertFalse( + any("expected True, False" in e.err_str for e in errs), + f"Did not expect mandatory error for False, got: {errs}", + ) + + def test_mandatory_python_expression_valid(self): + """Valid: mandatory with a Python expression should pass""" + valid = """ +mandatory: user_age > 18 +question: | + Hello +field: user_name +""" + errs = find_errors_from_string(valid, input_file="") + self.assertFalse( + any("expected True, False" in e.err_str for e in errs), + f"Did not expect mandatory error for Python expression, got: {errs}", + ) + + def test_mandatory_invalid_string_errors(self): + """Error: mandatory with a non-Python string should be flagged""" + invalid = """ +mandatory: yes please +question: | + Hello +field: user_name +""" + errs = find_errors_from_string(invalid, input_file="") + self.assertTrue( + any("expected True, False" in e.err_str for e in errs), + f"Expected mandatory invalid string error, got: {errs}", + ) + + def test_initial_number_errors(self): + """Error: initial with a number should be flagged""" + invalid = """ +initial: 10 +code: | + x = 1 +""" + errs = find_errors_from_string(invalid, input_file="") + self.assertTrue( + any("got number: 10" in e.err_str for e in errs), + f"Expected initial number error, got: {errs}", + ) + + def test_scan_for_variables_invalid_string_errors(self): + """Error: scan for variables with invalid string should be flagged""" + invalid = """ +scan for variables: yes please +code: | + x = 1 +""" + errs = find_errors_from_string(invalid, input_file="") + self.assertTrue( + any("expected True, False" in e.err_str for e in errs), + f"Expected scan for variables error, got: {errs}", + ) + + def test_mandatory_null_errors(self): + """Error: mandatory: null should be flagged""" + invalid = """ +mandatory: null +question: | + Hello +field: user_name +""" + errs = find_errors_from_string(invalid, input_file="") + self.assertTrue( + any("expected True, False" in e.err_str for e in errs), + f"Expected mandatory null error, got: {errs}", + ) + if __name__ == "__main__": unittest.main() From c508807a0511f4bdb9a2f5b09bf05d5b9c99bda4 Mon Sep 17 00:00:00 2001 From: rajeswari1301 Date: Tue, 26 May 2026 12:52:54 -0500 Subject: [PATCH 2/3] Apply black formatting --- src/dayamlchecker/yaml_structure.py | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/src/dayamlchecker/yaml_structure.py b/src/dayamlchecker/yaml_structure.py index f296948..de930eb 100644 --- a/src/dayamlchecker/yaml_structure.py +++ b/src/dayamlchecker/yaml_structure.py @@ -205,20 +205,32 @@ def __init__(self, x): self.errors = [] if isinstance(x, bool): return - #number like 10 or 0 - not valid, even though Python treats them as truthy/falsy + # number like 10 or 0 - not valid, even though Python treats them as truthy/falsy if isinstance(x, (int, float)): - self.errors = [(f"expected True, False, or a Python expression, got number: {x}", 1)] + self.errors = [ + (f"expected True, False, or a Python expression, got number: {x}", 1) + ] return - #must be a string at this point + # must be a string at this point if not isinstance(x, str): - self.errors = [(f"expected True, False, or a Python expression, got: {type(x).__name__}", 1)] + self.errors = [ + ( + f"expected True, False, or a Python expression, got: {type(x).__name__}", + 1, + ) + ] return - #try parsing it as a Python expression - covers things like "user_age > 18" + # try parsing it as a Python expression - covers things like "user_age > 18" try: ast.parse(x) except SyntaxError as ex: msg = ex.msg or str(ex) - self.errors = [(f"expected True, False, or a valid Python expression, got: {x!r} (Python syntax error: {msg})", 1)] + self.errors = [ + ( + f"expected True, False, or a valid Python expression, got: {x!r} (Python syntax error: {msg})", + 1, + ) + ] class JavascriptText: From a4043ade7a45ced0bdcd3a9a1c8f339576279ad7 Mon Sep 17 00:00:00 2001 From: rajeswari1301 Date: Wed, 27 May 2026 09:47:08 -0500 Subject: [PATCH 3/3] Remove PythonBool from scan for variables --- src/dayamlchecker/yaml_structure.py | 2 +- tests/test_yaml_structure.py | 13 ------------- 2 files changed, 1 insertion(+), 14 deletions(-) diff --git a/src/dayamlchecker/yaml_structure.py b/src/dayamlchecker/yaml_structure.py index de930eb..ad1ca1e 100644 --- a/src/dayamlchecker/yaml_structure.py +++ b/src/dayamlchecker/yaml_structure.py @@ -778,7 +778,7 @@ def _variable_candidates(self, var_expr): "default language": {}, "default validation messages": {}, "machine learning storage": {}, - "scan for variables": {"type": PythonBool}, + "scan for variables": {}, "if": {}, "sets": {}, "initial": {"type": PythonBool}, diff --git a/tests/test_yaml_structure.py b/tests/test_yaml_structure.py index 11165f5..125cf28 100644 --- a/tests/test_yaml_structure.py +++ b/tests/test_yaml_structure.py @@ -1815,19 +1815,6 @@ def test_initial_number_errors(self): f"Expected initial number error, got: {errs}", ) - def test_scan_for_variables_invalid_string_errors(self): - """Error: scan for variables with invalid string should be flagged""" - invalid = """ -scan for variables: yes please -code: | - x = 1 -""" - errs = find_errors_from_string(invalid, input_file="") - self.assertTrue( - any("expected True, False" in e.err_str for e in errs), - f"Expected scan for variables error, got: {errs}", - ) - def test_mandatory_null_errors(self): """Error: mandatory: null should be flagged""" invalid = """