diff --git a/docs/source/change_log.rst b/docs/source/change_log.rst index 280bfaa..a77cf95 100644 --- a/docs/source/change_log.rst +++ b/docs/source/change_log.rst @@ -15,6 +15,9 @@ Version 4.0.0 * **Breaking:** Changed ``STRING.to_ary`` to return an array of characters instead of splitting the string * Use the new builtin ``$split`` function to split a string on whitespace into an array of words * **Breaking:** Changed :py:class:`~rule_engine.engine.Context` to use keyword-only arguments +* **Breaking:** Dropped support for Python versions 3.4 and 3.5 +* **Breaking:** Invalid floating point literals now raise :py:exc:`~.errors.FloatSyntaxError` instead of + :py:exc:`~.errors.RuleSyntaxError` Version 3.x.x ------------- @@ -24,7 +27,7 @@ Version 3.6.0 Released :release:`3.6.0` on June 16th, 2023 -* Removed testing for Python 3.4 and 3.5 on GitHub Actions +* Removed testing for Python versions 3.4 and 3.5 on GitHub Actions * Add regex error details to the debug REPL * Add support for Python-style comments diff --git a/docs/source/rule_engine/errors.rst b/docs/source/rule_engine/errors.rst index 7dc3c94..e2102a3 100644 --- a/docs/source/rule_engine/errors.rst +++ b/docs/source/rule_engine/errors.rst @@ -29,6 +29,11 @@ Exceptions :show-inheritance: :special-members: __init__ +.. autoexception:: FloatSyntaxError + :members: + :show-inheritance: + :special-members: __init__ + .. autoexception:: EngineError :members: :show-inheritance: @@ -96,6 +101,7 @@ The class hierarchy for Rule Engine exceptions is: +-- SymbolTypeError +-- SyntaxError +-- DatetimeSyntaxError + +-- FloatSyntaxError +-- RegexSyntaxError +-- RuleSyntaxError +-- TimedeltaSyntaxError diff --git a/lib/rule_engine/_utils.py b/lib/rule_engine/_utils.py index 0a552f5..d413ad2 100644 --- a/lib/rule_engine/_utils.py +++ b/lib/rule_engine/_utils.py @@ -30,14 +30,14 @@ def parse_datetime(string, default_timezone): def parse_float(string): if re.match('^0[0-9]', string): - raise errors.RuleSyntaxError('invalid floating point literal: ' + string + ' (leading zeros in decimal literals are not permitted)') + raise errors.FloatSyntaxError('invalid floating point literal (leading zeros in decimal literals are not permitted)', string) try: if re.match('^0[box]', string): val = decimal.Decimal(pyast.literal_eval(string)) else: val = decimal.Decimal(string) except Exception: - raise errors.RuleSyntaxError('invalid floating point literal: ' + string) from None + raise errors.FloatSyntaxError('invalid floating point literal', string) from None return val def parse_timedelta(periodstring): diff --git a/lib/rule_engine/errors.py b/lib/rule_engine/errors.py index 7a51338..2e3c7c0 100644 --- a/lib/rule_engine/errors.py +++ b/lib/rule_engine/errors.py @@ -77,6 +77,21 @@ def __init__(self, message, value): self.value = value """The datetime value which contains the syntax error which caused this exception to be raised.""" +class FloatSyntaxError(SyntaxError): + """ + An error raised for issues regarding the use of improperly formatted float expressions. + + .. versionadded:: 4.0.0 + """ + def __init__(self, message, value): + """ + :param str message: A text description of what error occurred. + :param str value: The float value which contains the syntax error which caused this exception to be raised. + """ + super(FloatSyntaxError, self).__init__(message) + self.value = value + """The float value which contains the syntax error which caused this exception to be raised.""" + class TimedeltaSyntaxError(SyntaxError): """ An error raised for issues regarding the use of improperly formatted timedelta expressions. diff --git a/tests/builtins.py b/tests/builtins.py index d8389af..fafac05 100644 --- a/tests/builtins.py +++ b/tests/builtins.py @@ -168,7 +168,7 @@ def test_engine_builtins_function_parse_float(self): self.assertBuiltinFunction('parse_float', 1e1, '1e1') self.assertBuiltinFunction('parse_float', float('inf'), 'inf') self.assertBuiltinFunction('parse_float', -1, '-1') - with self.assertRaises(errors.RuleSyntaxError): + with self.assertRaises(errors.FloatSyntaxError): self.assertBuiltinFunction('parse_float', 1, 'f00d') def test_engine_builtins_function_parse_timedelta(self): diff --git a/tests/issues.py b/tests/issues.py index 40f8be4..f15d031 100644 --- a/tests/issues.py +++ b/tests/issues.py @@ -93,5 +93,5 @@ def test_number_54(self): "test=='NOTTEST' and count==01 and other=='other'" ) for rule in rules: - with self.assertRaises(errors.RuleSyntaxError): + with self.assertRaises(errors.FloatSyntaxError): engine.Rule(rule) diff --git a/tests/parser.py b/tests/parser.py index 2480bfe..a3bb6e3 100644 --- a/tests/parser.py +++ b/tests/parser.py @@ -373,7 +373,7 @@ def test_parse_float_base_8(self): def test_parse_float_base_10(self): self.assertLiteralStatementEqual('0', ast.FloatExpression, decimal.Decimal('0')) self.assertLiteralStatementEqual('99', ast.FloatExpression, decimal.Decimal('99')) - with self.assertRaises(errors.RuleSyntaxError): + with self.assertRaises(errors.FloatSyntaxError): self._parse('00', self.context) def test_parse_float_base_16(self):