Skip to content

Commit 6519eab

Browse files
dmitriplotnikovcopybara-github
authored andcommitted
Rewrote the Windows presubmit script from .ps1 to .bat to fix execution issues on Kokoro Windows executors where .ps1 files could not be executed directly. Updated the build config to point to the new batch file.
PiperOrigin-RevId: 915470198
1 parent a28cb01 commit 6519eab

13 files changed

Lines changed: 284 additions & 69 deletions

MODULE.bazel

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,14 @@ bazel_dep(name = "bazel_skylib", version = "1.8.2")
1313

1414
# https://registry.bazel.build/modules/cel-cpp
1515
bazel_dep(name = "cel-cpp", version = "0.15.0", repo_name = "com_google_cel_cpp")
16-
single_version_override(
16+
git_override(
1717
module_name = "cel-cpp",
18+
commit = "2e6e9ff4493bfbe0baf883107f3fb7ce6f675d88",
1819
patch_cmds = [
1920
# ABSL_CONST_INIT is incompatible with MSVC-CL with the /std:c++20 option
2021
"sed -i 's/ABSL_CONST_INIT //g' common/values/optional_value.cc",
2122
],
22-
version = "0.15.0",
23+
remote = "https://github.com/google/cel-cpp",
2324
)
2425

2526
# https://registry.bazel.build/modules/cel-spec

README.md

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,27 @@ The `cel.NewEnv` constructor also accepts the following optional parameters:
2626
* `pool` (`descriptor_pool.DescriptorPool`): The descriptor pool used for
2727
resolving protobuf message types within CEL expressions. If not provided,
2828
a default pool (`descriptor_pool.Default()`) is used.
29-
* `container` (str): The container name used for name resolution. For example,
29+
* `container` (`str` or `cel.ExpressionContainer`): The container name used
30+
for name resolution. For example,
3031
if `container` is `"foo.bar"`, then `Baz` will resolve to
3132
`foo.bar.Baz`.
33+
34+
You can also pass a `cel.ExpressionContainer` to configure abbreviations
35+
and aliases:
36+
37+
```python
38+
container = cel.ExpressionContainer(
39+
name="foo.bar",
40+
abbreviations=["foo.bar.baz"],
41+
aliases={"my_alias": "full.name.of.something"}
42+
)
43+
cel_env = cel.NewEnv(container=container)
44+
```
45+
46+
* `abbreviations`: A list of fully qualified names that can be referred
47+
to by their last component.
48+
* `aliases`: A dictionary mapping an alias name to a fully qualified
49+
name.
3250
* `extensions` (list): A list of extension objects to load. This can include
3351
standard extensions (like `math` or `string` libraries) or custom extensions
3452
defined in Python or C++.

cel_expr_python/BUILD

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,10 @@ pybind_extension(
6666
"@com_google_absl//absl/types:optional",
6767
"@com_google_absl//absl/types:span",
6868
"@com_google_cel_cpp//checker:type_checker_builder",
69-
"@com_google_cel_cpp//checker:type_checker_builder_factory",
7069
"@com_google_cel_cpp//checker:validation_result",
7170
"@com_google_cel_cpp//common:ast",
7271
"@com_google_cel_cpp//common:ast_proto",
72+
"@com_google_cel_cpp//common:container",
7373
"@com_google_cel_cpp//common:decl",
7474
"@com_google_cel_cpp//common:function_descriptor",
7575
"@com_google_cel_cpp//common:kind",
@@ -87,8 +87,6 @@ pybind_extension(
8787
"@com_google_cel_cpp//env:env_yaml",
8888
"@com_google_cel_cpp//env:runtime_std_extensions",
8989
"@com_google_cel_cpp//extensions/protobuf:runtime_adapter",
90-
"@com_google_cel_cpp//parser",
91-
"@com_google_cel_cpp//parser:options",
9290
"@com_google_cel_cpp//parser:parser_interface",
9391
"@com_google_cel_cpp//runtime",
9492
"@com_google_cel_cpp//runtime:activation",

cel_expr_python/cel.pyi

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ class CelExtensionBase:
1515
class EnvConfig:
1616
def to_yaml(self) -> str: ...
1717

18+
class ExpressionContainer:
19+
def __init__(self, name: str = ..., abbreviations: Sequence[str] | None = ..., aliases: Mapping[str, str] | None = ...) -> None: ...
20+
def container(self) -> str: ...
21+
1822
class Env:
1923
def Activation(self, data: Mapping[str, Any] | None = ..., functions: Sequence[Function] | None = ..., arena: _InternalArena = ...) -> Activation: ...
2024
def compile(self, expression: str, disable_check: bool = ...) -> Expression: ...
@@ -80,6 +84,6 @@ class _InternalArena:
8084

8185
def Arena() -> _InternalArena: ...
8286

83-
def NewEnv(descriptor_pool: proto_descriptor_pool.DescriptorPool | Any | None = ..., config: EnvConfig | None = ..., variables: Mapping[str, Type] | None = ..., extensions: Sequence[CelExtensionBase] | None = ..., container: str | None = ..., functions: Sequence[FunctionDecl] | None = ..., function_impls: Mapping[str, Callable[..., Any]] | None = ...) -> Env: ...
87+
def NewEnv(descriptor_pool: proto_descriptor_pool.DescriptorPool | Any | None = ..., config: EnvConfig | None = ..., variables: Mapping[str, Type] | None = ..., extensions: Sequence[CelExtensionBase] | None = ..., container: str | ExpressionContainer | None = ..., functions: Sequence[FunctionDecl] | None = ..., function_impls: Mapping[str, Callable[..., Any]] | None = ...) -> Env: ...
8488

8589
def NewEnvConfigFromYaml(yaml: str) -> EnvConfig: ...

cel_expr_python/cel_env_test.py

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,147 @@ def test_config_export_container(self):
108108
"""),
109109
)
110110

111+
def test_expression_container_abbreviations_and_aliases(self):
112+
expr_container = cel.ExpressionContainer(
113+
"test.container", abbreviations=["x.y.foo"], aliases={"abc": "x.y.bar"}
114+
)
115+
116+
env: cel.Env = cel.NewEnv(
117+
container=expr_container,
118+
variables={
119+
"x.y.foo": cel.Type.INT,
120+
"x.y.bar": cel.Type.STRING,
121+
},
122+
)
123+
124+
res = env.compile("foo").eval(data={"x.y.foo": 42})
125+
self.assertEqual(res.value(), 42)
126+
res = env.compile("abc").eval(data={"x.y.bar": "chocolate"})
127+
self.assertEqual(res.value(), "chocolate")
128+
129+
yaml: str = env.config().to_yaml()
130+
self.assertEqual(
131+
normalize_yaml(yaml),
132+
normalize_yaml("""
133+
container:
134+
name: "test.container"
135+
abbreviations:
136+
- "x.y.foo"
137+
aliases:
138+
- alias: "abc"
139+
qualified_name: "x.y.bar"
140+
variables:
141+
- name: "x.y.bar"
142+
type_name: "string"
143+
- name: "x.y.foo"
144+
type_name: "int"
145+
"""),
146+
)
147+
148+
def test_abbreviations_and_aliases_from_yaml(self):
149+
env: cel.Env = cel.NewEnv(config=cel.NewEnvConfigFromYaml("""
150+
container:
151+
name: "test.container"
152+
abbreviations:
153+
- "x.y.foo"
154+
aliases:
155+
- alias: "abc"
156+
qualified_name: "x.y.bar"
157+
variables:
158+
- name: "x.y.bar"
159+
type_name: "string"
160+
- name: "x.y.foo"
161+
type_name: "int"
162+
"""))
163+
164+
res = env.compile("foo").eval(data={"x.y.foo": 42})
165+
self.assertEqual(res.value(), 42)
166+
res = env.compile("abc").eval(data={"x.y.bar": "chocolate"})
167+
self.assertEqual(res.value(), "chocolate")
168+
169+
def test_abbreviations_and_aliases_combined(self):
170+
env: cel.Env = cel.NewEnv(
171+
config=cel.NewEnvConfigFromYaml("""
172+
container:
173+
name: "test.container"
174+
abbreviations:
175+
- "x.y.foo"
176+
aliases:
177+
- alias: "abc"
178+
qualified_name: "x.y.bar"
179+
variables:
180+
- name: "x.y.bar"
181+
type_name: "string"
182+
- name: "x.y.foo"
183+
type_name: "int"
184+
- name: "a.b.qux"
185+
type_name: "string"
186+
- name: "a.b.baz"
187+
type_name: "int"
188+
"""),
189+
container=cel.ExpressionContainer(
190+
"test.container",
191+
abbreviations=["a.b.baz"],
192+
aliases={"def": "a.b.qux"},
193+
),
194+
)
195+
196+
res = env.compile("foo").eval(data={"x.y.foo": 42})
197+
self.assertEqual(res.value(), 42)
198+
res = env.compile("baz").eval(data={"a.b.baz": 24})
199+
self.assertEqual(res.value(), 24)
200+
201+
res = env.compile("abc").eval(data={"x.y.bar": "chocolate"})
202+
self.assertEqual(res.value(), "chocolate")
203+
res = env.compile("def").eval(data={"a.b.qux": "vanilla"})
204+
self.assertEqual(res.value(), "vanilla")
205+
206+
yaml: str = env.config().to_yaml()
207+
self.assertEqual(
208+
normalize_yaml(yaml),
209+
normalize_yaml("""
210+
container:
211+
name: "test.container"
212+
abbreviations:
213+
- "a.b.baz"
214+
- "x.y.foo"
215+
aliases:
216+
- alias: "abc"
217+
qualified_name: "x.y.bar"
218+
- alias: "def"
219+
qualified_name: "a.b.qux"
220+
variables:
221+
- name: "a.b.baz"
222+
type_name: "int"
223+
- name: "a.b.qux"
224+
type_name: "string"
225+
- name: "x.y.bar"
226+
type_name: "string"
227+
- name: "x.y.foo"
228+
type_name: "int"
229+
"""),
230+
)
231+
232+
def test_alias_redefinition_error(self):
233+
with self.assertRaises(Exception) as e:
234+
cel.NewEnv(
235+
container=cel.ExpressionContainer(
236+
"test.container", aliases={"abc": "x.y.bar"}
237+
),
238+
config=cel.NewEnvConfigFromYaml("""
239+
container:
240+
name: "test.container"
241+
aliases:
242+
- alias: "abc"
243+
qualified_name: "x.y.baz"
244+
"""),
245+
)
246+
self.assertIn(
247+
"Alias 'abc' is already defined with a different qualified name:"
248+
" x.y.baz",
249+
str(e.exception),
250+
)
251+
111252
def test_config_export_variables(self):
112253
config: cel.Env = cel.NewEnv(
113254
variables={

cel_expr_python/py_cel_env.cc

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
#include <vector>
2626

2727
#include "absl/log/absl_check.h"
28-
#include "env/config.h"
28+
#include "common/container.h"
2929
#include "cel_expr_python/py_cel_activation.h"
3030
#include "cel_expr_python/py_cel_arena.h"
3131
#include "cel_expr_python/py_cel_env_config.h"
@@ -42,13 +42,42 @@ namespace cel_python {
4242
namespace py = ::pybind11;
4343

4444
void PyCelEnv::DefinePythonBindings(pybind11::module& m) {
45+
py::class_<cel::ExpressionContainer>(m, "ExpressionContainer")
46+
.def(py::init(
47+
[](const std::string& name,
48+
const std::optional<std::vector<std::string>>& abbreviations,
49+
const std::optional<
50+
std::unordered_map<std::string, std::string>>& aliases) {
51+
auto container =
52+
ThrowIfError(cel::MakeExpressionContainer(name));
53+
54+
if (abbreviations) {
55+
for (const auto& abrev : *abbreviations) {
56+
ThrowIfError(container.AddAbbreviation(abrev));
57+
}
58+
}
59+
60+
if (aliases) {
61+
for (const auto& [alias, full_name] : *aliases) {
62+
ThrowIfError(container.AddAlias(alias, full_name));
63+
}
64+
}
65+
66+
return container;
67+
}),
68+
py::arg("name") = "", py::arg("abbreviations") = py::none(),
69+
py::arg("aliases") = py::none())
70+
.def("container", [](const cel::ExpressionContainer& self) {
71+
return std::string(self.container());
72+
});
73+
4574
py::class_<PyCelEnv, std::shared_ptr<PyCelEnv>> cel_class(m, "Env");
4675
m.def(
4776
"NewEnv",
4877
[](py::object descriptor_pool, std::optional<PyCelEnvConfig>& config,
4978
std::optional<std::unordered_map<std::string, PyCelType>>& variables,
5079
std::optional<std::vector<py::object>>& extensions,
51-
const std::optional<std::string>& container,
80+
py::object container,
5281
std::optional<std::vector<std::shared_ptr<PyCelFunctionDecl>>>&
5382
functions,
5483
std::optional<std::unordered_map<std::string, py::object>>&
@@ -77,10 +106,23 @@ void PyCelEnv::DefinePythonBindings(pybind11::module& m) {
77106
}
78107
}
79108

109+
cel::ExpressionContainer expr_container;
110+
if (!container.is_none()) {
111+
if (py::isinstance<py::str>(container)) {
112+
expr_container = ThrowIfError(
113+
cel::MakeExpressionContainer(container.cast<std::string>()));
114+
} else if (py::isinstance<cel::ExpressionContainer>(container)) {
115+
expr_container = container.cast<cel::ExpressionContainer>();
116+
} else {
117+
throw py::type_error(
118+
"container must be a string or ExpressionContainer");
119+
}
120+
}
121+
80122
return PyCelEnv(config.value_or(PyCelEnvConfig()), pool_ptr,
81123
std::move(variables).value_or(
82124
std::unordered_map<std::string, PyCelType>{}),
83-
ext_ptrs, container.value_or(""),
125+
ext_ptrs, std::move(expr_container),
84126
functions.value_or(
85127
std::vector<std::shared_ptr<PyCelFunctionDecl>>{}),
86128
function_impls.value_or(
@@ -125,7 +167,8 @@ void PyCelEnv::DefinePythonBindings(pybind11::module& m) {
125167
PyCelEnv::PyCelEnv(
126168
const PyCelEnvConfig& config, PyObject* descriptor_pool,
127169
const std::unordered_map<std::string, PyCelType>& variable_types,
128-
const std::vector<PyObject*>& extensions, const std::string& container,
170+
const std::vector<PyObject*>& extensions,
171+
cel::ExpressionContainer container,
129172
const std::vector<std::shared_ptr<PyCelFunctionDecl>>& functions,
130173
const std::unordered_map<std::string, py::object>& function_impls) {
131174
env_ = ThrowIfError(PyCelEnvInternal::NewCelEnvInternal(

cel_expr_python/py_cel_env.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include <unordered_map>
2424
#include <vector>
2525

26+
#include "common/container.h"
2627
#include "cel_expr_python/py_cel_activation.h"
2728
#include "cel_expr_python/py_cel_arena.h"
2829
#include "cel_expr_python/py_cel_env_config.h"
@@ -70,7 +71,7 @@ class PyCelEnv {
7071
PyCelEnv(const PyCelEnvConfig& config, PyObject* descriptor_pool,
7172
const std::unordered_map<std::string, PyCelType>& variable_types,
7273
const std::vector<PyObject*>& extensions,
73-
const std::string& container,
74+
cel::ExpressionContainer container,
7475
const std::vector<std::shared_ptr<PyCelFunctionDecl>>& functions,
7576
const std::unordered_map<std::string, py::object>& function_impls);
7677

0 commit comments

Comments
 (0)