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.
–– 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:
–– 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:
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.
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 SPICE-0026.
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 external readers.
Commands are defined by extending the pkldoc:#[pkl:Command] module:
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.lengthCommands are executed using the pkl run CLI subcommand:
$ 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.0Automatic CLI help is provided:
$ 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 the documentation and SPICE-0025.
The Pkl CLI displays Pkl code in several locations: stack frames within errors messages, power assertions, and in the 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[]):
The Pkl CLI now supports specifying modules using dependency notation (pr:https://github.com/apple/pkl/pull/1434[], pr:https://github.com/apple/pkl/pull/1439[]). This is especially helpful for CLI commands defined in Packages:
$ 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. Local dependencies are not supported. |
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 SPICE-0024.
Additional new Pkl APIs for per-format property renaming will be added for many built-in renderers:
import "pkl:json"
import "pkl:yaml"
@json.Property { name = "foo_bar" }
@yaml.Property { name = "foo-bar" }
fooBar: String = "hello world"$ pkl eval fmt.pkl -f json
{
"foo_bar": "hello world"
}
$ pkl eval fmt.pkl -f yaml
foo-bar: hello worldNew 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
New properties have been added to the standard library (pr:https://github.com/apple/pkl/pull/1396[]).
-
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[]
Things to watch out for when upgrading.
Prior versions of Pkl had an undocumented feature allowing inclusion of CLI arguments from files using @path/to/file.
In order to support dependency notation on the CLI, @argfile support has been removed from Pkl.
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[]).
-
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 --writecommand now exits successfully when formatting violations are found and updated (pr:https://github.com/apple/pkl/pull/1340[]). -
Add
pkl-bommodule to aid in aligning Pkl Java dependencies (pr:https://github.com/apple/pkl/pull/1390[]). -
Improve error message when writing
PklProject.deps.jsonfails (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.FormatterJava API (pr:https://github.com/apple/pkl/pull/1428[]).
The following bugs have been fixed.
-
Function.toString()returns incorrect result (pr:https://github.com/apple/pkl/pull/1411[]). -
Failure when
--multiple-file-output-pathis a symlink (pr:https://github.com/apple/pkl/pull/1389[]). -
The
moduletype in a non-final module has default value of typeDynamic(pr:https://github.com/apple/pkl/pull/1392[]). -
The
moduletype is cached incorrectly in some cases (pr:https://github.com/apple/pkl/pull/1393[]). -
A possible race condition involving symlinks could bypass
--root-dirduring module and resource reading (pr:https://github.com/apple/pkl/pull/1426[]). -
pkl formatproduces internal stack traces when lexing fails (pr:https://github.com/apple/pkl/pull/1430[]). -
superaccess 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[]).
We would like to thank the contributors to this release (in alphabetical order):
