From 1fc6e495ab9ab0d2adcf608b11b5c89c6fda1c30 Mon Sep 17 00:00:00 2001 From: Jeroen Op 't Eynde Date: Mon, 5 Jun 2023 13:58:01 +0200 Subject: [PATCH 1/8] fix: fmt tests (#1094) --- doc/_stdlib_gen/stdlib-content.jsonnet | 4 ++++ test_suite/stdlib.jsonnet | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/doc/_stdlib_gen/stdlib-content.jsonnet b/doc/_stdlib_gen/stdlib-content.jsonnet index 533041841..e9554a88c 100644 --- a/doc/_stdlib_gen/stdlib-content.jsonnet +++ b/doc/_stdlib_gen/stdlib-content.jsonnet @@ -1349,6 +1349,8 @@ local html = import 'html.libsonnet'; description: html.paragraphs([ ||| Return the min of all element in arr. + |||, + ]), }, { name: 'maxArray', @@ -1357,6 +1359,8 @@ local html = import 'html.libsonnet'; description: html.paragraphs([ ||| Return the max of all element in arr. + |||, + ]), }, { name: 'contains', diff --git a/test_suite/stdlib.jsonnet b/test_suite/stdlib.jsonnet index 708b8b605..d69c763da 100644 --- a/test_suite/stdlib.jsonnet +++ b/test_suite/stdlib.jsonnet @@ -1565,7 +1565,7 @@ std.assertEqual(std.isEmpty(''), true) && std.assertEqual(std.isEmpty('non-empty string'), false) && std.assertEqual(std.contains([1, 2, 3], 2), true) && -std.assertEqual(std.contains([1, 2, 3], "foo"), false) && +std.assertEqual(std.contains([1, 2, 3], 'foo'), false) && std.assertEqual(std.equalsIgnoreCase('foo', 'FOO'), true) && std.assertEqual(std.equalsIgnoreCase('foo', 'bar'), false) && From 8f1e262c3a91737da998640819572a1f9fd7f0b6 Mon Sep 17 00:00:00 2001 From: Tejesh Raut Date: Tue, 13 Jun 2023 12:05:20 +0000 Subject: [PATCH 2/8] Add std.trim for string (#1067) * Add std.trim for string --- doc/_stdlib_gen/stdlib-content.jsonnet | 8 ++++++++ stdlib/std.jsonnet | 2 ++ test_suite/stdlib.jsonnet | 6 ++++++ 3 files changed, 16 insertions(+) diff --git a/doc/_stdlib_gen/stdlib-content.jsonnet b/doc/_stdlib_gen/stdlib-content.jsonnet index e9554a88c..a6b7d25aa 100644 --- a/doc/_stdlib_gen/stdlib-content.jsonnet +++ b/doc/_stdlib_gen/stdlib-content.jsonnet @@ -371,6 +371,14 @@ local html = import 'html.libsonnet'; Returns true if the the given string is of zero length. |||, }, + { + name: 'trim', + params: ['str'], + availableSince: 'upcoming', + description: ||| + Returns a copy of string after eliminating leading and trailing whitespaces. + |||, + }, { name: 'equalsIgnoreCase', params: ['str1', 'str2'], diff --git a/stdlib/std.jsonnet b/stdlib/std.jsonnet index 0349fb5df..00a91d1e4 100644 --- a/stdlib/std.jsonnet +++ b/stdlib/std.jsonnet @@ -1759,4 +1759,6 @@ limitations under the License. for k in std.objectFields(obj) if k != key }, + + trim(str):: std.stripChars(str, ' \t\n\f\r\u0085\u00A0'), } diff --git a/test_suite/stdlib.jsonnet b/test_suite/stdlib.jsonnet index d69c763da..0a810c3d1 100644 --- a/test_suite/stdlib.jsonnet +++ b/test_suite/stdlib.jsonnet @@ -1575,4 +1575,10 @@ std.assertEqual(std.removeAt([1, 2, 3], 1), [1, 3]) && std.assertEqual(std.objectRemoveKey({ foo: 1, bar: 2, baz: 3 }, 'foo'), { bar: 2, baz: 3 }) && +std.assertEqual(std.trim('already trimmed string'), 'already trimmed string') && +std.assertEqual(std.trim(' string with spaces on both ends '), 'string with spaces on both ends') && +std.assertEqual(std.trim('string with newline character at end\n'), 'string with newline character at end') && +std.assertEqual(std.trim('string with tabs at end\t\t'), 'string with tabs at end') && +std.assertEqual(std.trim('string with other special whitespaces at end\f\r\u0085\u00A0'), 'string with carriage return at end') && + true From fe8179a8560de6908e52aeef48a03e6fc76035d8 Mon Sep 17 00:00:00 2001 From: Hercules Merscher Date: Tue, 13 Jun 2023 14:34:56 +0200 Subject: [PATCH 3/8] feat: std.flattenDeepArray Concatenate an array containing values and arrays into a single flattened array. (#1082) * std.flattenDeepArray recursively flattens multiple arrays --- doc/_stdlib_gen/stdlib-content.jsonnet | 14 ++++++++++++++ stdlib/std.jsonnet | 6 ++++++ test_suite/stdlib.jsonnet | 5 +++++ 3 files changed, 25 insertions(+) diff --git a/doc/_stdlib_gen/stdlib-content.jsonnet b/doc/_stdlib_gen/stdlib-content.jsonnet index a6b7d25aa..46850b0c5 100644 --- a/doc/_stdlib_gen/stdlib-content.jsonnet +++ b/doc/_stdlib_gen/stdlib-content.jsonnet @@ -1278,6 +1278,20 @@ local html = import 'html.libsonnet'; }, ], }, + { + name: 'flattenDeepArray', + params: ['value'], + availableSince: 'upcoming', + description: ||| + Concatenate an array containing values and arrays into a single flattened array. + |||, + examples: [ + { + input: 'std.flattenDeepArray([[1, 2], [], [3, [4]], [[5, 6, [null]], [7, 8]]])', + output: std.flattenDeepArray([[1, 2], [], [3, [4]], [[5, 6, [null]], [7, 8]]]), + }, + ], + }, { name: 'reverse', params: ['arrs'], diff --git a/stdlib/std.jsonnet b/stdlib/std.jsonnet index 00a91d1e4..a7fafd3f7 100644 --- a/stdlib/std.jsonnet +++ b/stdlib/std.jsonnet @@ -865,6 +865,12 @@ limitations under the License. flattenArrays(arrs):: std.foldl(function(a, b) a + b, arrs, []), + flattenDeepArray(value):: + if std.isArray(value) then + [y for x in value for y in std.flattenDeepArray(x)] + else + [value], + manifestIni(ini):: local body_lines(body) = std.join([], [ diff --git a/test_suite/stdlib.jsonnet b/test_suite/stdlib.jsonnet index 0a810c3d1..9c1a19c89 100644 --- a/test_suite/stdlib.jsonnet +++ b/test_suite/stdlib.jsonnet @@ -313,6 +313,11 @@ std.assertEqual(std.lines(['a', null, 'b']), 'a\nb\n') && std.assertEqual(std.flattenArrays([[1, 2, 3], [4, 5, 6], []]), [1, 2, 3, 4, 5, 6]) && +std.assertEqual(std.flattenDeepArray([]), []) && +std.assertEqual(std.flattenDeepArray([1, 2, 3]), [1, 2, 3]) && +std.assertEqual(std.flattenDeepArray([1, [2, 3]]), [1, 2, 3]) && +std.assertEqual(std.flattenDeepArray([[1], [2, 3], [[null]]]), [1, 2, 3, null]) && + std.assertEqual( std.manifestIni({ main: { a: '1', b: '2' }, From fe3750f4bc603517d3532630d3a2d83903600194 Mon Sep 17 00:00:00 2001 From: Deep Goel <34025930+DeepanshuGoel17@users.noreply.github.com> Date: Tue, 13 Jun 2023 21:29:23 +0530 Subject: [PATCH 4/8] feat: implement std.avg (#1087) * Add std.avg in standard library --- doc/_stdlib_gen/stdlib-content.jsonnet | 10 ++++++++++ stdlib/std.jsonnet | 6 ++++++ test_suite/stdlib.jsonnet | 4 ++++ 3 files changed, 20 insertions(+) diff --git a/doc/_stdlib_gen/stdlib-content.jsonnet b/doc/_stdlib_gen/stdlib-content.jsonnet index 46850b0c5..3094a2f52 100644 --- a/doc/_stdlib_gen/stdlib-content.jsonnet +++ b/doc/_stdlib_gen/stdlib-content.jsonnet @@ -1394,6 +1394,16 @@ local html = import 'html.libsonnet'; |||, ]), }, + { + name: 'avg', + params: ['arr'], + availableSince: '0.20.0', + description: html.paragraphs([ + ||| + Return average of all element in arr. + |||, + ]), + }, { name: 'remove', params: ['arr', 'elem'], diff --git a/stdlib/std.jsonnet b/stdlib/std.jsonnet index a7fafd3f7..48c5c591b 100644 --- a/stdlib/std.jsonnet +++ b/stdlib/std.jsonnet @@ -1709,6 +1709,12 @@ limitations under the License. sum(arr):: std.foldl(function(a, b) a + b, arr, 0), + avg(arr):: + if std.length(arr) == 0 then + error 'Cannot calculate average of an empty array.' + else + std.sum(arr)/std.length(arr), + minArray(arr, keyF=id, onEmpty=error 'Expected at least one element in array. Got none'):: if std.length(arr) == 0 then onEmpty diff --git a/test_suite/stdlib.jsonnet b/test_suite/stdlib.jsonnet index 9c1a19c89..efb9f3c4b 100644 --- a/test_suite/stdlib.jsonnet +++ b/test_suite/stdlib.jsonnet @@ -1549,6 +1549,10 @@ std.assertEqual(std.all([]), true) && std.assertEqual(std.sum([1, 2, 3]), 6) && +std.assertEqual(std.avg([1, 2, 3]), 2) && +std.assertEqual(std.avg([0, 0, 0]), 0) && +std.assertEqual(std.avg([1, 1, 2.5]), 1.5) && + std.assertEqual(std.minArray([1, 2, 3]), 1) && std.assertEqual(std.minArray(['1', '2', '3']), '1') && From e328686f0812c4a71c12d80a36b8e6139fc07db4 Mon Sep 17 00:00:00 2001 From: Rohit Jangid Date: Tue, 13 Jun 2023 21:45:08 +0530 Subject: [PATCH 5/8] feat: add more crypto functions (#1085) Co-authored-by: Dave Cunningham --- doc/_stdlib_gen/stdlib-content.jsonnet | 52 ++++++++++++++++++++++++++ stdlib/std.jsonnet | 7 ++++ 2 files changed, 59 insertions(+) diff --git a/doc/_stdlib_gen/stdlib-content.jsonnet b/doc/_stdlib_gen/stdlib-content.jsonnet index 3094a2f52..910af53f5 100644 --- a/doc/_stdlib_gen/stdlib-content.jsonnet +++ b/doc/_stdlib_gen/stdlib-content.jsonnet @@ -1648,6 +1648,58 @@ local html = import 'html.libsonnet'; Encodes the given value into an MD5 string. |||, }, + { + name: 'sha1', + params: ['s'], + availableSince: 'upcoming', + description: [ + html.p({}, ||| + Encodes the given value into an SHA1 string. + |||), + html.p({}, ||| + This function is only available in Go version of jsonnet. + |||), + ], + }, + { + name: 'sha256', + params: ['s'], + availableSince: 'upcoming', + description: [ + html.p({}, ||| + Encodes the given value into an SHA256 string. + |||), + html.p({}, ||| + This function is only available in Go version of jsonnet. + |||), + ], + }, + { + name: 'sha512', + params: ['s'], + availableSince: 'upcoming', + description: [ + html.p({}, ||| + Encodes the given value into an SHA512 string. + |||), + html.p({}, ||| + This function is only available in Go version of jsonnet. + |||), + ], + }, + { + name: 'sha3', + params: ['s'], + availableSince: 'upcoming', + description: [ + html.p({}, ||| + Encodes the given value into an SHA3 string. + |||), + html.p({}, ||| + This function is only available in Go version of jsonnet. + |||), + ], + }, ], }, { diff --git a/stdlib/std.jsonnet b/stdlib/std.jsonnet index 48c5c591b..8e3ff885c 100644 --- a/stdlib/std.jsonnet +++ b/stdlib/std.jsonnet @@ -25,6 +25,8 @@ limitations under the License. local std = self, local id = function(x) x, + local go_only_function = error 'This function is only supported in go version of jsonnet. See https://github.com/google/go-jsonnet', + isString(v):: std.type(v) == 'string', isNumber(v):: std.type(v) == 'number', isBoolean(v):: std.type(v) == 'boolean', @@ -1772,5 +1774,10 @@ limitations under the License. if k != key }, + sha1(str):: go_only_function, + sha256(str):: go_only_function, + sha512(str):: go_only_function, + sha3(str):: go_only_function, + trim(str):: std.stripChars(str, ' \t\n\f\r\u0085\u00A0'), } From 14f5d8eaa5226aaa3aa91a0ccebafaafe23a3824 Mon Sep 17 00:00:00 2001 From: Morten Mjelva Date: Tue, 13 Jun 2023 21:05:13 +0200 Subject: [PATCH 6/8] Add source archive and snippet to release (#1089) --- .github/workflows/create_archive_and_notes.sh | 53 +++++++++++++++++++ .github/workflows/release.yml | 38 +++++++++++++ 2 files changed, 91 insertions(+) create mode 100755 .github/workflows/create_archive_and_notes.sh create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/create_archive_and_notes.sh b/.github/workflows/create_archive_and_notes.sh new file mode 100755 index 000000000..460ea3f74 --- /dev/null +++ b/.github/workflows/create_archive_and_notes.sh @@ -0,0 +1,53 @@ +#!/usr/bin/env bash +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# 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. + +set -o errexit -o nounset -o pipefail + +# Set by GH actions, see +# https://docs.github.com/en/actions/learn-github-actions/environment-variables#default-environment-variables +TAG=${GITHUB_REF_NAME} +# A prefix is added to better match the GitHub generated archives. +PREFIX="jsonnet-${TAG}" +ARCHIVE="jsonnet-$TAG.tar.gz" +git archive --format=tar --prefix=${PREFIX}/ ${TAG} | gzip > $ARCHIVE +SHA=$(shasum -a 256 $ARCHIVE | awk '{print $1}') + +cat > release_notes.txt << EOF +### Importing Jsonnet in a project that uses Bazel + +#### Using Bzlmod with Bazel 6 + +Add to your \`MODULE.bazel\` file: + +\`\`\`starlark +bazel_dep(name = "jsonnet", version = "${TAG}") +\`\`\` + +#### Using WORKSPACE + +Paste this snippet into your \`WORKSPACE\` file: + +\`\`\`starlark +load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") + +http_archive( + name = "jsonnet", + sha256 = "${SHA}", + strip_prefix = "${PREFIX}", + url = "https://github.com/google/jsonnet/releases/download/${TAG}/jsonnet-${TAG}.tar.gz", +) +\`\`\` + +EOF diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 000000000..d497b3e48 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,38 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# 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. + +# Cut a release whenever a new tag is pushed to the repo. +name: Release + +on: + push: + tags: + - "*.*.*" + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Create release archive and notes + run: .github/workflows/create_archive_and_notes.sh + - name: Release + uses: softprops/action-gh-release@v1 + with: + # Use GH feature to populate the changelog automatically + generate_release_notes: true + body_path: release_notes.txt + fail_on_unmatched_files: true + files: jsonnet-*.tar.gz From fe3ce9d4196a0ba5d5c9abb94717bffa8feb9022 Mon Sep 17 00:00:00 2001 From: Morten Mjelva Date: Tue, 13 Jun 2023 21:08:22 +0200 Subject: [PATCH 7/8] Change com_google_googletest to a non-dev dependency (#1090) I had to patch the MODULE.bazel file as part of publishing to BCR (https://github.com/bazelbuild/bazel-central-registry/pull/667), as some targets failed to build when googletest was marked as a dev dependency. I think it would be possible to get around this by limiting which parts of this repo are built by the BCR presubmit checks. Making googletest a normal dependency seems like the better option, as it will allow the presubmit checks to be more thorough. --- MODULE.bazel | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/MODULE.bazel b/MODULE.bazel index 0fddb83ba..94ac2641a 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -1,5 +1,7 @@ module(name = "jsonnet", version = "0.0.0") +bazel_dep(name = "googletest", version = "1.11.0", repo_name = "com_google_googletest") + build_defs = use_extension("//tools/build_defs:extensions.bzl", "build_defs") use_repo( build_defs, @@ -8,7 +10,3 @@ use_repo( ) register_toolchains("//platform_defs:default_python3_toolchain") - -# Dev dependencies - -bazel_dep(name = "googletest", version = "1.11.0", repo_name = "com_google_googletest", dev_dependency = True) From a5fefdb6110100014e77021f2db253679c049f9f Mon Sep 17 00:00:00 2001 From: Rohit Jangid Date: Wed, 14 Jun 2023 00:44:03 +0530 Subject: [PATCH 8/8] feat: Add more math functions (#1091) --- doc/_stdlib_gen/stdlib-content.jsonnet | 8 ++++++++ stdlib/std.jsonnet | 5 +++++ test_suite/stdlib.jsonnet | 9 +++++++++ 3 files changed, 22 insertions(+) diff --git a/doc/_stdlib_gen/stdlib-content.jsonnet b/doc/_stdlib_gen/stdlib-content.jsonnet index 910af53f5..dd662773d 100644 --- a/doc/_stdlib_gen/stdlib-content.jsonnet +++ b/doc/_stdlib_gen/stdlib-content.jsonnet @@ -110,12 +110,20 @@ local html = import 'html.libsonnet';
    std.acos(x)
    std.atan(x)
    std.round(x)
+
    std.isEven(x)
+
    std.isOdd(x)
+
    std.isInteger(x)
+
    std.isDecimal(x)

The function std.mod(a, b) is what the % operator is desugared to. It performs modulo arithmetic if the left hand side is a number, or if the left hand side is a string, it does Python-style string formatting with std.format().

+

+ The functions std.isEven(x) and std.isOdd(x) use integral part of a + floating number to test for even or odd. +

|||, ], fields: [ diff --git a/stdlib/std.jsonnet b/stdlib/std.jsonnet index 8e3ff885c..c861a4aec 100644 --- a/stdlib/std.jsonnet +++ b/stdlib/std.jsonnet @@ -1752,6 +1752,11 @@ limitations under the License. contains(arr, elem):: std.any([e == elem for e in arr]), equalsIgnoreCase(str1, str2):: std.asciiLower(str1) == std.asciiLower(str2), + + isEven(x):: std.round(x) % 2 == 0, + isOdd(x):: std.round(x) % 2 != 0, + isInteger(x):: std.round(x) == x, + isDecimal(x):: std.round(x) != x, removeAt(arr, at):: [ arr[i], diff --git a/test_suite/stdlib.jsonnet b/test_suite/stdlib.jsonnet index efb9f3c4b..e3b290e06 100644 --- a/test_suite/stdlib.jsonnet +++ b/test_suite/stdlib.jsonnet @@ -1579,6 +1579,15 @@ std.assertEqual(std.contains([1, 2, 3], 'foo'), false) && std.assertEqual(std.equalsIgnoreCase('foo', 'FOO'), true) && std.assertEqual(std.equalsIgnoreCase('foo', 'bar'), false) && +std.assertEqual(std.isEven(10), true) && +std.assertEqual(std.isEven(5), false) && +std.assertEqual(std.isOdd(5), true) && +std.assertEqual(std.isOdd(10), false) && +std.assertEqual(std.isInteger(1), true) && +std.assertEqual(std.isInteger(1.1), false) && +std.assertEqual(std.isDecimal(1.1), true) && +std.assertEqual(std.isDecimal(1), false) && + std.assertEqual(std.remove([1, 2, 3], 2), [1, 3]) && std.assertEqual(std.removeAt([1, 2, 3], 1), [1, 3]) &&