Skip to content

Latest commit

 

History

History
352 lines (254 loc) · 11.4 KB

File metadata and controls

352 lines (254 loc) · 11.4 KB

Pkl 0.31 Release Notes

Highlights 💖

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.

–– 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:

math.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.

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.

CLI Framework

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:

bird-generator.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:

$ 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:

$ 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.

Noteworthy 🎶

Syntax Highlighting

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[]):

syntax highlighted output

CLI Support for Dependency Notation

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.

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 SPICE-0024.

Additional new Pkl APIs for per-format property renaming will be added for many built-in renderers:

fmt.pkl
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 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 💔

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 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 🐸

Bugs fixed 🐜

The following bugs have been fixed.

Contributors 🙏

We would like to thank the contributors to this release (in alphabetical order):