Skip to content

Commit

Permalink
__doc__
Browse files Browse the repository at this point in the history
  • Loading branch information
saurabh0719 committed Dec 14, 2023
1 parent b4888b1 commit 8055586
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 46 deletions.
57 changes: 37 additions & 20 deletions py_rules/components.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,3 @@
"""
This module, `components.py`, contains component classes for building rules, conditions, and results for a rule engine.
Classes:
- Condition: Represents a condition in a rule. It supports logical `and` and `or` operations.
- Result: Represents a result of a rule. It supports the `and` operation.
- Rule: Represents a rule. A rule consists of an 'if' condition and 'then' and 'else' results. The 'then' and 'else' results are executed when the 'if' condition is met or not met, respectively.
Each class provides a `to_dict` method for converting the object to a dictionary, which can be useful for storing the object in a database or file, or for converting the object to JSON.
The `Rule` class also provides `save_to_file` and `load_from_file` methods for saving the rule to a file and loading the rule from a file, respectively.
Example usage:
condition = Condition('number', 'in', [1, 2, 3]) & Condition('number', '=', 1) & \
Condition('number', '=', 1) | Condition('number', '=', 2)
result = Result('xyz', 'str', 'Condition met') & Result('result', 'variable', 'xyz')
rule1 = Rule('Complex rule').If(condition).Then(result).Else(result)
print(rule1.to_dict())
"""

import datetime
import uuid
from abc import ABC, abstractmethod
Expand All @@ -28,6 +8,10 @@


class RuleComponent(ABC):
"""
Abstract base class for all rule components.
Each component has a unique ID, a version, a set of required context parameters, and optional metadata.
"""

def __init__(self, *args, **kwargs):
self.args = args
Expand All @@ -52,6 +36,13 @@ def load_metadata(self):


class Condition(RuleComponent):
"""
Represents a condition in a rule.
A condition has a variable, an operator, and a value.
The variable is a string that represents a parameter in the context.
The operator is a string that represents a comparison operator.
The value is the value to compare the variable to.
"""

def __init__(self, variable=None, operator=None, value=None, *args, **kwargs):
super().__init__(*args, **kwargs)
Expand Down Expand Up @@ -95,6 +86,10 @@ def to_dict(self):


class AndCondition(RuleComponent):
"""
Represents a logical 'and' of two conditions.
An AndCondition has two conditions, and evaluates to True if both conditions are True.
"""

def __init__(self, condition1: Condition, condition2: Condition):
super().__init__()
Expand All @@ -114,6 +109,10 @@ def to_dict(self):


class OrCondition(RuleComponent):
"""
Represents a logical 'or' of two conditions.
An OrCondition has two conditions, and evaluates to True if either condition is True.
"""

def __init__(self, condition1: Condition, condition2: Condition):
super().__init__()
Expand All @@ -133,6 +132,13 @@ def to_dict(self):


class Result(RuleComponent):
"""
Represents a result of a rule.
A result has a key, a type, and a value.
The key is a string that represents a parameter in the context.
The type is a string that represents the type of the value.
The value is the value to set the parameter to if the rule is applied.
"""

def __init__(self, key=None, vtype=None, value=None, result=None, *args, **kwargs):
super().__init__(*args, **kwargs)
Expand All @@ -152,6 +158,10 @@ def to_dict(self):


class AndResult(RuleComponent):
"""
Represents a logical 'and' of two results.
An AndResult has two results, and evaluates to a combined result if both results are True.
"""

def __init__(self, result1, result2):
super().__init__()
Expand All @@ -171,6 +181,13 @@ def to_dict(self):


class Rule(RuleComponent):
"""
Represents a rule.
A rule has a name, an 'if' condition, a 'then' result, and an optional 'else' result.
The 'if' condition is a Condition that is evaluated to determine whether to apply the rule.
The 'then' result is a Result that is applied if the 'if' condition is True.
The 'else' result is a Result that is applied if the 'if' condition is False.
"""

def __init__(self, name, *args, **kwargs):
super().__init__(*args, **kwargs)
Expand Down
39 changes: 14 additions & 25 deletions py_rules/engine.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,3 @@
"""
This module, `engine.py`, contains the `RuleEngine` class which is used to evaluate a parsed rule.
The `RuleEngine` class takes a `Rule` object and a context (a dictionary) as input. The context is used to evaluate the conditions in the rule.
The `RuleEngine` class provides several methods:
- `__init__`: Initializes the `RuleEngine` with a rule and a context. It also validates the context.
- `_validate_context`: Validates the context. It checks if the context is a dictionary and if it contains all the required parameters specified in the rule's metadata.
- `evaluate_result`: Builds a result dictionary from the action schema or returns a default boolean value.
- `evaluate_condition_block`: Evaluates a condition block. It supports logical `and` and `or` operations.
- `evaluate`: Evaluates the rule. It checks the 'if' condition and returns the result of the 'then' action if the condition is met, or the result of the 'else' action otherwise.
Example usage:
rule = Rule('Temperature Rule').If(Condition('temperature', '>', 30)).Then(Result('message', 'str', 'It is hot!'))
context = {'temperature': 35}
engine = RuleEngine(rule, context)
print(engine.evaluate()) # prints: {'message': 'It is hot!'}
This will create a rule that checks if the temperature is greater than 30. The context provides the actual temperature. The `RuleEngine` evaluates the rule in the given context and returns the result of the rule.
"""

from .__version__ import __version__
from .components import Rule
from .condition import RuleCondition
Expand All @@ -30,12 +7,24 @@

class RuleEngine:
"""
Class to evaluate a parsed rule.
Class to evaluate a Rule component.
Takes a `Rule` object and a context (a dictionary) as input. The context is used to evaluate the conditions in the rule.
- `evaluate`: Evaluates the rule. It checks the 'if' condition and returns the result of the 'then' action if the condition is met, or the result of the 'else' action otherwise.
Example usage:
rule = Rule('Temperature Rule').If(Condition('temperature', '>', 30)).Then(Result('message', 'str', 'It is hot!'))
context = {'temperature': 35}
engine = RuleEngine(rule, context)
print(engine.evaluate()) # prints: {'message': 'It is hot!'}
This will create a rule that checks if the temperature is greater than 30. The context provides the actual temperature. The `RuleEngine` evaluates the rule in the given context and returns the result of the rule.
"""

def __init__(self, rule: Rule, context: dict) -> None:
"""
Initialize the RuleEngine with a context
Initialize the RuleEngine with a context dict
Args:
rule (Rule): The rule to evaluate
Expand Down
16 changes: 15 additions & 1 deletion py_rules/errors.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,32 @@
class InvalidRuleValueError(ValueError):
"""
Exception raised when a rule's value is invalid or inappropriate.
"""
pass


class InvalidRuleConditionError(ValueError):
"""
Exception raised when a rule's condition is invalid or inappropriate.
"""
pass


class InvalidRuleExpressionError(ValueError):
"""
Exception raised when a rule's expression (combination of conditions and results) is invalid or inappropriate.
"""
pass


class InvalidRuleError(ValueError):
"""
Exception raised when a rule is invalid or inappropriate. This is a general exception for rule-related errors.
"""
pass


class InvalidRuleValueTypeError(ValueError):
pass
"""
Exception raised when a rule's value type is invalid or inappropriate.
"""

0 comments on commit 8055586

Please sign in to comment.