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

Uploaded CPython 3.12macOS 14.0+ ARM64

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

Uploaded CPython 3.11macOS 14.0+ ARM64

cel_bind-0.8.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.8.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.8.0-cp312-cp312-manylinux_2_35_x86_64.whl.

File metadata

File hashes

Hashes for cel_bind-0.8.0-cp312-cp312-manylinux_2_35_x86_64.whl
Algorithm Hash digest
SHA256 fac415cfc5b8d1de8869c9f1eae70ef8335580320244c39002dfd82038ea36d9
MD5 9995f15a6883cef4448f568e66efed7d
BLAKE2b-256 d9ee27011fb35672d485e8e61a8af93f12613b7561a39e3a2f008eb2b39abf2d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cel_bind-0.8.0-cp312-cp312-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 5c616dd5da12999d1def93d6034bd19a1682388de1faa881168f74a0dec81185
MD5 14fc2dfd7aa36853f9ec3eb527d35c22
BLAKE2b-256 9a66c653b81af84d2c64e8ea41b5ae05e0cf58c2182c43eb4f37c8e067948f1b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cel_bind-0.8.0-cp311-cp311-manylinux_2_35_x86_64.whl
Algorithm Hash digest
SHA256 d7a54303598fb0ff8ef39aa2d9e37ed230b4242dc8e9dc5287d34327dffb1b90
MD5 65d4f5dc83202acef64732aeb47ff48b
BLAKE2b-256 dead008c63c21d732ce36cc3d61ec2b76464d7d868683f6cc791ccd8ae8b5816

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cel_bind-0.8.0-cp311-cp311-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 8cd4b670fb81c8d2d54b3f8e4bb047ba0f379befa3a5dde6e086fab94434bfe5
MD5 db43962f1d24ee1e2a68f460c3f5468c
BLAKE2b-256 c5e27b0c0f885bb153bcf3df8bbb3b47c667b994c221849d29e3e6bcf4bbf371

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cel_bind-0.8.0-cp310-cp310-manylinux_2_35_x86_64.whl
Algorithm Hash digest
SHA256 e0cd48db589699d5e1f2edafede02c02f5812eb238ad507fc81026f178d8f9ac
MD5 a222bf88c4ec8ae2b29c1e487ca2541c
BLAKE2b-256 223265d2652c0d6af222f1e03a523bfa5edc82e008f2c8125ca9438795b6e747

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cel_bind-0.8.0-cp310-cp310-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 9706349d832114317ab8641b95afd9db1c2b2bc4e952e69090d524ff718d5d73
MD5 5687a749ce232b496dcff02887c1a90b
BLAKE2b-256 3a16a66d17b3170267a14aa572fccc7f0e2c8531c44aad4007a10e9832ee3b65

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