GitHub - hardbyte/python-common-expression-language: Python wrapper of a Rust CEL implementation
Fast, Safe, and Expressive evaluation of Google's Common Expression Language (CEL) in Python, powered by Rust.
The Common Expression Language (CEL) is a non-Turing complete language designed for simplicity, speed, and safety. This Python package wraps the Rust implementation cel-interpreter v0.10.0, providing microsecond-level expression evaluation with seamless Python integration.
๐ Use Cases
- ๐ก๏ธ Policy Enforcement: Define access control rules that can be updated without code changes
- โ๏ธ Configuration Validation: Validate complex settings with declarative rules
- ๐ Data Transformation: Transform and filter data with safe, portable expressions
- ๐ Business Rules: Implement decision logic that business users can understand
- ๐ Query Filtering: Build dynamic filters for databases and APIs
- ๐ฏ Feature Flags: Create sophisticated feature toggle conditions
Installation
pip install common-expression-language
Or using uv:
uv add common-expression-language
After installation, both the Python library and the cel command-line tool will be available.
๐ Full Documentation: https://python-common-expression-language.readthedocs.io/
Quick Start
Python API
from cel import evaluate # Simple expressions result = evaluate("1 + 2") # 3 result = evaluate("'Hello ' + 'World'") # "Hello World" result = evaluate("age >= 18", {"age": 25}) # True # Complex expressions with context result = evaluate( 'user.role == "admin" && "write" in permissions', { "user": {"role": "admin"}, "permissions": ["read", "write", "delete"] } ) # True
Command Line Interface
# Simple evaluation cel '1 + 2' # 3 # With context cel 'age >= 18' --context '{"age": 25}' # true # Interactive REPL cel --interactive
Pre-compilation for Performance
When evaluating the same expression multiple times with different contexts, use compile() for better performance:
import cel # Compile once program = cel.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
from cel import Context, evaluate def calculate_discount(price, rate): return price * rate context = Context() context.add_function("calculate_discount", calculate_discount) context.add_variable("price", 100) result = evaluate("price - calculate_discount(price, 0.1)", context) # 90.0
Real-World Example
from cel import evaluate, Context # Access control policy policy = """ user.role == "admin" || (resource.owner == user.id && current_hour >= 9 && current_hour <= 17) """ context = Context() context.update({ "user": {"id": "alice", "role": "user"}, "resource": {"owner": "alice"}, "current_hour": 14 # 2 PM }) access_granted = evaluate(policy, context) # True
Features
- โ Fast Evaluation: Microsecond-level expression evaluation via Rust
- โ Rich Type System: Integers, floats, strings, lists, maps, timestamps, durations
- โ Python Integration: Seamless type conversion and custom function support
- โ CLI Tools: Interactive REPL and batch processing capabilities
- โ Safety First: Non-Turing complete, safe for untrusted expressions
Documentation
๐ Complete documentation available at: https://python-common-expression-language.readthedocs.io/
Building Documentation Locally
To build and serve the documentation locally:
# Install documentation dependencies uv sync --group docs # Build the documentation uv run --group docs mkdocs build # Serve locally with live reload uv run --group docs mkdocs serve
The documentation will be available at http://localhost:8000
Development
Testing
# Run all tests uv run pytest # Run with coverage uv run pytest --cov=cel # Test all documentation examples (embedded code + standalone files) uv run --group docs pytest tests/test_docs.py -v
Building from Source
# Install development dependencies uv sync --dev # Build the package uv run maturin develop # Run tests uv run pytest
Contributing
Contributions are welcome! Please see our documentation for:
- CHANGELOG โ release notes and behaviour changes
- Development setup and guidelines
- Areas where help is needed
License
This project is licensed under the same terms as the original cel-interpreter crate.