Skip to content

execute_rule: triggered rules crash with stock PyPI deps (business_rules_enhanced passes results=; COREActions expects record-wise iteration) #1846

Description

@yanmingyu92

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    Priority

    None yet

    T-shirt sizing

    None yet

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions