Environment
cdisc-rules-engine==0.17.1 (PyPI), Python 3.12
business_rules_enhanced==1.4.8 (pulled by the >=1.4.8 requirement)
- Reproduced on Windows and Linux
Summary
RulesEngine.execute_rule evaluates conditions correctly (row-wise, observed via a PandasDataset + DatasetVariable), but any rule whose conditions trigger crashes in the action-dispatch path, making the engine unable to complete a triggered rule with stock PyPI dependencies.
Finding 1 ??action signature mismatch
business_rules/engine.py (do_actions, line ~119) calls
method(**params, results=results) unconditionally, but COREActions.generate_record_message(self, message, target=None) (cdisc_rules_engine/models/actions.py, ~line 38) does not accept results ??TypeError on every triggered rule.
Finding 2 ??missing record-wise iteration
After working around Finding 1 (subclass adding **kwargs and forwarding), generate_record_message fails with:
AttributeError: 'PatchedCOREActions' object has no attribute 'record'
The action dereferences self.record.get('row'), i.e. it expects the runtime to set .record per row before invoking actions. The PyPI business_rules_enhanced 1.4.8 do_actions does not perform record-wise iteration.
Minimal reproducer
# pip install cdisc-rules-engine==0.17.1 pandas
import pandas as pd
from cdisc_rules_engine.models.dataset import PandasDataset
from cdisc_rules_engine.models.rule_conditions.condition_composite_factory import (
ConditionCompositeFactory,
)
from cdisc_rules_engine.models.sdtm_dataset_metadata import SDTMDatasetMetadata
from cdisc_rules_engine.rules_engine import RulesEngine
df = pd.DataFrame({"STUDYID": ["S1", "S2", "S3"], "A": ["1", "", "3"]}).fillna("")
rule = {
"core_id": "REPRO-1",
"conditions": {
"all": [
{
"name": "get_dataset",
"operator": "exists",
"value": {"target": "A", "comparator": "A"},
}
]
},
"operations": [],
"actions": [
{
"name": "generate_record_message",
"params": {"message": "A is empty", "target": "A"},
}
],
}
rule["conditions"] = ConditionCompositeFactory.get_condition_composite(rule["conditions"])
results = RulesEngine().execute_rule(
rule,
PandasDataset(df.copy()),
SDTMDatasetMetadata(name="DM", filename="dm.xpt", record_count=len(df)),
)
print(results)
# -> TypeError: COREActions.generate_record_message() got an unexpected keyword argument 'results'
(Data path note: the same behavior was observed feeding a real SDTM domain via pandas.read_sas(path, format="xport").)
Question
Is the CORE application shipping a patched/forked business_rules runtime that provides the record-wise iteration and tolerates the results kwarg? If so, would you consider pinning that runtime as a wheel dependency so the MIT engine is runnable from PyPI as published? Happy to turn the reproducer into a unit test if useful.
Environment
cdisc-rules-engine==0.17.1(PyPI), Python 3.12business_rules_enhanced==1.4.8(pulled by the>=1.4.8requirement)Summary
RulesEngine.execute_ruleevaluates conditions correctly (row-wise, observed via aPandasDataset+DatasetVariable), but any rule whose conditions trigger crashes in the action-dispatch path, making the engine unable to complete a triggered rule with stock PyPI dependencies.Finding 1 ??action signature mismatch
business_rules/engine.py(do_actions, line ~119) callsmethod(**params, results=results)unconditionally, butCOREActions.generate_record_message(self, message, target=None)(cdisc_rules_engine/models/actions.py, ~line 38) does not acceptresults??TypeErroron every triggered rule.Finding 2 ??missing record-wise iteration
After working around Finding 1 (subclass adding
**kwargsand forwarding),generate_record_messagefails with:The action dereferences
self.record.get('row'), i.e. it expects the runtime to set.recordper row before invoking actions. The PyPIbusiness_rules_enhanced1.4.8do_actionsdoes not perform record-wise iteration.Minimal reproducer
(Data path note: the same behavior was observed feeding a real SDTM domain via
pandas.read_sas(path, format="xport").)Question
Is the CORE application shipping a patched/forked
business_rulesruntime that provides the record-wise iteration and tolerates theresultskwarg? If so, would you consider pinning that runtime as a wheel dependency so the MIT engine is runnable from PyPI as published? Happy to turn the reproducer into a unit test if useful.