Skip to main content

This is an expression language python package.

Project description

Dilemma Expression Language

CI codecov PyPI version Python 3.12+

A secure, powerful expression evaluation engine for Python applications that makes complex logical expressions readable and maintainable.

Why Dilemma?

Instead of writing complex Python conditionals like this:

if (user.get('profile', {}).get('age', 0) >= 18 and 
    user.get('subscription', {}).get('status') == 'active' and
    datetime.now() - user.get('last_login', datetime.min) < timedelta(days=30)):
    # grant access
    pass

Write this:

from dilemma import evaluate

expr = "user.profile.age >= 18 and user.subscription.status == 'active' and user.last_login upcoming within 30 days"

if evaluate(expr, context):
    # grant access
    pass

Features

  • Secure evaluation - No arbitrary code execution, only safe expressions
  • Rich data access - Navigate nested dictionaries and lists with ease
  • Date/time operations - Natural language date comparisons
  • Multiple resolvers - JsonPath, JQ, and basic dictionary lookup
  • Performance optimized - Compile expressions once, evaluate many times
  • Type safe - Built-in type checking and validation

Quick Start

pip install dilemma
from dilemma import evaluate

# Basic arithmetic and logic
result = evaluate("2 * (3 + 4)")  # Returns 14
result = evaluate("age >= 18 and status == 'active'", {"age": 25, "status": "active"})

# Date operations
result = evaluate("user.last_login upcoming within 7 days", context)
result = evaluate("subscription.end_date is $future", context)

# Complex data access
result = evaluate("user.permissions contains 'admin'", context)
result = evaluate("`[.users[] | select(.active == true) | .name] | length` > 0", context)

Language Features

All Language Features. Extensive Examples.

Data Access Patterns

# Dot notation for nested objects
"user.profile.settings.theme == 'dark'"

# Natural possessive syntax  
"user's subscription's status == 'premium'"

# Array/list access
"users[0].name == 'Alice'"

# Check membership
"'admin' in user.roles"
"user.permissions contains 'read'"

Date and Time Operations

# Relative time checks
"user.created_at upcoming within 30 days"
"order.shipped_date older than 1 week"

# State comparisons
"subscription.expires is $future"
"last_backup is $past"
"meeting.date is $today"

# Date comparisons
"start_date before end_date"
"event.date same_day_as $now"

Advanced JQ Integration

For complex data manipulation, use JQ expressions in backticks:

# Filter and transform arrays - working with provided context
evaluate('`[.users[] | select(.active == true) | .name]`', context)

# Mathematical operations on arrays  
evaluate('`[.sales[].amount] | add` > 10000', context)

# Complex conditionals
evaluate('`[.products[] | select(.price > 100 and .category == "electronics")] | length` > 1', context)

Performance Optimization

For repeated evaluations, compile expressions once:

from dilemma import compile_expression

# Compile once
eligibility_check = compile_expression(
    "user.age >= 18 and user.subscription.active and user.last_login upcoming within 30 days"
)

# Evaluate many times with different contexts
for user_data in users:
    if eligibility_check.evaluate(user_data):
        # send_premium_content(user_data)
        pass

Error Handling

Dilemma provides clear, actionable error messages:

try:
    result = evaluate("user.invalidfield == 'test'", context)
except VariableError as e:
    print(f"Expression error: {e}")
    # Suggests available fields and common fixes

Use Cases

  • Form validation rules - "email like '*@*' and age >= 13"
  • Business logic - "order.total > 100 and customer.tier == 'premium'"
  • Access control - "user.roles contains 'admin' or resource.owner == user.id"
  • Data filtering - "created_at upcoming within 24 hours and status == 'pending'"
  • Workflow conditions - "approval.status == 'approved' and budget.remaining >= cost"

Safety & Security

  • ✅ No arbitrary Python code execution
  • ✅ No access to imports or builtins
  • ✅ Sandboxed evaluation environment
  • ✅ Input validation and sanitization
  • ✅ Memory and complexity limits

License

MIT License - see LICENSE file for details.

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

dilemma-0.3.5.tar.gz (135.4 kB view details)

Uploaded Source

Built Distribution

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

dilemma-0.3.5-py3-none-any.whl (36.4 kB view details)

Uploaded Python 3

File details

Details for the file dilemma-0.3.5.tar.gz.

File metadata

  • Download URL: dilemma-0.3.5.tar.gz
  • Upload date:
  • Size: 135.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.5

File hashes

Hashes for dilemma-0.3.5.tar.gz
Algorithm Hash digest
SHA256 2f8c3ef28e67d504ec1854d108c72101d3d649f1ba93e5e99d2313328fbcf76d
MD5 35956e63fba33d7bb4ee8d1cb0b68163
BLAKE2b-256 63c4a1ec3af6d9b4e1ad4c92587d24f99613e561f2c6d6967e1926fe38fabcae

See more details on using hashes here.

File details

Details for the file dilemma-0.3.5-py3-none-any.whl.

File metadata

  • Download URL: dilemma-0.3.5-py3-none-any.whl
  • Upload date:
  • Size: 36.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.5

File hashes

Hashes for dilemma-0.3.5-py3-none-any.whl
Algorithm Hash digest
SHA256 4e5c129d2eca98b4431f2f2d2d68d686d90efb6ae6b5afa42c8cb7ed36874eaf
MD5 c431e5a3c5b673ea062bcd6ad81e90ab
BLAKE2b-256 618c2fbd744267891fe8a7a69aa479e147a9b6e478e0657004f57a65c7ffd81c

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