Skip to main content

No project description provided

Project description

Common Expression Language (Python)

The Common Expression Language (CEL) is a non-Turing complete language designed for simplicity, speed, safety, and portability. CEL's C-like syntax looks nearly identical to equivalent expressions in C++, Go, Java, and TypeScript. CEL is ideal for lightweight expression evaluation when a fully sandboxed scripting language is too resource intensive.

// Check whether a resource name starts with a group name.
resource.name.startsWith("/groups/" + auth.claims.group)
// Determine whether the request is in the permitted time window.
request.time - resource.age < duration("24h")
// Check whether all resource names in a list match a given filter.
auth.claims.email_verified && resources.all(r, r.startsWith(auth.claims.email))

Installing

pip install cel-bind

Overview

Determine the variables and functions you want to provide to CEL. Parse and check an expression to make sure it's valid. Then evaluate the output AST against some input.

Environment setup

Let's expose name and group variables to CEL:

import cel

env = {
    "name": cel.StringType(),
    "group": cel.StringType(),
}

Parse and Check

The parsing phase indicates whether the expression is syntactically valid and expands any macros present within the environment. Parsing and checking are more computationally expensive than evaluation, and it is recommended that expressions be parsed and checked ahead of time.

The parse and check phases are combined for convenience into the compile_to_checked_expr step:

pool = cel.DescriptorPool()
compiler = cel.Compiler(pool, env, None)
try:
    checked_expr = compiler.compile_to_checked_expr('name.startsWith("/groups/" + group)')
except Exception as e:
    logging.fatal("compiling error", exc_info=True)
    exit(1)

Evaluate

Build the expression plan with build_expression_plan and reuse it for multiple evaluations of the same expression:

interpreter = cel.Interpreter(pool, env, None)
expr_plan = interpreter.build_expression_plan(checked_expr)

res = interpreter.evaluate(expr_plan, {
    "name": "/groups/acme.co/documents/secret-stuff",
    "group": "acme.co"
})

print(res) # True

Objects

cel-bind supports the use of structured objects in its CEL type-checking and evaluation. First, declare the object type and add it to a cel.DescriptorPool:

schema = """
{
  "type": "Person",
  "properties": {
    "name": {
      "type": "string"
    },
    "age": {
      "type": "integer"
    },
    "hobbies": {
      "type": "array",
      "items": {
        "type": "string"
      }
    }
  },
  "required": ["name", "age"]
}
"""


pool = cel.DescriptorPool()
person_type = pool.add_json_schema("person", schema)

Then, use the returned object type when declaring your CEL environment:

env = {
    "person": person_type,
}

compiler = cel.Compiler(pool, env, None)
checked_expr = compiler.compile_to_checked_expr('person.age > 18')

Currently, only JSON schema is supported when declaring objects.

Extending CEL

Extension functions can be written in Python and then made available to CEL by registering it to a cel.FunctionRegistry:

def is_hiker(person):
    return "hiking" in person["hobbies"]

function_registry = cel.FunctionRegistry()
function_registry.add_function(
    "is_hiker",
    is_hiker,
    cel.BoolType(), # return type
    [person_type], # arguments type
)

Then use it in your CEL expression:

env = {
    "person": person_type,
}

compiler = cel.Compiler(pool, env, function_registry)
try:
    checked_expr = compiler.compile_to_checked_expr('person.age > 18 && is_hiker(person)')
except Exception as e:
    logging.fatal("compiling error", exc_info=True)
    exit(1)

interpreter = cel.Interpreter(pool, env, function_registry)
expr_plan = interpreter.build_expression_plan(checked_expr)

res = interpreter.evaluate(expr_plan, {
    "person": {
        "name": "Alice",
        "age": 20,
        "hobbies": ["cooking", "hiking"]
    }
})
print(res) # True

Type checking

Compiler.compile_to_checked_expr will raise an Exception if type checking fails. Some examples of of type checking errors are:

  • undefined object fields

    RuntimeError: ERROR: :1:7: undefined field 'last_name' not found in struct 'person_pkg.person'
    | person.last_name
    | ......^
    
  • undeclared reference:

    RuntimeError: ERROR: :1:1: undeclared reference to 'undeclared_var' (in container '')
    | undeclared_var > 5
    | ^
    
  • functions applied to incorrect types:

    RuntimeError: ERROR: :1:12: found no matching overload for '_==_' applied to '(int, string)'
    | person.age == "5"
    | ...........^
    

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

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

cel_bind-0.4.7-cp312-cp312-manylinux_2_35_x86_64.whl (2.9 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.35+ x86-64

cel_bind-0.4.7-cp312-cp312-macosx_14_0_arm64.whl (2.2 MB view details)

Uploaded CPython 3.12macOS 14.0+ ARM64

cel_bind-0.4.7-cp311-cp311-manylinux_2_35_x86_64.whl (2.9 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.35+ x86-64

cel_bind-0.4.7-cp311-cp311-macosx_14_0_arm64.whl (2.2 MB view details)

Uploaded CPython 3.11macOS 14.0+ ARM64

cel_bind-0.4.7-cp310-cp310-manylinux_2_35_x86_64.whl (2.9 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.35+ x86-64

cel_bind-0.4.7-cp310-cp310-macosx_14_0_arm64.whl (2.2 MB view details)

Uploaded CPython 3.10macOS 14.0+ ARM64

File details

Details for the file cel_bind-0.4.7-cp312-cp312-manylinux_2_35_x86_64.whl.

File metadata

File hashes

Hashes for cel_bind-0.4.7-cp312-cp312-manylinux_2_35_x86_64.whl
Algorithm Hash digest
SHA256 e6a970b1c2ae2113317cdc4e0e0a617f8744bb57379ce1cdaf4495b596daa007
MD5 3d5eae5fa6bb0377791601fb4018aa25
BLAKE2b-256 cde5fa8698cef97af339cde70f6e11324d845e3087696a6bf59f40c67f31116b

See more details on using hashes here.

File details

Details for the file cel_bind-0.4.7-cp312-cp312-macosx_14_0_arm64.whl.

File metadata

File hashes

Hashes for cel_bind-0.4.7-cp312-cp312-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 da1d89461a702d31d1615ba1a57a3141e53b970c3445246bab96e8b2be77514a
MD5 2174297fc668626d2243987ba0d79992
BLAKE2b-256 670e8fdafab0d06d60632b1e016789a22b89911768d18421584ec0f560d11a4b

See more details on using hashes here.

File details

Details for the file cel_bind-0.4.7-cp311-cp311-manylinux_2_35_x86_64.whl.

File metadata

File hashes

Hashes for cel_bind-0.4.7-cp311-cp311-manylinux_2_35_x86_64.whl
Algorithm Hash digest
SHA256 6debf45dc9652d1e06ca0d05440c116a910632225b0c8229594ff5883e40dfe8
MD5 0f73e7f4bf65198df670359c842988df
BLAKE2b-256 649b2aec8581cd02e2fb9c7b860c134c852f4e2b39dadfa819bbb9c368a0c71d

See more details on using hashes here.

File details

Details for the file cel_bind-0.4.7-cp311-cp311-macosx_14_0_arm64.whl.

File metadata

File hashes

Hashes for cel_bind-0.4.7-cp311-cp311-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 960079b2a6b9383c62e5e4de56387d220e9cc779459ad14e3362dfe5e2e38d8a
MD5 b9662040ebb3ad1d4addedfe5bdddf8b
BLAKE2b-256 fb0d0bbc78137af69aeeb940bd12166d52171f3aebc1c81302820f167332d7f8

See more details on using hashes here.

File details

Details for the file cel_bind-0.4.7-cp310-cp310-manylinux_2_35_x86_64.whl.

File metadata

File hashes

Hashes for cel_bind-0.4.7-cp310-cp310-manylinux_2_35_x86_64.whl
Algorithm Hash digest
SHA256 f19da595292df0da5928a842940503592449080e67cb35b63aba291ff0f770d6
MD5 90b35fef878a657d6b1b38c3db66470c
BLAKE2b-256 58fb0a5ad5a928256c34ea02a8148f7652b806865faa0ad1b000ff047a486c32

See more details on using hashes here.

File details

Details for the file cel_bind-0.4.7-cp310-cp310-macosx_14_0_arm64.whl.

File metadata

File hashes

Hashes for cel_bind-0.4.7-cp310-cp310-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 27194c62cb82780c25a6b9bf374b337a907b580f31610122e024b5fa48ff7ff4
MD5 71717f93fdc7f7fb944e356dd89c6c47
BLAKE2b-256 0d6139c44d280441ee74d5ede2df254677afff0e9f18ba1e76d9b37b6b79498e

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