Skip to main content

A lightweight, chainable rule engine for Python

Project description

Rulify 🧠

A lightweight, chainable, and prioritized rule engine for Python that makes business logic management simple and elegant.

PyPI version Python 3.8+ License: MIT

🚀 Quick Start

pip install rulify
from rulify import Rule, RuleEngine

def is_hot(ctx): 
    return ctx["temp"] > 30

def turn_on_ac(ctx):
    ctx["ac"] = True
    print("AC turned ON")
    return ctx

# Create engine and add rules
engine = RuleEngine()
engine.add_rule(Rule("Hot Check", is_hot, turn_on_ac, priority=10))

# Run with context
context = {"temp": 35}
result = engine.run(context)
print(result)  # {'temp': 35, 'ac': True}

✨ Features

  • 🎯 Rule Prioritization: Execute rules in order of importance
  • 🔗 Rule Chaining: Chain rules together for complex workflows
  • ⚡ Lightweight: Zero external dependencies
  • 🐍 Pythonic: Clean, intuitive API design
  • 🔧 Flexible: Works with any Python data structure

📖 Documentation

Basic Usage

from rulify import Rule, RuleEngine

# Define conditions and actions
def is_high_temp(ctx): 
    return ctx.get("temp", 0) > 30

def cool_down(ctx): 
    ctx["ac"] = True
    ctx["fan_speed"] = "high"
    print("Cooling system activated")
    return ctx

def is_low_temp(ctx): 
    return ctx.get("temp", 0) < 20

def heat_up(ctx): 
    ctx["heater"] = True
    print("Heating system activated")
    return ctx

# Create engine and add rules
engine = RuleEngine()
engine.add_rule(Rule("Too Hot", is_high_temp, cool_down, priority=10))
engine.add_rule(Rule("Too Cold", is_low_temp, heat_up, priority=5))

# Process context
context = {"temp": 33}
result = engine.run(context)

Rule Chaining

def check_weather(ctx):
    return ctx.get("weather") == "rainy"

def grab_umbrella(ctx):
    ctx["umbrella"] = True
    print("Grabbed umbrella")
    return ctx

def check_location(ctx):
    return ctx.get("location") == "outdoor"

def stay_inside(ctx):
    ctx["location"] = "indoor"
    print("Staying inside")
    return ctx

# Chain rules together
umbrella_rule = Rule("Grab Umbrella", check_weather, grab_umbrella)
location_rule = Rule("Stay Inside", check_location, stay_inside, next_rule=umbrella_rule)

engine = RuleEngine()
engine.add_rule(location_rule)

context = {"weather": "rainy", "location": "outdoor"}
result = engine.run(context)

Advanced Example: E-commerce Order Processing

def is_vip_customer(ctx):
    return ctx.get("customer_tier") == "VIP"

def apply_vip_discount(ctx):
    ctx["discount"] = 0.15
    ctx["priority_shipping"] = True
    print("VIP discount applied")
    return ctx

def is_high_value_order(ctx):
    return ctx.get("order_total", 0) > 1000

def apply_bulk_discount(ctx):
    ctx["discount"] = ctx.get("discount", 0) + 0.10
    print("Bulk discount applied")
    return ctx

def is_express_shipping(ctx):
    return ctx.get("shipping_type") == "express"

def calculate_shipping_cost(ctx):
    base_cost = 10
    if ctx.get("priority_shipping"):
        base_cost += 5
    ctx["shipping_cost"] = base_cost
    return ctx

# Build order processing engine
engine = RuleEngine()
engine.add_rule(Rule("VIP Customer", is_vip_customer, apply_vip_discount, priority=20))
engine.add_rule(Rule("High Value", is_high_value_order, apply_bulk_discount, priority=15))
engine.add_rule(Rule("Express Shipping", is_express_shipping, calculate_shipping_cost, priority=10))

# Process order
order = {
    "customer_tier": "VIP",
    "order_total": 1200,
    "shipping_type": "express"
}

result = engine.run(order)
print(result)

🛠️ API Reference

RuleEngine

The main engine for managing and executing rules.

Methods

  • add_rule(rule): Add a rule to the engine
  • run(context): Execute all rules against the given context

Rule

Represents a single rule with condition, action, and metadata.

Constructor

Rule(name, condition, action, priority=0, next_rule=None)
  • name (str): Human-readable name for the rule
  • condition (callable): Function that returns True/False based on context
  • action (callable): Function to execute when condition is True
  • priority (int): Higher numbers execute first (default: 0)
  • next_rule (Rule): Optional rule to chain after this one

🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/AmazingFeature)
  3. Commit your changes (git commit -m 'Add some AmazingFeature')
  4. Push to the branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

🙏 Acknowledgments

  • Inspired by business rule engines and workflow management systems
  • Built with simplicity and performance in mind

Made with ❤️ by Ertuğrul Kara

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

rulify-0.1.1.tar.gz (14.3 kB view details)

Uploaded Source

Built Distribution

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

rulify-0.1.1-py3-none-any.whl (8.5 kB view details)

Uploaded Python 3

File details

Details for the file rulify-0.1.1.tar.gz.

File metadata

  • Download URL: rulify-0.1.1.tar.gz
  • Upload date:
  • Size: 14.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.7

File hashes

Hashes for rulify-0.1.1.tar.gz
Algorithm Hash digest
SHA256 29149921db2cb77fcd6a13e079dc318faa053523ad72cbf28037378b2faf8ed6
MD5 9040d3e00611ce18e50844a32c411280
BLAKE2b-256 345bb93709d756d98958bb3fed96d1b0229886e5af2e72d328371a86f920b781

See more details on using hashes here.

File details

Details for the file rulify-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: rulify-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 8.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.7

File hashes

Hashes for rulify-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 d5835b3f57349cfdf15dd63e74527fc5c0953e934bd4fd2c8d197c7811954d23
MD5 a91f151258bc244a6d327ad63c8b2330
BLAKE2b-256 b30f500a7dfc786e95b855925d5f00b2b8a6af9acb699d5928e5533548781959

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