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.8.1-cp313-cp313-manylinux_2_35_x86_64.whl (3.0 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.35+ x86-64

cel_bind-0.8.1-cp313-cp313-macosx_14_0_arm64.whl (2.2 MB view details)

Uploaded CPython 3.13macOS 14.0+ ARM64

cel_bind-0.8.1-cp312-cp312-manylinux_2_35_x86_64.whl (3.0 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.35+ x86-64

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

Uploaded CPython 3.12macOS 14.0+ ARM64

cel_bind-0.8.1-cp311-cp311-manylinux_2_35_x86_64.whl (3.0 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.35+ x86-64

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

Uploaded CPython 3.11macOS 14.0+ ARM64

cel_bind-0.8.1-cp310-cp310-manylinux_2_35_x86_64.whl (3.0 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.35+ x86-64

cel_bind-0.8.1-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.8.1-cp313-cp313-manylinux_2_35_x86_64.whl.

File metadata

File hashes

Hashes for cel_bind-0.8.1-cp313-cp313-manylinux_2_35_x86_64.whl
Algorithm Hash digest
SHA256 9726315a91fdc1edf5953a21261eac5cbcf429fec9c7be13be30a53179572b61
MD5 35c8967c4fda9c35219cb816c47ef59f
BLAKE2b-256 4f8c604b20e5d0e51de9c833aebb19d8ddd0c532142d8c22e6121e27315ab3ad

See more details on using hashes here.

File details

Details for the file cel_bind-0.8.1-cp313-cp313-macosx_14_0_arm64.whl.

File metadata

File hashes

Hashes for cel_bind-0.8.1-cp313-cp313-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 4411c755b8fdd625108979c0b301a3dfd65ab3a682392322be082e34f20388b5
MD5 7430a3533fd0002eb8b0a0a3bcb97bcd
BLAKE2b-256 07be58a3965058c3da2edba28f878ea15d6d3c88b277fd74989a0f0c9249ad8f

See more details on using hashes here.

File details

Details for the file cel_bind-0.8.1-cp312-cp312-manylinux_2_35_x86_64.whl.

File metadata

File hashes

Hashes for cel_bind-0.8.1-cp312-cp312-manylinux_2_35_x86_64.whl
Algorithm Hash digest
SHA256 c286980b919bd182bc30beb6f0d27f4d3f67e84a6b7d034033d256d741ca0e9c
MD5 b826a5f348164b05721ba5ccf3e8d489
BLAKE2b-256 ee394238aad44ee601adbc681da315162c0552896f532f984d5757872b33caf5

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cel_bind-0.8.1-cp312-cp312-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 517bc75f7b3556d364d82bfd7f901304eb1af2148ae8a0343d5b714e093a9f4e
MD5 e058c7b85bf7b311e209be397ae192da
BLAKE2b-256 671142587b4162c0179995904e026bcccdcb727fb18c72e3da8ec41441b08737

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cel_bind-0.8.1-cp311-cp311-manylinux_2_35_x86_64.whl
Algorithm Hash digest
SHA256 69ca288067c9d9669fc03df8c104205700fcfca84b34dd0139fa7b878038c1e4
MD5 f4f09eba8ac871effab58280cc7bd5aa
BLAKE2b-256 b382d183e7f9ccd701b9ded6e697f486b0aa0b8c64a13dcef709627e5c698cf4

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cel_bind-0.8.1-cp311-cp311-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 a4bb1517be317d8b1a8f94f4d1406cf130db410bef7c490040a525082ba495bc
MD5 faa643a35a70e7fac019f36c175fddd2
BLAKE2b-256 78c63e7290fbc144b128f1f2f4cbe3eedbd5b69772ffa4461850871a4e105ac5

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cel_bind-0.8.1-cp310-cp310-manylinux_2_35_x86_64.whl
Algorithm Hash digest
SHA256 2741e8efc81d6e6685b2c6d6af667b919db79bb397c5e76a7a50ed8ed4709342
MD5 1af43eac9c451ec1344083b03aab15a9
BLAKE2b-256 d653100bd14418b6c74775efa1fd6ad4c2d00060b89e00c56542406c8ec354dd

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cel_bind-0.8.1-cp310-cp310-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 cfdafe12e6f5ea804e9dbf3e1a92bb58ca4c1ef2f51917c8eb097c633bcafe6f
MD5 9cc22c7d217e4aabe8b5acf619f53838
BLAKE2b-256 cca2a097edcd700439435bab8a993ff90cf803f046a36de38646f7aac45fb3ee

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