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

Uploaded CPython 3.12manylinux: glibc 2.39+ x86-64

cel_bind-0.2.0-cp312-cp312-macosx_14_0_arm64.whl (2.8 MB view details)

Uploaded CPython 3.12macOS 14.0+ ARM64

cel_bind-0.2.0-cp311-cp311-manylinux_2_39_x86_64.whl (3.7 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.39+ x86-64

cel_bind-0.2.0-cp311-cp311-macosx_14_0_arm64.whl (2.8 MB view details)

Uploaded CPython 3.11macOS 14.0+ ARM64

cel_bind-0.2.0-cp310-cp310-manylinux_2_39_x86_64.whl (3.7 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.39+ x86-64

cel_bind-0.2.0-cp310-cp310-macosx_14_0_arm64.whl (2.8 MB view details)

Uploaded CPython 3.10macOS 14.0+ ARM64

File details

Details for the file cel_bind-0.2.0-cp312-cp312-manylinux_2_39_x86_64.whl.

File metadata

File hashes

Hashes for cel_bind-0.2.0-cp312-cp312-manylinux_2_39_x86_64.whl
Algorithm Hash digest
SHA256 d91b796ea02e7ea74df523076a7ba2bd42b9c1033ac8834108595be18726a753
MD5 3577ae91eae5e760ff5e13f34c914189
BLAKE2b-256 d4050e998a4c28de4334ce9902f73760a312b8b37e031b79d98211ff395f6fc2

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cel_bind-0.2.0-cp312-cp312-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 a112ecb091ca7f746ea2f9a5c5dbcebbbc17c7fe7db7e1d667044f85dbc66de8
MD5 09b8b50249a7bcfada5f8c6ea6d89b0a
BLAKE2b-256 3e92f9367b996d3ba490c575d82282035db7e2a7b875e78bdfab6e8dce9e4878

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cel_bind-0.2.0-cp311-cp311-manylinux_2_39_x86_64.whl
Algorithm Hash digest
SHA256 90f1d381ff28a87b725aba59cb1d0d85232cb880d8ce585f9e0715ccd255f12c
MD5 cf51c362a782e933fe3561f0c0d5ca59
BLAKE2b-256 73fc9e0f92091216a671070b3d0d9cd00ba147053471ed8ff463b97973088659

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cel_bind-0.2.0-cp311-cp311-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 23e4a1cfd81307ef05712aba5614e363ec83fa7b6af7a11cb2659bd479d43b20
MD5 c33a1b66961256dfb5f77d00f693b378
BLAKE2b-256 90221c04ec9ad97dc5b952f529070672e905b4a0195dfc936db06c37c5136f2c

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cel_bind-0.2.0-cp310-cp310-manylinux_2_39_x86_64.whl
Algorithm Hash digest
SHA256 0d1f7c16a17d8e10c639607cb6344ce1435c6f1ef7fc1378e1cb1698d7b10c71
MD5 5b5cc6614c0e98e7498ff1d8e6a9fbff
BLAKE2b-256 02e37c47e33cb87498e232331af15b495984d06fb214c7392526a41352335e71

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cel_bind-0.2.0-cp310-cp310-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 b6a5bec598edb1f2f3e936a219df8acb017fa23e6597a022157e5cbb4bcd5d99
MD5 aee70936458df84618f4d70300520f0f
BLAKE2b-256 84c4fca3831a8964fb1f15d4a208e79b5aaa232a501776c88c8d00cfb8eaf18c

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