Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,21 @@ cel 'age >= 18' --context '{"age": 25}' # true
cel --interactive
```

### Pre-compilation for Performance

When evaluating the same expression multiple times with different contexts, use `compile()` for better performance:

```python
from cel import compile

# Compile once
program = compile("price * quantity > threshold")

# Execute many times - much faster than repeated evaluate() calls
result1 = program.execute({"price": 10, "quantity": 5, "threshold": 40}) # True
result2 = program.execute({"price": 5, "quantity": 3, "threshold": 20}) # False
```

### Custom Functions

```python
Expand Down
19 changes: 19 additions & 0 deletions docs/getting-started/quick-start.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,25 @@ assert result == "No phone" # → "No phone" (safe field checking prevents erro
print("✓ Context variables working correctly")
```

## Pre-compilation for Performance

Use `compile()` when evaluating the same expression many times with different contexts:

```python
from cel import compile

# Compile once, execute many times
program = compile("price * quantity > threshold")

result1 = program.execute({"price": 10, "quantity": 5, "threshold": 40})
assert result1 == True # → True (50 > 40)

result2 = program.execute({"price": 5, "quantity": 3, "threshold": 20})
assert result2 == False # → False (15 > 20)

print("Pre-compilation working correctly")
```

## Ready for More?

You've mastered the basics of CEL evaluation with dictionary context! For advanced features like custom Python functions, context objects, and production patterns, continue to the next guide.
Expand Down
119 changes: 118 additions & 1 deletion docs/reference/python-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,125 @@ Complete autogenerated reference for the Python CEL library.

::: cel.evaluate

### compile(expression: str) -> Program

## Classes
Compile a CEL expression into a reusable Program object.

This function parses and compiles a CEL expression, returning a Program object that can be executed multiple times with different contexts. This is more efficient than calling `evaluate()` repeatedly with the same expression.

**Parameters:**
- `expression`: The CEL expression to compile

**Returns:**
- A compiled `Program` object

**Raises:**
- `ValueError`: If the expression has syntax errors or is malformed

**Example:**
```python
from cel import compile

# Compile once
program = compile("x + y")

# Execute many times with different contexts
result1 = program.execute({"x": 1, "y": 2})
assert result1 == 3 # → 3

result2 = program.execute({"x": 10, "y": 20})
assert result2 == 30 # → 30
```

**When to use `compile()` vs `evaluate()`:**

- Use `evaluate()` for one-time evaluation or interactive/REPL usage
- Use `compile()` + `execute()` when evaluating the same expression with many different contexts or in performance-critical loops

## Classes

### Program

**A compiled CEL program that can be executed multiple times with different contexts.**

The Program class represents a pre-compiled CEL expression. Use this when you need to evaluate the same expression many times with different variable bindings. Compiling once and executing multiple times is significantly faster than calling `evaluate()` repeatedly.

```python
from cel import compile

# Compile the expression once
program = compile("price * quantity > 100")

# Execute many times with different contexts
result1 = program.execute({"price": 10, "quantity": 20})
assert result1 == True # → True (200 > 100)

result2 = program.execute({"price": 5, "quantity": 10})
assert result2 == False # → False (50 > 100)
```

#### Methods

##### execute(context=None) -> Any

Execute the compiled program with the given context.

**Parameters:**
- `context`: Optional evaluation context (dict or Context object)

**Returns:**
- The result of the expression evaluation

**Raises:**
- `RuntimeError`: If a variable or function is undefined
- `TypeError`: If there's a type mismatch during execution
- `ValueError`: If the context is an invalid type

**Example with dict context:**
```python
from cel import compile

program = compile("user.name + ' is ' + user.role")
result = program.execute({
"user": {"name": "Alice", "role": "admin"}
})
assert result == "Alice is admin"
```

**Example with Context object:**
```python
from cel import compile, Context

program = compile("greet(name)")

ctx = Context()
ctx.add_variable("name", "World")
ctx.add_function("greet", lambda x: f"Hello, {x}!")

result = program.execute(ctx)
assert result == "Hello, World!"
```

**Performance pattern - compile once, execute many:**
```python
from cel import compile

# Access control policy - compiled once at startup
policy = compile(
'user.role == "admin" || resource.owner == user.id'
)

# Evaluated many times per request
def check_access(user, resource):
return policy.execute({"user": user, "resource": resource})

# Fast repeated evaluation
assert check_access({"id": "alice", "role": "admin"}, {"owner": "bob"}) == True
assert check_access({"id": "bob", "role": "user"}, {"owner": "bob"}) == True
assert check_access({"id": "charlie", "role": "user"}, {"owner": "bob"}) == False
```

---

### Context

Expand Down
Loading