Change Log
==========
This document contains notes on the major changes for each version of the Rule Engine. In comparison to the git log,
this list is curated by the development team for note worthy changes.
Version 5.x.x
-------------
Version 5.0.0
^^^^^^^^^^^^^
Released :release:`5.0.0` on May 17th, 2026
* **Breaking:** Dropped support for Python versions 3.6, 3.7, 3.8 and 3.9.
* **Breaking:** Changed the precedence of operators to be more aligned with common programming languages.
* **Breaking:** The :ref:`debug-repl` utility now requires development dependencies to be installed.
* **Breaking:** BYTES literals now throw exceptions for invalid escape sequences
* **Breaking:** Removed ``setup.py``; project metadata now lives entirely in ``pyproject.toml`` (PEP 517/621).
* **Breaking:** The ``rule_engine.ast`` module no longer re-exports names from ``rule_engine.types`` (e.g. ``DataType``,
``coerce_value``); import them from ``rule_engine`` or ``rule_engine.types`` directly.
* Migrated the development workflow and CI from pipenv to `uv `_.
* Added support for raw STRING literals using the ``r`` prefix (e.g. ``r'\w+'``).
* Vendored the PLY dependency under ``rule_engine._vendor.ply`` — the upstream project is unmaintained, so the copy
removes an external install requirement and silences third-party vulnerability reports targeting it.
* Made :py:class:`~rule_engine.engine.Rule` and :py:class:`~rule_engine.engine.Context` objects serializable with
:py:mod:`pickle`. Transient, unpicklable state (thread-local storage, locks and the builtins table) is recreated on
restore. Any *type_resolver* or *resolver* callable must itself be picklable, so lambdas and other local functions
can not be used on a context that needs to be serialized.
* Added the new :py:attr:`~rule_engine.types.DataType.OBJECT` compound data type for user-defined schemas with named,
typed attributes. See the :ref:`OBJECT section` in the Data Types page for details.
* Use :py:meth:`~rule_engine.types.DataType.OBJECT.reference` (or the
:py:attr:`~rule_engine.types.DataType.OBJECT.self` shorthand sentinel) for self-referential and mutually-recursive
schemas.
* Attribute access is validated at parse time against the declared schema.
* Item access (``obj["name"]``) and containment checks (``"name" in obj``) on ``OBJECT`` values are rejected at
parse time.
* ``SET(OBJECT(...))`` is rejected at construction; use ``ARRAY(OBJECT(...))`` instead
* A custom *accessor* callable can be specified per ``OBJECT`` type (default: :py:func:`getattr`).
* Added :py:meth:`~rule_engine.types.DataType.OBJECT.from_dataclass` and
:py:func:`~rule_engine.engine.type_resolver_from_dataclass` for deriving ``OBJECT`` schemas and *type_resolvers*
automatically from Python :py:func:`~dataclasses.dataclass` definitions, including nullability for
:py:class:`~typing.Optional` fields and self / mutually-recursive references (closes :issue:`55`).
* Added :py:meth:`~rule_engine.types.DataType.OBJECT.from_sqlalchemy` and
:py:func:`~rule_engine.engine.type_resolver_from_sqlalchemy` for deriving ``OBJECT`` schemas and *type_resolvers*
from SQLAlchemy ORM mapped classes. Columns, relationships, and cycles between mutually-related classes are
all expanded automatically. SQLAlchemy is an optional dependency; the import is deferred until these entry
points are called.
* The ``from_dataclass`` and ``from_sqlalchemy`` entry points (and their ``type_resolver_from_*`` companions)
accept a ``strict`` keyword argument. The default ``strict=True`` raises :py:exc:`ValueError` on any
field / column whose type cannot be mapped to a Rule Engine data type; ``strict=False`` falls back to
:py:attr:`~rule_engine.types.DataType.UNDEFINED`.
* Added :py:class:`~rule_engine.errors.ObjectAttributeError`, a subclass of
:py:class:`~rule_engine.errors.AttributeResolutionError`, raised when an attribute is not found in an ``OBJECT``
schema
* Promoted nullability to a first-class type-system construct via the new
:py:attr:`~rule_engine.types.DataType.NULLABLE` one-argument type constructor. See the
:ref:`NULLABLE section` in the Data Types page for the full semantics.
* :py:meth:`~rule_engine.types.DataType.from_type` maps Python's ``Optional[T]`` / ``T | None`` to
``NULLABLE(from_type(T))``.
* :py:meth:`~rule_engine.types.DataType.OBJECT.from_dataclass` and
:py:meth:`~rule_engine.types.DataType.OBJECT.from_sqlalchemy` wrap nullable fields, columns, and scalar
relationships in ``NULLABLE(T)``; :py:func:`~rule_engine.engine.type_resolver_from_dataclass` and
:py:func:`~rule_engine.engine.type_resolver_from_sqlalchemy` preserve the wrappers through to the top-level
symbol types.
* Compound element and value types (``ARRAY``, ``SET``, ``MAPPING``) store ``NULLABLE(T)`` directly when the
member may be ``None``.
* AST operators reject ``NULLABLE`` operands at parse time wherever ``None`` has no meaningful semantics:
arithmetic, ordered comparisons, the regex operators, bitwise and bitwise-shift operators, unary minus,
containment, attribute access, item access, slicing, and function arguments all raise
:py:exc:`~rule_engine.errors.EvaluationError` (or :py:exc:`~rule_engine.errors.FunctionCallError` for function
arguments) with a message pointing at the discharge operators. Equality (``==``, ``!=``), logical connectives
(``and``, ``or``, ``not``), ternary expressions, and safe-navigation operators remain lenient.
* A new null-coalesce operator ``left ?? right`` discharges ``NULLABLE(T)`` to ``T``. Existing safe attribute
(``&.``) and item (``&[``) accessors still apply to nullable receivers and are the only access forms that do.
* **Deprecated:** The ``attributes_nullable`` kwarg on :py:attr:`~rule_engine.types.DataType.OBJECT` and the
``value_type_nullable`` kwarg on :py:attr:`~rule_engine.types.DataType.ARRAY`, :py:attr:`~rule_engine.types.DataType.SET`,
and :py:attr:`~rule_engine.types.DataType.MAPPING` now emit :py:class:`DeprecationWarning`. Wrap the relevant
attribute or element type in :py:attr:`~rule_engine.types.DataType.NULLABLE` instead. The kwargs will be removed
in v6.0.
* **Deprecated:** Accessing :py:attr:`~rule_engine.types.DataType.MAPPING` keys via dot syntax (``mapping.key``) now
emits a :py:class:`~rule_engine.errors.MappingAttributeLookupDeprecation` warning. Use bracket syntax
(``mapping["key"]``) instead. This fallback will be removed in v6.0. Set ``Context(mapping_attribute_lookup=False)``
to opt out now.
Version 4.x.x
-------------
Version 4.5.0
^^^^^^^^^^^^^
Released :release:`4.5.0` on June 19th, 2024
* :py:class:`~rule_engine.errors.StringSyntaxError` is now raised for invalid string literals
* :py:class:`~rule_engine.errors.FunctionCallError` is now raised when a typed function returns an incompatible value
* Added the new :py:class:`~rule_engine.types.DataType.BYTES` data type
* Added some new data attributes
* Added ``starts_with`` and ``ends_with`` to :py:class:`~rule_engine.types.DataType.ARRAY`, and
:py:class:`~rule_engine.types.DataType.STRING`
Version 4.4.0
^^^^^^^^^^^^^
Released :release:`4.4.0` on April 5th, 2024
* Added the ``$range`` builtin function
* Added the ``rule_engine.parser.utilities`` module with a few functions and documentation
Version 4.3.0
^^^^^^^^^^^^^
Released :release:`4.3.0` on January 15th, 2024
* Added the ``is_nan`` attribute for ``FLOAT`` values
Version 4.2.0
^^^^^^^^^^^^^
Released :release:`4.2.0` on December 11th, 2023
* Added attributes for coercion of types to themselves, e.g. ``to_str`` for ``STRING`` values
Version 4.1.0
^^^^^^^^^^^^^
Released :release:`4.1.0` on August 3rd, 2023
* Added the ``$abs`` builtin function
* Added support to :py:class:`~rule_engine.types.DataType.from_type` to handle Python's type hints
Version 4.0.0
^^^^^^^^^^^^^
Released :release:`4.0.0` on July 15th, 2023
* **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`
* **Breaking:** Moved ``rule_engine.engine.Builtins`` to :py:class:`rule_engine.builtins.Builtins`
* Added the new :py:class:`~rule_engine.types.DataType.FUNCTION` data type
Version 3.x.x
-------------
Version 3.6.0
^^^^^^^^^^^^^
Released :release:`3.6.0` on June 16th, 2023
* Removed testing for Python versions 3.4 and 3.5 on GitHub Actions
* Add regex error details to the :ref:`debug-repl` utility
* Add support for Python-style comments
Version 3.5.0
^^^^^^^^^^^^^
Released :release:`3.5.0` on July 16th, 2022
* Added the new :py:class:`~rule_engine.types.DataType.TIMEDELTA` data type
Version 3.4.0
^^^^^^^^^^^^^
Released :release:`3.4.0` on March 19th, 2022
* Add support for string concatenation via the ``+`` operator
Version 3.3.0
^^^^^^^^^^^^^
Released :release:`3.3.0` on July 20th, 2021
* Added ``to_epoch`` to :py:class:`~rule_engine.types.DataType.DATETIME`
Version 3.2.0
^^^^^^^^^^^^^
Released :release:`3.2.0` on April 3rd, 2021
* Refactored the :py:mod:`~rule_engine.ast` module to move the :py:class:`~rule_engine.types.DataType` class into a new,
dedicated :py:mod:`~rule_engine.types` module.
* Added the new :py:class:`~rule_engine.ast.ComprehensionExpression`
* Added suggestions to :py:class:`~rule_engine.errors.AttributeResolutionError` and
:py:class:`~rule_engine.errors.SymbolResolutionError`
Version 3.1.0
^^^^^^^^^^^^^
Released :release:`3.1.0` on March 15th, 2021
* Added the new :py:class:`~rule_engine.types.DataType.SET` data type
Version 3.0.0
^^^^^^^^^^^^^
Released :release:`3.0.0` on March 1st, 2021
* Switched the ``FLOAT`` datatype to use Python's :py:class:`~decimal.Decimal` from :py:class:`float` internally
* Reserved the ``if``, ``elif``, ``else``, ``for`` and ``while`` keywords for future use, they can no longer be used as
symbol names
* Added some new data attributes
* Added ``ceiling``, ``floor`` and ``to_str`` to :py:class:`~rule_engine.types.DataType.FLOAT`
Version 2.x.x
-------------
Version 2.4.0
^^^^^^^^^^^^^
Released :release:`2.4.0` on November 7th, 2020
* Added the :ref:`debug-repl` utility
* Added the safe navigation version of the attribute, item and slice operators
* Added the new :py:class:`~rule_engine.types.DataType.MAPPING` data type
* Switched from Travis-CI to GitHub Actions for continuous integration
* Added support for iterables to have multiple member types
Version 2.3.0
^^^^^^^^^^^^^
Released :release:`2.3.0` on October 11th, 2020
* Added support for arithmetic comparisons for all currently supported data types
* Added support for proper type hinting of builtin symbols
* Added the ``$re_groups`` builtin symbol for extracting groups from a regular expression match
* Added some new data attributes
* Added ``to_ary`` to :py:class:`~rule_engine.types.DataType.STRING`
* Added ``to_int`` and ``to_flt`` to :py:class:`~rule_engine.types.DataType.STRING`
Version 2.2.0
^^^^^^^^^^^^^
Released :release:`2.2.0` on September 9th, 2020
* Added script entries to the Pipfile for development
* Added support for slices on sequence data types
Version 2.1.0
^^^^^^^^^^^^^
Released :release:`2.1.0` on August 3rd, 2020
* Added coverage reporting to Travis-CI
* Changed :py:class:`~rule_engine.types.DataType`. from an enum to a custom class
* Improvements for the :py:class:`~rule_engine.types.DataType.ARRAY` data type
* Added ``get[item]`` support for arrays, allowing items to be retrieved by index
* Added ability for specifying the member type and optionally null
Version 2.0.0
^^^^^^^^^^^^^
Released :release:`2.0.0` on October 2nd, 2019
* Added proper support for attributes
* Added a change log
* Added additional information to the Graphviz output
* Added the new :py:class:`~rule_engine.types.DataType.ARRAY` data type
* Started using Travis-CI
* Added automatic unit testing using Travis-CI
* Added automatic deployment of documentation using Travis-CI
* Removed the resolver conversion functions
* Removed ``to_recursive_resolver`` in favor of attributes
* Removed ``to_default_resolver`` in favor of the *default_value* kwarg to
:py:meth:`~rule_engine.engine.Context.__init__`
Version 1.x.x
-------------
Version 1.1.0
^^^^^^^^^^^^^
Released :release:`1.1.0` on March 27th, 2019
* Added the :py:func:`~rule_engine.engine.to_default_dict` function
* Added the :py:func:`~rule_engine.engine.to_recursive_resolver` function
Version 1.0.0
^^^^^^^^^^^^^
Released :release:`1.0.0` on December 15th, 2018
* First major release