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.2.0
Released v5.2.0 on October 28th, 2026
Added the int_max_digits parameter to
Contextto limit the number of digits an integer can have when it is converted to aFLOATvalue. The conversion takes time that grows quadratically with the size of the integer, so a short rule could hang the process. Larger integers now raise anArithmeticError. The default ofNoneuses the interpreter’s limit fromsys.get_int_max_str_digits()and0disables the limit.coerce_value()andparse_float()accept it as a keyword-only argument.The parser tables are now generated when the wheel is built and are shipped in it, instead of being generated at runtime. Nothing is written to the installation directory, so installs work the same way for root and non-root users. Building the package now requires
python-dateutil.The
==,!=,andandoroperators now acceptBYTESandFUNCTIONvalues, andandandornow acceptOBJECTvalues, as documented. Rules such asb"ab" == b"ab"previously raised anEvaluationError.from_type()now mapsT | Nonetype hints toNULLABLE(T)on Python versions 3.10 to 3.13, where it previously raised aTypeError.The
to_intandto_fltattributes ofSTRINGvalues now accept leading zeros, e.g."02134".to_intis2134, where they previously raised Python’sSyntaxError.parse_float()and the$parse_floatbuiltin function now raise aFloatSyntaxErrorfor binary, octal and hexadecimal values followed by a comment or line continuation, such as"0x10 # c", and no longer cause Python to emit warnings for invalid strings.The
$re_groupsbuiltin symbol no longer raises aSymbolTypeErrorwhen an optional group didn’t take part in the match. The member for that group is null.The
ARRAY,SET,MAPPINGandFUNCTIONdata types can now be pickled and copied, as can theOBJECTtypes,ContextandRuleobjects that contain them. TheDataTypeconstants keep their identity when they are pickled or copied.Fixed some edge cases of
from_dataclass()andtype_resolver_from_dataclass()With
strict=True, dataclasses nested in the members of a field, such aslist[Hero | None]andlist[list[Address]], are now mapped, where they previously raised aValueError.With
strict=False, fields that can’t be mapped now map toUNDEFINEDas documented, where some of them previously raised. These include unsupported member types such asset[Address], forward references that can’t be resolved and sets of dataclasses that the schema refers to.The values of
Literaltype hints are no longer evaluated as code in the dataclass’s module.
SymbolTypeErrorandAttributeTypeErrormessages now spell out compound data types, e.g.ARRAY(FLOAT)instead ofARRAY. When anARRAYorSETvalue hasNonemembers, theis_typeattribute of aSymbolTypeErrornow wraps the member type inNULLABLE.Calling
str()on aEngineErrornow returns its message instead of the arguments it was created with.SymbolTypeError,AttributeTypeErrorandRegexSyntaxErrorerrors can now be pickled and copied.Deprecated: A typed symbol whose value has a
Nonemember where the member type is not nullable, such as{'a': None}forMAPPING(STRING, STRING), now emits aDeprecationWarning. These values will raise aSymbolTypeErrorin v6.0. Wrap the member type inNULLABLEto allowNone.
Version 5.1.0
Released v5.1.0 on October 20th, 2026
Added the
Chainclass for evaluating an object against an ordered list of rules and returning the value of the first one that matches, similar to a chain in iptables. See Rule Chains for details.find()returns theChainEntrythat matched, which can be used to determine which rule was applied, andindex()returns its position in the chain.When no rule matches and no default value is set, the new
ChainExhaustedErroris raised.Chains can be modified with
append(),insert(),delete()andflush()while other threads evaluate them, and can be pickled.Slicing a chain returns a new chain with the same default value and context.
Fixed the
UNDEFINEDsentinel losing its identity when pickled or copied. A restoredContextusing the default default_value would return a stand-in object for missing symbols and attributes instead of raising aSymbolResolutionErrororAttributeResolutionError. Contexts that were pickled by an earlier version are corrected when they are loaded.
Version 5.0.0
Released v5.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 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 inpyproject.toml(PEP 517/621).Breaking: The
rule_engine.astmodule no longer re-exports names fromrule_engine.types(e.g.DataType,coerce_value); import them fromrule_engineorrule_engine.typesdirectly.Breaking: A symbol typed by a type_resolver as an
ARRAYorSETwith a member type no longer acceptsNonemembers unless that type is wrapped inNULLABLE. Before 5.0.0, thevalue_type_nullablekwarg defaulted toTrue, so a symbol typed asARRAY(STRING)could resolve to('a', None). Now that value raises aSymbolTypeErrorwhen the symbol is resolved. To acceptNonemembers, useARRAY(NULLABLE(STRING))(or the deprecatedvalue_type_nullable=Trueuntil v6.0). Rules must then handle the nullable members, for example with??, before using them with operators that rejectNULLABLEoperands. See the NULLABLE section in the Data Types page for details.Migrated the development workflow and CI from pipenv to uv.
Added support for raw STRING literals using the
rprefix (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
RuleandContextobjects serializable withpickle. 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
OBJECTcompound data type for user-defined schemas with named, typed attributes. See the OBJECT section in the Data Types page for details.Use
reference()(or theselfshorthand 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) onOBJECTvalues are rejected at parse time.SET(OBJECT(...))is rejected at construction; useARRAY(OBJECT(...))insteadA custom accessor callable can be specified per
OBJECTtype (default:getattr()).Added
from_dataclass()andtype_resolver_from_dataclass()for derivingOBJECTschemas and type_resolvers automatically from Pythondataclass()definitions, including nullability forOptionalfields and self / mutually-recursive references (closes #55).Added
from_sqlalchemy()andtype_resolver_from_sqlalchemy()for derivingOBJECTschemas 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_dataclassandfrom_sqlalchemyentry points (and theirtype_resolver_from_*companions) accept astrictkeyword argument. The defaultstrict=TrueraisesValueErroron any field / column whose type cannot be mapped to a Rule Engine data type;strict=Falsefalls back toUNDEFINED.
Added
ObjectAttributeError, a subclass ofAttributeResolutionError, raised when an attribute is not found in anOBJECTschemaPromoted nullability to a first-class type-system construct via the new
NULLABLEone-argument type constructor. See the NULLABLE section in the Data Types page for the full semantics.from_type()maps Python’sOptional[T]/T | NonetoNULLABLE(from_type(T)).from_dataclass()andfrom_sqlalchemy()wrap nullable fields, columns, and scalar relationships inNULLABLE(T);type_resolver_from_dataclass()andtype_resolver_from_sqlalchemy()preserve the wrappers through to the top-level symbol types.Compound element and value types (
ARRAY,SET,MAPPING) storeNULLABLE(T)directly when the member may beNone.AST operators reject
NULLABLEoperands at parse time whereverNonehas 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 raiseEvaluationError(orFunctionCallErrorfor 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 ?? rightdischargesNULLABLE(T)toT. Existing safe attribute (&.) and item (&[) accessors still apply to nullable receivers and are the only access forms that do.
Deprecated: The
value_type_nullablekwarg onARRAY,SET, andMAPPINGnow emitsDeprecationWarning. Wrap the relevant element or value type inNULLABLEinstead. The kwarg will be removed in v6.0.Deprecated: Accessing
MAPPINGkeys via dot syntax (mapping.key) now emits aMappingAttributeLookupDeprecationwarning. Use bracket syntax (mapping["key"]) instead. This fallback will be removed in v6.0. SetContext(mapping_attribute_lookup=False)to opt out now.
Version 4.x.x
Version 4.5.0
Released v4.5.0 on June 19th, 2024
StringSyntaxErroris now raised for invalid string literalsFunctionCallErroris now raised when a typed function returns an incompatible valueAdded the new
BYTESdata typeAdded some new data attributes
Version 4.4.0
Released v4.4.0 on April 5th, 2024
Added the
$rangebuiltin functionAdded the
rule_engine.parser.utilitiesmodule with a few functions and documentation
Version 4.3.0
Released v4.3.0 on January 15th, 2024
Added the
is_nanattribute forFLOATvalues
Version 4.2.0
Released v4.2.0 on December 11th, 2023
Added attributes for coercion of types to themselves, e.g.
to_strforSTRINGvalues
Version 4.1.0
Released v4.1.0 on August 3rd, 2023
Added the
$absbuiltin functionAdded support to
from_typeto handle Python’s type hints
Version 4.0.0
Released v4.0.0 on July 15th, 2023
Breaking: Changed
STRING.to_aryto return an array of characters instead of splitting the stringUse the new builtin
$splitfunction to split a string on whitespace into an array of words
Breaking: Changed
Contextto use keyword-only argumentsBreaking: Dropped support for Python versions 3.4 and 3.5
Breaking: Invalid floating point literals now raise
FloatSyntaxErrorinstead ofRuleSyntaxErrorBreaking: Moved
rule_engine.engine.Builtinstorule_engine.builtins.BuiltinsAdded the new
FUNCTIONdata type
Version 3.x.x
Version 3.6.0
Released v3.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 Debug REPL utility
Add support for Python-style comments
Version 3.5.0
Released v3.5.0 on July 16th, 2022
Added the new
TIMEDELTAdata type
Version 3.4.0
Released v3.4.0 on March 19th, 2022
Add support for string concatenation via the
+operator
Version 3.3.0
Released v3.3.0 on July 20th, 2021
Added
to_epochtoDATETIME
Version 3.2.0
Released v3.2.0 on April 3rd, 2021
Refactored the
astmodule to move theDataTypeclass into a new, dedicatedtypesmodule.Added the new
ComprehensionExpressionAdded suggestions to
AttributeResolutionErrorandSymbolResolutionError
Version 3.1.0
Released v3.1.0 on March 15th, 2021
Added the new
SETdata type
Version 3.0.0
Released v3.0.0 on March 1st, 2021
Version 2.x.x
Version 2.4.0
Released v2.4.0 on November 7th, 2020
Added the Debug REPL utility
Added the safe navigation version of the attribute, item and slice operators
Added the new
MAPPINGdata typeSwitched from Travis-CI to GitHub Actions for continuous integration
Added support for iterables to have multiple member types
Version 2.3.0
Released v2.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_groupsbuiltin symbol for extracting groups from a regular expression matchAdded some new data attributes
Version 2.2.0
Released v2.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 v2.1.0 on August 3rd, 2020
Version 2.0.0
Released v2.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
ARRAYdata typeStarted 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_resolverin favor of attributesRemoved
to_default_resolverin favor of the default_value kwarg to__init__()
Version 1.x.x
Version 1.1.0
Released v1.1.0 on March 27th, 2019
Added the
to_default_dict()functionAdded the
to_recursive_resolver()function
Version 1.0.0
Released v1.0.0 on December 15th, 2018
First major release