Skip to content

Commit 0786ac2

Browse files
dmitriplotnikovcopybara-github
authored andcommitted
Integrate cel::Config::ExtensionConfig into Python CEL environment
PiperOrigin-RevId: 896167243
1 parent 1ec5a73 commit 0786ac2

6 files changed

Lines changed: 247 additions & 40 deletions

File tree

MODULE.bazel

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ bazel_dep(name = "bazel_skylib", version = "1.8.2")
1414
# https://registry.bazel.build/modules/cel-cpp
1515
bazel_dep(name = "cel-cpp", version = "0.14.0", repo_name = "com_google_cel_cpp")
1616

17-
# 03/30/2026
18-
_CEL_CPP_COMMIT = "5a3463337cf2a9b90b53833af2bbc1f35da90d64"
17+
# 04/07/2025
18+
_CEL_CPP_COMMIT = "7022451780867bd9c173956f5793b5dfb600928e"
1919

20-
_CEL_CPP_SHA256 = "299be398d1495340eb92da31f9a0667e1351479752e8a567ac31c385e4aea73c"
20+
_CEL_CPP_SHA256 = "d1b9b2c2e9745826c1c8540a49f972ea4b93dffd5878c6a67756a2627b0119ef"
2121

2222
archive_override(
2323
module_name = "cel-cpp",

cel_expr_python/BUILD

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ pybind_extension(
6363
"@com_google_absl//absl/types:optional",
6464
"@com_google_absl//absl/types:span",
6565
"@com_google_cel_cpp//checker:type_checker_builder",
66+
"@com_google_cel_cpp//checker:type_checker_builder_factory",
6667
"@com_google_cel_cpp//checker:validation_result",
6768
"@com_google_cel_cpp//common:ast",
6869
"@com_google_cel_cpp//common:ast_proto",
@@ -78,8 +79,13 @@ pybind_extension(
7879
"@com_google_cel_cpp//compiler",
7980
"@com_google_cel_cpp//env",
8081
"@com_google_cel_cpp//env:config",
82+
"@com_google_cel_cpp//env:env_runtime",
83+
"@com_google_cel_cpp//env:env_std_extensions",
8184
"@com_google_cel_cpp//env:env_yaml",
85+
"@com_google_cel_cpp//env:runtime_std_extensions",
8286
"@com_google_cel_cpp//extensions/protobuf:runtime_adapter",
87+
"@com_google_cel_cpp//parser",
88+
"@com_google_cel_cpp//parser:options",
8389
"@com_google_cel_cpp//parser:parser_interface",
8490
"@com_google_cel_cpp//runtime",
8591
"@com_google_cel_cpp//runtime:activation",
@@ -88,7 +94,7 @@ pybind_extension(
8894
"@com_google_cel_cpp//runtime:reference_resolver",
8995
"@com_google_cel_cpp//runtime:runtime_builder",
9096
"@com_google_cel_cpp//runtime:runtime_options",
91-
"@com_google_cel_cpp//runtime:standard_runtime_builder_factory",
97+
"@com_google_cel_cpp//validator",
9298
"@com_google_cel_spec//proto/cel/expr:checked_cc_proto",
9399
"@com_google_cel_spec//proto/cel/expr:syntax_cc_proto",
94100
"@com_google_protobuf//:protobuf",
@@ -135,6 +141,7 @@ py_test(
135141
srcs = ["cel_env_test.py"],
136142
deps = [
137143
":cel",
144+
"//cel_expr_python/ext:ext_math",
138145
"//testing:proto2_test_all_types_py_pb2",
139146
"@com_google_absl_py//absl/testing:absltest",
140147
],

cel_expr_python/cel_env_test.py

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
from absl.testing import absltest
2222
from cel_expr_python import cel
23+
from cel_expr_python.ext import ext_math
2324
from cel.expr.conformance.proto2 import test_all_types_pb2 as test_all_types_pb
2425

2526

@@ -236,6 +237,75 @@ def test_config_variable_types(self):
236237
self.assertEqual(res.type(), cel.Type.INT)
237238
self.assertEqual(res.value(), 42)
238239

240+
def test_config_extensions(self):
241+
config = cel.NewEnvConfigFromYaml("""
242+
extensions:
243+
- name: math
244+
- name: strings
245+
""")
246+
env = cel.NewEnv(
247+
config=config,
248+
extensions=[TestCelExtension()],
249+
)
250+
yaml = env.config().to_yaml()
251+
self.assertEqual(
252+
normalize_yaml(yaml),
253+
normalize_yaml("""
254+
extensions:
255+
- name: "math"
256+
- name: "strings"
257+
- name: "test_cel_extension"
258+
"""),
259+
)
260+
res = env.compile("'%.4f'.format([math.sqrt(2)])").eval()
261+
self.assertEqual(res.value(), "1.4142")
262+
res = env.compile("hello('World')").eval()
263+
self.assertEqual(res.value(), "Hello, World!")
264+
265+
def test_config_extensions_override(self):
266+
# TODO(b/498655870): add assertion based on extension aliases once
267+
# supported.
268+
config = cel.NewEnvConfigFromYaml("""
269+
extensions:
270+
- name: cel.lib.ext.math
271+
version: 0
272+
- name: cel.lib.ext.strings
273+
""")
274+
with self.assertRaises(Exception) as e:
275+
cel.NewEnv(
276+
config=config,
277+
extensions=[ext_math.ExtMath()],
278+
)
279+
self.assertIn(
280+
"Extension 'cel.lib.ext.math' version 0 is already included. Cannot"
281+
" also include version 'latest'",
282+
str(e.exception),
283+
)
284+
285+
286+
class TestCelExtension(cel.CelExtension):
287+
"""An example CEL extension for testing."""
288+
289+
def __init__(self):
290+
super().__init__(
291+
"test_cel_extension",
292+
functions=[
293+
cel.FunctionDecl(
294+
"hello",
295+
[
296+
cel.Overload(
297+
"hello(string)",
298+
return_type=cel.Type.STRING,
299+
parameters=[
300+
cel.Type.STRING,
301+
],
302+
impl=lambda arg: f"Hello, {arg}!",
303+
)
304+
],
305+
),
306+
],
307+
)
308+
239309

240310
def normalize_yaml(yaml: str) -> str:
241311
lines = yaml.split("\n")

cel_expr_python/ext/ext_optional.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ namespace cel_python {
2525

2626
class ExtOptional : public CelExtension {
2727
public:
28-
explicit ExtOptional() : CelExtension("cel.lib.optional") {}
28+
explicit ExtOptional() : CelExtension("optional") {}
2929

3030
absl::Status ConfigureCompiler(
3131
cel::CompilerBuilder& compiler_builder,

0 commit comments

Comments
 (0)