Skip to content

Commit 2e77bc8

Browse files
dmitriplotnikovcopybara-github
authored andcommitted
Add EnvConfig class to support parsing and generation of YAML
PiperOrigin-RevId: 889356928
1 parent e64e2e1 commit 2e77bc8

6 files changed

Lines changed: 224 additions & 3 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-
# 12/30/2025
18-
_CEL_CPP_COMMIT = "13b249f589ab3e22dee5b384169cb7dd50804b36"
17+
# 03/25/2026
18+
_CEL_CPP_COMMIT = "f6cd0c895e42954475b3734c867e8902557d1b37"
1919

20-
_CEL_CPP_SHA256 = "c7596db4538722e78f9c7f7ae704a15fd48d5e84254d717b5b558c3b1b0169fa"
20+
_CEL_CPP_SHA256 = "8af44a84983f190e30ba4e5064ed5f2a2bbd13988a50b5c75288096636f1548b"
2121

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

cel_expr_python/BUILD

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ pybind_extension(
1818
"py_cel_arena.h",
1919
"py_cel_env.cc",
2020
"py_cel_env.h",
21+
"py_cel_env_config.cc",
22+
"py_cel_env_config.h",
2123
"py_cel_env_internal.cc",
2224
"py_cel_env_internal.h",
2325
"py_cel_expression.cc",
@@ -76,6 +78,8 @@ pybind_extension(
7678
"@com_google_cel_cpp//compiler",
7779
"@com_google_cel_cpp//compiler:compiler_factory",
7880
"@com_google_cel_cpp//compiler:standard_library",
81+
"@com_google_cel_cpp//env:config",
82+
"@com_google_cel_cpp//env:env_yaml",
7983
"@com_google_cel_cpp//extensions/protobuf:runtime_adapter",
8084
"@com_google_cel_cpp//parser:parser_interface",
8185
"@com_google_cel_cpp//runtime",
@@ -126,3 +130,12 @@ py_test(
126130
"@com_google_protobuf//:protobuf",
127131
],
128132
)
133+
134+
py_test(
135+
name = "cel_env_test",
136+
srcs = ["cel_env_test.py"],
137+
deps = [
138+
":cel",
139+
"@com_google_absl_py//absl/testing:absltest",
140+
],
141+
)

cel_expr_python/cel_env_test.py

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
# Copyright 2026 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
"""Tests for Env/Config.
16+
17+
This module contains tests for the `cel.EnvConfig` class, focusing on its
18+
ability to be created from and serialized to YAML format.
19+
"""
20+
21+
from absl.testing import absltest
22+
from cel_expr_python import cel
23+
24+
25+
class CelEnvTest(absltest.TestCase):
26+
27+
def test_env_config_from_and_to_yaml(self):
28+
config = cel.NewEnvConfigFromYaml("""
29+
name: foo
30+
container: test.container
31+
stdlib:
32+
exclude_macros:
33+
- map
34+
- filter
35+
exclude_functions:
36+
- name: "_+_"
37+
extensions:
38+
- name: math
39+
variables:
40+
- name: one
41+
type_name: int
42+
value: 1
43+
functions:
44+
- name: add
45+
overloads:
46+
- id: "add_int_int"
47+
args:
48+
- type_name: int
49+
- type_name: int
50+
return:
51+
type_name: int
52+
""")
53+
yaml = config.to_yaml()
54+
self.assertEqual(
55+
normalize_yaml(yaml),
56+
normalize_yaml("""
57+
name: "foo"
58+
container: "test.container"
59+
extensions:
60+
- name: "math"
61+
stdlib:
62+
exclude_macros:
63+
- "filter"
64+
- "map"
65+
exclude_functions:
66+
- name: "_+_"
67+
variables:
68+
- name: "one"
69+
type_name: "int"
70+
value: 1
71+
functions:
72+
- name: "add"
73+
overloads:
74+
- id: "add_int_int"
75+
args:
76+
- type_name: "int"
77+
- type_name: "int"
78+
return:
79+
type_name: "int"
80+
"""),
81+
)
82+
83+
def test_invalid_yaml(self):
84+
with self.assertRaises(Exception) as e:
85+
cel.NewEnvConfigFromYaml(" invalid yaml")
86+
self.assertIn(
87+
"1:2: Invalid CEL environment config YAML\n"
88+
"| invalid yaml\n"
89+
"| ^",
90+
str(e.exception),
91+
)
92+
93+
94+
def normalize_yaml(yaml: str) -> str:
95+
lines = yaml.split("\n")
96+
indent = -1
97+
unindented_lines = []
98+
for line in lines:
99+
pos = -1
100+
for i, char in enumerate(line):
101+
if char != " " and char != "\t":
102+
pos = i
103+
break
104+
if pos == -1:
105+
# Skip blank lines.
106+
continue
107+
if indent == -1:
108+
indent = pos
109+
if pos >= indent:
110+
unindented_lines.append(line[indent:])
111+
else:
112+
unindented_lines.append(line)
113+
return "\n".join(unindented_lines)
114+
115+
116+
if __name__ == "__main__":
117+
absltest.main()
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* Copyright 2026 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
#include "cel_expr_python/py_cel_env_config.h"
17+
18+
#include <memory>
19+
#include <sstream>
20+
#include <string>
21+
22+
#include "env/env_yaml.h"
23+
#include "cel_expr_python/py_error_status.h"
24+
#include <pybind11/pybind11.h>
25+
26+
namespace cel_python {
27+
28+
namespace py = ::pybind11;
29+
30+
void PyCelEnvConfig::DefinePythonBindings(pybind11::module& m) {
31+
py::class_<PyCelEnvConfig, std::shared_ptr<PyCelEnvConfig>> cel_class(
32+
m, "EnvConfig");
33+
m.def("NewEnvConfigFromYaml", &PyCelEnvConfig::FromYaml, py::arg("yaml"));
34+
35+
cel_class.def("to_yaml", &PyCelEnvConfig::ToYaml);
36+
}
37+
38+
PyCelEnvConfig PyCelEnvConfig::FromYaml(std::string yaml) {
39+
PyCelEnvConfig config;
40+
config.config_ = ThrowIfError(cel::EnvConfigFromYaml(yaml));
41+
return config;
42+
}
43+
44+
std::string PyCelEnvConfig::ToYaml() const {
45+
std::stringstream ss;
46+
cel::EnvConfigToYaml(config_, ss);
47+
return ss.str();
48+
}
49+
50+
} // namespace cel_python
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Copyright 2026 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
#ifndef THIRD_PARTY_CEL_PYTHON_PY_CEL_ENV_CONFIG_H_
17+
#define THIRD_PARTY_CEL_PYTHON_PY_CEL_ENV_CONFIG_H_
18+
19+
#include <string>
20+
21+
#include "env/config.h"
22+
#include <pybind11/pybind11.h>
23+
24+
namespace cel_python {
25+
26+
class PyCelEnvConfig {
27+
public:
28+
static void DefinePythonBindings(pybind11::module& m);
29+
30+
static PyCelEnvConfig FromYaml(std::string yaml);
31+
std::string ToYaml() const;
32+
33+
private:
34+
cel::Config config_;
35+
};
36+
37+
} // namespace cel_python
38+
39+
#endif // THIRD_PARTY_CEL_PYTHON_PY_CEL_ENV_CONFIG_H_

cel_expr_python/py_cel_module.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "cel_expr_python/py_cel_activation.h"
1616
#include "cel_expr_python/py_cel_arena.h"
1717
#include "cel_expr_python/py_cel_env.h"
18+
#include "cel_expr_python/py_cel_env_config.h"
1819
#include "cel_expr_python/py_cel_expression.h"
1920
#include "cel_expr_python/py_cel_function.h"
2021
#include "cel_expr_python/py_cel_function_decl.h"
@@ -38,6 +39,7 @@ PYBIND11_MODULE(cel, m) {
3839
PyCelFunctionDecl::DefinePythonBindings(m);
3940
PyCelPythonExtension::DefinePythonBindings(m);
4041
PyCelFunction::DefinePythonBindings(m);
42+
PyCelEnvConfig::DefinePythonBindings(m);
4143
PyCelEnv::DefinePythonBindings(m);
4244
}
4345

0 commit comments

Comments
 (0)