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

Uploaded CPython 3.12macOS 14.0+ ARM64

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

Uploaded CPython 3.11macOS 14.0+ ARM64

cel_bind-0.4.3-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.3-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.3-cp312-cp312-manylinux_2_35_x86_64.whl.

File metadata

File hashes

Hashes for cel_bind-0.4.3-cp312-cp312-manylinux_2_35_x86_64.whl
Algorithm Hash digest
SHA256 186e4853e3bbdc76597bf74f6893b5d1392fbaf86ca89999a9a499892b390ebc
MD5 8a8f7d7ae9bc640e8ff7e2388bbdcb71
BLAKE2b-256 c46fab69d86736a340f912cb72d596cf0c6e867b68188968b35774864f92d5d2

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cel_bind-0.4.3-cp312-cp312-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 32feb6bef8e3349bba3564dddf6f3dbcbc867ced904fa33e409330d953e44d19
MD5 f517829a3109b7151dd899f0040d42c6
BLAKE2b-256 482dcfc763fe9e46caa93ccb710fb32544e2b4dd20ee9595483ce810b9c8b408

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cel_bind-0.4.3-cp311-cp311-manylinux_2_35_x86_64.whl
Algorithm Hash digest
SHA256 9788d5f0d6d0cb1fc872c9dcc6121e191b799603a7630e1c17648eabf3b88b2d
MD5 96b4471f7db44a7c916b6caceb42ca9e
BLAKE2b-256 4b31cdb5f740bd58199cf77df7009b66611f079f012cf2d147b1cc49708aa37c

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cel_bind-0.4.3-cp311-cp311-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 f5baf4a9d26a3855dd1746f99c0468e2682b01725c65da08075c50b46046ede4
MD5 a3f1e30a355423098b936cdc25117dcb
BLAKE2b-256 809af954c099fcb16f7834d97d1ef2e080a082bbfe970237c169e51284d8050a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cel_bind-0.4.3-cp310-cp310-manylinux_2_35_x86_64.whl
Algorithm Hash digest
SHA256 06f7228db4e168370ea51f0df6ee390869a666253be64112d76adb62588400dd
MD5 3242279b85921154d867761fe70666e8
BLAKE2b-256 a47d9c12c916ce42558260f5b388456cdac608dfc169764a1ca66165b2c30e5a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cel_bind-0.4.3-cp310-cp310-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 e18c7de7eb93d1914d1ad3332f96bc29ce04690644bcd986a9ffb3c99aa7e646
MD5 4512abf2018e33b4c14e0937bee9fa86
BLAKE2b-256 0780a5796541cc435f403da3f218990baf947faf70772c7b2e8df7502dbeaa64

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