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.1-cp312-cp312-manylinux_2_39_x86_64.whl (10.9 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.39+ x86-64

cel_bind-0.4.1-cp312-cp312-macosx_14_0_arm64.whl (8.5 MB view details)

Uploaded CPython 3.12macOS 14.0+ ARM64

cel_bind-0.4.1-cp311-cp311-manylinux_2_39_x86_64.whl (10.9 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.39+ x86-64

cel_bind-0.4.1-cp311-cp311-macosx_14_0_arm64.whl (8.5 MB view details)

Uploaded CPython 3.11macOS 14.0+ ARM64

cel_bind-0.4.1-cp310-cp310-manylinux_2_39_x86_64.whl (10.9 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.39+ x86-64

cel_bind-0.4.1-cp310-cp310-macosx_14_0_arm64.whl (8.5 MB view details)

Uploaded CPython 3.10macOS 14.0+ ARM64

File details

Details for the file cel_bind-0.4.1-cp312-cp312-manylinux_2_39_x86_64.whl.

File metadata

File hashes

Hashes for cel_bind-0.4.1-cp312-cp312-manylinux_2_39_x86_64.whl
Algorithm Hash digest
SHA256 12ea665fac076efc8b66ec3916efd01977d832f45d9151e2c6614213a985442f
MD5 16be18f45b1b3e6193cc327c0c371700
BLAKE2b-256 d1b38a2958259984b9fe3de76809612b35c2682106ca053ee1d175592055f051

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cel_bind-0.4.1-cp312-cp312-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 5678e072593c4ce74211895d55d6bc5bd6a14e2b55694c85fbb096a933f99923
MD5 d649d3bd64705124087a4498eb34f5da
BLAKE2b-256 b0e1ef03c9f09765d23662d51d05fa642dea0d8ab4521a87247b61d8140b945c

See more details on using hashes here.

File details

Details for the file cel_bind-0.4.1-cp311-cp311-manylinux_2_39_x86_64.whl.

File metadata

File hashes

Hashes for cel_bind-0.4.1-cp311-cp311-manylinux_2_39_x86_64.whl
Algorithm Hash digest
SHA256 08f6ab11d5956a2f3513e44c775959e730ecf74ee453dbcb8d51faf48f0e7eb1
MD5 dd06fa6433b19fadce846d6e41ddbf32
BLAKE2b-256 8580d81521e6e731661e9763a43488c4318940465cf1c5ef27524024d74e6053

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cel_bind-0.4.1-cp311-cp311-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 9e4d795df2f26f0b42115c0fdd180e3ec35974a9e9684c527ea97a1e88201c11
MD5 168c51f0d701485485d1c37f72d549ec
BLAKE2b-256 307aa836b4d92fe217ef38dd6e8853887d22d1e9903a225a47efe18fa472cf9e

See more details on using hashes here.

File details

Details for the file cel_bind-0.4.1-cp310-cp310-manylinux_2_39_x86_64.whl.

File metadata

File hashes

Hashes for cel_bind-0.4.1-cp310-cp310-manylinux_2_39_x86_64.whl
Algorithm Hash digest
SHA256 34c0c0e601e7de7717f1a145232d7410c653c89e6036b6011074f20c88d59db0
MD5 b8acaaefadfad00e8703e92e937a56f9
BLAKE2b-256 63b64c61337a962e8e3cdc639aa1d6e35f1d720f133c065313ee036ef5c6540b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cel_bind-0.4.1-cp310-cp310-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 2f23f619b621ddadf8d4709555d0c9027e754fca04ed4b1856d0d25a389426cd
MD5 837356acbe25c8a3861746c14668ea2f
BLAKE2b-256 c2da83c1a0342782e7ba40b732c6d2f81510d5b0434811aaf60469eab468b543

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