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

Uploaded CPython 3.12macOS 14.0+ ARM64

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

Uploaded CPython 3.11macOS 14.0+ ARM64

cel_bind-0.4.6-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.6-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.6-cp312-cp312-manylinux_2_35_x86_64.whl.

File metadata

File hashes

Hashes for cel_bind-0.4.6-cp312-cp312-manylinux_2_35_x86_64.whl
Algorithm Hash digest
SHA256 b52bac5484c905c28da34197ef3030362e786c1245235de3602e700d2d495fcf
MD5 47d691450cd3b8f298d05b3b251017b8
BLAKE2b-256 c2b59136aef19cae68dc26e8e7905c1b19183b1817c07a1c4f6ba6f361c4c18d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cel_bind-0.4.6-cp312-cp312-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 bae0b03b16a7b9da912b8b1fcee6f562ffcaf1fdf46f9f7edd8fc2d957c8b9f6
MD5 0760f36a01668735acf2107cec76bdda
BLAKE2b-256 8e807c9b2169f9915489a38cb69fb33c490083bbd88f44eb602cc2dbf4a815f4

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cel_bind-0.4.6-cp311-cp311-manylinux_2_35_x86_64.whl
Algorithm Hash digest
SHA256 f509cd172e94d57d2795daeb5e226fcfea9bfca0c90cf1b3bb1a53e5d91cc41a
MD5 c332e5b99d3d36deb0a3905e4d47e029
BLAKE2b-256 82439e5ad592369c736fbe8d792e6ff078bb11fdc5a6358b23c8afbb9ec7b6e0

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cel_bind-0.4.6-cp311-cp311-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 aced5e8ea4c0e4c10238429fe2bef4de8c8061f25c8c5be79078b122760a2545
MD5 93457b3974b70be74961433bd79d92aa
BLAKE2b-256 5db008f5bcb161e0a4dd6602752f541066a86afd8ae34aa9affd5201f8065072

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cel_bind-0.4.6-cp310-cp310-manylinux_2_35_x86_64.whl
Algorithm Hash digest
SHA256 62b645803074051529bba8784bfcd6a830045b78a2e282ded0873926f5d75e14
MD5 99a04c415efc4f94264ef2b1d2e4e3e5
BLAKE2b-256 0fe12fe2ba8e204d7054ae116b5ece0426a04278974d9acce80e795fe40293d6

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cel_bind-0.4.6-cp310-cp310-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 611daccd95d09521313a9c585f2750ca1f77e47208f1ae21264f3d9984cff530
MD5 681f2a985e2348b2922eadf2634ef3f4
BLAKE2b-256 310104d59733330d73a228a84dfec71577a78f90b4c398c09070dad68f13c0bb

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