Skip to content

Commit f8dd975

Browse files
Pass --strict_message conformance (minus duration/timestamp) (#256)
We can't currently pass the conformance tests involving duration+timestamp types, as cel-python does not support nanoseconds in its duration implementation (linked issue). Otherwise, this gets us to a conformant spot. Related to #255.
1 parent 8786f15 commit f8dd975

File tree

3 files changed

+24
-2
lines changed

3 files changed

+24
-2
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export PATH := $(BIN):$(PATH)
1111
export GOBIN := $(abspath $(BIN))
1212
# Set to use a different Python interpreter. For example, `PYTHON=python make test`.
1313
PYTHON ?= python3
14-
CONFORMANCE_ARGS ?= --strict --expected_failures=tests/conformance/nonconforming.yaml --timeout 10s
14+
CONFORMANCE_ARGS ?= --strict --strict_message --expected_failures=tests/conformance/nonconforming.yaml --timeout 10s
1515
ADD_LICENSE_HEADER := $(BIN)/license-header \
1616
--license-type apache \
1717
--copyright-holder "Buf Technologies, Inc." \

protovalidate/internal/string_format.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15+
from decimal import Decimal
16+
1517
import celpy # type: ignore
1618
from celpy import celtypes # type: ignore
1719

@@ -146,16 +148,32 @@ def format_string(self, arg: celtypes.Value) -> celpy.Result:
146148
if isinstance(arg, celtypes.StringType):
147149
return arg
148150
if isinstance(arg, celtypes.BytesType):
149-
return celtypes.StringType(arg.hex())
151+
return celtypes.StringType(arg)
150152
if isinstance(arg, celtypes.ListType):
151153
return self.format_list(arg)
154+
if isinstance(arg, celtypes.BoolType):
155+
# True -> true
156+
return celtypes.StringType(str(arg).lower())
157+
if isinstance(arg, celtypes.DoubleType):
158+
return celtypes.StringType(f"{arg:.0f}")
159+
if isinstance(arg, celtypes.DurationType):
160+
return celtypes.StringType(self._format_duration(arg))
161+
if isinstance(arg, celtypes.TimestampType):
162+
base = arg.isoformat()
163+
if arg.getMilliseconds() != 0:
164+
base = arg.isoformat(timespec="milliseconds")
165+
return celtypes.StringType(base.removesuffix("+00:00") + "Z")
152166
return celtypes.StringType(arg)
153167

154168
def format_value(self, arg: celtypes.Value) -> celpy.Result:
155169
if isinstance(arg, (celtypes.StringType, str)):
156170
return celtypes.StringType(quote(arg))
157171
if isinstance(arg, celtypes.UintType):
158172
return celtypes.StringType(arg)
173+
if isinstance(arg, celtypes.DurationType):
174+
return celtypes.StringType(f'duration("{self._format_duration(arg)}")')
175+
if isinstance(arg, celtypes.DoubleType):
176+
return celtypes.StringType(f"{arg:f}")
159177
return self.format_string(arg)
160178

161179
def format_list(self, arg: celtypes.ListType) -> celpy.Result:
@@ -167,6 +185,9 @@ def format_list(self, arg: celtypes.ListType) -> celpy.Result:
167185
result += "]"
168186
return celtypes.StringType(result)
169187

188+
def _format_duration(self, arg: celtypes.DurationType) -> celpy.Result:
189+
return f"{arg.seconds + Decimal(arg.microseconds) / Decimal(1_000_000):f}s"
190+
170191

171192
_default_format = StringFormat("en_US")
172193
format = _default_format.format # noqa: A001

tests/conformance/nonconforming.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# celpy doesn't support nano seconds
2+
# ref: https://github.com/cloud-custodian/cel-python/issues/43
23
standard_constraints/well_known_types/duration:
34
- gte_lte/invalid/above
45
- lte/invalid

0 commit comments

Comments
 (0)