mirror of
https://github.com/apple/pkl.git
synced 2026-03-18 15:23:58 +01:00
353 lines
11 KiB
Plaintext
353 lines
11 KiB
Plaintext
= Pkl 0.31 Release Notes
|
||
:version: 0.31
|
||
:version-minor: 0.31.0
|
||
:release-date: February 26th, 2026
|
||
:version-next: 0.32
|
||
:version-next-date: July 2026
|
||
|
||
include::partial$intro.adoc[]
|
||
|
||
== Highlights [small]#💖#
|
||
|
||
[[power-assertions]]
|
||
=== Power Assertions
|
||
|
||
Pkl's test output and error output has been improved with power assertions (pr:https://github.com/apple/pkl/pull/1384[], pr:https://github.com/apple/pkl/pull/1419[])!
|
||
|
||
Pkl has two places that are effectively assertions.
|
||
These are:
|
||
|
||
* Type constraint expressions
|
||
* Test facts
|
||
|
||
Currently, when these assertions fail, the error message prints the assertion's source section.
|
||
However, this information can sometimes be lacking.
|
||
It tells you what the mechanics of the assertion is, but doesn't tell you _why_ the assertion is failing.
|
||
|
||
For example, here is the current error output of a failing typecheck.
|
||
|
||
[source,text]
|
||
----
|
||
–– Pkl Error ––
|
||
Type constraint `name.endsWith(lastName)` violated.
|
||
Value: new Person { name = "Bub Johnson" }
|
||
|
||
7 | passenger: Person(name.endsWith(lastName)) = new { name = "Bub Johnson" }
|
||
----
|
||
|
||
Just from this error message, we don't know what the last name is supposed to be.
|
||
What is `name` supposed to end with?
|
||
We just know it's some property called `lastName` but, we don't know what it _is_.
|
||
|
||
In Pkl 0.31, the error output becomes:
|
||
|
||
[source,text]
|
||
----
|
||
–– Pkl Error ––
|
||
Type constraint `name.endsWith(lastName)` violated.
|
||
Value: new Person { name = "Bub Johnson" }
|
||
|
||
name.endsWith(lastName)
|
||
│ │ │
|
||
│ false "Smith"
|
||
"Bub Johnson"
|
||
|
||
7 | passenger: Person(name.endsWith(lastName)) = new { name = "Bub Johnson" }
|
||
----
|
||
|
||
Now, we know what the expectation is.
|
||
|
||
This type of diagram is also added to test facts.
|
||
When tests fail, Pkl emits a diagram of the expression, and the values produced.
|
||
|
||
For example, given the following test:
|
||
|
||
.math.pkl
|
||
[source,pkl]
|
||
----
|
||
amends "pkl:test"
|
||
|
||
facts {
|
||
local function add(a: Int, b: Int) = a * b
|
||
local function divide(a: Int, b: Int) = a % b
|
||
["math"] {
|
||
add(3, 4) == 7
|
||
divide(8, 2) == 4
|
||
}
|
||
}
|
||
----
|
||
|
||
The error output now includes a power assertion diagram, which helps explain why the test failed.
|
||
|
||
[source,text]
|
||
----
|
||
module math
|
||
facts
|
||
✘ math
|
||
add(3, 4) == 7 (math.pkl:9)
|
||
│ │
|
||
12 false
|
||
divide(8, 2) == 4 (math.pkl:10)
|
||
│ │
|
||
0 false
|
||
|
||
0.0% tests pass [1/1 failed], 0.0% asserts pass [2/2 failed]
|
||
----
|
||
|
||
To learn more about this feature, consult https://github.com/apple/pkl-evolution/blob/main/spices/SPICE-0026-power-assertions.adoc[SPICE-0026].
|
||
|
||
[[cli-framework]]
|
||
=== CLI Framework
|
||
|
||
Pkl 0.31 introduces a new framework for implementing CLI tools in Pkl (pr:https://github.com/apple/pkl/pull/1367[], pr:https://github.com/apple/pkl/pull/1431[], pr:https://github.com/apple/pkl/pull/1432[], pr:https://github.com/apple/pkl/pull/1436[], pr:https://github.com/apple/pkl/pull/1440[], pr:https://github.com/apple/pkl/pull/1444[]).
|
||
|
||
The framework provides a way to build command line tools with user experience idioms that will be immediately familiar to users.
|
||
CLI tools implemented in Pkl have largely the same capabilities as normal Pkl evaluation (i.e. writing to standard output and files), but this may be extended using xref:language-reference:index.adoc#external-readers[external readers].
|
||
|
||
Commands are defined by extending the pkldoc:#[pkl:Command] module:
|
||
|
||
.bird-generator.pkl
|
||
[source,pkl]
|
||
----
|
||
extends "pkl:Command"
|
||
|
||
options: Options
|
||
|
||
class Options {
|
||
/// Mapping of <bird>=<bird age> pairs defining the list of birds.
|
||
@Argument
|
||
birds: Mapping<String, Number>
|
||
|
||
/// Aggregation function to apply to all bird ages.
|
||
aggregate: *"sum" | "mean" | "count"
|
||
}
|
||
|
||
class Bird {
|
||
/// Name of the bird.
|
||
name: String
|
||
|
||
/// Age of the bird in years.
|
||
age: Number
|
||
}
|
||
|
||
birds: Listing<Bird> = new {
|
||
for (_name, _age in options.birds) {
|
||
new { name = _name; age = _age }
|
||
}
|
||
}
|
||
|
||
result: Number =
|
||
if (options.aggregate == "sum")
|
||
birds.toList().fold(0.0, (result, bird) -> result + bird.age)
|
||
else if (options.aggregate == "mean")
|
||
birds.toList().fold(0.0, (result, bird) -> result + bird.age) / birds.length
|
||
else
|
||
birds.length
|
||
----
|
||
|
||
Commands are executed using the `pkl run` CLI subcommand:
|
||
|
||
[source,bash]
|
||
----
|
||
$ pkl run bird-generator.pkl pigeon --aggregate=mean Pigeon=1 Hawk=8 Eagle=3
|
||
birds {
|
||
new {
|
||
name = "Pigeon"
|
||
age = 1
|
||
}
|
||
new {
|
||
name = "Hawk"
|
||
age = 8
|
||
}
|
||
new {
|
||
name = "Eagle"
|
||
age = 3
|
||
}
|
||
}
|
||
result = 4.0
|
||
----
|
||
|
||
Automatic CLI help is provided:
|
||
|
||
[source,bash]
|
||
----
|
||
$ pkl run test.pkl -h
|
||
Usage: test.pkl [<options>] [<birds>]... <command> [<args>]...
|
||
|
||
Options:
|
||
--aggregate=<count, mean, sum> Aggregation function to apply to all bird ages.
|
||
-h, --help Show this message and exit
|
||
|
||
Arguments:
|
||
<birds> Mapping of <bird>=<bird age> pairs defining the list of birds.
|
||
----
|
||
|
||
To learn more about this feature, consult xref:pkl-cli:index.adoc#cli-tools[the documentation] and https://github.com/apple/pkl-evolution/blob/main/spices/SPICE-0025-pkl-run-cli-framework.adoc[SPICE-0025].
|
||
|
||
== Noteworthy [small]#🎶#
|
||
|
||
=== Syntax Highlighting
|
||
|
||
The Pkl CLI displays Pkl code in several locations: stack frames within errors messages, <<power-assertions,power assertions>>, and in the xref:pkl-cli:index.adoc#repl[REPL].
|
||
This code is now syntax highlighted to improve readability (pr:https://github.com/apple/pkl/pull/1385[], pr:https://github.com/apple/pkl/pull/1409[]):
|
||
|
||
image::syntax-highlight-error.png[syntax highlighted output]
|
||
|
||
[[cli-dependency-notation]]
|
||
=== CLI Support for Dependency Notation
|
||
|
||
The Pkl CLI now supports specifying modules using xref:language-reference:index.adoc#project-dependencies[dependency notation] (pr:https://github.com/apple/pkl/pull/1434[], pr:https://github.com/apple/pkl/pull/1439[]).
|
||
This is especially helpful for <<cli-framework,CLI commands>> defined in Packages:
|
||
|
||
[source,bash]
|
||
----
|
||
$ pkl run @my-tool/cmd.pkl ...
|
||
----
|
||
|
||
This enhancement applies to the `pkl eval`, `pkl run`, `pkl test`, and `pkl analyze imports` commands.
|
||
It also applies to the `pkldoc`, `pkl-codegen-java`, and `pkl-codegen-kotlin` tools.
|
||
|
||
[NOTE]
|
||
Dependency notation only works for remote package dependencies. xref:language-reference:index.adoc#local-dependencies[Local dependencies] are not supported.
|
||
|
||
=== Property Converter Annotations
|
||
|
||
Pkl provides the pkldoc:BaseValueRenderers#converters[] mechanism for transforming values during rendering.
|
||
Converters are flexible, but their design makes some transformations awkward.
|
||
In particular, modifying property names during rendering required a lot of extra code.
|
||
|
||
The new pkldoc:ConvertProperty[] annotation adds a way to express parameterized per-property name and value transformations (pr:https://github.com/apple/pkl/pull/1333[]).
|
||
|
||
To learn more about this feature, consult https://github.com/apple/pkl-evolution/blob/main/spices/SPICE-0024-annotation-converters.adoc[SPICE-0024].
|
||
|
||
Additional new Pkl APIs for per-format property renaming will be added for many built-in renderers:
|
||
|
||
.fmt.pkl
|
||
[source,pkl]
|
||
----
|
||
import "pkl:json"
|
||
import "pkl:yaml"
|
||
|
||
@json.Property { name = "foo_bar" }
|
||
@yaml.Property { name = "foo-bar" }
|
||
fooBar: String = "hello world"
|
||
----
|
||
|
||
[source,terminaloutput]
|
||
----
|
||
$ pkl eval fmt.pkl -f json
|
||
{
|
||
"foo_bar": "hello world"
|
||
}
|
||
|
||
$ pkl eval fmt.pkl -f yaml
|
||
foo-bar: hello world
|
||
----
|
||
|
||
=== Java API changes
|
||
|
||
==== New classes
|
||
|
||
New classes are introduced to the Java API.
|
||
|
||
* `org.pkl.core.CommandSpec`
|
||
|
||
==== New methods
|
||
|
||
New methods are introduced to the Java API.
|
||
|
||
* `org.pkl.core.Evaluator.evaluateCommand`
|
||
* `org.pkl.core.EvaluatorBuilder.setPowerAssertionsEnabled`
|
||
* `org.pkl.core.EvaluatorBuilder.getPowerAssertionsEnabled`
|
||
* `org.pkl.core.SecurityManager.resolveSecurePath`
|
||
* `org.pkl.config.java.ConfigEvaluator.evaluateOutputValue`
|
||
* `org.pkl.coznfig.java.ConfigEvaluator.evaluateExpression`
|
||
|
||
=== Standard Library changes
|
||
|
||
New properties have been added to the standard library (pr:https://github.com/apple/pkl/pull/1396[]).
|
||
|
||
==== Additions to `pkl:base`
|
||
|
||
* pkldoc:List#isNotEmpty[]
|
||
* pkldoc:Map#isNotEmpty[]
|
||
* pkldoc:Set#isNotEmpty[]
|
||
* pkldoc:Listing#isNotEmpty[]
|
||
* pkldoc:Mapping#isNotEmpty[]
|
||
* pkldoc:String#isNotEmpty[]
|
||
* pkldoc:String#isNotBlank[]
|
||
* pkldoc:ConvertProperty[]
|
||
* pkldoc:BaseValueRenderer#convertPropertyTransformers[]
|
||
|
||
==== New module `pkl:Command`
|
||
|
||
The pkldoc:#[pkl:Command] standard library module is added.
|
||
|
||
==== Additions to `pkl:json`
|
||
|
||
* pkldoc:Property[pkl:json]
|
||
|
||
==== Additions to `pkl:jsonnet`
|
||
|
||
* pkldoc:Property[pkl:jsonnet]
|
||
|
||
==== Additions to `pkl:protobuf`
|
||
|
||
* pkldoc:Property[pkl:protobuf]
|
||
|
||
==== Additions to `pkl:xml`
|
||
|
||
* pkldoc:Property[pkl:xml]
|
||
|
||
==== Additions to `pkl:yaml`
|
||
|
||
* pkldoc:Property[pkl:yaml]
|
||
|
||
== Breaking Changes [small]#💔#
|
||
|
||
Things to watch out for when upgrading.
|
||
|
||
=== Removal of `@argfile` support
|
||
|
||
Prior versions of Pkl had an undocumented feature allowing inclusion of CLI arguments from files using `@path/to/file`.
|
||
In order to support <<cli-dependency-notation,dependency notation>> on the CLI, `@argfile` support has been removed from Pkl.
|
||
|
||
=== Removal of `Collection#transpose()`
|
||
|
||
Prior versions of Pkl defined a `transpose()` method on the `Collection` class.
|
||
This method was never implemented and threw an error when called.
|
||
As it was never functional, it has been removed entirely without a deprecation warning (pr:https://github.com/apple/pkl/pull/1437[]).
|
||
|
||
== Miscellaneous [small]#🐸#
|
||
|
||
* Improve formatting of imports to keep surrounding comments (pr:https://github.com/apple/pkl/pull/1424[]).
|
||
* Add support for evaluating module output and expressions to `ConfigEvaluator` (pr:https://github.com/apple/pkl/pull/1297[]).
|
||
* The `pkl format --write` command now exits successfully when formatting violations are found and updated (pr:https://github.com/apple/pkl/pull/1340[]).
|
||
* Add `pkl-bom` module to aid in aligning Pkl Java dependencies (pr:https://github.com/apple/pkl/pull/1390[]).
|
||
* Improve error message when writing `PklProject.deps.json` fails (pr:https://github.com/apple/pkl/pull/1405[]).
|
||
* Add information about pkldoc:Annotation[]s to the language reference (pr:https://github.com/apple/pkl/pull/1427[]).
|
||
* Improved usability for the `org.pkl.formatter.Formatter` Java API (pr:https://github.com/apple/pkl/pull/1428[]).
|
||
|
||
== Bugs fixed [small]#🐜#
|
||
|
||
The following bugs have been fixed.
|
||
|
||
* `Function.toString()` returns incorrect result (pr:https://github.com/apple/pkl/pull/1411[]).
|
||
* Failure when `--multiple-file-output-path` is a symlink (pr:https://github.com/apple/pkl/pull/1389[]).
|
||
* The `module` type in a non-final module has default value of type `Dynamic` (pr:https://github.com/apple/pkl/pull/1392[]).
|
||
* The `module` type is cached incorrectly in some cases (pr:https://github.com/apple/pkl/pull/1393[]).
|
||
* A possible race condition involving symlinks could bypass `--root-dir` during module and resource reading (pr:https://github.com/apple/pkl/pull/1426[]).
|
||
* `pkl format` produces internal stack traces when lexing fails (pr:https://github.com/apple/pkl/pull/1430[]).
|
||
* `super` access expressions are parsed incorrectly inside the spread operator (pr:https://github.com/apple/pkl/pull/1364[]).
|
||
* Modules and resources with `jar:file:` URIs were not properly sandboxed by `--root-dir` (pr:https://github.com/apple/pkl/pull/1442[]).
|
||
|
||
== Contributors [small]#🙏#
|
||
|
||
We would like to thank the contributors to this release (in alphabetical order):
|
||
|
||
* https://github.com/bioball[@bioball]
|
||
* https://github.com/eddie4941[@eddie4941]
|
||
* https://github.com/HT154[@HT154]
|
||
* https://github.com/stackoverflow[@stackoverflow]
|
||
* https://github.com/StefMa[@StefMa]
|