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.
🚀 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 enginerun(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 rulecondition(callable): Function that returns True/False based on contextaction(callable): Function to execute when condition is Truepriority(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.
- Fork the repository
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - 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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
29149921db2cb77fcd6a13e079dc318faa053523ad72cbf28037378b2faf8ed6
|
|
| MD5 |
9040d3e00611ce18e50844a32c411280
|
|
| BLAKE2b-256 |
345bb93709d756d98958bb3fed96d1b0229886e5af2e72d328371a86f920b781
|
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d5835b3f57349cfdf15dd63e74527fc5c0953e934bd4fd2c8d197c7811954d23
|
|
| MD5 |
a91f151258bc244a6d327ad63c8b2330
|
|
| BLAKE2b-256 |
b30f500a7dfc786e95b855925d5f00b2b8a6af9acb699d5928e5533548781959
|