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

Uploaded CPython 3.12macOS 14.0+ ARM64

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

Uploaded CPython 3.11macOS 14.0+ ARM64

cel_bind-0.4.5-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.4.5-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.4.5-cp312-cp312-manylinux_2_35_x86_64.whl.

File metadata

File hashes

Hashes for cel_bind-0.4.5-cp312-cp312-manylinux_2_35_x86_64.whl
Algorithm Hash digest
SHA256 54de697fdfa3f756b1f5037769f853f68eb3f78c0db01edc4c34f35a1cab65c3
MD5 097a00eca2797625c184b9b26d60a342
BLAKE2b-256 32deeefc36fb80b7eb14f18af646c3e0d30191ba8cc9d48c3ee1f235ad63c871

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cel_bind-0.4.5-cp312-cp312-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 044291cb9e741073b8d5002232ff83ebefb0ccac4ae206c44c6aa8c0f3f18012
MD5 5e9d56b200694cf39120b5194000502f
BLAKE2b-256 eb7219ad4282c44734c47aba22a222b961f9a4021509144913d2d735320127a3

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cel_bind-0.4.5-cp311-cp311-manylinux_2_35_x86_64.whl
Algorithm Hash digest
SHA256 fa9e75705dd5af1397f3fe5b812c2c16aad369de6dccc4c7224502ae6fd27f6b
MD5 507bd4792b1fbb6648b109b851283d40
BLAKE2b-256 ccf704ce448a2c1b87f5e186d202ba8e87e819632c0cdc8ae13bac851f1dda53

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cel_bind-0.4.5-cp311-cp311-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 0581eb8bc79e373ab4d4c98b4eac083592fdf2f3bff7ef8a8b937fc8a042abd4
MD5 e3f39f5cfa7c5489685bc567cd81367f
BLAKE2b-256 97c7c69490dc05c415187835674a017181886516bb138ae8bacc207eedf62582

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cel_bind-0.4.5-cp310-cp310-manylinux_2_35_x86_64.whl
Algorithm Hash digest
SHA256 219bc15d698346a2f6b92c8d74123d2cf2e68603b68d17d9c29b41f17af7c50d
MD5 ee55c8d74c06c6c3fd477eb88e32914a
BLAKE2b-256 76740552282ae0795159226dd2cc66e231b24e9c6ade20a07222eda2a0e7dd83

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cel_bind-0.4.5-cp310-cp310-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 e7c416d075004a46e5573c2a00134a0ec1a5079472b8369326d4a8f7dd096c3b
MD5 bbb36f3d1fad10df0ebe475f6b823132
BLAKE2b-256 9b5e589a26abcf6fa913bbbb171078b5d57dd0f2042269d272997006fe907123

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