rulify 0.1.1
A lightweight, chainable rule engine for Python
License: MIT
Requires Python: >=3.8
Keywords: rule engine, rules, business logic, workflow, automation, python

# Rulify 🧠

A lightweight, chainable, and prioritized rule engine for Python that makes business logic management simple and elegant.

[![PyPI version](https://badge.fury.io/py/rulify.svg)](https://badge.fury.io/py/rulify)
[![Python 3.8+](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/downloads/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

## 🚀 Quick Start

```bash
pip install rulify
```

```python
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

```python
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

```python
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

```python
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

```python
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](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](https://github.com/ertugrulkra)**