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

Uploaded CPython 3.12manylinux: glibc 2.39+ x86-64

cel_bind-0.4.0-cp312-cp312-macosx_14_0_arm64.whl (2.8 MB view details)

Uploaded CPython 3.12macOS 14.0+ ARM64

cel_bind-0.4.0-cp311-cp311-manylinux_2_39_x86_64.whl (3.8 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.39+ x86-64

cel_bind-0.4.0-cp311-cp311-macosx_14_0_arm64.whl (2.8 MB view details)

Uploaded CPython 3.11macOS 14.0+ ARM64

cel_bind-0.4.0-cp310-cp310-manylinux_2_39_x86_64.whl (3.8 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.39+ x86-64

cel_bind-0.4.0-cp310-cp310-macosx_14_0_arm64.whl (2.8 MB view details)

Uploaded CPython 3.10macOS 14.0+ ARM64

File details

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

File metadata

File hashes

Hashes for cel_bind-0.4.0-cp312-cp312-manylinux_2_39_x86_64.whl
Algorithm Hash digest
SHA256 da65e556621288205a1ff1343aeaf88ae783d07d0617310e55ca15ae2a1b7509
MD5 39f4d8e91444fa7849ec246103d9135e
BLAKE2b-256 66a0bc576cb826dd1dc0dfb02e0bd31ec381089350d1a7f969acac5e1b42ff63

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cel_bind-0.4.0-cp312-cp312-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 df1759793aa9c40a221a76479d3edda0526bdab097852fd2ed167a635489fae6
MD5 510f17684a9155b8fb901a0a1edefe0e
BLAKE2b-256 ca30b8c8889202d3ed05cbccd479aef1c68d94332f5ba0451c42580e6bad1693

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cel_bind-0.4.0-cp311-cp311-manylinux_2_39_x86_64.whl
Algorithm Hash digest
SHA256 8f1e2f2b5342c60e7ffb445ea9a97609cabbabdd8d28a4c53bcd6eb51da0b0a8
MD5 5901562fa63d6beec4b575512ccf4ba6
BLAKE2b-256 fa6cf05d175e6b4e67c00fc57f80baffcb3ece6d44eef9955046501d5427c2bc

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cel_bind-0.4.0-cp311-cp311-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 8f9128c99a104ccc2775d6767ad6953db164e118ec72d1ffcbf9b20bcb2bdc84
MD5 015c96547c6524d9741b3c57aef7df51
BLAKE2b-256 cc306984459e8551d38319316754a5663e760d77b97a0fc9dec189ceebe1050c

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cel_bind-0.4.0-cp310-cp310-manylinux_2_39_x86_64.whl
Algorithm Hash digest
SHA256 756162071c97a87d8c31ae3c96856352192732f77f0c78f1521d42e6ef5ee139
MD5 ac4b0d88ad87709d0973bca6f5f9f268
BLAKE2b-256 396582533733f33a7124d621490d7aa0c513ccf2492891fd9259475719bd55a5

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cel_bind-0.4.0-cp310-cp310-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 3c8551b28ad01e2c7c43deb82d04bf324a47da7aca68dc701f704a2aa630e23a
MD5 a7ef3a85f4fcd14bd73c992501d2715e
BLAKE2b-256 61039a84da7f0e95d78dca4bedc9748f6be4c436e41068286b892d1d73d3c53a

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