Skip to main content

Evaluate rules based on a subject

Project description

Python Simple Rules Engine

rogervila/docker-smtp-server

Coverage Quality Gate Status Maintainability Rating

Evaluate rules based on a subject.

Install

pip install python_simple_rules_engine

Usage

The package expects a subject and a list of rules.

Each rule must be a class that extends AbstractRule.

The subject parameter can be any type of object (Any)

Basic usage

Rules return a Evaluation object that should contain a result property defined by the user.

Also, the user can define the value of the stop property to determine if the evaluation process should stop or continue.

In this example, the stop property value does not affect the evaluation process since we are evaluating only one rule.

from python_simple_rules_engine import AbstractRule, Evaluation, run

class FooRule(AbstractRule):
    def evaluate(self, subject, previous_evaluation: Evaluation = None) -> Evaluation:
        return Evaluation({
            'stop': False, # False by default. When set to True, the evaluation process is stopped.
            'result': (subject == 'foo') # Any. It should contain the evaluation result defined by the user.
        })

evaluation = run('foo', [FooRule()])

print(evaluation.result) # True
print(evaluation.rule) # FooRule instance

Advanced usage

When evaluating multiple rules you can retrieve the historic of rules evaluated for a specific evaluation process by passing the with_history parameter as True.

The final Evaluation object will contain a history list with evaluations returned by the rules evaluated during the evaluation process.

Check test_evaluation_with_history method on tests/test_python_simple_rules_engine.py for a more detailed implementation.

rules = [RuleA(), RuleB(), RuleC()]

# Let's pretend that the final evaluation comes from RuleC()
evaluation = run('C', rules, with_history=True)

print(len(evaluation.history)) # 2
print(evaluation.history[0].rule) # RuleA instance
print(evaluation.history[1].rule) # RuleB instance

Examples

The examples are very simple for demo purposes, but they show the basic features this package comes with.

There is another python rules engine called durable rules that comes with some examples. We will recreate them with this package.

Pattern matching

Find a credit card type based on its number.

Check test_match_example_with_cards method on tests/test_python_simple_rules_engine.py for a more detailed implementation.

class Card():
    def __init__(self, number):
        self.number = number

amex = Card('375678956789765')
visa = Card('4345634566789888')
mastercard = Card('2228345634567898')

class AmexRule(AbstractRule):
    def evaluate(self, subject, previous_evaluation: Evaluation = None) -> Evaluation:
        card_type = None

        if re.match(r"3[47][0-9]{13}", subject.number):
            card_type = 'amex'

        return Evaluation({'stop': (card_type != None), 'result': card_type})

class VisaRule(AbstractRule):
    def evaluate(self, subject, previous_evaluation: Evaluation = None) -> Evaluation:
        card_type = None

        if re.match(r"4[0-9]{12}([0-9]{3})?", subject.number):
            card_type = 'visa'

        return Evaluation({'stop': (card_type != None), 'result': card_type})

class MasterCardRule(AbstractRule):
    def evaluate(self, subject, previous_evaluation: Evaluation = None) -> Evaluation:
        card_type = None

        if re.match(r"(5[1-5][0-9]{2}|222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|2720)[0-9]{12}", subject.number):
            card_type = 'mastercard'

        return Evaluation({'stop': (card_type != None), 'result': card_type})

# rules order does not affect the result.
rules = [AmexRule(), VisaRule(), MasterCardRule()]

evaluation = run(amex, rules)
print(evaluation.result) # 'amex'
print(evaluation.rule.__class__.__name__) # 'AmexRule'

evaluation = run(visa, rules)
print(evaluation.result) # 'visa'
print(evaluation.rule.__class__.__name__) # 'VisaRule'

evaluation = run(mastercard, rules)
print(evaluation.result) # 'mastercard'
print(evaluation.rule.__class__.__name__) # 'MasterCardRule'

Set of facts

Define the type of an animal based on facts.

In this case, we will compare the current rule result with the previous evaluation result. If they match, we stop the evaluation process.

Check test_facts_example method on tests/test_python_simple_rules_engine.py for a more detailed implementation.

class Animal():
    def __init__(self, eats, lives, color):
        self.eats = eats
        self.lives = lives
        self.color = color

frog = Animal('flies', 'water', 'green')
bird = Animal('worms', 'nest', 'black')

class EatsRule(AbstractRule):
    facts = {'flies': 'frog', 'worms': 'bird'}

    def evaluate(self, subject, previous_evaluation: Evaluation = None) -> Evaluation:
        previous_result = previous_evaluation.result if previous_evaluation is not None else None
        current_result = self.facts[getattr(subject, 'eats')]

        return Evaluation({'stop': (previous_result == current_result), 'result': current_result})

class LivesRule(AbstractRule):
    facts = {'water': 'frog', 'nest': 'bird'}

    def evaluate(self, subject, previous_evaluation: Evaluation = None) -> Evaluation:
        previous_result = previous_evaluation.result if previous_evaluation is not None else None
        current_result = self.facts[getattr(subject, 'lives')]

        return Evaluation({'stop': (previous_result == current_result), 'result': current_result})

class ColorRule(AbstractRule):
    facts = {'green': 'frog', 'black': 'bird'}

    def evaluate(self, subject, previous_evaluation: Evaluation = None) -> Evaluation:
        previous_result = previous_evaluation.result if previous_evaluation is not None else None
        current_result = self.facts[getattr(subject, 'color')]

        return Evaluation({'stop': (previous_result == current_result), 'result': current_result})

# rules order does not affect the result.
rules = [EatsRule(), ColorRule(), LivesRule()]

evaluation = run(frog, rules)
print(evaluation.result) # 'frog'

evaluation = run(bird, rules)
print(evaluation.result) # 'bird'

License

This project is open-sourced software licensed under the MIT license.

Icons made by Gregor Cresnar from www.flaticon.com

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

python_simple_rules_engine-0.3.0.tar.gz (4.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

python_simple_rules_engine-0.3.0-py3-none-any.whl (5.0 kB view details)

Uploaded Python 3

File details

Details for the file python_simple_rules_engine-0.3.0.tar.gz.

File metadata

  • Download URL: python_simple_rules_engine-0.3.0.tar.gz
  • Upload date:
  • Size: 4.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.4.2 importlib_metadata/4.6.3 pkginfo/1.7.1 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.62.0 CPython/3.9.6

File hashes

Hashes for python_simple_rules_engine-0.3.0.tar.gz
Algorithm Hash digest
SHA256 7880e547f4729bd28dccf5bf08698e78da527cce340bcae6887d033269e02dec
MD5 c75dd6bce0f44b3109379c44d6a5c7e0
BLAKE2b-256 a79f57b1a0cd503e39a41ce5fb47b30566dea70c576e85f302c12a5ccc1fd20e

See more details on using hashes here.

File details

Details for the file python_simple_rules_engine-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: python_simple_rules_engine-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 5.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.4.2 importlib_metadata/4.6.3 pkginfo/1.7.1 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.62.0 CPython/3.9.6

File hashes

Hashes for python_simple_rules_engine-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 18119404da4b48faf98d0f66ab5f0111dcbec386e9282958c0bfbf9be63ea4b6
MD5 1c977f31a651badaa4d232740d56a8f3
BLAKE2b-256 435c23c7d3a31e3adb80a772f631e29923a198ebd780a258b80d2690d6e2312b

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page