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

Uploaded CPython 3.12macOS 14.0+ ARM64

cel_bind-0.1.2-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.1.2-cp311-cp311-macosx_14_0_arm64.whl (2.8 MB view details)

Uploaded CPython 3.11macOS 14.0+ ARM64

cel_bind-0.1.2-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.1.2-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.1.2-cp312-cp312-manylinux_2_39_x86_64.whl.

File metadata

File hashes

Hashes for cel_bind-0.1.2-cp312-cp312-manylinux_2_39_x86_64.whl
Algorithm Hash digest
SHA256 fc9477a8d9695551e29db09018d694863f7fb7d17f8bf451f482f85bc4d36e0d
MD5 95796b681eb1c81ea7b64ba684ba0a86
BLAKE2b-256 b4b7aadb45b70b1962cc8af33996ff126a1937ade3e061910ec57f011d6b2218

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cel_bind-0.1.2-cp312-cp312-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 7b701d8abde1f666a857b729a8495e3f3f82f074837c027079c5ebe8254de399
MD5 08d0ac4cd308a3e71d838ddf78ae8471
BLAKE2b-256 4830e243e4440cda681d1985a3a71178e5a32961b078f59d42f4583aaf03436a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cel_bind-0.1.2-cp311-cp311-manylinux_2_39_x86_64.whl
Algorithm Hash digest
SHA256 0b29be870be8896205a52ffddc1811ccef728eb915fb5b7cb4ded142155daada
MD5 a88267949263592b4d27c08d4ecf5015
BLAKE2b-256 1f6721ab18e1322e2e4a447fc0953faf141a6b21d4b5f7a5ebaee39f7974265a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cel_bind-0.1.2-cp311-cp311-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 87027a3a8d47ae8498de9cbfe20b37f01abf7f5838d0086af3dc053500745f0f
MD5 620f37d5c2bbd7d43d074a3a3e3e2ff9
BLAKE2b-256 1dbd5447b1ae677d68d05ee9395f91b28f0c2050113523d83d195c51ac955c76

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cel_bind-0.1.2-cp310-cp310-manylinux_2_39_x86_64.whl
Algorithm Hash digest
SHA256 c6ccfa348f888a5399104ace76fbb19184790dbbb094e5d0a17561a4714e605e
MD5 6c1a08c2c3f60674a40353b2a3cf089b
BLAKE2b-256 565f732a1b6ad657828a5593141c3395142ae203983ce0f6713f45a72f3cdc53

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cel_bind-0.1.2-cp310-cp310-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 63c0d66a386201c26d2c56c6f96ddead5eab3bab835f6f9e9c0b68a92243f675
MD5 bafc764b19f94a753f4640b6f88317b1
BLAKE2b-256 3aa891e277cd16522229bd8b66d5fb0208a52a3c37322e7f9dc6de7be3abdf35

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