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

Uploaded CPython 3.12macOS 14.0+ ARM64

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

Uploaded CPython 3.11macOS 14.0+ ARM64

cel_bind-0.4.4-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.4-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.4-cp312-cp312-manylinux_2_35_x86_64.whl.

File metadata

File hashes

Hashes for cel_bind-0.4.4-cp312-cp312-manylinux_2_35_x86_64.whl
Algorithm Hash digest
SHA256 c9a95c066dc1297df2ba6d5eb949c7063afb4a8461d02b724bbe41feded22c6d
MD5 e65be99e8a1b6b27a10ab60790459e49
BLAKE2b-256 8838f61692ed92a3e13a89869700a77d2822fad6ac496a01fa31524f0d160bef

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cel_bind-0.4.4-cp312-cp312-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 7abdbb9963bdcad5d72e5eaf364c54bf1167ccfb213750b5523fc0153ff42e65
MD5 6de49464fe4e1d9fea131107a8f178ef
BLAKE2b-256 37a2c20735e3e56bbf61327866160845523e77f89db4bf4cfe4d30f113997329

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cel_bind-0.4.4-cp311-cp311-manylinux_2_35_x86_64.whl
Algorithm Hash digest
SHA256 582f421c800b5ceb2db83662accfd0ef6a498fbaa8c04035ad0e5b6a3f45713f
MD5 ffc24138958e3131415ef75e01197eeb
BLAKE2b-256 d045c237a8af5d5e3553856e286340d73d61c3972f88d5349b34c7f4af228386

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cel_bind-0.4.4-cp311-cp311-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 05cc41aea8ecebec5c8ec1abc78c660f5b7c0eb413919ab55303fc005ac1d6ed
MD5 e3bc14da5117dda8fa956ff3cc964994
BLAKE2b-256 7b9e1e2a7798133196967041968f023e31acd78ff46409c275cd1903b33ca5b9

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cel_bind-0.4.4-cp310-cp310-manylinux_2_35_x86_64.whl
Algorithm Hash digest
SHA256 afda7d868a03a526b1be0884de4cc231fc947790c1aa38db7a97edf58e4683c3
MD5 02876236219fe7ab502e181de89a04a9
BLAKE2b-256 a3e4c4c114af2f5bc21eaed764b251fe8cdaffe9278eb15af778f467f281b392

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cel_bind-0.4.4-cp310-cp310-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 688eaaa087e7e50610a3e491f1085bdc94fadec1377a69da6de705734b095d58
MD5 54a71d95f782764a36646eb9f845799f
BLAKE2b-256 412f9650f6b238459a6332db6ffb8b3d3a2cd7bb65f082b8d3f38c18a0d4b721

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