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.2-cp312-cp312-manylinux_2_39_x86_64.whl (3.0 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.39+ x86-64

cel_bind-0.4.2-cp312-cp312-macosx_14_0_arm64.whl (2.2 MB view details)

Uploaded CPython 3.12macOS 14.0+ ARM64

cel_bind-0.4.2-cp311-cp311-manylinux_2_39_x86_64.whl (3.0 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.39+ x86-64

cel_bind-0.4.2-cp311-cp311-macosx_14_0_arm64.whl (2.2 MB view details)

Uploaded CPython 3.11macOS 14.0+ ARM64

cel_bind-0.4.2-cp310-cp310-manylinux_2_39_x86_64.whl (3.0 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.39+ x86-64

cel_bind-0.4.2-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.2-cp312-cp312-manylinux_2_39_x86_64.whl.

File metadata

File hashes

Hashes for cel_bind-0.4.2-cp312-cp312-manylinux_2_39_x86_64.whl
Algorithm Hash digest
SHA256 376fec0b5bd4e7913b0e44256ba67858d29082373ff198a64c0734fcc684da4d
MD5 c7a8d221afca6f3c50a7f7ccad2bb749
BLAKE2b-256 f84304a9150dd3e4a2c2f59b339b142ca5bc82983b011e24f8b965ca56301509

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cel_bind-0.4.2-cp312-cp312-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 371f8062c2d4c7f65efe13711afe470763bad1887506c1f9613e91f55c250870
MD5 74fe0b1195b8c3b99216e33311b6d82e
BLAKE2b-256 d142ec896f4e3680ed15a0830c9499152ca8b0e2d22753d0e3e5da2287c63d43

See more details on using hashes here.

File details

Details for the file cel_bind-0.4.2-cp311-cp311-manylinux_2_39_x86_64.whl.

File metadata

File hashes

Hashes for cel_bind-0.4.2-cp311-cp311-manylinux_2_39_x86_64.whl
Algorithm Hash digest
SHA256 ecc167136da570aadb13ad599fe2d80ba219b4b1de14926c6ef17b7025aabb60
MD5 b606860ab860df896d3ed1f33bd942f3
BLAKE2b-256 e24de32a88e94038ff47d1fa979ac96c13efcc861a13b98cd03af5c85b0a4f82

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cel_bind-0.4.2-cp311-cp311-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 0b5d83710c175676a8fec2a172723668e22e887d332e70b225a2ab26ac5d964d
MD5 4d44e0e3c463b54877ec1f84f1f8bd53
BLAKE2b-256 bdd8d4059ae14fa9bc5c3b4a85afd0cbf409d95312400471a2e0c373558a8020

See more details on using hashes here.

File details

Details for the file cel_bind-0.4.2-cp310-cp310-manylinux_2_39_x86_64.whl.

File metadata

File hashes

Hashes for cel_bind-0.4.2-cp310-cp310-manylinux_2_39_x86_64.whl
Algorithm Hash digest
SHA256 a3c177f6c025d17c91bacab81227e9c1ed573257c9bd6c871e4934b3e87395ad
MD5 c8fbbb9ebde0c3df3c7d27e295c2d68b
BLAKE2b-256 1a7d6d551f8046f6e2063120d8da13efa9f191e7ab1c68cf317ab758bd803895

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cel_bind-0.4.2-cp310-cp310-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 be02bf60776b3cd54b23da3dd89b6d8671654c7496224fc787e369647ef79d41
MD5 9ed7eab77e126d1d60340558ef877850
BLAKE2b-256 e777c8d96912def20b4412ec8d6c79385fd02991121825549eb8c56829d4e892

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