-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
cue: add Context and Context.compile
Add `Context` class representing a CUE context along with `compile` function from Python str or bytes to CUE Value. Expand definition of `Value` to take both a `Context` and the resource from `libcue`. Make both `Context` and `Value` release Go resources when deallocated. Test `compile`. Since at the moment we can't inspect CUE value, this reduces to testing that compilation is either successful in producing a CUE value (as a Python `Value`, or errors out with an expected message. Fixes #3071. Fixes #3072. Updates #3100. Updates #3073. Updates #3074. Signed-off-by: Aram Hăvărneanu <[email protected]> Change-Id: Ib98c06aca3bcceb8dc5d3f42a3acae289bc324c0 Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue-py/+/1194797 TryBot-Result: CUEcueckoo <[email protected]> Reviewed-by: Daniel Martí <[email protected]>
- Loading branch information
Showing
7 changed files
with
357 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
# Copyright 2024 The CUE Authors | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
""" | ||
Compile CUE code. | ||
""" | ||
|
||
from cue.build import BuildOption, encode_build_opts | ||
from cue.value import Value | ||
from cue.error import Error | ||
import libcue | ||
|
||
from typing import TYPE_CHECKING | ||
if TYPE_CHECKING: | ||
from cue.context import Context | ||
|
||
def compile(ctx: 'Context', s: str, *opts: BuildOption) -> Value: | ||
val_ptr = libcue.ffi.new("cue_value*") | ||
buf = libcue.ffi.new("char[]", s.encode("utf-8")) | ||
|
||
build_opts = encode_build_opts(*opts) | ||
err = libcue.compile_string(ctx._ctx, buf, build_opts, val_ptr) | ||
if err != 0: | ||
raise Error(err) | ||
return Value(ctx, val_ptr[0]) | ||
|
||
def compile_bytes(ctx: 'Context', buf: bytes, *opts: BuildOption) -> Value: | ||
val_ptr = libcue.ffi.new("cue_value*") | ||
buf_ptr = libcue.ffi.from_buffer(buf) | ||
|
||
build_opts = encode_build_opts(*opts) | ||
err = libcue.compile_bytes(ctx._ctx, buf_ptr, len(buf), build_opts, val_ptr) | ||
if err != 0: | ||
raise Error(err) | ||
return Value(ctx, val_ptr[0]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
# Copyright 2024 The CUE Authors | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
""" | ||
Create CUE values. | ||
""" | ||
|
||
from functools import singledispatchmethod | ||
from typing import final | ||
from cue.value import Value | ||
from cue.build import BuildOption | ||
from cue.compile import compile, compile_bytes | ||
import libcue | ||
|
||
@final | ||
class Context: | ||
""" | ||
Create new CUE values. | ||
Any operation that involves two values should originate from | ||
the same Context. | ||
Corresponding Go functionality is documented at: | ||
https://pkg.go.dev/cuelang.org/go/cue#Context | ||
""" | ||
|
||
_ctx: int | ||
|
||
def __init__(self): | ||
self._ctx = libcue.newctx() | ||
|
||
def __del__(self): | ||
libcue.free(self._ctx) | ||
|
||
@singledispatchmethod | ||
def compile(self, s, *opts: BuildOption) -> Value: | ||
""" | ||
Compile CUE code returning corresponding Value. | ||
Corresponding Go functionality is documented at: | ||
https://pkg.go.dev/cuelang.org/go/cue#Context.CompileString and | ||
https://pkg.go.dev/cuelang.org/go/cue#Context.CompileBytes | ||
Args: | ||
s: CUE code to compile, can be or type str or bytes. | ||
*opts: build options to use. | ||
Returns: | ||
Value: the CUE value corresponding to s. | ||
Raises: | ||
Error: if any error occurred. | ||
""" | ||
raise NotImplementedError | ||
|
||
@compile.register | ||
def _(self, s: str, *opts: BuildOption) -> Value: | ||
return compile(self, s, *opts) | ||
|
||
@compile.register | ||
def _(self, b: bytes, *opts: BuildOption) -> Value: | ||
return compile_bytes(self, b, *opts) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# Copyright 2024 The CUE Authors | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
""" | ||
CUE Python tests. | ||
""" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
# Copyright 2024 The CUE Authors | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
""" | ||
cue.Context tests. | ||
""" | ||
|
||
import pytest | ||
import cue | ||
|
||
def test_compile_empty(): | ||
ctx = cue.Context() | ||
|
||
val = ctx.compile("") | ||
assert isinstance(val, cue.Value) | ||
|
||
val = ctx.compile(b"") | ||
assert isinstance(val, cue.Value) | ||
|
||
def test_compile_empty_with_options(): | ||
ctx = cue.Context() | ||
|
||
val = ctx.compile("", cue.FileName("empty.cue"), cue.ImportPath("example.com/foo/bar")) | ||
assert isinstance(val, cue.Value) | ||
|
||
val = ctx.compile(b"", cue.FileName("empty.cue"), cue.ImportPath("example.com/foo/bar")) | ||
assert isinstance(val, cue.Value) | ||
|
||
def test_compile(): | ||
ctx = cue.Context() | ||
|
||
val = ctx.compile("true") | ||
assert isinstance(val, cue.Value) | ||
|
||
val = ctx.compile("42") | ||
assert isinstance(val, cue.Value) | ||
|
||
val = ctx.compile("1.2345") | ||
assert isinstance(val, cue.Value) | ||
|
||
val = ctx.compile('"hello"') | ||
assert isinstance(val, cue.Value) | ||
|
||
val = ctx.compile("'world'") | ||
assert isinstance(val, cue.Value) | ||
|
||
val = ctx.compile("int") | ||
assert isinstance(val, cue.Value) | ||
|
||
val = ctx.compile("{}") | ||
assert isinstance(val, cue.Value) | ||
|
||
val = ctx.compile("x: 42") | ||
assert isinstance(val, cue.Value) | ||
|
||
val = ctx.compile("x: y: z: true") | ||
assert isinstance(val, cue.Value) | ||
|
||
def test_compile_bytes(): | ||
ctx = cue.Context() | ||
|
||
val = ctx.compile(b"true") | ||
assert isinstance(val, cue.Value) | ||
|
||
val = ctx.compile(b"42") | ||
assert isinstance(val, cue.Value) | ||
|
||
val = ctx.compile(b"1.2345") | ||
assert isinstance(val, cue.Value) | ||
|
||
val = ctx.compile(b'"hello"') | ||
assert isinstance(val, cue.Value) | ||
|
||
val = ctx.compile(b"'world'") | ||
assert isinstance(val, cue.Value) | ||
|
||
val = ctx.compile(b"int") | ||
assert isinstance(val, cue.Value) | ||
|
||
val = ctx.compile(b"{}") | ||
assert isinstance(val, cue.Value) | ||
|
||
val = ctx.compile(b"x: 42") | ||
assert isinstance(val, cue.Value) | ||
|
||
val = ctx.compile(b"x: y: z: true") | ||
assert isinstance(val, cue.Value) | ||
|
||
def test_compile_with_options(): | ||
ctx = cue.Context() | ||
|
||
val = ctx.compile("true", cue.FileName("empty.cue")) | ||
assert isinstance(val, cue.Value) | ||
|
||
val = ctx.compile("42", cue.FileName("empty.cue")) | ||
assert isinstance(val, cue.Value) | ||
|
||
val = ctx.compile("1.2345", cue.FileName("empty.cue")) | ||
assert isinstance(val, cue.Value) | ||
|
||
val = ctx.compile('"hello"', cue.FileName("empty.cue")) | ||
assert isinstance(val, cue.Value) | ||
|
||
val = ctx.compile("'world'", cue.FileName("empty.cue")) | ||
assert isinstance(val, cue.Value) | ||
|
||
val = ctx.compile("int", cue.FileName("empty.cue")) | ||
assert isinstance(val, cue.Value) | ||
|
||
val = ctx.compile("{}", cue.FileName("empty.cue")) | ||
assert isinstance(val, cue.Value) | ||
|
||
val = ctx.compile("x: 42", cue.FileName("empty.cue")) | ||
assert isinstance(val, cue.Value) | ||
|
||
val = ctx.compile("x: y: z: true", cue.FileName("empty.cue")) | ||
assert isinstance(val, cue.Value) | ||
|
||
def test_compile_error(): | ||
ctx = cue.Context() | ||
|
||
with pytest.raises(cue.Error): | ||
ctx.compile("<") | ||
|
||
with pytest.raises(cue.Error, match="expected operand, found 'EOF'"): | ||
ctx.compile("a: b: -") | ||
|
||
with pytest.raises(cue.Error, match="expected operand, found 'EOF'"): | ||
ctx.compile(b"a: b: -") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
# Copyright 2024 The CUE Authors | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
""" | ||
cue.Value tests. | ||
""" | ||
|
||
import pytest | ||
import cue | ||
|
||
def test_context(): | ||
ctx = cue.Context() | ||
|
||
val = ctx.compile("") | ||
assert val.context() == ctx | ||
|
||
val = ctx.compile("x: 42") | ||
assert val.context() == ctx |