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.5.0-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.5.0-cp312-cp312-macosx_14_0_arm64.whl (2.2 MB view details)

Uploaded CPython 3.12macOS 14.0+ ARM64

cel_bind-0.5.0-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.5.0-cp311-cp311-macosx_14_0_arm64.whl (2.2 MB view details)

Uploaded CPython 3.11macOS 14.0+ ARM64

cel_bind-0.5.0-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.5.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.5.0-cp312-cp312-manylinux_2_35_x86_64.whl.

File metadata

File hashes

Hashes for cel_bind-0.5.0-cp312-cp312-manylinux_2_35_x86_64.whl
Algorithm Hash digest
SHA256 4068f3419681bfb424e5fbd9d3643bcd3aeff8df1c74d882f6fa434245261d68
MD5 cd7def41c6cff3593d187bea39a21b88
BLAKE2b-256 8739e66a2eddec2bd5f4cafa076983737a3c7b3da4cd2b36ae712c8096af61ab

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cel_bind-0.5.0-cp312-cp312-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 28301c500268b0a95b052873bc9fe366ca7cdebed6faa19c0fe4c621d91d7188
MD5 28b931977d6b90f2163d8324bfd07022
BLAKE2b-256 dfeddba91264c08e2b44f23a612ce7b17f0c51a8300ca4f79cbcc2bfb1c6a8ce

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cel_bind-0.5.0-cp311-cp311-manylinux_2_35_x86_64.whl
Algorithm Hash digest
SHA256 5d0029fa256230100ce9fc781f761a91e83f9a782158e7cf36cd8eb53c49d4f0
MD5 3bd05ef88a58d7812bd89223bcf5d3c0
BLAKE2b-256 403b5f5175914d96c0f40bd66cd24a7ede63677d9c157e4f127198f405edefae

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cel_bind-0.5.0-cp311-cp311-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 95ee3a4072fb0a470a90d30abd42b70855057cf9a828aa7b3b977061ae6dc3cd
MD5 19110241c6864e41e400e74056667b5b
BLAKE2b-256 f59b735367bc0288c5e0c32077b226775e9bd7a378b283749b1492d933ba7748

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cel_bind-0.5.0-cp310-cp310-manylinux_2_35_x86_64.whl
Algorithm Hash digest
SHA256 7f1bc8ed32011fd5aae81057e68fba5a7dba58c729f3e99ff3a554f6369e4511
MD5 7a4e6ef2e1e0852c898fbb349d5fe168
BLAKE2b-256 3949dc8397041537018d4acf80f9057f5ffb3e29b1cbc11e968bc70a0ddfef44

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cel_bind-0.5.0-cp310-cp310-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 794a2ac868957ceec9f04225dced66b879eead23de5e2a35b5d17cb9d40b56a8
MD5 79a3c5419ed69f1da4b7923f2dd7aa4b
BLAKE2b-256 caf7201595cb624ac6accc88302c6e5d7ad57e2708becfbef2171d220e924c83

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