A simple rule engine
Project description
Simple Rule Engine in Pure Python
The Simple Rule Engine is a lightweight library for creating, combining, and evaluating (nested) rules. Inspired by Django's Q object, it allows you to construct complex logical conditions and evaluate them against dictionaries of data.
Quickstart
pip install light-rule-engine
from rule_engine import Rule, evaluate
# Rule: (foo == "bar" OR foo == "baz") AND (name == "John" AND age >= 21)
rule = Rule(
Rule(foo="bar") | Rule(foo="baz"),
name="John", age__gte=21
)
example_true = {"foo": "bar", "name": "John", "age": 22}
example_false = {"foo": "qux", "name": "Jane", "age": 19}
assert evaluate(rule, example_true)
assert not evaluate(rule, example_false)
Features
- Create rules with simple conditions or nested logic.
- Combine rules using logical operators:
&(AND)|(OR)~(NOT)
- Evaluate rules against dictionaries of values.
- Supports a wide range of operators (listed below).
- Extensible: Add your own custom operators if needed.
Installation
pip install light-rule-engine
poetry add light-rule-engine
uv add light-rule-engine
Supported Operators
| Operator | Description |
|---|---|
gte |
Greater than or equal to |
gt |
Greater than |
lte |
Less than or equal to |
lt |
Less than |
in |
Value is in a list/collection |
iin |
Value is in a list/collection or string (case insensitive) |
nin |
Value is not in a list/collection |
inin |
Value is not in a list/collection or string (case insensitive) |
startswith |
String starts with a specific value |
istartswith |
String starts with a specific value (case-insensitive) |
endswith |
String ends with a specific value |
iendswith |
String ends with a specific value (case-insensitive) |
contains |
Collection or string contains a specific value |
icontains |
String contains a specific value (case-insensitive) |
exact |
Value matches exactly |
iexact |
Value matches exactly (case-insensitive) |
ne |
Not equal |
eq |
Equal to |
regex |
Matches a regular expression pattern |
is |
Identity comparison (evaluates with is) |
notset |
Value is not set |
Basic Usage
Creating Rules
Rules can be created using the Rule object. You can pass positional arguments (*args) for nested rules and keyword arguments (**kwargs) for conditions.
from rule_engine import Rule
# Simple rule with conditions
rule = Rule(name="John", age__gte=21)
# Nested rules with logical operators
complex_rule = Rule(
Rule(name="John") & Rule(age__gte=21),
Rule(name="Jane") | Rule(age__lt=20)
)
Logical Operators
&(AND): Combines rules that must all be satisfied.|(OR): Combines rules where at least one must be satisfied.~(NOT): Negates a rule.
Example:
from rule_engine import Rule
# Rule: (name == "John" AND age >= 21) OR (name == "Jane" AND age < 20)
rule = Rule(
Rule(name="John") & Rule(age__gte=21) |
Rule(name="Jane") & Rule(age__lt=20)
)
Alternatively, you can also express this in the following fashion:
from rule_engine import Rule
rule = Rule(name="John", age__gte=21) | Rule(name="Jane", age__lt=20)
Evaluating Rules
To evaluate a rule, use the evaluate function or the evaluate method of the rule. Provide a dictionary of data to check the rule against.
from rule_engine import Rule, evaluate
# Rule: (foo == "bar" OR foo == "baz") AND (name == "John" AND age >= 21)
rule = Rule(
Rule(foo="bar") | Rule(foo="baz"),
name="John", age__gte=21
)
example_true = {"foo": "bar", "name": "John", "age": 22}
example_false = {"foo": "qux", "name": "Jane", "age": 19}
assert evaluate(rule, example_true)
assert not evaluate(rule, example_false)
Advanced Usage
Custom Operators
You can extend the rule engine by adding new operators.
Use the func operator for custom logic, or modify the OPERATOR_FUNCTIONS dictionary for persistent custom operators.
You can set a Rule's id in two ways:
from rule_engine import Rule
rule = Rule(name="John")
rule.id = "my-rule"
or
from rule_engine import Rule
rule = Rule(name="John", __id="my-rule")
Raise on Missing Fields
from rule_engine import Rule
rule = Rule(name="John", age__gte=21, __raise_on_notset=True)
rule.evaluate({"name": "John"})
# >>> ValueError(f"Field 'age' is not set in the example data")
Full example
from rule_engine import Rule, evaluate
# Complex rule example
rule = Rule(
Rule(credit_rating__gte=50, flood_risk__lt=10) |
Rule(revenue__gt=1_000_000)
)
data = {"credit_rating": 55, "flood_risk": 5}
assert evaluate(rule, data)
data = {"revenue": 1_500_000}
assert evaluate(rule, data)
data = {"credit_rating": 40, "flood_risk": 15, "revenue": 500_000}
assert not evaluate(rule, data)
The EvaluationResult object
The evaluate function returns an EvaluationResult object that contains the result of the evaluation and the rule that was evaluated.
It contains a granular representation of the evaluation process, including the result of each condition and the final result.
from rule_engine import Rule, evaluate
rule = Rule(name="John") & Rule(age__gte=21) | Rule(name="Jane")
example = {"name": "John", "age": 22}
res = evaluate(rule, example)
print(bool(res)) # True
print(res.to_json(indent=2)) # to_dict() also available
"""
{
"field": "name",
"value": "John",
"operator": "eq",
"condition_value": "John",
"result": true,
"negated": false,
"children": [
[
"AND",
{
"field": "age",
"value": 22,
"operator": "gte",
"condition_value": 21,
"result": true,
"negated": false,
"children": []
}
],
[
"OR",
{
"field": "name",
"value": "John",
"operator": "eq",
"condition_value": "Jane",
"result": false,
"negated": false,
"children": []
}
]
]
}
"""
Contributing
Contributions are welcome! For feature requests, bug reports, or questions, please open an issue on GitHub.
License
This project is licensed under the MIT License. See the LICENSE file for details.
Acknowledgements
This project was inspired by Django's awesome Q object and the need for a simple rule engine in Python.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file light_rule_engine-1.2.0.tar.gz.
File metadata
- Download URL: light_rule_engine-1.2.0.tar.gz
- Upload date:
- Size: 20.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
98963ac09d69417aa4df8202a38b4c9a44e9e4c7bb63cd9b9eff862e92bf5836
|
|
| MD5 |
0354e263636f96cfb5a6bbfe2613a56a
|
|
| BLAKE2b-256 |
bedc039230d1549105c8ada12b6ce58eb64cff83bf1c577b42be18b5b846f7c2
|
Provenance
The following attestation bundles were made for light_rule_engine-1.2.0.tar.gz:
Publisher:
pypi.yml on biagiodistefano/rule-engine
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
light_rule_engine-1.2.0.tar.gz -
Subject digest:
98963ac09d69417aa4df8202a38b4c9a44e9e4c7bb63cd9b9eff862e92bf5836 - Sigstore transparency entry: 200629818
- Sigstore integration time:
-
Permalink:
biagiodistefano/rule-engine@d6943896a98575bcd5a5cc26c5f0ad15c8cac13d -
Branch / Tag:
refs/tags/v1.2.0 - Owner: https://github.com/biagiodistefano
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi.yml@d6943896a98575bcd5a5cc26c5f0ad15c8cac13d -
Trigger Event:
release
-
Statement type:
File details
Details for the file light_rule_engine-1.2.0-py3-none-any.whl.
File metadata
- Download URL: light_rule_engine-1.2.0-py3-none-any.whl
- Upload date:
- Size: 20.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4e9e03042f1d42432310682f84ee3d6f7a31ef1671f648c44175b6a824d6bc60
|
|
| MD5 |
8079ae011ac0e7c5094b32dcf09822e8
|
|
| BLAKE2b-256 |
566d3f36fc7dcfcfea504ad06fd2d5ae8d1889701153c79b16dc0585ed381488
|
Provenance
The following attestation bundles were made for light_rule_engine-1.2.0-py3-none-any.whl:
Publisher:
pypi.yml on biagiodistefano/rule-engine
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
light_rule_engine-1.2.0-py3-none-any.whl -
Subject digest:
4e9e03042f1d42432310682f84ee3d6f7a31ef1671f648c44175b6a824d6bc60 - Sigstore transparency entry: 200629821
- Sigstore integration time:
-
Permalink:
biagiodistefano/rule-engine@d6943896a98575bcd5a5cc26c5f0ad15c8cac13d -
Branch / Tag:
refs/tags/v1.2.0 - Owner: https://github.com/biagiodistefano
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi.yml@d6943896a98575bcd5a5cc26c5f0ad15c8cac13d -
Trigger Event:
release
-
Statement type: