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.6.0-cp312-cp312-manylinux_2_35_x86_64.whl (3.0 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.35+ x86-64

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

Uploaded CPython 3.12macOS 14.0+ ARM64

cel_bind-0.6.0-cp311-cp311-manylinux_2_35_x86_64.whl (3.0 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.35+ x86-64

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

Uploaded CPython 3.11macOS 14.0+ ARM64

cel_bind-0.6.0-cp310-cp310-manylinux_2_35_x86_64.whl (3.0 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.35+ x86-64

cel_bind-0.6.0-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.6.0-cp312-cp312-manylinux_2_35_x86_64.whl.

File metadata

File hashes

Hashes for cel_bind-0.6.0-cp312-cp312-manylinux_2_35_x86_64.whl
Algorithm Hash digest
SHA256 b429b270c4c2ab12de5aa37f02ce02f9f364ec7dfb5805ca3168b9c39acdc6c1
MD5 73597fefba973e99ca779e2bcf8d1a08
BLAKE2b-256 26a99254c993425d39eb722715abf897e0e0bf8f60a7f1055394b944b197da65

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cel_bind-0.6.0-cp312-cp312-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 9da3b20e57218ffc70fa852b55220dd12bd1a2193ea9957d8a4b0e28efbe74c2
MD5 67364644f67468f9c5b1c5ef853f8342
BLAKE2b-256 62a79dd10f5692e0b792a3f1152a694ae7e02fc50c19ac3d462191e2b94dcb52

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cel_bind-0.6.0-cp311-cp311-manylinux_2_35_x86_64.whl
Algorithm Hash digest
SHA256 38b81dd0fd25f2dc642261945f8f396a2fef3e9091793c89e777fca6ea87e73e
MD5 efb255781cb9a5d217fcad4ed92ffab2
BLAKE2b-256 a3cea831949d919e974d021371e8f21a6215de982b94758f31e841c601d7a42b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cel_bind-0.6.0-cp311-cp311-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 d65da5a4f73d697a7420fafedc5be96588c6ff68a055b1a873b3636faaafa338
MD5 456897e041653785c869b82b3d73001d
BLAKE2b-256 0c9bc147512c883ab329c1a4b0aa5d4105373361aa02f6271b4218550261ac88

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cel_bind-0.6.0-cp310-cp310-manylinux_2_35_x86_64.whl
Algorithm Hash digest
SHA256 19b353952e16fb13aed79a7811ce9d89c01b78ef51c98136bce2d1f4161500fa
MD5 47f430472901e1f7c02d4a550088f8e3
BLAKE2b-256 27cdd24c74538cc2bc3403d9389b79361285d6a6b83c0a25c7fdb467013268f7

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cel_bind-0.6.0-cp310-cp310-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 0028e802e27e4567e5168bbe90acd3c886fa9f8839acae282f353206a5f4e4f6
MD5 104090934aaafcc3ec7137d103694cb5
BLAKE2b-256 c50abc651783f3eef498f90bc0c51705b1d84ba8d45ff0cde09a632f0cba5051

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